public void ConvertFile(string inputPath, string exportPath) { exportPath = exportPath + "\\" + Path.GetFileNameWithoutExtension(inputPath) + ".lwo"; XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(File.ReadAllText(inputPath)); FileStream fileStream = new FileStream(exportPath, FileMode.Create); BinaryWriter binaryWriter = new BinaryWriter2(fileStream); binaryWriter.Write("FORMtempLWOB".ToCharArray()); foreach (XmlNode chunk in xmlDocument.DocumentElement.ChildNodes) { ReadChunk(chunk, fileStream, binaryWriter); } // Final length fileStream.Seek(4, SeekOrigin.Begin); binaryWriter.Write((UInt32)(fileStream.Length - 8)); binaryWriter.Close(); fileStream.Close(); }
public void SaveGC(string path) { if (Wumpas.Count > 256) { while (Wumpas.Count > 256) { Wumpas.RemoveAt(255); } } using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { BinaryWriter2 writer = new BinaryWriter2(fileStream); writer.Write(Wumpas.Count); for (int i = 0; i < Wumpas.Count; i++) { writer.Write(Wumpas[i].X); writer.Write(Wumpas[i].Y); writer.Write(Wumpas[i].Z); } } }
public void Save(Stream stream) { BinaryWriter2 bw = new BinaryWriter2(stream); bw.Write(_version); bw.Write7BitEncodedInt(_data.Count); foreach (var file in _data.Values) { bw.Write(file.hash); bw.Write(file.mode); bw.Write(file.crc32); bw.Write7BitEncodedInt(file.size); if (file.mode == MODE_ORGINAL) { bw.Write(file.origin); } } bw.Flush(); }
static void SaveLWO(bool exportUV) { // Error check if (Selection.activeTransform == null) { Debug.LogWarning("Please select the model you want to export"); return; } // Get stuff GameObject parent = Selection.activeTransform.gameObject; string modelName = parent.name; MeshRenderer[] meshRenderers = parent.GetComponentsInChildren <MeshRenderer>(); // Loop through stuff List <Material> surfaces = new List <Material>(); List <string> surfaceNames = new List <string>(); CustomMesh mesh = new CustomMesh(); int vertBoost = 0; for (int i = 0; i < meshRenderers.Length; i++) { // Get MeshFilter MeshFilter meshFilter = meshRenderers[i].gameObject.GetComponent <MeshFilter>(); if (meshFilter.sharedMesh.subMeshCount != meshRenderers[i].sharedMaterials.Length) { Debug.LogError("SubMesh count and material count don't match on " + meshRenderers[i].gameObject.name); return; } // Fill out surface lists foreach (Material material in meshRenderers[i].sharedMaterials) { // Moar error check if (material == null) { Debug.LogError("Material slot is null on " + meshRenderers[i].gameObject.name); return; } if (material.shader.name != "Rock Raiders" && material.shader.name != "Rock Raiders Transparent") { Debug.LogError(material.name + " doesn't use a Rock Raiders shader"); return; } // Surface stuff if (!surfaceNames.Contains(material.name)) { surfaces.Add(material); surfaceNames.Add(material.name); } } // Fill out our CustomMesh // verts foreach (Vector3 vertex in meshFilter.sharedMesh.vertices) { mesh.vertices.Add(meshFilter.gameObject.transform.TransformPoint(vertex)); } // normals - these won't be exported, but used later for determining which verts to merge in the LWO, so the smoothing the game calculates is correct if (meshFilter.sharedMesh.normals.Length == 0) { // default normals - zero is fine for this, the actual value doesn't really matter, we're only gonna be checking if verts have equal normals to each other for (int j = 0; j < meshFilter.sharedMesh.vertices.Length; j++) { mesh.normals.Add(Vector3.zero); } } else { // use normals if present foreach (Vector3 normal in meshFilter.sharedMesh.normals) { mesh.normals.Add(normal); } } // UV if (meshFilter.sharedMesh.uv.Length == 0) { // default UVs for (int j = 0; j < meshFilter.sharedMesh.vertices.Length; j++) { // these will be 0, 0 in the final UV file once flipped mesh.uv.Add(new Vector2(0.0f, 1.0f)); } } else { // use UVs if present foreach (Vector2 uv in meshFilter.sharedMesh.uv) { mesh.uv.Add(uv); } } // tris/submeshes for (int j = 0; j < meshFilter.sharedMesh.subMeshCount; j++) { SubMesh subMesh = new SubMesh(); subMesh.triangles = meshFilter.sharedMesh.GetTriangles(j); // reverse winding order for negative scale if (meshFilter.gameObject.transform.localToWorldMatrix.determinant < 0.0f) { for (int k = 0; k < subMesh.triangles.Length; k += 3) { int temp = subMesh.triangles[k]; subMesh.triangles[k] = subMesh.triangles[k + 2]; subMesh.triangles[k + 2] = temp; } } // vert boost for (int k = 0; k < subMesh.triangles.Length; k++) { subMesh.triangles[k] += vertBoost; } subMesh.material = meshRenderers[i].sharedMaterials[j]; mesh.subMeshes.Add(subMesh); } vertBoost += meshFilter.sharedMesh.vertices.Length; } // make condensed list of verts with only those that have different positions and normals (no UV splits etc) - so only intentionally unwelded verts will be unwelded in the LWO List <Vertex> uniqueVerts = new List <Vertex>(); int[] redirectArray = new int[mesh.vertices.Count]; for (int i = 0; i < mesh.vertices.Count; i++) { Vertex vertex; vertex.position = mesh.vertices[i]; vertex.normal = mesh.normals[i]; if (!uniqueVerts.Contains(vertex)) { uniqueVerts.Add(vertex); } int newVertexIndex; int findResults = uniqueVerts.IndexOf(vertex); if (findResults == -1) { uniqueVerts.Add(vertex); newVertexIndex = uniqueVerts.Count - 1; } else { newVertexIndex = findResults; } redirectArray[i] = newVertexIndex; } // Get path string path = EditorUtility.SaveFilePanel("Save LWO", "", modelName + ".lwo", "lwo"); if (string.IsNullOrEmpty(path)) { return; } // Start writing stuff FileStream fileStream = new FileStream(path, FileMode.Create); BinaryWriter binaryWriter = new BinaryWriter2(fileStream); long rememberMe; binaryWriter.Write("FORMtempLWOB".ToCharArray()); // PNTS binaryWriter.Write("PNTS".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; foreach (Vertex vertex in uniqueVerts) { binaryWriter.Write(-vertex.position.x); binaryWriter.Write(vertex.position.y); binaryWriter.Write(-vertex.position.z); } FinishWritingChunk(fileStream, binaryWriter, rememberMe); // SRFS binaryWriter.Write("SRFS".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; foreach (string surfaceName in surfaceNames) { binaryWriter.Write(surfaceName.ToCharArray()); binaryWriter.Write('\0'); // padding if (surfaceName.Length % 2 == 0) { binaryWriter.Write('\0'); } } FinishWritingChunk(fileStream, binaryWriter, rememberMe); // POLS binaryWriter.Write("POLS".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; for (int i = 0; i < mesh.subMeshes.Count; i++) { int surfaceIndex = surfaceNames.IndexOf(mesh.subMeshes[i].material.name) + 1; int[] tris = mesh.subMeshes[i].triangles; for (int j = 0; j < tris.Length; j += 3) { binaryWriter.Write((UInt16)3); // How many verts binaryWriter.Write((UInt16)redirectArray[tris[j]]); binaryWriter.Write((UInt16)redirectArray[tris[j + 1]]); binaryWriter.Write((UInt16)redirectArray[tris[j + 2]]); binaryWriter.Write((UInt16)surfaceIndex); } } FinishWritingChunk(fileStream, binaryWriter, rememberMe); // SURFs foreach (Material surface in surfaces) { binaryWriter.Write("SURF".ToCharArray()); // Temp length binaryWriter.Write("temp".ToCharArray()); rememberMe = fileStream.Position; binaryWriter.Write(surface.name.ToCharArray()); binaryWriter.Write('\0'); // padding if (surface.name.Length % 2 == 0) { binaryWriter.Write('\0'); } // COLR binaryWriter.Write("COLR".ToCharArray()); binaryWriter.Write((UInt16)4); Color32 color = (Color32)surface.GetColor("_Color"); binaryWriter.Write(color.r); binaryWriter.Write(color.g); binaryWriter.Write(color.b); binaryWriter.Write((byte)0); // FLAG binaryWriter.Write("FLAG".ToCharArray()); binaryWriter.Write((UInt16)2); int flag = 0; if (surface.GetFloat("_Luminosity") != 0.0f) { flag++; } flag += 4; // smoothing if (surface.GetFloat("_Additive") != 0.0f) { flag += 512; } binaryWriter.Write((UInt16)flag); // DIFF if (surface.GetFloat("_Diffuse") != 0.0f) { binaryWriter.Write("DIFF".ToCharArray()); binaryWriter.Write((UInt16)2); binaryWriter.Write((UInt16)(surface.GetFloat("_Diffuse") * 256.0f)); } // TRAN if (surface.GetFloat("_Transparency") != 0.0f) { binaryWriter.Write("TRAN".ToCharArray()); binaryWriter.Write((UInt16)2); binaryWriter.Write((UInt16)(surface.GetFloat("_Transparency") * 256.0f)); } // LUMI if (surface.GetFloat("_Luminosity") != 0.0f) { binaryWriter.Write("LUMI".ToCharArray()); binaryWriter.Write((UInt16)2); binaryWriter.Write((UInt16)(surface.GetFloat("_Luminosity") * 256.0f)); } if (!exportUV && surface.GetTexture("_MainTex") != null) { // CTEX binaryWriter.Write("CTEX".ToCharArray()); binaryWriter.Write((UInt16)18); binaryWriter.Write("Planar Image Map".ToCharArray()); binaryWriter.Write('\0'); binaryWriter.Write('\0'); // TIMG binaryWriter.Write("TIMG".ToCharArray()); // Temp length binaryWriter.Write("te".ToCharArray()); long rememberMe2 = fileStream.Position; string texturePath = null; string sequence; if (surface.GetFloat("_Sequence") != 0.0f) { sequence = " (sequence)"; } else { sequence = ""; } if (surface.GetFloat("_SharedTexture") != 0.0f) { texturePath = @"\\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } else { texturePath = @"D:\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } binaryWriter.Write(texturePath.ToCharArray()); binaryWriter.Write('\0'); // padding if (texturePath.Length % 2 == 0) { binaryWriter.Write('\0'); } FinishWritingSurfChunk(fileStream, binaryWriter, rememberMe2); // TFLG binaryWriter.Write("TFLG".ToCharArray()); binaryWriter.Write((UInt16)2); int textureFlag = 0; if (surface.GetFloat("_X") != 0.0f) { textureFlag++; } else if (surface.GetFloat("_Y") != 0.0f) { textureFlag += 2; } else if (surface.GetFloat("_Z") != 0.0f) { textureFlag += 4; } else { // default to z like the game seems to do if none are specified textureFlag += 4; } if (surface.GetFloat("_PixelBlending") != 0.0f) { textureFlag += 32; } binaryWriter.Write((UInt16)textureFlag); // TSIZ binaryWriter.Write("TSIZ".ToCharArray()); binaryWriter.Write((UInt16)12); binaryWriter.Write(surface.GetFloat("_TextureSizeX")); binaryWriter.Write(surface.GetFloat("_TextureSizeY")); binaryWriter.Write(surface.GetFloat("_TextureSizeZ")); // TCTR binaryWriter.Write("TCTR".ToCharArray()); binaryWriter.Write((UInt16)12); binaryWriter.Write(surface.GetFloat("_TextureCenterX")); binaryWriter.Write(surface.GetFloat("_TextureCenterY")); binaryWriter.Write(surface.GetFloat("_TextureCenterZ")); } FinishWritingChunk(fileStream, binaryWriter, rememberMe); } // Final length fileStream.Seek(4, SeekOrigin.Begin); binaryWriter.Write((UInt32)(fileStream.Length - 8)); binaryWriter.Close(); fileStream.Close(); Debug.Log("Saved file " + path); // UV TIME if (!exportUV) { return; } StringBuilder uvString = new StringBuilder(); uvString.Append("2\n"); uvString.Append(surfaces.Count).Append("\n"); foreach (string surfaceName in surfaceNames) { uvString.Append(surfaceName).Append("\n"); } foreach (Material surface in surfaces) { string texturePath; string sequence; if (surface.GetFloat("_Sequence") != 0.0f) { sequence = " (sequence)"; } else { sequence = ""; } if (surface.GetTexture("_MainTex") == null) { texturePath = "NULL"; } else if (surface.GetFloat("_SharedTexture") != 0.0f) { texturePath = @"\\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } else { texturePath = @"D:\dummy\" + surface.GetTexture("_MainTex").name + ".bmp" + sequence; } uvString.Append(texturePath).Append("\n"); } int totalIndexCount = 0; foreach (SubMesh subMesh in mesh.subMeshes) { totalIndexCount += subMesh.triangles.Length; } uvString.Append(totalIndexCount / 3).Append("\n"); int whatever = 0; foreach (SubMesh subMesh in mesh.subMeshes) { for (int i = 0; i < subMesh.triangles.Length; i += 3) { uvString.Append(whatever).Append(" 3\n"); uvString.Append(mesh.uv[subMesh.triangles[i]].x).Append(" ").Append(-mesh.uv[subMesh.triangles[i]].y + 1.0f).Append(" 0\n"); uvString.Append(mesh.uv[subMesh.triangles[i + 1]].x).Append(" ").Append(-mesh.uv[subMesh.triangles[i + 1]].y + 1.0f).Append(" 0\n"); uvString.Append(mesh.uv[subMesh.triangles[i + 2]].x).Append(" ").Append(-mesh.uv[subMesh.triangles[i + 2]].y + 1.0f).Append(" 0\n"); whatever++; } } // dummy data for (int i = 0; i < surfaces.Count; i++) { uvString.Append("4\n0.000000 0.000000 0.000000\n0.000000 0.000000 0.000000\n0.000000 0.000000 0.000000\n1.000000 1.000000 1.000000\n"); } string uvPath = Path.ChangeExtension(path, ".uv"); File.WriteAllText(uvPath, uvString.ToString()); Debug.Log("Saved file " + uvPath); }