/// <summary> /// Gets the model information in this scene as an IO Model /// </summary> /// <returns></returns> public override IOModel GetIOModel() { IOModel iomodel = new IOModel(); iomodel.Skeleton = (SBSkeleton)Skeleton; foreach (var mesh in Model.Meshes) { var iomesh = new IOMesh(); iomesh.Name = mesh.Name; iomodel.Meshes.Add(iomesh); iomesh.HasPositions = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.Position0); iomesh.HasNormals = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.Normal0); iomesh.HasUV0 = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.map1); iomesh.HasUV1 = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.uvSet); iomesh.HasUV2 = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.uvSet1); iomesh.HasUV3 = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.uvSet2); iomesh.HasColor = mesh.ExportAttributes.Contains(SSBHLib.Tools.MESHAttribute.colorSet1); iomesh.HasBoneWeights = true; iomesh.Indices.AddRange(mesh.Indices); foreach (var vertex in mesh.Vertices) { var iovertex = new IOVertex(); iovertex.Position = vertex.Position0; iovertex.Normal = vertex.Normal0; iovertex.Tangent = vertex.Tangent0; iovertex.UV0 = vertex.Map1; iovertex.UV1 = vertex.UvSet; iovertex.UV2 = vertex.UvSet1; iovertex.Color = vertex.ColorSet1; iovertex.BoneIndices = new Vector4(vertex.BoneIndices.X, vertex.BoneIndices.Y, vertex.BoneIndices.Z, vertex.BoneIndices.W); iovertex.BoneWeights = vertex.BoneWeights; // single bind fix if (mesh.ParentBone != "" && Skeleton != null) { var parentBone = Skeleton[mesh.ParentBone]; if (parentBone != null) { iovertex.Position = Vector3.TransformPosition(vertex.Position0, parentBone.WorldTransform); iovertex.Normal = Vector3.TransformNormal(vertex.Normal0, parentBone.WorldTransform); iovertex.BoneIndices = new Vector4(Skeleton.IndexOfBone(parentBone), 0, 0, 0); iovertex.BoneWeights = new Vector4(1, 0, 0, 0); } } iomesh.Vertices.Add(iovertex); } } return(iomodel); }
/// <summary> /// /// </summary> /// <param name="type"></param> /// <param name="vertices"></param> /// <param name="parent"></param> /// <returns></returns> private List <IOVertex> ConvertGXDLtoTriangleList(GXPrimitiveType type, List <SBHsdVertex> vertices, SBHsdBone parent) { var list = new List <IOVertex>(); foreach (var v in vertices) { var vertex = new IOVertex() { Position = new System.Numerics.Vector3(v.POS.X, v.POS.Y, v.POS.Z), Normal = new System.Numerics.Vector3(v.NRM.X, v.NRM.Y, v.NRM.Z), }; vertex.SetUV(v.UV0.X, v.UV0.Y, 0); for (int i = 0; i < 4; i++) { if (v.Weight[i] > 0) { vertex.Envelope.Weights.Add(new IOBoneWeight() { BoneName = "JOBJ_" + (int)v.Bone[i], Weight = v.Weight[i] }); } } if (parent != null) { vertex.Transform(TktoNumeric(parent.WorldTransform)); if (vertex.Envelope.Weights.Count == 0) { vertex.Envelope.Weights.Add(new IOBoneWeight() { BoneName = parent.Name, Weight = 1 }); } } if (v.Weight.X == 1) { vertex.Transform(TktoNumeric(Skeleton.Bones[(int)v.Bone.X].WorldTransform)); } list.Add(vertex); } if (type == GXPrimitiveType.TriangleStrip) { TriangleConvert.StripToList(list, out list); } if (type == GXPrimitiveType.Quads) { TriangleConvert.QuadToList(list, out list); } return(list); }
private static UltimateVertex IOToUltimateVertex(IOVertex iov) { return(new UltimateVertex(iov.Position, iov.Normal, iov.Tangent, Vector3.Zero, iov.UV0, iov.UV1, iov.UV2, new IVec4() { X = (int)iov.BoneIndices.X, Y = (int)iov.BoneIndices.Y, Z = (int)iov.BoneIndices.Z, W = (int)iov.BoneIndices.W }, iov.BoneWeights, Vector2.Zero, Vector4.One, Vector4.One)); }
private List <IOVertex> ConvertGXDLtoTriangleList(GXPrimitiveType type, List <SBHsdVertex> vertices, SBHsdBone parent) { var list = new List <IOVertex>(); foreach (var v in vertices) { var vertex = new IOVertex() { Position = GXtoGL.GLVector3(v.POS), Normal = GXtoGL.GLVector3(v.NRM), UV0 = GXtoGL.GLVector2(v.UV0), BoneIndices = v.Bone, BoneWeights = v.Weight, }; if (parent != null) { vertex.Position = Vector3.TransformPosition(vertex.Position, parent.WorldTransform); vertex.Normal = Vector3.TransformNormal(vertex.Normal, parent.WorldTransform); if (vertex.BoneWeights.X == 0) { vertex.BoneWeights.X = 1; vertex.BoneIndices.X = Skeleton.IndexOfBone(parent); } } if (v.Weight.X == 1) { vertex.Position = Vector3.TransformPosition(vertex.Position, Skeleton.Bones[(int)v.Bone.X].WorldTransform); vertex.Normal = Vector3.TransformNormal(vertex.Normal, Skeleton.Bones[(int)v.Bone.X].WorldTransform); } list.Add(vertex); } if (type == GXPrimitiveType.TriangleStrip) { TriangleConvert.StripToList(list, out list); } if (type == GXPrimitiveType.Quads) { TriangleConvert.QuadToList(list, out list); } return(list); }
/// <summary> /// /// </summary> /// <returns></returns> private static IOVertex ParseVertex(string line, Dictionary <int, IOBone> idxToBones, out IOBone parentBone) { var args = Regex.Replace(line.Trim(), @"\s+", " ").Split(' '); IOVertex vertex = new IOVertex(); // parse parent index int parent = int.Parse(args[0]); // parse attributes vertex.Position = new System.Numerics.Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])); vertex.Normal = new System.Numerics.Vector3(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6])); vertex.UVs.Add(new System.Numerics.Vector2(float.Parse(args[7]), float.Parse(args[8]))); // transform by parent so we can ignore it if (parent != -1) { vertex.Transform(idxToBones[parent].WorldTransform); parentBone = idxToBones[parent]; } else { parentBone = null; } // parse weights if (args.Length >= 10) { int links = int.Parse(args[9]); for (int i = 0; i < links; i++) { vertex.Envelope.Weights.Add(new IOBoneWeight() { BoneName = idxToBones[int.Parse(args[10 + i * 2])].Name, Weight = float.Parse(args[11 + i * 2]) }); } } return(vertex); }
private static SMDVertex IOVertexToSMDVertex(IOVertex iovertex) { var smdvertex = new SMDVertex(); smdvertex.Position = iovertex.Position; smdvertex.Normal = iovertex.Normal; smdvertex.UV = iovertex.UV0; int weightCount = CountWeights(iovertex.BoneWeights); smdvertex.Bones = new int[weightCount]; smdvertex.Weights = new float[weightCount]; for (int i = 0; i < weightCount; i++) { smdvertex.Bones[0] = (int)iovertex.BoneIndices[i]; smdvertex.Weights[0] = iovertex.BoneWeights[i]; } return(smdvertex); }
private static IOVertex ReadVertex(string[] args) { var vertex = new IOVertex() { Position = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])), Normal = new Vector3(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6])), UV0 = new Vector2(float.Parse(args[7]), float.Parse(args[8])), }; vertex.Color = Vector4.One; int InfluenceCount = int.Parse(args[9]); for (int i = 0; i < InfluenceCount * 2; i += 2) { int boneIndex = int.Parse(args[10 + i]); float weight = float.Parse(args[10 + i + 1]); if (i / 2 == 0) { vertex.BoneIndices.X = boneIndex; vertex.BoneWeights.X = weight; } if (i / 2 == 1) { vertex.BoneIndices.Y = boneIndex; vertex.BoneWeights.Y = weight; } if (i / 2 == 2) { vertex.BoneIndices.Z = boneIndex; vertex.BoneWeights.Z = weight; } if (i / 2 == 3) { vertex.BoneIndices.W = boneIndex; vertex.BoneWeights.W = weight; } } return(vertex); }
/// <summary> /// /// </summary> /// <param name="semantic"></param> /// <param name="values"></param> /// <param name="vertex"></param> /// <param name="vertices"></param> private void ProcessInput(Input_Semantic semantic, string source, int set, IOVertex vertex, Vertices vertices, int index, SourceManager srcs, List <IOEnvelope> vertexEnvelopes) { var values = srcs.GetFloatValue(source, index); switch (semantic) { case Input_Semantic.VERTEX: // process per vertex input foreach (var vertInput in vertices.Input) { ProcessInput(vertInput.Semantic, vertInput.source, 0, vertex, vertices, index, srcs, vertexEnvelopes); } // load envelopes if availiable if (vertexEnvelopes != null && index < vertexEnvelopes.Count) { // copy bone weights var en = vertexEnvelopes[index]; for (int i = 0; i < en.Weights.Count; i++) { vertex.Envelope.Weights.Add(new IOBoneWeight() { BoneName = en.Weights[i].BoneName, Weight = en.Weights[i].Weight, BindMatrix = en.Weights[i].BindMatrix }); } // make the bind matrix as being used vertex.Envelope.UseBindMatrix = true; } break; case Input_Semantic.POSITION: vertex.Position = new Vector3( values.Length > 0 ? values[0] : 0, values.Length > 1 ? values[1] : 0, values.Length > 2 ? values[2] : 0); break; case Input_Semantic.NORMAL: vertex.Normal = new Vector3( values.Length > 0 ? values[0] : 0, values.Length > 1 ? values[1] : 0, values.Length > 2 ? values[2] : 0); break; case Input_Semantic.TANGENT: vertex.Tangent = new Vector3( values.Length > 0 ? values[0] : 0, values.Length > 1 ? values[1] : 0, values.Length > 2 ? values[2] : 0); break; case Input_Semantic.BINORMAL: vertex.Binormal = new Vector3( values.Length > 0 ? values[0] : 0, values.Length > 1 ? values[1] : 0, values.Length > 2 ? values[2] : 0); break; case Input_Semantic.TEXCOORD: vertex.SetUV( values.Length > 0 ? values[0] : 0, values.Length > 1 ? values[1] : 0, set); break; case Input_Semantic.COLOR: vertex.SetColor( values.Length > 0 ? values[0] : 0, values.Length > 1 ? values[1] : 0, values.Length > 2 ? values[2] : 0, values.Length > 3 ? values[3] : 0, set); break; } }
/// <summary> /// /// </summary> /// <param name="n"></param> /// <param name="id"></param> /// <returns></returns> public IOMesh LoadGeometryFromID(Node n, string id, List <IOEnvelope> vertexEnvelopes = null) { // sanitize id = ColladaHelper.SanitizeID(id); // find geometry by id var geom = _collada.Library_Geometries.Geometry.First(e => e.ID == id); // not found if (geom == null) { return(null); } // create new mesh IOMesh mesh = new IOMesh() { Name = n.Name }; // create source manager helper SourceManager srcs = new SourceManager(); if (geom.Mesh.Source != null) { foreach (var src in geom.Mesh.Source) { srcs.AddSource(src); } } // load geomtry meshes if (geom.Mesh.Triangles != null) { foreach (var tri in geom.Mesh.Triangles) { var stride = tri.Input.Max(e => e.Offset) + 1; var poly = new IOPolygon() { PrimitiveType = IOPrimitive.TRIANGLE, MaterialName = tri.Material }; var p = tri.P.GetValues(); for (int i = 0; i < tri.Count * 3; i++) { IOVertex vertex = new IOVertex(); for (int j = 0; j < tri.Input.Length; j++) { var input = tri.Input[j]; var index = p[i * stride + input.Offset]; ProcessInput(input.Semantic, input.source, input.Set, vertex, geom.Mesh.Vertices, index, srcs, vertexEnvelopes); } poly.Indicies.Add(mesh.Vertices.Count); mesh.Vertices.Add(vertex); } mesh.Polygons.Add(poly); } } //TODO: collada trifan //TODO: collada tristrip //TODO: collada linestrip //TODO: collada polylist //TODO: collada polygon return(mesh); }
/// <summary> /// /// </summary> private void ProcessGeometry(FbxNode node, out IOPolygon poly, out List <IOVertex> verts) { double[] vertices; int[] indices; // load vertices if (node["Vertices"].Value is double[]) { vertices = (double[])node["Vertices"].Value; } else { vertices = node["Vertices"].Properties.Select(e => (double)e).ToArray(); } // load vertex indices if (node["PolygonVertexIndex"].Value is int[]) { indices = (int[])node["PolygonVertexIndex"].Value; } else { indices = node["PolygonVertexIndex"].Properties.Select(e => (int)e).ToArray(); } // get binds var deformers = GetChildConnections(node).Where(e => e.Name == "Deformer"); List <Dictionary <int, Tuple <float, string> > > deforms = new List <Dictionary <int, Tuple <float, string> > >(); foreach (var par in deformers) { foreach (var sub in GetChildConnections(par)) { // get bone name var name = ""; foreach (var mod in GetChildConnections(sub)) { if (mod.Name == "Model") { name = GetNameWithoutNamespace(mod.Properties[NodeDescSize - 2].ToString()); } } if (!string.IsNullOrEmpty(name) && sub["Indexes"] != null) { // create deform map Dictionary <int, Tuple <float, string> > deformmap = new Dictionary <int, Tuple <float, string> >(); // indices int[] ind; if (sub["Indexes"].Value is int[]) { ind = (int[])sub["Indexes"].Value; } else { ind = sub["Indexes"].Properties.Select(e => (int)e).ToArray(); } // weights float[] weights; if (sub["Weights"].Value is double[]) { weights = ((double[])sub["Weights"].Value).Select(e => (float)e).ToArray(); } else { weights = sub["Weights"].Properties.Select(e => (float)(double)e).ToArray(); } // generate map for (int i = 0; i < weights.Length; i++) { deformmap.Add(ind[i], new Tuple <float, string>(weights[i], name)); } // add deform entry deforms.Add(deformmap); } } } // generate polygon poly = new IOPolygon(); verts = new List <IOVertex>(); poly.PrimitiveType = IOPrimitive.TRIANGLE; // process primitives and convert to triangles var primLength = 0; for (int i = 0; i < indices.Length; i++) { var idx1 = indices[i]; primLength++; if (idx1 < 0) { switch (primLength) { case 4: // convert quad to triangle poly.Indicies.Add(i - 3); poly.Indicies.Add(i - 2); poly.Indicies.Add(i - 1); poly.Indicies.Add(i - 3); poly.Indicies.Add(i - 1); poly.Indicies.Add(i); break; case 3: // triangle poly.Indicies.Add(i - 2); poly.Indicies.Add(i - 1); poly.Indicies.Add(i); break; default: // tri strip for (var vi = i - primLength; vi < i - 2; vi++) { if ((vi & 1) != 0) { poly.Indicies.Add(vi); poly.Indicies.Add(vi + 1); poly.Indicies.Add(vi + 2); } else { poly.Indicies.Add(vi); poly.Indicies.Add(vi + 2); poly.Indicies.Add(vi + 1); } } break; } idx1 = Math.Abs(idx1) - 1; // xor -1 primLength = 0; } IOVertex v = new IOVertex() { Position = new Vector3((float)vertices[idx1 * 3], (float)vertices[idx1 * 3 + 1], (float)vertices[idx1 * 3 + 2]) }; // find deforms foreach (var map in deforms) { if (map.ContainsKey(idx1)) { v.Envelope.Weights.Add(new Core.IOBoneWeight() { Weight = map[idx1].Item1, BoneName = map[idx1].Item2, }); } } verts.Add(v); } // get layer information ProcessLayer(node, "Normal", indices, verts); ProcessLayer(node, "Tangent", indices, verts); ProcessLayer(node, "Binormal", indices, verts); ProcessLayer(node, "UV", indices, verts); ProcessLayer(node, "Color", indices, verts); }
public IOModel GetIOModel() { IOModel outModel = new IOModel(); MESH meshFile = null; foreach (FileNode n in Parent.Nodes) { if (n.Text.Equals(_model.MeshString)) { meshFile = ((NUMSHB_Node)n).mesh; } if (n.Text.Equals(_model.SkeletonFileName)) { outModel.Skeleton = (RSkeleton)((SKEL_Node)n).GetRenderableNode(); } } Dictionary <string, int> indexByBoneName = new Dictionary <string, int>(); if (outModel.Skeleton != null) { for (int i = 0; i < outModel.Skeleton.Bones.Count; i++) { indexByBoneName.Add(outModel.Skeleton.Bones[i].Name, i); } } if (meshFile != null) { using (SSBHVertexAccessor vertexAccessor = new SSBHVertexAccessor(meshFile)) { SSBHRiggingAccessor riggingAccessor = new SSBHRiggingAccessor(meshFile); foreach (MeshObject obj in meshFile.Objects) { IOMesh outMesh = new IOMesh() { Name = obj.Name, }; outModel.Meshes.Add(outMesh); IOVertex[] vertices = new IOVertex[obj.VertexCount]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new IOVertex(); } foreach (MeshAttribute attr in obj.Attributes) { SSBHVertexAttribute[] values = vertexAccessor.ReadAttribute(attr.AttributeStrings[0].Name, 0, obj.VertexCount, obj); if (attr.AttributeStrings[0].Name.Equals("Position0")) { outMesh.HasPositions = true; for (int i = 0; i < values.Length; i++) { vertices[i].Position = new OpenTK.Vector3(values[i].X, values[i].Y, values[i].Z); } } if (attr.AttributeStrings[0].Name.Equals("Normal0")) { outMesh.HasNormals = true; for (int i = 0; i < values.Length; i++) { vertices[i].Normal = new OpenTK.Vector3(values[i].X, values[i].Y, values[i].Z); } } if (attr.AttributeStrings[0].Name.Equals("map1")) { outMesh.HasUV0 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV0 = new OpenTK.Vector2(values[i].X, values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("uvSet")) { outMesh.HasUV1 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV1 = new OpenTK.Vector2(values[i].X, values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("uvSet1")) { outMesh.HasUV2 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV2 = new OpenTK.Vector2(values[i].X, values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("uvSet2")) { outMesh.HasUV3 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV3 = new OpenTK.Vector2(values[i].X, values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("colorSet1")) { outMesh.HasColor = true; for (int i = 0; i < values.Length; i++) { vertices[i].Color = new OpenTK.Vector4(values[i].X, values[i].Y, values[i].Z, values[i].W); } } } // Fix SingleBinds if (outModel.Skeleton != null && !obj.ParentBoneName.Equals("")) { int parentIndex = outModel.Skeleton.GetBoneIndex(obj.ParentBoneName); if (parentIndex != -1) { for (int i = 0; i < vertices.Length; i++) { vertices[i].Position = OpenTK.Vector3.TransformPosition(vertices[i].Position, outModel.Skeleton.Bones[parentIndex].WorldTransform); vertices[i].Normal = OpenTK.Vector3.TransformNormal(vertices[i].Normal, outModel.Skeleton.Bones[parentIndex].WorldTransform); vertices[i].BoneIndices.X = indexByBoneName[obj.ParentBoneName]; vertices[i].BoneWeights.X = 1; } } } // Apply Rigging SSBHVertexInfluence[] influences = riggingAccessor.ReadRiggingBuffer(obj.Name, (int)obj.SubMeshIndex); foreach (SSBHVertexInfluence influence in influences) { // Some influences refer to bones that don't exist in the skeleton. // _eff bones? if (!indexByBoneName.ContainsKey(influence.BoneName)) { continue; } if (vertices[influence.VertexIndex].BoneWeights.X == 0) { vertices[influence.VertexIndex].BoneIndices.X = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.X = influence.Weight; } else if (vertices[influence.VertexIndex].BoneWeights.Y == 0) { vertices[influence.VertexIndex].BoneIndices.Y = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.Y = influence.Weight; } else if (vertices[influence.VertexIndex].BoneWeights.Z == 0) { vertices[influence.VertexIndex].BoneIndices.Z = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.Z = influence.Weight; } else if (vertices[influence.VertexIndex].BoneWeights.W == 0) { vertices[influence.VertexIndex].BoneIndices.W = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.W = influence.Weight; } } outMesh.Vertices.AddRange(vertices); outMesh.Indices.AddRange(vertexAccessor.ReadIndices(0, obj.IndexCount, obj)); } } } return(outModel); }
public IOModel GetIOModel() { IOModel outModel = new IOModel(); Mesh meshFile = null; Matl materialFile = null; foreach (FileNode n in Parent.Nodes) { if (n.Text.Equals(model.MeshString)) { meshFile = ((NumsbhNode)n).mesh; } if (n.Text.Equals(model.SkeletonFileName)) { outModel.Skeleton = (RSkeleton)((SkelNode)n).GetRenderableNode(); } if (n.Text.Equals(model.MaterialFileNames[0].MaterialFileName)) { materialFile = ((MatlNode)n).Material; } } Dictionary <string, int> indexByBoneName = new Dictionary <string, int>(); if (outModel.Skeleton != null) { for (int i = 0; i < outModel.Skeleton.Bones.Count; i++) { indexByBoneName.Add(outModel.Skeleton.Bones[i].Name, i); } } Dictionary <string, int> materialNameToIndex = new Dictionary <string, int>(); if (materialFile != null) { int materialIndex = 0; foreach (var entry in materialFile.Entries) { materialNameToIndex.Add(entry.ShaderLabel, materialIndex++); IOMaterial material = new IOMaterial { Name = entry.ShaderLabel }; outModel.Materials.Add(material); foreach (var attr in entry.Attributes) { if (attr.ParamId == MatlEnums.ParamId.Texture0) { IOTexture dif = new IOTexture { Name = attr.DataObject.ToString() }; material.DiffuseTexture = dif; } } } } if (meshFile != null) { SsbhVertexAccessor vertexAccessor = new SsbhVertexAccessor(meshFile); { SsbhRiggingAccessor riggingAccessor = new SsbhRiggingAccessor(meshFile); foreach (MeshObject obj in meshFile.Objects) { IOMesh outMesh = new IOMesh() { Name = obj.Name, }; outModel.Meshes.Add(outMesh); // get material if (materialFile != null) { foreach (var entry in model.ModelEntries) { if (entry.MeshName.Equals(obj.Name) && entry.SubIndex == obj.SubMeshIndex) { outMesh.MaterialIndex = materialNameToIndex[entry.MaterialLabel]; break; } } } IOVertex[] vertices = new IOVertex[obj.VertexCount]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new IOVertex(); } foreach (MeshAttribute attr in obj.Attributes) { SsbhVertexAttribute[] values = vertexAccessor.ReadAttribute(attr.AttributeStrings[0].Name, 0, obj.VertexCount, obj); if (attr.AttributeStrings[0].Name.Equals("Position0")) { outMesh.HasPositions = true; for (int i = 0; i < values.Length; i++) { vertices[i].Position = new OpenTK.Vector3(values[i].X, values[i].Y, values[i].Z); } } if (attr.AttributeStrings[0].Name.Equals("Normal0")) { outMesh.HasNormals = true; for (int i = 0; i < values.Length; i++) { vertices[i].Normal = new OpenTK.Vector3(values[i].X, values[i].Y, values[i].Z); } } // Flip UVs vertically for export. if (attr.AttributeStrings[0].Name.Equals("map1")) { outMesh.HasUV0 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV0 = new OpenTK.Vector2(values[i].X, 1 - values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("uvSet")) { outMesh.HasUV1 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV1 = new OpenTK.Vector2(values[i].X, 1 - values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("uvSet1")) { outMesh.HasUV2 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV2 = new OpenTK.Vector2(values[i].X, 1 - values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("uvSet2")) { outMesh.HasUV3 = true; for (int i = 0; i < values.Length; i++) { vertices[i].UV3 = new OpenTK.Vector2(values[i].X, 1 - values[i].Y); } } if (attr.AttributeStrings[0].Name.Equals("colorSet1")) { outMesh.HasColor = true; for (int i = 0; i < values.Length; i++) { vertices[i].Color = new OpenTK.Vector4(values[i].X, values[i].Y, values[i].Z, values[i].W) / 127f; } } } // Fix SingleBinds if (outModel.Skeleton != null && !obj.ParentBoneName.Equals("")) { int parentIndex = outModel.Skeleton.GetBoneIndex(obj.ParentBoneName); if (parentIndex != -1) { for (int i = 0; i < vertices.Length; i++) { vertices[i].Position = OpenTK.Vector3.TransformPosition(vertices[i].Position, outModel.Skeleton.Bones[parentIndex].WorldTransform); vertices[i].Normal = OpenTK.Vector3.TransformNormal(vertices[i].Normal, outModel.Skeleton.Bones[parentIndex].WorldTransform); vertices[i].BoneIndices.X = indexByBoneName[obj.ParentBoneName]; vertices[i].BoneWeights.X = 1; outMesh.HasBoneWeights = true; } } } // Apply Rigging SsbhVertexInfluence[] influences = riggingAccessor.ReadRiggingBuffer(obj.Name, (int)obj.SubMeshIndex); foreach (SsbhVertexInfluence influence in influences) { outMesh.HasBoneWeights = true; // Some influences refer to bones that don't exist in the skeleton. // _eff bones? if (!indexByBoneName.ContainsKey(influence.BoneName)) { continue; } if (vertices[influence.VertexIndex].BoneWeights.X == 0) { vertices[influence.VertexIndex].BoneIndices.X = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.X = influence.Weight; } else if (vertices[influence.VertexIndex].BoneWeights.Y == 0) { vertices[influence.VertexIndex].BoneIndices.Y = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.Y = influence.Weight; } else if (vertices[influence.VertexIndex].BoneWeights.Z == 0) { vertices[influence.VertexIndex].BoneIndices.Z = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.Z = influence.Weight; } else if (vertices[influence.VertexIndex].BoneWeights.W == 0) { vertices[influence.VertexIndex].BoneIndices.W = indexByBoneName[influence.BoneName]; vertices[influence.VertexIndex].BoneWeights.W = influence.Weight; } } outMesh.Vertices.AddRange(vertices); outMesh.Indices.AddRange(vertexAccessor.ReadIndices(0, obj.IndexCount, obj)); } } } return(outModel); }
/// <summary> /// /// </summary> /// <param name="filePath"></param> /// <returns></returns> public IOScene GetScene(string filePath) { // create scene and model IOScene scene = new IOScene(); // load materials var mtlFile = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".mtl"); if (File.Exists(mtlFile)) { LoadMaterialLibrary(scene, mtlFile); } // parse obj file using (FileStream stream = new FileStream(filePath, FileMode.Open)) using (StreamReader r = new StreamReader(stream)) { List <Vector3> v = new List <Vector3>(); List <Vector2> vt = new List <Vector2>(); List <Vector3> vn = new List <Vector3>(); List <Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > > > objects = new List <Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > > >(); var objName = "Mesh"; var matNam = ""; Dictionary <IOPrimitive, List <int[]> > polygons = new Dictionary <IOPrimitive, List <int[]> >(); while (!r.EndOfStream) { var args = Regex.Replace(r.ReadLine().Trim(), @"\s+", " ").Split(' '); if (args.Length > 0) { switch (args[0]) { case "v": v.Add(new Vector3( args.Length > 1 ? float.Parse(args[1]) : 0, args.Length > 2 ? float.Parse(args[2]) : 0, args.Length > 3 ? float.Parse(args[3]) : 0)); break; case "vt": vt.Add(new Vector2( args.Length > 1 ? float.Parse(args[1]) : 0, args.Length > 2 ? float.Parse(args[2]) : 0)); break; case "vn": vn.Add(new Vector3( args.Length > 1 ? float.Parse(args[1]) : 0, args.Length > 2 ? float.Parse(args[2]) : 0, args.Length > 3 ? float.Parse(args[3]) : 0)); break; case "f": var faces = ParseFaces(args); if (args.Length == 2) { // point if (!polygons.ContainsKey(IOPrimitive.POINT)) { polygons.Add(IOPrimitive.POINT, new List <int[]>()); } polygons[IOPrimitive.POINT].AddRange(faces); } if (args.Length == 3) { // line if (!polygons.ContainsKey(IOPrimitive.LINE)) { polygons.Add(IOPrimitive.LINE, new List <int[]>()); } polygons[IOPrimitive.LINE].AddRange(faces); } if (args.Length == 4) { // triangle if (!polygons.ContainsKey(IOPrimitive.TRIANGLE)) { polygons.Add(IOPrimitive.TRIANGLE, new List <int[]>()); } polygons[IOPrimitive.TRIANGLE].AddRange(faces); } if (args.Length == 5) { // quad if (!polygons.ContainsKey(IOPrimitive.QUAD)) { polygons.Add(IOPrimitive.QUAD, new List <int[]>()); } polygons[IOPrimitive.QUAD].AddRange(faces); } if (args.Length == 6) { // strip if (!polygons.ContainsKey(IOPrimitive.TRISTRIP)) { polygons.Add(IOPrimitive.TRISTRIP, new List <int[]>()); } polygons[IOPrimitive.TRISTRIP].AddRange(faces); } break; case "o": if (polygons.Count > 0) { objects.Add(new Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > >(objName, matNam, polygons)); } objName = args[1]; matNam = ""; polygons = new Dictionary <IOPrimitive, List <int[]> >(); break; case "usemtl": matNam = args[1]; break; } } } objects.Add(new Tuple <string, string, Dictionary <IOPrimitive, List <int[]> > >(objName, matNam, polygons)); // generate model IOModel model = new IOModel(); scene.Models.Add(model); // dummy bone model.Skeleton.RootBones.Add(new Core.Skeleton.IOBone() { Name = "Root" }); // convert and add polygons foreach (var obj in objects) { IOMesh mesh = new IOMesh() { Name = obj.Item1 }; foreach (var p in obj.Item3) { IOPolygon poly = new IOPolygon() { PrimitiveType = p.Key, MaterialName = obj.Item2, }; for (int i = 0; i < p.Value.Count; i++) { var face = p.Value[i]; IOVertex vert = new IOVertex() { Position = face[0] != -1 ? v[face[0]] : Vector3.Zero, Normal = face[2] != -1 ? vn[face[2]] : Vector3.Zero, }; if (face[1] != -1) { vert.UVs.Add(vt[face[1]]); } poly.Indicies.Add(mesh.Vertices.Count); mesh.Vertices.Add(vert); } mesh.Polygons.Add(poly); } // add mesh to model model.Meshes.Add(mesh); } ; } return(scene); }
/// <summary> /// /// </summary> /// <param name="geometry"></param> /// <param name="Index"></param> /// <returns></returns> private static IOVertex CreateVertex(Matrix4 transform, FbxGeometry geometry, int Index, Vector4[] boneIndices, Vector4[] boneWeights, float scale) { int VertexIndex = geometry.Indices[Index]; if ((Index + 1) % 3 == 0) { VertexIndex = (geometry.Indices[Index] + 1) * -1; } IOVertex vertex = new IOVertex() { Position = Vector3.TransformPosition( new Vector3( (float)geometry.Vertices[VertexIndex * 3], (float)geometry.Vertices[VertexIndex * 3 + 1], (float)geometry.Vertices[VertexIndex * 3 + 2]), transform) * scale, BoneIndices = boneIndices[VertexIndex], BoneWeights = boneWeights[VertexIndex] }; vertex.Color = Vector4.One; //Deforming foreach (var layer in geometry.Layers) { int layerIndex = Index; if (!layer.ReferenceInformationType.Equals("Direct")) { layerIndex = layer.Indices[Index]; } switch (layer.Name) { case "LayerElementNormal": if (layer.Data.Length == geometry.Vertices.Length) { vertex.Normal = new Vector3((float)layer.Data[VertexIndex * 3], (float)layer.Data[VertexIndex * 3 + 1], (float)layer.Data[VertexIndex * 3 + 2]); vertex.Normal = Vector3.TransformNormal(vertex.Normal, transform); vertex.Normal.Normalize(); break; } else { vertex.Normal = new Vector3((float)layer.Data[layerIndex * 3], (float)layer.Data[layerIndex * 3 + 1], (float)layer.Data[layerIndex * 3 + 2]); vertex.Normal = Vector3.TransformNormal(vertex.Normal, transform); vertex.Normal.Normalize(); break; } case "LayerElementColor": vertex.Color = new Vector4((float)layer.Data[layerIndex * 4], (float)layer.Data[layerIndex * 4 + 1], (float)layer.Data[layerIndex * 4 + 2], (float)layer.Data[layerIndex * 4 + 3]); break; case "LayerElementUV": Vector2 uv = new Vector2((float)layer.Data[layerIndex * 2], 1 - (float)layer.Data[layerIndex * 2 + 1]); if (layer.Layer == 0) { vertex.UV0 = uv; } if (layer.Layer == 1) { vertex.UV1 = uv; } if (layer.Layer == 2) { vertex.UV2 = uv; } if (layer.Layer == 3) { vertex.UV3 = uv; } break; } } return(vertex); }