|
@@ -10,156 +10,234 @@ namespace Max2Babylon
|
|
partial class BabylonExporter
|
|
partial class BabylonExporter
|
|
{
|
|
{
|
|
private int bonesCount;
|
|
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;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (meshNode.GetBoolProperty("babylonjs_noexport"))
|
|
|
|
|
|
+ if (meshNode.MaxNode.GetBoolProperty("babylonjs_noexport"))
|
|
{
|
|
{
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false))
|
|
|
|
|
|
+ if (!ExportHiddenObjects && meshNode.MaxNode.IsHidden(NodeHideFlags.None, false))
|
|
{
|
|
{
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ var gameMesh = meshNode.IGameObject.AsGameMesh();
|
|
|
|
+ bool initialized = gameMesh.InitializeData;
|
|
|
|
+
|
|
var babylonMesh = new BabylonMesh();
|
|
var babylonMesh = new BabylonMesh();
|
|
- int vx1, vx2, vx3;
|
|
|
|
|
|
|
|
babylonMesh.name = meshNode.Name;
|
|
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.
|
|
// 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.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");
|
|
|
|
|
|
// Collisions
|
|
// 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;
|
|
|
|
+ if (isSkinned)
|
|
{
|
|
{
|
|
|
|
+ unskinnedMesh = skin.InitialPose;
|
|
|
|
+ bonesCount = skin.TotalSkinBoneCount;
|
|
|
|
+ skins.Add(skin);
|
|
babylonMesh.skeletonId = skins.IndexOf(skin);
|
|
babylonMesh.skeletonId = skins.IndexOf(skin);
|
|
- bonesCount = skin.NumBones;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- // Position / rotation / scaling
|
|
|
|
- var wm = Tools.ExtractCoordinates(meshNode, babylonMesh, exportQuaternionsInsteadOfEulers);
|
|
|
|
|
|
|
|
- if (wm.Parity)
|
|
|
|
- {
|
|
|
|
- vx1 = 2;
|
|
|
|
- vx2 = 1;
|
|
|
|
- vx3 = 0;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
|
|
+ // Position / rotation / scaling
|
|
{
|
|
{
|
|
- vx1 = 0;
|
|
|
|
- vx2 = 1;
|
|
|
|
- vx3 = 2;
|
|
|
|
|
|
+ var localTM = meshNode.GetLocalTM(0);
|
|
|
|
+ //var worldTM = meshNode.GetWorldTM(0);
|
|
|
|
+ //var objTM = 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 };
|
|
}
|
|
}
|
|
-
|
|
|
|
- // 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
|
|
// Mesh
|
|
- var objectState = meshNode.EvalWorldState(0, false);
|
|
|
|
- var triObject = objectState.Obj.GetMesh();
|
|
|
|
- var mesh = triObject != null ? triObject.Mesh : null;
|
|
|
|
|
|
+
|
|
|
|
|
|
RaiseMessage(meshNode.Name, 1);
|
|
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);
|
|
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);
|
|
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);
|
|
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
|
|
// Material
|
|
- var mtl = meshNode.Mtl;
|
|
|
|
|
|
+ var mtl = meshNode.NodeMaterial;
|
|
var multiMatsCount = 1;
|
|
var multiMatsCount = 1;
|
|
|
|
|
|
if (mtl != null)
|
|
if (mtl != null)
|
|
{
|
|
{
|
|
- babylonMesh.materialId = mtl.GetGuid().ToString();
|
|
|
|
|
|
+ babylonMesh.materialId = mtl.MaxMaterial.GetGuid().ToString();
|
|
|
|
|
|
if (!referencedMaterials.Contains(mtl))
|
|
if (!referencedMaterials.Contains(mtl))
|
|
{
|
|
{
|
|
referencedMaterials.Add(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 vertices = new List<GlobalVertex>();
|
|
var indices = new List<int>();
|
|
var indices = new List<int>();
|
|
- var matIDs = new List<int>();
|
|
|
|
|
|
|
|
- var hasUV = mesh.NumTVerts > 0;
|
|
|
|
- var hasUV2 = mesh.GetNumMapVerts(2) > 0;
|
|
|
|
- var hasColor = mesh.NumVertCol > 0;
|
|
|
|
- var hasAlpha = mesh.GetNumMapVerts(-2) > 0;
|
|
|
|
|
|
+ var hasUV = unskinnedMesh.NumberOfTexVerts > 0;
|
|
|
|
+ var hasUV2 = unskinnedMesh.GetNumberOfMapVerts(2) > 0;
|
|
|
|
+ var hasColor = unskinnedMesh.NumberOfColorVerts > 0;
|
|
|
|
+ var hasAlpha = unskinnedMesh.GetNumberOfMapVerts(-2) > 0;
|
|
|
|
|
|
- var optimizeVertices = meshNode.GetBoolProperty("babylonjs_optimizevertices");
|
|
|
|
|
|
+ var optimizeVertices = meshNode.MaxNode.GetBoolProperty("babylonjs_optimizevertices");
|
|
|
|
|
|
- // Skin
|
|
|
|
- IISkinContextData skinContext = null;
|
|
|
|
-
|
|
|
|
- if (skin != null)
|
|
|
|
- {
|
|
|
|
- skinContext = skin.GetContextInterface(meshNode);
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
|
|
// Compute normals
|
|
// Compute normals
|
|
- VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
|
|
|
|
|
|
+ // VNormal[] vnorms = Tools.ComputeNormals(mesh, optimizeVertices);
|
|
List<GlobalVertex>[] verticesAlreadyExported = null;
|
|
List<GlobalVertex>[] verticesAlreadyExported = null;
|
|
|
|
|
|
if (optimizeVertices)
|
|
if (optimizeVertices)
|
|
{
|
|
{
|
|
- verticesAlreadyExported = new List<GlobalVertex>[mesh.NumVerts];
|
|
|
|
|
|
+ verticesAlreadyExported = new List<GlobalVertex>[unskinnedMesh.NumberOfVerts];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var subMeshes = new List<BabylonSubMesh>();
|
|
|
|
+ var indexStart = 0;
|
|
|
|
+
|
|
|
|
+ List<Guid> orderedSubMeshes = new List<Guid>();
|
|
|
|
+ for(int i=0;i< meshNode.NodeMaterial.SubMaterialCount; ++i)
|
|
|
|
+ {
|
|
|
|
+ orderedSubMeshes.Add(meshNode.NodeMaterial.GetSubMaterial(i).MaxMaterial.GetGuid());
|
|
}
|
|
}
|
|
|
|
|
|
- for (var face = 0; face < mesh.NumFaces; face++)
|
|
|
|
|
|
+ var materialIds = unskinnedMesh.ActiveMatIDs;
|
|
|
|
+ for(int i=0; i< materialIds.Count; ++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();
|
|
|
|
|
|
+ var materialIndexer = new IntPtr(i);
|
|
|
|
+ int materialId = materialIds[materialIndexer];
|
|
|
|
+ Marshal.FreeHGlobal(materialIndexer);
|
|
|
|
+ var materialFaces = unskinnedMesh.GetFacesFromMatID(materialId);
|
|
|
|
+
|
|
|
|
+ var indexCount = 0;
|
|
|
|
+ var minVertexIndex = int.MaxValue;
|
|
|
|
+ var maxVertexIndex = int.MinValue;
|
|
|
|
+ var subMesh = new BabylonSubMesh();
|
|
|
|
+ subMesh.indexStart = indexStart;
|
|
|
|
+ subMesh.materialIndex = materialId;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for (int j= 0; j<materialFaces.Count; ++j)
|
|
|
|
+ {
|
|
|
|
+ var faceIndexer = new IntPtr(j);
|
|
|
|
+ var face = materialFaces[faceIndexer];
|
|
|
|
+
|
|
|
|
+ Marshal.FreeHGlobal(faceIndexer);
|
|
|
|
+ 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();
|
|
|
|
+ }
|
|
|
|
+ if (indexCount != 0)
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ subMesh.indexCount = indexCount;
|
|
|
|
+ subMesh.verticesStart = minVertexIndex;
|
|
|
|
+ subMesh.verticesCount = maxVertexIndex - minVertexIndex + 1;
|
|
|
|
+
|
|
|
|
+ indexStart += indexCount;
|
|
|
|
+
|
|
|
|
+ subMeshes.Add(subMesh);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
if (vertices.Count >= 65536)
|
|
if (vertices.Count >= 65536)
|
|
{
|
|
{
|
|
RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2);
|
|
RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2);
|
|
@@ -173,15 +251,15 @@ namespace Max2Babylon
|
|
RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);
|
|
RaiseMessage(string.Format("{0} vertices, {1} faces", vertices.Count, indices.Count / 3), 2);
|
|
|
|
|
|
// Buffers
|
|
// 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)
|
|
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)
|
|
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)
|
|
if (skin != null)
|
|
@@ -196,89 +274,23 @@ namespace Max2Babylon
|
|
babylonMesh.hasVertexAlpha = hasAlpha;
|
|
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();
|
|
babylonMesh.subMeshes = subMeshes.ToArray();
|
|
|
|
|
|
|
|
|
|
// Buffers - Indices
|
|
// Buffers - Indices
|
|
- babylonMesh.indices = sortedIndices.ToArray();
|
|
|
|
|
|
+ babylonMesh.indices = indices.ToArray();
|
|
|
|
|
|
- triObject.Dispose();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // handle instances and animations
|
|
|
|
+
|
|
|
|
+
|
|
// Instances
|
|
// Instances
|
|
var tabs = Loader.Global.NodeTab.Create();
|
|
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>();
|
|
var instances = new List<BabylonAbstractMesh>();
|
|
|
|
|
|
for (var index = 0; index < tabs.Count; index++)
|
|
for (var index = 0; index < tabs.Count; index++)
|
|
@@ -288,19 +300,38 @@ namespace Max2Babylon
|
|
|
|
|
|
Marshal.FreeHGlobal(indexer);
|
|
Marshal.FreeHGlobal(indexer);
|
|
|
|
|
|
- if (meshNode.GetGuid() == tab.GetGuid())
|
|
|
|
|
|
+ if (meshNode.MaxNode.GetGuid() == tab.GetGuid())
|
|
|
|
+ {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ var instanceGameNode = scene.GetIGameNode(tab);
|
|
|
|
+ if(instanceGameNode == null)
|
|
{
|
|
{
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
-
|
|
|
|
tab.MarkAsInstance();
|
|
tab.MarkAsInstance();
|
|
|
|
|
|
- var instance = new BabylonAbstractMesh {name = tab.Name};
|
|
|
|
-
|
|
|
|
- Tools.ExtractCoordinates(tab, instance, exportQuaternionsInsteadOfEulers);
|
|
|
|
- var instanceAnimations = new List<BabylonAnimation>();
|
|
|
|
- GenerateCoordinatesAnimations(tab, instanceAnimations);
|
|
|
|
- instance.animations = instanceAnimations.ToArray();
|
|
|
|
|
|
+ var instance = new BabylonAbstractMesh { name = tab.Name };
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ var localTM = instanceGameNode.GetLocalTM(0);
|
|
|
|
+ //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);
|
|
|
|
+ //instance.animations = instanceAnimations.ToArray();
|
|
|
|
|
|
instances.Add(instance);
|
|
instances.Add(instance);
|
|
}
|
|
}
|
|
@@ -308,100 +339,169 @@ namespace Max2Babylon
|
|
babylonMesh.instances = instances.ToArray();
|
|
babylonMesh.instances = instances.ToArray();
|
|
|
|
|
|
// Animations
|
|
// Animations
|
|
- var animations = new List<BabylonAnimation>();
|
|
|
|
- GenerateCoordinatesAnimations(meshNode, animations);
|
|
|
|
-
|
|
|
|
|
|
+ //var animations = new List<BabylonAnimation>();
|
|
|
|
+ //GenerateCoordinatesAnimations(meshNode, animations);
|
|
|
|
|
|
- if (!ExportFloatController(meshNode.VisController, "visibility", animations))
|
|
|
|
- {
|
|
|
|
- ExportFloatAnimation("visibility", animations, key => new[] { meshNode.GetVisibility(key, Tools.Forever) });
|
|
|
|
- }
|
|
|
|
|
|
|
|
- babylonMesh.animations = animations.ToArray();
|
|
|
|
|
|
+ //if (!ExportFloatController(meshNode.VisController, "visibility", animations))
|
|
|
|
+ //{
|
|
|
|
+ // ExportFloatAnimation("visibility", animations, key => new[] { meshNode.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.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);
|
|
babylonScene.MeshesList.Add(babylonMesh);
|
|
}
|
|
}
|
|
|
|
|
|
- public static void GenerateCoordinatesAnimations(IINode 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();
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
|
|
|
|
- {
|
|
|
|
- ExportQuaternionAnimation("rotationQuaternion", animations, key =>
|
|
|
|
- {
|
|
|
|
- var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
|
-
|
|
|
|
- var affineParts = Loader.Global.AffineParts.Create();
|
|
|
|
- Loader.Global.DecompAffine(worldMatrix, affineParts);
|
|
|
|
-
|
|
|
|
- return affineParts.Q.ToArray();
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
|
|
|
|
- {
|
|
|
|
- ExportVector3Animation("scaling", animations, key =>
|
|
|
|
- {
|
|
|
|
- var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
|
-
|
|
|
|
- var affineParts = Loader.Global.AffineParts.Create();
|
|
|
|
- Loader.Global.DecompAffine(worldMatrix, affineParts);
|
|
|
|
-
|
|
|
|
- return affineParts.K.ToArraySwitched();
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- 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)
|
|
|
|
|
|
+ //public static void GenerateCoordinatesAnimations(IIGameNode meshNode, List<BabylonAnimation> animations)
|
|
|
|
+ //{
|
|
|
|
+ // var control = meshNode.IGameControl;
|
|
|
|
+ // if (control.IsAnimated(IGameControlType.Tm))
|
|
|
|
+ // {
|
|
|
|
+ // // combined tm anim
|
|
|
|
+ // ExportTMAnimation(control, animations);
|
|
|
|
+ // }
|
|
|
|
+ // else
|
|
|
|
+ // {
|
|
|
|
+ // if (control.IsAnimated(IGameControlType.Pos))
|
|
|
|
+ // {
|
|
|
|
+ // ExportPosAnimation(control, animations);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // //if (!ExportVector3Controller(meshNode.TMController.PositionController, "position", animations))
|
|
|
|
+ // //{
|
|
|
|
+ // // ExportVector3Animation("position", animations, key =>
|
|
|
|
+ // // {
|
|
|
|
+ // // var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
|
+ // // return worldMatrix.Trans.ToArraySwitched();
|
|
|
|
+ // // });
|
|
|
|
+ // //}
|
|
|
|
+
|
|
|
|
+ // //if (!ExportQuaternionController(meshNode.TMController.RotationController, "rotationQuaternion", animations))
|
|
|
|
+ // //{
|
|
|
|
+ // // ExportQuaternionAnimation("rotationQuaternion", animations, key =>
|
|
|
|
+ // // {
|
|
|
|
+ // // var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
|
+
|
|
|
|
+ // // var affineParts = Loader.Global.AffineParts.Create();
|
|
|
|
+ // // Loader.Global.DecompAffine(worldMatrix, affineParts);
|
|
|
|
+
|
|
|
|
+ // // return affineParts.Q.ToArray();
|
|
|
|
+ // // });
|
|
|
|
+ // //}
|
|
|
|
+
|
|
|
|
+ // //if (!ExportVector3Controller(meshNode.TMController.ScaleController, "scaling", animations))
|
|
|
|
+ // //{
|
|
|
|
+ // // ExportVector3Animation("scaling", animations, key =>
|
|
|
|
+ // // {
|
|
|
|
+ // // var worldMatrix = meshNode.GetWorldMatrix(key, meshNode.HasParent());
|
|
|
|
+
|
|
|
|
+ // // var affineParts = Loader.Global.AffineParts.Create();
|
|
|
|
+ // // Loader.Global.DecompAffine(worldMatrix, affineParts);
|
|
|
|
+
|
|
|
|
+ // // return affineParts.K.ToArraySwitched();
|
|
|
|
+ // // });
|
|
|
|
+ // //}
|
|
|
|
+ //}
|
|
|
|
+
|
|
|
|
+ //private static void ExportPosAnimation(IIGameControl control, List<BabylonAnimation> animations)
|
|
|
|
+ //{
|
|
|
|
+ // ITab<IIGameKey> keys = Loader.Global.Tab.Create<IIGameKey>();
|
|
|
|
+ // if(control.GetLinearKeys(keys, IGameControlType.Pos))
|
|
|
|
+ // {
|
|
|
|
+ // if(keys.Count != 0)
|
|
|
|
+ // {
|
|
|
|
+ // // todo
|
|
|
|
+
|
|
|
|
+ // return;
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // // full sampling
|
|
|
|
+ // if(control.GetFullSampledKeys(keys, Loader.Global.FrameRate, IGameControlType.Pos, false))
|
|
|
|
+ // {
|
|
|
|
+ // if(keys.Count != 0)
|
|
|
|
+ // {
|
|
|
|
+ // List<BabylonAnimationKey> babKeys = new List<BabylonAnimationKey>();
|
|
|
|
+
|
|
|
|
+ // for(int i = 0; i < keys.Count; ++i)
|
|
|
|
+ // {
|
|
|
|
+ // var keyIndexer = new IntPtr(i);
|
|
|
|
+ // var key = keys[keyIndexer];
|
|
|
|
+ // babKeys.Add(new BabylonAnimationKey {
|
|
|
|
+ // frame = key.T /Ticks,
|
|
|
|
+ // values = new float[] { key.SampleKey.Pval.X, key.SampleKey.Pval.Y, key.SampleKey.Pval.Z }
|
|
|
|
+ // });
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // var babylonAnimation = new BabylonAnimation
|
|
|
|
+ // {
|
|
|
|
+ // dataType = BabylonAnimation.DataType.Vector3,
|
|
|
|
+ // name = "position animation",
|
|
|
|
+ // keys = babKeys.ToArray(),
|
|
|
|
+ // framePerSecond = Loader.Global.FrameRate,
|
|
|
|
+ // loopBehavior = BabylonAnimation.LoopBehavior.Cycle,
|
|
|
|
+ // property = "position",
|
|
|
|
+
|
|
|
|
+ // };
|
|
|
|
+ // animations.Add(babylonAnimation);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ //}
|
|
|
|
+
|
|
|
|
+ //private static void ExportTMAnimation(IIGameControl control, List<BabylonAnimation> animations)
|
|
|
|
+ //{
|
|
|
|
+
|
|
|
|
+ //}
|
|
|
|
+
|
|
|
|
+ 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
|
|
var vertex = new GlobalVertex
|
|
{
|
|
{
|
|
BaseIndex = vertexIndex,
|
|
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)
|
|
if (hasUV)
|
|
{
|
|
{
|
|
- var tvertexIndex = (int)mesh.TvFace[face].T[facePart];
|
|
|
|
- vertex.UV = Loader.Global.Point2.Create(mesh.TVerts[tvertexIndex].X, mesh.TVerts[tvertexIndex].Y);
|
|
|
|
|
|
+ var tvertexIndex = (int)face.TexCoord[facePart];
|
|
|
|
+ vertex.UV = mesh.GetTexVertex(tvertexIndex);
|
|
}
|
|
}
|
|
|
|
|
|
if (hasUV2)
|
|
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);
|
|
|
|
|
|
+ IPoint3 p = Loader.Global.Point3.Create();
|
|
|
|
+ var tvertexIndex = mesh.GetMapFaceIndex(2, face.MeshFaceIndex, p.GetNativeHandle());
|
|
|
|
+ vertex.UV2 = Loader.Global.Point2.Create(p.X, p.Y);
|
|
}
|
|
}
|
|
|
|
|
|
if (hasColor)
|
|
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 weight0 = 0;
|
|
float weight1 = 0;
|
|
float weight1 = 0;
|
|
@@ -410,29 +510,29 @@ namespace Max2Babylon
|
|
int bone1 = bonesCount;
|
|
int bone1 = bonesCount;
|
|
int bone2 = bonesCount;
|
|
int bone2 = bonesCount;
|
|
int bone3 = bonesCount;
|
|
int bone3 = bonesCount;
|
|
- int nbBones = skinContextData.GetNumAssignedBones(vertexIndex);
|
|
|
|
|
|
+ int nbBones = skin.GetNumberOfBones(vertexIndex);
|
|
|
|
|
|
if (nbBones > 0)
|
|
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)
|
|
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)
|
|
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)
|
|
if (nbBones > 3)
|
|
{
|
|
{
|
|
- bone3 = skinContextData.GetAssignedBone(vertexIndex, 3);
|
|
|
|
|
|
+ bone3 = skin.GetBoneIndex(skin.GetBone(vertexIndex, 3), false);
|
|
}
|
|
}
|
|
|
|
|
|
if (nbBones == 0)
|
|
if (nbBones == 0)
|