public void WriteObjNode(StreamWriter f, CgfData.ChunkNode chunkNode) // Pass a node to this to have it write to the Stream { // Console.WriteLine("\n*** Processing Chunk node {0:X}", chunkNode.id); // Console.WriteLine("*** Object ID {0:X}", chunkNode.Object); // We are only processing Nodes that have Materials. The chunkType should never be Helper. Check for Nodes to not process // This is wrong. We have to process nodes that have helpers as the mesh info for the transform. Vector3 transform = new Vector3(); transform.x = 0; // initializing the transform vector. transform.y = 0; transform.z = 0; if (cgfData.ChunkDictionary[chunkNode.Object].chunkType == ChunkType.Helper) { // This needs work. transform = cgfData.GetTransform(chunkNode, transform); return; } CgfData.ChunkMesh tmpMesh = (CgfData.ChunkMesh)cgfData.ChunkDictionary[chunkNode.Object]; // Get the Transform here. It's the node chunk Transform.m(41/42/42) divided by 100, added to the parent transform. // The transform of a child has to add the transforms of ALL the parents. Need to use regression? Maybe a while loop... if (chunkNode.Parent != 0xFFFFFFFF) { // Not the parent node. Parent node shouldn't have a transform, so no need to calculate it. // add the current node's transform to transform.x, y and z. transform = cgfData.GetTransform(chunkNode, transform); } //transform.WriteVector3(); if (cgfData.ChunkDictionary[chunkNode.Object].chunkType == ChunkType.Helper) { // This can still have transform, so need to to the transform before skipping. We should still write an empty, but..obj. Console.WriteLine("*********************Found a node chunk for a Helper (ID: {0:X}). Skipping...", tmpMesh.id); //tmpMesh.WriteChunk(); //Console.WriteLine("Node Chunk: {0}", chunkNode.Name); transform = cgfData.GetTransform(chunkNode, transform); return; } if (tmpMesh.MeshSubsets == 0) // This is probably wrong. These may be parents with no geometry, but still have an offset { Console.WriteLine("*********************Found a Mesh chunk with no Submesh ID (ID: {0:X}). Skipping...", tmpMesh.id); //tmpMesh.WriteChunk(); //Console.WriteLine("Node Chunk: {0}", chunkNode.Name); transform = cgfData.GetTransform(chunkNode, transform); return; } if (tmpMesh.VerticesData == 0 && tmpMesh.VertsUVsData == 0) // This is probably wrong. These may be parents with no geometry, but still have an offset { Console.WriteLine("*********************Found a Mesh chunk with no Vertex info (ID: {0:X}). Skipping...", tmpMesh.id); //tmpMesh.WriteChunk(); //Console.WriteLine("Node Chunk: {0}", chunkNode.Name); transform = cgfData.GetTransform(chunkNode, transform); return; } CgfData.ChunkMtlName tmpMtlName = (CgfData.ChunkMtlName)cgfData.ChunkDictionary[chunkNode.MatID]; CgfData.ChunkMeshSubsets tmpMeshSubsets = (CgfData.ChunkMeshSubsets)cgfData.ChunkDictionary[tmpMesh.MeshSubsets]; // Listed as Object ID for the Node // Going to assume that there is only one VerticesData datastream for now. Need to watch for this. // Some 801 types have vertices and not VertsUVs. //Console.WriteLine("TEMPMESH WITH NO CurrentIndicesPosition"); //tmpMesh.WriteChunk(); CgfData.ChunkDataStream tmpIndices = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMesh.IndicesData]; CgfData.ChunkDataStream tmpNormals = new CgfData.ChunkDataStream(); CgfData.ChunkDataStream tmpUVs = new CgfData.ChunkDataStream(); CgfData.ChunkDataStream tmpVertices = new CgfData.ChunkDataStream(); CgfData.ChunkDataStream tmpVertsUVs = new CgfData.ChunkDataStream(); if (tmpMesh.VerticesData != 0) { tmpVertices = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMesh.VerticesData]; } if (tmpMesh.NormalsData != 0) { tmpNormals = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMesh.NormalsData]; } if (tmpMesh.UVsData != 0) { tmpUVs = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMesh.UVsData]; } if (tmpMesh.VertsUVsData != 0) { tmpVertsUVs = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMesh.VertsUVsData]; } // We only use 3 things in obj files: vertices, normals and UVs. No need to process the Tangents. uint numChildren = chunkNode.NumChildren; // use in a for loop to print the mesh for each child for (int i = 0; i < tmpMeshSubsets.NumMeshSubset; i++) { // Write vertices data for each MeshSubSet (v) f.WriteLine("g"); if (tmpMesh.VerticesData == 0) { // Probably using VertsUVs (3.7+). Write those vertices out. Do UVs at same time. for (int j = (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j < (int)tmpMeshSubsets.MeshSubsets[i].NumVertices + (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j++) { string s4 = String.Format("v {0:F7} {1:F7} {2:F7}", tmpVertsUVs.Vertices[j].x + transform.x, tmpVertsUVs.Vertices[j].y + transform.y, tmpVertsUVs.Vertices[j].z + transform.z); f.WriteLine(s4); } f.WriteLine(); for (int j = (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j < (int)tmpMeshSubsets.MeshSubsets[i].NumVertices + (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j++) { string s4 = String.Format("vt {0:F7} {1:F7} 0", tmpVertsUVs.UVs[j].U, 1 - tmpVertsUVs.UVs[j].V); f.WriteLine(s4); } f.WriteLine(); } else { // Using Verts. Write those vertices out. for (int j = (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j < (int)tmpMeshSubsets.MeshSubsets[i].NumVertices + (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j++) { string s4 = String.Format("v {0:F7} {1:F7} {2:F7}", tmpVertices.Vertices[j].x + transform.x, tmpVertices.Vertices[j].y + transform.y, tmpVertices.Vertices[j].z + transform.z); f.WriteLine(s4); } f.WriteLine(); for (int j = (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j < (int)tmpMeshSubsets.MeshSubsets[i].NumVertices + (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j++) { string s5 = String.Format("vt {0:F7} {1:F7} 0", tmpUVs.UVs[j].U, 1 - tmpUVs.UVs[j].V); f.WriteLine(s5); } //f.WriteLine(); } // Write Normals block (vn) if (tmpMesh.NormalsData != 0) { for (int j = (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j < (int)tmpMeshSubsets.MeshSubsets[i].NumVertices + (int)tmpMeshSubsets.MeshSubsets[i].FirstVertex; j++) { string s6 = String.Format("vn {0:F7} {1:F7} {2:F7}", tmpNormals.Normals[j].x, tmpNormals.Normals[j].y, tmpNormals.Normals[j].z); f.WriteLine(s6); } } //f.WriteLine(); string s7 = String.Format("g {0}", chunkNode.Name); f.WriteLine(s7); // usemtl <number> refers to the position of this material in the .mtl file. If it's 0, it's the first entry, etc. MaterialNameArray[] if (!cgfData.MatFile.MtlFile.Exists) // No names in the material file. use the chunknode name. { // The material file doesn't have any elements with the Name of the material. Use the object name. string s_material = String.Format("usemtl {0}", cgfData.RootNode.Name); f.WriteLine(s_material); } else { string s_material = String.Format("usemtl {0}", cgfData.MatFile.MaterialNameArray[tmpMeshSubsets.MeshSubsets[i].MatID].MaterialName); f.WriteLine(s_material); } // Now write out the faces info based on the MtlName for (int j = (int)tmpMeshSubsets.MeshSubsets[i].FirstIndex; j < (int)tmpMeshSubsets.MeshSubsets[i].NumIndices + (int)tmpMeshSubsets.MeshSubsets[i].FirstIndex; j++) { string s9 = String.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", // Vertices, UVs, Normals tmpIndices.Indices[j] + 1 + cgfData.CurrentVertexPosition, tmpIndices.Indices[j + 1] + 1 + cgfData.CurrentVertexPosition, tmpIndices.Indices[j + 2] + 1 + cgfData.CurrentVertexPosition); f.WriteLine(s9); j = j + 2; } //f.WriteLine(); cgfData.TempVertexPosition += tmpMeshSubsets.MeshSubsets[i].NumVertices; // add the number of vertices so future objects can start at the right place cgfData.TempIndicesPosition += tmpMeshSubsets.MeshSubsets[i].NumIndices; // Not really used... } // Extend the current vertex, uv and normal positions by the length of those arrays. cgfData.CurrentVertexPosition = cgfData.TempVertexPosition; cgfData.CurrentIndicesPosition = cgfData.TempIndicesPosition; }
public void WriteLibrary_Geometries() { // Geometry library. this is going to be fun... Grendgine_Collada_Library_Geometries libraryGeometries = new Grendgine_Collada_Library_Geometries(); libraryGeometries.ID = cgfData.RootNode.Name; // Make a list for all the geometries objects we will need. Will convert to array at end. Define the array here as well List <Grendgine_Collada_Geometry> geometryList = new List <Grendgine_Collada_Geometry>(); // For each of the nodes, we need to write the geometry. // Need to figure out how to assign the right material to the node as well. // Use a foreach statement to get all the node chunks. This will get us the meshes, which will contain the vertex, UV and normal info. foreach (CgfData.ChunkNode nodeChunk in cgfData.CgfChunks.Where(a => a.chunkType == ChunkType.Node)) { // Create a geometry object. Use the chunk ID for the geometry ID // Will have to be careful with this, since with .cga/.cgam pairs will need to match by Name. Grendgine_Collada_Geometry tmpGeo = new Grendgine_Collada_Geometry(); tmpGeo.Name = nodeChunk.Name; tmpGeo.ID = nodeChunk.id.ToString(); // Now make the mesh object. This will have 3 sources, 1 vertices, and 1 triangles (with material ID) // If the Object ID of Node chunk points to a Helper or a Controller though, place an empty. // Will have to figure out transforms here too. Grendgine_Collada_Mesh tmpMesh = new Grendgine_Collada_Mesh(); // need to make a list of the sources and triangles to add to tmpGeo.Mesh List <Grendgine_Collada_Source> sourceList = new List <Grendgine_Collada_Source>(); List <Grendgine_Collada_Triangles> triList = new List <Grendgine_Collada_Triangles>(); CgfData.ChunkDataStream tmpNormals = new CgfData.ChunkDataStream(); CgfData.ChunkDataStream tmpUVs = new CgfData.ChunkDataStream(); CgfData.ChunkDataStream tmpVertices = new CgfData.ChunkDataStream(); CgfData.ChunkDataStream tmpVertsUVs = new CgfData.ChunkDataStream(); if (cgfData.ChunkDictionary[nodeChunk.Object].chunkType == ChunkType.Mesh) { // Get the mesh chunk and submesh chunk for this node. CgfData.ChunkMesh tmpMeshChunk = (CgfData.ChunkMesh)cgfData.ChunkDictionary[nodeChunk.Object]; CgfData.ChunkMeshSubsets tmpMeshSubsets = tmpMeshSubsets = (CgfData.ChunkMeshSubsets)cgfData.ChunkDictionary[tmpMeshChunk.MeshSubsets]; // Listed as Object ID for the Node // Get pointers to the vertices data if (tmpMeshChunk.VerticesData != 0) { tmpVertices = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMeshChunk.VerticesData]; } if (tmpMeshChunk.NormalsData != 0) { tmpNormals = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMeshChunk.NormalsData]; } if (tmpMeshChunk.UVsData != 0) { tmpUVs = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMeshChunk.UVsData]; } if (tmpMeshChunk.VertsUVsData != 0) { tmpVertsUVs = (CgfData.ChunkDataStream)cgfData.ChunkDictionary[tmpMeshChunk.VertsUVsData]; } // need a collada_source for position, normal, UV and color, what the source is (verts), and the tri index Grendgine_Collada_Source posSource = new Grendgine_Collada_Source(); Grendgine_Collada_Source normSource = new Grendgine_Collada_Source(); Grendgine_Collada_Source uvSource = new Grendgine_Collada_Source(); Grendgine_Collada_Vertices verts = new Grendgine_Collada_Vertices(); Grendgine_Collada_Triangles tris = new Grendgine_Collada_Triangles(); posSource.ID = nodeChunk.Name + "_pos"; // I want to use the chunk ID, but that may be daunting. posSource.Name = nodeChunk.Name + "_pos"; normSource.ID = nodeChunk.Name + "_norm"; normSource.Name = nodeChunk.Name + "_norm"; uvSource.Name = nodeChunk.Name + "_UV"; uvSource.ID = nodeChunk.Name + "_UV"; // Create a float_array object to store all the data Grendgine_Collada_Float_Array floatArray = new Grendgine_Collada_Float_Array(); floatArray.ID = posSource.Name + "_array"; floatArray.Count = (int)tmpVertices.NumElements; // Build the string of vertices with a stringbuilder StringBuilder vertString = new StringBuilder(); for (int i = 0; i < floatArray.Count; i++) { // this is an array of Vector3s? } //floatArray = normSource.ID = nodeChunk.Name + "_pos"; normSource.Name = nodeChunk.Name + "_pos"; uvSource.ID = nodeChunk.Name + "_UV"; uvSource.Name = nodeChunk.Name + "_UV"; // make a vertices eliment. Only one, so no list needed. // tris are easy. Just the index of faces } else if (cgfData.ChunkDictionary[nodeChunk.Object].chunkType == ChunkType.Helper) { } else if (cgfData.ChunkDictionary[nodeChunk.Object].chunkType == ChunkType.Controller) { } tmpGeo.Mesh = tmpMesh; // Add the tmpGeo geometry to the list geometryList.Add(tmpGeo); } libraryGeometries.Geometry = geometryList.ToArray(); daeObject.Library_Geometries = libraryGeometries; }