jkunz07 Posted December 1, 2014 Share Posted December 1, 2014 (edited) I was wondering what the recommended workflow is for simulating a bunch of objects using packed primitives and then rendering them with motion blur. I've been conducting some tests and here's what I've found so far: I tried importing the packed geo from dops and rendering that - it didn't show up in the render, no errors or anything reported by Mantra even after increasing verbosity. While this is a bit odd it's not a to concerning for me, as the packed primitives aren't packed disk primitives it would be pretty inefficient to write them to disk or render them this way as a copy of the entire geometry would be stored for each frame. So I unpacked the geo, computed v with a trail sop and rendered with geometry velocity blur. This works and gives be rendered images i'm pleased with, but I can see it becoming pretty heavy and inefficient for really large sims. This method is also storing a copy of the entire geo (with additional v attribute) for every frame so the amount of disk space used by this method can grow quite large very quickly. I also tried writing out the geometry before sim, each piece a separate .bgeo file. Reading the pieces back in as packed disk primitives, then using the transform pieces sop to transform each packed disk primitive by it's corresponding simulation point. I couldn't really get this working, trying to use geometry deformation samples for motion blur always yielded some pretty odd results. Finally I made a subnet with a geometry object for every piece. Inside the geometry containers, the corresponding piece is read in through a file sop, bringing the geo in as a packed disk primitive. The simulation animation is baked into each objects translation and rotation parameters. This let's motion blur be calculated using transformation time samples. The geometry is much lighter too, as only on copy of the geometry must be saved for the entire animation, the geometry also doesn't need to have any v attribute. Here is a frame rendered using this method (The motion blur is all from xform time samples, only 1 geometry time sample, and no v attribute on geometry): My only concern is that this is very cumbersome, surely there must be a better way without having to create all these objects and animation channels for every fragment in your packed rbd sim?! Edited December 1, 2014 by jkunz07 Quote Link to comment Share on other sites More sharing options...
jkunz07 Posted December 2, 2014 Author Share Posted December 2, 2014 OK, I think I've sorted this out. The best solution I found was to write out each piece as a separate .bgeo file. So you would have like $HIP/geo/piece1.bgeo, $HIP/geo/piece2.bgeo, $HIP/geo/piece3.bgeo... etc. Then these pieces get read in, each one as a packed disk primitive and merged together like so: The packed disk pieces can be moved using xformpieces sop and the simulation points cached from the sim (dopimport "Create Points to Represent Objects"). The timeblend sop can then be used to generate sub frame data. So this can be rendered with geometry deformation blur giving you non-linear motion blur, really light .ifd files too cause everything is packed disk. I guess this is a better method then what I was doing previously although it's still a little counter-intuitive as you have to unlock the file merge to enable reading geo as packed disk. It is nice not to have to rely on scripts to bake the geo into the file though, especially as that can cause .hip files to become enormous pretty quickly. I'm thinking it still may be useful to bake sim xforms to object level xforms though, as this would allow for a nicely exported alembic hierarchy. Here is a file containing both methods of rendering with multi seg motion blur, transforming pieces at render-time. rbd_mo_blur.tar.gz The script to bake xforms is in the session module of the file, but I'll also put it here as it might be helpful def bake_sim_anim(): # The simulated packed geometry (fetch packed geometry from dop network) xfrom_pts = hou.node('/obj/rbd_packed_bullet/simulation_xform_pts') # Find how many pieces are in the simulated object # I guess we can't add or remove pieces during the sim if we're gonna do this method num_pieces = len(xfrom_pts.geometry().iterPoints()) # Make a subnet to store all the piece geometry objects in piece_subnet = hou.node('/obj').createNode("subnet", "bake_pieces_anim") # Fill the subnet with pieces for i in range(num_pieces): piece_geo = piece_subnet.createNode("geo", "piece"+str(i)) # Setup the file sop in every piece to load it's piece geo from disk piece_file = hou.node(piece_geo.path()+'/file1') hou.parm(piece_file.path()+'/missingframe').set(1) hou.parm(piece_file.path()+'/loadtype').set('delayed') hou.parm(piece_file.path()+'/viewportlod').set(0) hou.parm(piece_file.path()+'/file').set('$HIP/geo/piece'+str(i)+'.bgeo') # Set the pivot parameter of each piece hou.parmTuple(piece_geo.path()+'/p').set(xfrom_pts.geometry().iterPoints()[i].attribValue("pivot")) piece_subnet.layoutChildren() # Frame range to bake animation fstart = 1001 fend = 1096 finc = 1 cur_frame = fstart while cur_frame <= fend: hou.setFrame(cur_frame) for i in range(num_pieces): piv = hou.hmath.buildTranslate(hou.Vector3(xfrom_pts.geometry().iterPoints()[i].attribValue("pivot"))) # Roation matrix4 from primintrinsic tran = piv.inverted() tran *= hou.Matrix4(hou.Quaternion(xfrom_pts.geometry().iterPoints()[i].attribValue("orient")).extractRotationMatrix3()) # Xfrom matrix4 containing point translation #tran *= hou.hmath.buildTranslate(packed_geo.geometry().iterPoints()[i].position()-hou.Vector3(packed_geo.geometry().prims()[i].intrinsicValue("pivot"))) tran *= hou.hmath.buildTranslate(xfrom_pts.geometry().iterPoints()[i].position()) # Set parameter on object node hou.node(piece_subnet.path()+'/piece'+str(i)).setParmTransform(tran) # Bake current value of translation and rotation parms into keyframes for parm in hou.parmTuple(piece_subnet.path()+'/piece'+str(i)+'/t'): hou_keyframe = hou.Keyframe() hou_keyframe.setTime(hou.time()) hou_keyframe.setValue(parm.eval()) hou_keyframe.setExpression("linear()", hou.exprLanguage.Hscript) parm.setKeyframe(hou_keyframe) for parm in hou.parmTuple(piece_subnet.path()+'/piece'+str(i)+'/r'): hou_keyframe = hou.Keyframe() hou_keyframe.setTime(hou.time()) hou_keyframe.setValue(parm.eval()) hou_keyframe.setExpression("linear()", hou.exprLanguage.Hscript) parm.setKeyframe(hou_keyframe) # Increment the frame number cur_frame += finc 1 Quote Link to comment Share on other sites More sharing options...
csp Posted December 4, 2014 Share Posted December 4, 2014 # I guess we can't add or remove pieces during the sim if we're gonna do this method I believe you can if you nest the for-loops inside the while-loop. For examples: for every frame: for each piece: if piece has not been created inside the subnet: create it. set keyframes 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.