def UnapplySchema(self, dgModifier): if self.GetMayaObjectForSchema() is None: # Already unapplied? return False path = om.MDagPath.getAPathTo(self.mayaObject) if not path or not path.pop(): return False BulletUtils.checkPluginLoaded() BulletUtils.removeBulletObjectsFromList([path.fullPathName()]) return self.GetMayaObjectForSchema() is None
def _ApplyBulletSchema(mayaShape): """Creates a bullet simulation containing the "mayaShape", this is obviously demo code, so we will not even try to add the shape to an existing simluation.""" if _GetBulletShape(mayaShape) is not None: return True path = om.MDagPath.getAPathTo(mayaShape) if not path or not path.pop(): return False BulletUtils.checkPluginLoaded() RigidBody.CreateRigidBody.command(transformName=path.fullPathName(), bAttachSelected=False) return True
# GenerateFractureLogs # Script to generate fracture points in the Log scene import maya.cmds as cmds import random import math import maya.app.mayabullet.BulletUtils as BulletUtils import maya.app.mayabullet.RigidBody as RigidBody BulletUtils.checkPluginLoaded() # Get object to be shattered cmds.select(['log1','log2','log3']) selected = cmds.ls(sl=True, transforms=True) objCounter = 0 for obj in selected: print(obj) # Get center point of collision (in our case center of the logs) com = cmds.objectCenter(obj, gl=True) numPoints = 30 fractureRadius = 3 thickness = 1 # Will get divided by 2 height = cmds.getAttr(obj + '.translateY') transX = cmds.getAttr(obj + '.translateX') rotY = cmds.getAttr(obj + '.rotateY') voroX = [] voroY = [] voroZ = [] #print(height)
def testComplexAdaptation(self): """Test that we can adapt a bullet simulation""" mayaUsdLib.SchemaApiAdaptor.Register(TestBulletMassShemaAdaptor, "shape", "PhysicsMassAPI") mayaUsdLib.SchemaApiAdaptor.Register(TestBulletRigidBodyShemaAdaptor, "shape", "PhysicsRigidBodyAPI") # Build a scene (and exercise the adaptor in a freeform context) cmds.file(f=True, new=True) s1T = cmds.polySphere()[0] cmds.loadPlugin("bullet") if not BulletUtils.checkPluginLoaded(): return rbT, rbShape = RigidBody.CreateRigidBody().command( autoFit=True, colliderShapeType=RigidBody.eShapeType.kColliderSphere, meshes=[s1T], radius=1.0, mass=5.0, centerOfMass=(0.9, 0.8, 0.7)) # See if the plugin adaptor can read the bullet shape under the mesh: sl = om.MSelectionList() sl.add(s1T) dagPath = sl.getDagPath(0) dagPath.extendToShape() adaptor = mayaUsdLib.Adaptor(dagPath.fullPathName()) self.assertEqual(adaptor.GetUsdType(), Tf.Type.FindByName('UsdGeomMesh')) # NOTICE: PhysicsRigidBodyAPI is not in the list because that API is # supported only on export!!! self.assertEqual(adaptor.GetAppliedSchemas(), ['PhysicsMassAPI']) physicsMass = adaptor.GetSchemaByName("PhysicsMassAPI") self.assertEqual(physicsMass.GetName(), "PhysicsMassAPI") massAttributes = set([ 'physics:centerOfMass', 'physics:density', 'physics:diagonalInertia', 'physics:mass', 'physics:principalAxes' ]) self.assertEqual(set(physicsMass.GetAttributeNames()), massAttributes) bulletAttributes = set(['physics:centerOfMass', 'physics:mass']) self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()), bulletAttributes) bulletMass = physicsMass.GetAttribute('physics:mass') self.assertAlmostEqual(bulletMass.Get(), 5.0) bulletMass.Set(12.0) bulletCenter = physicsMass.GetAttribute('physics:centerOfMass') bulletCenter.Set(Gf.Vec3f(3, 4, 5)) sl = om.MSelectionList() sl.add(s1T) bulletPath = sl.getDagPath(0) bulletPath.extendToShape(1) massDepFn = om.MFnDependencyNode(bulletPath.node()) plug = om.MPlug(bulletPath.node(), massDepFn.attribute("mass")) self.assertAlmostEqual(plug.asFloat(), 12.0) # Create an untranslated attribute: usdDensity = physicsMass.CreateAttribute('physics:density') usdDensity.Set(33.0) self.assertAlmostEqual(usdDensity.Get(), 33.0) # This will result in a dynamic attribute on the bulletShape: plug = massDepFn.findPlug("USD_ATTR_physics_density", True) self.assertAlmostEqual(plug.asFloat(), 33.0) bulletAttributes.add('physics:density') self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()), bulletAttributes) physicsMass.RemoveAttribute('physics:density') bulletAttributes.remove('physics:density') self.assertEqual(set(physicsMass.GetAuthoredAttributeNames()), bulletAttributes) # Add some animation: cmds.setKeyframe(bulletPath, at="mass", t=0, v=3.0) cmds.setKeyframe(bulletPath, at="mass", t=10, v=30.0) # Modify the velocity so it can be exported to the RBD Physics schema. cmds.setKeyframe(bulletPath, at="initialVelocityX", t=0, v=5.0) cmds.setKeyframe(bulletPath, at="initialVelocityX", t=10, v=50.0) cmds.setKeyframe(bulletPath, at="initialVelocityY", t=0, v=6.0) cmds.setKeyframe(bulletPath, at="initialVelocityY", t=10, v=60.0) cmds.setKeyframe(bulletPath, at="initialVelocityZ", t=0, v=7.0) cmds.setKeyframe(bulletPath, at="initialVelocityZ", t=10, v=70.0) # Try applying the schema on a new sphere: s2T = cmds.polySphere()[0] sl.add(s2T) dagPath = sl.getDagPath(1) dagPath.extendToShape() adaptor = UsdMaya.Adaptor(dagPath.fullPathName()) physicsMass = adaptor.ApplySchemaByName("PhysicsMassAPI") self.assertEqual(physicsMass.GetName(), "PhysicsMassAPI") self.assertEqual(adaptor.GetUsdType(), Tf.Type.FindByName('UsdGeomMesh')) self.assertEqual(adaptor.GetAppliedSchemas(), ['PhysicsMassAPI']) usdDensity = physicsMass.CreateAttribute('physics:density') usdDensity.Set(33.0) # Export, but without enabling Bullet: usdFilePath = os.path.abspath('UsdExportSchemaApiTest_NoBullet.usda') cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath) # Check that there are no Physics API schemas exported: stage = Usd.Stage.Open(usdFilePath) for i in (1, 2): spherePrim = stage.GetPrimAtPath( '/pSphere{0}/pSphereShape{0}'.format(i)) self.assertFalse( "PhysicsMassAPI" in spherePrim.GetAppliedSchemas()) schemasToExport = ["PhysicsMassAPI", "PhysicsRigidBodyAPI"] # Export, with Bullet: usdFilePath = os.path.abspath('UsdExportSchemaApiTest_WithBullet.usda') cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFilePath, apiSchema=schemasToExport, frameRange=(1, 10)) # Check that Physics API schemas did get exported: stage = Usd.Stage.Open(usdFilePath) values = [ ("physics:centerOfMass", (Gf.Vec3f(3, 4, 5), Gf.Vec3f(0, 0, 0))), ("physics:mass", (3.0, 1.0)), ("physics:density", (None, 33.0)), ] for i in (1, 2): spherePrim = stage.GetPrimAtPath( '/pSphere{0}/pSphereShape{0}'.format(i)) self.assertTrue("PhysicsMassAPI" in spherePrim.GetAppliedSchemas()) for n, v in values: if v[i - 1]: a = spherePrim.GetAttribute(n) self.assertEqual(a.Get(), v[i - 1]) if i == 1: # Is mass animated? a = spherePrim.GetAttribute("physics:mass") self.assertEqual(a.Get(10), 30) # This got exported even though invisible in interactive: self.assertTrue( "PhysicsRigidBodyAPI" in spherePrim.GetAppliedSchemas()) a = spherePrim.GetAttribute("physics:velocity") if i == 1: self.assertEqual(a.Get(0), (5, 6, 7)) self.assertEqual(a.Get(10), (50, 60, 70)) numberOfExportedKeys = len(a.GetTimeSamples()) # Try unapplying the schema: adaptor.UnapplySchemaByName("PhysicsMassAPI") self.assertEqual(adaptor.GetAppliedSchemas(), []) # Test import of USDPhysics without job context: cmds.file(new=True, force=True) cmds.mayaUSDImport(f=usdFilePath) sl = om.MSelectionList() # pSphereShape1 is a transform, since the bullet shape prevented merging the mesh and the # transform. The shape will be pSphereShape1Shape... sl.add("pSphereShape1") bulletPath = sl.getDagPath(0) # No bullet shape since we did not put Bullet as jobContext self.assertEqual(bulletPath.numberOfShapesDirectlyBelow(), 1) cmds.file(new=True, force=True) cmds.mayaUSDImport(f=usdFilePath, apiSchema=schemasToExport, readAnimData=True) sl = om.MSelectionList() sl.add("pSphereShape1") bulletPath = sl.getDagPath(0) # Finds bullet shape since we did put Bullet as jobContext self.assertEqual(bulletPath.numberOfShapesDirectlyBelow(), 2) # The bullet shape has animated mass and initial velocity since we read the animation. bulletPath.extendToShape(1) massDepFn = om.MFnDependencyNode(bulletPath.node()) for attrName in ("mass", "initialVelocityX", "initialVelocityY", "initialVelocityZ"): plug = om.MPlug(bulletPath.node(), massDepFn.attribute(attrName)) self.assertTrue(plug.isConnected) fcurve = oma.MFnAnimCurve(plug.source().node()) self.assertEqual(fcurve.numKeys, numberOfExportedKeys)