private void LoadMeshFromObj(string filename) { // Force garbage collection to ensure that unmanaged resources are released. // Temporary workaround until unmanaged resource leak is identified GC.Collect(); bool objectFound = false; //Dictionary<string, ObjectNode> objectTable = new Dictionary<string, ObjectNode>(); List<ObjectNode> objects = new List<ObjectNode>(); ObjectNode currentObject = new ObjectNode(); currentObject.Name = "Default"; int triangleCount = 0; int vertexCount = 0; // List<Mesh.Group> matGroups = new List<Mesh.Group>(); List<PositionNormalTextured> vertexList = new List<PositionNormalTextured>(); List<Vector3> vertList = new List<Vector3>(); List<Vector3> normList = new List<Vector3>(); List<Vector2> uvList = new List<Vector2>(); vertList.Add(new Vector3()); normList.Add(new Vector3()); uvList.Add(new Vector2()); List<int> indexList = new List<int>(); List<int> attribList = new List<int>(); List<int[]> applyLists = new List<int[]>(); List<int> applyListsIndex = new List<int>(); List<string> materialNames = new List<string>(); int currentMaterialIndex = -1; Material currentMaterial = new Material(); Mesh.Group currentGroup = new Mesh.Group(); int currentIndex = 0; //initialize the default material currentMaterial = new Material(); currentMaterial.Diffuse = Color; currentMaterial.Ambient = Color; currentMaterial.Specular = System.Drawing.Color.White; currentMaterial.SpecularSharpness = 30.0f; currentMaterial.Opacity = 1.0f; currentMaterial.Default = true; //initialize the group currentGroup.startIndex = 0; currentGroup.indexCount = 0; currentGroup.materialIndex = 0; using (Stream fs = new FileStream(filename, FileMode.Open,FileAccess.Read)) { StreamReader sr = new StreamReader(fs); while (!sr.EndOfStream) { string line = sr.ReadLine().Replace(" ", " "); string[] parts = line.Trim().Split(new char[] { ' ' }); if (parts.Length > 0) { switch (parts[0]) { case "mtllib": { string path = filename.Substring(0, filename.LastIndexOf('\\') + 1); string matFile = path + "\\" + parts[1]; LoadMatLib(matFile); } break; case "usemtl": string materialName = parts[1]; if (matLib.ContainsKey(materialName)) { if (currentMaterialIndex == -1 && currentIndex > 0) { addMaterial(currentMaterial); currentMaterialIndex++; } if (currentMaterialIndex > -1) { currentGroup.indexCount = currentIndex - currentGroup.startIndex; // matGroups.Add(currentGroup); currentObject.DrawGroup.Add(currentGroup); } currentMaterialIndex++; if (matLib.ContainsKey(materialName)) { currentMaterial = matLib[materialName]; if (textureLib.ContainsKey(materialName)) { try { if (!TextureCache.ContainsKey(textureLib[materialName])) { string path = filename.Substring(0, filename.LastIndexOf('\\') + 1); Texture11 tex = LoadTexture(path + textureLib[materialName]); if (tex != null) { meshFilenames.Add(textureLib[materialName]); TextureCache.Add(textureLib[materialName], tex); } } meshTextures.Add(TextureCache[textureLib[materialName]]); } catch { } } addMaterial(currentMaterial); currentGroup = new Mesh.Group(); currentGroup.startIndex = currentIndex; currentGroup.indexCount = 0; currentGroup.materialIndex = currentMaterialIndex; } } break; case "v": vertexCount++; if (FlipHandedness) { vertList.Add(new Vector3(-float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]))); } else { vertList.Add(new Vector3(float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]))); } break; case "vn": if (FlipHandedness) { normList.Add(new Vector3(-float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]))); } else { normList.Add(new Vector3(float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]))); } break; case "vt": uvList.Add(new Vector2(float.Parse(parts[1]), FlipV ? (1 - float.Parse(parts[2])) : float.Parse(parts[2]))); break; case "g": case "o": if (objectFound) { if (currentMaterialIndex > -1) { currentGroup.indexCount = currentIndex - currentGroup.startIndex; // matGroups.Add(currentGroup); currentObject.DrawGroup.Add(currentGroup); currentGroup = new Mesh.Group(); currentGroup.startIndex = currentIndex; currentGroup.indexCount = 0; currentGroup.materialIndex = currentMaterialIndex; } currentObject = new ObjectNode(); } objectFound = true; if (parts.Length > 1) { currentObject.Name = parts[1]; } else { currentObject.Name = "Unnamed"; } objects.Add(currentObject); //if (!objectTable.ContainsKey(currentObject.Name)) //{ // objectTable.Add(currentObject.Name, currentObject); //} break; case "f": int[] indexiesA = GetIndexies(parts[1]); int[] indexiesB = GetIndexies(parts[2]); int[] indexiesC = GetIndexies(parts[3]); vertexList.Add(new PositionNormalTextured(vertList[indexiesA[0]], normList[indexiesA[2]], uvList[indexiesA[1]])); vertexList.Add(new PositionNormalTextured(vertList[indexiesB[0]], normList[indexiesB[2]], uvList[indexiesB[1]])); vertexList.Add(new PositionNormalTextured(vertList[indexiesC[0]], normList[indexiesC[2]], uvList[indexiesC[1]])); if (FlipHandedness) { indexList.Add(currentIndex); indexList.Add(currentIndex + 2); indexList.Add(currentIndex + 1); } else { indexList.Add(currentIndex); indexList.Add(currentIndex + 1); indexList.Add(currentIndex + 2); } triangleCount++; currentIndex += 3; //bool flip = true; if (parts.Length > 4) { int partIndex = 4; while (partIndex < (parts.Length)) { if (FlipHandedness) { indexiesA = GetIndexies(parts[1]); indexiesC = GetIndexies(parts[partIndex]); indexiesB = GetIndexies(parts[partIndex - 1]); } else { indexiesA = GetIndexies(parts[1]); indexiesB = GetIndexies(parts[partIndex - 1]); indexiesC = GetIndexies(parts[partIndex]); } vertexList.Add(new PositionNormalTextured(vertList[indexiesA[0]], normList[indexiesA[2]], uvList[indexiesA[1]])); vertexList.Add(new PositionNormalTextured(vertList[indexiesB[0]], normList[indexiesB[2]], uvList[indexiesB[1]])); vertexList.Add(new PositionNormalTextured(vertList[indexiesC[0]], normList[indexiesC[2]], uvList[indexiesC[1]])); indexList.Add(currentIndex); indexList.Add(currentIndex + 1); indexList.Add(currentIndex + 2); triangleCount++; currentIndex += 3; partIndex++; } } break; } } } } if (!objectFound) { // add the default object objects.Add(currentObject); } if (currentMaterialIndex == -1 && currentIndex > 0) { addMaterial(currentMaterial); currentMaterialIndex++; } if (currentMaterialIndex > -1) { currentGroup.indexCount = currentIndex - currentGroup.startIndex; currentObject.DrawGroup.Add(currentGroup); } if (normList.Count < 2) { float creaseAngleRad = MathUtil.DegreesToRadians(Smooth ? 170.0f : 45.0f); Vector3[] vertexNormals = CalculateVertexNormalsMerged(vertexList, indexList, creaseAngleRad); List<PositionNormalTextured> newVertexList = new List<PositionNormalTextured>(); int newVertexCount = indexList.Count; for (int vertexIndex = 0; vertexIndex < newVertexCount; ++vertexIndex) { PositionNormalTextured v = vertexList[indexList[vertexIndex]]; v.Normal = vertexNormals[vertexIndex]; newVertexList.Add(v); } vertexList = newVertexList; } mesh = new Mesh(vertexList.ToArray(), indexList.ToArray()); ObjectNode rootDummy = new ObjectNode(); rootDummy.Name = "Root"; rootDummy.Parent = null; rootDummy.Level = -1; rootDummy.DrawGroup = null; rootDummy.Children = objects; Objects = new List<ObjectNode>(); Objects.Add(rootDummy); mesh.setObjects(Objects); //List<ObjectNode> objects = new List<ObjectNode>(); //ObjectNode node = new ObjectNode(); //node.Name = "Default"; //node.DrawGroup = matGroups; //objects.Add(node); //mesh.setObjects(objects); //Objects = objects; mesh.commitToDevice(RenderContext11.PrepDevice); dirty = false; GC.Collect(); }