public static Surface ReadSurface(ChunkReader reader) { // allocate the Surface structure var surf = new Surface(); // names surf.name = reader.ReadString(); surf.srcname = reader.ReadString(); // process subchunks as they're encountered while (reader.BytesLeft > 0) { var id = reader.ReadID<SurfaceParameter>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { // Vertex Color Map - VCOL { intensity[FP4], envelope[VX], vmap-type[ID4], name[S0] } // The vertex color map subchunk identifies an RGB or RGBA VMAP that will be used to color the surface case SurfaceParameter.ID_VCOL: { var intensity = subChunkReader.ReadSingle(); var envelope_index = subChunkReader.ReadVariableLengthIndex(); var vmap_type = subChunkReader.ReadUInt32(); var name = subChunkReader.ReadString(); break; } case SurfaceParameter.ID_CMNT: // Not mentioned in LWO documentation, maybe means 'comment'? { break; } case SurfaceParameter.ID_VERS: // Not mentioned in LWO documentation, maybe means 'version'? { break; } case SurfaceParameter.ID_NODS: // Not mentioned in LWO documentation, maybe means 'nodes'? { break; } case SurfaceParameter.ID_COLR: { surf.color.Red = subChunkReader.ReadSingle(); surf.color.Green = subChunkReader.ReadSingle(); surf.color.Blue = subChunkReader.ReadSingle(); surf.color.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } case SurfaceParameter.ID_LUMI: surf.luminosity.Value = subChunkReader.ReadSingle(); surf.luminosity.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_DIFF: surf.diffuse.Value = subChunkReader.ReadSingle(); surf.diffuse.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_SPEC: surf.specularity.Value = subChunkReader.ReadSingle(); surf.specularity.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_GLOS: surf.glossiness.Value = subChunkReader.ReadSingle(); surf.glossiness.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_REFL: surf.reflection.values.Value = subChunkReader.ReadSingle(); surf.reflection.values.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_RFOP: surf.reflection.options = subChunkReader.ReadUInt16(); break; case SurfaceParameter.ID_RIMG: surf.reflection.clip_index = subChunkReader.ReadVariableLengthIndex(); break; // Reflection Blurring - RBLR { blur-percentage[FP4], envelope[VX] } // The amount of blurring of reflections. The default is zero. case SurfaceParameter.ID_RBLR: break; case SurfaceParameter.ID_RSAN: surf.reflection.seam_angle = subChunkReader.ReadSingle(); break; case SurfaceParameter.ID_TRAN: surf.transparency.values.Value = subChunkReader.ReadSingle(); surf.transparency.values.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_TROP: surf.transparency.options = subChunkReader.ReadUInt16(); break; case SurfaceParameter.ID_TIMG: surf.transparency.clip_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_RIND: surf.eta.Value = subChunkReader.ReadSingle(); surf.eta.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_TRNL: surf.translucency.Value = subChunkReader.ReadSingle(); surf.translucency.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_BUMP: surf.bump.Value = subChunkReader.ReadSingle(); surf.bump.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_SMAN: surf.smooth = subChunkReader.ReadSingle(); break; case SurfaceParameter.ID_SIDE: surf.sideflags = subChunkReader.ReadUInt16(); break; case SurfaceParameter.ID_CLRH: surf.color_hilite.value = subChunkReader.ReadSingle(); surf.color_hilite.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_CLRF: surf.color_filter.value = subChunkReader.ReadSingle(); surf.color_filter.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_ADTR: surf.add_trans.value = subChunkReader.ReadSingle(); surf.add_trans.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_SHRP: surf.dif_sharp.value = subChunkReader.ReadSingle(); surf.dif_sharp.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_GVAL: surf.glow.value = subChunkReader.ReadSingle(); surf.glow.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; // Render Outlines - LINE { flags[U2], ( size[F4], size-envelope[VX], ( color[COL12], color-envelope[VX] )? )? } case SurfaceParameter.ID_LINE: surf.line.enabled = 1; if (sz >= 2) surf.line.flags = subChunkReader.ReadUInt16(); if (sz >= 6) surf.line.size.value = subChunkReader.ReadSingle(); if (sz >= 8) surf.line.size.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case SurfaceParameter.ID_ALPH: surf.alpha_mode = subChunkReader.ReadUInt16(); surf.alpha = subChunkReader.ReadSingle(); break; case SurfaceParameter.ID_AVAL: surf.alpha = subChunkReader.ReadSingle(); break; case SurfaceParameter.ID_BLOK: { var type = subChunkReader.ReadID<TextureType>(); switch (type) { case TextureType.ID_IMAP: case TextureType.ID_PROC: case TextureType.ID_GRAD: { using (var blockReader = subChunkReader.GetSubChunk((uint)subChunkReader.BytesLeft)) { var tex = Texture.ReadTexture(blockReader, type); switch ( tex.Channel ) { case TextureChannel.ID_COLR: surf.color .textures.Add(tex); break; case TextureChannel.ID_LUMI: surf.luminosity .textures.Add(tex); break; case TextureChannel.ID_DIFF: surf.diffuse .textures.Add(tex); break; case TextureChannel.ID_SPEC: surf.specularity .textures.Add(tex); break; case TextureChannel.ID_GLOS: surf.glossiness .textures.Add(tex); break; case TextureChannel.ID_REFL: surf.reflection .values .textures.Add(tex); break; case TextureChannel.ID_TRAN: surf.transparency .values .textures.Add(tex); break; case TextureChannel.ID_RIND: surf.eta .textures.Add(tex); break; case TextureChannel.ID_TRNL: surf.translucency .textures.Add(tex); break; case TextureChannel.ID_BUMP: surf.bump .textures.Add(tex); break; default: throw new Exception("Unknown texture channel"); // TODO: create proper exception calass for this } } break; } case TextureType.ID_SHDR: { using (var blockReader = subChunkReader.GetSubChunk((uint)subChunkReader.BytesLeft)) { surf.shader.Add( LightwavePlugin.ReadShader(blockReader) ); } break; } default: Console.WriteLine("Unknown blok type " + reader.GetIDString((uint)type)); break; } break; } default: Console.WriteLine("Unknown surface parameter type " + reader.GetIDString((uint)id)); break; } } } return surf; }
// LWOB public static Surface ReadSurface5(ChunkReader reader, LightwaveObject obj) { var surf = new Surface(); surf.name = reader.ReadString(); Texture tex = null; LightwavePlugin shdr = null; float[] v = new float[3]; uint flags = 0; // process subchunks as they're encountered while (reader.BytesLeft > 0) { var id = reader.ReadID<SurfaceParameter>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case SurfaceParameter.ID_COLR: { surf.color.Red = subChunkReader.ReadUInt8() / 255.0f; surf.color.Green = subChunkReader.ReadUInt8() / 255.0f; surf.color.Blue = subChunkReader.ReadUInt8() / 255.0f; break; } case SurfaceParameter.ID_FLAG: { flags = subChunkReader.ReadUInt16(); if ((flags & 4) != 0) surf.smooth = 1.56207f; if ((flags & 8) != 0) surf.color_hilite.value = 1.0f; if ((flags & 16) != 0) surf.color_filter.value = 1.0f; if ((flags & 128) != 0) surf.dif_sharp.value = 0.5f; if ((flags & 256) != 0) surf.sideflags = 3; if ((flags & 512) != 0) surf.add_trans.value = 1.0f; break; } case SurfaceParameter.ID_LUMI: { surf.luminosity.Value = subChunkReader.ReadSInt16() / 256.0f; break; } case SurfaceParameter.ID_VLUM: { surf.luminosity.Value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_DIFF: { surf.diffuse.Value = subChunkReader.ReadSInt16() / 256.0f; break; } case SurfaceParameter.ID_VDIF: { surf.diffuse.Value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_SPEC: { surf.specularity.Value = subChunkReader.ReadSInt16() / 256.0f; break; } case SurfaceParameter.ID_VSPC: { surf.specularity.Value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_GLOS: { surf.glossiness.Value = (float)Math.Log(subChunkReader.ReadUInt16()) / 20.7944f; break; } case SurfaceParameter.ID_SMAN: { surf.smooth = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_REFL: { surf.reflection.values.Value = subChunkReader.ReadSInt16() / 256.0f; break; } case SurfaceParameter.ID_RFLT: { surf.reflection.options = subChunkReader.ReadUInt16(); break; } case SurfaceParameter.ID_RIMG: { var s = subChunkReader.ReadString(); surf.reflection.clip_index = AddClip(s, obj.Clips); surf.reflection.options = 3; break; } case SurfaceParameter.ID_RSAN: { surf.reflection.seam_angle = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TRAN: { surf.transparency.values.Value = subChunkReader.ReadSInt16() / 256.0f; break; } case SurfaceParameter.ID_RIND: { surf.eta.Value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_BTEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.bump.textures.Add(tex); break; } case SurfaceParameter.ID_CTEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.color.textures.Add(tex); break; } case SurfaceParameter.ID_DTEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.diffuse.textures.Add(tex); break; } case SurfaceParameter.ID_LTEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.luminosity.textures.Add(tex); break; } case SurfaceParameter.ID_RTEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.reflection.values.textures.Add(tex); break; } case SurfaceParameter.ID_STEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.specularity.textures.Add(tex); break; } case SurfaceParameter.ID_TTEX: { var s = subChunkReader.ReadString(sz);//.getbytes((uint)sz); tex = ParseTexture(s); surf.transparency.values.textures.Add(tex); break; } case SurfaceParameter.ID_TFLG: { if (tex == null) return null; flags = subChunkReader.ReadUInt16(); int i = 0; if ((flags & 1) != 0) i = 0; if ((flags & 2) != 0) i = 1; if ((flags & 4) != 0) i = 2; tex.axis = (ushort)i; if (tex.Type == TextureType.ID_IMAP) tex.imap.axis = i; else tex.proc.axis = i; if ((flags & 8) != 0) tex.tmap.CoordinateSystem = 1; if ((flags & 16) != 0) tex.negative = 1; if ((flags & 32) != 0) tex.imap.pblend = 1; if ((flags & 64) != 0) { tex.imap.aa_strength = 1.0f; tex.imap.aas_flags = 1; } break; } case SurfaceParameter.ID_TSIZ: { tex.tmap.Size.values[0] = subChunkReader.ReadSingle(); tex.tmap.Size.values[1] = subChunkReader.ReadSingle(); tex.tmap.Size.values[2] = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TCTR: { tex.tmap.Center.values[0] = subChunkReader.ReadSingle(); tex.tmap.Center.values[1] = subChunkReader.ReadSingle(); tex.tmap.Center.values[2] = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TFAL: { tex.tmap.FallOff.values[0] = subChunkReader.ReadSingle(); tex.tmap.FallOff.values[1] = subChunkReader.ReadSingle(); tex.tmap.FallOff.values[2] = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TVEL: { for (var i = 0; i < 3; i++) v[i] = subChunkReader.ReadSingle(); tex.tmap.Center.envelope_index = AddTextureVelocity(tex.tmap.Center.values, v, obj.Envelopes); break; } case SurfaceParameter.ID_TCLR: { if (tex.Type == TextureType.ID_PROC) { tex.proc.value_0 = subChunkReader.ReadUInt8() / 255.0f; tex.proc.value_1 = subChunkReader.ReadUInt8() / 255.0f; tex.proc.value_2 = subChunkReader.ReadUInt8() / 255.0f; } break; } case SurfaceParameter.ID_TVAL: { tex.proc.value_0 = subChunkReader.ReadSInt16() / 256.0f; break; } case SurfaceParameter.ID_TAMP: { if (tex.Type == TextureType.ID_IMAP) tex.imap.amplitude.value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TIMG: { var s = subChunkReader.ReadString(); tex.imap.clip_index = AddClip(s, obj.Clips); break; } case SurfaceParameter.ID_TAAS: { tex.imap.aa_strength = subChunkReader.ReadSingle(); tex.imap.aas_flags = 1; break; } case SurfaceParameter.ID_TREF: { tex.tmap.ReferenceObject = subChunkReader.ReadString((uint)sz);//.getbytes((uint)sz); break; } case SurfaceParameter.ID_TOPC: { tex.opacity.value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TFP0: { if (tex.Type == TextureType.ID_IMAP) tex.imap.wrapw.value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_TFP1: { if (tex.Type == TextureType.ID_IMAP) tex.imap.wraph.value = subChunkReader.ReadSingle(); break; } case SurfaceParameter.ID_SHDR: { shdr = new LightwavePlugin(); if (shdr == null) return null; shdr.name = subChunkReader.ReadString((uint)sz); surf.shader.Add(shdr); break; } case SurfaceParameter.ID_SDAT: { if (shdr == null) return null; shdr.data = subChunkReader.ReadBytes(sz); break; } default: Console.WriteLine("Unknown surface parameter type " + reader.GetIDString((uint)id)); break; } } } return surf; }
void ResolvePolygonSurfaces(List<Polygon> polygonList, List<string> surfaceNames, List<Surface> surfaceList, uint layerIndex) { var surfaceLookup = new Surface[surfaceNames.Count]; for (var i = 0; i < surfaceNames.Count; i++) { foreach (var surface in surfaceList) { if (string.Compare(surface.name, surfaceNames[i]) == 0) { surfaceLookup[i] = surface; break; } } } foreach (var polygon in polygonList) { polygon.layer_index = layerIndex; var surface_index = (int)polygon.surf_index; if (surface_index < 0 || surface_index > surfaceLookup.Length) throw new Exception("Surface index out of bounds"); // TODO: create a proper exception class // make sure the surface exists, even if it's empty ... if (surfaceLookup[surface_index] == null) { var new_surface = new Surface(); new_surface.name = surfaceNames[surface_index]; surfaceList.Add(new_surface); surfaceLookup[surface_index] = new_surface; } polygon.SurfaceReference = surfaceLookup[surface_index]; } }