public bool eq(cOutputVertex e) { if ((s.X == e.X) && (s.Y == e.Y) && (s.Z == e.Z)) { return(true); } else { return(false); } }
public int CompareTo(object obj) { cOutputVertex c = (cOutputVertex)obj; if ((this.X == c.X) && (this.Y == c.Y) && (this.Z == c.Z)) { return(0); } else { return(-1); } }
public XYZ(cOutputVertex ss) { s = ss; }
static int Main(string[] args) { List <int> NbrVertices_x3 = new List <int>(); List <int> FaceStartIndex = new List <int>(); List <int> NbrFaces_x3 = new List <int>(); List <int> VertexStartIndex = new List <int>(); List <String> objName = new List <String>(); List <String> textureName = new List <String>(); List <objParams> ObjParamList = new List <objParams>(); List <cOutputVertex> OutputVertexList = new List <cOutputVertex>(); List <cOutputNormal> OutputNormalList = new List <cOutputNormal>(); List <cOutputUV> OutputUVList = new List <cOutputUV>(); Common.InputArguments arguments = new Common.InputArguments(args); bool verbose = arguments.Contains("v"); if (!arguments.Contains("f")) { Version version = Assembly.GetExecutingAssembly().GetName().Version; Console.WriteLine("Version {0}.{1}", version.Major, version.Minor); Console.WriteLine("Usage: c3d2obj -f <filename> | -v"); return(1); } string FileBaseName = arguments["-f"]; try { string extension = Path.GetExtension(FileBaseName); if (extension == null) { Console.WriteLine("Usage: c3d2obj -f <filename> | -v"); return(1); } else if (extension == String.Empty) { FileBaseName += ".c3d"; } else if (Path.GetExtension(FileBaseName) != ".c3d") { Console.WriteLine("Usage: c3d2obj -f <filename> | -v"); return(1); } // Open a filestream to read from FileStream fsC3DReader = new FileStream(FileBaseName, FileMode.Open); // Pass read stream to BinaryReader BinaryReader readBinary = new BinaryReader(fsC3DReader, System.Text.Encoding.GetEncoding("iso-8859-1")); // Create new file name to write to string WriteFN = Path.ChangeExtension(FileBaseName, ".obj"); // Open filestream to write to FileStream fsObjWriter = new FileStream(WriteFN, FileMode.Create); // Pass write file stream to a StreamWriter TextWriter writer = new StreamWriter(fsObjWriter); // Create new file name to write material to string MtlFN = Path.ChangeExtension(FileBaseName, ".mtl"); // Open filestream to write to FileStream fsMtlWriter = new FileStream(MtlFN, FileMode.Create); // Pass write file stream to a StreamWriter TextWriter MtlWriter = new StreamWriter(fsMtlWriter); int count = 0; try { if (readBinary.ReadInt32() != 0x01443343) { Console.Write("Not a C3D File"); throw new FormatException(); } int unknown1 = SwapEndianness(readBinary.ReadInt32()); int NbrObj = SwapEndianness(readBinary.ReadInt32()); int NbrTextures = SwapEndianness(readBinary.ReadInt32()); byte[] x = readBinary.ReadBytes(3); if (verbose) { Console.WriteLine("File contains {0} objects", NbrObj); } // For each object in the c3d file read each object's generic parameters for (count = 0; count < NbrObj; count++) { // Read the object parameters objParams objParam = new objParams(); objName.Add(readBinary.ReadString()); VertexStartIndex.Add(readBinary.ReadInt32()); NbrVertices_x3.Add(readBinary.ReadInt32()); FaceStartIndex.Add(readBinary.ReadInt32()); NbrFaces_x3.Add(readBinary.ReadInt32()); textureName.Add(readBinary.ReadString()); objParam.Red = readBinary.ReadSingle(); objParam.Green = readBinary.ReadSingle(); objParam.Blue = readBinary.ReadSingle(); objParam.Alpha = readBinary.ReadSingle(); objParam.Spec = readBinary.ReadSingle(); objParam.Shiny = readBinary.ReadSingle(); objParam.Env = readBinary.ReadSingle(); // Add this object to the list ObjParamList.Add(objParam); // Write material file MtlWriter.Write("# Blender MTL File from c3d2obj" + Environment.NewLine); MtlWriter.Write("newmtl Material_" + count.ToString() + Environment.NewLine); MtlWriter.Write("Ns 300.0" + Environment.NewLine); MtlWriter.Write("Ka 1.000000 1.000000 1.000000" + Environment.NewLine); // Ambient MtlWriter.Write("Kd " + objParam.Red.ToString("0.000000") + " " + objParam.Green.ToString("0.000000") + " " + objParam.Blue.ToString("0.000000") + Environment.NewLine); // Ambient MtlWriter.Write("Ks " + objParam.Spec.ToString("0.000000") + " " + objParam.Spec.ToString("0.000000") + " " + objParam.Spec.ToString("0.000000") + Environment.NewLine); // Ambient MtlWriter.Write("Ni 1.5" + Environment.NewLine); MtlWriter.Write("d 1.000000" + Environment.NewLine); MtlWriter.Write("illum 2" + Environment.NewLine); MtlWriter.Write("map_Kd " + textureName[count] + Environment.NewLine); } if (verbose) { Console.WriteLine(MtlFN + " written"); } // Next is the total number of vertices (over all objects) int TotalNbrVertices = readBinary.ReadInt32(); List <cVertex> VertexList = new List <cVertex>(); // Read the vertex information into VertexList for (count = 0; count < TotalNbrVertices; count++) { cVertex Vertex = new cVertex(); Vertex.Y = readBinary.ReadSingle(); Vertex.X = -readBinary.ReadSingle(); Vertex.Z = readBinary.ReadSingle(); Vertex.nY = readBinary.ReadSingle(); Vertex.nX = -readBinary.ReadSingle(); Vertex.nZ = readBinary.ReadSingle(); Vertex.U = readBinary.ReadSingle(); Vertex.V = 1.0f - readBinary.ReadSingle(); // Add this vertex to the list VertexList.Add(Vertex); } // Number of faces to end of file (triplets) int nbrFaces = readBinary.ReadInt32(); // Read face information List <cFace> FaceList = new List <cFace>(); for (int i = 0; i < nbrFaces / 3; i++) { cFace Face = new cFace(); Face.A = readBinary.ReadInt32(); Face.B = readBinary.ReadInt32(); Face.C = readBinary.ReadInt32(); FaceList.Add(Face); } // Done reading so close .c3d file fsC3DReader.Close(); /* * Now for each object we have the general information such as names and RGB values. * There is also a list of vertices with their X Y Z nX Ny nZ U and V values * For each face there is a list of indices into VertexList * * Now need to rearrange all that data into .obj format * There is a separate section for each object */ int faceIndex = 0; int UVIndex = 0; int OldUVIndex = 0; int XYZIndex = 0; int OldXYZIndex = 0; int NormalIndex = 0; int OldNormalIndex = 0; #region for each object for (int objCount = 0; objCount < NbrObj; objCount++) { // Write name of material file writer.Write("mtllib " + Path.GetFileName(MtlFN) + Environment.NewLine); writer.Write("o " + objName[objCount] + Environment.NewLine); int maxCount; maxCount = NbrVertices_x3[objCount]; // Create list of vertices with the same X Y Z values OutputVertexList.Clear(); XYZIndex = VertexStartIndex[objCount]; for (int i = 0; i < maxCount; i++) { cVertex v = VertexList[XYZIndex++]; if (!isInGeometryList(v, OutputVertexList)) { // Add current vertex to output list cOutputVertex ov = new cOutputVertex(); ov.X = v.X; ov.Y = v.Y; ov.Z = v.Z; // Add this to the OutputVertexList OutputVertexList.Add(ov); // Write v .obj record writer.Write("v " + ov.X.ToString("0.000000") + " " + ov.Z.ToString("0.000000") + " " + ov.Y.ToString("0.000000") + Environment.NewLine); } } OutputUVList.Clear(); // Create list of unique UVs UVIndex = VertexStartIndex[objCount]; for (int i = 0; i < maxCount; i++) { cVertex v = VertexList[UVIndex++]; if (!isInUVList(v, OutputUVList)) { // Add current normal to output list cOutputUV oUV = new cOutputUV(); oUV.U = v.U; oUV.V = v.V; OutputUVList.Add(oUV); writer.Write("vt " + oUV.U.ToString("0.000000") + " " + oUV.V.ToString("0.000000") + Environment.NewLine); } } // Create list of unique Normals OutputNormalList.Clear(); NormalIndex = VertexStartIndex[objCount]; for (int i = 0; i < maxCount; i++) { cVertex v = VertexList[NormalIndex++]; if (!isInNormalList(v, OutputNormalList)) { // Add current normal to output list cOutputNormal oNormal = new cOutputNormal(); oNormal.A = v.nX; oNormal.B = v.nY; oNormal.C = v.nZ; OutputNormalList.Add(oNormal); writer.Write("vn " + oNormal.A.ToString("0.000000") + " " + oNormal.C.ToString("0.000000") + " " + oNormal.B.ToString("0.000000") + Environment.NewLine); } } writer.Write("usemtl Material_" + objCount.ToString() + Environment.NewLine); writer.Write("s off" + Environment.NewLine); // No smoothing group int[] vNum = new int[3]; // vertex number int[] tNum = new int[3]; // texture int[] nNum = new int[3]; // Normal /* * for each face we need 9 numbers, which are indecies * i.e. the first vertex is number 1, the second number 2 etc. * The same applies for textures (UV coordinates) and Normals */ faceIndex = FaceStartIndex[objCount] / 3; for (int i = 0; i < NbrFaces_x3[objCount] / 3; i++) { cFace f = FaceList[faceIndex++]; // f.A is the integer index of one vertex of the face // Get the XYZ of that vertex var Coord = new cOutputVertex(); Coord.X = VertexList[f.A].X; Coord.Y = VertexList[f.A].Y; Coord.Z = VertexList[f.A].Z; var es = new XYZ(Coord); // Now find the index of that coordinate in the OutputVertexList vNum[0] = OutputVertexList.FindIndex(es.eq); if (vNum[0] == -1) { break; } vNum[0] += 1 + OldXYZIndex; Coord.X = VertexList[f.B].X; Coord.Y = VertexList[f.B].Y; Coord.Z = VertexList[f.B].Z; // Now find the index of that coordinate in the OutputVertexList vNum[1] = OutputVertexList.FindIndex(es.eq); if (vNum[1] == -1) { break; } vNum[1] += 1 + OldXYZIndex; Coord.X = VertexList[f.C].X; Coord.Y = VertexList[f.C].Y; Coord.Z = VertexList[f.C].Z; // Now find the index of that coordinate in the OutputVertexList vNum[2] = OutputVertexList.FindIndex(es.eq); if (vNum[2] == -1) { break; } vNum[2] += 1 + OldXYZIndex; var OUV = new cOutputUV(); OUV.U = VertexList[f.A].U; OUV.V = VertexList[f.A].V; var oOUV = new UV(OUV); // Now find the index of that coordinate in the OutputUVList tNum[0] = OutputUVList.FindIndex(oOUV.eq); if (tNum[0] == -1) { break; } tNum[0] += 1 + OldUVIndex; OUV.U = VertexList[f.B].U; OUV.V = VertexList[f.B].V; // Now find the index of that coordinate in the OutputUVList tNum[1] = OutputUVList.FindIndex(oOUV.eq); if (tNum[1] == -1) { break; } tNum[1] += 1 + OldUVIndex; OUV.U = VertexList[f.C].U; OUV.V = VertexList[f.C].V; // Now find the index of that coordinate in the OutputUVList tNum[2] = OutputUVList.FindIndex(oOUV.eq); if (tNum[2] == -1) { break; } tNum[2] += 1 + OldUVIndex; var ONorm = new cOutputNormal(); ONorm.A = VertexList[f.A].nX; ONorm.B = VertexList[f.A].nY; ONorm.C = VertexList[f.A].nZ; var oABC = new ABC(ONorm); // Now find the index of that coordinate in the OutputNormalList nNum[0] = OutputNormalList.FindIndex(oABC.eq); if (nNum[0] == -1) { break; } nNum[0] += 1 + OldNormalIndex; ONorm.A = VertexList[f.B].nX; ONorm.B = VertexList[f.B].nY; ONorm.C = VertexList[f.B].nZ; // Now find the index of that coordinate in the OutputNormalList nNum[1] = OutputNormalList.FindIndex(oABC.eq); if (nNum[1] == -1) { break; } nNum[1] += 1 + OldNormalIndex; ONorm.A = VertexList[f.C].nX; ONorm.B = VertexList[f.C].nY; ONorm.C = VertexList[f.C].nZ; // Now find the index of that coordinate in the OutputNormalList nNum[2] = OutputNormalList.FindIndex(oABC.eq); if (nNum[2] == -1) { break; } nNum[2] += 1 + OldNormalIndex; // The order these are written is important! writer.Write("f " + vNum[0] + "/" + tNum[0] + "/" + nNum[0] + " "); writer.Write(vNum[2] + "/" + tNum[2] + "/" + nNum[2] + " "); writer.Write(vNum[1] + "/" + tNum[1] + "/" + nNum[1] + Environment.NewLine); writer.Flush(); } OldXYZIndex += OutputVertexList.Count; OldUVIndex += OutputUVList.Count; OldNormalIndex += OutputNormalList.Count; } #endregion } catch (Exception ex) { Console.WriteLine("Oh dear something went wrong"); Console.WriteLine(ex.Message); writer.Flush(); fsObjWriter.Close(); MtlWriter.Flush(); fsMtlWriter.Close(); } writer.Flush(); fsObjWriter.Close(); MtlWriter.Flush(); fsMtlWriter.Close(); if (verbose) { Console.WriteLine(WriteFN + " written"); } Console.WriteLine("Done"); } catch (SecurityException ex) { Console.WriteLine("Security error.\n\nError message: {ex.Message}\n\n" + "Details:\n\n{ex.StackTrace}"); } return(0); }