private BabylonMatrix ConvertMayaToBabylonMatrix(MMatrix mMatrix) { var transformationMatrix = new MTransformationMatrix(mMatrix); // Retreive TRS vectors from matrix float[] position = transformationMatrix.getTranslation(); float[] rotationQuaternion = transformationMatrix.getRotationQuaternion(); float[] scaling = transformationMatrix.getScale(); // Switch coordinate system at object level position[2] *= -1; rotationQuaternion[0] *= -1; rotationQuaternion[1] *= -1; // Apply unit conversion factor to meter position[0] *= scaleFactorToMeters; position[1] *= scaleFactorToMeters; position[2] *= scaleFactorToMeters; // The composed matrix return(BabylonMatrix.Compose(new BabylonVector3(scaling[0], scaling[1], scaling[2]), // scaling new BabylonQuaternion(rotationQuaternion[0], rotationQuaternion[1], rotationQuaternion[2], rotationQuaternion[3]), // rotation new BabylonVector3(position[0], position[1], position[2]) // position )); }
private void GetTransform(MFnTransform mFnTransform, ref float[] position, ref float[] rotationQuaternion, ref float[] rotation, ref BabylonVector3.EulerRotationOrder rotationOrder, ref float[] scaling) { var transformationMatrix = new MTransformationMatrix(mFnTransform.transformationMatrix); var mayaRotationOrder = 0; MGlobal.executeCommand($"getAttr {mFnTransform.fullPathName}.rotateOrder", out mayaRotationOrder); rotationOrder = Tools.ConvertMayaRotationOrder((MEulerRotation.RotationOrder)mayaRotationOrder); position = transformationMatrix.getTranslation(); rotationQuaternion = transformationMatrix.getRotationQuaternion(); rotation = transformationMatrix.getRotation(); scaling = transformationMatrix.getScale(); // Switch coordinate system at object level position[2] *= -1; rotationQuaternion[0] *= -1; rotationQuaternion[1] *= -1; rotation[0] *= -1; rotation[1] *= -1; rotationOrder = Tools.InvertRotationOrder(rotationOrder); // Apply unit conversion factor to meter position[0] *= scaleFactorToMeters; position[1] *= scaleFactorToMeters; position[2] *= scaleFactorToMeters; }
private void GetTransform(MFnTransform mFnTransform, ref float[] position) { var transformationMatrix = new MTransformationMatrix(mFnTransform.transformationMatrix); position = transformationMatrix.getTranslation(); // Switch coordinate system at object level position[2] *= -1; }
private void GetTransform(MFnTransform mFnTransform, ref float[] position, ref float[] rotationQuaternion, ref float[] rotation, ref float[] scaling) { var transformationMatrix = new MTransformationMatrix(mFnTransform.transformationMatrix); position = transformationMatrix.getTranslation(); rotationQuaternion = transformationMatrix.getRotationQuaternion(); rotation = transformationMatrix.getRotation(); scaling = transformationMatrix.getScale(); // Switch coordinate system at object level position[2] *= -1; rotationQuaternion[0] *= -1; rotationQuaternion[1] *= -1; rotation[0] *= -1; rotation[1] *= -1; }
private void ExportTransform(BabylonAbstractMesh babylonAbstractMesh, MFnDagNode mFnDagNode) { // Position / rotation / scaling var transformationMatrix = new MTransformationMatrix(mFnDagNode.transformationMatrix); babylonAbstractMesh.position = transformationMatrix.getTranslation(); if (_exportQuaternionsInsteadOfEulers) { babylonAbstractMesh.rotationQuaternion = transformationMatrix.getRotationQuaternion(); } else { babylonAbstractMesh.rotation = transformationMatrix.getRotation(); } babylonAbstractMesh.scaling = transformationMatrix.getScale(); }
private BabylonNode ExportMesh(MObject mObject, BabylonScene babylonScene) { MFnMesh mFnMesh = new MFnMesh(mObject); MFnDagNode mFnDagNode = new MFnDagNode(mObject); var mObjectParent = mFnMesh.parent(0); MFnDagNode mFnDagNodeParent = new MFnDagNode(mObjectParent); // --- prints --- #region prints RaiseVerbose("BabylonExporter.Mesh | mFnMesh data", 2); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.name=" + mFnMesh.name, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.absoluteName=" + mFnMesh.absoluteName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.fullPathName=" + mFnMesh.fullPathName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.partialPathName=" + mFnMesh.partialPathName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numVertices=" + mFnMesh.numVertices, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numEdges=" + mFnMesh.numEdges, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numPolygons=" + mFnMesh.numPolygons, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numFaceVertices=" + mFnMesh.numFaceVertices, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numNormals=" + mFnMesh.numNormals, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numUVSets=" + mFnMesh.numUVSets, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numUVsProperty=" + mFnMesh.numUVsProperty, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.activeColor=" + mFnMesh.activeColor.toString(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.attributeCount=" + mFnMesh.attributeCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.childCount=" + mFnMesh.childCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.displayColors=" + mFnMesh.displayColors, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.dormantColor=" + mFnMesh.dormantColor, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.hasUniqueName=" + mFnMesh.hasUniqueName, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.inUnderWorld=" + mFnMesh.inUnderWorld, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isDefaultNode=" + mFnMesh.isDefaultNode, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isInstanceable=" + mFnMesh.isInstanceable, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isInstanced(true)=" + mFnMesh.isInstanced(true), 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isInstanced(false)=" + mFnMesh.isInstanced(false), 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isInstanced()=" + mFnMesh.isInstanced(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isIntermediateObject=" + mFnMesh.isIntermediateObject, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.isShared=" + mFnMesh.isShared, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numColorSets=" + mFnMesh.numColorSets, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.numColorsProperty=" + mFnMesh.numColorsProperty, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.objectColor=" + mFnMesh.objectColor, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.parentCount=" + mFnMesh.parentCount, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.parentNamespace=" + mFnMesh.parentNamespace, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.uuid().asString()=" + mFnMesh.uuid().asString(), 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.dagRoot().apiType=" + mFnMesh.dagRoot().apiType, 3); RaiseVerbose("BabylonExporter.Mesh | mFnMesh.model.equalEqual(mFnMesh.objectProperty)=" + mFnMesh.model.equalEqual(mFnMesh.objectProperty), 3); RaiseVerbose("BabylonExporter.Mesh | ToString(mFnMesh.transformationMatrix)=" + mFnMesh.transformationMatrix.toString(), 3); var transformationMatrix = new MTransformationMatrix(mFnMesh.transformationMatrix); RaiseVerbose("BabylonExporter.Mesh | transformationMatrix.getTranslation().toString()=" + transformationMatrix.getTranslation().toString(), 3); var transformationMatrixParent = new MTransformationMatrix(mFnDagNodeParent.transformationMatrix); RaiseVerbose("BabylonExporter.Mesh | transformationMatrixParent.getTranslation().toString()=" + transformationMatrixParent.getTranslation().toString(), 3); // Geometry MIntArray triangleCounts = new MIntArray(); MIntArray trianglesVertices = new MIntArray(); mFnMesh.getTriangles(triangleCounts, trianglesVertices); RaiseVerbose("BabylonExporter.Mesh | triangleCounts.ToArray()=" + triangleCounts.ToArray().toString(), 3); RaiseVerbose("BabylonExporter.Mesh | trianglesVertices.ToArray()=" + trianglesVertices.ToArray().toString(), 3); int[] polygonsVertexCount = new int[mFnMesh.numPolygons]; for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++) { polygonsVertexCount[polygonId] = mFnMesh.polygonVertexCount(polygonId); } RaiseVerbose("BabylonExporter.Mesh | polygonsVertexCount=" + polygonsVertexCount.toString(), 3); //MFloatPointArray points = new MFloatPointArray(); //mFnMesh.getPoints(points); //RaiseVerbose("BabylonExporter.Mesh | points.ToArray()=" + points.ToArray().Select(mFloatPoint => mFloatPoint.toString()), 3); //MFloatVectorArray normals = new MFloatVectorArray(); //mFnMesh.getNormals(normals); //RaiseVerbose("BabylonExporter.Mesh | normals.ToArray()=" + normals.ToArray().Select(mFloatPoint => mFloatPoint.toString()), 3); for (int polygonId = 0; polygonId < mFnMesh.numPolygons; polygonId++) { MIntArray verticesId = new MIntArray(); RaiseVerbose("BabylonExporter.Mesh | polygonId=" + polygonId, 3); int nbTriangles = triangleCounts[polygonId]; RaiseVerbose("BabylonExporter.Mesh | nbTriangles=" + nbTriangles, 3); for (int triangleIndex = 0; triangleIndex < triangleCounts[polygonId]; triangleIndex++) { RaiseVerbose("BabylonExporter.Mesh | triangleIndex=" + triangleIndex, 3); int[] triangleVertices = new int[3]; mFnMesh.getPolygonTriangleVertices(polygonId, triangleIndex, triangleVertices); RaiseVerbose("BabylonExporter.Mesh | triangleVertices=" + triangleVertices.toString(), 3); foreach (int vertexId in triangleVertices) { RaiseVerbose("BabylonExporter.Mesh | vertexId=" + vertexId, 3); MPoint point = new MPoint(); mFnMesh.getPoint(vertexId, point); RaiseVerbose("BabylonExporter.Mesh | point=" + point.toString(), 3); MVector normal = new MVector(); mFnMesh.getFaceVertexNormal(polygonId, vertexId, normal); RaiseVerbose("BabylonExporter.Mesh | normal=" + normal.toString(), 3); } } } #endregion if (IsMeshExportable(mFnMesh) == false) { return(null); } RaiseMessage(mFnMesh.name, 1); var babylonMesh = new BabylonMesh { name = mFnMesh.name, id = mFnMesh.uuid().asString() }; // Position / rotation / scaling / hierarchy ExportNode(babylonMesh, mFnDagNode, babylonScene); // Misc. // TODO - Retreive from Maya // TODO - What is the difference between isVisible and visibility? // TODO - Fix fatal error: Attempting to save in C:/Users/Fabrice/AppData/Local/Temp/Fabrice.20171205.1613.ma //babylonMesh.isVisible = mDagPath.isVisible; //babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever); //babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1; //babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1; if (mFnMesh.numPolygons < 1) { RaiseError($"Mesh {babylonMesh.name} has no face", 2); } if (mFnMesh.numVertices < 3) { RaiseError($"Mesh {babylonMesh.name} has not enough vertices", 2); } if (mFnMesh.numVertices >= 65536) { RaiseWarning($"Mesh {babylonMesh.name} has more than 65536 vertices which means that it will require specific WebGL extension to be rendered. This may impact portability of your scene on low end devices.", 2); } // TODO - Material var vertices = new List <GlobalVertex>(); var indices = new List <int>(); // TODO - UV, color, alpha //var mappingChannels = unskinnedMesh.ActiveMapChannelNum; //bool hasUV = false; //bool hasUV2 = false; //for (int i = 0; i < mappingChannels.Count; ++i) //{ // var indexer = i; // var channelNum = mappingChannels[indexer]; // if (channelNum == 1) // { // hasUV = true; // } // else if (channelNum == 2) // { // hasUV2 = true; // } //} //var hasColor = unskinnedMesh.NumberOfColorVerts > 0; //var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0; // TODO - Add custom properties var optimizeVertices = false; // meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices"); // Compute normals var subMeshes = new List <BabylonSubMesh>(); ExtractGeometry(mFnMesh, vertices, indices, subMeshes, optimizeVertices); if (vertices.Count >= 65536) { RaiseWarning($"Mesh {babylonMesh.name} has {vertices.Count} vertices. This may prevent your scene to work on low end devices where 32 bits indice are not supported", 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } RaiseMessage($"{vertices.Count} vertices, {indices.Count / 3} faces", 2); // Buffers babylonMesh.positions = vertices.SelectMany(v => v.Position).ToArray(); babylonMesh.normals = vertices.SelectMany(v => v.Normal).ToArray(); babylonMesh.subMeshes = subMeshes.ToArray(); // Buffers - Indices babylonMesh.indices = indices.ToArray(); babylonScene.MeshesList.Add(babylonMesh); RaiseMessage("BabylonExporter.Mesh | done", 3); return(babylonMesh); }
private List <BabylonAnimation> GetAnimationsFrameByFrame(MFnTransform mFnTransform) { int start = Loader.GetMinTime(); int end = Loader.GetMaxTime(); // Animations List <BabylonAnimation> animations = new List <BabylonAnimation>(); string[] babylonAnimationProperties = new string[] { "scaling", "rotationQuaternion", "position", "visibility" }; Dictionary <string, List <BabylonAnimationKey> > keysPerProperty = new Dictionary <string, List <BabylonAnimationKey> >(); keysPerProperty.Add("scaling", new List <BabylonAnimationKey>()); keysPerProperty.Add("rotationQuaternion", new List <BabylonAnimationKey>()); keysPerProperty.Add("position", new List <BabylonAnimationKey>()); keysPerProperty.Add("visibility", new List <BabylonAnimationKey>()); // get keys for (int currentFrame = start; currentFrame <= end; currentFrame++) { // get transformation matrix at this frame MDoubleArray mDoubleMatrix = new MDoubleArray(); MGlobal.executeCommand($"getAttr -t {currentFrame} {mFnTransform.fullPathName}.matrix", mDoubleMatrix); mDoubleMatrix.get(out float[] localMatrix); MMatrix matrix = new MMatrix(localMatrix); var transformationMatrix = new MTransformationMatrix(matrix); // Retreive TRS vectors from matrix var position = transformationMatrix.getTranslation(); var rotationQuaternion = transformationMatrix.getRotationQuaternion(); var scaling = transformationMatrix.getScale(); // Switch coordinate system at object level position[2] *= -1; rotationQuaternion[0] *= -1; rotationQuaternion[1] *= -1; // create animation key for each property for (int indexAnimation = 0; indexAnimation < babylonAnimationProperties.Length; indexAnimation++) { string babylonAnimationProperty = babylonAnimationProperties[indexAnimation]; BabylonAnimationKey key = new BabylonAnimationKey(); key.frame = currentFrame; switch (indexAnimation) { case 0: // scaling key.values = scaling.ToArray(); break; case 1: // rotationQuaternion key.values = rotationQuaternion.ToArray(); break; case 2: // position key.values = position.ToArray(); break; case 3: // visibility key.values = new float[] { Loader.GetVisibility(mFnTransform.fullPathName, currentFrame) }; break; } keysPerProperty[babylonAnimationProperty].Add(key); } } // create animation for each property for (int indexAnimation = 0; indexAnimation < babylonAnimationProperties.Length; indexAnimation++) { string babylonAnimationProperty = babylonAnimationProperties[indexAnimation]; List <BabylonAnimationKey> keys = keysPerProperty[babylonAnimationProperty]; var keysFull = new List <BabylonAnimationKey>(keys); // Optimization OptimizeAnimations(keys, true); // Ensure animation has at least 2 frames if (IsAnimationKeysRelevant(keys)) { int dataType = 0; // "scaling", "rotationQuaternion", "position", "visibility" if (indexAnimation == 0 || indexAnimation == 2) // scaling and position { dataType = (int)BabylonAnimation.DataType.Vector3; } else if (indexAnimation == 1) // rotationQuaternion { dataType = (int)BabylonAnimation.DataType.Quaternion; } else // visibility { dataType = (int)BabylonAnimation.DataType.Float; } // Create BabylonAnimation animations.Add(new BabylonAnimation() { dataType = dataType, name = babylonAnimationProperty + " animation", framePerSecond = Loader.GetFPS(), loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle, property = babylonAnimationProperty, keys = keys.ToArray(), keysFull = keysFull }); } } return(animations); }
public void ResetLights() { //<AmbientLight Color="White" /> //<DirectionalLight Color="White" Direction="-1,-1,-1" /> //<PointLight Color="White" ConstantAttenuation="1" LinearAttenuation="1" Position="0,0,0" QuadraticAttenuation="1" Range="0" /> //<SpotLight Color="White" ConstantAttenuation="1" Direction="-1,-1,-1" InnerConeAngle="10" LinearAttenuation="1" OuterConeAngle="10" Position="0,0,0" QuadraticAttenuation="1" Range="0" /> lights.Children.Clear(); MItDag dagIterator = new MItDag(MItDag.TraversalType.kDepthFirst, MFn.Type.kLight); for ( ; !dagIterator.isDone; dagIterator.next()) { MDagPath lightPath = new MDagPath(); dagIterator.getPath(lightPath); MFnLight light = new MFnLight(lightPath); bool isAmbient = light.lightAmbient; MColor mcolor = light.color; Color color = Color.FromScRgb(1.0f, mcolor.r, mcolor.g, mcolor.b); if (isAmbient) { AmbientLight ambient = new AmbientLight(color); lights.Children.Add(ambient); continue; } MFloatVector lightDirection = light.lightDirection(0, MSpace.Space.kWorld); Vector3D direction = new Vector3D(lightDirection.x, lightDirection.y, lightDirection.z); bool isDiffuse = light.lightDiffuse; try { MFnDirectionalLight dirLight = new MFnDirectionalLight(lightPath); DirectionalLight directional = new DirectionalLight(color, direction); lights.Children.Add(directional); continue; } catch { } MObject transformNode = lightPath.transform; MFnDagNode transform = new MFnDagNode(transformNode); MTransformationMatrix matrix = new MTransformationMatrix(transform.transformationMatrix); double [] threeDoubles = new double [3]; int rOrder = 0; //MTransformationMatrix.RotationOrder rOrder ; matrix.getRotation(threeDoubles, out rOrder, MSpace.Space.kWorld); matrix.getScale(threeDoubles, MSpace.Space.kWorld); MVector pos = matrix.getTranslation(MSpace.Space.kWorld); Point3D position = new Point3D(pos.x, pos.y, pos.z); try { MFnPointLight pointLight = new MFnPointLight(lightPath); PointLight point = new PointLight(color, position); //point.ConstantAttenuation =pointLight. ; // LinearAttenuation / QuadraticAttenuation //point.Range =pointLight.rayDepthLimit ; lights.Children.Add(point); continue; } catch { } try { MFnSpotLight spotLight = new MFnSpotLight(lightPath); MAngle InnerConeAngle = new MAngle(spotLight.coneAngle); MAngle OuterConeAngle = new MAngle(spotLight.penumbraAngle); SpotLight spot = new SpotLight(color, position, direction, OuterConeAngle.asDegrees, InnerConeAngle.asDegrees); spot.ConstantAttenuation = spotLight.dropOff; // LinearAttenuation / QuadraticAttenuation //spot.Range =spotLight.rayDepthLimit ; lights.Children.Add(spot); continue; } catch { } } }
public void ResetLights() { //<AmbientLight Color="White" /> //<DirectionalLight Color="White" Direction="-1,-1,-1" /> //<PointLight Color="White" ConstantAttenuation="1" LinearAttenuation="1" Position="0,0,0" QuadraticAttenuation="1" Range="0" /> //<SpotLight Color="White" ConstantAttenuation="1" Direction="-1,-1,-1" InnerConeAngle="10" LinearAttenuation="1" OuterConeAngle="10" Position="0,0,0" QuadraticAttenuation="1" Range="0" /> lights.Children.Clear () ; MItDag dagIterator =new MItDag (MItDag.TraversalType.kDepthFirst, MFn.Type.kLight) ; for ( ; !dagIterator.isDone ; dagIterator.next () ) { MDagPath lightPath =new MDagPath () ; dagIterator.getPath (lightPath) ; MFnLight light =new MFnLight (lightPath) ; bool isAmbient =light.lightAmbient ; MColor mcolor =light.color ; Color color =Color.FromScRgb (1.0f, mcolor.r, mcolor.g, mcolor.b) ; if ( isAmbient ) { AmbientLight ambient =new AmbientLight (color) ; lights.Children.Add (ambient) ; continue ; } MFloatVector lightDirection =light.lightDirection (0, MSpace.Space.kWorld) ; Vector3D direction =new Vector3D (lightDirection.x, lightDirection.y, lightDirection.z) ; bool isDiffuse =light.lightDiffuse ; try { MFnDirectionalLight dirLight =new MFnDirectionalLight (lightPath) ; DirectionalLight directional =new DirectionalLight (color, direction) ; lights.Children.Add (directional) ; continue ; } catch { } MObject transformNode =lightPath.transform ; MFnDagNode transform =new MFnDagNode (transformNode) ; MTransformationMatrix matrix =new MTransformationMatrix (transform.transformationMatrix) ; double [] threeDoubles =new double [3] ; int rOrder =0 ; //MTransformationMatrix.RotationOrder rOrder ; matrix.getRotation (threeDoubles, out rOrder, MSpace.Space.kWorld) ; matrix.getScale (threeDoubles, MSpace.Space.kWorld) ; MVector pos =matrix.getTranslation (MSpace.Space.kWorld) ; Point3D position =new Point3D (pos.x, pos.y, pos.z) ; try { MFnPointLight pointLight =new MFnPointLight (lightPath) ; PointLight point =new PointLight (color, position) ; //point.ConstantAttenuation =pointLight. ; // LinearAttenuation / QuadraticAttenuation //point.Range =pointLight.rayDepthLimit ; lights.Children.Add (point) ; continue ; } catch { } try { MFnSpotLight spotLight =new MFnSpotLight (lightPath) ; MAngle InnerConeAngle =new MAngle (spotLight.coneAngle) ; MAngle OuterConeAngle =new MAngle (spotLight.penumbraAngle) ; SpotLight spot =new SpotLight (color, position, direction, OuterConeAngle.asDegrees, InnerConeAngle.asDegrees) ; spot.ConstantAttenuation =spotLight.dropOff ; // LinearAttenuation / QuadraticAttenuation //spot.Range =spotLight.rayDepthLimit ; lights.Children.Add (spot) ; continue ; } catch { } } }
private List <BabylonAnimation> GetAnimationsFrameByFrame(MFnTransform mFnTransform) { int start = GetMinTime()[0]; int end = GetMaxTime()[0]; // Animations List <BabylonAnimation> animations = new List <BabylonAnimation>(); string[] babylonAnimationProperties = new string[] { "scaling", "rotationQuaternion", "position" }; Dictionary <string, List <BabylonAnimationKey> > keysPerProperty = new Dictionary <string, List <BabylonAnimationKey> >(); keysPerProperty.Add("scaling", new List <BabylonAnimationKey>()); keysPerProperty.Add("rotationQuaternion", new List <BabylonAnimationKey>()); keysPerProperty.Add("position", new List <BabylonAnimationKey>()); // get keys for (int currentFrame = start; currentFrame <= end; currentFrame++) { // get transformation matrix at this frame MDoubleArray mDoubleMatrix = new MDoubleArray(); MGlobal.executeCommand($"getAttr -t {currentFrame} {mFnTransform.fullPathName}.matrix", mDoubleMatrix); mDoubleMatrix.get(out float[] localMatrix); MMatrix matrix = new MMatrix(localMatrix); var transformationMatrix = new MTransformationMatrix(matrix); // Retreive TRS vectors from matrix var position = transformationMatrix.getTranslation(); var rotationQuaternion = transformationMatrix.getRotationQuaternion(); var scaling = transformationMatrix.getScale(); // Switch coordinate system at object level position[2] *= -1; rotationQuaternion[0] *= -1; rotationQuaternion[1] *= -1; // create animation key for each property for (int indexAnimation = 0; indexAnimation < babylonAnimationProperties.Length; indexAnimation++) { string babylonAnimationProperty = babylonAnimationProperties[indexAnimation]; BabylonAnimationKey key = new BabylonAnimationKey(); key.frame = currentFrame; switch (indexAnimation) { case 0: // scaling key.values = scaling.ToArray(); break; case 1: // rotationQuaternion key.values = rotationQuaternion.ToArray(); break; case 2: // position key.values = position.ToArray(); break; } keysPerProperty[babylonAnimationProperty].Add(key); } } // create animation for each property for (int indexAnimation = 0; indexAnimation < babylonAnimationProperties.Length; indexAnimation++) { string babylonAnimationProperty = babylonAnimationProperties[indexAnimation]; List <BabylonAnimationKey> keys = keysPerProperty[babylonAnimationProperty]; // Optimization OptimizeAnimations(keys, true); // Ensure animation has at least 2 frames if (keys.Count > 1) { var animationPresent = true; // Ensure animation has at least 2 non equal frames if (keys.Count == 2) { if (keys[0].values.IsEqualTo(keys[1].values)) { animationPresent = false; } } if (animationPresent) { // Create BabylonAnimation animations.Add(new BabylonAnimation() { dataType = indexAnimation == 1 ? (int)BabylonAnimation.DataType.Quaternion : (int)BabylonAnimation.DataType.Vector3, name = babylonAnimationProperty + " animation", framePerSecond = GetFPS(), loopBehavior = (int)BabylonAnimation.LoopBehavior.Cycle, property = babylonAnimationProperty, keys = keys.ToArray() }); } } } return(animations); }
/// <summary> /// Default space is transform /// </summary> /// <param name="mTransformationMatrix"></param> /// <returns></returns> public static float[] getTranslation(this MTransformationMatrix mTransformationMatrix) { MVector mVector = mTransformationMatrix.getTranslation(MSpace.Space.kTransform); return(mVector.toArray()); }