public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readUShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readUShort(); header.addressCount = f.readUShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } f.seek((off * 4) + header.gpuCommandsOffset); if (header.backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Skeletal animation for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++) { f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); string skeletalAnimationName = f.readString(f.readInt(), -1); int animationFlags = f.readInt(); //int skeletalAnimationloopMode = f.readByte(); //pas ça du tout float skeletalAnimationframeSize = f.readFloat(); int boneTableOffset = f.readInt(); int boneTableEntries = f.readInt(); int metaDataPointerOffset = f.readInt(); //Debug.WriteLine("Animation Name: " + skeletalAnimationName); //Debug.WriteLine("BonetableOffset: " + boneTableOffset.ToString("X")); //Debug.WriteLine("BonetableEntry: " + boneTableEntries.ToString("X")); for (int i = 0; i < boneTableEntries; i++) { f.seek(boneTableOffset + (i * 4)); int offset = f.readInt(); OSkeletalAnimationBone bone = new OSkeletalAnimationBone(); f.seek(offset); bone.name = f.readString(f.readInt(), -1); Console.WriteLine("Bone Name: " + bone.name); int animationTypeFlags = f.readInt(); int flags = f.readInt(); OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf); switch (segmentType) { case OSegmentType.transform: f.seek(offset + 0x18); int notExistMask = 0x80000; int constantMask = 0x200; for (int j = 0; j < 2; j++) { for (int axis = 0; axis < 3; axis++) { bool notExist = (flags & notExistMask) > 0; bool constant = (flags & constantMask) > 0; OAnimationKeyFrameGroup frame = new OAnimationKeyFrameGroup(); frame.exists = !notExist; if (frame.exists) { if (constant) { frame.interpolation = OInterpolationMode.linear; frame.keyFrames.Add(new OAnimationKeyFrame(f.readFloat(), 0)); } else { int frameOffset = f.readInt(); int position = f.pos(); f.seek(frameOffset); //getAnimationKeyFrame(input, frame); f.seek(position); } } else { f.seek(f.pos() + 0x04); } if (j == 0) { switch (axis) { case 0: bone.rotationX = frame; break; case 1: bone.rotationY = frame; break; case 2: bone.rotationZ = frame; break; } } else { switch (axis) { case 0: bone.translationX = frame; break; case 1: bone.translationY = frame; break; case 2: bone.translationZ = frame; break; } } notExistMask <<= 1; constantMask <<= 1; } constantMask <<= 1; } break; case OSegmentType.transformQuaternion: bone.isFrameFormat = true; int scaleOffset = f.readInt(); int rotationOffset = f.readInt(); int translationOffset = f.readInt(); if ((flags & 0x20) == 0) { bone.scale.exists = true; f.seek(scaleOffset); if ((flags & 4) > 0) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.scale.startFrame = f.readFloat(); bone.scale.endFrame = f.readFloat(); int scaleFlags = f.readInt(); int scaleDataOffset = f.readInt(); int scaleEntries = f.readInt(); f.seek(scaleDataOffset); for (int j = 0; j < scaleEntries; j++) { bone.scale.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } if ((flags & 0x10) == 0) { bone.rotationQuaternion.exists = true; f.seek(rotationOffset); if ((flags & 2) > 0) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } else { bone.rotationQuaternion.startFrame = f.readFloat(); bone.rotationQuaternion.endFrame = f.readFloat(); int rotationFlags = f.readInt(); int rotationDataOffset = f.readInt(); int rotationEntries = f.readInt(); f.seek(rotationDataOffset); for (int j = 0; j < rotationEntries; j++) { bone.rotationQuaternion.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat())); } } } if ((flags & 8) == 0) { bone.translation.exists = true; f.seek(translationOffset); if ((flags & 1) > 0) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } else { bone.translation.startFrame = f.readFloat(); bone.translation.endFrame = f.readFloat(); int translationFlags = f.readInt(); int translationDataOffset = f.readInt(); int translationEntries = f.readInt(); f.seek(translationDataOffset); for (int j = 0; j < translationEntries; j++) { bone.translation.vector.Add(new Vector4( f.readFloat(), f.readFloat(), f.readFloat(), 0)); } } } break; case OSegmentType.transformMatrix: bone.isFullBakedFormat = true; f.readInt(); f.readInt(); int matrixOffset = f.readInt(); int entries = f.readInt(); f.seek(matrixOffset); for (int j = 0; j < entries; j++) { /*OMatrix transform = new OMatrix(); * transform.M11 = f.readFloat(); * transform.M21 = f.readFloat(); * transform.M31 = f.readFloat(); * transform.M41 = f.readFloat(); * * transform.M12 = f.readFloat(); * transform.M22 = f.readFloat(); * transform.M32 = f.readFloat(); * transform.M42 = f.readFloat(); * * transform.M13 = f.readFloat(); * transform.M23 = f.readFloat(); * transform.M33 = f.readFloat(); * transform.M43 = f.readFloat(); * * bone.transform.Add(transform);*/ } break; default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name)); } //skeletalAnimation.bone.Add(bone); } } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); f.seek(textureCommandsOffset); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.Height = f.readUShort(); tex.Width = f.readUShort(); f.skip(12); int doffset = f.readInt(); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); tex.texture = _3DS.DecodeImage(tex.data, tex.Width, tex.Height, (_3DS.Tex_Formats)tex.type); //Texture texture = new Texture2D(tex.texture); //tex.display = texture.Id; } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readUShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); String name = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readUShort(); int rootRightNode = f.readUShort(); int rootNameOffset = f.readInt(); for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = f.readShort(); short rightNode = f.readShort(); objectName[i] = f.readString(f.readInt(), -1); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[materialsTableEntries]; for (int index = 0; index < materialsTableEntries; index++) { f.seek(materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readUShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readUShort(); mbn.mesh[index].Text = objectName[nameId]; // node visibility TODO: finish... mbn.mesh[index].Checked = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readUShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] } //Skeleton f.seek(skeletonOffset); for (int index = 0; index < skeletonEntries; index++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = f.readShort(); short boneSpace = f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); f.skip(4); // Meta data bones.bones.Add(bone); model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
public void Render(Matrix4 view) { shader = Runtime.shaders["MBN"]; GL.UseProgram(shader.programID); GL.Uniform1(shader.getAttribute("renderVertColor"), Runtime.renderVertColor ? 1 : 0); GL.Uniform1(shader.getAttribute("renderType"), 0);//(int)Runtime.renderType GL.Uniform1(shader.getAttribute("selectedBoneIndex"), Runtime.selectedBoneIndex); GL.UniformMatrix4(shader.getAttribute("modelview"), false, ref view); GL.Uniform3(shader.getAttribute("difLightColor"), Lights.diffuseLight.difR, Lights.diffuseLight.difG, Lights.diffuseLight.difB); GL.Uniform3(shader.getAttribute("ambLightColor"), Lights.diffuseLight.ambR, Lights.diffuseLight.ambG, Lights.diffuseLight.ambB); GL.ActiveTexture(TextureUnit.Texture10); GL.BindTexture(TextureTarget.Texture2D, RenderTools.UVTestPattern); GL.Uniform1(shader.getAttribute("UVTestPattern"), 10); Matrix4[] f = skeleton.getShaderMatrix(); int maxUniformBlockSize = GL.GetInteger(GetPName.MaxUniformBlockSize); int boneCount = skeleton.bones.Count; int dataSize = boneCount * Vector4.SizeInBytes * 4; GL.BindBuffer(BufferTarget.UniformBuffer, vbo_bone); GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(dataSize), IntPtr.Zero, BufferUsageHint.DynamicDraw); GL.BindBuffer(BufferTarget.UniformBuffer, 0); var blockIndex = GL.GetUniformBlockIndex(shader.programID, "bones"); GL.BindBufferBase(BufferRangeTarget.UniformBuffer, blockIndex, vbo_bone); if (f.Length > 0) { GL.BindBuffer(BufferTarget.UniformBuffer, vbo_bone); GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, (IntPtr)(f.Length * Vector4.SizeInBytes * 4), f); } shader.enableAttrib(); GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_vert); GL.BufferData <Vertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertex.Stride * Vertices.Length), Vertices, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(shader.getAttribute("pos"), 3, VertexAttribPointerType.Float, false, Vertex.Stride, 0); GL.VertexAttribPointer(shader.getAttribute("nrm"), 3, VertexAttribPointerType.Float, false, Vertex.Stride, 12); GL.VertexAttribPointer(shader.getAttribute("col"), 4, VertexAttribPointerType.Float, false, Vertex.Stride, 24); GL.VertexAttribPointer(shader.getAttribute("tx0"), 2, VertexAttribPointerType.Float, false, Vertex.Stride, 40); GL.VertexAttribPointer(shader.getAttribute("bone"), 2, VertexAttribPointerType.Float, false, Vertex.Stride, 48); GL.VertexAttribPointer(shader.getAttribute("weight"), 2, VertexAttribPointerType.Float, false, Vertex.Stride, 56); GL.PointSize(4f); //GL.DrawArrays(PrimitiveType.Points, 0, Vertices.Length); foreach (BCH_Mesh m in Nodes) { GL.Uniform4(shader.getAttribute("colorSamplerUV"), new Vector4(1, 1, 0, 0)); GL.ActiveTexture(TextureUnit.Texture0); BCH_Material material = (BCH_Material)((BCH)Parent.Parent).Materials.Nodes[m.MaterialIndex]; BCH_Texture tex = ((BCH)Parent.Parent).GetTexture(material.Text); GL.BindTexture(TextureTarget.Texture2D, tex == null ? VBNViewport.defaulttex : tex.display); GL.Uniform1(shader.getAttribute("tex"), 0); if (!m.Checked) { continue; } foreach (BCH_PolyGroup pg in m.Nodes) { GL.Uniform1(shader.getAttribute("boneList"), pg.BoneList.Length, pg.BoneList); GL.Disable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Back); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_faces); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(pg.Faces.Length * sizeof(int)), pg.Faces, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.DrawElements(PrimitiveType.Triangles, pg.Faces.Length, DrawElementsType.UnsignedInt, 0); } } shader.disableAttrib(); }
public override void Read(string filename) { FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); int backwardCompatibility = f.readByte(); int forwardCompatibility = f.readByte(); int version = f.readShort(); int mainHeaderOffset = f.readInt(); int stringTableOffset = f.readInt(); int gpuCommandsOffset = f.readInt(); int dataOffset = f.readInt(); int dataExtendedOffset = 0; int dataExtendedLength = 0; if (backwardCompatibility > 0x20) { dataExtendedOffset = f.readInt(); } int relocationTableOffset = f.readInt(); int mainHeaderLength = f.readInt(); int stringTableLength = f.readInt(); int gpuCommandsLength = f.readInt(); int dataLength = f.readInt(); if (backwardCompatibility > 0x20) { dataExtendedLength = f.readInt(); } int relocationTableLength = f.readInt(); int uninitializedDataSectionLength = f.readInt(); int uninitializedDescriptionSectionLength = f.readInt(); if (backwardCompatibility > 7) { int flags = f.readShort(); int addressCount = f.readShort(); } // Relocation table for (int i = 0; i < relocationTableLength; i += 4) { f.seek(relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + mainHeaderOffset); break; case 1: f.seek(off + mainHeaderOffset); f.writeInt((off) + mainHeaderOffset, f.readInt() + stringTableOffset); break; case 2: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + mainHeaderOffset); f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + dataOffset); break; } f.seek((off * 4) + gpuCommandsOffset); if (backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + int gpuCommandsOffset, ((f.readInt() + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + int dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } //File.WriteAllBytes(filename + "_offset", f.getSection(0, f.size())); f.seek(mainHeaderOffset); int modelsPointerTableOffset = f.readInt(); int modelsPointerTableEntries = f.readInt(); int modelsNameOffset = f.readInt(); int materialsPointerTableOffset = f.readInt(); int materialsPointerTableEntries = f.readInt(); int materialsNameOffset = f.readInt(); int shadersPointerTableOffset = f.readInt(); int shadersPointerTableEntries = f.readInt(); int shadersNameOffset = f.readInt(); int texturesPointerTableOffset = f.readInt(); int texturesPointerTableEntries = f.readInt(); int texturesNameOffset = f.readInt(); int materialsLUTPointerTableOffset = f.readInt(); int materialsLUTPointerTableEntries = f.readInt(); int materialsLUTNameOffset = f.readInt(); int lightsPointerTableOffset = f.readInt(); int lightsPointerTableEntries = f.readInt(); int lightsNameOffset = f.readInt(); int camerasPointerTableOffset = f.readInt(); int camerasPointerTableEntries = f.readInt(); int camerasNameOffset = f.readInt(); int fogsPointerTableOffset = f.readInt(); int fogsPointerTableEntries = f.readInt(); int fogsNameOffset = f.readInt(); int skeletalAnimationsPointerTableOffset = f.readInt(); int skeletalAnimationsPointerTableEntries = f.readInt(); int skeletalAnimationsNameOffset = f.readInt(); int materialAnimationsPointerTableOffset = f.readInt(); int materialAnimationsPointerTableEntries = f.readInt(); int materialAnimationsNameOffset = f.readInt(); int visibilityAnimationsPointerTableOffset = f.readInt(); int visibilityAnimationsPointerTableEntries = f.readInt(); int visibilityAnimationsNameOffset = f.readInt(); int lightAnimationsPointerTableOffset = f.readInt(); int lightAnimationsPointerTableEntries = f.readInt(); int lightAnimationsNameOffset = f.readInt(); int cameraAnimationsPointerTableOffset = f.readInt(); int cameraAnimationsPointerTableEntries = f.readInt(); int cameraAnimationsNameOffset = f.readInt(); int fogAnimationsPointerTableOffset = f.readInt(); int fogAnimationsPointerTableEntries = f.readInt(); int fogAnimationsNameOffset = f.readInt(); int scenePointerTableOffset = f.readInt(); int scenePointerTableEntries = f.readInt(); int sceneNameOffset = f.readInt(); Console.WriteLine(modelsPointerTableEntries > 0 ? "Has Models" : ""); Console.WriteLine(shadersPointerTableEntries > 0 ? "Has Shaders" : ""); Console.WriteLine(texturesPointerTableEntries > 0 ? "Has Textures" : ""); Console.WriteLine(materialsPointerTableEntries > 0 ? "Has Materials" : ""); Console.WriteLine(materialsLUTPointerTableEntries > 0 ? "Has Material LUT" : ""); Console.WriteLine(materialAnimationsPointerTableEntries > 0 ? "Has Material Animation" : ""); Console.WriteLine(lightsPointerTableEntries > 0 ? "Has Lights" : ""); Console.WriteLine(lightAnimationsPointerTableEntries > 0 ? "Has LightAnimations" : ""); Console.WriteLine(camerasPointerTableEntries > 0 ? "Has Camera" : ""); Console.WriteLine(cameraAnimationsPointerTableEntries > 0 ? "Has CameraAnimation" : ""); Console.WriteLine(fogsPointerTableEntries > 0 ? "Has Fog" : ""); Console.WriteLine(fogAnimationsPointerTableEntries > 0 ? "Has FogAnimation" : ""); Console.WriteLine(skeletalAnimationsPointerTableEntries > 0 ? "Has Skeletal Animations" : ""); Console.WriteLine(visibilityAnimationsPointerTableEntries > 0 ? "Has Visibility" : ""); Console.WriteLine(scenePointerTableEntries > 0 ? "Has Scene" : ""); // Textures for (int index = 0; index < texturesPointerTableEntries; index++) { f.seek(texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); // one for each mip I assume int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int textureCommandsOffset2 = f.readInt(); int textureCommandsWordCount2 = f.readInt(); int textureCommandsOffset3 = f.readInt(); int textureCommandsWordCount3 = f.readInt(); int unk = f.readInt(); BCH_Texture tex = new BCH_Texture(); tex.Text = f.readString(f.readInt(), -1); Textures.Nodes.Add(tex); f.seek(textureCommandsOffset); tex.ReadParameters(f, textureCommandsWordCount); } //Models for (int index = 0; index < modelsPointerTableEntries; index++) { f.seek(modelsPointerTableOffset + (index * 4)); f.seek(f.readInt()); BCH_Model model = new BCH_Model(); Models.Nodes.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new OpenTK.Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt(); int materialsTableEntries = f.readInt(); int materialNameOffset = f.readInt(); int verticesTableOffset = f.readInt(); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt(); int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt(); int objectsNodeVisibilityOffset = f.readInt(); int objectsNodeCount = f.readInt(); model.Text = f.readString(f.readInt(), -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 int metaDataPointerOffset = f.readInt(); f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt(); //Console.WriteLine(rootReferenceBit.ToString("x") + " " + f.readString(rootNameOffset, -1) + " " + rootLeftNode + " " + rootRightNode); // Object name tree Radix Tree for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); Console.WriteLine((referenceBit >> 3) + " " + (referenceBit & 0x7) + " " + objectName[i] + " " + leftNode + " " + rightNode); } //TODO: Metadata, boundingbox, normal mesh, materials f.seek(verticesTableOffset); Dictionary <int, BCH_Mesh> MeshIndex = new Dictionary <int, BCH_Mesh>(); int nim = 0; for (int i = 0; i < verticesTableEntries; i++) { BCH_Mesh Mesh = new BCH_Mesh(); Mesh.MaterialIndex = f.readShort(); int mflags = f.readShort(); int meshId = f.readShort(); if (!MeshIndex.ContainsKey(meshId)) { MeshIndex.Add(meshId, Mesh); Mesh.Text = nim < objectName.Length ? objectName[nim++] : i + ""; model.Nodes.Add(Mesh); } else { BCH_Mesh m = MeshIndex[meshId]; Mesh.Text = m.Text; model.Nodes.Insert(model.Nodes.IndexOf(m) - 1, Mesh); } // node visibility TODO: finish... Mesh.Checked = ((nodeVisibility & (1 << i)) > 0); Mesh.renderPriority = f.readShort(); int vshAttBufferCommandOffset = f.readInt(); int vshAttBufferCommandCount = f.readInt(); int faceOffset = f.readInt(); int faceCount = f.readInt(); int vshAttBufferCommandOffsetEx = f.readInt(); int vshAttBufferCommandCountEx = f.readInt(); Vector3 Center = new Vector3(f.readFloat(), f.readFloat(), f.readFloat()); int flagoffset = f.readInt(); // flagsOffset f.skip(4); // 0? int boundingBoxOffset = f.readInt(); } //Materials Console.WriteLine(materialsTableOffset.ToString("x") + " " + materialsPointerTableOffset.ToString("x")); for (int i = 0; i < materialsTableEntries; i++) { f.seek(materialsTableOffset + (i * 0x2c)); int paramOffset = f.readInt(); f.skip(12); // other offsets int texCommandOffset = f.readInt(); int texCommandCount = f.readInt(); int mapperOffset = f.readInt(); BCH_Material mat = new BCH_Material(); Materials.Nodes.Add(mat); mat.Text = f.readString(f.readInt(), -1); Console.WriteLine(mat.Text); //Console.WriteLine(f.readString(f.readInt(), -1)); //Console.WriteLine(f.readString(f.readInt(), -1)); //Console.WriteLine(f.readString(f.readInt(), -1)); // TODO: Parameters } //Skeleton f.seek(skeletonOffset); for (int bindex = 0; bindex < skeletonEntries; bindex++) { Bone bone = new Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); int metaDataPointerOffset2 = f.readInt(); if (metaDataPointerOffset2 != 0) { int position = f.pos(); f.seek(metaDataPointerOffset2); //bone.userData = getMetaData(input); f.seek(position); } model.skeleton.bones.Add(bone); } model.skeleton.reset(); model.skeleton.update(); } }
public void Render(Matrix4 view) { if (vertices == null) { return; } bool buffersWereInitialized = vertVbo != 0 && boneVbo != 0 && facesIbo != 0; if (!buffersWereInitialized) { GenerateBuffers(); } shader = OpenTKSharedResources.shaders["Mbn"]; shader.UseProgram(); GL.Uniform1(shader.GetVertexAttributeUniformLocation("renderVertColor"), Runtime.renderVertColor ? 1 : 0); GL.Uniform1(shader.GetVertexAttributeUniformLocation("renderType"), (int)Runtime.renderType); GL.Uniform1(shader.GetVertexAttributeUniformLocation("selectedBoneIndex"), Runtime.selectedBoneIndex); GL.UniformMatrix4(shader.GetVertexAttributeUniformLocation("modelview"), false, ref view); GL.Uniform3(shader.GetVertexAttributeUniformLocation("difLightColor"), Runtime.lightSetParam.characterDiffuse.diffuseColor.R, Runtime.lightSetParam.characterDiffuse.diffuseColor.G, Runtime.lightSetParam.characterDiffuse.diffuseColor.B); GL.Uniform3(shader.GetVertexAttributeUniformLocation("ambLightColor"), Runtime.lightSetParam.characterDiffuse.ambientColor.R, Runtime.lightSetParam.characterDiffuse.ambientColor.G, Runtime.lightSetParam.characterDiffuse.ambientColor.B); GL.ActiveTexture(TextureUnit.Texture10); RenderTools.uvTestPattern.Bind(); GL.Uniform1(shader.GetVertexAttributeUniformLocation("UVTestPattern"), 10); Matrix4[] f = skeleton.getShaderMatrix(); int maxUniformBlockSize = GL.GetInteger(GetPName.MaxUniformBlockSize); int boneCount = skeleton.bones.Count; int dataSize = boneCount * Vector4.SizeInBytes * 4; GL.BindBuffer(BufferTarget.UniformBuffer, boneVbo); GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)(dataSize), IntPtr.Zero, BufferUsageHint.DynamicDraw); GL.BindBuffer(BufferTarget.UniformBuffer, 0); var blockIndex = GL.GetUniformBlockIndex(shader.Id, "bones"); GL.BindBufferBase(BufferRangeTarget.UniformBuffer, blockIndex, boneVbo); if (f.Length > 0) { GL.BindBuffer(BufferTarget.UniformBuffer, boneVbo); GL.BufferSubData(BufferTarget.UniformBuffer, IntPtr.Zero, (IntPtr)(f.Length * Vector4.SizeInBytes * 4), f); } shader.EnableVertexAttributes(); GL.BindBuffer(BufferTarget.ArrayBuffer, vertVbo); GL.BufferData <Vertex>(BufferTarget.ArrayBuffer, (IntPtr)(Vertex.sizeInBytes * vertices.Length), vertices, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(shader.GetVertexAttributeUniformLocation("pos"), 3, VertexAttribPointerType.Float, false, Vertex.sizeInBytes, 0); GL.VertexAttribPointer(shader.GetVertexAttributeUniformLocation("nrm"), 3, VertexAttribPointerType.Float, false, Vertex.sizeInBytes, 12); GL.VertexAttribPointer(shader.GetVertexAttributeUniformLocation("col"), 4, VertexAttribPointerType.Float, false, Vertex.sizeInBytes, 24); GL.VertexAttribPointer(shader.GetVertexAttributeUniformLocation("tx0"), 2, VertexAttribPointerType.Float, false, Vertex.sizeInBytes, 40); GL.VertexAttribPointer(shader.GetVertexAttributeUniformLocation("bone"), 2, VertexAttribPointerType.Float, false, Vertex.sizeInBytes, 48); GL.VertexAttribPointer(shader.GetVertexAttributeUniformLocation("weight"), 2, VertexAttribPointerType.Float, false, Vertex.sizeInBytes, 56); GL.PointSize(4f); foreach (BCH_Mesh m in Nodes) { GL.Uniform4(shader.GetVertexAttributeUniformLocation("colorSamplerUV"), new Vector4(1, 1, 0, 0)); GL.ActiveTexture(TextureUnit.Texture0); BCH_Material material = (BCH_Material)((BCH)Parent.Parent).Materials.Nodes[m.MaterialIndex]; BCH_Texture tex = ((BCH)Parent.Parent).GetTexture(material.Text); GL.BindTexture(TextureTarget.Texture2D, tex == null ? RenderTools.defaultTex.Id : tex.display); GL.Uniform1(shader.GetVertexAttributeUniformLocation("tex"), 0); if (!m.Checked) { continue; } foreach (BCH_PolyGroup pg in m.Nodes) { GL.Uniform1(shader.GetVertexAttributeUniformLocation("boneList"), pg.BoneList.Length, pg.BoneList); GL.Disable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Back); GL.BindBuffer(BufferTarget.ElementArrayBuffer, facesIbo); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(pg.Faces.Length * sizeof(int)), pg.Faces, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.DrawElements(PrimitiveType.Triangles, pg.Faces.Length, DrawElementsType.UnsignedInt, 0); } } shader.DisableVertexAttributes(); }
public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readShort(); header.addressCount = f.readShort(); } // Relocation table for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } f.seek((off * 4) + header.gpuCommandsOffset); if (header.backwardCompatibility < 6) { switch (flag) { case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 8) { switch (flag) { case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else if (header.backwardCompatibility < 0x21) { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode } } else { switch (flag) { case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Texture case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break; //Vertex relative to Data Offset //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset } } } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X")); f.seek(textureCommandsOffset); //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X")); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt(); //Debug.WriteLine("doffset: " + doffset.ToString("X")); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); model.materialsTableOffset = f.readInt(); model.materialsTableEntries = f.readInt(); model.materialsNameOffset = f.readInt(); model.verticesTableOffset = f.readInt(); //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); model.verticesTableEntries = f.readInt(); f.skip(0x28); model.skeletonOffset = f.readInt(); model.skeletonEntries = f.readInt(); model.skeletonNameOffset = f.readInt(); model.objectsNodeVisibilityOffset = f.readInt(); model.objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt(), -1); model.objectsNodeNameEntries = f.readInt(); model.objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 model.metaDataPointerOffset = f.readInt(); f.seek(model.objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[model.objectsNodeNameEntries]; f.seek(model.objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + header.mainHeaderOffset; for (int i = 0; i < model.objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[model.materialsTableEntries]; for (int index = 0; index < model.materialsTableEntries; index++) { f.seek(model.materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(model.verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < model.verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(model.skeletonOffset); for (int index = 0; index < model.skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.Text = f.readString(f.readInt(), -1); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); } }
public override void Read(string filename) { FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(8); int mainHeaderOffset = f.readInt(); int stringTableOffset = f.readInt(); int gpuCommandOffset = f.readInt(); int dataOffset = f.readInt(); int dataExtendOffset = f.readInt(); int relocationTableOffset = f.readInt(); int mainHeaderLength = f.readInt(); int stringTableLength = f.readInt(); int gpuCommandLength = f.readInt(); int dataLength = f.readInt(); int dataExtendLength = f.readInt(); int relocationTableLength = f.readInt(); int datsSecLength = f.readInt(); int desSecLength = f.readInt(); int flags = f.readShort(); int addressCount = f.readShort(); // TODO: Finished Relocation table stuff for (int i = 0; i < relocationTableLength; i += 4) { f.seek(relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + mainHeaderOffset); break; } } // Content Header f.seek(mainHeaderOffset); int modelsPointerTableOffset = f.readInt() + mainHeaderOffset; int modelsPointerTableEntries = f.readInt(); int modelsNameOffset = f.readInt() + mainHeaderOffset; int materialsPointerTableOffset = f.readInt() + mainHeaderOffset; int materialsPointerTableEntries = f.readInt(); int materialsNameOffset = f.readInt() + mainHeaderOffset; int shadersPointerTableOffset = f.readInt() + mainHeaderOffset; int shadersPointerTableEntries = f.readInt(); int shadersNameOffset = f.readInt() + mainHeaderOffset; int texturesPointerTableOffset = f.readInt() + mainHeaderOffset; int texturesPointerTableEntries = f.readInt(); int texturesNameOffset = f.readInt() + mainHeaderOffset; int materialsLUTPointerTableOffset = f.readInt() + mainHeaderOffset; int materialsLUTPointerTableEntries = f.readInt(); int materialsLUTNameOffset = f.readInt() + mainHeaderOffset; int lightsPointerTableOffset = f.readInt() + mainHeaderOffset; int lightsPointerTableEntries = f.readInt(); int lightsNameOffset = f.readInt() + mainHeaderOffset; int camerasPointerTableOffset = f.readInt() + mainHeaderOffset; int camerasPointerTableEntries = f.readInt(); int camerasNameOffset = f.readInt() + mainHeaderOffset; int fogsPointerTableOffset = f.readInt() + mainHeaderOffset; int fogsPointerTableEntries = f.readInt(); int fogsNameOffset = f.readInt() + mainHeaderOffset; int skeletalAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int skeletalAnimationsPointerTableEntries = f.readInt(); int skeletalAnimationsNameOffset = f.readInt() + mainHeaderOffset; int materialAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int materialAnimationsPointerTableEntries = f.readInt(); int materialAnimationsNameOffset = f.readInt() + mainHeaderOffset; int visibilityAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int visibilityAnimationsPointerTableEntries = f.readInt(); int visibilityAnimationsNameOffset = f.readInt() + mainHeaderOffset; int lightAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int lightAnimationsPointerTableEntries = f.readInt(); int lightAnimationsNameOffset = f.readInt() + mainHeaderOffset; int cameraAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int cameraAnimationsPointerTableEntries = f.readInt(); int cameraAnimationsNameOffset = f.readInt() + mainHeaderOffset; int fogAnimationsPointerTableOffset = f.readInt() + mainHeaderOffset; int fogAnimationsPointerTableEntries = f.readInt(); int fogAnimationsNameOffset = f.readInt() + mainHeaderOffset; int scenePointerTableOffset = f.readInt() + mainHeaderOffset; int scenePointerTableEntries = f.readInt(); int sceneNameOffset = f.readInt() + mainHeaderOffset; // Textures // WIP Section for (int index = 0; index < texturesPointerTableEntries; index++) { f.seek(texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset + mainHeaderOffset); int textureCommandsOffset = f.readInt() + gpuCommandOffset; int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt() + stringTableOffset, -1); f.seek(textureCommandsOffset); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt() + dataOffset; f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // Model data for (int modelIndex = 0; modelIndex < modelsPointerTableEntries; modelIndex++) { f.seek(modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt() + mainHeaderOffset; // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); int materialsTableOffset = f.readInt() + mainHeaderOffset; int materialsTableEntries = f.readInt(); int materialsNamesOffset = f.readInt() + mainHeaderOffset; int verticesTableOffset = f.readInt() + mainHeaderOffset; //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); int verticesTableEntries = f.readInt(); f.skip(0x28); int skeletonOffset = f.readInt() + mainHeaderOffset; int skeletonEntries = f.readInt(); int skeletonNameOffset = f.readInt() + mainHeaderOffset; int objectsNodeVisibilityOffset = f.readInt() + mainHeaderOffset; int objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt() + stringTableOffset, -1); int objectsNodeNameEntries = f.readInt(); int objectsNodeNameOffset = f.readInt() + mainHeaderOffset; f.readInt(); //0x0 int metaDataPointerOffset = f.readInt() + mainHeaderOffset; f.seek(objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[objectsNodeNameEntries]; f.seek(objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + mainHeaderOffset; for (int i = 0; i < objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt() + stringTableOffset, -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[materialsTableEntries]; for (int index = 0; index < materialsTableEntries; index++) { f.seek(materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt() + stringTableOffset, -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; f.skip(2); // flags int nameId = f.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt() + mainHeaderOffset; des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt() + mainHeaderOffset; des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt() + mainHeaderOffset; des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(skeletonOffset); for (int index = 0; index < skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.boneName = f.readString(f.readInt() + stringTableOffset, -1).ToCharArray(); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); } }
public override void Read(string filename) { bchHeader header = new bchHeader(); FileData f = new FileData(filename); f.Endian = System.IO.Endianness.Little; f.skip(4); header.backwardCompatibility = f.readByte(); header.forwardCompatibility = f.readByte(); header.version = f.readShort(); header.mainHeaderOffset = f.readInt(); header.stringTableOffset = f.readInt(); header.gpuCommandsOffset = f.readInt(); header.dataOffset = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedOffset = f.readInt(); } header.relocationTableOffset = f.readInt(); header.mainHeaderLength = f.readInt(); header.stringTableLength = f.readInt(); header.gpuCommandsLength = f.readInt(); header.dataLength = f.readInt(); if (header.backwardCompatibility > 0x20) { header.dataExtendedLength = f.readInt(); } header.relocationTableLength = f.readInt(); header.uninitializedDataSectionLength = f.readInt(); header.uninitializedDescriptionSectionLength = f.readInt(); if (header.backwardCompatibility > 7) { header.flags = f.readShort(); header.addressCount = f.readShort(); } // TODO: Finished Relocation table stuff for (int i = 0; i < header.relocationTableLength; i += 4) { f.seek(header.relocationTableOffset + i); int val = f.readInt(); int off = val & 0x1FFFFFF; byte flag = (byte)(val >> 25); switch (flag) { case 0: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset); break; case 1: f.seek(off + header.mainHeaderOffset); f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset); break; case 2: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset); break; case 0xc: f.seek((off * 4) + header.mainHeaderOffset); f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; } /*f.seek((off * 4) + header.gpuCommandsOffset); * if (header.backwardCompatibility < 6) * { * switch (flag) * { * case 0x23: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Texture * case 0x25: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Vertex * // Trying to understand the mess first * case 0x26: f.writeInt((off * 4) + header.mainHeaderOffset, Convert.ToInt32(((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000)); break; //Index 16 bits mode * //case 0x27: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else if (header.backwardCompatibility < 8) * { * switch (flag) * { * case 0x24: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex * case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode * case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else if (header.backwardCompatibility < 0x21) * { * switch (flag) * { * case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x27: writer.Write(peek(input) + header.dataOffset); break; //Vertex * case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode * case 0x29: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode * } * } * else * { * switch (flag) * { * case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture * case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex relative to Data Offset * case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset * case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset * case 0x2b: writer.Write(peek(input) + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset * case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset * case 0x2d: writer.Write((peek(input) + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset * } * } */ } // Content Header f.seek(header.mainHeaderOffset); bchContentHeader content = new bchContentHeader(); { content.modelsPointerTableOffset = f.readInt(); content.modelsPointerTableEntries = f.readInt(); content.modelsNameOffset = f.readInt(); content.materialsPointerTableOffset = f.readInt(); content.materialsPointerTableEntries = f.readInt(); content.materialsNameOffset = f.readInt(); content.shadersPointerTableOffset = f.readInt(); content.shadersPointerTableEntries = f.readInt(); content.shadersNameOffset = f.readInt(); content.texturesPointerTableOffset = f.readInt(); content.texturesPointerTableEntries = f.readInt(); content.texturesNameOffset = f.readInt(); content.materialsLUTPointerTableOffset = f.readInt(); content.materialsLUTPointerTableEntries = f.readInt(); content.materialsLUTNameOffset = f.readInt(); content.lightsPointerTableOffset = f.readInt(); content.lightsPointerTableEntries = f.readInt(); content.lightsNameOffset = f.readInt(); content.camerasPointerTableOffset = f.readInt(); content.camerasPointerTableEntries = f.readInt(); content.camerasNameOffset = f.readInt(); content.fogsPointerTableOffset = f.readInt(); content.fogsPointerTableEntries = f.readInt(); content.fogsNameOffset = f.readInt(); content.skeletalAnimationsPointerTableOffset = f.readInt(); content.skeletalAnimationsPointerTableEntries = f.readInt(); content.skeletalAnimationsNameOffset = f.readInt(); content.materialAnimationsPointerTableOffset = f.readInt(); content.materialAnimationsPointerTableEntries = f.readInt(); content.materialAnimationsNameOffset = f.readInt(); content.visibilityAnimationsPointerTableOffset = f.readInt(); content.visibilityAnimationsPointerTableEntries = f.readInt(); content.visibilityAnimationsNameOffset = f.readInt(); content.lightAnimationsPointerTableOffset = f.readInt(); content.lightAnimationsPointerTableEntries = f.readInt(); content.lightAnimationsNameOffset = f.readInt(); content.cameraAnimationsPointerTableOffset = f.readInt(); content.cameraAnimationsPointerTableEntries = f.readInt(); content.cameraAnimationsNameOffset = f.readInt(); content.fogAnimationsPointerTableOffset = f.readInt(); content.fogAnimationsPointerTableEntries = f.readInt(); content.fogAnimationsNameOffset = f.readInt(); content.scenePointerTableOffset = f.readInt(); content.scenePointerTableEntries = f.readInt(); content.sceneNameOffset = f.readInt(); } //Shaders (unused for now, until someone wants to add them) for (int index = 0; index < content.shadersPointerTableEntries; index++) { f.seek(content.shadersPointerTableOffset + (index * 4)); int dataOffset = f.readInt(); f.seek(dataOffset); int shaderDataOffset = f.readInt(); int shaderDataLength = f.readInt(); } // Textures // WIP Section for (int index = 0; index < content.texturesPointerTableEntries; index++) { f.seek(content.texturesPointerTableOffset + (index * 4)); int dOffset = f.readInt(); f.seek(dOffset); Debug.WriteLine("dOffset: " + dOffset.ToString("X")); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); f.seek(f.pos() + 0x14); String textureName = f.readString(f.readInt(), -1); //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X")); f.seek(textureCommandsOffset); //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X")); BCH_Texture tex = new BCH_Texture(); textures.Add(textureName, tex); tex.height = f.readShort(); tex.width = f.readShort(); f.skip(12); int doffset = f.readInt(); //Debug.WriteLine("doffset: " + doffset.ToString("X")); f.skip(4); tex.type = f.readInt(); tex.data = f.getSection(doffset, f.size() - doffset); if (tex.type == 12) { tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height)); } } // Model data for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++) { f.seek(content.modelsPointerTableOffset + (modelIndex * 4)); int objectsHeaderOffset = f.readInt(); // Objects f.seek(objectsHeaderOffset); BCH_Model model = new BCH_Model(); models.Add(model); model.flags = f.readByte(); model.skeletonScaleType = f.readByte(); model.silhouetteMaterialEntries = f.readShort(); model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat() , 0, 0, 0, 1); model.materialsTableOffset = f.readInt(); model.materialsTableEntries = f.readInt(); model.materialsNameOffset = f.readInt(); model.verticesTableOffset = f.readInt(); //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X")); model.verticesTableEntries = f.readInt(); f.skip(0x28); model.skeletonOffset = f.readInt(); model.skeletonEntries = f.readInt(); model.skeletonNameOffset = f.readInt(); model.objectsNodeVisibilityOffset = f.readInt(); model.objectsNodeCount = f.readInt(); model.name = f.readString(f.readInt(), -1); model.objectsNodeNameEntries = f.readInt(); model.objectsNodeNameOffset = f.readInt(); f.readInt(); //0x0 model.metaDataPointerOffset = f.readInt(); f.seek(model.objectsNodeVisibilityOffset); int nodeVisibility = f.readInt(); string[] objectName = new string[model.objectsNodeNameEntries]; f.seek(model.objectsNodeNameOffset); int rootReferenceBit = f.readInt(); //Radix tree int rootLeftNode = f.readShort(); int rootRightNode = f.readShort(); int rootNameOffset = f.readInt() + header.mainHeaderOffset; for (int i = 0; i < model.objectsNodeNameEntries; i++) { int referenceBit = f.readInt(); short leftNode = (short)f.readShort(); short rightNode = (short)f.readShort(); objectName[i] = f.readString(f.readInt(), -1); //Debug.WriteLine(objectName[i]); } // Materials // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM String[] materialNames = new String[model.materialsTableEntries]; for (int index = 0; index < model.materialsTableEntries; index++) { f.seek(model.materialsTableOffset + (index * 0x2c)); int materialParametersOffset = f.readInt(); f.readInt(); f.readInt(); f.readInt(); int textureCommandsOffset = f.readInt(); int textureCommandsWordCount = f.readInt(); int materialMapperOffset = f.readInt(); materialNames[index] = f.readString(f.readInt(), -1); } // Object Descriptions... // Assumes MBN is already loaded for now f.seek(model.verticesTableOffset); List <objDes> objDescriptors = new List <objDes>(); Debug.WriteLine(model.name); if (mbn == null) { mbn = new Smash_Forge.MBN(); for (int index = 0; index < model.verticesTableEntries; index++) { mbn.mesh.Add(new MBN.Mesh()); } mbn.PreRender(); } for (int index = 0; index < mbn.mesh.Count; index++) { int i = f.readShort(); if (index > mbn.mesh.Count) { break; } if (i > materialNames.Length) { break; } mbn.mesh[index].texId = textures[materialNames[i]].display; Console.WriteLine("Tex index" + mbn.mesh[index].texId); f.skip(2); // flags int nameId = f.readShort(); mbn.mesh[index].name = objectName[nameId]; // node visibility TODO: finish... //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0); mbn.mesh[index].renderPriority = f.readShort(); objDes des = new objDes(); objDescriptors.Add(des); des.vshAttBufferCommandOffset = f.readInt(); des.vshAttBufferCommandCount = f.readInt(); des.faceOffset = f.readInt(); des.faceCount = f.readInt(); des.vshAttBufferCommandOffsetEx = f.readInt(); des.vshAttBufferCommandCountEx = f.readInt(); f.skip(12); // center vector f.skip(4); // flagsOffset f.skip(4); // 0? f.readInt(); //bbOffsets[i] = + mainheaderOffset //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X")); } //Skeleton f.seek(model.skeletonOffset); for (int index = 0; index < model.skeletonEntries; index++) { Bone bone = new Smash_Forge.Bone(model.skeleton); int boneFlags = f.readInt(); bone.parentIndex = (short)f.readShort(); short boneSpace = (short)f.readShort(); bone.scale = new float[3]; bone.rotation = new float[3]; bone.position = new float[3]; bone.scale[0] = f.readFloat(); bone.scale[1] = f.readFloat(); bone.scale[2] = f.readFloat(); bone.rotation[0] = f.readFloat(); bone.rotation[1] = f.readFloat(); bone.rotation[2] = f.readFloat(); bone.position[0] = f.readFloat(); bone.position[1] = f.readFloat(); bone.position[2] = f.readFloat(); // bone matrix... not really needed to be stored per say f.skip(4 * 4 * 3); bone.boneName = f.readString(f.readInt(), -1).ToCharArray(); f.skip(4); // Meta data model.skeleton.bones.Add(bone); } model.skeleton.reset(); /* //Skeletal Animations * * SkelAnimation anim = new SkelAnimation(); * * for (int index = 0; index < content.skeletalAnimationsPointerTableEntries; index++) * { * f.seek(content.skeletalAnimationsPointerTableOffset + (index * 4)); * int dataOffset = f.readInt(); * f.seek(dataOffset); * * RenderBase.OSkeletalAnimation skeletalAnimation = new RenderBase.OSkeletalAnimation(); * * skeletalAnimation.name = f.readString(f.readInt(), -1); * int animationFlags = f.readInt(); * skeletalAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1); * skeletalAnimation.frameSize = f.readFloat(); * int boneTableOffset = f.readInt(); * int boneTableEntries = f.readInt(); * int metaDataPointerOffset = f.readInt(); * * // /*if (metaDataPointerOffset != 0) * // { * // data.Seek(metaDataPointerOffset, SeekOrigin.Begin); * // skeletalAnimation.userData = getMetaData(input); * // } * * for (int i = 0; i < boneTableEntries; i++) * { * f.seek(boneTableOffset + (i * 4)); * int offset = f.readInt(); * * RenderBase.OSkeletalAnimationBone bone = new RenderBase.OSkeletalAnimationBone(); * * f.seek(offset); * bone.name = f.readString(f.readInt(), -1); * int animationTypeFlags = f.readInt(); * * int flags = f.readInt(); * * RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf); * switch (segmentType) * { * case RenderBase.OSegmentType.transform: * f.seek(offset + 0x18); * * uint notExistMask = 0x80000; * uint constantMask = 0x200; * * for (int j = 0; j < 2; j++) * { * for (int axis = 0; axis < 3; axis++) * { * bool notExist = (flags & notExistMask) > 0; * bool constant = (flags & constantMask) > 0; * * RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup(); * frame.exists = !notExist; * if (frame.exists) * { * if (constant) * { * frame.interpolation = RenderBase.OInterpolationMode.linear; * frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0)); * } * else * { * int frameOffset = f.readInt(); * long position = data.Position; * f.seek(frameOffset); * getAnimationKeyFrame(input, frame); * f.seek(position); * } * } * else * data.Seek(4, SeekOrigin.Current); * * if (j == 0) * { * switch (axis) * { * case 0: bone.rotationX = frame; break; * case 1: bone.rotationY = frame; break; * case 2: bone.rotationZ = frame; break; * } * } * else * { * switch (axis) * { * case 0: bone.translationX = frame; break; * case 1: bone.translationY = frame; break; * case 2: bone.translationZ = frame; break; * } * } * * notExistMask <<= 1; * constantMask <<= 1; * } * * constantMask <<= 1; * } * * break; * case RenderBase.OSegmentType.transformQuaternion: * bone.isFrameFormat = true; * * uint scaleOffset = input.ReadUInt32(); * uint rotationOffset = input.ReadUInt32(); * uint translationOffset = input.ReadUInt32(); * * if ((flags & 0x20) == 0) * { * bone.scale.exists = true; * data.Seek(scaleOffset, SeekOrigin.Begin); * * if ((flags & 4) > 0) * { * bone.scale.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * else * { * bone.scale.startFrame = input.ReadSingle(); * bone.scale.endFrame = input.ReadSingle(); * * uint scaleFlags = input.ReadUInt32(); * uint scaleDataOffset = input.ReadUInt32(); * uint scaleEntries = input.ReadUInt32(); * * data.Seek(scaleDataOffset, SeekOrigin.Begin); * for (int j = 0; j < scaleEntries; j++) * { * bone.scale.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * } * } * * if ((flags & 0x10) == 0) * { * bone.rotationQuaternion.exists = true; * data.Seek(rotationOffset, SeekOrigin.Begin); * * if ((flags & 2) > 0) * { * bone.rotationQuaternion.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle())); * } * else * { * bone.rotationQuaternion.startFrame = input.ReadSingle(); * bone.rotationQuaternion.endFrame = input.ReadSingle(); * * uint rotationFlags = input.ReadUInt32(); * uint rotationDataOffset = input.ReadUInt32(); * uint rotationEntries = input.ReadUInt32(); * * data.Seek(rotationDataOffset, SeekOrigin.Begin); * for (int j = 0; j < rotationEntries; j++) * { * bone.rotationQuaternion.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle())); * } * } * } * * if ((flags & 8) == 0) * { * bone.translation.exists = true; * data.Seek(translationOffset, SeekOrigin.Begin); * * if ((flags & 1) > 0) * { * bone.translation.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * else * { * bone.translation.startFrame = input.ReadSingle(); * bone.translation.endFrame = input.ReadSingle(); * * uint translationFlags = input.ReadUInt32(); * uint translationDataOffset = input.ReadUInt32(); * uint translationEntries = input.ReadUInt32(); * * data.Seek(translationDataOffset, SeekOrigin.Begin); * for (int j = 0; j < translationEntries; j++) * { * bone.translation.vector.Add(new RenderBase.OVector4( * input.ReadSingle(), * input.ReadSingle(), * input.ReadSingle(), * 0)); * } * } * } * * break; * case RenderBase.OSegmentType.transformMatrix: * bone.isFullBakedFormat = true; * * input.ReadUInt32(); * input.ReadUInt32(); * uint matrixOffset = input.ReadUInt32(); * uint entries = input.ReadUInt32(); * * data.Seek(matrixOffset, SeekOrigin.Begin); * for (int j = 0; j < entries; j++) * { * RenderBase.OMatrix transform = new RenderBase.OMatrix(); * transform.M11 = input.ReadSingle(); * transform.M21 = input.ReadSingle(); * transform.M31 = input.ReadSingle(); * transform.M41 = input.ReadSingle(); * * transform.M12 = input.ReadSingle(); * transform.M22 = input.ReadSingle(); * transform.M32 = input.ReadSingle(); * transform.M42 = input.ReadSingle(); * * transform.M13 = input.ReadSingle(); * transform.M23 = input.ReadSingle(); * transform.M33 = input.ReadSingle(); * transform.M43 = input.ReadSingle(); * * bone.transform.Add(transform); * } * * break; * default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name)); * } * * skeletalAnimation.bone.Add(bone); * } * * models.skeletalAnimation.list.Add(skeletalAnimation); * } * * //Material Animations * for (int index = 0; index < contentHeader.materialAnimationsPointerTableEntries; index++) * { * data.Seek(contentHeader.materialAnimationsPointerTableOffset + (index * 4), SeekOrigin.Begin); * uint dataOffset = input.ReadUInt32(); * data.Seek(dataOffset, SeekOrigin.Begin); * * RenderBase.OMaterialAnimation materialAnimation = new RenderBase.OMaterialAnimation(); * * materialAnimation.name = readString(input); * uint animationFlags = input.ReadUInt32(); * materialAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1); * materialAnimation.frameSize = input.ReadSingle(); * uint dataTableOffset = input.ReadUInt32(); * uint dataTableEntries = input.ReadUInt32(); * input.ReadUInt32(); * uint textureNameTableOffset = input.ReadUInt32(); * uint textureNameTableEntries = input.ReadUInt32(); * * data.Seek(textureNameTableOffset, SeekOrigin.Begin); * for (int i = 0; i < textureNameTableEntries; i++) * { * string name = readString(input); * materialAnimation.textureName.Add(name); * } * * for (int i = 0; i < dataTableEntries; i++) * { * data.Seek(dataTableOffset + (i * 4), SeekOrigin.Begin); * uint offset = input.ReadUInt32(); * * RenderBase.OMaterialAnimationData animationData = new RenderBase.OMaterialAnimationData(); * * data.Seek(offset, SeekOrigin.Begin); * animationData.name = readString(input); * uint animationTypeFlags = input.ReadUInt32(); * uint flags = input.ReadUInt32(); * * animationData.type = (RenderBase.OMaterialAnimationType)(animationTypeFlags & 0xff); * RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf); * * int segmentCount = 0; * switch (segmentType) * { * case RenderBase.OSegmentType.rgbaColor: segmentCount = 4; break; * case RenderBase.OSegmentType.vector2: segmentCount = 2; break; * case RenderBase.OSegmentType.single: segmentCount = 1; break; * case RenderBase.OSegmentType.integer: segmentCount = 1; break; * } * * for (int j = 0; j < segmentCount; j++) * { * RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup(); * * data.Seek(offset + 0xc + (j * 4), SeekOrigin.Begin); * * frame.exists = (flags & (0x100 << j)) == 0; * bool constant = (flags & (1 << j)) > 0; * * if (frame.exists) * { * if (constant) * { * frame.interpolation = RenderBase.OInterpolationMode.linear; * frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0)); * } * else * { * uint frameOffset = input.ReadUInt32(); * data.Seek(frameOffset, SeekOrigin.Begin); * getAnimationKeyFrame(input, frame); * } * } * * animationData.frameList.Add(frame); * } * * materialAnimation.data.Add(animationData); * } * * models.materialAnimation.list.Add(materialAnimation); * } * */ } }
private void Render(object sender, PaintEventArgs e) { if (!ReadyToRender) { return; } glViewport.MakeCurrent(); GL.LoadIdentity(); GL.Viewport(glViewport.ClientRectangle); // Push all attributes so we don't have to clean up later GL.PushAttrib(AttribMask.AllAttribBits); // clear the gf buffer GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); // use fixed function pipeline for drawing background and floor grid GL.UseProgram(0); if (MeshList.treeView1.SelectedNode != null) { if (MeshList.treeView1.SelectedNode is BCH_Texture) { GL.PopAttrib(); BCH_Texture tex = ((BCH_Texture)MeshList.treeView1.SelectedNode); RenderTools.DrawTexturedQuad(tex.display, tex.Width, tex.Height, true, true, true, true, false, true); glViewport.SwapBuffers(); return; } if (MeshList.treeView1.SelectedNode is NUT_Texture) { GL.PopAttrib(); NUT_Texture tex = ((NUT_Texture)MeshList.treeView1.SelectedNode); RenderTools.DrawTexturedQuad(((NUT)tex.Parent).draw[tex.HASHID], tex.Width, tex.Height, true, true, true, true, false, true); glViewport.SwapBuffers(); return; } } if (Runtime.renderBackGround) { // background uses different matrices GL.MatrixMode(MatrixMode.Modelview); GL.LoadIdentity(); GL.MatrixMode(MatrixMode.Projection); GL.LoadIdentity(); RenderTools.RenderBackground(); } // Camera Update // ------------------------------------------------------------- GL.MatrixMode(MatrixMode.Projection); if (glViewport.ClientRectangle.Contains(glViewport.PointToClient(Cursor.Position)) && glViewport.Focused && CurrentMode == Mode.Normal && !TransformTool.hit) { Camera.Update(); //if (cameraPosForm != null && !cameraPosForm.IsDisposed) // cameraPosForm.updatePosition(); } try { if (OpenTK.Input.Mouse.GetState() != null) { Camera.mouseSLast = OpenTK.Input.Mouse.GetState().WheelPrecise; } } catch { } Matrix4 matrix = Camera.getMVPMatrix(); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref matrix); // Floor // ------------------------------------------------------------- if (Runtime.renderFloor) { RenderTools.drawFloor(); } // Shadows // ------------------------------------------------------------- if (Runtime.drawModelShadow) { CalculateLightSource(); // update light matrix and setup shadowmap rendering GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref lightMatrix); GL.Enable(EnableCap.DepthTest); GL.Viewport(0, 0, sw, sh); GL.BindFramebuffer(FramebufferTarget.Framebuffer, sfb); foreach (ModelContainer m in draw) { m.RenderShadow(Camera, 0, Matrix4.Zero, Camera.getMVPMatrix()); } // reset matrices and viewport for model rendering again GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.LoadMatrix(ref matrix); GL.Viewport(glViewport.ClientRectangle); } // render models into hdr buffer // ------------------------------------------------------------- if (Runtime.useDepthTest) { GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Lequal); } else { GL.Disable(EnableCap.DepthTest); } GL.Enable(EnableCap.DepthTest); // Models // ------------------------------------------------------------- //frameTime.Start(); if (Runtime.renderModel || Runtime.renderModelWireframe) { foreach (TreeNode m in draw) { if (m is ModelContainer) { ((ModelContainer)m).Render(Camera, 0, Matrix4.Zero, Camera.getMVPMatrix()); } } } if (ViewComboBox.SelectedIndex == 1) { foreach (TreeNode m in draw) { if (m is ModelContainer) { ((ModelContainer)m).RenderPoints(Camera); } } } //GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); /*// render gaussian blur stuff * if (Runtime.drawQuadBlur) * DrawQuadBlur(); * * // render full screen quad for post processing * if (Runtime.drawQuadFinalOutput) * DrawQuadFinalOutput();*/ // use fixed function pipeline again for area lights, lvd, bones, hitboxes, etc SetupFixedFunctionRendering(); /*// draw path.bin * if (Runtime.renderPath) * DrawPathDisplay(); * * // area light bounding boxes should intersect stage geometry and not render on top * if (Runtime.drawAreaLightBoundingBoxes) * DrawAreaLightBoundingBoxes();*/ // clear depth buffer so stuff will render on top of the models GL.Clear(ClearBufferMask.DepthBufferBit); if (Runtime.renderLVD) { _lvd.Render(); } if (Runtime.renderBones) { foreach (ModelContainer m in draw) { m.RenderBones(); } } // ACMD if (ParamManager != null && Runtime.renderHurtboxes && draw.Count > 0 && (draw[0] is ModelContainer)) { ParamManager.RenderHurtboxes(Frame, scriptId, ACMDScript, ((ModelContainer)draw[0]).GetVBN()); } if (ACMDScript != null && draw.Count > 0 && (draw[0] is ModelContainer)) { ACMDScript.Render(((ModelContainer)draw[0]).GetVBN()); } //Debug.WriteLine(frameTime.getAverageRenderTime()); // Bone Transform Tool if (ViewComboBox.SelectedIndex == 2) { if (modeBone.Checked) { TransformTool.Render(Camera, new Ray(Camera, glViewport)); if (TransformTool.state == 1) { CurrentMode = Mode.Selection; } else { CurrentMode = Mode.Normal; } } if (TransformTool.HasChanged()) { if (Animation != null && TransformTool.b != null) { // get the node group for the current bone in animation Animation.KeyNode ThisNode = null; foreach (Animation.KeyNode node in Animation.Bones) { if (node.Text.Equals(TransformTool.b.Text)) { // found ThisNode = node; break; } } if (ThisNode == null) { ThisNode = new Animation.KeyNode(TransformTool.b.Text); Animation.Bones.Add(ThisNode); } // update or add the key frame ThisNode.SetKeyFromBone((float)currentFrame.Value, TransformTool.b); } } } // Mouse selection // ------------------------------------------------------------- if (ViewComboBox.SelectedIndex == 1) { try { if (CurrentMode == Mode.Normal && OpenTK.Input.Mouse.GetState().IsButtonDown(OpenTK.Input.MouseButton.Right)) { CurrentMode = Mode.Selection; Vector2 m = GetMouseOnViewport(); sx1 = m.X; sy1 = m.Y; } } catch { } if (CurrentMode == Mode.Selection) { if (!OpenTK.Input.Mouse.GetState().IsButtonDown(OpenTK.Input.MouseButton.Right)) { checkSelect(); CurrentMode = Mode.Normal; } GL.MatrixMode(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); Vector2 m = GetMouseOnViewport(); GL.Color3(Color.Black); GL.LineWidth(2f); GL.Begin(PrimitiveType.LineLoop); GL.Vertex2(sx1, sy1); GL.Vertex2(m.X, sy1); GL.Vertex2(m.X, m.Y); GL.Vertex2(sx1, m.Y); GL.End(); GL.Color3(Color.White); GL.LineWidth(1f); GL.Begin(PrimitiveType.LineLoop); GL.Vertex2(sx1, sy1); GL.Vertex2(m.X, sy1); GL.Vertex2(m.X, m.Y); GL.Vertex2(sx1, m.Y); GL.End(); GL.PopMatrix(); } } /*if (CurrentMode == Mode.Photoshoot) * { * freezeCamera = false; * if (Keyboard.GetState().IsKeyDown(Key.W) && Mouse.GetState().IsButtonDown(MouseButton.Left)) * { * shootX = this.PointToClient(Cursor.Position).X; * shootY = this.PointToClient(Cursor.Position).Y; * freezeCamera = true; * } * // Hold on to your pants, boys * RenderTools.DrawPhotoshoot(glViewport, shootX, shootY, shootWidth, shootHeight); * }*/ GL.PopAttrib(); glViewport.SwapBuffers(); }