private void SetupTextureCoordArray(SepdChunk sepd) { if (!texCoordBufferObjects.ContainsKey(sepd)) { return; } GL.EnableClientState(ArrayCap.TextureCoordArray); GL.BindBuffer(BufferTarget.ArrayBuffer, texCoordBufferObjects[sepd]); GL.TexCoordPointer(2, sepd.TexCoordPointerType, 0, IntPtr.Zero); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
private void SetupVertexArray(SepdChunk sepd) { if (!vertexBufferObjects.ContainsKey(sepd)) { return; } GL.EnableClientState(ArrayCap.VertexArray); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBufferObjects[sepd]); GL.VertexPointer(3, sepd.VertexPointerType, 0, IntPtr.Zero); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
private void SetupNormalArray(SepdChunk sepd) { if (!normalBufferObjects.ContainsKey(sepd)) { return; } GL.EnableClientState(ArrayCap.NormalArray); GL.BindBuffer(BufferTarget.ArrayBuffer, normalBufferObjects[sepd]); GL.NormalPointer(sepd.NormalPointerType, 0, IntPtr.Zero); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
private void SetupColorArray(SepdChunk sepd) { if (!colorBufferObjects.ContainsKey(sepd)) { return; } GL.EnableClientState(ArrayCap.ColorArray); GL.BindBuffer(BufferTarget.ArrayBuffer, colorBufferObjects[sepd]); GL.ColorPointer(4, sepd.ColorPointerType, 0, IntPtr.Zero); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); }
public ShpChunk(byte[] data, int offset, BaseCTRChunk parent) : base(data, offset, parent) { SepdCount = BitConverter.ToUInt32(ChunkData, 0x8); Unknown1 = BitConverter.ToUInt32(ChunkData, 0xC); SepdOffsets = new ushort[SepdCount]; for (int i = 0; i < SepdOffsets.Length; i++) { SepdOffsets[i] = BitConverter.ToUInt16(ChunkData, 0x10 + (i * 2)); } SepdChunks = new SepdChunk[SepdCount]; for (int i = 0; i < SepdChunks.Length; i++) { SepdChunks[i] = new SepdChunk(ChunkData, SepdOffsets[i], this); } }
public CmbChunk(byte[] data, int offset, BaseCTRChunk parent) : base(data, offset, parent) { FileSize = BitConverter.ToUInt32(ChunkData, 0x4); NumberOfChunks = BitConverter.ToUInt32(ChunkData, 0x8); Unknown2 = BitConverter.ToUInt32(ChunkData, 0xC); CmbName = Encoding.ASCII.GetString(ChunkData, 0x10, 16).TrimEnd('\0'); NumberOfIndices = BitConverter.ToUInt32(ChunkData, 0x20); BaseCTRChunk.IsMajora3D = (NumberOfChunks == 0x0A); if (!BaseCTRChunk.IsMajora3D) { SklChunk = new SklChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklChunkPointer_OoT), this); MatsChunk = new MatsChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, MatsChunkPointer_OoT), this); TexChunk = new TexChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, TexChunkPointer_OoT), this); SklmChunk = new SklmChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklmChunkPointer_OoT), this); VatrChunk = new VatrChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, VatrChunkPointer_OoT), this); vtxIdxOffset = (int)BitConverter.ToUInt32(ChunkData, VertexIndicesPointer_OoT); texDataOffset = (int)BitConverter.ToUInt32(ChunkData, TextureDataPointer_OoT); } else { SklChunk = new SklChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklChunkPointer_MM), this); MatsChunk = new MatsChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, MatsChunkPointer_MM), this); TexChunk = new TexChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, TexChunkPointer_MM), this); SklmChunk = new SklmChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, SklmChunkPointer_MM), this); VatrChunk = new VatrChunk(ChunkData, (int)BitConverter.ToUInt32(ChunkData, VatrChunkPointer_MM), this); vtxIdxOffset = (int)BitConverter.ToUInt32(ChunkData, VertexIndicesPointer_MM); texDataOffset = (int)BitConverter.ToUInt32(ChunkData, TextureDataPointer_MM); } Indices = new byte[NumberOfIndices * sizeof(ushort)]; Buffer.BlockCopy(ChunkData, vtxIdxOffset, Indices, 0, Indices.Length); TextureData = new byte[ChunkData.Length - texDataOffset]; Buffer.BlockCopy(ChunkData, texDataOffset, TextureData, 0, TextureData.Length); /* For information purposes, tho inexact if (probably) one array type isn't used by sepd (or smth) */ TotalPrimitives = 0; foreach (SepdChunk sepd in SklmChunk.ShpChunk.SepdChunks) { TotalPrimitives += sepd.TotalPrimitives; } TotalVertices = TotalTexCoords = TotalColors = TotalNormals = 0; for (int i = 0; i < SklmChunk.ShpChunk.SepdChunks.Length; i++) { if (i == SklmChunk.ShpChunk.SepdChunks.Length - 1) { SepdChunk sepdCurrent = SklmChunk.ShpChunk.SepdChunks[i]; if (VatrChunk.Sizes[VatrChunk.VertexArray_OoT] != 0) { TotalVertices += (int)((VatrChunk.Sizes[VatrChunk.VertexArray_OoT] - sepdCurrent.VertexArrayOffset) / sepdCurrent.VertexSize); } if (VatrChunk.Sizes[VatrChunk.TextureCoordArray_OoT] != 0) { TotalTexCoords += (int)((VatrChunk.Sizes[VatrChunk.TextureCoordArray_OoT] - sepdCurrent.TextureCoordArrayOffset) / sepdCurrent.TexCoordSize); } if (VatrChunk.Sizes[VatrChunk.ColorArray_OoT] != 0) { TotalColors += (int)((VatrChunk.Sizes[VatrChunk.ColorArray_OoT] - sepdCurrent.ColorArrayOffset) / sepdCurrent.ColorSize); } if (VatrChunk.Sizes[VatrChunk.NormalArray_OoT] != 0) { TotalNormals += (int)((VatrChunk.Sizes[VatrChunk.NormalArray_OoT] - sepdCurrent.NormalArrayOffset) / sepdCurrent.NormalSize); } } else { SepdChunk sepdCurrent = SklmChunk.ShpChunk.SepdChunks[i]; SepdChunk sepdNext = SklmChunk.ShpChunk.SepdChunks[i + 1]; if (VatrChunk.Sizes[VatrChunk.VertexArray_OoT] != 0) { TotalVertices += (int)((sepdNext.VertexArrayOffset - sepdCurrent.VertexArrayOffset) / sepdCurrent.VertexSize); } if (VatrChunk.Sizes[VatrChunk.TextureCoordArray_OoT] != 0) { TotalTexCoords += (int)((sepdNext.TextureCoordArrayOffset - sepdCurrent.TextureCoordArrayOffset) / sepdCurrent.TexCoordSize); } if (VatrChunk.Sizes[VatrChunk.ColorArray_OoT] != 0) { TotalColors += (int)((sepdNext.ColorArrayOffset - sepdCurrent.ColorArrayOffset) / sepdCurrent.ColorSize); } if (VatrChunk.Sizes[VatrChunk.NormalArray_OoT] != 0) { TotalNormals += (int)((sepdNext.NormalArrayOffset - sepdCurrent.NormalArrayOffset) / sepdCurrent.NormalSize); } } } }
private void PrepareBoneInformation(SepdChunk sepd, PrmsChunk prms) { /* TODO!! B/C HURR DURR, DON'T KNOW https://www.the-gcn.com/topic/2859-oot-3d-3ds-model-format-discussion/page-3#entry46121 */ if (prms.SkinningMode == PrmsChunk.SkinningModes.PerVertex) { uint[] lookupInts = new uint[(int)(Root.VatrChunk.BoneIndexLookup.Length - sepd.BoneIndexLookupArrayOffset) / sepd.BoneIndexLookupSize]; for (int i = 0; i < lookupInts.Length; i++) { switch (sepd.BoneIndexLookupArrayDataType) { case Constants.PicaDataType.Byte: case Constants.PicaDataType.UnsignedByte: lookupInts[i] = (uint)Root.VatrChunk.BoneIndexLookup[sepd.BoneIndexLookupArrayOffset + (i * sizeof(byte))]; break; case Constants.PicaDataType.Short: case Constants.PicaDataType.UnsignedShort: lookupInts[i] = (uint)BitConverter.ToUInt16(Root.VatrChunk.BoneIndexLookup, (int)(sepd.BoneIndexLookupArrayOffset + (i * sizeof(ushort)))); break; case Constants.PicaDataType.Int: case Constants.PicaDataType.UnsignedInt: lookupInts[i] = (uint)BitConverter.ToUInt32(Root.VatrChunk.BoneIndexLookup, (int)(sepd.BoneIndexLookupArrayOffset + (i * sizeof(uint)))); break; case Constants.PicaDataType.Float: lookupInts[i] = (uint)BitConverter.ToSingle(Root.VatrChunk.BoneIndexLookup, (int)(sepd.BoneIndexLookupArrayOffset + (i * sizeof(float)))); break; } } GL.ActiveTexture(TextureUnit.Texture0 + vertBoneTexUnit); GL.BindTexture(TextureTarget.TextureBuffer, vertBoneTexId); GL.BindBuffer(BufferTarget.TextureBuffer, vertBoneBufferId); GL.BufferData <uint>(BufferTarget.TextureBuffer, new IntPtr(lookupInts.Length * sizeof(uint)), lookupInts, BufferUsageHint.StaticDraw); GL.BindBuffer(BufferTarget.TextureBuffer, 0); } /* Maaaaaaybe? I dunno... not using this yet either */ Vector2[] weights = new Vector2[(int)(Root.VatrChunk.BoneWeights.Length - sepd.BoneWeightArrayOffset) / 2]; for (int i = 0, j = 0; i < weights.Length; i++, j += 2) { weights[i] = new Vector2( Root.VatrChunk.BoneWeights[sepd.BoneWeightArrayOffset + j], Root.VatrChunk.BoneWeights[sepd.BoneWeightArrayOffset + (j + 1)]); } for (int i = 0; i < prms.BoneIndexCount; i++) { Matrix4 matrix = Matrix4.Identity; SklChunk.Bone bone = Root.SklChunk.Bones.FirstOrDefault(x => x.BoneID == prms.BoneIndices[i]); if (bone != null) { matrix = bone.GetMatrix(prms.SkinningMode != PrmsChunk.SkinningModes.PerVertexNoTrans); } GL.UniformMatrix4(GL.GetUniformLocation(program, string.Format("boneMatrix[{0}]", i)), false, ref matrix); } }
public void Render(short meshToRender, Csab.AnimHandler animHandler = null) { if (Disposed) { throw new ObjectDisposedException(string.Format("{0} was disposed", this.GetType().Name)); } GL.PushAttrib(AttribMask.AllAttribBits); GL.PushClientAttrib(ClientAttribMask.ClientAllAttribBits); /* If we haven't yet, prepare some OGL stuff (shaders etc) */ if (!ready) { PrepareGL(); } /* Shaders or no shaders? */ if (Properties.Settings.Default.DisableAllShaders) { GL.UseProgram(0); } else { GL.UseProgram(program); } /* Some setup if we want the wireframe overlay... */ if (Properties.Settings.Default.AddWireframeOverlay) { GL.Enable(EnableCap.PolygonOffsetFill); GL.PolygonOffset(2.0f, 2.0f); } else { GL.Disable(EnableCap.PolygonOffsetFill); } /* Determine what to render... */ List <MshsChunk.Mesh> renderList = new List <MshsChunk.Mesh>(); if (meshToRender != -1) { renderList.Add(Root.SklmChunk.MshsChunk.Meshes[meshToRender]); } else { renderList.AddRange(Root.SklmChunk.MshsChunk.Meshes); renderList = renderList.OrderBy(x => x.Unknown).ToList(); } /* Render meshes normally */ foreach (MshsChunk.Mesh mesh in renderList) { if (mesh.SepdID > Root.SklmChunk.ShpChunk.SepdChunks.Length) { continue; } if (mesh.MaterialID > Root.MatsChunk.Materials.Length) { continue; } if (mesh.MaterialID > Root.MatsChunk.TextureEnvSettings.Length) { continue; } SepdChunk sepd = Root.SklmChunk.ShpChunk.SepdChunks[mesh.SepdID]; MatsChunk.Material mat = Root.MatsChunk.Materials[mesh.MaterialID]; MatsChunk.TextureEnvSetting tenv = Root.MatsChunk.TextureEnvSettings[mesh.MaterialID]; /* Blend, Alphatest, etc (likely incorrect) */ GL.Enable(EnableCap.Blend); GL.BlendFunc(mat.BlendingFactorSrc, mat.BlendingFactorDest); GL.BlendColor(1.0f, 1.0f, 1.0f, mat.BlendColorA); if (mat.AlphaTestEnable) { GL.Enable(EnableCap.AlphaTest); } else { GL.Disable(EnableCap.AlphaTest); } GL.AlphaFunc(mat.AlphaFunction, mat.AlphaReference); /* Texenv stuff testing, tho it doesn't work w/ shaders anyway, I dunno */ /* Probably needs seperate shader per material, where the texenv stuff gets simulated... */ /* And yes, I know this doesn't map 100% to standard OpenGL anyway */ if (false) { GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Combine); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineRgb, (int)tenv.CombineRgb); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Source0Rgb, (int)tenv.SourceRgb[0]); // OpenTK, Y U name this one differently? GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src1Rgb, (int)tenv.SourceRgb[1]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src2Rgb, (int)tenv.SourceRgb[2]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand0Rgb, (int)tenv.OperandRgb[0]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand1Rgb, (int)tenv.OperandRgb[1]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand2Rgb, (int)tenv.OperandRgb[2]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineAlpha, (int)tenv.CombineAlpha); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src0Alpha, (int)tenv.SourceAlpha[0]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src1Alpha, (int)tenv.SourceAlpha[1]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Src2Alpha, (int)tenv.SourceAlpha[2]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand0Alpha, (int)tenv.OperandAlpha[0]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand1Alpha, (int)tenv.OperandAlpha[1]); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Operand2Alpha, (int)tenv.OperandAlpha[2]); } /* Apply textures :P */ ApplyTextures(mat); /* Setup component arrays */ GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.ColorArray); GL.DisableClientState(ArrayCap.TextureCoordArray); GL.DisableClientState(ArrayCap.VertexArray); SetupNormalArray(sepd); SetupColorArray(sepd); SetupTextureCoordArray(sepd); SetupVertexArray(sepd); /* Send stuff to shader */ GL.Uniform1(boneIdLocation, 0); GL.Uniform1(vertBoneSamplerLocation, vertBoneTexUnit); GL.Uniform1(tex0Location, 0); GL.Uniform1(tex1Location, 1); GL.Uniform1(tex2Location, 2); //GL.Uniform4(materialColorLocation, 1.0f, 1.0f, 1.0f, mat.Float158); GL.Uniform4(materialColorLocation, 1.0f, 1.0f, 1.0f, 1.0f); GL.Uniform1(vertexScaleLocation, sepd.VertexArrayScale); GL.Uniform1(texCoordScaleLocation, sepd.TextureCoordArrayScale); GL.Uniform1(normalScaleLocation, sepd.NormalArrayScale); GL.Uniform1(disableAlphaLocation, Convert.ToInt16(Properties.Settings.Default.DisableAlpha)); GL.Uniform1(enableLightingLocation, Convert.ToInt16(Properties.Settings.Default.EnableLighting)); GL.Uniform1(enableSkeletalStuffLocation, Convert.ToInt16(Properties.Settings.Default.EnableSkeletalStuff)); /* Render each prms chunk */ foreach (PrmsChunk prms in sepd.PrmsChunks) { PrepareBoneInformation(sepd, prms); GL.Uniform1(skinningModeLocation, Convert.ToInt16(prms.SkinningMode)); RenderBuffer(prms); } /* Clean up arrays */ GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.ColorArray); GL.DisableClientState(ArrayCap.TextureCoordArray); GL.DisableClientState(ArrayCap.VertexArray); } /* Render wireframe overlay */ if (Properties.Settings.Default.AddWireframeOverlay && !Properties.Settings.Default.DisableAllShaders) { GL.UseProgram(programOverlay); foreach (MshsChunk.Mesh mesh in renderList) { GL.Disable(EnableCap.PolygonOffsetFill); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); SepdChunk sepd = Root.SklmChunk.ShpChunk.SepdChunks[mesh.SepdID]; GL.Uniform1(vertexScaleLocationOverlay, sepd.VertexArrayScale); GL.Uniform1(enableSkeletalStuffLocationOverlay, Convert.ToInt16(Properties.Settings.Default.EnableSkeletalStuff)); SetupVertexArray(sepd); GL.Uniform1(boneIdLocationOverlay, 0); GL.Uniform1(vertBoneSamplerLocationOverlay, vertBoneTexUnit); foreach (PrmsChunk prms in sepd.PrmsChunks) { PrepareBoneInformation(sepd, prms); GL.Uniform1(skinningModeLocationOverlay, Convert.ToInt16(prms.SkinningMode)); RenderBuffer(prms); } GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.ColorArray); GL.DisableClientState(ArrayCap.TextureCoordArray); GL.DisableClientState(ArrayCap.VertexArray); } } /* Reset stuff */ GL.Disable(EnableCap.AlphaTest); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); /* Render skeleton */ //if (false) { // TODO get rid of immediate mode GL.PushAttrib(AttribMask.AllAttribBits); GL.Disable(EnableCap.Texture2D); GL.Disable(EnableCap.DepthTest); GL.Disable(EnableCap.Lighting); GL.PointSize(10.0f); GL.LineWidth(5.0f); GL.UseProgram(0); GL.Color4(Color4.Red); GL.Begin(PrimitiveType.Points); foreach (SklChunk.Bone bone in Root.SklChunk.Bones) { GL.Vertex3(Vector3.Transform(Vector3.One, bone.GetMatrix(true))); } GL.End(); GL.Color4(Color4.Blue); GL.Begin(PrimitiveType.Lines); foreach (SklChunk.Bone bone in Root.SklChunk.Bones.Where(x => x.ParentBone != null)) { GL.Vertex3(Vector3.Transform(Vector3.One, bone.GetMatrix(true))); GL.Vertex3(Vector3.Transform(Vector3.One, bone.ParentBone.GetMatrix(true))); } GL.End(); GL.PopAttrib(); // END TODO } GL.PopClientAttrib(); GL.PopAttrib(); }
private void PrepareBuffers() { vertexBufferObjects = new Dictionary <SepdChunk, int>(); normalBufferObjects = new Dictionary <SepdChunk, int>(); colorBufferObjects = new Dictionary <SepdChunk, int>(); texCoordBufferObjects = new Dictionary <SepdChunk, int>(); elementBufferObjects = new Dictionary <PrmsChunk, int>(); foreach (MshsChunk.Mesh mesh in Root.SklmChunk.MshsChunk.Meshes) { int size, expectedSize; SepdChunk sepd = Root.SklmChunk.ShpChunk.SepdChunks[mesh.SepdID]; if (Root.VatrChunk.Vertices.Length > 0) { int newVertexBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, newVertexBuffer); if (sepd.VertexArrayDataType == Constants.PicaDataType.Byte || sepd.VertexArrayDataType == Constants.PicaDataType.UnsignedByte) { short[] converted = new short[Root.VatrChunk.Vertices.Length]; expectedSize = (converted.Length * sizeof(ushort)); for (int i = 0; i < Root.VatrChunk.Vertices.Length; i++) { converted[i] = Root.VatrChunk.Vertices[i]; } GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(expectedSize), ref converted[sepd.VertexArrayOffset], BufferUsageHint.StaticDraw); } else { expectedSize = (int)(Root.VatrChunk.Vertices.Length - sepd.VertexArrayOffset); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(expectedSize), ref Root.VatrChunk.Vertices[sepd.VertexArrayOffset], BufferUsageHint.StaticDraw); } GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out size); if (size != expectedSize) { throw new ApplicationException(string.Format("Problem uploading vertices to VBO; tried {0} bytes, uploaded {1}", expectedSize, size)); } GL.BindBuffer(BufferTarget.ArrayBuffer, 0); vertexBufferObjects.Add(sepd, newVertexBuffer); } if (Root.VatrChunk.Normals.Length > 0) { int newNormalBuffer = GL.GenBuffer(); expectedSize = (int)(Root.VatrChunk.Normals.Length - sepd.NormalArrayOffset); GL.BindBuffer(BufferTarget.ArrayBuffer, newNormalBuffer); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(expectedSize), ref Root.VatrChunk.Normals[sepd.NormalArrayOffset], BufferUsageHint.StaticDraw); GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out size); if (size != expectedSize) { throw new ApplicationException(string.Format("Problem uploading normals to VBO; tried {0} bytes, uploaded {1}", expectedSize, size)); } GL.BindBuffer(BufferTarget.ArrayBuffer, 0); normalBufferObjects.Add(sepd, newNormalBuffer); } if (Root.VatrChunk.Colors.Length > 0) { int newColorBuffer = GL.GenBuffer(); expectedSize = (int)(Root.VatrChunk.Colors.Length - sepd.ColorArrayOffset); GL.BindBuffer(BufferTarget.ArrayBuffer, newColorBuffer); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(expectedSize), ref Root.VatrChunk.Colors[sepd.ColorArrayOffset], BufferUsageHint.StaticDraw); GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out size); if (size != expectedSize) { throw new ApplicationException(string.Format("Problem uploading colors to VBO; tried {0} bytes, uploaded {1}", expectedSize, size)); } GL.BindBuffer(BufferTarget.ArrayBuffer, 0); colorBufferObjects.Add(sepd, newColorBuffer); } if (Root.VatrChunk.TextureCoords.Length > 0) { int newTexCoordBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, newTexCoordBuffer); if (sepd.TextureCoordArrayDataType == Constants.PicaDataType.Byte || sepd.TextureCoordArrayDataType == Constants.PicaDataType.UnsignedByte) { short[] converted = new short[Root.VatrChunk.TextureCoords.Length]; expectedSize = (converted.Length * sizeof(ushort)); for (int i = 0; i < Root.VatrChunk.TextureCoords.Length; i++) { converted[i] = Root.VatrChunk.TextureCoords[i]; } GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(expectedSize), ref converted[sepd.TextureCoordArrayOffset], BufferUsageHint.StaticDraw); } else { expectedSize = (int)(Root.VatrChunk.TextureCoords.Length - sepd.TextureCoordArrayOffset); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(expectedSize), ref Root.VatrChunk.TextureCoords[sepd.TextureCoordArrayOffset], BufferUsageHint.StaticDraw); } GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out size); if (size != expectedSize) { throw new ApplicationException(string.Format("Problem uploading texcoords to VBO; tried {0} bytes, uploaded {1}", expectedSize, size)); } GL.BindBuffer(BufferTarget.ArrayBuffer, 0); texCoordBufferObjects.Add(sepd, newTexCoordBuffer); } foreach (PrmsChunk prms in sepd.PrmsChunks) { int newElementBuffer = GL.GenBuffer(); expectedSize = (prms.PrmChunk.NumberOfIndices * prms.PrmChunk.ElementSize); GL.BindBuffer(BufferTarget.ElementArrayBuffer, newElementBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(expectedSize), ref Root.Indices[prms.PrmChunk.FirstIndex * sizeof(ushort)], BufferUsageHint.StaticDraw); GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out size); if (size != expectedSize) { throw new ApplicationException(string.Format("Problem uploading indices to VBO; tried {0} bytes, uploaded {1}", expectedSize, size)); } GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); elementBufferObjects.Add(prms, newElementBuffer); } } }
private static void WriteSectionLibraryVisualScenes(XmlTextWriter xw, CmbChunk cmbRoot) { xw.WriteStartElement("library_visual_scenes"); { xw.WriteStartElement("visual_scene"); xw.WriteAttributeString("id", "default"); { foreach (MshsChunk.Mesh mesh in cmbRoot.SklmChunk.MshsChunk.Meshes) { SepdChunk sepd = cmbRoot.SklmChunk.ShpChunk.SepdChunks[mesh.SepdID]; MatsChunk.Material mat = cmbRoot.MatsChunk.Materials[mesh.MaterialID]; string nodeId = string.Format("node-{0:X8}", mesh.GetHashCode()); xw.WriteStartElement("node"); xw.WriteAttributeString("id", nodeId); xw.WriteAttributeString("name", nodeId); { xw.WriteStartElement("translate"); xw.WriteString("0.0 0.0 0.0"); xw.WriteEndElement(); xw.WriteStartElement("rotate"); xw.WriteString("0.0 0.0 1.0 0.0"); xw.WriteEndElement(); xw.WriteStartElement("rotate"); xw.WriteString("0.0 1.0 0.0 0.0"); xw.WriteEndElement(); xw.WriteStartElement("rotate"); xw.WriteString("1.0 0.0 0.0 0.0"); xw.WriteEndElement(); xw.WriteStartElement("scale"); xw.WriteString("1.0 1.0 1.0"); xw.WriteEndElement(); xw.WriteStartElement("instance_geometry"); xw.WriteAttributeString("url", string.Format("#geom-{0:X8}", mesh.GetHashCode())); { xw.WriteStartElement("bind_material"); { xw.WriteStartElement("technique_common"); { xw.WriteStartElement("instance_material"); xw.WriteAttributeString("symbol", string.Format("material-{0:X8}-symbol", mat.GetHashCode())); xw.WriteAttributeString("target", string.Format("#material-{0:X8}", mat.GetHashCode())); xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); } } xw.WriteEndElement(); } xw.WriteEndElement(); }
private static void WriteSectionLibraryGeometry(XmlTextWriter xw, CmbChunk cmbRoot) { xw.WriteStartElement("library_geometries"); { foreach (MshsChunk.Mesh mesh in cmbRoot.SklmChunk.MshsChunk.Meshes) { SepdChunk sepd = cmbRoot.SklmChunk.ShpChunk.SepdChunks[mesh.SepdID]; MatsChunk.Material mat = cmbRoot.MatsChunk.Materials[mesh.MaterialID]; string meshId = string.Format("geom-{0:X8}", mesh.GetHashCode()); xw.WriteStartElement("geometry"); xw.WriteAttributeString("id", meshId); xw.WriteAttributeString("name", meshId); { xw.WriteStartElement("mesh"); { /* Vertices */ xw.WriteStartElement("source"); xw.WriteAttributeString("id", string.Format("{0}-pos", meshId)); { float[] vtxData = ConvertToFloatArray(sepd.VertexArrayDataType, cmbRoot.VatrChunk.Vertices, sepd.VertexArrayOffset, sepd.VertexArrayScale); xw.WriteStartElement("float_array"); xw.WriteAttributeString("id", string.Format("{0}-pos-array", meshId)); xw.WriteAttributeString("count", string.Format("{0}", vtxData.Length)); { for (int i = 0; i < vtxData.Length; i++) { xw.WriteString(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00} ", vtxData[i])); } } xw.WriteEndElement(); xw.WriteStartElement("technique_common"); { xw.WriteStartElement("accessor"); xw.WriteAttributeString("source", string.Format("#{0}-pos-array", meshId)); xw.WriteAttributeString("count", string.Format("{0}", vtxData.Length / 3)); xw.WriteAttributeString("stride", "3"); { xw.WriteStartElement("param"); xw.WriteAttributeString("name", "X"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); xw.WriteStartElement("param"); xw.WriteAttributeString("name", "Y"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); xw.WriteStartElement("param"); xw.WriteAttributeString("name", "Z"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); /* Texcoords */ xw.WriteStartElement("source"); xw.WriteAttributeString("id", string.Format("{0}-texcoord", meshId)); { float[] texCoordData = ConvertToFloatArray(sepd.TextureCoordArrayDataType, cmbRoot.VatrChunk.TextureCoords, sepd.TextureCoordArrayOffset, sepd.TextureCoordArrayScale); xw.WriteStartElement("float_array"); xw.WriteAttributeString("id", string.Format("{0}-texcoord-array", meshId)); xw.WriteAttributeString("count", string.Format("{0}", texCoordData.Length)); { for (int i = 0; i < texCoordData.Length; i++) { xw.WriteString(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00} ", texCoordData[i])); } } xw.WriteEndElement(); xw.WriteStartElement("technique_common"); { xw.WriteStartElement("accessor"); xw.WriteAttributeString("source", string.Format("#{0}-texcoord-array", meshId)); xw.WriteAttributeString("count", string.Format("{0}", texCoordData.Length / 2)); xw.WriteAttributeString("stride", "2"); { xw.WriteStartElement("param"); xw.WriteAttributeString("name", "S"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); xw.WriteStartElement("param"); xw.WriteAttributeString("name", "T"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); /* Colors */ xw.WriteStartElement("source"); xw.WriteAttributeString("id", string.Format("{0}-colors", meshId)); { float[] colorData = ConvertToFloatArray(sepd.ColorArrayDataType, cmbRoot.VatrChunk.Colors, sepd.ColorArrayOffset, sepd.ColorArrayScale); xw.WriteStartElement("float_array"); xw.WriteAttributeString("id", string.Format("{0}-colors-array", meshId)); xw.WriteAttributeString("count", string.Format("{0}", colorData.Length)); { for (int i = 0; i < colorData.Length; i++) { xw.WriteString(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00} ", colorData[i])); } } xw.WriteEndElement(); xw.WriteStartElement("technique_common"); { xw.WriteStartElement("accessor"); xw.WriteAttributeString("source", string.Format("#{0}-colors-array", meshId)); xw.WriteAttributeString("count", string.Format("{0}", colorData.Length / 4)); xw.WriteAttributeString("stride", "4"); { xw.WriteStartElement("param"); xw.WriteAttributeString("name", "R"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); xw.WriteStartElement("param"); xw.WriteAttributeString("name", "G"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); xw.WriteStartElement("param"); xw.WriteAttributeString("name", "B"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); xw.WriteStartElement("param"); xw.WriteAttributeString("name", "A"); xw.WriteAttributeString("type", "float"); xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); } xw.WriteEndElement(); /* Normals */ /*xw.WriteStartElement("source"); * xw.WriteAttributeString("id", string.Format("{0}-norm", meshId)); * { * float[] normData = ConvertToFloatArray(sepd.NormalArrayFormat, cmbRoot.VatrChunk.Normals, sepd.NormalArrayDisplacement, sepd.NormalArrayScale); * * xw.WriteStartElement("float_array"); * xw.WriteAttributeString("id", string.Format("{0}-norm-array", meshId)); * xw.WriteAttributeString("count", string.Format("{0}", normData.Length)); * { * for (int i = 0; i < normData.Length; i += 3) * { * xw.WriteString(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:0.00} {1:0.00} {2:0.00} ", normData[i], normData[i + 1], normData[i + 2])); * } * } * xw.WriteEndElement(); * * xw.WriteStartElement("technique_common"); * { * xw.WriteStartElement("accessor"); * xw.WriteAttributeString("source", string.Format("#{0}-norm-array", meshId)); * xw.WriteAttributeString("count", string.Format("{0}", normData.Length / 3)); * xw.WriteAttributeString("stride", "3"); * { * xw.WriteStartElement("param"); * xw.WriteAttributeString("name", "X"); * xw.WriteAttributeString("type", "float"); * xw.WriteEndElement(); * * xw.WriteStartElement("param"); * xw.WriteAttributeString("name", "Y"); * xw.WriteAttributeString("type", "float"); * xw.WriteEndElement(); * * xw.WriteStartElement("param"); * xw.WriteAttributeString("name", "Z"); * xw.WriteAttributeString("type", "float"); * xw.WriteEndElement(); * } * xw.WriteEndElement(); * } * xw.WriteEndElement(); * } * xw.WriteEndElement(); */ xw.WriteStartElement("vertices"); xw.WriteAttributeString("id", string.Format("{0}-vtx", meshId)); { xw.WriteStartElement("input"); xw.WriteAttributeString("semantic", "POSITION"); xw.WriteAttributeString("source", string.Format("#{0}-pos", meshId)); xw.WriteEndElement(); } xw.WriteEndElement(); foreach (PrmsChunk prms in sepd.PrmsChunks) { xw.WriteStartElement("triangles"); xw.WriteAttributeString("count", string.Format("{0}", prms.PrmChunk.NumberOfIndices)); xw.WriteAttributeString("material", string.Format("material-{0:X8}-symbol", mat.GetHashCode())); { xw.WriteStartElement("input"); xw.WriteAttributeString("semantic", "VERTEX"); xw.WriteAttributeString("source", string.Format("#{0}-vtx", meshId)); xw.WriteAttributeString("offset", "0"); xw.WriteEndElement(); xw.WriteStartElement("input"); xw.WriteAttributeString("semantic", "TEXCOORD"); xw.WriteAttributeString("source", string.Format("#{0}-texcoord", meshId)); xw.WriteAttributeString("offset", "0"); xw.WriteEndElement(); xw.WriteStartElement("input"); xw.WriteAttributeString("semantic", "COLOR"); xw.WriteAttributeString("source", string.Format("#{0}-colors", meshId)); xw.WriteAttributeString("offset", "0"); xw.WriteEndElement(); /* * xw.WriteStartElement("input"); * xw.WriteAttributeString("semantic", "NORMAL"); * xw.WriteAttributeString("source", string.Format("#{0}-norm", meshId)); * xw.WriteAttributeString("offset", "0"); * xw.WriteEndElement(); */ uint[] idx = new uint[prms.PrmChunk.NumberOfIndices]; switch (prms.PrmChunk.DataType) { case Constants.PicaDataType.UnsignedByte: for (int i = 0; i < prms.PrmChunk.NumberOfIndices; i++) { idx[i] = (uint)cmbRoot.Indices[(prms.PrmChunk.FirstIndex * sizeof(ushort)) + (i * prms.PrmChunk.ElementSize)]; } break; case Constants.PicaDataType.UnsignedShort: for (int i = 0; i < prms.PrmChunk.NumberOfIndices; i++) { idx[i] = (uint)BitConverter.ToUInt16(cmbRoot.Indices, (prms.PrmChunk.FirstIndex * sizeof(ushort)) + (i * prms.PrmChunk.ElementSize)); } break; case Constants.PicaDataType.UnsignedInt: for (int i = 0; i < prms.PrmChunk.NumberOfIndices; i++) { idx[i] = BitConverter.ToUInt32(cmbRoot.Indices, (prms.PrmChunk.FirstIndex * sizeof(ushort)) + (i * prms.PrmChunk.ElementSize)); } break; } xw.WriteStartElement("p"); { for (int i = 0; i < idx.Length; i++) { xw.WriteString(string.Format("{0} ", idx[i])); } } xw.WriteEndElement(); } xw.WriteEndElement(); } } xw.WriteEndElement(); } xw.WriteEndElement(); } } xw.WriteEndElement(); }