|
@@ -10,158 +10,219 @@ namespace Max2Babylon
|
|
|
partial class BabylonExporter
|
|
|
{
|
|
|
private int bonesCount;
|
|
|
- private void ExportMesh(IINode meshNode, BabylonScene babylonScene)
|
|
|
+ private void ExportMesh(IIGameScene scene, IIGameNode meshNode, BabylonScene babylonScene)
|
|
|
{
|
|
|
- if (meshNode.IsInstance())
|
|
|
+ if (meshNode.MaxNode.IsInstance())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (meshNode.GetBoolProperty("babylonjs_noexport"))
|
|
|
+ if (meshNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false))
|
|
|
+ if (!ExportHiddenObjects && meshNode.MaxNode.IsHidden(NodeHideFlags.None, false))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ var gameMesh = meshNode.IGameObject.AsGameMesh();
|
|
|
+ bool initialized = gameMesh.InitializeData; //needed, the property is in fact a method initializing the exporter that has wrongly been auto
|
|
|
+ // translated into a property because it has no parameters
|
|
|
+
|
|
|
var babylonMesh = new BabylonMesh();
|
|
|
- int vx1, vx2, vx3;
|
|
|
|
|
|
babylonMesh.name = meshNode.Name;
|
|
|
- babylonMesh.id = meshNode.GetGuid().ToString();
|
|
|
- if (meshNode.HasParent())
|
|
|
+ babylonMesh.id = meshNode.MaxNode.GetGuid().ToString();
|
|
|
+ if (meshNode.NodeParent != null)
|
|
|
{
|
|
|
- babylonMesh.parentId = meshNode.ParentNode.GetGuid().ToString();
|
|
|
+ babylonMesh.parentId = meshNode.NodeParent.MaxNode.GetGuid().ToString();
|
|
|
}
|
|
|
|
|
|
// Misc.
|
|
|
- babylonMesh.isVisible = meshNode.Renderable == 1;
|
|
|
- babylonMesh.pickable = meshNode.GetBoolProperty("babylonjs_checkpickable");
|
|
|
- babylonMesh.receiveShadows = meshNode.RcvShadows == 1;
|
|
|
- babylonMesh.showBoundingBox = meshNode.GetBoolProperty("babylonjs_showboundingbox");
|
|
|
- babylonMesh.showSubMeshesBoundingBox = meshNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
|
|
|
- babylonMesh.applyFog = meshNode.ApplyAtmospherics == 1;
|
|
|
- babylonMesh.alphaIndex = (int)meshNode.GetFloatProperty("babylonjs_alphaindex", 1000);
|
|
|
+ babylonMesh.isVisible = meshNode.MaxNode.Renderable == 1;
|
|
|
+ babylonMesh.pickable = meshNode.MaxNode.GetBoolProperty("babylonjs_checkpickable");
|
|
|
+ babylonMesh.receiveShadows = meshNode.MaxNode.RcvShadows == 1;
|
|
|
+ babylonMesh.showBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showboundingbox");
|
|
|
+ babylonMesh.showSubMeshesBoundingBox = meshNode.MaxNode.GetBoolProperty("babylonjs_showsubmeshesboundingbox");
|
|
|
+ babylonMesh.applyFog = meshNode.MaxNode.ApplyAtmospherics == 1;
|
|
|
+ babylonMesh.alphaIndex = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_alphaindex", 1000);
|
|
|
|
|
|
// Collisions
|
|
|
- babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions");
|
|
|
-
|
|
|
- // Skin
|
|
|
- var skin = GetSkinModifier(meshNode);
|
|
|
+ babylonMesh.checkCollisions = meshNode.MaxNode.GetBoolProperty("babylonjs_checkcollisions");
|
|
|
|
|
|
- if (skin != null)
|
|
|
+ bool isSkinned = gameMesh.IsObjectSkinned;
|
|
|
+ var skin = gameMesh.IGameSkin;
|
|
|
+ var unskinnedMesh = gameMesh;
|
|
|
+ IGMatrix skinInitPoseMatrix = Loader.Global.GMatrix.Create(Loader.Global.Matrix3.Create(true));
|
|
|
+ if (isSkinned)
|
|
|
{
|
|
|
+ //unskinnedMesh = skin.InitialPose;
|
|
|
+ bonesCount = skin.TotalSkinBoneCount;
|
|
|
+ skins.Add(skin);
|
|
|
+ skinnedNodes.Add(meshNode);
|
|
|
babylonMesh.skeletonId = skins.IndexOf(skin);
|
|
|
- bonesCount = skin.NumBones;
|
|
|
+ skin.GetInitSkinTM(skinInitPoseMatrix);
|
|
|
}
|
|
|
|
|
|
// Position / rotation / scaling
|
|
|
- var wm = Tools.ExtractCoordinates(meshNode, babylonMesh, exportQuaternionsInsteadOfEulers);
|
|
|
-
|
|
|
- if (wm.Parity)
|
|
|
{
|
|
|
- vx1 = 2;
|
|
|
- vx2 = 1;
|
|
|
- vx3 = 0;
|
|
|
+ //var localTM = unskinnedMesh.IGameObjectTM;
|
|
|
+ //var worldTM = meshNode.GetWorldTM(0);
|
|
|
+ var localTM = meshNode.GetObjectTM(0);
|
|
|
+
|
|
|
+ var meshTrans = localTM.Translation;
|
|
|
+ var meshRotation = localTM.Rotation;
|
|
|
+ var meshScale = localTM.Scaling;
|
|
|
+ babylonMesh.position = new float[] { meshTrans.X, meshTrans.Y, meshTrans.Z };
|
|
|
+ //float rotx = 0, roty = 0, rotz = 0;
|
|
|
+ //unsafe
|
|
|
+ //{
|
|
|
+ // meshRotation.GetEuler(new IntPtr(&rotx), new IntPtr(&roty), new IntPtr(&rotz));
|
|
|
+ //}
|
|
|
+ //babylonMesh.rotation = new float[] { rotx, roty, rotz };
|
|
|
+ babylonMesh.rotationQuaternion = new float[] { meshRotation.X, meshRotation.Y, meshRotation.Z, -meshRotation.W };
|
|
|
+ babylonMesh.scaling = new float[] { meshScale.X, meshScale.Y, meshScale.Z };
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- vx1 = 0;
|
|
|
- vx2 = 1;
|
|
|
- vx3 = 2;
|
|
|
- }
|
|
|
-
|
|
|
- // Pivot
|
|
|
- var pivotMatrix = Tools.Identity;
|
|
|
- pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
|
|
|
- Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
|
|
|
- Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
|
|
|
- babylonMesh.pivotMatrix = pivotMatrix.ToArray();
|
|
|
+ //// Pivot // something to do with GameMesh ?
|
|
|
+ //meshNode.GetObjectTM
|
|
|
+ //var pivotMatrix = Tools.Identity;
|
|
|
+ //pivotMatrix.PreTranslate(meshNode.ObjOffsetPos);
|
|
|
+ //Loader.Global.PreRotateMatrix(pivotMatrix, meshNode.ObjOffsetRot);
|
|
|
+ //Loader.Global.ApplyScaling(pivotMatrix, meshNode.ObjOffsetScale);
|
|
|
+ //babylonMesh.pivotMatrix = pivotMatrix.ToArray();
|
|
|
|
|
|
// Mesh
|
|
|
- var objectState = meshNode.EvalWorldState(0, false);
|
|
|
- var triObject = objectState.Obj.GetMesh();
|
|
|
- var mesh = triObject != null ? triObject.Mesh : null;
|
|
|
|
|
|
RaiseMessage(meshNode.Name, 1);
|
|
|
|
|
|
- if (mesh != null)
|
|
|
+ if (unskinnedMesh != null && unskinnedMesh.IGameType == Autodesk.Max.IGameObject.ObjectTypes.Mesh && unskinnedMesh.MaxMesh != null)
|
|
|
{
|
|
|
- mesh.BuildNormals();
|
|
|
|
|
|
- if (mesh.NumFaces < 1)
|
|
|
+
|
|
|
+ if (unskinnedMesh.NumberOfFaces < 1)
|
|
|
{
|
|
|
RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2);
|
|
|
}
|
|
|
|
|
|
- if (mesh.NumVerts < 3)
|
|
|
+ if (unskinnedMesh.NumberOfVerts < 3)
|
|
|
{
|
|
|
RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2);
|
|
|
}
|
|
|
|
|
|
- if (mesh.NumVerts >= 65536)
|
|
|
+ if (unskinnedMesh.NumberOfVerts >= 65536)
|
|
|
{
|
|
|
RaiseWarning(string.Format("Mesh {0} has tmore 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.", babylonMesh.name), 2);
|
|
|
}
|
|
|
|
|
|
// Material
|
|
|
- var mtl = meshNode.Mtl;
|
|
|
+ var mtl = meshNode.NodeMaterial;
|
|
|
var multiMatsCount = 1;
|
|
|
|
|
|
if (mtl != null)
|
|
|
{
|
|
|
- babylonMesh.materialId = mtl.GetGuid().ToString();
|
|
|
+ babylonMesh.materialId = mtl.MaxMaterial.GetGuid().ToString();
|
|
|
|
|
|
if (!referencedMaterials.Contains(mtl))
|
|
|
{
|
|
|
referencedMaterials.Add(mtl);
|
|
|
}
|
|
|
|
|
|
- multiMatsCount = Math.Max(mtl.NumSubMtls, 1);
|
|
|
+ multiMatsCount = Math.Max(mtl.SubMaterialCount, 1);
|
|
|
}
|
|
|
|
|
|
- babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever);
|
|
|
+ babylonMesh.visibility = meshNode.MaxNode.GetVisibility(0, Tools.Forever);
|
|
|
|
|
|
var vertices = new List<GlobalVertex>();
|
|
|
var indices = new List<int>();
|
|
|
- var matIDs = new List<int>();
|
|
|
+ var mappingChannels = unskinnedMesh.ActiveMapChannelNum;
|
|
|
+ bool hasUV = false;
|
|
|
+ bool hasUV2 = false;
|
|
|
+ for (int i = 0; i < mappingChannels.Count; ++i)
|
|
|
+ {
|
|
|
+ IntPtr indexer = new IntPtr(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;
|
|
|
|
|
|
- var hasUV = mesh.NumTVerts > 0;
|
|
|
- var hasUV2 = mesh.GetNumMapVerts(2) > 0;
|
|
|
- var hasColor = mesh.NumVertCol > 0;
|
|
|
- var hasAlpha = mesh.GetNumMapVerts(-2) > 0;
|
|
|
+ var optimizeVertices = meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices");
|
|
|
|
|
|
- var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices");
|
|
|
|
|
|
- // Skin
|
|
|
- IISkinContextData skinContext = null;
|
|
|
-
|
|
|
- if (skin != null)
|
|
|
- {
|
|
|
- skinContext = skin.GetContextInterface(meshNode);
|
|
|
- }
|
|
|
|
|
|
// Compute normals
|
|
|
- VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
|
|
|
+ // VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
|
|
|
List<GlobalVertex>[] verticesAlreadyExported = null;
|
|
|
|
|
|
if (optimizeVertices)
|
|
|
{
|
|
|
- verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts];
|
|
|
+ verticesAlreadyExported = new List<GlobalVertex>[unskinnedMesh.NumberOfVerts];
|
|
|
}
|
|
|
|
|
|
- for (var face = 0; face < mesh.NumFaces; face++)
|
|
|
+ var subMeshes = new List<BabylonSubMesh>();
|
|
|
+ var indexStart = 0;
|
|
|
+
|
|
|
+
|
|
|
+ for (int i = 0; i < multiMatsCount; ++i)
|
|
|
{
|
|
|
- indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
|
|
|
- indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
|
|
|
- indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, hasColor, hasAlpha, vnorms, verticesAlreadyExported, skinContext));
|
|
|
- matIDs.Add(mesh.Faces[face].MatID % multiMatsCount);
|
|
|
- CheckCancelled();
|
|
|
+ int materialId = meshNode.NodeMaterial.GetMaterialID(i);
|
|
|
+ ITab<IFaceEx> materialFaces = null;
|
|
|
+ var indexCount = 0;
|
|
|
+ var minVertexIndex = int.MaxValue;
|
|
|
+ var maxVertexIndex = int.MinValue;
|
|
|
+ var subMesh = new BabylonSubMesh();
|
|
|
+ subMesh.indexStart = indexStart;
|
|
|
+ subMesh.materialIndex = i;
|
|
|
+
|
|
|
+ if (multiMatsCount == 1)
|
|
|
+ {
|
|
|
+ for(int j = 0; j < unskinnedMesh.NumberOfFaces; ++j)
|
|
|
+ {
|
|
|
+ var face = unskinnedMesh.GetFace(j);
|
|
|
+ ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ materialFaces = unskinnedMesh.GetFacesFromMatID(materialId);
|
|
|
+ for (int j = 0; j < materialFaces.Count; ++j)
|
|
|
+ {
|
|
|
+ var faceIndexer = new IntPtr(j);
|
|
|
+ var face = materialFaces[faceIndexer];
|
|
|
+
|
|
|
+ Marshal.FreeHGlobal(faceIndexer);
|
|
|
+ ExtractFace(skin, unskinnedMesh, vertices, indices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, ref indexCount, ref minVertexIndex, ref maxVertexIndex, face);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (indexCount != 0)
|
|
|
+ {
|
|
|
+
|
|
|
+ subMesh.indexCount = indexCount;
|
|
|
+ subMesh.verticesStart = minVertexIndex;
|
|
|
+ subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
|
|
|
+
|
|
|
+ indexStart += indexCount;
|
|
|
+
|
|
|
+ subMeshes.Add(subMesh);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
if (vertices.Count >= 65536)
|
|
|
{
|
|
|
RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2);
|
|
@@ -175,15 +236,15 @@ namespace Max2Babylon
|
|
|
RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);
|
|
|
|
|
|
// Buffers
|
|
|
- babylonMesh.positions = vertices.SelectMany(v => v.Position.ToArraySwitched()).ToArray();
|
|
|
- babylonMesh.normals = vertices.SelectMany(v => v.Normal.ToArraySwitched()).ToArray();
|
|
|
+ babylonMesh.positions = vertices.SelectMany(v => new float[] { v.Position.X, v.Position.Y, v.Position.Z }).ToArray();
|
|
|
+ babylonMesh.normals = vertices.SelectMany(v => new float[] { v.Normal.X, v.Normal.Y, v.Normal.Z }).ToArray();
|
|
|
if (hasUV)
|
|
|
{
|
|
|
- babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray();
|
|
|
+ babylonMesh.uvs = vertices.SelectMany(v => new float[] { v.UV.X, 1 - v.UV.Y }).ToArray();
|
|
|
}
|
|
|
if (hasUV2)
|
|
|
{
|
|
|
- babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray();
|
|
|
+ babylonMesh.uvs2 = vertices.SelectMany(v => new float[] { v.UV2.X, 1 - v.UV2.Y }).ToArray();
|
|
|
}
|
|
|
|
|
|
if (skin != null)
|
|
@@ -198,89 +259,23 @@ namespace Max2Babylon
|
|
|
babylonMesh.hasVertexAlpha = hasAlpha;
|
|
|
}
|
|
|
|
|
|
- // Submeshes
|
|
|
- var sortedIndices = new List<int>();
|
|
|
- var subMeshes = new List<BabylonSubMesh>();
|
|
|
- var indexStart = 0;
|
|
|
- for (var index = 0; index < multiMatsCount; index++)
|
|
|
- {
|
|
|
- var subMesh = new BabylonSubMesh();
|
|
|
- var indexCount = 0;
|
|
|
- var minVertexIndex = int.MaxValue;
|
|
|
- var maxVertexIndex = int.MinValue;
|
|
|
-
|
|
|
- subMesh.indexStart = indexStart;
|
|
|
- subMesh.materialIndex = index;
|
|
|
-
|
|
|
- for (var face = 0; face < matIDs.Count; face++)
|
|
|
- {
|
|
|
- if (matIDs[face] == index)
|
|
|
- {
|
|
|
- var a = indices[3 * face];
|
|
|
- var b = indices[3 * face + 1];
|
|
|
- var c = indices[3 * face + 2];
|
|
|
-
|
|
|
- sortedIndices.Add(a);
|
|
|
- sortedIndices.Add(b);
|
|
|
- sortedIndices.Add(c);
|
|
|
- indexCount += 3;
|
|
|
-
|
|
|
- if (a < minVertexIndex)
|
|
|
- {
|
|
|
- minVertexIndex = a;
|
|
|
- }
|
|
|
-
|
|
|
- if (b < minVertexIndex)
|
|
|
- {
|
|
|
- minVertexIndex = b;
|
|
|
- }
|
|
|
-
|
|
|
- if (c < minVertexIndex)
|
|
|
- {
|
|
|
- minVertexIndex = c;
|
|
|
- }
|
|
|
-
|
|
|
- if (a > maxVertexIndex)
|
|
|
- {
|
|
|
- maxVertexIndex = a;
|
|
|
- }
|
|
|
-
|
|
|
- if (b > maxVertexIndex)
|
|
|
- {
|
|
|
- maxVertexIndex = b;
|
|
|
- }
|
|
|
-
|
|
|
- if (c > maxVertexIndex)
|
|
|
- {
|
|
|
- maxVertexIndex = c;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (indexCount != 0)
|
|
|
- {
|
|
|
-
|
|
|
- subMesh.indexCount = indexCount;
|
|
|
- subMesh.verticesStart = minVertexIndex;
|
|
|
- subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
|
|
|
|
|
|
- indexStart += indexCount;
|
|
|
|
|
|
- subMeshes.Add(subMesh);
|
|
|
- }
|
|
|
- CheckCancelled();
|
|
|
- }
|
|
|
babylonMesh.subMeshes = subMeshes.ToArray();
|
|
|
|
|
|
|
|
|
// Buffers - Indices
|
|
|
- babylonMesh.indices = sortedIndices.ToArray();
|
|
|
+ babylonMesh.indices = indices.ToArray();
|
|
|
|
|
|
- triObject.Dispose();
|
|
|
}
|
|
|
|
|
|
+ // handle instances and animations
|
|
|
+
|
|
|
+
|
|
|
// Instances
|
|
|
var tabs = Loader.Global.NodeTab.Create();
|
|
|
- Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode, tabs);
|
|
|
+
|
|
|
+ Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode.MaxNode, tabs);
|
|
|
var instances = new List<BabylonAbstractMesh>();
|
|
|
|
|
|
for (var index = 0; index < tabs.Count; index++)
|
|
@@ -290,18 +285,38 @@ namespace Max2Babylon
|
|
|
|
|
|
Marshal.FreeHGlobal(indexer);
|
|
|
|
|
|
- if (meshNode.GetGuid() == tab.GetGuid())
|
|
|
+ if (meshNode.MaxNode.GetGuid() == tab.GetGuid())
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var instanceGameNode = scene.GetIGameNode(tab);
|
|
|
+ if (instanceGameNode == null)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
tab.MarkAsInstance();
|
|
|
|
|
|
- var instance = new BabylonAbstractMesh {name = tab.Name};
|
|
|
+ var instance = new BabylonAbstractMesh { name = tab.Name };
|
|
|
+ {
|
|
|
+
|
|
|
+ var localTM = meshNode.GetObjectTM(0);
|
|
|
|
|
|
- Tools.ExtractCoordinates(tab, instance, exportQuaternionsInsteadOfEulers);
|
|
|
+ //var worldTM = meshNode.GetWorldTM(0);
|
|
|
+ //var objTM = meshNode.GetObjectTM(0);
|
|
|
+ var meshTrans = localTM.Translation;
|
|
|
+ var meshRotation = localTM.Rotation;
|
|
|
+ var meshScale = localTM.Scaling;
|
|
|
+ instance.position = new float[] { meshTrans.X, meshTrans.Y, meshTrans.Z };
|
|
|
+ float rotx = 0, roty = 0, rotz = 0;
|
|
|
+ unsafe
|
|
|
+ {
|
|
|
+ meshRotation.GetEuler(new IntPtr(&rotx), new IntPtr(&roty), new IntPtr(&rotz));
|
|
|
+ }
|
|
|
+ instance.rotation = new float[] { rotx, roty, rotz };
|
|
|
+ instance.scaling = new float[] { meshScale.X, meshScale.Y, meshScale.Z };
|
|
|
+ }
|
|
|
var instanceAnimations = new List<BabylonAnimation>();
|
|
|
- GenerateCoordinatesAnimations(tab, instanceAnimations);
|
|
|
+ GenerateCoordinatesAnimations(meshNode, instanceAnimations);
|
|
|
instance.animations = instanceAnimations.ToArray();
|
|
|
|
|
|
instances.Add(instance);
|
|
@@ -314,96 +329,163 @@ namespace Max2Babylon
|
|
|
GenerateCoordinatesAnimations(meshNode, animations);
|
|
|
|
|
|
|
|
|
- if (!ExportFloatController(meshNode.VisController, "visibility", animations))
|
|
|
+ if (!ExportFloatController(meshNode.MaxNode.VisController, "visibility", animations))
|
|
|
{
|
|
|
- ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) });
|
|
|
+ ExportFloatAnimation("visibility", animations, key => new[] { meshNode.MaxNode.GetVisibility(key, Tools.Forever) });
|
|
|
}
|
|
|
|
|
|
babylonMesh.animations = animations.ToArray();
|
|
|
|
|
|
- if (meshNode.GetBoolProperty("babylonjs_autoanimate", 1))
|
|
|
+ if (meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimate", 1))
|
|
|
{
|
|
|
babylonMesh.autoAnimate = true;
|
|
|
- babylonMesh.autoAnimateFrom = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_from");
|
|
|
- babylonMesh.autoAnimateTo = (int)meshNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
|
|
|
- babylonMesh.autoAnimateLoop = meshNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
|
|
|
+ babylonMesh.autoAnimateFrom = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_from");
|
|
|
+ babylonMesh.autoAnimateTo = (int)meshNode.MaxNode.GetFloatProperty("babylonjs_autoanimate_to", 100);
|
|
|
+ babylonMesh.autoAnimateLoop = meshNode.MaxNode.GetBoolProperty("babylonjs_autoanimateloop", 1);
|
|
|
}
|
|
|
|
|
|
babylonScene.MeshesList.Add(babylonMesh);
|
|
|
}
|
|
|
|
|
|
- public static void GenerateCoordinatesAnimations(IINode meshNode, List<BabylonAnimation> animations)
|
|
|
+ private void ExtractFace(IIGameSkin skin, IIGameMesh unskinnedMesh, List<GlobalVertex> vertices, List<int> indices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, ref int indexCount, ref int minVertexIndex, ref int maxVertexIndex, IFaceEx face)
|
|
|
{
|
|
|
- if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
|
|
|
+ var a = CreateGlobalVertex(unskinnedMesh, face, 0, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
|
|
|
+ var b = CreateGlobalVertex(unskinnedMesh, face, 2, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
|
|
|
+ var c = CreateGlobalVertex(unskinnedMesh, face, 1, vertices, hasUV, hasUV2, hasColor, hasAlpha, verticesAlreadyExported, skin);
|
|
|
+ indices.Add(a);
|
|
|
+ indices.Add(b);
|
|
|
+ indices.Add(c);
|
|
|
+
|
|
|
+ if (a < minVertexIndex)
|
|
|
+ {
|
|
|
+ minVertexIndex = a;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (b < minVertexIndex)
|
|
|
+ {
|
|
|
+ minVertexIndex = b;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (c < minVertexIndex)
|
|
|
{
|
|
|
+ minVertexIndex = c;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (a > maxVertexIndex)
|
|
|
+ {
|
|
|
+ maxVertexIndex = a;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (b > maxVertexIndex)
|
|
|
+ {
|
|
|
+ maxVertexIndex = b;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (c > maxVertexIndex)
|
|
|
+ {
|
|
|
+ maxVertexIndex = c;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ indexCount += 3;
|
|
|
+ CheckCancelled();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void GenerateCoordinatesAnimations(IIGameNode meshNode, List<BabylonAnimation> animations)
|
|
|
+ {
|
|
|
+ //if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
|
|
|
+ //{
|
|
|
ExportVector3Animation("position", animations, key =>
|
|
|
{
|
|
|
- var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
- return worldMatrix.Trans.ToArraySwitched();
|
|
|
+ var worldMatrix = meshNode.GetObjectTM(key);
|
|
|
+ var trans = worldMatrix.Translation;
|
|
|
+ return new float[] { trans.X, trans.Y, trans.Z };
|
|
|
});
|
|
|
- }
|
|
|
+ //}
|
|
|
|
|
|
- if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
|
|
|
- {
|
|
|
+
|
|
|
+ //if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
|
|
|
+ //{
|
|
|
ExportQuaternionAnimation("rotationQuaternion", animations, key =>
|
|
|
{
|
|
|
- var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
+ var worldMatrix = meshNode.GetObjectTM(key);
|
|
|
|
|
|
- var affineParts = Loader.Global.AffineParts.Create();
|
|
|
- Loader.Global.DecompAffine(worldMatrix, affineParts);
|
|
|
|
|
|
- return affineParts.Q.ToArray();
|
|
|
+
|
|
|
+ var rot = worldMatrix.Rotation;
|
|
|
+ return new float[] { rot.X, rot.Y, rot.Z, -rot.W };
|
|
|
});
|
|
|
- }
|
|
|
+ //}
|
|
|
|
|
|
- if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
|
|
|
- {
|
|
|
+
|
|
|
+ //if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
|
|
|
+ //{
|
|
|
ExportVector3Animation("scaling", animations, key =>
|
|
|
{
|
|
|
- var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
+ var worldMatrix = meshNode.GetObjectTM(key);
|
|
|
+ var scale = worldMatrix.Scaling;
|
|
|
|
|
|
- var affineParts = Loader.Global.AffineParts.Create();
|
|
|
- Loader.Global.DecompAffine(worldMatrix, affineParts);
|
|
|
-
|
|
|
- return affineParts.K.ToArraySwitched();
|
|
|
+ return new float[] { scale.X, scale.Y, scale.Z };
|
|
|
});
|
|
|
- }
|
|
|
+ // }
|
|
|
}
|
|
|
|
|
|
- int CreateGlobalVertex(IMesh mesh, int face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, VNormal[] vnorms, List<GlobalVertex>[] verticesAlreadyExported, IISkinContextData skinContextData)
|
|
|
+
|
|
|
+ int CreateGlobalVertex(IIGameMesh mesh, IFaceEx face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, bool hasColor, bool hasAlpha, List<GlobalVertex>[] verticesAlreadyExported, IIGameSkin skin)
|
|
|
{
|
|
|
- var faceObject = mesh.Faces[face];
|
|
|
- var vertexIndex = (int)faceObject.V[facePart];
|
|
|
+ var vertexIndex = (int)face.Vert[facePart];
|
|
|
|
|
|
var vertex = new GlobalVertex
|
|
|
{
|
|
|
BaseIndex = vertexIndex,
|
|
|
- Position = mesh.Verts[vertexIndex],
|
|
|
- Normal = vnorms[vertexIndex].GetNormal(verticesAlreadyExported != null ? 1 : faceObject.SmGroup)
|
|
|
+ Position = mesh.GetVertex(vertexIndex, true),
|
|
|
+ Normal = mesh.GetNormal((int)face.Norm[facePart], true) //vnorms[vertexIndex].GetNormal(verticesAlreadyExported != null ? 1 : faceObject.SmGroup)
|
|
|
};
|
|
|
|
|
|
if (hasUV)
|
|
|
{
|
|
|
- var tvertexIndex = (int)mesh.TvFace[face].T[facePart];
|
|
|
- vertex.UV = Loader.Global.Point2.Create(mesh.TVerts[tvertexIndex].X, mesh.TVerts[tvertexIndex].Y);
|
|
|
+ int[] indices = new int[3];
|
|
|
+ unsafe
|
|
|
+ {
|
|
|
+ fixed (int* indicesPtr = indices)
|
|
|
+ {
|
|
|
+ mesh.GetMapFaceIndex(1, face.MeshFaceIndex, new IntPtr(indicesPtr));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var texCoord = mesh.GetMapVertex(1, indices[facePart]);
|
|
|
+ vertex.UV = Loader.Global.Point2.Create(texCoord.X, -texCoord.Y);
|
|
|
}
|
|
|
|
|
|
if (hasUV2)
|
|
|
{
|
|
|
- var tvertexIndex = (int)mesh.MapFaces(2)[face].T[facePart];
|
|
|
- vertex.UV2 = Loader.Global.Point2.Create(mesh.MapVerts(2)[tvertexIndex].X, mesh.MapVerts(2)[tvertexIndex].Y);
|
|
|
+ int[] indices = new int[3];
|
|
|
+ unsafe
|
|
|
+ {
|
|
|
+ fixed (int* indicesPtr = indices)
|
|
|
+ {
|
|
|
+ mesh.GetMapFaceIndex(2, face.MeshFaceIndex, new IntPtr(indicesPtr));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var texCoord = mesh.GetMapVertex(2, indices[facePart]);
|
|
|
+ vertex.UV2 = Loader.Global.Point2.Create(texCoord.X, -texCoord.Y);
|
|
|
}
|
|
|
|
|
|
if (hasColor)
|
|
|
{
|
|
|
- var vertexColorIndex = (int)mesh.VcFace[face].T[facePart];
|
|
|
- var vertexColor = mesh.VertCol[vertexColorIndex];
|
|
|
- var alpha = hasAlpha ? mesh.MapVerts(-2)[vertexColorIndex].X : 1;
|
|
|
+ var vertexColorIndex = (int)face.Color[facePart];
|
|
|
+ var vertexColor = mesh.GetColorVertex(vertexColorIndex);
|
|
|
+ float alpha = 1;
|
|
|
+ if (hasAlpha)
|
|
|
+ {
|
|
|
+ IPoint3 p = Loader.Global.Point3.Create();
|
|
|
+ mesh.GetMapFaceIndex(-2, face.MeshFaceIndex, p.GetNativeHandle());
|
|
|
+ alpha = p.X;
|
|
|
+ }
|
|
|
|
|
|
- vertex.Color = new float[] { vertexColor.X, vertexColor.Y, vertexColor.Z, alpha};
|
|
|
+ vertex.Color = new float[] { vertexColor.X, vertexColor.Y, vertexColor.Z, alpha };
|
|
|
}
|
|
|
|
|
|
- if (skinContextData != null)
|
|
|
+ if (skin != null)
|
|
|
{
|
|
|
float weight0 = 0;
|
|
|
float weight1 = 0;
|
|
@@ -412,29 +494,29 @@ namespace Max2Babylon
|
|
|
int bone1 = bonesCount;
|
|
|
int bone2 = bonesCount;
|
|
|
int bone3 = bonesCount;
|
|
|
- int nbBones = skinContextData.GetNumAssignedBones(vertexIndex);
|
|
|
+ int nbBones = skin.GetNumberOfBones(vertexIndex);
|
|
|
|
|
|
if (nbBones > 0)
|
|
|
{
|
|
|
- bone0 = skinContextData.GetAssignedBone(vertexIndex, 0);
|
|
|
- weight0 = skinContextData.GetBoneWeight(vertexIndex, 0);
|
|
|
+ bone0 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 0), false);
|
|
|
+ weight0 = skin.GetWeight(vertexIndex, 0);
|
|
|
}
|
|
|
|
|
|
if (nbBones > 1)
|
|
|
{
|
|
|
- bone1 = skinContextData.GetAssignedBone(vertexIndex, 1);
|
|
|
- weight1 = skinContextData.GetBoneWeight(vertexIndex, 1);
|
|
|
+ bone1 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 1), false);
|
|
|
+ weight1 = skin.GetWeight(vertexIndex, 1);
|
|
|
}
|
|
|
|
|
|
if (nbBones > 2)
|
|
|
{
|
|
|
- bone2 = skinContextData.GetAssignedBone(vertexIndex, 2);
|
|
|
- weight2 = skinContextData.GetBoneWeight(vertexIndex, 2);
|
|
|
+ bone2 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 2), false);
|
|
|
+ weight2 = skin.GetWeight(vertexIndex, 2);
|
|
|
}
|
|
|
|
|
|
if (nbBones > 3)
|
|
|
{
|
|
|
- bone3 = skinContextData.GetAssignedBone(vertexIndex, 3);
|
|
|
+ bone3 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 3), false);
|
|
|
}
|
|
|
|
|
|
if (nbBones == 0)
|