def update(self, state, time): # use 60 fps time codes time = time * 60.0 try: self.stage.SetEndTimeCode(time) except: pass # convert to list particle_x = state.q.tolist() particle_orientations = [Gf.Quath(1.0, 0.0, 0.0, 0.0)] * self.model.particle_count self.particle_instancer.GetPositionsAttr().Set(particle_x, time) self.particle_instancer.GetOrientationsAttr().Set(particle_orientations, time) # update cloth if (self.cloth_mesh): for k, v in self.cloth_remap.items(): self.cloth_verts[v] = particle_x[k] self.cloth_mesh.GetPointsAttr().Set(self.cloth_verts, time) # update springs if (self.model.spring_count > 0): line_positions = [] line_rotations = [] line_scales = [] for i in range(self.model.spring_count): index0 = self.model.spring_indices[i * 2 + 0] index1 = self.model.spring_indices[i * 2 + 1] pos0 = particle_x[index0] pos1 = particle_x[index1] (pos, rot, scale) = self.compute_segment_xform(Gf.Vec3f(pos0), Gf.Vec3f(pos1)) line_positions.append(pos) line_rotations.append(rot) line_scales.append(scale) self.line_instancer.GetPositionsAttr().Set(line_positions, time) self.line_instancer.GetOrientationsAttr().Set(line_rotations, time) self.line_instancer.GetScalesAttr().Set(line_scales, time) # rigids for b in range(self.model.rigid_count): #xform = UsdGeom.Xform.Define(self.stage, self.root.GetPath().AppendChild("body_" + str(b))) xform = UsdGeom.Xform(self.stage.GetPrimAtPath(self.root.GetPath().AppendChild("body_" + str(b)))) x = state.rigid_x[b].tolist() r = state.rigid_r[b].tolist() usd_set_xform(xform, x, r, (1.0, 1.0, 1.0), time)
def sync_update(root_prim, obj_data: ObjectData, is_updated_geometry, is_updated_transform, **kwargs): """ Updates existing rpr object. Checks obj.type and calls corresponded sync_update() """ log("sync_update", obj_data.object, obj_data.instance_id, is_updated_geometry, is_updated_transform) obj_prim = root_prim.GetChild(obj_data.sdf_name) if not obj_prim.IsValid(): sync(root_prim, obj_data, **kwargs) return if is_updated_transform: xform = UsdGeom.Xform(obj_prim) xform.MakeMatrixXform().Set(Gf.Matrix4d(obj_data.transform)) if is_updated_geometry: obj = obj_data.object if obj.type == 'MESH': if obj.mode == 'OBJECT': mesh.sync_update(obj_prim, obj, **kwargs) else: to_mesh.sync_update(obj_prim, obj, **kwargs) elif obj.type == 'LIGHT': light.sync_update(obj_prim, obj, **kwargs) elif obj.type == 'CAMERA': camera.sync_update(obj_prim, obj, **kwargs) elif obj.type in ('EMPTY', 'ARMATURE'): pass else: to_mesh.sync_update(obj_prim, obj, **kwargs)
def sync_from_prim(self, prim, context): prim_obj = self.id_data if not prim or str(prim.GetTypeName()) != 'Xform': self.cached_stage.clear() prim_obj.name = self.sdf_path = "/" prim_obj.matrix_world = mathutils.Matrix.Identity(4) # hiding, deactivating and deselecting prim object prim_obj.hide_viewport = True prim_obj.select_set(False) if context.view_layer.objects.active == prim_obj: context.view_layer.objects.active = None return self.cached_stage.assign(prim.GetStage()) prim_obj.name = self.sdf_path = str(prim.GetPath()) xform = UsdGeom.Xform(prim) ops = xform.GetOrderedXformOps() if ops: prim_obj.matrix_world = mathutils.Matrix(ops[0].Get()).transposed() else: prim_obj.matrix_world = mathutils.Matrix.Identity(4) # showing, activating and selecting prim object prim_obj.hide_viewport = False context.view_layer.objects.active = prim_obj if len(context.selected_objects) < 2: if context.selected_objects: context.selected_objects[0].select_set(False) prim_obj.select_set(True)
def sync_update(root_prim, obj: bpy.types.Object, is_updated_geometry, is_updated_transform, **kwargs): """ Updates existing rpr object. Checks obj.type and calls corresponded sync_update() """ log("sync_update", obj, is_updated_geometry, is_updated_transform) obj_prim = root_prim.GetChild(sdf_name(obj)) if not obj_prim.IsValid(): sync(root_prim, obj, **kwargs) return if is_updated_transform: xform = UsdGeom.Xform(obj_prim) xform.MakeMatrixXform().Set(Gf.Matrix4d(get_transform(obj))) if is_updated_geometry: if obj.type == 'MESH': if obj.mode == 'OBJECT': mesh.sync_update(obj_prim, obj, **kwargs) else: to_mesh.sync_update(obj_prim, obj, **kwargs) elif obj.type == 'LIGHT': light.sync_update(obj_prim, obj, **kwargs) elif obj.type in ('CURVE', 'FONT', 'SURFACE', 'META'): to_mesh.sync_update(obj_prim, obj, **kwargs) elif obj.type == 'EMPTY': pass else: log.warn("Not supported object to sync_update", obj, obj.type)
def sync_to_prim(self): prim = self.get_prim() if not prim: return obj = self.id_data xform = UsdGeom.Xform(prim) xform.MakeMatrixXform().Set(Gf.Matrix4d(object.get_transform_local(obj)))
def sync_to_prim(self): stage = self.cached_stage() if not stage: return obj = self.id_data prim = stage.GetPrimAtPath(self.sdf_path) xform = UsdGeom.Xform(prim) xform.MakeMatrixXform().Set(Gf.Matrix4d(get_transform(obj)))
def sync_from_prim(self, root_obj, prim): prim_obj = self.id_data self.sdf_path = str(prim.GetPath()) self.cached_stage.assign(prim.GetStage()) prim_obj.name = prim.GetName() prim_obj.parent = root_obj prim_obj.matrix_local = usd_utils.get_xform_transform(UsdGeom.Xform(prim)) prim_obj.hide_viewport = prim.GetTypeName() not in GEOM_TYPES
def _ValidateXformPrim(self, stage, xformPrimPath, expectedTranslation=None): xformPrim = stage.GetPrimAtPath(xformPrimPath) self.assertTrue(xformPrim) xformSchema = UsdGeom.Xform(xformPrim) self.assertTrue(xformSchema) self._ValidateXformOps(xformPrim, expectedTranslation) return xformSchema
def __init__(self, stroke, startVert, vertCount, startIndex, indexCount): # pylint: disable=too-many-arguments self.stroke = stroke self.startVert = startVert self.vertCount = vertCount self.startIndex = startIndex self.indexCount = indexCount self.i = startVert self.step = 10 self.radius = 0 self.indicesWritten = 0 self.growthVel = 1 self.minHeight = self.GetVertex(0)[2] self.maxHeight = self.GetVertex(0)[2] self.avgHeight = self.GetVertex(0)[2] self.minLen = 10000000 self.minPoint = self.GetVertex(0) minVal = (self.minPoint - worldCenter).GetLength() for i in range(vertCount): v = self.GetVertex(i) length = (v - worldCenter).GetLength() if length < minVal: minVal = length self.minPoint = v if Gf.IsClose(v, Gf.Vec3f(), 1e-7): continue length = Gf.Vec2f(v[0], v[2]).GetLength() self.minHeight = min(self.minHeight, v[1]) self.maxHeight = max(self.minHeight, v[1]) self.avgHeight = (self.maxHeight - self.minHeight) / 2.0 self.minLen = min(self.minLen, length) # Debug visualization. self.minPtDebug = UsdGeom.Sphere.Define( stroke.prim.GetStage(), str(stroke.prim.GetPath()) + "/minPt" + str(startIndex), ) self.minPtDebug.GetPrim().GetAttribute("purpose").Set("guide") attr = self.minPtDebug.GetPrim().GetAttribute( "primvars:displayOpacity") attr.Set([0.25]) attr.SetMetadata("interpolation", "constant") attr = self.minPtDebug.GetPrim().GetAttribute("primvars:displayColor") attr.Set([Gf.Vec3f(1, 1, 1)], 0) attr.SetMetadata("interpolation", "constant") self.minPtDebug.CreateRadiusAttr(1.0) UsdGeom.Xform(self.minPtDebug.GetPrim()).AddTranslateOp().Set( self.minPoint)
def animate(stage): """The output from Tilt Brush is strokes with a growth velocity. This could be authored per vertex later (e.g. for easing). """ # The current animation time, this will increase monotonicly to generate frames of animation. time = 1 # The maximum number of animated strokes, for performance constraints. maxActive = 30 # Filters dictate when a stroke becomes active, i.e. predicates for activation. activeFilter = isInRadius activeFilterVert = isHigherVert # The target length of the animation. lengthInSeconds = 30 # The playback framerate. framesPerSecond = 30 # The number of frames we will generate based on target time and rate. numFrames = lengthInSeconds * framesPerSecond # Boundaries for activation. minHeight = 0 maxHeight = 20 radius = 17.0 maxRadius = 100. height = minHeight # Compute the actual radius of the world bounds. worldBounds = UsdGeom.Xform(stage.GetPrimAtPath("/")).ComputeWorldBound(0, "default") maxRadius = (worldBounds.GetRange().max - worldBounds.GetRange().min).GetLength() # Compute the centroid of the world. global worldCenter worldCenter = Gf.Vec3f(worldBounds.ComputeCentroid()) # Just for newIntroSketch.tilt if "NewIntroSketch" in stage.GetRootLayer().identifier: worldCenter = Gf.Vec3f(0.73135, 19.92212, 33.2210311) worldCenter[1] = worldBounds.GetRange().min[1] print("World Center:", worldCenter) print("Max Radius:", maxRadius) # Visualize the radius. debugSphere = UsdGeom.Sphere(stage.DefinePrim("/debug", "Sphere")) debugSphere.CreateRadiusAttr(radius) debugSphere.GetPrim().GetAttribute("purpose").Set("guide") attr = debugSphere.GetPrim().GetAttribute("primvars:displayOpacity") attr.Set([0.125]) attr.SetMetadata("interpolation", "constant") UsdGeom.Xform(attr.GetPrim()).AddTranslateOp().Set(worldCenter) # Initialize data structures. # - strokes are Unity meshes (or Tilt Brush batches). # - substrokes are the individual brush strokes within a single mesh. # - activeSubstrokes are sub-strokes currently in-flight. # - completeSubstrokes are sub-strokes that are done animating. strokes = MakeStrokes(stage) substrokes = MakeSubstrokes(strokes) activeStrokes = set() activeSubstrokes = set() completeSubstrokes = set() # Compute step sizes based on target animation length. dRadius = (maxRadius - radius) / float(numFrames) / 1.5 dHeight = (maxHeight - minHeight) / float(numFrames) # Set USD animation start/end times. stage.SetStartTimeCode(time) stage.SetEndTimeCode(numFrames) # Zero out stroke opacities for s in strokes: s.Save(time) # Main animation loop. for time in range(0, numFrames): print() print("Time:", time, height, radius, smoothstep(1.0, float(numFrames), time)) curActive = 0 if len(activeStrokes) < maxActive: # On the final frame, increase activation volumes to "infinity" (and beyond ;) if time == numFrames - 1: height = 10000000 radius = 10000000 # Search for strokes to be activated. didAddStroke = 0 for ss in substrokes: # Already animating, skip. if ss in activeSubstrokes: continue # Done animating, skip. if ss in completeSubstrokes: continue # Overloaded. if len(activeStrokes) >= maxActive: break # If this sub-stroke passes the filter, add it to the animating list. if activeFilter(ss.minPoint, radius): didAddStroke = 1 activeSubstrokes.add(ss) activeStrokes.add(ss.stroke) # Mark the stroke as dirty to save its initial state. ss.stroke.dirty = True ss.SetRadius(radius, time) print("+", end=' ') if not didAddStroke: # We didn't add any strokes, which means the radius needs to increase. # Grow the activation volumes (increase sphere size, raise floor plane height). height += dHeight radius += dRadius * smoothstep(1.0, float(numFrames), time) # Update debug vis. debugSphere.GetRadiusAttr().Set(radius, time) # Call save on everything, but only dirty strokes will actually write data. # Save a key at the previous frame here so that when a stroke starts animating, when linearly # interpolated, it will not start animating from frame zero to the first key frame. #for s in strokes: # s.Save(time - 1) # Update stroke animation. remove = [] for ss in activeSubstrokes: print(".", end=' ') if not ss.Update(dRadius, smoothstep(1.0, float(numFrames), time)): if ss.indicesWritten != ss.indexCount: raise "Fail" remove.append(ss) # Remove all the completed strokes. for ss in remove: activeSubstrokes.remove(ss) completeSubstrokes.add(ss) # Save keyframes for the current time. for s in strokes: s.Save(time) # Rebuild the activeStrokes set. activeStrokes = set() for ss in activeSubstrokes: activeStrokes.add(ss.stroke) # Drainstop: we have leftover strokes that didn't finish animating within the target time, rather # than popping them, we let them finish animating and run over the target time. while len(activeSubstrokes) > 0: remove = [] time += 1 # Since we blew past the initial frame estimate, we also need to update the USD end time. stage.SetEndTimeCode(time) # Loop: update, remove, save, rinse, repeat. for ss in activeSubstrokes: if not ss.Update(dRadius, 2.0): if ss.indicesWritten != ss.indexCount: raise "Fail" remove.append(ss) for ss in remove: activeSubstrokes.remove(ss) completeSubstrokes.add(ss) for s in strokes: s.Save(time)
def sync_transform_from_prim(self, prim): prim_obj = self.id_data prim_obj.matrix_local = usd_utils.get_xform_transform( UsdGeom.Xform(prim))