moomarkus Posted October 3, 2013 Share Posted October 3, 2013 (edited) writeMCC.007.otl ########################################################################################## Python script to process Volume from Houdini, then# Write it out to Maya's .mc fluid cache format## Author: Markus Ng # mark.c.ng@gmail.com# www.distill3d.com# Date : Oct 3, 2013## Limitations: Resizing *FIXED* volumes seems to be un stable, so use consist volume size# problem was indexing of volume (cartiesian 3 space to 1 linear array mapping error )# Add Channel Data, ie: temperature, velocity, colour, etc if you wish# Density, resolution, and offset seems to be the least required data in caches...# ## (or maybe Density aren't needed. (Was not tested.)# # Fixed bad resolution querys, expecially when velocity's fields are queried by mistake.# ** Disclaimer:# Free for all to use... thanks. * Use at own risk as well *##########################################################################################yy## Thanks to 1: https://github.com/westernx/mayatools/blob/master/docs/binary.rst# And 2: http://100cells.com/downloads/MayaCacheDLL/MayaCacheBitstreamDocumentation.pdf# Which help to dicpher much of the ncache fuild format (.mc)## Other help are from maya's devkit directory for the .xml descriptor file# ie: C:\Program Files\Autodesk\Maya2012\devkit\pythonScripts\*.py## TO DO: Not implemented or test is the 'Single file ncache' which is multiple frames'# caches are stored in one file. # File formats are described in URL's 1: and 2: above.## Let me know if you found this useful. Thanks!# # Note: OpenVDB will probably make this script/converter obsolete# Houdini 12.5.xx has OpenVDB nodes already, but Maya 2013.5 has yet to have it yet.# Rumour as of September 2013, Maya suppose to have plug-in availabe 'later' this year.##########################################################################################yyimport houimport arrayimport sys,os#def writeChannel(fileout,curChannelName,l_values,dataType,flag_convert_list=True,vector3Id=0,maya_name=""):def writeChannel(fileout,curChannelName,l_values,dataType,vector3Id=0): #################################### # START Channel section # 28 + n bytes #################################### fileout.write("CHNM") # check if need to override name channelNameLen = len(curChannelName) padnum = 4-(channelNameLen%4) b = array.array('L',[channelNameLen+1 ]) b.byteswap() # channel name length (4 bytes) # for now, max size is ff(hex) = 255 fileout.write( # channel name (padded with modulus of 4) # ie: padding =4 -len(name)%4 #for item in range(padnum): channelNamePadded=curChannelName+chr(0)*padnum fileout.write(channelNamePadded) #tag for channels's array size: "SIZE" fileout.write("SIZE") #arraysize data length(bytes) 4 bytes :"00 00 00 04" b = bytearray([0,0,0,4 ]) fileout.write( #array size(number of elements) 4 bytes #b = bytearray([0,0,0,numElements ]) #fout.write( #array size(4 bytes) #split array to 4 byte chunks num_elements = len(l_values) # b = array.array('L',[num_elements]) b.byteswap() fileout.write( # #tag for datatype (4 bytes) : "DBLA","FVCA","DVCA","FBCA" # ************* Hardcoding toe FBCA for now... dataType = "FBCA" fileout.write(dataType) arraySize =0 ##################################################################### # arraySize for follow (except for type : FBCA) is just a guess. # I leave it up to you to verify the results ##################################################################### sizeVector=1 # handle the case for vector field #if vector3Id !=0 : # sizeVector=1 if dataType =="DBLA": arraySize = num_elements * 4 * sizeVector arrayType = 'd' elif dataType =="FVCA": arraySize = num_elements * 4 * sizeVector arrayType = 'f' elif dataType =="DVCA": arraySize = num_elements * 4 * sizeVector arrayType = 'd' elif dataType =="FBCA": arraySize = num_elements * 4 * sizeVector arrayType = 'f' ##################################################################### # write size of Data Value block ##################################################################### b = array.array('L',[arraySize]) b.byteswap() fileout.write( ############################################# # THis is used ** if ** a list is to be passed in and used as-is when # outputted to file ############################################# # for now, array's are of type 'f' or 'd', but vectors are not implemented yet # I'll leave this to the user to implement# if vector3Id == False: # write out single# b = array.array(arrayType,l_values)# else: # this is a vector float, so need to flatten this list. b = array.array(arrayType,l_values) b.byteswap() fileout.write( ################################ ## END CHANNEL ################################ numbytes = len(l_values) print "l_values:%d size:%d"%(numbytes,numbytes*4) return 28 + numbytes*4def channelNameLenPadded(channelName): channelNameLen = len(channelName) padnum = 4-(channelNameLen%4) return channelNameLen + padnumdef normList(L,max_val = 0.0 ,bias=0.0, normalizeTo=1): '''normalize values of a list to make its max = normalizeTo''' # see if there's an max value for ceil specified... # if not, then find max value in this list, and normalize to that... if max_val == 0.0: vMax = max(L) else: vMax = max_val print "max value: ",vMax # prevent division by zero... if vMax == 0 : vMax = 1.0 return [ (((x/vMax)*normalizeTo)+bias) for x in L]def processVolume(l_curVolume,normalize=-1,norm_bias=0.0,normalizeTo=1.0,vector3Id=0): # get size (gSize_x,gSize_y,gSize_z) = l_curVolume[0].resolution() num_volumes = len(l_curVolume) print "processVolume: x: %d, y:%d, z:%d"%(gSize_x,gSize_y,gSize_z) # get values for current voxel # Should be of size: (gSize_x * gSize_y * gSize_z) l_return=[0.0]*(gSize_x*gSize_y*gSize_z*num_volumes) l_return_max = gSize_x*gSize_y*gSize_z l_index =0 for k in range(0,gSize_z): for j in range(0,gSize_y): for i in range(0,gSize_x): #cur_index = + gSize_z*(j+(i*gSize_y)) for curVolume in l_curVolume: l_return[l_index] = curVolume.voxel((i,j,k)) up=15 lw=12 if (up>i)& (lw<i)& (up>j)& (lw<j) & (up>k)& (lw<k): print "%d,%d,%d"%(i,j,k),":", type(curVolume.voxel((i,j,k)) ) ,":", l_return[l_index] #print "i:%d j:%d k:%d index:%d >> val:"%(i,j,k,cur_index),l_return[cur_index] l_index+=1 # return normalize if specified if normalize!=-1: return normList(l_return,max_val=normalize,bias=norm_bias,normalizeTo=normalizeTo) return l_returndef processVector3Volume(l_curVolume,normalize=-1,norm_bias=0.0,normalizeTo=1.0,vector3Id=0,velocityTag = False): # get size (gSize_x,gSize_y,gSize_z) = l_curVolume[0].resolution() num_volumes = len(l_curVolume) (xr,yr,zr) = (gSize_x,gSize_y,gSize_z) #data_indices = ( #i + (j * (xr + 1)) + (k * (xr + 1) * yr ), #i + (j * xr ) + (k * xr * (yr + 1)) + ((xr + 1) * yr * zr), #i + (j * xr ) + (k * xr * yr ) + ((xr + 1) * yr * zr) + (xr * (yr + 1) * zr), #) print "processVolume3d: x: %d, y:%d, z:%d"%(gSize_x,gSize_y,gSize_z) # get values for current voxel # Should be of size: (gSize_x * gSize_y * gSize_z) if velocityTag : xcache_size = (gSize_x+1)*(gSize_y*gSize_z) ycache_size = (gSize_y+1)*(gSize_x*gSize_z) zcache_size = (gSize_z+1)*(gSize_x*gSize_y) else: xcache_size = (gSize_x)*(gSize_y*gSize_z) ycache_size = (gSize_y)*(gSize_x*gSize_z) zcache_size = (gSize_z)*(gSize_x*gSize_y) velvoxelsize_volumes = xcache_size + ycache_size + zcache_size print ">>>size:%d %d %d = %d"%(xcache_size,ycache_size, zcache_size,velvoxelsize_volumes) l_return=[0.0]*(velvoxelsize_volumes ) #l_return_max = (1+gSize_x)*(1+gSize_y)*(1+gSize_z) l_index =0 for k in range(0,gSize_z): for j in range(0,gSize_y): for i in range(0,gSize_x): #cur_index = + gSize_z*(j+(i*gSize_y)) #for curVolume in l_curVolume: if velocityTag: data_indices = ( i + (j * (xr + 1)) + (k * (xr + 1) * yr ), i + (j * xr ) + (k * xr * (yr + 1)) + ((xr + 1) * yr * zr), i + (j * xr ) + (k * xr * yr ) + ((xr + 1) * yr * zr) + (xr * (yr + 1) * zr), ) else: data_indices = ( i + (j * (xr )) + (k * (xr ) * yr ), i + (j * xr ) + (k * xr * (yr )) + ((xr ) * yr * zr), i + (j * xr ) + (k * xr * yr ) + ((xr ) * yr * zr) + (xr * (yr ) * zr), ) l_return[data_indices[0]] = l_curVolume[0].voxel((i,j,k)) l_return[data_indices[1]] = l_curVolume[1].voxel((i,j,k)) l_return[data_indices[2]] = l_curVolume[2].voxel((i,j,k)) x_l =data_indices[0] y_l =data_indices[1] z_l =data_indices[2] lw=0 up=2 if (up>i)& (lw<i)& (up>j)& (lw<j) & (up>k)& (lw<k): print "%d,%d,%d"%(i,j,k),":", type(l_curVolume[0].voxel((i,j,k)) ) ,":%f,%f,%f"%(l_return[x_l],l_return[y_l],l_return[z_l]) #print "i:%d j:%d k:%d index:%d >> val:"%(i,j,k,cur_index),l_return[cur_index] l_index+=1 # return normalize if specified if normalize!=-1: return normList(l_return,max_val=normalize,bias=norm_bias,normalizeTo=normalizeTo) return l_return############################################################################start###########################################################################def writeFrames(): this_node = hou.pwd() inputs = this_node.inputs() # Get the geometry from the second input # (first input=0, second input=1, third=2, etc.) first_input_geo = inputs[0].geometry() s = first_input_geo.sopNode() dop_str = s.path() print "Converting volume: ",dop_str #param 1 #dop_str="/obj/import_pyro_build1/file1" #param 2 startframe= this_node.parm("startFrame").evalAsInt() print "startFrame:",startframe #param 3 endframe = this_node.parm("endFrame").evalAsInt() print "endFrame:",endframe #param 4 #fluidPrefix= "fluidShape1" fluidPrefix = this_node.parm("fluidPrefix").evalAsString() print "fluid prefix:",fluidPrefix # create directory of output #param 5 #outfilename_prefix="i:/maya/data/fireball7/fluidShape1Frame" outfilename_prefix = this_node.parm("outFile").evalAsString() if not os.path.exists(os.path.dirname(outfilename_prefix)): os.makedirs(os.path.dirname(outfilename_prefix)) print "Creating directory:",os.path.dirname(outfilename_prefix) print "Output directory:",outfilename_prefix #param 6 d_channel= {} d_channel['density'] ={"index":0,"normalize":-1,"norm_bias":0.0, "maxClip":1.0, "vector3Id":0} # if vector3Id = non-zero, then process channelnames = 'channelname.x','channelname.y','channelname.z' and dump into flatten vector array of x*y*z d_channel['vel'] ={"index":1,"normalize":-1,"norm_bias":0.0, "maxClip":1.0, "vector3Id":1, "override_name":"velocity"} d_channel['temperature'] ={"index":4,"normalize":-1,"norm_bias":0.0, "maxClip":1.0, "vector3Id":0} #d_channel['heat'] = {"index":2,"normalize":-1,"norm_bias":0.0, "maxClip":1.0, "vector3Id":0} #d_channel['fuel'] = {"index":2,"normalize":-1,"norm_bias":0.0, "maxClip":1.0, "vector3Id":0} ###########>>>>>>>>>>>>>>>>> hou.setFrame(startframe) # get fluid object h=hou.node(dop_str) ### get initial size/rez densityVolume=h.geometry().prims()[0] # store init pos first_l_res = densityVolume.resolution() first_min_position = densityVolume.indexToPos((0,0,0)) first_max_position = densityVolume.indexToPos(first_l_res) first_delta = first_max_position - first_min_position first_mid_point = hou.Vector3((first_delta[0]/2,first_delta[1]/2,first_delta[2]/2)) first_mid_point += first_min_position print ">>>> ",type(first_mid_point) print "initial pos 1:",first_min_position print "initial pos 2:",first_max_position first_size_v = first_max_position-first_min_position print "initial size:",first_size_v #first_centre = hou.Vector3(first_size_v[0]/2.0,first_size_v[1]/2.0,first_size_v[2]/2.0 ) first_centre=densityVolume.vertex(0).point().position() print "initial centre:",first_centre print "first calc'ed centre:",first_mid_point for curframe in range(startframe,endframe+1): # check for interupt. if hou.updateProgressAndCheckForInterrupt(): break # increment the curframe hou.setFrame(curframe) h=hou.node(dop_str) #channel_lists # always include : mandatory channels: resolution, offset # Construct file name outfilename = outfilename_prefix + "Frame%d.mc"%curframe print "outfile:",outfilename # get volume object, initialize sum length: totalDataLen = 0 for key in d_channel: maya_channelName = fluidPrefix+"_"+key override_name ="" if d_channel[key].has_key('override_name'): override_name = d_channel[key]['override_name'] if override_name != "": maya_channelName = fluidPrefix+"_"+override_name d_channel[key]['maya_name']=maya_channelName prim_index = d_channel[key]['index'] vector3Id = d_channel[key]['vector3Id'] print "working on channel:",key, " index:",prim_index if vector3Id == 0 : d_channel[key]['volume_object']=[h.geometry().prims()[prim_index] ] else: print "getting vector volumes:",prim_index+1,prim_index+2 d_channel[key]['volume_object']=[] d_channel[key]['volume_object'].append(h.geometry().prims()[prim_index] ) d_channel[key]['volume_object'].append(h.geometry().prims()[prim_index+1] ) d_channel[key]['volume_object'].append(h.geometry().prims()[prim_index+2] ) n_val=d_channel[key]["normalize"] nbias= d_channel[key]["norm_bias"] maxclip =d_channel[key]["maxClip" ] vector3Id =d_channel[key]["vector3Id" ] if vector3Id: if override_name == "velocity": d_channel[key]['values_list'] = processVector3Volume(d_channel[key]['volume_object'],normalize=n_val,norm_bias=nbias,normalizeTo=maxclip,vector3Id=vector3Id,velocityTag=True) else: d_channel[key]['values_list'] = processVector3Volume(d_channel[key]['volume_object'],normalize=n_val,norm_bias=nbias,normalizeTo=maxclip,vector3Id=vector3Id,velocityTag=False) else: d_channel[key]['values_list'] = processVolume(d_channel[key]['volume_object'],normalize=n_val,norm_bias=nbias,normalizeTo=maxclip,vector3Id=vector3Id)# def processVolume(l_curVolume,normalize=-1,norm_bias=0.0,normalizeTo=1.0,vector3Id=0): d_channel[key]['PaddedNameLen'] = channelNameLenPadded(maya_channelName) totalDataLen += (28 + d_channel[key]['PaddedNameLen'] +(len(d_channel[key]['values_list'] )*4)) #heatVolume=h.geometry().prims()[2] ########################################## # Get data values From source volume voxels ########################################## # get density values #l_densityValues = processVolume(densityVolume) # get resolution from first volume in list, but not velocity: l_res = None first_volume=None for key in d_channel.keys(): if not key.startswith('vel'): first_volume=d_channel[key]['volume_object'][0] print "getting resolution from volume: ", key if first_volume ==None: print "Unable to get resolution from volumes." raise Exception("Unable to get resolution from volumes. Need to be not 'vel.*', like 'density','temperature','heat','fuel'") l_res = first_volume.resolution() print "this l_res:", str (l_res) cur_centre=first_volume.vertex(0).point().position() array_resolutionValues = array.array('f',l_res) min_position = first_volume.indexToPos((0,0,0)) max_position = first_volume.indexToPos(l_res) mid_point = max_position - min_position delta = max_position - min_position mid_point = hou.Vector3((delta[0]/2,delta[1]/2,delta[2]/2)) mid_point += min_position print ">>>>",mid_point # mid_point = mid_point /2 size_v = max_position-min_position # set offset to [0,0,0] v_offset = mid_point - first_mid_point v_offset = first_centre = cur_centre # v_offset=[0,0,0] print "current centre:",cur_centre array_offsetValues = array.array('f',v_offset) ############################################# # open file to write converted fuild data ############################################# fout = open (outfilename,"wb") ############### # header ############### #cache format fout.write("FOR4") #header data length (bytes) # value = 0x28 b = bytearray([0,0,0,0x28]) fout.write( #flag for cache verseion and cache version data length(bytes) fout.write("CACHVRSN") b = bytearray([0,0,0,0x04,0x30,0x2e,0x31,0x00]) fout.write( #tag for start time #start time data length (bytes) fout.write("STIM") b = bytearray([0,0,0,0x04]) fout.write( #current frame b = array.array('L',[curframe*250]) b.byteswap() fout.write( #tag for end time and Endtime data length (bytes) fout.write("ETIM") b = bytearray([0,0,0,0x04]) fout.write( #current frame** b = array.array('L',[curframe*250]) b.byteswap() fout.write( #get padded length of channel names #densityPLen = channelNameLenPadded("fluidShape1_density") #temperaturePLen = channelNameLenPadded("fluidShape1_temperature") #fuelPLen = channelNameLenPadded("fluidShape1_fuel") resPLen = channelNameLenPadded("fluidShape1_resolution") offsetPLen = channelNameLenPadded("fluidShape1_offset") #calculate length of channel data block: density,resolution,offset totalDataLen += (28+ resPLen+(len(array_resolutionValues)*4)) \ + (28+ offsetPLen+(len(array_offsetValues)*4)) \ + len("MYCH") ########################### # BLOCK HEADER 12+n bytes ########################### #cache format fout.write("FOR4") b = array.array('L',[totalDataLen]) b.byteswap() fout.write( #tag for channels block fout.write("MYCH") ################################ # Channel start here ################################ for key in d_channel: # Write CHANNEL channelName = d_channel[key]['maya_name'] dataType = "FBCA" l_values= d_channel[key]['values_list'] vector3Id= d_channel[key]['vector3Id'] maya_name= d_channel[key]['maya_name'] writeChannel(fout,channelName,l_values,dataType,vector3Id) # RESOLUTION CHANNEL channelName = "fluidShape1_resolution" dataType = "FBCA" vector3Id= 0 writeChannel(fout,channelName,array_resolutionValues,dataType,vector3Id) # OFFSET CHANNEL channelName = "fluidShape1_offset" dataType = "FBCA" vector3Id= 0 writeChannel(fout,channelName,array_offsetValues,dataType,vector3Id) # Close the file for this frame fout.close() ############################################### # Author: Markus Ng # mark.c.ng@gmail.com # www.distill3d.com # Date : Oct 3, 2013 ################################################def onCreated(node): #hou.ui.displayMessage("You created " + node.path()) #startvalue= hou.playbar.playbackRange()[0] #endvalue= hou.playbar.playbackRange()[1] #node.setParms({"startFrame":startvalue}) #node.setParms({"endFrame":int(endvalue)})def onCreate(this_node): ## follow is for onCreate script of a otl node definition # get new created node this_node = kwargs['node'] #set start and end values startvalue= hou.playbar.playbackRange()[0] endvalue= hou.playbar.playbackRange()[1] this_node.setParms({"startFrame":startvalue}) this_node.setParms({"endFrame":int(endvalue)}) this_node.setParms({"fluidPrefix":"fluidShape1_"}) this_node.setParms({"outFile":"$HIP/"+"fluidShape1"})import sys,osimport timedef writeMCC(outFileName,l_channelNames,start,end,sample_rate,res_x, res_y, res_z, dim_x,dim_y,dim_z, base_res =100,max_res=200 ): # optionally read from a separate text file #inFile = open ("I:/dev/mayafluid_template_xml.txt/","r") #text_buffer = inFile.read() # read from predefined in current source file (bottom of file) text_buffer = xmlTemplateData startmcc=str(start*sample_rate) endmcc=str(end*sample_rate) title="Generated from script" notes="Date:"+str(time.ctime()) description = "Description: " shapename = "fluidShape1" text_buffer = text_buffer.replace("%START_MCC%",startmcc) text_buffer = text_buffer.replace("%END_MCC%",endmcc) text_buffer = text_buffer.replace("%SAMPLE_RATE%",str(sample_rate)) text_buffer = text_buffer.replace("%CACHE_TITLE%",title) text_buffer = text_buffer.replace("%CACHE_NOTES%",notes) text_buffer = text_buffer.replace("%CACHE_DESCRIPTION%",description) text_buffer = text_buffer.replace("%CACHE_SHAPENAME%",shapename) text_buffer = text_buffer.replace("%VOLUME_DIM_X%",str(dim_x)) text_buffer = text_buffer.replace("%VOLUME_DIM_Y%",str(dim_y)) text_buffer = text_buffer.replace("%VOLUME_DIM_Z%",str(dim_z)) text_buffer = text_buffer.replace("%VOLUME_RES_X%",str(res_x)) text_buffer = text_buffer.replace("%VOLUME_RES_Y%",str(res_y)) text_buffer = text_buffer.replace("%VOLUME_RES_Z%",str(res_z)) text_buffer = text_buffer.replace("%MAX_RES%",str(max_res)) text_buffer = text_buffer.replace("%BASE_RES%",str(base_res)) #Add Channel block channelBlockText = "" channel_num =10 for channel in l_channelNames: channel_template_string = '<channel%CH_NUM% ChannelName="%CACHE_SHAPENAME%_%CHANNEL_NAME%" ChannelType="FloatArray" ChannelInterpretation="%CHANNEL_NAME%" SamplingType="Regular" SamplingRate="%SAMPLE_RATE%" StartTime="%START_MCC%" EndTime="%END_MCC%"/>' curText =channel_template_string.replace("%START_MCC%",startmcc) curText =curText.replace("%END_MCC%",endmcc) curText =curText.replace("%CACHE_SHAPENAME%",shapename) curText =curText.replace("%CHANNEL_NAME%",channel) curText =curText.replace("%CH_NUM%",str(channel_num)) curText =curText.replace("%SAMPLE_RATE%",str(sample_rate)) channelBlockText += curText +"\n" channel_num +=1 text_buffer = text_buffer.replace("%CHANNEL_BLOCK%",channelBlockText) ######################## # Writing to out file ######################## outfile = open(outFileName,"w") outfile.write(text_buffer) ## check directory exists, and make it. dirpath = os.path.dirname(outFileName) if not os.path.exists(dirpath): os.makedirs(dirpath) print "writing file : ",outFileName outfile.close()################## end of file ################### channel_template_string="<channel0 ChannelName=\""\# + shapename+"_"+channel\# + " ChannelType=\"FloatArray\" ChannelInterpretation=\""\# + channel\# + "\" SamplingType=\"Regular\" SamplingRate=\"250\" StartTime=\""\# + startmcc + "\" EndTime=\""+endmcc+"\"/>"# <channel1 ChannelName="fluidShape1_temperature" ChannelType="FloatArray" ChannelInterpretation="temperature" SamplingType="Regular" SamplingRate="250" StartTime="250" EndTime="30000"/># <channel2 ChannelName="fluidShape1_fuel" ChannelType="FloatArray" ChannelInterpretation="fuel" SamplingType="Regular" SamplingRate="250" StartTime="250" EndTime="30000"/># <channel3 ChannelName="fluidShape1_resolution" ChannelType="FloatArray" ChannelInterpretation="resolution" SamplingType="Regular" SamplingRate="250" StartTime="250" EndTime="30000"/># <channel4 ChannelName="fluidShape1_offset" ChannelType="FloatArray" ChannelInterpretation="offset" SamplingType="Regular" SamplingRate="250" StartTime="250" EndTime="30000"/>##################### Template data:###################xmlTemplateData= \'''\<?xml version="1.0"?><Autodesk_Cache_File> <cacheType Type="OneFilePerFrame" Format="mcc"/> <time Range="%START_MCC%-%END_MCC%"/> <cacheTimePerFrame TimePerFrame="%SAMPLE_RATE%"/> <cacheVersion Version="2.0"/> <extra>Houdini To Maya Script Generated cache file</extra> <extra>%CACHE_TITLE%</extra> <extra>%CACHE_NOTES%</extra> <extra>%CACHE_DESCRIPTION%</extra> <extra>%CACHE_SHAPENAME%</extra> <extra>Fluid Info for fluidShape1:</extra> <extra>fluidShape1.autoResize=1</extra> <extra>fluidShape1.dimensionsW=%VOLUME_DIM_X%</extra> <extra>fluidShape1.dimensionsH=%VOLUME_DIM_Y%</extra> <extra>fluidShape1.dimensionsD=%VOLUME_DIM_Z%</extra> <extra>fluidShape1.coordinateMethod=0</extra> <extra>fluidShape1.solverQuality=20</extra> <extra>fluidShape1.substeps=1</extra> <extra>fluidShape1.falloffMethod=0</extra> <extra>fluidShape1.densityMethod=2</extra> <extra>fluidShape1.velocityMethod=0</extra> <extra>fluidShape1.temperatureMethod=2</extra> <extra>fluidShape1.colorMethod=0</extra> <extra>fluidShape1.fuelMethod=2</extra> <extra>fluidShape1.startFrame=1</extra> <extra>fluidShape1.baseResolution=%BASE_RES%</extra> <extra>fluidShape1.resolutionW=%VOLUME_RES_X%</extra> <extra>fluidShape1.resolutionH=%VOLUME_RES_Y%</extra> <extra>fluidShape1.resolutionD=%VOLUME_RES_Z%</extra> <extra>fluidShape1.resizeClosedBoundaries=1</extra> <extra>fluidShape1.autoResizeThreshold=0.009999999776</extra> <extra>fluidShape1.maxResolution=%MAX_RES%</extra> <extra>fluidShape1.resizeToEmitter=1</extra> <extra>fluidShape1.resizeInSubsteps=1</extra> <extra>fluidShape1.autoResizeMargin=0</extra> <extra>fluidShape1.doFields=1</extra> <extra>fluidShape1.doEmission=1</extra> <extra>fluidShape1.inheritFactor=0</extra> <extra>fluidShape1.slices=2</extra> <extra>fluidShape1.voxelQuality=1</extra> <extra>fluidShape1.opacityPreviewGain=0.5</extra> <extra>fluidShape1.hardwareSelfShadow=1</extra> <extra>fluidShape1.selfShadow=1</extra> <extra>fluidShape1.gridInterpolator=0</extra> <extra>fluidShape1.solver=1</extra> <extra>fluidShape1.emitInSubsteps=0</extra> <extra>fluidShape1.highDetailSolve=0</extra> <extra>fluidShape1.enableLiquidSimulation=0</extra> <extra>fluidShape1.liquidMethod=1</extra> <extra>fluidShape1.liquidMinDensity=0.5</extra> <extra>fluidShape1.liquidMistFall=0</extra> <extra>fluidShape1.massRange=200</extra> <extra>fluidShape1.forwardAdvection=0</extra> <extra>fluidShape1.boundaryX=1</extra> <extra>fluidShape1.boundaryY=1</extra> <extra>fluidShape1.boundaryZ=1</extra> <extra>fluidShape1.massConversion=1</extra> <extra>fluidShape1.densityScale=0.5</extra> <extra>fluidShape1.densityDissipation=0</extra> <extra>fluidShape1.densityDiffusion=0</extra> <extra>fluidShape1.conserveMass=1</extra> <extra>fluidShape1.densityBuoyancy=1</extra> <extra>fluidShape1.densityGradientForce=0</extra> <extra>fluidShape1.densityTension=0</extra> <extra>fluidShape1.tensionForce=0</extra> <extra>fluidShape1.densityNoise=0</extra> <extra>fluidShape1.densityPressure=0</extra> <extra>fluidShape1.densityPressureThreshold=1</extra> <extra>fluidShape1.selfAttract=0.1000000015</extra> <extra>fluidShape1.selfRepel=0.1000000015</extra> <extra>fluidShape1.equilibriumValue=0.5</extra> <extra>fluidShape1.selfForceDistance=16</extra> <extra>fluidShape1.gravity=9.800000191</extra> <extra>fluidShape1.velocityScaleX=1</extra> <extra>fluidShape1.velocityScaleY=1</extra> <extra>fluidShape1.velocityScaleZ=1</extra> <extra>fluidShape1.viscosity=0</extra> <extra>fluidShape1.friction=0</extra> <extra>fluidShape1.velocitySwirl=0</extra> <extra>fluidShape1.velocityNoise=0</extra> <extra>fluidShape1.velocityDamp=0</extra> <extra>fluidShape1.velocityAdvect=1</extra> <extra>fluidShape1.velocityProject=1</extra> <extra>fluidShape1.turbulenceStrength=0</extra> <extra>fluidShape1.turbulenceFrequency=0.200000003</extra> <extra>fluidShape1.turbulenceSpeed=0.200000003</extra> <extra>fluidShape1.temperatureScale=1</extra> <extra>fluidShape1.temperatureDissipation=0.1</extra> <extra>fluidShape1.temperatureDiffusion=0.1</extra> <extra>fluidShape1.temperatureTurbulence=0.1000000015</extra> <extra>fluidShape1.temperatureNoise=0</extra> <extra>fluidShape1.temperaturePressure=0</extra> <extra>fluidShape1.temperaturePressureThreshold=0</extra> <extra>fluidShape1.buoyancy=3</extra> <extra>fluidShape1.temperatureTension=0</extra> <extra>fluidShape1.colorDissipation=0</extra> <extra>fluidShape1.colorDiffusion=0</extra> <extra>fluidShape1.fuelScale=1</extra> <extra>fluidShape1.reactionSpeed=0.05000000075</extra> <extra>fluidShape1.fuelIgnitionTemp=0</extra> <extra>fluidShape1.maxReactionTemp=1</extra> <extra>fluidShape1.airFuelRatio=0</extra> <extra>fluidShape1.heatReleased=1</extra> <extra>fluidShape1.lightReleased=0</extra> <extra>fluidShape1.lightColorR=1</extra> <extra>fluidShape1.lightColorG=1</extra> <extra>fluidShape1.lightColorB=1</extra> <extra>fluidShape1.matteOpacity=1</extra> <extra>fluidShape1.quality=1</extra> <extra>fluidShape1.renderInterpolator=1</extra> <extra>fluidShape1.color[0].color_Position=0</extra> <extra>fluidShape1.color[0].color_ColorR=1</extra> <extra>fluidShape1.color[0].color_ColorG=1</extra> <extra>fluidShape1.color[0].color_ColorB=1</extra> <extra>fluidShape1.color[0].color_Interp=1</extra> <extra>fluidShape1.colorInputBias=0</extra> <extra>fluidShape1.opacity[0].opacity_Position=0</extra> <extra>fluidShape1.opacity[0].opacity_FloatValue=0</extra> <extra>fluidShape1.opacity[0].opacity_Interp=1</extra> <extra>fluidShape1.opacity[1].opacity_Position=1</extra> <extra>fluidShape1.opacity[1].opacity_FloatValue=1</extra> <extra>fluidShape1.opacity[1].opacity_Interp=1</extra> <extra>fluidShape1.opacityInputBias=0</extra> <extra>fluidShape1.transparencyR=0.25</extra> <extra>fluidShape1.transparencyG=0.25</extra> <extra>fluidShape1.transparencyB=0.25</extra> <extra>fluidShape1.shadowOpacity=0.5</extra> <extra>fluidShape1.shadowDiffusion=0</extra> <extra>fluidShape1.lightBrightness=1</extra> <extra>fluidShape1.fluidLightColorR=1</extra> <extra>fluidShape1.fluidLightColorG=1</extra> <extra>fluidShape1.fluidLightColorB=1</extra> <extra>fluidShape1.ambientBrightness=0</extra> <extra>fluidShape1.ambientDiffusion=2</extra> <extra>fluidShape1.ambientColorR=0.5</extra> <extra>fluidShape1.ambientColorG=0.6999999881</extra> <extra>fluidShape1.ambientColorB=1</extra> <extra>fluidShape1.incandescence[0].incandescence_Position=0</extra> <extra>fluidShape1.incandescence[0].incandescence_ColorR=0</extra> <extra>fluidShape1.incandescence[0].incandescence_ColorG=0</extra> <extra>fluidShape1.incandescence[0].incandescence_ColorB=0</extra> <extra>fluidShape1.incandescence[0].incandescence_Interp=1</extra> <extra>fluidShape1.incandescence[1].incandescence_Position=0.8000000119</extra> <extra>fluidShape1.incandescence[1].incandescence_ColorR=0.8999999762</extra> <extra>fluidShape1.incandescence[1].incandescence_ColorG=0.200000003</extra> <extra>fluidShape1.incandescence[1].incandescence_ColorB=0</extra> <extra>fluidShape1.incandescence[1].incandescence_Interp=1</extra> <extra>fluidShape1.incandescence[2].incandescence_Position=1</extra> <extra>fluidShape1.incandescence[2].incandescence_ColorR=1.5</extra> <extra>fluidShape1.incandescence[2].incandescence_ColorG=1</extra> <extra>fluidShape1.incandescence[2].incandescence_ColorB=0</extra> <extra>fluidShape1.incandescence[2].incandescence_Interp=1</extra> <extra>fluidShape1.incandescenceInputBias=0</extra> <extra>fluidShape1.glowIntensity=0</extra> <extra>fluidShape1.specularColorR=0</extra> <extra>fluidShape1.specularColorG=0</extra> <extra>fluidShape1.specularColorB=0</extra> <extra>fluidShape1.cosinePower=20</extra> <extra>fluidShape1.environment[0].environment_Position=0</extra> <extra>fluidShape1.environment[0].environment_ColorR=0</extra> <extra>fluidShape1.environment[0].environment_ColorG=0</extra> <extra>fluidShape1.environment[0].environment_ColorB=0</extra> <extra>fluidShape1.environment[0].environment_Interp=1</extra> <extra>fluidShape1.edgeDropoff=0.05000000075</extra> <extra>fluidShape1.contrastTolerance=0.009999999776</extra> <extra>fluidShape1.surfaceThreshold=0.009999999776</extra> <extra>fluidShape1.surfaceTolerance=0.1000000015</extra> <extra>fluidShape1.meshResolution=2</extra> <extra>fluidShape1.refractiveIndex=1.799999952</extra> <extra>fluidShape1.pointLightX=0</extra> <extra>fluidShape1.pointLightY=0</extra> <extra>fluidShape1.pointLightZ=0</extra> <extra>fluidShape1.directionalLightX=0.5</extra> <extra>fluidShape1.directionalLightY=0.8000000119</extra> <extra>fluidShape1.directionalLightZ=0.5</extra> <extra>fluidShape1.textureType=0</extra> <extra>fluidShape1.colorTexture=0</extra> <extra>fluidShape1.colorTexGain=1</extra> <extra>fluidShape1.incandTexture=0</extra> <extra>fluidShape1.incandTexGain=1</extra> <extra>fluidShape1.opacityTexture=0</extra> <extra>fluidShape1.opacityTexGain=1</extra> <extra>fluidShape1.invertTexture=0</extra> <extra>fluidShape1.amplitude=1</extra> <extra>fluidShape1.ratio=0.7070000172</extra> <extra>fluidShape1.threshold=0</extra> <extra>fluidShape1.textureScaleX=1</extra> <extra>fluidShape1.textureScaleY=1</extra> <extra>fluidShape1.textureScaleZ=1</extra> <extra>fluidShape1.textureOriginX=0</extra> <extra>fluidShape1.textureOriginY=0</extra> <extra>fluidShape1.textureOriginZ=0</extra> <extra>fluidShape1.textureRotateX=0</extra> <extra>fluidShape1.textureRotateY=0</extra> <extra>fluidShape1.textureRotateZ=0</extra> <extra>fluidShape1.depthMax=2</extra> <extra>fluidShape1.frequency=1</extra> <extra>fluidShape1.frequencyRatio=2</extra> <extra>fluidShape1.inflection=0</extra> <extra>fluidShape1.textureTime=0</extra> <extra>fluidShape1.billowDensity=1</extra> <extra>fluidShape1.spottyness=0.1000000015</extra> <extra>fluidShape1.sizeRand=0</extra> <extra>fluidShape1.randomness=1</extra> <extra>fluidShape1.numWaves=5</extra> <extra>fluidShape1.implode=0</extra> <extra>fluidShape1.implodeCenterX=0</extra> <extra>fluidShape1.implodeCenterY=0</extra> <extra>fluidShape1.implodeCenterZ=0</extra> <extra>fluidShape1.focus=1</extra> <extra>fluidShape1.zoomFactor=1</extra> <extra>fluidShape1.escapeRadius=2</extra> <extra>fluidShape1.lobes=1</extra> <extra>fluidShape1.leafEffect=0</extra> <extra>fluidShape1.checker=0</extra> <extra>fluidShape1.lineBlending=0</extra> <extra>fluidShape1.lineFocus=0.5</extra> <extra>fluidShape1.points=0</extra> <extra>fluidShape1.stalksU=0</extra> <extra>fluidShape1.stalksV=0</extra> <extra>fluidShape1.circles=0</extra> <extra>fluidShape1.circleRadius=0.5</extra> <extra>fluidShape1.circleSizeRatio=1</extra> <extra>fluidShape1.lineOffsetU=0</extra> <extra>fluidShape1.lineOffsetV=0</extra> <extra>fluidShape1.lineOffsetRatio=1</extra> <extra>fluidShape1.juliaU=0</extra> <extra>fluidShape1.juliaV=0</extra> <extra>fluidShape1.boxRadius=1</extra> <extra>fluidShape1.boxMinRadius=0.5</extra> <extra>fluidShape1.boxRatio=-3</extra> <extra>fluidShape1.playFromCache=0</extra> <extra>fluidShape1.collide=1</extra> <extra>fluidShape1.surfaceShaderDepth=1</extra> <extra>fluidShape1.coordinateSpeed=0.200000003</extra> <Channels> %CHANNEL_BLOCK%</Channels></Autodesk_Cache_File>'''########################################################################################### start main line##########################################################################################import sysimport getoptdef do_write_MCC(): this_node = hou.pwd() inputs = this_node.inputs() # Get the geometry from the second input # (first input=0, second input=1, third=2, etc.) first_input_geo = inputs[0].geometry() print dir(first_input_geo) print "hello2:" print str(type(first_input_geo)) s = first_input_geo.sopNode() print str(type(s)) print "ahaha" print s.name() print this_node.path() print "xoxo" sample_rate = 250 l_ch=['density','velocity','temperature','resolution','offset']# l_ch=d_channels.keys()# l_ch=['density','resolution','offset'] print "blah" fluidPrefix = this_node.parm("fluidPrefix").evalAsString() print "fluid prefix, to be used as shape name:",fluidPrefix# shapeName = fluidPrefix outfilename_prefix = this_node.parm("outFile").evalAsString() if not os.path.exists(os.path.dirname(outfilename_prefix)): os.makedirs(os.path.dirname(outfilename_prefix)) print "Creating directory:",os.path.dirname(outfilename_prefix) print "Output directory:",outfilename_prefix outpath= outfilename_prefix+".xml" this_node = hou.pwd() start= this_node.parm("startFrame").evalAsInt() print "startFrame:",start end = this_node.parm("endFrame").evalAsInt() print "endFrame:",end # store current playback frame curFrame = hou.frame() print "Current frame:",curFrame # goto first frame and get dimensions and size hou.setFrame(start) print type(s),">>>",dir(s.geometry().prims()[0]) curVolume=s.geometry().prims()[0] # store init pos first_l_res = curVolume.resolution() (res_x,res_y,res_z) = curVolume.resolution() print "x: %d, y:%d, z:%d"%(res_x,res_y,res_z) first_min_position = curVolume.indexToPos((0,0,0)) first_max_position = curVolume.indexToPos(first_l_res) [dim_x,dim_y,dim_z] = first_max_position-first_min_position print "size: %f, %f, %f"%(dim_x,dim_y,dim_z) # set base rez to 'y's' size base_res= dim_y writeMCC(outpath,l_ch,start,end, sample_rate, res_x, res_y, res_z, dim_x,dim_y,dim_z,base_res = 50, max_res=200 ) print_maya_fluid_creation_script(res_x,res_y,res_z, dim_x,dim_y,dim_z) # set curFrame back to stored frame hou.setFrame(curFrame)# writeMCC(outpath,l_ch,start,end, sample_rate, res_x, res_y, res_z, dim_x,dim_y,dim_z,base_res = 50, max_res=200 )#if __name__ == "__main__":# main()def print_maya_fluid_creation_script(res_x,res_y,res_z, dim_x,dim_y,dim_z): mel_script = '''string $cmdstr = "";string $flname = "";$cmdstr = "create3DFluid %d %d %d %f %f %f";$flname = eval ($cmdstr);$cmdstr = "setAttr \\""+$flname+".temperatureMethod\\" 2";eval($cmdstr);$cmdstr = "setAttr \\""+$flname+".densityMethod\\" 2";eval($cmdstr);$cmdstr = "setAttr \\""+$flname+".fuelMethod\\" 2";eval($cmdstr); '''%(res_x,res_y,res_z, dim_x,dim_y,dim_z) print "// *********************************************************" print "// *********************************************************" print "// Run this in maya to create Fluid container:" print mel_script print "// End of script" print "// *********************************************************" print "// *********************************************************" writeMCC.otl writeMCC.002.otl writeFluidMayaMCC.004.zip Edited December 27, 2013 by moomarkus Quote Link to comment Share on other sites More sharing options...
moomarkus Posted October 3, 2013 Author Share Posted October 3, 2013 Actually, this is my first python script in Houdini.... I executed it in the "Python Source Editor". Is this the *Best* way to this? Or are there other ways to do this? My initial approach was to use vex , and/or vex script in a custom ROP, but I couldn't wrap my head around how to write a file without open and closing a file for each voxel/particle/point (ie: if I used a volume wranger, or point wrangle node). <--- is this possible to do for my result? THanks! Please comment! Markus Quote Link to comment Share on other sites More sharing options...
moomarkus Posted October 4, 2013 Author Share Posted October 4, 2013 Update on my current problem with this. I have resize containers working now. The only problem is that when I bring into maya, the Volume container is self-centering, so it's shifting around. I'd like it grow from the base of the volume, but it's not. One possible solution is to some how use the offset channel, but I'm not sure how to calculate that offset right now. I suppose I can try: In Houdini: 1. find base position (call it 'original positition) at start frame of sim. and get dimensions of volume 2. For each frame, get dimensions of volume and do a delta on 'original position' and calc offset(vector) : = delta(vector)/2 I'll post my findings later. Quote Link to comment Share on other sites More sharing options...
sea Posted October 16, 2013 Share Posted October 16, 2013 Hi : it looks very good tools , but could you tell me how did you create .xml file for maya cache ? thank you Quote Link to comment Share on other sites More sharing options...
moomarkus Posted October 17, 2013 Author Share Posted October 17, 2013 Yup, basically for now, I've regenerated an mcc xml in maya, then modify the values as needed by the channel / frame requirments of the file caches outputed from the first script. IE: use the maya mcc.xml as a template. You can wrap that in a python function if it's too tedious. (Which is what I've done) Quote Link to comment Share on other sites More sharing options...
sea Posted October 17, 2013 Share Posted October 17, 2013 I make xml in maya and laod this mc file , I got error report , saying my cache is empty or invalid , could you tell me why ? or maybe something wrong with xml , then could you tell me which value should I modify in xml file ? thank you . Quote Link to comment Share on other sites More sharing options...
moomarkus Posted October 18, 2013 Author Share Posted October 18, 2013 (edited) <deleted\> Edited November 2, 2013 by moomarkus Quote Link to comment Share on other sites More sharing options...
moomarkus Posted October 31, 2013 Author Share Posted October 31, 2013 (edited) HInt for velocity field in nFluid cache (mcc/mcx) : - How is velocity laid out? It is on the surfaces bettween voxels. Test to set velocities: for x in range(3): for y in range(5): for z in range(7): cmds.setFluidAttr(at='density', xi=x, yi=y, zi=z, fv=(x + y + z)) cmds.setFluidAttr(at='velocity', xi=x, yi=y, zi=z, vv=(x + 1, y + 1, z + 1)) Duncan says: Velocity is defined at voxel boundaries, not the centers (it takes a little thinking to appreciate this fully). Thus for a 10x10x10 grid the velocityX grid will be (11,10,10), the velocityY(10,11,10) and the velocityZ(10,10,11). The API docs also clarify quite well: http://download.auto...b82dbe223133529 Looking at the raw data set via cmds.setFluidAttr(..., lowerFace=True), the X values go (0, 1, 2, 2), the Y (0, 1, 2, 3, 4, 4), and the Z do the same. They also iterate in the same Z,Y,X order that the density does. **1 References: **1 : https://github.com/westernx/mayatools http://download.auto...99211af08ae8d0c http://blog3d.distill3d.com/ Edited October 31, 2013 by moomarkus Quote Link to comment Share on other sites More sharing options...
eko Posted December 27, 2013 Share Posted December 27, 2013 Nice tool !Thanks for sharing Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.