private void LoadFromColladaSceneNode(ColladaSceneNodeBase node) { if (node.Type != ColladaSceneNodeBase.NodeType.Node && node.Type != ColladaSceneNodeBase.NodeType.Scene) { return; } // This is not correct. When using a skin there is an 'instance_controller' if (node.Instance_Geometry != null) { ColladaMesh mesh = node.Instance_Geometry; for (int iPart = 0; iPart < mesh.Parts.Count; iPart++) { ColladaMesh.PrimitiveList meshPart = mesh.Parts[iPart]; SkinnedMesh skinnedMesh = new SkinnedMesh(skinnedModel); Matrix objectMatrix = node.GetFullMatrix() * Matrix.CreateRotationX(-MathHelper.PiOver2); LoadMesh(skinnedMesh, mesh, meshPart, objectMatrix); skinnedModel.Meshes.Add(skinnedMesh); //model.FullData.ObjectMatrix = node.GetFullMatrix(); // TODO: this only counts when model is from max! //model.FullData.ObjectMatrix = model.FullData.ObjectMatrix * Matrix.CreateRotationX( -MathHelper.PiOver2 ); } } for (int iNode = 0; iNode < node.Nodes.Count; iNode++) { LoadFromColladaSceneNode(node.Nodes[iNode]); } }
public void AppendMesh(ColladaMesh mesh, Matrix worldMatrix) { Matrix normalMatrix = Matrix.Transpose(Matrix.Invert(worldMatrix)); int vertexCount = VertexData.Count; int normalCount = NormalData.Count; int texcoordCount = TexcoordData.Count; foreach (Vector3 v in mesh.VertexData) { VertexData.Add(VectorTransform(v, worldMatrix)); } foreach (Vector3 v in mesh.NormalData) { NormalData.Add(Vector3.Normalize(VectorTransform(v, normalMatrix))); } TexcoordData.AddRange(mesh.TexcoordData); foreach (int index in mesh.VertexIndices) { VertexIndices.Add(vertexCount + index); } foreach (int index in mesh.NormalIndices) { NormalIndices.Add(normalCount + index); } foreach (int index in mesh.TexcoordIndices) { TexcoordIndices.Add(texcoordCount + index); } }
public static Software.Mesh ParseCollada(String filename) { ColladaDocument doc = new ColladaDocument(filename); ColladaMesh resultMesh = new ColladaMesh(); Dictionary <String, ColladaMesh> geometryMeshes = new Dictionary <string, ColladaMesh>(); foreach (ColladaDocument.Geometry g in doc.geometries) { if (geometryMeshes.ContainsKey(g.id)) { throw new Exception("Duplicate geometry entries"); } geometryMeshes[g.id] = ExtractColladaGeometry(g); } if (doc.visualScenes.Count != 1) { throw new NotImplementedException("There has to be exactly one Visual Scene"); } foreach (ColladaDocument.Node n in doc.visualScenes[0].nodes) { HandleNode(geometryMeshes, ref resultMesh, n, Matrix.Identity); } resultMesh.BuildVertexList(); return(IndexedCollada(resultMesh.Vertices, resultMesh.Indices)); }
public ColladaGeometry(ColladaRoot collada, XElement node) : base(collada, node, "") { XElement xElement = node.Element(ColladaRoot.Namespace + "mesh"); if (xElement != null) { Mesh = new ColladaMesh(collada, xElement); } }
public void Read(XmlNode root) { id = (string)root.Attributes["id"].Value; name = (string)root.Attributes["name"].Value; mesh = new ColladaMesh(); foreach (XmlNode node in root.ChildNodes) { if (node.Name.Equals("mesh")) { mesh.Read(node); } } }
public void LoadMeshes() { //Dictionary<ColladaMaterial, EditorMaterial> materials = new Dictionary<ColladaMaterial, EditorMaterial>(); // Load all models from the scene. Each meshPart/primitivelist will become a seperate model //TODO: this does not work, now simply load every mesh found //LoadFromColladaSceneNode( colladaModel.Scene ); for (int i = 0; i < colladaModel.Meshes.Count; i++) { ColladaMesh colladaMesh = colladaModel.Meshes[i]; for (int j = 0; j < colladaMesh.Parts.Count; j++) { SkinnedMesh mesh = new SkinnedMesh(skinnedModel); skinnedModel.Meshes.Add(mesh); LoadMesh(mesh, colladaMesh, colladaMesh.Parts[j], Matrix.CreateRotationX(-MathHelper.PiOver2)); } } }
private static void HandleNode(Dictionary <string, ColladaMesh> geometryMeshes, ref ColladaMesh resultMesh, ColladaDocument.Node node, Matrix world) { if (node.transforms != null) { world = ConcatTransforms(node.transforms, world); } if (node.instances != null) { if (node.instances.Count != 1) { throw new Exception("Nodes need to have exactly one instance right now"); } if (!(node.instances[0] is ColladaDocument.InstanceGeometry)) { return; // SILENT FAIL } ColladaDocument.Instance i = node.instances[0]; ColladaMesh mesh = geometryMeshes[i.url.Fragment]; resultMesh.AppendMesh(mesh, world); if (node.children != null && node.children.Count > 0) { throw new Exception("Tell Joakim."); } } else if (node.children != null && node.children.Count > 0) { foreach (ColladaDocument.Node n in node.children) { HandleNode(geometryMeshes, ref resultMesh, n, world); } } else { //throw new Exception("Node has no instance and no child. Keh?"); } }
public static Software.Mesh ParseCollada(String filename) { ColladaDocument doc = new ColladaDocument(filename); ColladaMesh resultMesh = new ColladaMesh(); Dictionary<String, ColladaMesh> geometryMeshes = new Dictionary<string, ColladaMesh>(); foreach (ColladaDocument.Geometry g in doc.geometries) { if (geometryMeshes.ContainsKey(g.id)) throw new Exception("Duplicate geometry entries"); geometryMeshes[g.id] = ExtractColladaGeometry(g); } if (doc.visualScenes.Count != 1) throw new NotImplementedException("There has to be exactly one Visual Scene"); foreach (ColladaDocument.Node n in doc.visualScenes[0].nodes) HandleNode(geometryMeshes, ref resultMesh, n, Matrix.Identity); resultMesh.BuildVertexList(); return IndexedCollada(resultMesh.Vertices, resultMesh.Indices); }
private static ColladaMesh ExtractColladaGeometry(ColladaDocument.Geometry g) { ColladaMesh mesh = new ColladaMesh(); var m = g.mesh; Vector3[] vertexData = null; Vector3[] normalData = null; Vector3[] texcoordData = null; if (m.primitives.Count != 1) { throw new NotImplementedException("m.primitives.Count = " + m.primitives.Count); } var p = m.primitives[0]; Dictionary <string, float[]> data = new Dictionary <string, float[]>(); for (int i = 0; i < m.sources.Count; i++) { ColladaDocument.Array <float> inputArr = (ColladaDocument.Array <float>)m.sources[i].array; if (data.ContainsKey(m.sources[i].id)) { throw new Exception("A data entry called " + m.sources[i].id + " has already been parsed."); } data[m.sources[i].id] = inputArr.arr; } int indlen = p.p.Length / p.stride; int[] vertexIndices = new int[indlen]; int[] normalIndices = new int[indlen]; int[] texcoordIndices = new int[indlen]; foreach (ColladaDocument.Input input in p.Inputs) { switch (input.semantic.ToLower()) { case "vertex": if (!(input.source is ColladaDocument.Vertices)) { throw new Exception("VERTEX source should be of type ColladaDocument.Vertices"); } ProcessVertex((ColladaDocument.Vertices)input.source, p.p, p.stride, input.offset, data, ref vertexData, ref vertexIndices, ref normalData, ref normalIndices, ref texcoordData, ref texcoordIndices); break; case "normal": if (!(input.source is ColladaDocument.Source)) { throw new Exception("NORMAL source should be of type ColladaDocument.Vertices"); } var nsource = (ColladaDocument.Source)input.source; // set up indices for (int i = 0; i < indlen; i++) { normalIndices[i] = p.p[i * p.stride + input.offset]; } // load data normalData = ParseNormalData(data[nsource.id]); break; case "texcoord": if (!(input.source is ColladaDocument.Source)) { throw new Exception("TEXCOORD source should be of type ColladaDocument.Vertices"); } var tsource = (ColladaDocument.Source)input.source; // set up indices for (int i = 0; i < indlen; i++) { texcoordIndices[i] = p.p[i * p.stride + input.offset]; } // load data texcoordData = ParseTexcoordData(data[tsource.id], tsource.accessor.stride); break; default: throw new NotImplementedException(); } } if (vertexIndices.Length != normalIndices.Length || normalIndices.Length != texcoordIndices.Length) { throw new NotImplementedException("all of them needs to be supplied and of the same amount right now"); } mesh.VertexData = new List <Vector3>(vertexData); mesh.VertexIndices = new List <int>(vertexIndices); if (normalData != null) { mesh.NormalData = new List <Vector3>(normalData); mesh.NormalIndices = new List <int>(normalIndices); } if (texcoordData != null) { mesh.TexcoordData = new List <Vector3>(texcoordData); mesh.TexcoordIndices = new List <int>(texcoordIndices); } return(mesh); }
private void LoadMesh(SkinnedMesh mesh, ColladaMesh colladaMesh, ColladaMesh.PrimitiveList primitives, Matrix objectMatrix) { //EDIT: the vertices now include the objectmatrix, so this is always identity objectMatrix = colladaMesh.objectMatrix; mesh.Shader.World = Matrix.Identity; mesh.Primitives = new Primitives(); mesh.Primitives.PrimitiveCount = primitives.PrimitiveCount; mesh.Primitives.VertexCount = primitives.PrimitiveCount * 3; if (primitives.PrimitiveCount * 3 >= int.MaxValue) { throw new Exception("Too many vertices"); } int numVertices = primitives.PrimitiveCount * 3; // TODO check if all inputs are available /*if ( meshPart.ContainsInput( ColladaMesh.Input.InputSemantics.Position ) ) positions = new Vector3[ numVertices ]; * if ( meshPart.ContainsInput( ColladaMesh.Input.InputSemantics.Normal ) ) normals = new Vector3[ numVertices ]; * if ( meshPart.ContainsInput( ColladaMesh.Input.InputSemantics.Texcoord, 1 ) ) texCoords = new Vector3[ numVertices ]; * if ( meshPart.ContainsInput( ColladaMesh.Input.InputSemantics.TexTangent, 1 ) ) tangents = new Vector3[ numVertices ];*/ SkinnedTangentVertex[] vertices = new SkinnedTangentVertex[numVertices]; for (int i = 0; i < numVertices; i++) { SkinnedTangentVertex v = new SkinnedTangentVertex(); v.pos = primitives.GetVector3(ColladaMesh.Input.InputSemantics.Position, i); //GetPosition( i ); v.normal = primitives.GetVector3(ColladaMesh.Input.InputSemantics.Normal, i); // Texture Coordinates Vector3 texcoord = Vector3.Zero; if (primitives.ContainsInput(ColladaMesh.Input.InputSemantics.Texcoord, 1)) { texcoord = primitives.GetVector3(ColladaMesh.Input.InputSemantics.Texcoord, 1, i); texcoord.Y = 1.0f - texcoord.Y; // V coordinate is inverted in max } v.uv = new Vector2(texcoord.X, texcoord.Y); // Tangent Vector3 tangent = Vector3.Zero; if (primitives.ContainsInput(ColladaMesh.Input.InputSemantics.TexTangent, 1)) { v.tangent = primitives.GetVector3(ColladaMesh.Input.InputSemantics.TexTangent, 1, i); } // Bone weights and joint indices int positionIndex = primitives.GetSourceIndex( primitives.GetInput(ColladaMesh.Input.InputSemantics.Position), i); // WARNING: THIS IS EXTREMELY IMPORTANT AND COSTED MORE THAN 6 HOURS DEBUGGING // Indexes are PREMULTIPLIED BY 3!!! v.blendIndices = colladaMesh.vertexSkinJoints[positionIndex]; //v.blendIndices = Vector3.One; v.blendIndices = v.blendIndices * 3; v.blendWeights = colladaMesh.vertexSkinWeights[positionIndex]; v.pos = Vector3.Transform(v.pos, objectMatrix); v.normal = Vector3.Transform(v.normal, objectMatrix); vertices[i] = v; } //vertices[ 0 ].pos = Vector3.Transform( Vector3.Zero, Matrix.Invert( objectMatrix ) ); //vertices[ 0 ].pos = Vector3.Zero; mesh.Primitives.InitializeFromVertices(skinnedModel.Game, vertices, SkinnedTangentVertex.SizeInBytes); //CalculateBoundingBox(); //CalculateBoundingSphere(); //TODO: Material, maybe not really a good way of doing this //LoadDataFromColladaMaterial( meshPart.Material ); }
private static ColladaMesh ExtractColladaGeometry(ColladaDocument.Geometry g) { ColladaMesh mesh = new ColladaMesh(); var m = g.mesh; Vector3[] vertexData = null; Vector3[] normalData = null; Vector3[] texcoordData = null; if (m.primitives.Count != 1) throw new NotImplementedException("m.primitives.Count = " + m.primitives.Count); var p = m.primitives[0]; Dictionary<string, float[]> data = new Dictionary<string, float[]>(); for (int i = 0; i < m.sources.Count; i++) { ColladaDocument.Array<float> inputArr = (ColladaDocument.Array<float>)m.sources[i].array; if (data.ContainsKey(m.sources[i].id)) throw new Exception("A data entry called " + m.sources[i].id + " has already been parsed."); data[m.sources[i].id] = inputArr.arr; } int indlen = p.p.Length / p.stride; int[] vertexIndices = new int[indlen]; int[] normalIndices = new int[indlen]; int[] texcoordIndices = new int[indlen]; foreach (ColladaDocument.Input input in p.Inputs) { switch (input.semantic.ToLower()) { case "vertex": if (!(input.source is ColladaDocument.Vertices)) throw new Exception("VERTEX source should be of type ColladaDocument.Vertices"); ProcessVertex((ColladaDocument.Vertices)input.source, p.p, p.stride, input.offset, data, ref vertexData, ref vertexIndices, ref normalData, ref normalIndices, ref texcoordData, ref texcoordIndices); break; case "normal": if (!(input.source is ColladaDocument.Source)) throw new Exception("NORMAL source should be of type ColladaDocument.Vertices"); var nsource = (ColladaDocument.Source)input.source; // set up indices for (int i = 0; i < indlen; i++) normalIndices[i] = p.p[i * p.stride + input.offset]; // load data normalData = ParseNormalData(data[nsource.id]); break; case "texcoord": if (!(input.source is ColladaDocument.Source)) throw new Exception("TEXCOORD source should be of type ColladaDocument.Vertices"); var tsource = (ColladaDocument.Source)input.source; // set up indices for (int i = 0; i < indlen; i++) texcoordIndices[i] = p.p[i * p.stride + input.offset]; // load data texcoordData = ParseTexcoordData(data[tsource.id], tsource.accessor.stride); break; default: throw new NotImplementedException(); } } if (vertexIndices.Length != normalIndices.Length || normalIndices.Length != texcoordIndices.Length) throw new NotImplementedException("all of them needs to be supplied and of the same amount right now"); mesh.VertexData = new List<Vector3>(vertexData); mesh.VertexIndices = new List<int>(vertexIndices); if (normalData != null) { mesh.NormalData = new List<Vector3>(normalData); mesh.NormalIndices = new List<int>(normalIndices); } if (texcoordData != null) { mesh.TexcoordData = new List<Vector3>(texcoordData); mesh.TexcoordIndices = new List<int>(texcoordIndices); } return mesh; }
public void AppendMesh(ColladaMesh mesh, Matrix worldMatrix) { Matrix normalMatrix = Matrix.Transpose(Matrix.Invert(worldMatrix)); int vertexCount = VertexData.Count; int normalCount = NormalData.Count; int texcoordCount = TexcoordData.Count; foreach (Vector3 v in mesh.VertexData) VertexData.Add(VectorTransform(v, worldMatrix)); foreach (Vector3 v in mesh.NormalData) NormalData.Add(Vector3.Normalize(VectorTransform(v, normalMatrix))); TexcoordData.AddRange(mesh.TexcoordData); foreach (int index in mesh.VertexIndices) VertexIndices.Add(vertexCount + index); foreach (int index in mesh.NormalIndices) NormalIndices.Add(normalCount + index); foreach (int index in mesh.TexcoordIndices) TexcoordIndices.Add(texcoordCount + index); }
private static void HandleNode(Dictionary<string, ColladaMesh> geometryMeshes, ref ColladaMesh resultMesh, ColladaDocument.Node node, Matrix world) { if(node.transforms != null) world = ConcatTransforms(node.transforms, world); if (node.instances != null) { if (node.instances.Count != 1) throw new Exception("Nodes need to have exactly one instance right now"); if (!(node.instances[0] is ColladaDocument.InstanceGeometry)) return; // SILENT FAIL ColladaDocument.Instance i = node.instances[0]; ColladaMesh mesh = geometryMeshes[i.url.Fragment]; resultMesh.AppendMesh(mesh, world); if (node.children != null && node.children.Count > 0) throw new Exception("Tell Joakim."); } else if (node.children != null && node.children.Count > 0) { foreach (ColladaDocument.Node n in node.children) HandleNode(geometryMeshes, ref resultMesh, n, world); } else { //throw new Exception("Node has no instance and no child. Keh?"); } }