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; }
//====================================================================== // AddTextureVelocity() // // Add a triple of envelopes to simulate the old texture velocity // parameters. //====================================================================== static uint AddTextureVelocity(float[] pos, float[] vel, List<Envelope> elist) { Envelope env = null; for (var i = 0; i < 3; i++) { env = new Envelope(); var key0 = new EnvelopeKey(0, // time pos[i]); // value var key1 = new EnvelopeKey(1, // time pos[i] + vel[i] * 30.0f); // value key0.Shape = key1.Shape = KeyShape.ID_LINE; env.Index = (uint)(elist.Count + 1); // Q: shouldn't this be + 0? env.Type = 0x0301 + i; env.Name = "Position." + i; env.Keys.Add(key0); env.Keys.Add(key1); env.PreBehavior = EvalType.BEH_LINEAR; env.PostBehavior = EvalType.BEH_LINEAR; elist.Add(env); } return env.Index - 2; // Q: why the -2? }