public static void WriteObj(FileInfo file, IGeometryData geo) { var meshes = new List <WriteMesh>(); var mesh = new SimpleMesh(); var map = new Dictionary <Vector3, int>(); var indeces = new List <int>(); for (var index = 0; index < geo.Positions.Length; index++) { var v = geo.Positions[index]; if (!map.ContainsKey(v)) { map.Add(v, map.Count); } } for (var index = 0; index < geo.Indices.Length; index++) { var i = geo.Indices[index]; var v = geo.Positions[i]; indeces.Add(map[v]); } var points = map.Keys.ToArray(); var pcount = points.Length * 3; var pp = new double[pcount]; var pindex = 0; for (var index = 0; index < points.Length; index++) { var v = points[index]; pp[pindex++] = v.X; pp[pindex++] = v.Y; pp[pindex++] = v.Z; } mesh.Initialize(new VectorArray3d(pp), new VectorArray3i(indeces.ToArray())); meshes.Add(new WriteMesh(mesh, $"d3dlab export")); StandardMeshWriter.WriteFile(file.FullName, meshes, WriteOptions.Defaults); }
public virtual SimpleMesh RestoreSimpleMesh(TypedAttribSet attributes, bool bSwapRightLeft) { bool bBinary = true; TypedAttribSet meshAttr = find_struct(attributes, IOStrings.BinaryMeshStruct); if (meshAttr == null) { meshAttr = find_struct(attributes, IOStrings.AsciiMeshStruct); bBinary = false; } if (meshAttr == null) { throw new Exception("SOFactory.RestoreSimpleMesh: Mesh ascii/binary struct not found!"); } VectorArray3d v = null; VectorArray3i t = null; VectorArray3f n = null, c = null; VectorArray2f uv = null; if (bBinary) { if (check_key_or_debug_print(meshAttr, IOStrings.AMeshVertices3Binary)) { v = meshAttr[IOStrings.AMeshVertices3Binary] as VectorArray3d; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshTrianglesBinary)) { t = meshAttr[IOStrings.AMeshTrianglesBinary] as VectorArray3i; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshNormals3Binary)) { n = meshAttr[IOStrings.AMeshNormals3Binary] as VectorArray3f; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshColors3Binary)) { c = meshAttr[IOStrings.AMeshColors3Binary] as VectorArray3f; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshUVs2Binary)) { uv = meshAttr[IOStrings.AMeshUVs2Binary] as VectorArray2f; } } else { if (check_key_or_debug_print(meshAttr, IOStrings.AMeshVertices3)) { v = meshAttr[IOStrings.AMeshVertices3] as VectorArray3d; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshTriangles)) { t = meshAttr[IOStrings.AMeshTriangles] as VectorArray3i; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshNormals3)) { n = meshAttr[IOStrings.AMeshNormals3] as VectorArray3f; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshColors3)) { c = meshAttr[IOStrings.AMeshColors3] as VectorArray3f; } if (check_key_or_debug_print(meshAttr, IOStrings.AMeshUVs2)) { uv = meshAttr[IOStrings.AMeshUVs2] as VectorArray2f; } } if (v == null || t == null) { return(null); } if (bSwapRightLeft) { int N = v.Count; for (int i = 0; i < N; ++i) { Vector3d vv = v[i]; v.Set(i, -vv.x, vv.y, -vv.z); } if (n != null && n.Count == N) { for (int i = 0; i < N; ++i) { Vector3f nn = n[i]; n.Set(i, -nn.x, nn.y, -nn.z); } } } SimpleMesh m = new SimpleMesh(); m.Initialize(v, t, n, c, uv); return(m); }
public virtual ExportStatus Export(FScene scene, string filename) { int[] vertexMap = new int[2048]; // temp List <WriteMesh> vMeshes = new List <WriteMesh>(); if (WriteFaceGroups) { throw new Exception("SceneMeshExporter.Export: writing face groups has not yet been implemented!"); } // extract all the mesh data we want to export foreach (SceneObject so in scene.SceneObjects) { if (so.IsTemporary || so.IsSurface == false || SceneUtil.IsVisible(so) == false) { continue; } if (SOFilterF != null && SOFilterF(so) == false) { continue; } // if this SO has an internal mesh we can just copy, use it if (so is DMeshSO) { DMeshSO meshSO = so as DMeshSO; // todo: flags // make a copy of mesh DMesh3 m = new DMesh3(meshSO.Mesh, true); // transform to scene coords and swap left/right foreach (int vid in m.VertexIndices()) { Vector3f v = (Vector3f)m.GetVertex(vid); v = SceneTransforms.ObjectToScene(meshSO, v); v = UnityUtil.SwapLeftRight(v); m.SetVertex(vid, v); } m.ReverseOrientation(); vMeshes.Add(new WriteMesh(m, so.Name)); } // Look for lower-level fGameObject items to export. By default // this is anything with a MeshFilter, override CollectGOChildren // or use GOFilterF to add restrictions List <fGameObject> vExports = CollectGOChildren(so); if (vExports.Count > 0) { SimpleMesh m = new SimpleMesh(); m.Initialize(WriteNormals, WriteVertexColors, WriteUVs, WriteFaceGroups); int groupCounter = 1; foreach (fGameObject childgo in vExports) { if (GOFilterF != null && GOFilterF(so, childgo) == false) { continue; } if (AppendGOMesh(childgo, m, vertexMap, scene, groupCounter)) { groupCounter++; } } vMeshes.Add(new WriteMesh(m, so.Name)); } } // ok, we are independent of Scene now and can write in bg thread if (WriteInBackgroundThreads) { ExportStatus status = new ExportStatus() { Exporter = this, IsComputing = true }; WriteOptions useOptions = Options; useOptions.ProgressFunc = (cur, max) => { status.Progress = cur; status.MaxProgress = max; }; BackgroundWriteThread t = new BackgroundWriteThread() { Meshes = vMeshes, options = useOptions, Filename = filename, CompletionF = (result) => { LastWriteStatus = result.code; LastErrorMessage = result.message; status.LastErrorMessage = result.message; status.Ok = (result.code == IOCode.Ok); status.IsComputing = false; if (BackgroundWriteCompleteF != null) { BackgroundWriteCompleteF(this, status); } } }; t.Start(); return(status); } else { IOWriteResult result = StandardMeshWriter.WriteFile(filename, vMeshes, Options); LastWriteStatus = result.code; LastErrorMessage = result.message; return(new ExportStatus() { Exporter = this, IsComputing = false, Ok = (result.code == IOCode.Ok), LastErrorMessage = result.message }); } }
public static SimpleMesh UnityMeshToSimpleMesh(UnityEngine.Mesh mesh, bool bSwapLeftright) { SimpleMesh smesh = new SimpleMesh(); Vector3[] vertices = mesh.vertices; Vector3[] normals = mesh.normals; Color32[] colors32 = mesh.colors32; Color[] colors = mesh.colors; Vector2[] uv = mesh.uv; bool bNormals = (normals.Length == mesh.vertexCount); bool bColors = (colors.Length == mesh.vertexCount || colors32.Length == mesh.vertexCount); bool bByteColors = (colors32.Length == mesh.vertexCount); bool bUVs = (uv.Length == mesh.vertexCount); smesh.Initialize(bNormals, bColors, bUVs, false); for (int i = 0; i < mesh.vertexCount; ++i) { Vector3d v = vertices[i]; if (bSwapLeftright) { v.x = -v.x; v.z = -v.z; } NewVertexInfo vInfo = new NewVertexInfo(v); if (bNormals) { vInfo.bHaveN = true; vInfo.n = normals[i]; if (bSwapLeftright) { vInfo.n.x = -vInfo.n.x; vInfo.n.z = -vInfo.n.z; } } if (bColors) { vInfo.bHaveC = true; if (bByteColors) { vInfo.c = new Colorf(colors32[i].r, colors32[i].g, colors32[i].b, 255); } else { vInfo.c = colors[i]; } } if (bUVs) { vInfo.bHaveUV = true; vInfo.uv = uv[i]; } int vid = smesh.AppendVertex(vInfo); if (vid != i) { throw new InvalidOperationException("UnityUtil.UnityMeshToSimpleMesh: indices weirdness..."); } } int[] triangles = mesh.triangles; for (int i = 0; i < triangles.Length / 3; ++i) { smesh.AppendTriangle(triangles[3 * i], triangles[3 * i + 1], triangles[3 * i + 2]); } return(smesh); }
public ExportStatus Export(FScene s, string filename) { List <WriteMesh> vMeshes = new List <WriteMesh>(); if (WriteFaceGroups) { throw new Exception("SceneMeshExporter.Export: writing face groups has not yet been implemented!"); } foreach (SceneObject so in s.SceneObjects) { if (so.IsTemporary) { continue; } SimpleMesh m = new SimpleMesh(); m.Initialize(WriteNormals, WriteVertexColors, WriteUVs, WriteFaceGroups); int groupCounter = 1; GameObject rootgo = so.RootGameObject; int[] vertexMap = new int[2048]; foreach (GameObject childgo in rootgo.Children()) { MeshFilter filter = childgo.GetComponent <MeshFilter>(); if (filter == null || filter.mesh == null) { continue; } if (GOFilterF != null && GOFilterF(so, childgo) == false) { continue; } Mesh curMesh = filter.sharedMesh; Vector3[] vertices = curMesh.vertices; Vector3[] normals = (WriteNormals) ? curMesh.normals : null; Color[] colors = (WriteVertexColors) ? curMesh.colors : null; Vector2[] uvs = (WriteUVs) ? curMesh.uv : null; if (vertexMap.Length < curMesh.vertexCount) { vertexMap = new int[curMesh.vertexCount * 2]; } for (int i = 0; i < curMesh.vertexCount; ++i) { NewVertexInfo vi = new NewVertexInfo(); vi.bHaveN = WriteNormals; vi.bHaveC = WriteVertexColors; vi.bHaveUV = WriteUVs; Vector3 v = vertices[i]; // local to world v = filter.gameObject.transform.TransformPoint(v); // world back to scene vi.v = UnityUtil.SwapLeftRight(s.RootGameObject.transform.InverseTransformPoint(v)); if (WriteNormals) { Vector3 n = normals[i]; n = filter.gameObject.transform.TransformDirection(n); vi.n = UnityUtil.SwapLeftRight(s.RootGameObject.transform.InverseTransformDirection(n)); } if (WriteVertexColors) { vi.c = colors[i]; } if (WriteUVs) { vi.uv = uvs[i]; } vertexMap[i] = m.AppendVertex(vi); } int[] triangles = curMesh.triangles; int nTriangles = triangles.Length / 3; for (int i = 0; i < nTriangles; ++i) { int a = vertexMap[triangles[3 * i]]; int b = vertexMap[triangles[3 * i + 1]]; int c = vertexMap[triangles[3 * i + 2]]; m.AppendTriangle(a, c, b, groupCounter); // TRI ORIENTATION IS REVERSED HERE!! } groupCounter++; } vMeshes.Add(new WriteMesh(m, so.Name)); } if (WriteInBackgroundThreads) { ExportStatus status = new ExportStatus() { Exporter = this, IsComputing = true }; WriteOptions useOptions = Options; useOptions.ProgressFunc = (cur, max) => { status.Progress = cur; status.MaxProgress = max; }; BackgroundWriteThread t = new BackgroundWriteThread() { Meshes = vMeshes, options = useOptions, Filename = filename, CompletionF = (result) => { LastWriteStatus = result.code; LastErrorMessage = result.message; status.LastErrorMessage = result.message; status.Ok = (result.code == IOCode.Ok); status.IsComputing = false; } }; t.Start(); return(status); } else { IOWriteResult result = StandardMeshWriter.WriteFile(filename, vMeshes, Options); LastWriteStatus = result.code; LastErrorMessage = result.message; return(new ExportStatus() { Exporter = this, IsComputing = false, Ok = (result.code == IOCode.Ok), LastErrorMessage = result.message }); } }
public static void WriteObj(FileInfo file, IEnumerable <IFileGeometry3D> geometries) { var meshes = new List <WriteMesh>(); var mesh = new SimpleMesh(); var map = new Dictionary <Vector3, int>(); var indeces = new List <int>(); foreach (var geo in geometries) { //var pcount = geo.Positions.Count * 3; //var pp = new double[pcount]; //var pindex = 0; //for(var index =0; index < geo.Positions.Count; index++) { // var v = geo.Positions[index]; // pp[pindex++] = v.X; // pp[pindex++] = v.Y; // pp[pindex++] = v.Z; //} //mesh.Initialize(new VectorArray3d(pp), new VectorArray3i(geo.Indices.ToArray())); for (var index = 0; index < geo.Positions.Count; index++) { var v = geo.Positions[index]; if (!map.ContainsKey(v)) { map.Add(v, map.Count); } } for (var index = 0; index < geo.Indices.Count; index++) { var i = geo.Indices[index]; var v = geo.Positions[i]; indeces.Add(map[v]); } } var points = map.Keys.ToArray(); var pcount = points.Length * 3; var pp = new double[pcount]; var pindex = 0; for (var index = 0; index < points.Length; index++) { var v = points[index]; pp[pindex++] = v.X; pp[pindex++] = v.Y; pp[pindex++] = v.Z; } mesh.Initialize(new VectorArray3d(pp), new VectorArray3i(indeces.ToArray())); meshes.Add(new WriteMesh(mesh, $"d3dlab export")); StandardMeshWriter.WriteFile(file.FullName, meshes, WriteOptions.Defaults); //var obj = new OBJWriter(); //System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; //using (var stream = File.Open(file.FullName, FileMode.Create)) { // using (var writer = new StreamWriter(stream, Encoding.UTF8)) { // obj.Write(writer, meshes, WriteOptions.Defaults); // } //} }