/// <summary> /// Initializes a new instance of the <see cref="NiParticlesData"/> class. /// </summary> /// <param name="file">The file.</param> /// <param name="reader">The reader.</param> public NiParticlesData(NiFile file, BinaryReader reader) : base(file, reader) { if (this.File.Header.Version <= eNifVersion.VER_4_0_0_2) { this.NumParticles = reader.ReadUInt16(); } if (this.File.Header.Version <= eNifVersion.VER_10_0_1_0) { this.ParticleRadius = reader.ReadSingle(); } if (this.File.Header.Version >= eNifVersion.VER_10_1_0_0) { this.HasRadii = reader.ReadBoolean(Version); if (this.HasRadii) { this.Radii = reader.ReadFloatArray((int)this.NumVertices); } } this.NumActive = reader.ReadUInt16(); this.HasSizes = reader.ReadBoolean(Version); if (this.HasSizes) { this.Sizes = reader.ReadFloatArray((int)this.NumVertices); } if (this.File.Header.Version >= eNifVersion.VER_10_0_1_0) { this.HasRotations = reader.ReadBoolean(Version); if (this.HasRotations) { this.Rotations = new Vector4[this.NumVertices]; int num = 0; while ((long)num < (long)((ulong)this.NumVertices)) { this.Rotations[num] = reader.ReadVector4(); num++; } } } }
// TODO: // // 1. Figure out how the bone remap indices work // They seem to be tied to the used bone indices somehow // Maybe building up an hierarchy as the same indices appear multiple times // Indices that aren't in the used bone indices are set to 0xFF // // 2. Figure out the BoneRLE // First byte is the hierarchy index of the affected bone // Second byte seems to be something like how many bones it shares weights with on the same material split? // // 3. Figure out the inverse matrices // I can currently just copy and paste the one from the original file // But knowing how to calculate it would be a lot easier internal RWSkinPlugin(RWNodeFactory.RWNodeInfo header, BinaryReader reader, RWMesh rwGeometry) : base(header) { int numVertices = rwGeometry.VertexCount; m_numBones = reader.ReadByte(); m_numUsedBones = reader.ReadByte(); m_numWeightPerVertex = reader.ReadByte(); m_unused = reader.ReadByte(); m_usedBoneIndices = reader.ReadBytes(m_numUsedBones); m_skinBoneIndices = new byte[numVertices][]; for (int i = 0; i < numVertices; i++) { m_skinBoneIndices[i] = reader.ReadBytes(4); } m_skinBoneWeights = new float[numVertices][]; for (int i = 0; i < numVertices; i++) { m_skinBoneWeights[i] = reader.ReadFloatArray(4); } m_inverseBoneMatrices = new Matrix4x4[m_numBones]; for (int i = 0; i < BoneCount; i++) { Matrix4x4 mtx = Matrix4x4.Identity; mtx.M11 = reader.ReadSingle(); mtx.M12 = reader.ReadSingle(); mtx.M13 = reader.ReadSingle(); reader.BaseStream.Position += 4; mtx.M21 = reader.ReadSingle(); mtx.M22 = reader.ReadSingle(); mtx.M23 = reader.ReadSingle(); reader.BaseStream.Position += 4; mtx.M31 = reader.ReadSingle(); mtx.M32 = reader.ReadSingle(); mtx.M33 = reader.ReadSingle(); reader.BaseStream.Position += 4; mtx.M41 = reader.ReadSingle(); mtx.M42 = reader.ReadSingle(); mtx.M43 = reader.ReadSingle(); reader.BaseStream.Position += 4; m_inverseBoneMatrices[i] = mtx; } m_boneLimit = reader.ReadInt32(); m_numMaterialSplit = reader.ReadInt32(); m_materialSplitNumUsedBones = reader.ReadInt32(); if (m_numMaterialSplit < 1) return; m_boneRemapIndices = reader.ReadBytes(m_numBones); m_materialSplitSkinInfo = new MaterialSplitSkinInfo[m_numMaterialSplit]; for (int i = 0; i < m_numMaterialSplit; i++) m_materialSplitSkinInfo[i] = new MaterialSplitSkinInfo { UsedBonesStartIndex = reader.ReadByte(), NumUsedBones = reader.ReadByte() }; m_materialSplitUsedBoneInfo = new MaterialSplitUsedBoneInfo[m_materialSplitNumUsedBones]; for (int i = 0; i < m_materialSplitNumUsedBones; i++) m_materialSplitUsedBoneInfo[i] = new MaterialSplitUsedBoneInfo { UsedBoneHierarchyIndex = reader.ReadByte(), Unknown = reader.ReadByte() }; PrintInfo(); }
/// <summary> /// Initializes a new instance of the <see cref="SkinPartition"/> class. /// </summary> /// <param name="file">The file.</param> /// <param name="reader">The reader.</param> public SkinPartition(NiFile file, BinaryReader reader) { this.NumVertices = reader.ReadUInt16(); this.NumTriangles = reader.ReadUInt16(); this.NumBones = reader.ReadUInt16(); this.NumStrips = reader.ReadUInt16(); this.NumWeightsPerVertex = reader.ReadUInt16(); this.Bones = reader.ReadUInt16Array((int)this.NumBones); this.HasVertexMap = true; this.HasVertexWeights = true; this.HasFaces = true; if (file.Version >= eNifVersion.VER_10_1_0_0) { this.HasVertexMap = reader.ReadBoolean(file.Version); } if (this.HasVertexMap) { this.VertexMap = reader.ReadUInt16Array((int)this.NumVertices); } if (file.Version >= eNifVersion.VER_10_1_0_0) { this.HasVertexWeights = reader.ReadBoolean(file.Version); } if (this.HasVertexWeights) { this.VertexWeights = new float[(int)this.NumVertices][]; for (int i = 0; i < (int)this.NumVertices; i++) { this.VertexWeights[i] = reader.ReadFloatArray((int)this.NumWeightsPerVertex); } } this.StripLengths = reader.ReadUInt16Array((int)this.NumStrips); if (file.Version >= eNifVersion.VER_10_1_0_0) { this.HasFaces = reader.ReadBoolean(file.Version); } if (this.HasFaces && this.NumStrips != 0) { this.Strips = new ushort[(int)this.NumStrips][]; for (int j = 0; j < (int)this.NumStrips; j++) { this.Strips[j] = reader.ReadUInt16Array((int)this.StripLengths[j]); } } else if (this.HasFaces && this.NumStrips == 0) { this.Triangles = new Triangle[(int)this.NumTriangles]; for (int k = 0; k < this.Triangles.Length; k++) { this.Triangles[k] = new Triangle(reader); } } this.HasBoneIndicies = reader.ReadBoolean(file.Version); if (this.HasBoneIndicies) { this.BoneIndicies = new byte[(int)this.NumVertices][]; for (int l = 0; l < this.BoneIndicies.Length; l++) { this.BoneIndicies[l] = new byte[(int)this.NumWeightsPerVertex]; for (int m = 0; m < (int)this.NumWeightsPerVertex; m++) { this.BoneIndicies[l][m] = reader.ReadByte(); } } } if (file.Header.UserVersion >= 12u) { this.UnkownShort = reader.ReadUInt16(); } if (file.Version == eNifVersion.VER_10_2_0_0 && file.Header.UserVersion == 1u) { this.UnkownShort2 = reader.ReadUInt16(); this.UnkownShort3 = reader.ReadUInt16(); this.NumVertices2 = reader.ReadUInt16(); this.UnkownShort4 = reader.ReadUInt16(); this.UnkownShort5 = reader.ReadUInt16(); this.UnkownShort6 = reader.ReadUInt16(); this.UnkownArr = new SkinPartitionUnkownItem1[(int)this.NumVertices2]; for (int n = 0; n < (int)this.NumVertices2; n++) { this.UnkownArr[n] = new SkinPartitionUnkownItem1(file, reader); } } }
// Private Methods private void Read(BinaryReader reader) { _id = reader.ReadUInt32(); _flags = reader.ReadUInt32(); for (int i = 16; i < 31; i++) { if (BitHelper.IsBitSet(_flags, i)) { switch (i) { case 16: _color1 = Color.FromArgb(reader.ReadInt32()); break; case 17: _color2 = Color.FromArgb(reader.ReadInt32()); break; case 18: _textureID = reader.ReadUInt32(); break; case 19: _floatArray1 = reader.ReadFloatArray(5); break; case 20: _color3 = Color.FromArgb(reader.ReadInt32()); break; case 21: _shortArray1 = reader.ReadUInt16Array(2); break; case 22: _floatArray2 = reader.ReadFloatArray(5); break; case 23: _color4 = Color.FromArgb(reader.ReadInt32()); break; case 25: _float1 = reader.ReadSingle(); break; case 26: _floatArray3 = reader.ReadFloatArray(2); break; default: throw new NotImplementedException("Unknown material flag bit set"); } } } }
/// <summary> /// Initializes a new instance of the <see cref="NiParticleSystemController" /> class. /// </summary> /// <param name="file">The file.</param> /// <param name="reader">The reader.</param> public NiParticleSystemController(NiFile file, BinaryReader reader) : base(file, reader) { if (base.Version <= eNifVersion.VER_3_1) { this.OldSpeed = reader.ReadUInt32(); } if (base.Version >= eNifVersion.VER_3_3_0_13) { this.Speed = reader.ReadSingle(); } this.RandomSpeed = reader.ReadSingle(); this.VerticalDirection = reader.ReadSingle(); this.VerticalAngle = reader.ReadSingle(); this.HorizontalDirection = reader.ReadSingle(); this.HorizontalAngle = reader.ReadSingle(); this.UnkownNormal = reader.ReadVector3(); this.UnkownColor = reader.ReadColor4(); this.Size = reader.ReadSingle(); this.EmitStartTime = reader.ReadSingle(); this.EmitStopTime = reader.ReadSingle(); if (base.Version >= eNifVersion.VER_4_0_0_2) { this.UnkownByte = reader.ReadByte(); } if (base.Version <= eNifVersion.VER_3_1) { this.OldEmitRate = reader.ReadUInt32(); } if (base.Version >= eNifVersion.VER_3_3_0_13) { this.EmitRate = reader.ReadSingle(); } this.Lifetime = reader.ReadSingle(); this.LifetimeRandom = reader.ReadSingle(); if (base.Version >= eNifVersion.VER_4_0_0_2) { this.EmitFlags = reader.ReadUInt16(); } this.StartRandom = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); this.Emitter = new NiRef<NiObject>(reader); if (base.Version >= eNifVersion.VER_4_0_0_2) { reader.ReadUInt16(); reader.ReadSingle(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt16(); } if (base.Version <= eNifVersion.VER_3_1) { this.ParticleVelocity = reader.ReadVector3(); this.ParticleUnkownVector = reader.ReadVector3(); this.ParticleLifeTime = reader.ReadSingle(); this.ParticleLink = new NiRef<NiObject>(reader); this.ParticleTimestamp = reader.ReadUInt32(); this.ParticleUnkownShort = reader.ReadUInt16(); this.ParticleVertexId = reader.ReadUInt16(); } if (base.Version >= eNifVersion.VER_4_0_0_2) { this.NumParticles = reader.ReadUInt16(); this.NumValid = reader.ReadUInt16(); this.Particles = new Particle[(int)this.NumParticles]; for (int i = 0; i < (int)this.NumParticles; i++) { this.Particles[i] = new Particle(file, reader); } this.UnkownRef = new NiRef<NiObject>(reader); } this.ParticleExtra = new NiRef<NiParticleModifier>(reader); this.UnkownRef2 = new NiRef<NiObject>(reader); if (base.Version >= eNifVersion.VER_4_0_0_2) { this.Trailer = reader.ReadByte(); } if (base.Version <= eNifVersion.VER_3_1) { this.ColorData = new NiRef<NiColorData>(reader); this.UnkownFloat1 = reader.ReadSingle(); this.UnkownFloats2 = reader.ReadFloatArray((int)this.ParticleUnkownShort); } }