public void ReadFromCDO(Stream stream) { ushort vertexCount = stream.ReadUShort(); // 3B40 ushort triangleCount = stream.ReadUShort(); ushort quadCount = stream.ReadUShort(); unknown = stream.ReadUShort(); lowBoundX = stream.ReadShort(); lowBoundY = stream.ReadShort(); lowBoundZ = stream.ReadShort(); lowBoundW = stream.ReadShort(); highBoundX = stream.ReadShort(); highBoundY = stream.ReadShort(); highBoundZ = stream.ReadShort(); highBoundW = stream.ReadShort(); Scale = stream.ReadUShort(); unknown2 = stream.ReadSingleByte(); unknown3 = stream.ReadSingleByte(); Vertices = new List <ShadowVertex>(vertexCount); // 3B5C Triangles = new List <ShadowPolygon>(triangleCount); // 3BBC Quads = new List <ShadowPolygon>(quadCount); for (int i = 0; i < vertexCount; i++) { var vertex = new ShadowVertex(); vertex.ReadFromCDO(stream); Vertices.Add(vertex); } for (int i = 0; i < triangleCount; i++) { var triangle = new ShadowPolygon(); triangle.ReadFromCDO(stream, false, Vertices); Triangles.Add(triangle); } for (int i = 0; i < quadCount; i++) { var quad = new ShadowPolygon(); quad.ReadFromCDO(stream, true, Vertices); Quads.Add(quad); } }
public void ReadFromCAR(Stream stream) { ushort unknown = stream.ReadUShort(); // always 0? ushort quadCount = stream.ReadUShort(); Scale = stream.ReadUShort(); ushort unknown2 = stream.ReadUShort(); // always 0? lowBoundX = stream.ReadShort(); lowBoundY = stream.ReadShort(); lowBoundZ = stream.ReadShort(); lowBoundW = stream.ReadShort(); highBoundX = stream.ReadShort(); highBoundY = stream.ReadShort(); highBoundZ = stream.ReadShort(); highBoundW = stream.ReadShort(); stream.Position += 8; int vertexCount = quadCount * 4; Vertices = new List <ShadowVertex>(vertexCount); Triangles = new List <ShadowPolygon>(); Quads = new List <ShadowPolygon>(quadCount); for (int i = 0; i < vertexCount; i++) { var vertex = new ShadowVertex(); vertex.ReadFromCAR(stream); Vertices.Add(vertex); } for (int i = 0; i < quadCount; i++) { var quad = new ShadowPolygon(); quad.ReadFromCAR(stream, Vertices, i); Quads.Add(quad); } }
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(); }