Example #1
0
        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();
        }
Example #2
0
        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();
            }
        }
Example #3
0
        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();
        }