public static bool Export_To(string _filepath) { List <IINode> nodes = GetSelection(); foreach (IINode _node in nodes) { IIDerivedObject _gObject = (IIDerivedObject)_node.ObjectRef; IClass_ID classID = maxGlobal.Class_ID.Create((uint)BuiltInClassIDA.TRIOBJ_CLASS_ID, 0); ITriObject _mObject = (ITriObject)_gObject.ObjRef.ConvertToType(0, classID); IMesh _mMesh = _mObject.Mesh; _mMesh.BuildNormals(); IIDerivedObject theObj = (IIDerivedObject)_node.ObjectRef; for (int m = 0; m < theObj.Modifiers.Count; m++) { IModifier theModifier = theObj.GetModifier(m); if (theModifier.ClassName == "Skin") { IISkin _skin = (IISkin)theModifier.GetInterface((InterfaceID)(0x00010000)); IISkinContextData _skinContext = _skin.GetContextInterface(_node); ComputeVertexData(_mMesh, _skinContext, semantic, _filepath); } } } return(true); }
public static void ComputeVertexData(IMesh _mMesh, IISkinContextData _skin, Semantic _semantic, string _filepath) { Dictionary <int, VertexUndivided> verticesFullData = new Dictionary <int, VertexUndivided>(); List <FaceData> facesFullData = new List <FaceData>(); List <List <VertexDivided> > verticesParsedData = new List <List <VertexDivided> >(); IList <IFace> faces = _mMesh.Faces; IList <ITVFace> Tfaces = _mMesh.TvFace; IList <IPoint3> vertices = _mMesh.Verts; IList <IPoint3> Tvertices = _mMesh.TVerts; /* * foreach (IPoint3 _v in vertices) * { * float temp = _v.Y; * _v.Y = -_v.Z; * _v.Z = temp; * } */ for (int _fID = 0; _fID < faces.Count; _fID++) { FaceData _face = new FaceData((int)faces[_fID].SmGroup); // vectors are inverted to make up for max being clockwise Vector3 A_B = vertices[(int)faces[_fID].GetVert(1)].convertToVector3() - vertices[(int)faces[_fID].GetVert(0)].convertToVector3(); Vector3 A_C = vertices[(int)faces[_fID].GetVert(2)].convertToVector3() - vertices[(int)faces[_fID].GetVert(0)].convertToVector3(); Vector3 U = Tvertices[(int)Tfaces[_fID].GetTVert(1)].convertToVector3() - Tvertices[(int)Tfaces[_fID].GetTVert(0)].convertToVector3(); Vector3 V = Tvertices[(int)Tfaces[_fID].GetTVert(2)].convertToVector3() - Tvertices[(int)Tfaces[_fID].GetTVert(0)].convertToVector3(); Vector3 normUnsure = Vector3.Cross(A_B, A_C); normUnsure.Normalize(); float area = U.X * V.Y - U.Y * V.X; int sign = area < 0 ? -1 : 1; Vector3 tangent = new Vector3(0, 0, 1); tangent.X = A_B.X * V.Y - U.Y * A_C.X; tangent.Y = A_B.Y * V.Y - U.Y * A_C.Y; tangent.Z = A_B.Z * V.Y - U.Y * A_C.Z; tangent.Normalize(); tangent *= sign; for (int i = 0; i < 3; i++) { _face.vertices.Add((int)faces[_fID].GetVert(i)); if (verticesFullData.ContainsKey((int)faces[_fID].GetVert(i))) { VertexUndivided _v = verticesFullData[(int)faces[_fID].GetVert(i)]; _v.faceInfo.Add(new PerFaceInfo(_fID, (int)faces[_fID].SmGroup, (Tvertices[(int)Tfaces[_fID].GetTVert(i)]).convertToVector2(), normUnsure, tangent)); } else { VertexUndivided _v = new VertexUndivided(); _v.ID = faces[_fID].GetVert(i); int nbBonesA = _skin.GetNumAssignedBones((int)_v.ID); List <int> bonesID = new List <int>(); List <float> bonesWeights = new List <float>(); for (int b = 0; b < 4; b++) { if (nbBonesA < b + 1) { bonesID.Add(0); bonesWeights.Add(0); } else { bonesID.Add(_skin.GetAssignedBone((int)_v.ID, b)); bonesWeights.Add(_skin.GetBoneWeight((int)_v.ID, b)); } } _v.bonesID = new ROD_core.BoneIndices(bonesID[0], bonesID[1], bonesID[2], bonesID[3]); _v.bonesWeights = new Vector4(bonesWeights[0], bonesWeights[1], bonesWeights[2], bonesWeights[3]); _v.pos = (vertices[(int)_v.ID]).convertToVector3(); _v.faceInfo.Add(new PerFaceInfo(_fID, (int)faces[_fID].SmGroup, (Tvertices[(int)Tfaces[_fID].GetTVert(i)]).convertToVector2(), normUnsure, tangent)); verticesFullData.Add((int)faces[_fID].GetVert(i), _v); } } facesFullData.Add(_face); } List <int> IndexBuffer = new List <int>(); List <VertexDivided> VertexBuffer = new List <VertexDivided>(); // vertex index in vertexfullData "undivided" et sa valeur en fonction du SMG Dictionary <int, Dictionary <int, int> > VertexDictionary = new Dictionary <int, Dictionary <int, int> >(); Mesh mesh = new Mesh(); for (int _faceID = 0; _faceID < facesFullData.Count; _faceID++) { facesFullData[_faceID].vertices.Reverse(); foreach (int _vertex in facesFullData[_faceID].vertices) { Dictionary <int, int> vertexTranslation; int _vID = (int)verticesFullData[_vertex].ID; List <PerFaceInfo> unitedVertex = verticesFullData[_vertex].faceInfo.Where(x => x.SMG == facesFullData[_faceID].SMG).ToList(); if (!VertexDictionary.ContainsKey(_vID)) { VertexDictionary.Add(_vID, new Dictionary <int, int>()); } vertexTranslation = VertexDictionary[_vID]; VertexDivided _newVertex = new VertexDivided(); _newVertex.pos = verticesFullData[_vertex].pos; _newVertex.UV.X = verticesFullData[_vertex].faceInfo.Where(x => x.ID == _faceID).FirstOrDefault().UV.X; _newVertex.UV.Y = 1 - verticesFullData[_vertex].faceInfo.Where(x => x.ID == _faceID).FirstOrDefault().UV.Y; Vector3 _normal_aggreagate = new Vector3(0, 0, 0); Vector3 _tangent_aggreagate = new Vector3(0, 0, 0); foreach (PerFaceInfo _FI in unitedVertex) { _normal_aggreagate += _FI.normal; _tangent_aggreagate += _FI.tangent; } _normal_aggreagate.Normalize(); _tangent_aggreagate.Normalize(); _newVertex.normal = _normal_aggreagate; _newVertex.tangent = _tangent_aggreagate; _newVertex.binormal = Vector3.Cross(_normal_aggreagate, _tangent_aggreagate); _newVertex.bonesID = verticesFullData[_vertex].bonesID; _newVertex.bonesWeights = verticesFullData[_vertex].bonesWeights; IndexBuffer.Add(VertexBuffer.Count); VertexBuffer.Add(_newVertex); } } mesh._indexStream = new IndexStream(IndexBuffer.Count, typeof(UInt16), true, true); mesh._vertexStream = new VertexStream(VertexBuffer.Count, true, true, _semantic); foreach (int id in IndexBuffer) { UInt16 _id = Convert.ToUInt16(id); VertexDivided res = VertexBuffer[_id]; mesh._indexStream.WriteIndex(_id); } Type dv = DynamicVertex.CreateVertex(_semantic); FieldInfo[] PI = dv.GetFields(); foreach (VertexDivided vd in VertexBuffer) { if (mesh._boundingBox.Minimum == null) { mesh._boundingBox.Minimum = new Vector3(vd.pos.X, vd.pos.Y, vd.pos.Z); mesh._boundingBox.Maximum = new Vector3(vd.pos.X, vd.pos.Y, vd.pos.Z); } mesh._boundingBox.Minimum.X = Math.Min(mesh._boundingBox.Minimum.X, vd.pos.X); mesh._boundingBox.Minimum.Y = Math.Min(mesh._boundingBox.Minimum.Y, vd.pos.Y); mesh._boundingBox.Minimum.Z = Math.Min(mesh._boundingBox.Minimum.Z, vd.pos.Z); mesh._boundingBox.Maximum.X = Math.Max(mesh._boundingBox.Maximum.X, vd.pos.X); mesh._boundingBox.Maximum.Y = Math.Max(mesh._boundingBox.Maximum.Y, vd.pos.Y); mesh._boundingBox.Maximum.Z = Math.Max(mesh._boundingBox.Maximum.Z, vd.pos.Z); List <object> vertexData = new List <object>(); for (int i = 0; i < PI.Length; i++) { string fieldSemantic = ((InputElementAttribute)PI[i].GetCustomAttributes(true).First()).Semantic; vertexData.Add(vd.GetSemanticObject(fieldSemantic)); } object[] obj = vertexData.ToArray(); //object[] obj = new object[] { vd.pos, vd.normal, vd.UV, vd.binormal, vd.bonesID, vd.bonesWeights, vd.tangent }; //object[] obj = new object[] { vd.pos, vd.normal, vd.UV, vd.binormal, vd.tangent }; //object[] obj = new object[] { vd.pos, vd.normal, vd.UV}; mesh._vertexStream.WriteVertex(obj); } Mesh.saveToFile(mesh, _filepath); }
int CreateGlobalVertex(IMesh mesh, int face, int facePart, List<GlobalVertex> vertices, bool hasUV, bool hasUV2, VNormal[] vnorms, List<GlobalVertex>[] verticesAlreadyExported, IISkinContextData skinContextData) { var faceObject = mesh.Faces[face]; var vertexIndex = (int)faceObject.V[facePart]; var vertex = new GlobalVertex { BaseIndex = vertexIndex, Position = mesh.Verts[vertexIndex], Normal = 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); } 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); } if (skinContextData != null) { float weight0 = 0; float weight1 = 0; float weight2 = 0; int bone0 = bonesCount; int bone1 = bonesCount; int bone2 = bonesCount; int bone3 = bonesCount; int nbBones = skinContextData.GetNumAssignedBones(vertexIndex); if (nbBones > 0) { bone0 = skinContextData.GetAssignedBone(vertexIndex, 0); weight0 = skinContextData.GetBoneWeight(vertexIndex, 0); } if (nbBones > 1) { bone1 = skinContextData.GetAssignedBone(vertexIndex, 1); weight1 = skinContextData.GetBoneWeight(vertexIndex, 1); } if (nbBones > 2) { bone2 = skinContextData.GetAssignedBone(vertexIndex, 2); weight2 = skinContextData.GetBoneWeight(vertexIndex, 2); } if (nbBones > 3) { bone3 = skinContextData.GetAssignedBone(vertexIndex, 3); } if (nbBones == 0) { weight0 = 1.0f; bone0 = bonesCount; } if (nbBones > 4) { RaiseError("Too many bones influences per vertex: " + nbBones + ". Babylon.js only support 4 bones influences per vertex.", 2); } vertex.Weights = Loader.Global.Point4.Create(weight0, weight1, weight2, 1.0 - weight0 - weight1 - weight2); vertex.BonesIndices = (bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0; } if (verticesAlreadyExported != null) { if (verticesAlreadyExported[vertexIndex] != null) { var index = verticesAlreadyExported[vertexIndex].IndexOf(vertex); if (index > -1) { return verticesAlreadyExported[vertexIndex][index].CurrentIndex; } } else { verticesAlreadyExported[vertexIndex] = new List<GlobalVertex>(); } vertex.CurrentIndex = vertices.Count; verticesAlreadyExported[vertexIndex].Add(vertex); } vertices.Add(vertex); return vertices.Count - 1; }
int CreateGlobalVertex(IMesh mesh, int face, int facePart, List <GlobalVertex> vertices, bool hasUV, bool hasUV2, VNormal[] vnorms, List <GlobalVertex>[] verticesAlreadyExported, IISkinContextData skinContextData) { var faceObject = mesh.Faces[face]; var vertexIndex = (int)faceObject.V[facePart]; var vertex = new GlobalVertex { BaseIndex = vertexIndex, Position = mesh.Verts[vertexIndex], Normal = 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); } 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); } if (skinContextData != null) { float weight0 = 0; float weight1 = 0; float weight2 = 0; int bone0 = bonesCount; int bone1 = bonesCount; int bone2 = bonesCount; int bone3 = bonesCount; int nbBones = skinContextData.GetNumAssignedBones(vertexIndex); if (nbBones > 0) { bone0 = skinContextData.GetAssignedBone(vertexIndex, 0); weight0 = skinContextData.GetBoneWeight(vertexIndex, 0); } if (nbBones > 1) { bone1 = skinContextData.GetAssignedBone(vertexIndex, 1); weight1 = skinContextData.GetBoneWeight(vertexIndex, 1); } if (nbBones > 2) { bone2 = skinContextData.GetAssignedBone(vertexIndex, 2); weight2 = skinContextData.GetBoneWeight(vertexIndex, 2); } if (nbBones > 3) { bone3 = skinContextData.GetAssignedBone(vertexIndex, 3); } if (nbBones == 0) { weight0 = 1.0f; bone0 = bonesCount; } if (nbBones > 4) { RaiseError("Too many bones influences per vertex: " + nbBones + ". Babylon.js only support 4 bones influences per vertex.", 2); } vertex.Weights = Loader.Global.Point4.Create(weight0, weight1, weight2, 1.0 - weight0 - weight1 - weight2); vertex.BonesIndices = (bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0; } if (verticesAlreadyExported != null) { if (verticesAlreadyExported[vertexIndex] != null) { var index = verticesAlreadyExported[vertexIndex].IndexOf(vertex); if (index > -1) { return(verticesAlreadyExported[vertexIndex][index].CurrentIndex); } } else { verticesAlreadyExported[vertexIndex] = new List <GlobalVertex>(); } vertex.CurrentIndex = vertices.Count; verticesAlreadyExported[vertexIndex].Add(vertex); } vertices.Add(vertex); return(vertices.Count - 1); }
private void ExportMesh(IINode meshNode, BabylonScene babylonScene) { if (meshNode.IsInstance()) { return; } if (meshNode.GetBoolProperty("babylonjs_noexport")) { return; } if (!ExportHiddenObjects && meshNode.IsHidden(NodeHideFlags.None, false)) { return; } var babylonMesh = new BabylonMesh(); int vx1, vx2, vx3; babylonMesh.name = meshNode.Name; babylonMesh.id = meshNode.GetGuid().ToString(); if (meshNode.HasParent()) { babylonMesh.parentId = meshNode.ParentNode.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"); // Collisions babylonMesh.checkCollisions = meshNode.GetBoolProperty("babylonjs_checkcollisions"); // Skin var skin = GetSkinModifier(meshNode); if (skin != null) { 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 { 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(); // 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) { mesh.BuildNormals(); if (mesh.NumFaces < 1) { RaiseError(string.Format("Mesh {0} has no face", babylonMesh.name), 2); } if (mesh.NumVerts < 3) { RaiseError(string.Format("Mesh {0} has not enough vertices", babylonMesh.name), 2); } if (mesh.NumVerts >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices (more than 65535)", babylonMesh.name), 2); } // Material var mtl = meshNode.Mtl; var multiMatsCount = 1; if (mtl != null) { babylonMesh.materialId = mtl.GetGuid().ToString(); if (!referencedMaterials.Contains(mtl)) { referencedMaterials.Add(mtl); } multiMatsCount = Math.Max(mtl.NumSubMtls, 1); } babylonMesh.visibility = meshNode.GetVisibility(0, Tools.Forever); var vertices = new List <GlobalVertex>(); var indices = new List <int>(); var matIDs = new List <int>(); var hasUV = mesh.NumTVerts > 0; var hasUV2 = mesh.GetNumMapVerts(2) > 0; 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); List <GlobalVertex>[] verticesAlreadyExported = null; if (optimizeVertices) { verticesAlreadyExported = new List <GlobalVertex> [mesh.NumVerts]; } for (var face = 0; face < mesh.NumFaces; face++) { indices.Add(CreateGlobalVertex(mesh, face, vx1, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx2, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); indices.Add(CreateGlobalVertex(mesh, face, vx3, vertices, hasUV, hasUV2, vnorms, verticesAlreadyExported, skinContext)); matIDs.Add(mesh.Faces[face].MatID % multiMatsCount); CheckCancelled(); } if (vertices.Count >= 65536) { RaiseError(string.Format("Mesh {0} has too many vertices: {1} (limit is 65535)", babylonMesh.name, vertices.Count), 2); if (!optimizeVertices) { RaiseError("You can try to optimize your object using [Try to optimize vertices] option", 2); } } 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(); if (hasUV) { babylonMesh.uvs = vertices.SelectMany(v => v.UV.ToArray()).ToArray(); } if (hasUV2) { babylonMesh.uvs2 = vertices.SelectMany(v => v.UV2.ToArray()).ToArray(); } if (skin != null) { babylonMesh.matricesWeights = vertices.SelectMany(v => v.Weights.ToArray()).ToArray(); babylonMesh.matricesIndices = vertices.Select(v => v.BonesIndices).ToArray(); } // 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(); triObject.Dispose(); } // Instances var tabs = Loader.Global.NodeTab.Create(); Loader.Global.IInstanceMgr.InstanceMgr.GetInstances(meshNode, tabs); var instances = new List <BabylonAbstractMesh>(); for (var index = 0; index < tabs.Count; index++) { var indexer = new IntPtr(index); var tab = tabs[indexer]; Marshal.FreeHGlobal(indexer); if (meshNode.GetGuid() == tab.GetGuid()) { continue; } 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(); instances.Add(instance); } babylonMesh.instances = instances.ToArray(); // 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 (meshNode.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); } babylonScene.MeshesList.Add(babylonMesh); }
public static void ComputeVertexData(IMesh _mMesh, IISkinContextData _skin, Semantic _semantic, string _filepath) { Dictionary<int, VertexUndivided> verticesFullData = new Dictionary<int, VertexUndivided>(); List<FaceData> facesFullData = new List<FaceData>(); List<List<VertexDivided>> verticesParsedData = new List<List<VertexDivided>>(); IList<IFace> faces = _mMesh.Faces; IList<ITVFace> Tfaces = _mMesh.TvFace; IList<IPoint3> vertices = _mMesh.Verts; IList<IPoint3> Tvertices = _mMesh.TVerts; /* foreach (IPoint3 _v in vertices) { float temp = _v.Y; _v.Y = -_v.Z; _v.Z = temp; } */ for (int _fID = 0; _fID < faces.Count; _fID++) { FaceData _face = new FaceData((int)faces[_fID].SmGroup); // vectors are inverted to make up for max being clockwise Vector3 A_B = vertices[(int)faces[_fID].GetVert(1)].convertToVector3() - vertices[(int)faces[_fID].GetVert(0)].convertToVector3(); Vector3 A_C = vertices[(int)faces[_fID].GetVert(2)].convertToVector3() - vertices[(int)faces[_fID].GetVert(0)].convertToVector3(); Vector3 U = Tvertices[(int)Tfaces[_fID].GetTVert(1)].convertToVector3() - Tvertices[(int)Tfaces[_fID].GetTVert(0)].convertToVector3(); Vector3 V = Tvertices[(int)Tfaces[_fID].GetTVert(2)].convertToVector3() - Tvertices[(int)Tfaces[_fID].GetTVert(0)].convertToVector3(); Vector3 normUnsure = Vector3.Cross(A_B, A_C); normUnsure.Normalize(); float area = U.X * V.Y - U.Y * V.X; int sign = area < 0 ? -1 : 1; Vector3 tangent = new Vector3(0, 0, 1); tangent.X = A_B.X * V.Y - U.Y * A_C.X; tangent.Y = A_B.Y * V.Y - U.Y * A_C.Y; tangent.Z = A_B.Z * V.Y - U.Y * A_C.Z; tangent.Normalize(); tangent *= sign; for (int i = 0; i < 3; i++) { _face.vertices.Add((int)faces[_fID].GetVert(i)); if (verticesFullData.ContainsKey((int)faces[_fID].GetVert(i))) { VertexUndivided _v = verticesFullData[(int)faces[_fID].GetVert(i)]; _v.faceInfo.Add(new PerFaceInfo(_fID, (int)faces[_fID].SmGroup, (Tvertices[(int)Tfaces[_fID].GetTVert(i)]).convertToVector2(), normUnsure, tangent)); } else { VertexUndivided _v = new VertexUndivided(); _v.ID = faces[_fID].GetVert(i); int nbBonesA=_skin.GetNumAssignedBones((int)_v.ID); List<int> bonesID = new List<int>(); List<float> bonesWeights = new List<float>(); for (int b = 0; b < 4; b++) { if(nbBonesA<b+1) { bonesID.Add(0); bonesWeights.Add(0); } else { bonesID.Add(_skin.GetAssignedBone((int)_v.ID, b)); bonesWeights.Add(_skin.GetBoneWeight((int)_v.ID, b)); } } _v.bonesID = new ROD_core.BoneIndices(bonesID[0], bonesID[1], bonesID[2], bonesID[3]); _v.bonesWeights = new Vector4(bonesWeights[0], bonesWeights[1], bonesWeights[2], bonesWeights[3]); _v.pos = (vertices[(int)_v.ID]).convertToVector3(); _v.faceInfo.Add(new PerFaceInfo(_fID, (int)faces[_fID].SmGroup, (Tvertices[(int)Tfaces[_fID].GetTVert(i)]).convertToVector2(), normUnsure, tangent)); verticesFullData.Add((int)faces[_fID].GetVert(i), _v); } } facesFullData.Add(_face); } List<int> IndexBuffer = new List<int>(); List<VertexDivided> VertexBuffer = new List<VertexDivided>(); // vertex index in vertexfullData "undivided" et sa valeur en fonction du SMG Dictionary<int, Dictionary<int, int>> VertexDictionary = new Dictionary<int, Dictionary<int, int>>(); Mesh mesh = new Mesh(); for (int _faceID = 0; _faceID < facesFullData.Count; _faceID++) { facesFullData[_faceID].vertices.Reverse(); foreach (int _vertex in facesFullData[_faceID].vertices) { Dictionary<int, int> vertexTranslation; int _vID = (int)verticesFullData[_vertex].ID; List<PerFaceInfo> unitedVertex = verticesFullData[_vertex].faceInfo.Where(x => x.SMG == facesFullData[_faceID].SMG).ToList(); if (!VertexDictionary.ContainsKey(_vID)) { VertexDictionary.Add(_vID, new Dictionary<int, int>()); } vertexTranslation = VertexDictionary[_vID]; VertexDivided _newVertex = new VertexDivided(); _newVertex.pos = verticesFullData[_vertex].pos; _newVertex.UV.X = verticesFullData[_vertex].faceInfo.Where(x => x.ID == _faceID).FirstOrDefault().UV.X; _newVertex.UV.Y = 1 - verticesFullData[_vertex].faceInfo.Where(x => x.ID == _faceID).FirstOrDefault().UV.Y; Vector3 _normal_aggreagate = new Vector3(0, 0, 0); Vector3 _tangent_aggreagate = new Vector3(0, 0, 0); foreach (PerFaceInfo _FI in unitedVertex) { _normal_aggreagate += _FI.normal; _tangent_aggreagate += _FI.tangent; } _normal_aggreagate.Normalize(); _tangent_aggreagate.Normalize(); _newVertex.normal = _normal_aggreagate; _newVertex.tangent = _tangent_aggreagate; _newVertex.binormal = Vector3.Cross(_normal_aggreagate, _tangent_aggreagate); _newVertex.bonesID = verticesFullData[_vertex].bonesID; _newVertex.bonesWeights = verticesFullData[_vertex].bonesWeights; IndexBuffer.Add(VertexBuffer.Count); VertexBuffer.Add(_newVertex); } } mesh._indexStream = new IndexStream(IndexBuffer.Count, typeof(UInt16), true, true); mesh._vertexStream = new VertexStream(VertexBuffer.Count, true, true, _semantic); foreach (int id in IndexBuffer) { UInt16 _id = Convert.ToUInt16(id); VertexDivided res = VertexBuffer[_id]; mesh._indexStream.WriteIndex(_id); } Type dv = DynamicVertex.CreateVertex(_semantic); FieldInfo[] PI = dv.GetFields(); foreach (VertexDivided vd in VertexBuffer) { if (mesh._boundingBox.Minimum == null) { mesh._boundingBox.Minimum = new Vector3(vd.pos.X, vd.pos.Y, vd.pos.Z); mesh._boundingBox.Maximum = new Vector3(vd.pos.X, vd.pos.Y, vd.pos.Z); } mesh._boundingBox.Minimum.X = Math.Min(mesh._boundingBox.Minimum.X, vd.pos.X); mesh._boundingBox.Minimum.Y = Math.Min(mesh._boundingBox.Minimum.Y, vd.pos.Y); mesh._boundingBox.Minimum.Z = Math.Min(mesh._boundingBox.Minimum.Z, vd.pos.Z); mesh._boundingBox.Maximum.X = Math.Max(mesh._boundingBox.Maximum.X, vd.pos.X); mesh._boundingBox.Maximum.Y = Math.Max(mesh._boundingBox.Maximum.Y, vd.pos.Y); mesh._boundingBox.Maximum.Z = Math.Max(mesh._boundingBox.Maximum.Z, vd.pos.Z); List<object> vertexData = new List<object>(); for (int i = 0; i < PI.Length; i++) { string fieldSemantic = ((InputElementAttribute)PI[i].GetCustomAttributes(true).First()).Semantic; vertexData.Add(vd.GetSemanticObject(fieldSemantic)); } object[] obj = vertexData.ToArray(); //object[] obj = new object[] { vd.pos, vd.normal, vd.UV, vd.binormal, vd.bonesID, vd.bonesWeights, vd.tangent }; //object[] obj = new object[] { vd.pos, vd.normal, vd.UV, vd.binormal, vd.tangent }; //object[] obj = new object[] { vd.pos, vd.normal, vd.UV}; mesh._vertexStream.WriteVertex(obj); } Mesh.saveToFile(mesh, _filepath); }