// Returns the contents of a LWOB static LightwaveObject ReadObject5(ChunkReader reader) { // allocate an object and a default layer var newObject = new LightwaveObject(); var currentLayer = new Layer(); newObject.Layers.Add(currentLayer); uint pointOffset = 0; uint polygonOffset = 0; uint tagOffset = 0; // process chunks as they're encountered while (reader.BytesLeft > 0) { var id = reader.ReadID<ChunkType>(); var cksize = reader.ReadUInt32(); cksize += cksize & 1; using (var subchunkReader = reader.GetSubChunk(cksize)) { switch (id) { case ChunkType.ID_PNTS: { pointOffset = (uint)currentLayer.Points.Count; currentLayer.Points.AddRange( ReadPoints(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_POLS: { polygonOffset = (uint)currentLayer.Polygons.Count; currentLayer.Polygons.AddRange( ReadPolygons5(subchunkReader, pointOffset) // throws exception on failure ); break; } case ChunkType.ID_SRFS: { tagOffset = (uint)newObject.Tags.Count; newObject.Tags.AddRange( LightwaveObject.ReadTags(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_SURF: { newObject.Surfaces.Add( Surface.ReadSurface5(subchunkReader, newObject) // throws exception on failure ); break; } default: Console.WriteLine("Unknown chunk type " + reader.GetIDString((uint)id)); break; } } } if (newObject.Tags.Count == 0) throw new Exception("No tags found for this layer"); // TODO: create a proper exception class uint layer_index = 0; foreach (var layer in newObject.Layers) { layer.CalculateBoundingBox(); newObject.CalculatePolygonNormals(layer.Points, layer.Polygons); newObject.ResolvePointPolygons(layer.Points, layer.Polygons); newObject.ResolvePolygonSurfaces(layer.Polygons, newObject.Tags, newObject.Surfaces, layer_index); newObject.CalculateVertexNormals(layer.Points, layer.Polygons); layer_index++; } return newObject; }
static LightwaveObject ReadObject2(ChunkReader reader) { // allocate an object and a default layer var newObject = new LightwaveObject(); var currentLayer = new Layer(); newObject.Layers.Add(currentLayer); bool createdLayer = false; uint pointOffset = 0; uint polygonOffset = 0; uint tagOffset = 0; // process chunks as they're encountered while (reader.BytesLeft > 0) { var id = reader.ReadID<ChunkType>(); var cksize = reader.ReadUInt32(); cksize += cksize & 1; using (var subchunkReader = reader.GetSubChunk(cksize)) { switch (id) { case ChunkType.ID_LAYR: { if (createdLayer) { currentLayer = new Layer(); newObject.Layers.Add(currentLayer); } createdLayer = true; currentLayer.Index = subchunkReader.ReadUInt16(); currentLayer.Flags = subchunkReader.ReadUInt16(); currentLayer.pivot_x = subchunkReader.ReadSingle(); currentLayer.pivot_y = subchunkReader.ReadSingle(); currentLayer.pivot_z = subchunkReader.ReadSingle(); currentLayer.Name = subchunkReader.ReadString(); if (subchunkReader.BytesLeft > 2) currentLayer.Parent = subchunkReader.ReadUInt16(); break; } case ChunkType.ID_PTAG: { ReadPolygonTags(subchunkReader, currentLayer.Polygons, polygonOffset, tagOffset); break; } case ChunkType.ID_BBOX: { currentLayer.bbox_min_x = subchunkReader.ReadSingle(); currentLayer.bbox_min_y = subchunkReader.ReadSingle(); currentLayer.bbox_min_z = subchunkReader.ReadSingle(); currentLayer.bbox_max_x = subchunkReader.ReadSingle(); currentLayer.bbox_max_y = subchunkReader.ReadSingle(); currentLayer.bbox_max_z = subchunkReader.ReadSingle(); break; } case ChunkType.ID_PNTS: { pointOffset = (uint)currentLayer.Points.Count; currentLayer.Points.AddRange( ReadPoints(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_POLS: { polygonOffset = (uint)currentLayer.Polygons.Count; currentLayer.Polygons.AddRange( ReadPolygons(subchunkReader, pointOffset) // throws exception on failure ); break; } case ChunkType.ID_VMAP: { currentLayer.VertexMaps.Add( VertexMap.ReadVertexMap(subchunkReader, false) // throws exception on failure ); break; } case ChunkType.ID_VMAD: { currentLayer.VertexMaps.Add( VertexMap.ReadVertexMap(subchunkReader, true) // throws exception on failure ); break; } case ChunkType.ID_TAGS: { tagOffset = (uint)newObject.Tags.Count; newObject.Tags.AddRange( LightwaveObject.ReadTags(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_ENVL: { newObject.Envelopes.Add( Envelope.ReadEnvelope(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_CLIP: { newObject.Clips.Add( Clip.ReadClip(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_SURF: { newObject.Surfaces.Add( Surface.ReadSurface(subchunkReader) // throws exception on failure ); break; } case ChunkType.ID_DESC: // Description Line - DESC { description-line[S0] } case ChunkType.ID_TEXT: // Commentary Text - TEXT { comment[S0] } case ChunkType.ID_ICON: // Thumbnail Icon Image - ICON { encoding[U2], width[U2], data[U1] * } case ChunkType.ID_VMPA: // Vertex Map Parameter - VMPA { UV subdivision type[I4], sketch color[I4] } break; default: Console.WriteLine("Unknown chunk type " + reader.GetIDString((uint)id)); break; } } } if (newObject.Tags.Count == 0) throw new Exception("No tags found for this layer"); // TODO: create a proper exception class uint layer_index = 0; foreach (var layer in newObject.Layers) { layer.CalculateBoundingBox(); newObject.CalculatePolygonNormals(layer.Points, layer.Polygons); newObject.ResolvePointPolygons(layer.Points, layer.Polygons); newObject.ResolvePolygonSurfaces(layer.Polygons, newObject.Tags, newObject.Surfaces, layer_index); newObject.CalculateVertexNormals(layer.Points, layer.Polygons); newObject.ResolvePointVertexMaps(layer.Points, layer.VertexMaps); newObject.ResolvePolygonVertexMaps(layer.Polygons, layer.VertexMaps); layer_index++; } return newObject; }