public static Clip ReadClip(ChunkReader reader) { // index var index = reader.ReadUInt32(); // first subchunk header var type = reader.ReadID<ClipType>(); var subchunk_size = reader.ReadUInt16(); subchunk_size += (ushort)(subchunk_size & 1); Clip clip = null; using (var subChunkReader = reader.GetSubChunk(subchunk_size)) { switch (type) { case ClipType.ID_STIL: { var tmp_clip = new ClipStill(index); tmp_clip.Name = subChunkReader.ReadString(); clip = tmp_clip; break; } case ClipType.ID_ISEQ: { var tmp_clip = new ClipSequence(index); tmp_clip.Digits = subChunkReader.ReadUInt8(); tmp_clip.Flags = subChunkReader.ReadUInt8(); tmp_clip.Offset = subChunkReader.ReadSInt16(); subChunkReader.ReadUInt16(); // Legacy Cruft: Nothing to see here tmp_clip.Start = subChunkReader.ReadSInt16(); tmp_clip.End = subChunkReader.ReadSInt16(); tmp_clip.Prefix = subChunkReader.ReadString(); tmp_clip.Suffix = subChunkReader.ReadString(); clip = tmp_clip; break; } case ClipType.ID_ANIM: { var tmp_clip = new ClipAnim(index); tmp_clip.Name = subChunkReader.ReadString(); tmp_clip.Server = subChunkReader.ReadString(); tmp_clip.Data = subChunkReader.ReadBytes((uint)subChunkReader.BytesLeft); clip = tmp_clip; break; } case ClipType.ID_XREF: { var tmp_clip = new ClipCloned(index); tmp_clip.clip_reference_index = subChunkReader.ReadUInt32(); tmp_clip.Name = subChunkReader.ReadString(); clip = tmp_clip; break; } case ClipType.ID_STCC: { var tmp_clip = new ClipColorCycle(index); tmp_clip.lo = subChunkReader.ReadSInt16(); tmp_clip.hi = subChunkReader.ReadSInt16(); tmp_clip.Name = subChunkReader.ReadString(); clip = tmp_clip; break; } default: throw new Exception("Unknown Clip type"); // TODO: create proper exception class for this ... } } while (reader.BytesLeft > 0) { // process subchunks as they're encountered var id = reader.ReadID<ClipDataType>(); subchunk_size = reader.ReadUInt16(); subchunk_size += (ushort)(subchunk_size & 1); using (var subChunkReader = reader.GetSubChunk(subchunk_size)) { switch (id) { //case ClipDataType.ID_CLRS: // Color Space RGB - CLRS { flags[U2], colorspace[U2], filename[FNAM0] } //case ClipDataType.ID_CLRA: // Color Space Alpha - CLRA { flags[U2], colorspace[U2], filename[FNAM0] } //case ClipDataType.ID_FILT: // Image Filtering - FILT { flags[U2] } //case ClipDataType.ID_DITH: // Image Dithering - DITH { flags[U2] } // Contrast - CONT { contrast-delta[FP4], envelope[VX] } case ClipDataType.ID_CONT: { clip.Contrast.value = subChunkReader.ReadSingle(); clip.Contrast.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Brightness - BRIT { brightness-delta[FP4], envelope[VX] } case ClipDataType.ID_BRIT: { clip.Brightness.value = subChunkReader.ReadSingle(); clip.Brightness.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Saturation - SATR { saturation-delta[FP4], envelope[VX] } case ClipDataType.ID_SATR: { clip.Saturation.value = subChunkReader.ReadSingle(); clip.Saturation.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Hue - HUE { hue-rotation[FP4], envelope[VX] } case ClipDataType.ID_HUE: { clip.Hue.value = subChunkReader.ReadSingle(); clip.Hue.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Gamma Correction - GAMM { gamma[F4], envelope[VX] } case ClipDataType.ID_GAMM: { clip.Gamma.value = subChunkReader.ReadSingle(); clip.Gamma.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; } // Negative - NEGA { enable[U2] } case ClipDataType.ID_NEGA: { clip.Negative = subChunkReader.ReadUInt16() != 0; break; } // Time - TIME { start-time[FP4], duration[FP4], frame-rate[FP4] } case ClipDataType.ID_TIME: { clip.StartTime = subChunkReader.ReadSingle(); clip.Duration = subChunkReader.ReadSingle(); clip.FrameRate = subChunkReader.ReadSingle(); break; } // Plug-in Image Filters - IFLT { server-name[S0], flags[U2], data[...] } case ClipDataType.ID_IFLT: // Plug-in Pixel Filters - PFLT { server-name[S0], flags[U2], data[...] } case ClipDataType.ID_PFLT: { var filt = new LightwavePlugin(); filt.name = subChunkReader.ReadString(); filt.flags = subChunkReader.ReadUInt16(); filt.data = subChunkReader.ReadBytes((uint)subChunkReader.BytesLeft); if (id == ClipDataType.ID_IFLT) clip.ImageFilters.Add(filt); else clip.PixelFilters.Add(filt); break; } case ClipDataType.ID_FLAG: // not mentioned in documentation ... var flags = subChunkReader.ReadUInt16(); // unknown what they mean ... break; default: Console.WriteLine("Unknown clip type " + reader.GetIDString((uint)id)); break; } } } return clip; }
public static Envelope ReadEnvelope(ChunkReader reader) { var env = new Envelope(); // allocate the Envelope structure env.Index = reader.ReadVariableLengthIndex(); // index EnvelopeKey lastKey = null; while (reader.BytesLeft > 0) { // process subchunks as they're encountered var id = reader.ReadID<EnvelopeType>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case EnvelopeType.ID_TYPE: { env.Type = subChunkReader.ReadUInt16(); break; } case EnvelopeType.ID_NAME: { env.Name = subChunkReader.ReadString(); break; } case EnvelopeType.ID_PRE: { env.PreBehavior = (EvalType)subChunkReader.ReadUInt16(); break; } case EnvelopeType.ID_POST: { env.PostBehavior = (EvalType)subChunkReader.ReadUInt16(); break; } case EnvelopeType.ID_KEY: { lastKey = new EnvelopeKey( subChunkReader.ReadSingle(), // time subChunkReader.ReadSingle() // value ); env.Keys.Add(lastKey); //TODO: not sort all the time env.Keys.Sort((Comparison<EnvelopeKey>)delegate(EnvelopeKey k1, EnvelopeKey k2) { return k1.Time > k2.Time ? 1 : k1.Time < k2.Time ? -1 : 0; }); break; } case EnvelopeType.ID_SPAN: { if (lastKey == null) // We should've encountered an ID_KEY before an ID_SPAN throw new Exception("Key not defined"); //TODO: make proper exception class lastKey.Shape = subChunkReader.ReadID<KeyShape>(); switch (lastKey.Shape) { case KeyShape.ID_TCB: { lastKey.Tension = subChunkReader.ReadSingle(); lastKey.Continuity = subChunkReader.ReadSingle(); lastKey.Bias = subChunkReader.ReadSingle(); break; } case KeyShape.ID_BEZI: case KeyShape.ID_HERM: case KeyShape.ID_BEZ2: { Array.Clear(lastKey.param, 0, lastKey.param.Length); int i = 0; while (i < 4 && subChunkReader.BytesLeft > 0) { lastKey.param[i] = subChunkReader.ReadSingle(); i++; } break; } case KeyShape.ID_LINE: break; default: Console.WriteLine("Unknown envelope span shape type " + reader.GetIDString((uint)lastKey.Shape)); break; } break; } case EnvelopeType.ID_CHAN: { var plug = new LightwavePlugin(); plug.name = subChunkReader.ReadString(); plug.flags = subChunkReader.ReadUInt16(); plug.data = subChunkReader.ReadBytes((uint)reader.BytesLeft); env.ChannelFilters.Add(plug); break; } default: Console.WriteLine("Unknown envelope type " + reader.GetIDString((uint)id)); break; } } } return env; }
public static TextureMap ReadTextureMap(ChunkReader reader) { var tmap = new TextureMap(); while (reader.BytesLeft > 0) { var id = reader.ReadID<TextureCoordinates>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case TextureCoordinates.ID_SIZE: tmap.Size.values[0] = subChunkReader.ReadSingle(); tmap.Size.values[1] = subChunkReader.ReadSingle(); tmap.Size.values[2] = subChunkReader.ReadSingle(); tmap.Size.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case TextureCoordinates.ID_CNTR: tmap.Size.values[0] = subChunkReader.ReadSingle(); tmap.Size.values[1] = subChunkReader.ReadSingle(); tmap.Size.values[2] = subChunkReader.ReadSingle(); tmap.Center.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case TextureCoordinates.ID_ROTA: tmap.Size.values[0] = subChunkReader.ReadSingle(); tmap.Size.values[1] = subChunkReader.ReadSingle(); tmap.Size.values[2] = subChunkReader.ReadSingle(); tmap.Rotate.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case TextureCoordinates.ID_FALL: tmap.FallType = subChunkReader.ReadUInt16(); tmap.Size.values[0] = subChunkReader.ReadSingle(); tmap.Size.values[1] = subChunkReader.ReadSingle(); tmap.Size.values[2] = subChunkReader.ReadSingle(); tmap.FallOff.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case TextureCoordinates.ID_OREF: tmap.ReferenceObject = subChunkReader.ReadString(); break; case TextureCoordinates.ID_CSYS: tmap.CoordinateSystem = subChunkReader.ReadUInt16(); break; default: Console.WriteLine("Unknown texture map type " + reader.GetIDString((uint)id)); break; } } } return tmap; }
public static VertexMap ReadVertexMap(ChunkReader reader, bool perpoly) { var type = reader.ReadID<VertexMapType>(); var dimensions = reader.ReadUInt16(); var name = reader.ReadString(); var vertex_map = new VertexMap(type, name, perpoly); var vertex_indices = new List<uint>(); var polygon_indices = new List<uint>(); var values = new List<float[]>(); // fill in the vertex-map values while (reader.BytesLeft > 0) { vertex_indices.Add(reader.ReadVariableLengthIndex()); if (perpoly) polygon_indices.Add(reader.ReadVariableLengthIndex()); var pointValues = new float[dimensions]; for (var j = 0; j < dimensions; j++) pointValues[j] = reader.ReadSingle(); values.Add(pointValues); } vertex_map.Values = values.ToArray(); vertex_map.vertex_index = vertex_indices.ToArray(); if (perpoly) vertex_map.polygon_index = polygon_indices.ToArray(); return vertex_map; }
bool ReadImageMap(ChunkReader reader) { while (reader.BytesLeft > 0) { // get the next subchunk header var id = reader.ReadID<ImageMapType>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case ImageMapType.ID_TMAP: { tmap = TextureMap.ReadTextureMap(subChunkReader); break; } case ImageMapType.ID_PROJ: imap.projection = (ProjectionType)subChunkReader.ReadUInt16(); break; case ImageMapType.ID_VMAP: imap.vertex_map_name = subChunkReader.ReadString(); break; case ImageMapType.ID_AXIS: imap.axis = subChunkReader.ReadUInt16(); break; case ImageMapType.ID_IMAG: imap.clip_index = subChunkReader.ReadVariableLengthIndex(); break; case ImageMapType.ID_PIXB: imap.pblend = subChunkReader.ReadUInt16(); break; case ImageMapType.ID_WRAP: imap.wrapw_type = (WrapType)subChunkReader.ReadUInt16(); imap.wraph_type = (WrapType)subChunkReader.ReadUInt16(); break; case ImageMapType.ID_WRPW: imap.wrapw.value = subChunkReader.ReadSingle(); imap.wrapw.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case ImageMapType.ID_WRPH: imap.wraph.value = subChunkReader.ReadSingle(); imap.wraph.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case ImageMapType.ID_AAST: imap.aas_flags = subChunkReader.ReadUInt16(); imap.aa_strength = subChunkReader.ReadSingle(); break; case ImageMapType.ID_STCK: imap.stck.value = subChunkReader.ReadSingle(); imap.stck.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case ImageMapType.ID_TAMP: imap.amplitude.value = subChunkReader.ReadSingle(); imap.amplitude.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; default: Console.WriteLine("Unknown image map type " + reader.GetIDString((uint)id)); break; } } } return true; }
bool ReadProcedural(ChunkReader reader) { while (reader.BytesLeft > 0) { var id = reader.ReadID<ProceduralType>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case ProceduralType.ID_TMAP: { tmap = TextureMap.ReadTextureMap(subChunkReader); break; } case ProceduralType.ID_AXIS: { proc.axis = subChunkReader.ReadUInt16(); break; } case ProceduralType.ID_VALU: { proc.value_0 = subChunkReader.ReadSingle(); if (sz >= 8) proc.value_1 = subChunkReader.ReadSingle(); if (sz >= 12) proc.value_2 = subChunkReader.ReadSingle(); break; } case ProceduralType.ID_FUNC: { proc.name = subChunkReader.ReadString(); proc.data = subChunkReader.ReadBytes((uint)subChunkReader.BytesLeft); break; } default: Console.WriteLine("Unknown procedural map type " + reader.GetIDString((uint)id)); break; } } } return true; }
public static Texture ReadTexture(ChunkReader reader, TextureType type) { var tex = new Texture(type); var header_size = reader.ReadUInt16(); using (var headerReader = reader.GetSubChunk(header_size)) { // ordinal string tex.ord = headerReader.ReadString(); // process subchunks as they're encountered while (headerReader.BytesLeft > 0) { var subchunk_id = headerReader.ReadID<TextureDataType>(); var subchunk_size = headerReader.ReadUInt16(); subchunk_size += (ushort)(subchunk_size & 1); using (var subChunkReader = headerReader.GetSubChunk(subchunk_size)) { switch (subchunk_id) { case TextureDataType.ID_CHAN: tex.Channel = subChunkReader.ReadID<TextureChannel>(); break; case TextureDataType.ID_OPAC: tex.opac_type = subChunkReader.ReadUInt16(); tex.opacity.value = subChunkReader.ReadSingle(); tex.opacity.envelope_index = subChunkReader.ReadVariableLengthIndex(); break; case TextureDataType.ID_ENAB: tex.enabled = subChunkReader.ReadUInt16(); break; case TextureDataType.ID_NEGA: tex.negative = subChunkReader.ReadUInt16(); break; case TextureDataType.ID_AXIS: tex.axis = subChunkReader.ReadUInt16(); break; default: Console.WriteLine("Unknown texture header type " + reader.GetIDString((uint)subchunk_id)); break; } } } } if (reader.BytesLeft > 0) { using (var blockReader = reader.GetSubChunk((uint)reader.BytesLeft)) { switch (type) { case TextureType.ID_IMAP: tex.ReadImageMap(blockReader); break; case TextureType.ID_PROC: tex.ReadProcedural(blockReader); break; case TextureType.ID_GRAD: tex.ReadGradient(blockReader); break; default: Console.WriteLine("Unknown texture type " + reader.GetIDString((uint)type)); break; } } } return tex; }
bool ReadGradient(ChunkReader reader) { while (reader.BytesLeft > 0) { var id = reader.ReadID<GradientType>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case GradientType.ID_TMAP: { tmap = TextureMap.ReadTextureMap(subChunkReader); break; } case GradientType.ID_PNAM: { grad.paramname = subChunkReader.ReadString(); break; } case GradientType.ID_INAM: { grad.itemname = subChunkReader.ReadString(); break; } case GradientType.ID_GRST: { grad.start = subChunkReader.ReadSingle(); break; } case GradientType.ID_GREN: { grad.end = subChunkReader.ReadSingle(); break; } case GradientType.ID_GRPT: { grad.repeat = subChunkReader.ReadUInt16(); break; } case GradientType.ID_FKEY: { var keys = new List<GradientKey>(); while (subChunkReader.BytesLeft > 0) { var key = new GradientKey(); key.value = subChunkReader.ReadSingle(); key.rgba_0 = subChunkReader.ReadSingle(); key.rgba_1 = subChunkReader.ReadSingle(); key.rgba_2 = subChunkReader.ReadSingle(); key.rgba_3 = subChunkReader.ReadSingle(); keys.Add(key); } grad.Keys = keys.ToArray(); break; } case GradientType.ID_IKEY: { var ikeys = new List<ushort>(); while (subChunkReader.BytesLeft > 0) ikeys.Add(subChunkReader.ReadUInt16()); grad.ikey = ikeys.ToArray(); break; } case GradientType.ID_GVER: // unknown, not mentioned in lightwave sdk documentation break; default: Console.WriteLine("Unknown gradient type " + reader.GetIDString((uint)id)); break; } } } return true; }
// 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; }
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; }
public static LightwavePlugin ReadShader(ChunkReader reader) { var shader = new LightwavePlugin(); var hsz = reader.ReadUInt16(); // Q: example code does this, but can't find this in documentation? shader.ord = reader.ReadString(); using (var headerReader = reader.GetSubChunk(hsz)) { while (headerReader.BytesLeft > 0) { var id = headerReader.ReadID<PluginType>(); var sz = headerReader.ReadUInt16(); sz += (ushort)(sz & 1); hsz -= sz; if (id == PluginType.ID_ENAB) { shader.flags = headerReader.ReadUInt16(); break; } } } while (reader.BytesLeft > 0) { var id = reader.ReadID<PluginType>(); var sz = reader.ReadUInt16(); sz += (ushort)(sz & 1); using (var subChunkReader = reader.GetSubChunk(sz)) { switch (id) { case PluginType.ID_FUNC: { shader.name = subChunkReader.ReadString(); shader.data = subChunkReader.ReadBytes((uint)subChunkReader.BytesLeft); break; } default: //Console.WriteLine("Unknown shader type " + reader.GetIDString((uint)id)); break; } } } return shader; }
// LWOB static IEnumerable<Polygon> ReadPolygons5(ChunkReader reader, uint vertex_offset) { // fill in the new polygons while (reader.BytesLeft > 0) { var vertex_count = reader.ReadUInt16(); var newPolygon = new Polygon(PolygonType.ID_FACE); for (var j = 0; j < vertex_count; j++) newPolygon.Vertices.Add( new PolygonVertex(reader.ReadUInt16() + vertex_offset) ); var index = (int)reader.ReadSInt16(); if (index < 0) { index = (int)-index; reader.ReadSInt16(); // skip 2 bytes - Q: why?? } newPolygon.surf_index = (uint)(index - 1); yield return newPolygon; } }
static IEnumerable<Polygon> ReadPolygons(ChunkReader reader, uint vertex_offset) { var type = reader.ReadID<PolygonType>(); // fill in the new polygons while (reader.BytesLeft > 0) { var vertex_count = reader.ReadUInt16(); var flags = vertex_count & 0xFC00; vertex_count &= 0x03FF; var newPolygon = new Polygon(type, flags); for (var j = 0; j < vertex_count; j++) newPolygon.Vertices.Add( new PolygonVertex(reader.ReadVariableLengthIndex() + vertex_offset) ); yield return newPolygon; } }