public static ObjGeometry MergeGeometries(IEnumerable <ObjGeometry> geometries, ObjMaterial material) { ObjGeometry mergedGeometry = new ObjGeometry(material); foreach (ObjGeometry item in geometries) { mergedGeometry.Faces.AddRange(item.Faces); } return(mergedGeometry); }
private static void WriteObj(Int32Rect[][] tiles, BitmapSource[][][] imagedata, ConvertOptions options) { var positions = new Dictionary <Vector3, int>(); var normals = new Dictionary <Vector3, int>(); var uvs = new Dictionary <Vector2, int>(); var normal = new Vector3(0, 0, 1); var xcount = (options.ImageWidth.Value + options.TileWidth - 1) / options.TileWidth; var ycount = (options.ImageHeight.Value + options.TileHeight - 1) / options.TileHeight; var folder = Path.GetDirectoryName(options.InputFileName); var filename = Path.GetFileNameWithoutExtension(options.InputFileName); var mtl = new ObjMaterialFile(); var obj = new ObjFile(); obj.MaterialLibraries.Add($"{filename}.mtl"); for (var y = 0; y < ycount; y++) { for (var x = 0; x < xcount; x++) { var tile = tiles[y][x]; var texture = imagedata[0][y][x]; var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(texture)); var matname = $"{filename}_{y:D3}_{x:D3}"; using (var outfile = File.Open(Path.Combine(folder, $"{matname}.png"), FileMode.Create, FileAccess.Write, FileShare.None)) { encoder.Save(outfile); } var material = new ObjMaterial(matname); material.DiffuseMap = new ObjMaterialMap($"{matname}.png"); mtl.Materials.Add(material); var face = new ObjFace(); face.MaterialName = matname; face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X, -(tile.Y), 0)), uvs.AddUniqueIndex(new Vector2(0, (float)tile.Height / texture.PixelHeight)), normals.AddUniqueIndex(normal) )); face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X + tile.Width, -(tile.Y), 0)), uvs.AddUniqueIndex(new Vector2((float)tile.Width / texture.PixelWidth, (float)tile.Height / texture.PixelHeight)), normals.AddUniqueIndex(normal) )); face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X + tile.Width, -(tile.Y + tile.Height), 0)), uvs.AddUniqueIndex(new Vector2((float)tile.Width / texture.PixelWidth, 0)), normals.AddUniqueIndex(normal) )); face.Vertices.Add(new ObjTriplet( positions.AddUniqueIndex(new Vector3(tile.X, -(tile.Y + tile.Height), 0)), uvs.AddUniqueIndex(new Vector2(0, 0)), normals.AddUniqueIndex(normal) )); obj.Faces.Add(face); } } (from x in positions orderby x.Value select x.Key).ToList().ForEach(x => obj.Vertices.Add(x.ToObjVertex())); (from x in normals orderby x.Value select x.Key).ToList().ForEach(x => obj.VertexNormals.Add(x.ToObjVector3())); (from x in uvs orderby x.Value select x.Key).ToList().ForEach(x => obj.TextureVertices.Add(x.ToObjVector3())); mtl.WriteTo(Path.Combine(folder, $"{filename}.mtl")); obj.WriteTo(Path.Combine(folder, $"{filename}.obj")); }
private static string MeshToString(MeshFilter mf, Dictionary <string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent <Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); foreach (Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); // this is not how to convert from left to right handed coordinates //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int i = 0; i < m.subMeshCount; i++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[i].name).Append("\n"); sb.Append("usemap ").Append(mats[i].name).Append("\n"); ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[i].name; if (mats[i].mainTexture) { // #if UNITY_EDITOR objMaterial.textureName = AssetDatabase.GetAssetPath(mats[i].mainTexture); } // #else // objMaterial.textureName = mats[i].mainTexture.name; // #endif else { objMaterial.textureName = null; } materialList.Add(objMaterial.name, objMaterial); int[] tri = m.GetTriangles(i); for (int n = 0; n < tri.Length; n += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", tri[n] + 1 + vertexOffset, tri[n + 1] + 1 + normalOffset, tri[n + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
public void AddObject(IObjObject aObject, ObjMaterial anObjMaterial) { aObject.Material = anObjMaterial; AddObject(aObject); }
public MeshInfo(DynamicRenderMesh parent, Vertex[] vertices, Matrix4 transformMatrix) { Material = parent.Material; Title = parent.Title; var positionsMapping = new Dictionary <Vector3, int>(new VectorEqualityComparer()); var texCoordsMapping = new Dictionary <Vector2, int>(new VectorEqualityComparer()); var normalsMapping = new Dictionary <Vector3, int>(new VectorEqualityComparer()); foreach (var vertex in vertices) { // var index = i * 3; var position = vertex.Position; var texCoord = vertex.TexCoord; texCoord.Y = 1.0f - texCoord.Y; var normal = vertex.Normal; if (transformMatrix != Matrix4.Zero) { var scaleCoef = 1f; if (parent.meshType == MeshType.Accessory) { scaleCoef = 246f; } else if (parent.meshType == MeshType.Head) { scaleCoef = PickingController.GetHeadScale(ProgramCore.Project.ManType); } else { scaleCoef = PickingController.GetHairScale(ProgramCore.Project.ManType); } bool useExporter = ProgramCore.PluginMode && ProgramCore.MainForm.ctrlRenderControl.pickingController.ObjExport != null; var invScale = Matrix4.CreateScale(useExporter ? 1.0f : 1.0f / scaleCoef); var tempTransform = transformMatrix; tempTransform *= invScale; if (useExporter) { var d = ProgramCore.MainForm.ctrlRenderControl.pickingController.ObjExport.Delta; d.Y -= 0.0060975609f; tempTransform *= Matrix4.CreateTranslation(d * scaleCoef); } position = Vector3.Transform(position, tempTransform); normal = Vector3.Transform(normal, tempTransform); } int id; if (!positionsMapping.TryGetValue(position, out id)) { id = Positions.Count; Positions.Add(position); positionsMapping.Add(position, id); } IndicesPositions.Add(id); if (!normalsMapping.TryGetValue(normal, out id)) { id = Normals.Count; Normals.Add(normal); normalsMapping.Add(normal, id); } IndicesNormals.Add(id); if (!texCoordsMapping.TryGetValue(texCoord, out id)) { id = TexCoords.Count; TexCoords.Add(texCoord); texCoordsMapping.Add(texCoord, id); } IndicesTexCoords.Add(id); } }
private List <ObjGroup> CreateRenderGameObjects() { Dictionary <ObjectGame.ObjcetIds, PlainBmpTexture> gameObjectsTextures = RenderObjects.RenderObjects.CreateGameObjectsTextures(new Size(20, 20), program); List <ObjGroup> tempObjList = new List <ObjGroup>(); List <ObjectGame> gameObjects = TheGameStatus.GameObjects; foreach (ObjectGame gameObject in gameObjects) { Vector tempLoc; ObjGroupGameObject tempGroup = null; ObjGameObject tempObjObject; switch (gameObject.TheObjectId) { case ObjectGame.ObjcetIds.Player: tempGroup = new ObjGroupGameObjectPlayer(program) { TheObjectGame = gameObject }; tempLoc = new Vector(0.0f, 0.0f); tempLoc -= new Vector(gameObject.Diameter * 0.5f, gameObject.Diameter * 0.5f); tempObjObject = new ObjGameObject(ObjectPrimitives.CreateCube(new Vector3(tempLoc.X, 0, tempLoc.Y), new Vector3(tempLoc.X + gameObject.Diameter, gameObject.Diameter, tempLoc.Y + gameObject.Diameter), true)); ObjMaterial tempMaterial = TheResourceManager.GetFromFile(program, "tileTestMike200x200.png"); tempObjObject.Material = tempMaterial; tempGroup.AddObject(tempObjObject); playerObjObject = tempGroup; tempGroup.Location = gameObject.Location; break; case ObjectGame.ObjcetIds.Enemy: tempGroup = new ObjGroupGameObjectEnemy(program) { TheObjectGame = gameObject }; tempLoc = new Vector(0.0f, 0.0f); tempLoc -= new Vector(gameObject.Diameter * 0.5f, gameObject.Diameter * 0.5f); tempObjObject = new ObjGameObject(ObjectPrimitives.CreateCube(new Vector3(tempLoc.X, 0, tempLoc.Y), new Vector3(tempLoc.X + gameObject.Diameter, gameObject.Diameter, tempLoc.Y + gameObject.Diameter), true)); ObjMaterial tempMaterial1 = TheResourceManager.GetFromFile(program, "tileTestMike200x200.png"); tempObjObject.Material = tempMaterial1; tempGroup.AddObject(tempObjObject); tempGroup.Location = gameObject.Location; break; case ObjectGame.ObjcetIds.Turret: ObjGroup tempGroup1 = ObjLoader.LoadObjFileToObjMesh(program, @"./Resources/Models/Turret1.obj"); ObjectTurret tempTurret = (ObjectTurret)gameObject; tempGroup = new ObjGroupGameObjectTurret(tempGroup1) { Location = gameObject.Location, Scale = Vector3.UnitScale * 0.3f, TheObjectGame = tempTurret }; // tempGroup.Orientation = tempTurret.Orientation; break; default: tempLoc = new Vector(0.0f, 0.0f); tempLoc -= new Vector(gameObject.Diameter * 0.5f, gameObject.Diameter * 0.5f); tempObjObject = new ObjGameObject(ObjectPrimitives.CreateCube(new Vector3(tempLoc.X, 0, tempLoc.Y), new Vector3(tempLoc.X + gameObject.Diameter, gameObject.Diameter, tempLoc.Y + gameObject.Diameter), true)) { Material = gameObjectsTextures[gameObject.TheObjectId].Material }; tempGroup.AddObject(tempObjObject); tempGroup.TheObjectGame = gameObject; break; } tempObjList.Add(tempGroup); } return(tempObjList); }
private ObjMaterial ProcessMaterial(string mtlName, string folderPath) { ObjMaterial material = null; string filePath = Path.Combine(folderPath, mtlName); var input = File.ReadLines(filePath); foreach (string line in input) { string[] parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length > 0) { switch (parts[0].Trim('\t', ' ')) { case "newmtl": material = new ObjMaterial(parts[1]); break; case "map_Kd": string textureName = parts[1]; material.DiffuseTexture = new Bitmap(Path.Combine(folderPath, textureName)); break; } } } return material; }
public static string MeshToString(MeshFilter mf, Dictionary <string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent <Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); // foreach(Vector3 v in m.vertices) { // sb.Append(string.Format("v {0} {1} {2}\n",v.x,v.y,v.z)); // } foreach (Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); // foreach(Vector3 v in m.normals) { // sb.Append(string.Format("vn {0} {1} {2}\n",v.x,v.y,v.z)); // } foreach (Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } int countMat = m.subMeshCount; if (mats == null) { Debug.LogWarning($"NavMeshExporter MeshToString Error - 没有找到材质"); return(sb.ToString()); } else if (mats.Length < countMat) { Debug.LogWarning($"NavMeshExporter MeshToString Error - 共享材质数量小于该物体的子物体数量 - {mats.Length} / {countMat}"); countMat = mats.Length; } for (int material = 0; material < countMat; material++) { string nameMat = "null"; Texture mainTexture = null; if (mats[material] != null) { nameMat = mats[material].name; mainTexture = mats[material].mainTexture; } sb.Append("\n"); sb.Append("usemtl ").Append(nameMat).Append("\n"); sb.Append("usemap ").Append(nameMat).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = nameMat; if (mainTexture) { objMaterial.textureName = AssetDatabase.GetAssetPath(mainTexture); } else { objMaterial.textureName = null; } materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } // int[] triangles = m.GetTriangles(material); // for (int i=0;i<triangles.Length;i+=3) { // sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", // triangles[i]+1, triangles[i+1]+1, triangles[i+2]+1)); // } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private static string MeshToString(MeshFilter mf, Dictionary<string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent<Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); foreach(Vector3 lv in m.vertices) { Vector3 wv = lv; // this is not how to convert from left to right handed coordinates //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n",-wv.x,wv.y,wv.z)); } sb.Append("\n"); foreach(Vector3 lv in m.normals) { Vector3 wv = lv; sb.Append(string.Format("vn {0} {1} {2}\n",-wv.x,wv.y,wv.z)); } sb.Append("\n"); foreach(Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n",v.x,v.y)); } for (int i = 0; i < m.subMeshCount; i ++) { sb.Append("\n"); sb.Append("g ").Append(mats[i].name).Append("\n"); sb.Append("usemtl ").Append(mats[i].name).Append("\n"); sb.Append("usemap ").Append(mats[i].name).Append("\n"); ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[i].name; if (mats[i].mainTexture) objMaterial.textureName = UnityEditor.AssetDatabase.GetAssetPath(mats[i].mainTexture); else objMaterial.textureName = null; materialList.Add(objMaterial.name, objMaterial); int[] tri = m.GetTriangles(i); for (int n = 0; n < tri.Length; n += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", tri[n]+1 + vertexOffset, tri[n+1]+1 + normalOffset, tri[n+2]+1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return sb.ToString(); }
static void ConvertDLPToOBJ(DLPFile dlp) { if (dlp == null) { throw new InvalidOperationException("Cannot convert a null DLP object to OBJ!"); } var rootDir = Path.GetFullPath($"{Path.GetDirectoryName(dlp.FileName)}.\\..\\"); var objPath = Path.ChangeExtension(dlp.FileName, ".obj"); var mtlPath = Path.ChangeExtension(dlp.FileName, ".mtl"); var obj = new StringBuilder(); var mtl = new StringBuilder(); obj.AppendLine($"# DLP converted to OBJ using ARTS Manager"); obj.AppendLine($"# Source: {dlp.FileName}"); obj.AppendLine(); obj.AppendLine($"# Vertices: {dlp.Vertices.Count}"); obj.AppendLine($"# Patches: {dlp.Patches.Count}"); obj.AppendLine($"# Groups: {dlp.Groups.Count}"); obj.AppendLine(); obj.AppendLine($"mtllib {Path.GetFileName(mtlPath)}"); obj.AppendLine(); mtl.AppendLine($"# DLP7 materials"); mtl.AppendLine(); var vxIndex = 0; // increases when we add a new vertex var minIndex = 0; // for normals/uvs var materialLookup = new Dictionary <string, ObjMaterial>(); var materials = new Dictionary <string, ObjMaterial>(); foreach (var group in dlp.Groups) { var objF = new StringBuilder(); var objVx = new StringBuilder(); var objVn = new StringBuilder(); var objVt = new StringBuilder(); var vBuf = new Dictionary <int, int>(); var curMtl = 0; var curTex = 0; foreach (var p in group.Patches) { var patch = dlp.Patches[p]; if (patch.Stride != 1) { continue; } if ((patch.Resolution < 3) || (patch.Resolution > 4)) { continue; } if ((patch.Material != curMtl) || (patch.Texture != curTex)) { curMtl = patch.Material; curTex = patch.Texture; var mat = (curMtl != 0) ? dlp.Materials[curMtl - 1] : null; var tex = (curTex != 0) ? dlp.Textures[curTex - 1] : null; var materialName = ""; if ((mat != null) && (tex != null)) { materialName = $"{mat.Name}|{tex.Name}"; } else { materialName = (mat != null) ? mat.Name : (tex != null) ? tex.Name : ""; } if (String.IsNullOrEmpty(materialName)) { throw new InvalidOperationException("apparently this patch doesn't have any clothes on..."); } if (!materialLookup.ContainsKey(materialName)) { var material = new ObjMaterial(materialName); var texture = (tex != null) ? tex.Name : null; var hasAlpha = false; if (texture != null) { var tex16OPath = Path.Combine(rootDir, $"TEX16O\\{texture}.DDS"); var tex16APath = Path.Combine(rootDir, $"TEX16A\\{texture}.DDS"); var hasTex16O = File.Exists(tex16OPath); var hasTex16A = File.Exists(tex16APath); texture = (hasTex16O) ? tex16OPath : ((hasAlpha = hasTex16A)) ? tex16APath : $"{texture}.DDS"; } if (mat != null) { material.SetComponentColor(ComponentType.Ambient, mat.Ambient); material.SetComponentColor(ComponentType.Diffuse, mat.Diffuse); material.SetComponentColor(ComponentType.Specular, mat.Specular); //material.Specularity = mat.Shininess; } if (tex != null) { // maybe have a thing that checks if its 3ds max? //material.SetComponentMap(ComponentType.Ambient, texture); material.SetComponentMap(ComponentType.Diffuse, texture); if (hasAlpha) { material.Properties["d"] = "0.0000"; material.Properties["map_d"] = texture; } } // compile material.Save(mtl); materialLookup.Add(materialName, material); materials.Add(materialName, material); } objF.AppendLine($"usemtl {materialLookup[materialName].Name}"); } // open face objF.Append("f "); for (int i = 0; i < patch.Resolution; i++) { var v = patch.Vertices[i]; int vx = v.Vertex; var vt1 = v.SMap; var vt2 = (-v.TMap - 1); var vn = v.Normals; if (!vBuf.ContainsKey(vx)) { var vertex = dlp.Vertices[vx]; objVx.AppendLine($"v {vertex.X:F6} {vertex.Y:F6} {vertex.Z:F6}"); vBuf.Add(vx, vxIndex++); } // translate to index in buffer vx = vBuf[vx]; objVt.AppendLine($"vt {vt1:F6} {vt2:F6} 1.000000"); objVn.AppendLine($"vn {vn.X:F6} {vn.Y:F6} {vn.Z:F6}"); // append face objF.AppendFormat("{0}/{1}/{1} ", (vx + 1), (i + minIndex + 1)); } minIndex += patch.Resolution; // move to next face objF.AppendLine(); } // commit changes, move along obj.AppendLine($"o {group.Name}"); obj.AppendLine(objVx.ToString()); obj.AppendLine(objVn.ToString()); obj.AppendLine(objVt.ToString()); obj.AppendLine($"g {group.Name}"); obj.AppendLine(objF.ToString()); } File.WriteAllText(objPath, obj.ToString()); File.WriteAllText(mtlPath, mtl.ToString()); }
private static string SkinnedMeshToString(SkinnedMeshRenderer smr, Dictionary <string, ObjMaterial> materialList) { Mesh m = smr.sharedMesh; if (m == null) { return(""); } if (!smr.enabled || !smr.gameObject.activeInHierarchy) { return(""); } if (m.uv.Length == 0) { //TODO figure out why all the vertices explode when uvs not set VadRLogger.error("Skipping export of skinned mesh \"" + smr.name + "\". Exporting meshes must be unwrapped"); return(""); } Material[] mats = smr.sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("o ").Append(smr.name).Append("\n"); foreach (Vector3 lv in m.vertices) { Vector3 wv = smr.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = smr.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); Vector2 textureScale = Vector3.one; if (mats.Length > 0 && mats[0] != null && mats[0].HasProperty("_MainTex")) { textureScale = mats[0].GetTextureScale("_MainTex"); } foreach (Vector3 v in m.uv) { //scale uvs to deal with tiled textures sb.Append(string.Format("vt {0} {1}\n", v.x * textureScale.x, v.y * textureScale.y)); } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); if (material >= mats.Length) { continue; } if (mats[material] == null) { sb.Append("usemtl ").Append("null").Append("\n"); } else { sb.Append("usemtl ").Append(mats[material].name).Append("\n"); //sb.Append("usemap ").Append(mats[material].name).Append("\n"); } //See if this material is already in the materiallist. try { if (mats[material] == null) { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = "null"; objMaterial.textureName = null; objMaterial.material = new Material(Shader.Find("Unlit/Color")); objMaterial.material.color = Color.magenta; materialList.Add(objMaterial.name, objMaterial); } else { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) { objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); } else { objMaterial.textureName = null; } objMaterial.material = mats[material]; materialList.Add(objMaterial.name, objMaterial); } } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private static string MeshToString(MeshFilter mf) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent <Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); foreach (Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) { objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); } else { objMaterial.textureName = null; } } catch (ArgumentException) { } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private static string MeshToString(MeshFilter mf, Dictionary <string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent <Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); GameObject space = GameObject.Find("space"); foreach (Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); Vector3 rv = space.transform.InverseTransformPoint(wv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". //sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); sb.Append(string.Format("v {0} {1} {2}\n", rv.x, rv.y, rv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); Vector3 rv = space.transform.InverseTransformDirection(wv); sb.Append(string.Format("vn {0} {1} {2}\n", -rv.x, rv.y, rv.z)); //sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int material = 0; material < m.subMeshCount; material++) { string mat_name; if (mats[material] == null) { mat_name = "Default-Material"; } else { mat_name = mats[material].name; } sb.Append("\n"); sb.Append("usemtl ").Append(mat_name).Append("\n"); sb.Append("usemap ").Append(mat_name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mat_name; /* * if (mats[material].mainTexture) * //objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); * { * objMaterial.textureName = ""; * //#if UNITY_EDITOR * objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); * Debug.LogError("objMaterial.textureName : " + AssetDatabase.GetAssetPath(mats[material].mainTexture)); * //#endif * } * else * { * Debug.LogError("mats[material].mainTexture = null "); * objMaterial.textureName = null; * * } */ objMaterial.textureName = null; materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private static string SkinnedMeshToString(SkinnedMeshRenderer skRenderer, Dictionary<string, ObjMaterial> materialList) { Mesh mTemp = skRenderer.sharedMesh; Vector3[] vertices = new Vector3[mTemp.vertexCount]; Vector3[] normals = new Vector3[mTemp.vertexCount]; Matrix4x4[] boneMatrices = new Matrix4x4[skRenderer.bones.Length]; for (int i = 0; i < boneMatrices.Length; i++) { boneMatrices[i] = skRenderer.bones[i].localToWorldMatrix * mTemp.bindposes[i]; } for (int i = 0; i < mTemp.vertexCount; i++) { BoneWeight weight = mTemp.boneWeights[i]; Matrix4x4 bm0 = boneMatrices[weight.boneIndex0]; Matrix4x4 bm1 = boneMatrices[weight.boneIndex1]; Matrix4x4 bm2 = boneMatrices[weight.boneIndex2]; Matrix4x4 bm3 = boneMatrices[weight.boneIndex3]; Matrix4x4 vertexMatrix = new Matrix4x4(); vertexMatrix = Matrix4x4.identity; for (int n=0; n<16; n++) { vertexMatrix[n] = bm0[n] * weight.weight0 + bm1[n] * weight.weight1 + bm2[n] * weight.weight2 + bm3[n] * weight.weight3; } /* Vector3 pos0 = bm0.MultiplyPoint(mTemp.vertices[i]); Vector3 pos1 = bm1.MultiplyPoint(mTemp.vertices[i]); Vector3 pos2 = bm2.MultiplyPoint(mTemp.vertices[i]); Vector3 pos3 = bm3.MultiplyPoint(mTemp.vertices[i]); Vector3 pos = pos0 * weight.weight0 + pos1 * weight.weight1 + pos2 * weight.weight2 + pos3 * weight.weight3; vertices[i] = pos; */ vertices[i] = vertexMatrix.MultiplyPoint (mTemp.vertices[i]); normals[i] = vertexMatrix.MultiplyVector (mTemp.normals[i]); } Mesh m = new Mesh(); m.vertices = vertices; m.normals = normals; m.uv = mTemp.uv; m.triangles = mTemp.triangles; m.subMeshCount = mTemp.subMeshCount; m.RecalculateBounds(); m.RecalculateNormals(); Material[] mats = skRenderer.GetComponent<Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(skRenderer.gameObject.name).Append("\n"); foreach(Vector3 lv in m.vertices) { Vector3 wv = skRenderer.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n",-wv.x,wv.y,wv.z)); } sb.Append("\n"); foreach(Vector3 lv in m.normals) { Vector3 wv = skRenderer.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n",-wv.x,wv.y,wv.z)); } sb.Append("\n"); foreach(Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n",v.x,v.y)); } for (int material=0; material < m.subMeshCount; material ++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); else objMaterial.textureName = null; materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i=0;i<triangles.Length;i+=3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i]+1 + vertexOffset, triangles[i+1]+1 + normalOffset, triangles[i+2]+1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return sb.ToString(); }
private static void ParseMaterial(StreamReader sr, ObjContext objContext, string[] token) { ObjMaterial objMaterial = new ObjMaterial(token[0]); string objLine; while ((objLine = sr.ReadLine()) != null) { // Trim spaces objLine = objLine.Trim(); // Skip comments if (_CommentLine.IsMatch(objLine)) { continue; } // Stop material parsing on empty line // Note: is this robust enought? I don't think so. if (objLine.Length == 0) { break; } Match commandMatch = _MtlParamLine.Match(objLine); if (commandMatch.Success == false) { continue; } string command = commandMatch.Groups["Command"].Value; string commandToken = commandMatch.Groups["Tokens"].Value.Trim(); string[] commandTokens = Regex.Split(commandToken, " +"); switch (command) { case "Ka": // Ambient objMaterial.Ambient = ParseMaterialColor(objMaterial, commandTokens); break; case "Kd": // Diffuse objMaterial.Diffuse = ParseMaterialColor(objMaterial, commandTokens); break; case "Ks": // Specular objMaterial.Specular = ParseMaterialColor(objMaterial, commandTokens); break; case "Tf": // Transmission Filter break; case "illum": // Illumination model break; case "d": // Dissolve factor break; case "Ns": // Specular exponent objMaterial.SpecularExponent = Single.Parse(commandTokens[0]); break; case "sharpness": // Reflection sharpness break; case "Ni": // Index of refrection break; case "map_Ka": objMaterial.AmbientTexture = ParseMaterialTexture(objContext, objMaterial, commandTokens); break; case "map_Kd": objMaterial.DiffuseTexture = ParseMaterialTexture(objContext, objMaterial, commandTokens); break; case "map_Ks": objMaterial.SpecularTexture = ParseMaterialTexture(objContext, objMaterial, commandTokens); break; case "map_d": case "map_Ns": case "map_aat": case "decal": case "disp": case "bump": case "refl": default: // Ignore break; // Custom case "map_n": objMaterial.NormalTexture = ParseMaterialTexture(objContext, objMaterial, commandTokens); break; } } // Collect material objContext.Materials.Add(objMaterial.Name, objMaterial); }
private static string MeshToString(MeshFilter mf, Dictionary <string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.renderer.sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); { var __array1 = m.vertices; var __arrayLength1 = __array1.Length; for (int __i1 = 0; __i1 < __arrayLength1; ++__i1) { var lv = (Vector3)__array1[__i1]; { Vector3 wv = mf.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } } } sb.Append("\n"); { var __array2 = m.normals; var __arrayLength2 = __array2.Length; for (int __i2 = 0; __i2 < __arrayLength2; ++__i2) { var lv = (Vector3)__array2[__i2]; { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } } } sb.Append("\n"); { var __array3 = m.uv; var __arrayLength3 = __array3.Length; for (int __i3 = 0; __i3 < __arrayLength3; ++__i3) { var v = (Vector3)__array3[__i3]; { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } } } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) { objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); } else { objMaterial.textureName = null; } materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private static string MeshToString(MeshFilter mf, Dictionary <string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent <Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); try { foreach (Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); } catch (Exception e) { Debug.LogError("mf name____" + mf.gameObject.name); } foreach (Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) { objMaterial.textureName = EditorUtility.GetAssetPath(mats[material].mainTexture); } else { objMaterial.textureName = null; } materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private static string SkinnedMeshToString(SkinnedMeshRenderer skRenderer, Dictionary <string, ObjMaterial> materialList) { Mesh mTemp = skRenderer.sharedMesh; Vector3[] vertices = new Vector3[mTemp.vertexCount]; Vector3[] normals = new Vector3[mTemp.vertexCount]; Matrix4x4[] boneMatrices = new Matrix4x4[skRenderer.bones.Length]; for (int i = 0; i < boneMatrices.Length; i++) { boneMatrices[i] = skRenderer.bones[i].localToWorldMatrix * mTemp.bindposes[i]; } for (int i = 0; i < mTemp.vertexCount; i++) { BoneWeight weight = mTemp.boneWeights[i]; Matrix4x4 bm0 = boneMatrices[weight.boneIndex0]; Matrix4x4 bm1 = boneMatrices[weight.boneIndex1]; Matrix4x4 bm2 = boneMatrices[weight.boneIndex2]; Matrix4x4 bm3 = boneMatrices[weight.boneIndex3]; Matrix4x4 vertexMatrix = new Matrix4x4(); vertexMatrix = Matrix4x4.identity; for (int n = 0; n < 16; n++) { vertexMatrix[n] = bm0[n] * weight.weight0 + bm1[n] * weight.weight1 + bm2[n] * weight.weight2 + bm3[n] * weight.weight3; } /* * Vector3 pos0 = bm0.MultiplyPoint(mTemp.vertices[i]); * Vector3 pos1 = bm1.MultiplyPoint(mTemp.vertices[i]); * Vector3 pos2 = bm2.MultiplyPoint(mTemp.vertices[i]); * Vector3 pos3 = bm3.MultiplyPoint(mTemp.vertices[i]); * * Vector3 pos = pos0 * weight.weight0 + pos1 * weight.weight1 + pos2 * weight.weight2 + pos3 * weight.weight3; * * vertices[i] = pos; */ vertices[i] = vertexMatrix.MultiplyPoint(mTemp.vertices[i]); normals[i] = vertexMatrix.MultiplyVector(mTemp.normals[i]); } Mesh m = new Mesh(); m.vertices = vertices; m.normals = normals; m.uv = mTemp.uv; m.triangles = mTemp.triangles; m.subMeshCount = mTemp.subMeshCount; m.RecalculateBounds(); m.RecalculateNormals(); Material[] mats = skRenderer.renderer.sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(skRenderer.gameObject.name).Append("\n"); foreach (Vector3 lv in m.vertices) { Vector3 wv = skRenderer.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = skRenderer.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) { objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); } else { objMaterial.textureName = null; } materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
private void ProcessLine(string line, string folderPath) { string[] parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length > 0) { switch (parts[0]) { case "mtllib": Material = ProcessMaterial(parts[1], folderPath); break; case "v": Vector3 vertex = ProcessVertex(parts); Vertices.Add(vertex); break; case "vt": Vector2 texCoord = ProcessTextureCoordinate(parts); TexCoords.Add(texCoord); break; case "vn": Vector3 normal = ProcessVertex(parts); Normals.Add(normal); break; case "f": ObjFace face = ProcessFace(parts); Faces.Add(face); break; } } }
public BaseRenderMesh() { Id = Guid.NewGuid(); Material = new ObjMaterial(Id.ToString().Replace("-", "")); }
private static string MeshToString(MeshFilter mf, Dictionary<string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.renderer.sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); foreach(Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n",-wv.x,wv.y,wv.z)); } sb.Append("\n"); foreach(Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n",-wv.x,wv.y,wv.z)); } sb.Append("\n"); foreach(Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n",v.x,v.y)); } for (int material=0; material < m.subMeshCount; material ++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); else objMaterial.textureName = null; materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i=0;i<triangles.Length;i+=3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i]+1 + vertexOffset, triangles[i+1]+1 + normalOffset, triangles[i+2]+1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return sb.ToString(); }
private static string MeshToStringNoFilter(Mesh m, Dictionary <string, ObjMaterial> materialList) { StringBuilder sb = new StringBuilder(); sb.Append("g ").Append("navmesh").Append("\n"); foreach (Vector3 lv in m.vertices) { Vector3 wv = lv; //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = lv; sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); sb.Append("usemtl ").Append("Default-Material").Append("\n"); sb.Append("usemap ").Append("Default-Material").Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = "Default-Material"; objMaterial.textureName = null; materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }