public void ReadFromOBJ(TextReader reader, Stream unknownData) { if (unknownData != null) { Unknown1 = unknownData.ReadUShort(); Unknown2 = unknownData.ReadUShort(); Unknown3 = unknownData.ReadUShort(); Unknown4 = unknownData.ReadUShort(); unknownData.Read(Unknown5); } var lods = new LOD[3]; var wheelPositions = new WheelPosition[4]; string line; int currentWheelPosition = -1; short currentWheelPositionWValue = 0; int currentLODNumber = -1; bool shadow = false; string currentMaterial = "untextured"; Vertex wheelPositionCandidate = null; LOD currentLOD = null; var vertices = new List <Vertex>(); var normals = new List <Normal>(); var uvCoords = new List <UVCoordinate>(); var usedVertexIDs = new List <int>(); var usedNormalIDs = new List <int>(); int shadowVertexStartID = 0; double currentScale = 1; do { line = reader.ReadLine(); if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#")) { continue; } try { if (line.StartsWith("o ") || line.StartsWith("g ")) { string[] objectNameParts = line.Split(' ')[1].Split('/'); if (objectNameParts[0].StartsWith("wheelpos")) { currentWheelPosition = int.Parse(objectNameParts[0].Replace("wheelpos", "")); foreach (string namePart in objectNameParts) { string[] keyAndValue = namePart.Split('='); if (keyAndValue.Length == 2 && keyAndValue[0] == "w") { currentWheelPositionWValue = short.Parse(keyAndValue[1]); } } } else if (objectNameParts[0].StartsWith("lod")) { if (wheelPositions.Any(position => position == null)) { //throw new Exception("Expected four wheel position objects before any LOD objects."); // TODO: is this safe to remove? } if (currentLOD != null) { currentLOD.Vertices = usedVertexIDs.OrderBy(id => id).Distinct().Select(id => vertices[id]).ToList(); usedVertexIDs = new List <int>(); currentLOD.Normals = usedNormalIDs.OrderBy(id => id).Distinct().Select(id => normals[id]).ToList(); usedNormalIDs = new List <int>(); currentLOD.GenerateBoundingBox(); } currentLODNumber = int.Parse(objectNameParts[0].Replace("lod", "")); currentLOD = new LOD(); currentLOD.PrepareForOBJRead(unknownData); lods[currentLODNumber] = currentLOD; currentScale = GetScale(objectNameParts); currentLOD.Scale = LOD.ConvertScale(currentScale); } else if (objectNameParts[0].StartsWith("shadow")) { if (lods.Any(lod => lod == null)) { throw new Exception("Expected three LOD objects before shadow object."); } currentLOD.Vertices = usedVertexIDs.OrderBy(id => id).Distinct().Select(id => vertices[id]).ToList(); currentLOD.Normals = usedNormalIDs.OrderBy(id => id).Distinct().Select(id => normals[id]).ToList(); currentLOD.GenerateBoundingBox(); shadow = true; Shadow = new Shadow(); Shadow.PrepareForOBJRead(unknownData); shadowVertexStartID = vertices.Count; currentScale = GetScale(objectNameParts); Shadow.Scale = LOD.ConvertScale(currentScale); } } else if (line.StartsWith("v ")) { if (shadow) { var vertex = new ShadowVertex(); vertex.ReadFromOBJ(line, currentScale); Shadow.Vertices.Add(vertex); } else { var vertex = new Vertex(); vertex.ReadFromOBJ(line, currentScale); vertices.Add(vertex); if (currentLODNumber == -1) { wheelPositionCandidate = vertex; } } } else if (line.StartsWith("vt ")) { var uvCoord = new UVCoordinate(); uvCoord.ReadFromOBJ(line); uvCoords.Add(uvCoord); } else if (line.StartsWith("vn ")) { var normal = new Normal(); normal.ReadFromOBJ(line); normals.Add(normal); } else if (line.StartsWith("usemtl ")) { currentMaterial = line.Split(' ')[1]; } else if (line.StartsWith("f ")) { if (shadow) { var polygon = new ShadowPolygon(); polygon.ReadFromOBJ(line, Shadow.Vertices, shadowVertexStartID, currentMaterial); if (polygon.IsQuad) { Shadow.Quads.Add(polygon); } else { Shadow.Triangles.Add(polygon); } } else if (currentLODNumber == -1) { continue; //throw new Exception("Face found outside of a LOD or shadow."); } else if (currentMaterial.StartsWith("untextured")) { var polygon = new Polygon(); polygon.ReadFromOBJ(line, vertices, normals, currentMaterial, usedVertexIDs, usedNormalIDs); if (polygon.IsQuad) { currentLOD.Quads.Add(polygon); } else { currentLOD.Triangles.Add(polygon); } } else { var polygon = new UVPolygon(); polygon.ReadFromOBJ(line, vertices, normals, uvCoords, currentMaterial, usedVertexIDs, usedNormalIDs); if (polygon.IsQuad) { currentLOD.UVQuads.Add(polygon); } else { currentLOD.UVTriangles.Add(polygon); } } } if (currentWheelPosition != -1 && wheelPositionCandidate != null) { var position = new WheelPosition(); position.ReadFromOBJ(wheelPositionCandidate, currentWheelPositionWValue); wheelPositions[currentWheelPosition] = position; wheelPositionCandidate = null; currentWheelPosition = -1; } } catch (Exception exception) { throw new Exception($"Line:{line}\r\n{exception.Message}", exception); } }while (line != null); Shadow.GenerateBoundingBox(); LODs = lods.ToList(); WheelPositions = wheelPositions.ToList(); }
public void ReadFromCAR(Stream stream) { ushort vertexCount = stream.ReadUShort(); // at 0x80 ushort normalCount = stream.ReadUShort(); ushort triangleCount = stream.ReadUShort(); ushort quadCount = stream.ReadUShort(); stream.Position += sizeof(ushort) * 2; ushort uvTriangleCount = stream.ReadUShort(); ushort uvQuadCount = stream.ReadUShort(); stream.Position += sizeof(ushort) * 10; // at 0x90 Scale = stream.ReadUShort(); stream.Position += 2; Vertices = new List <Vertex>(vertexCount); // at 0xA8 Normals = new List <Normal>(normalCount); Triangles = new List <Polygon>(triangleCount); Quads = new List <Polygon>(quadCount); UVTriangles = new List <UVPolygon>(uvTriangleCount); UVQuads = new List <UVPolygon>(uvQuadCount); for (int i = 0; i < vertexCount; i++) { var vertex = new Vertex(); vertex.ReadFromCAR(stream); Vertices.Add(vertex); } for (int i = 0; i < normalCount; i++) { var normal = new Normal(); normal.ReadFromCAR(stream); Normals.Add(normal); } for (int i = 0; i < triangleCount; i++) { var triangle = new Polygon(); triangle.ReadFromCAR(stream, false, Vertices, Normals); Triangles.Add(triangle); } for (int i = 0; i < quadCount; i++) { var quad = new Polygon(); quad.ReadFromCAR(stream, true, Vertices, Normals); Quads.Add(quad); } for (int i = 0; i < uvTriangleCount; i++) { var uvTriangle = new UVPolygon(); uvTriangle.ReadFromCAR(stream, false, Vertices, Normals); UVTriangles.Add(uvTriangle); } for (int i = 0; i < uvQuadCount; i++) { var uvQuad = new UVPolygon(); uvQuad.ReadFromCAR(stream, true, Vertices, Normals); UVQuads.Add(uvQuad); } // calculate model bounds - can't spot this sort of data in CAR GenerateBoundingBox(); }
public void ReadFromCDO(Stream stream) { ushort vertexCount = stream.ReadUShort(); ushort normalCount = stream.ReadUShort(); ushort triangleCount = stream.ReadUShort(); ushort quadCount = stream.ReadUShort(); stream.Position += sizeof(ushort) * 2; ushort uvTriangleCount = stream.ReadUShort(); ushort uvQuadCount = stream.ReadUShort(); stream.Read(unknown); lowBoundX = stream.ReadShort(); // at 8C0 lowBoundY = stream.ReadShort(); lowBoundZ = stream.ReadShort(); lowBoundW = stream.ReadShort(); highBoundX = stream.ReadShort(); highBoundY = stream.ReadShort(); highBoundZ = stream.ReadShort(); highBoundW = stream.ReadShort(); Scale = stream.ReadUShort(); // at 8D0 unknown2 = stream.ReadSingleByte(); unknown3 = stream.ReadSingleByte(); Vertices = new List <Vertex>(vertexCount); Normals = new List <Normal>(normalCount); Triangles = new List <Polygon>(triangleCount); Quads = new List <Polygon>(quadCount); UVTriangles = new List <UVPolygon>(uvTriangleCount); UVQuads = new List <UVPolygon>(uvQuadCount); for (int i = 0; i < vertexCount; i++) { var vertex = new Vertex(); vertex.ReadFromCDO(stream); Vertices.Add(vertex); } for (int i = 0; i < normalCount; i++) { var normal = new Normal(); normal.ReadFromCDO(stream); Normals.Add(normal); } for (int i = 0; i < triangleCount; i++) { var triangle = new Polygon(); triangle.ReadFromCDO(stream, false, Vertices, Normals); Triangles.Add(triangle); } for (int i = 0; i < quadCount; i++) { var quad = new Polygon(); quad.ReadFromCDO(stream, true, Vertices, Normals); Quads.Add(quad); } for (int i = 0; i < uvTriangleCount; i++) { var uvTriangle = new UVPolygon(); uvTriangle.ReadFromCDO(stream, false, Vertices, Normals); UVTriangles.Add(uvTriangle); } for (int i = 0; i < uvQuadCount; i++) { var uvQuad = new UVPolygon(); uvQuad.ReadFromCDO(stream, true, Vertices, Normals); UVQuads.Add(uvQuad); } }
public void ReadFromCAR(Stream stream) { ushort vertexCount = stream.ReadUShort(); ushort normalCount = stream.ReadUShort(); ushort triangleCount = stream.ReadUShort(); ushort quadCount = stream.ReadUShort(); stream.Position += sizeof(ushort) * 2; ushort uvTriangleCount = stream.ReadUShort(); ushort uvQuadCount = stream.ReadUShort(); stream.Position += sizeof(ushort) * 12; Vertices = new List <Vertex>(vertexCount); Normals = new List <Normal>(normalCount); Triangles = new List <Polygon>(triangleCount); Quads = new List <Polygon>(quadCount); UVTriangles = new List <UVPolygon>(uvTriangleCount); UVQuads = new List <UVPolygon>(uvQuadCount); for (int i = 0; i < vertexCount; i++) { var vertex = new Vertex(); vertex.ReadFromCAR(stream); Vertices.Add(vertex); } for (int i = 0; i < normalCount; i++) { var normal = new Normal(); normal.ReadFromCAR(stream); Normals.Add(normal); } for (int i = 0; i < triangleCount; i++) { var triangle = new Polygon(); triangle.ReadFromCAR(stream, false, Vertices, Normals); Triangles.Add(triangle); } for (int i = 0; i < quadCount; i++) { var quad = new Polygon(); quad.ReadFromCAR(stream, true, Vertices, Normals); Quads.Add(quad); } for (int i = 0; i < uvTriangleCount; i++) { var uvTriangle = new UVPolygon(); uvTriangle.ReadFromCAR(stream, false, Vertices, Normals); UVTriangles.Add(uvTriangle); } for (int i = 0; i < uvQuadCount; i++) { var uvQuad = new UVPolygon(); uvQuad.ReadFromCAR(stream, true, Vertices, Normals); UVQuads.Add(uvQuad); } }