private void render() { glControl1.MakeCurrent(); GL.Viewport(0, 0, glControl1.ClientSize.Width, glControl1.ClientSize.Height); //clear GL.ClearColor(backgroundColorDialog.Color); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); //projection matrix Matrix4 projection = glControl1.Camera.Projection; GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref projection); //view matrix Matrix4 view = glControl1.Camera.View; GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref view); if (showAxesButton.Checked) { // debug axes GL.Begin(PrimitiveType.Lines); //x GL.Color3(Color.Red); GL.Vertex3(Vector3.Zero); GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX + new Vector3(-0.125f, 0.125f, 0.0f)); GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX + new Vector3(-0.125f, -0.125f, 0.0f)); //y GL.Color3(Color.Green); GL.Vertex3(Vector3.Zero); GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY + new Vector3(0.125f, -0.125f, 0.0f)); GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY + new Vector3(-0.125f, -0.125f, 0.0f)); //z GL.Color3(Color.Blue); GL.Vertex3(Vector3.Zero); GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ + new Vector3(0, -0.125f, -0.125f)); GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ + new Vector3(0, 0.125f, -0.125f)); GL.End(); } //TODO: Decide what to do with non-version 4 models. if (model != null && model.Version == 4) { GL.PushMatrix(); GL.PushAttrib(AttribMask.PolygonBit | AttribMask.EnableBit | AttribMask.LightingBit | AttribMask.CurrentBit); GL.UseProgram(currentShader); GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.CullFace(CullFaceMode.Back); GL.FrontFace(FrontFaceDirection.Cw); for (Int32 i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, textures[i]); if (currentShader == texturedShader) { int loc = GL.GetUniformLocation(currentShader, "colorMap"); GL.Uniform1(loc, 0); } //pin handles to stream data GCHandle[] streamDataGCHandles = new GCHandle[mesh.VertexStreams.Length]; for (Int32 j = 0; j < streamDataGCHandles.Length; ++j) { streamDataGCHandles[j] = GCHandle.Alloc(mesh.VertexStreams[j].Data, GCHandleType.Pinned); } //fetch material definition and vertex layout Int32 materialIndex = (Int32)mesh.MaterialIndex; uint materialDefinitionHash = model.Materials[materialIndex].MaterialDefinitionHash; MaterialDefinition materialDefinition = null; VertexLayout vertexLayout = null; if (MaterialDefinitionManager.Instance.MaterialDefinitions.ContainsKey(materialDefinitionHash)) { materialDefinition = MaterialDefinitionManager.Instance.MaterialDefinitions[materialDefinitionHash]; vertexLayout = MaterialDefinitionManager.Instance.VertexLayouts[materialDefinition.DrawStyles[0].VertexLayoutNameHash]; } GL.Color3(meshColors[i % meshColors.Length]); if (renderModeWireframeButton.Checked) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } else { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } //position VertexLayout.Entry.DataTypes positionDataType = VertexLayout.Entry.DataTypes.None; Int32 positionStream = 0; Int32 positionOffset = 0; bool positionExists = (vertexLayout != null ? vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStream, out positionOffset) : false); if (positionExists) { IntPtr positionData = streamDataGCHandles[positionStream].AddrOfPinnedObject(); GL.EnableClientState(ArrayCap.VertexArray); GL.VertexPointer(3, VertexPointerType.Float, mesh.VertexStreams[positionStream].BytesPerVertex, positionData + positionOffset); } //normal VertexLayout.Entry.DataTypes normalDataType = VertexLayout.Entry.DataTypes.None; Int32 normalStream = 0; Int32 normalOffset = 0; bool normalExists = (vertexLayout != null ? vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Normal, 0, out normalDataType, out normalStream, out normalOffset) : false); if (normalExists) { IntPtr normalData = streamDataGCHandles[normalStream].AddrOfPinnedObject(); GL.EnableClientState(ArrayCap.NormalArray); GL.NormalPointer(NormalPointerType.Float, mesh.VertexStreams[normalStream].BytesPerVertex, normalData + normalOffset); } //texture coordiantes VertexLayout.Entry.DataTypes texCoord0DataType = VertexLayout.Entry.DataTypes.None; Int32 texCoord0Stream = 0; Int32 texCoord0Offset = 0; bool texCoord0Exists = (vertexLayout != null ? vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0Stream, out texCoord0Offset) : false); if (texCoord0Exists) { IntPtr texCoord0Data = streamDataGCHandles[texCoord0Stream].AddrOfPinnedObject(); GL.EnableClientState(ArrayCap.TextureCoordArray); TexCoordPointerType texCoord0PointerType = TexCoordPointerType.Float; switch (texCoord0DataType) { case VertexLayout.Entry.DataTypes.Float2: texCoord0PointerType = TexCoordPointerType.Float; break; case VertexLayout.Entry.DataTypes.float16_2: texCoord0PointerType = TexCoordPointerType.HalfFloat; break; default: break; } GL.TexCoordPointer(2, texCoord0PointerType, mesh.VertexStreams[texCoord0Stream].BytesPerVertex, texCoord0Data + texCoord0Offset); } //indices GCHandle indexDataHandle = GCHandle.Alloc(mesh.IndexData, GCHandleType.Pinned); IntPtr indexData = indexDataHandle.AddrOfPinnedObject(); GL.DrawElements(PrimitiveType.Triangles, (Int32)mesh.IndexCount, DrawElementsType.UnsignedShort, indexData); indexDataHandle.Free(); GL.DisableClientState(ArrayCap.VertexArray); GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.TextureCoordArray); //free stream data handles for (Int32 j = 0; j < streamDataGCHandles.Length; ++j) { streamDataGCHandles[j].Free(); } } GL.UseProgram(0); GL.PopAttrib(); ////bounding box //if (showBoundingBoxButton.Checked) //{ // GL.PushAttrib(AttribMask.CurrentBit | AttribMask.EnableBit); // GL.Color3(Color.Red); // GL.Enable(EnableCap.DepthTest); // Vector3 min = model.Min; // Vector3 max = model.Max; // Vector3[] vertices = new Vector3[8]; // UInt32[] indices = { 0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 1, 5, 2, 6, 3, 7, 4, 5, 5, 6, 6, 7, 7, 4 }; // vertices[0] = min; // vertices[1] = new Vector3(max.X, min.Y, min.Z); // vertices[2] = new Vector3(max.X, min.Y, max.Z); // vertices[3] = new Vector3(min.X, min.Y, max.Z); // vertices[4] = new Vector3(min.X, max.Y, min.Z); // vertices[5] = new Vector3(max.X, max.Y, min.Z); // vertices[6] = max; // vertices[7] = new Vector3(min.X, max.Y, max.Z); // GL.EnableClientState(ArrayCap.VertexArray); // GL.VertexPointer(3, VertexPointerType.Float, 0, vertices); // GL.DrawRangeElements(BeginMode.Lines, 0, 23, 24, DrawElementsType.UnsignedInt, indices); // GL.PopAttrib(); //} } glControl1.SwapBuffers(); }
private Vector3 ReadVector3(int offset, Mesh.VertexStream vertexStream, int index, VertexLayout.Entry.DataTypes dataType) { Vector3 vector3 = new Vector3(); switch (dataType) { case VertexLayout.Entry.DataTypes.Float3: vector3.x = BitConverter.ToSingle(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 0); vector3.y = BitConverter.ToSingle(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 4); vector3.z = BitConverter.ToSingle(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 8); break; default: throw new InvalidDataException($"Unhandled stream DataType \"{dataType}\""); } return vector3; }
private Vector2 ReadVector2(int offset, Mesh.VertexStream vertexStream, int index, VertexLayout.Entry.DataTypes dataType) { Vector2 vector2 = new Vector2(); switch (dataType) { case VertexLayout.Entry.DataTypes.Float2: vector2.x = BitConverter.ToSingle(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 0); vector2.y = 1.0f - BitConverter.ToSingle(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 4); break; case VertexLayout.Entry.DataTypes.float16_2: vector2.x = Mathf.HalfToFloat(BitConverter.ToUInt16(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 0)); vector2.y = 1.0f - Mathf.HalfToFloat(BitConverter.ToUInt16(vertexStream.Data, (vertexStream.BytesPerVertex * index) + offset + 2)); break; default: throw new InvalidDataException($"Unhandled stream DataType \"{dataType}\""); } return vector2; }
public override void Render() { if (DesignMode) { return; } MakeCurrent(); GL.Viewport(0, 0, ClientSize.Width, ClientSize.Height); //clear GL.ClearColor(Color.Black); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); if (Camera == null) { return; } //projection matrix Matrix4 projection = Camera.Projection; GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref projection); //view matrix Matrix4 view = Camera.View; GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref view); if (DrawAxes) { // debug axes GL.Begin(BeginMode.Lines); //x GL.Color3(Color.Red); GL.Vertex3(Vector3.Zero); GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX + new Vector3(-0.125f, 0.125f, 0.0f)); GL.Vertex3(Vector3.UnitX); GL.Vertex3(Vector3.UnitX + new Vector3(-0.125f, -0.125f, 0.0f)); //y GL.Color3(Color.Green); GL.Vertex3(Vector3.Zero); GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY + new Vector3(0.125f, -0.125f, 0.0f)); GL.Vertex3(Vector3.UnitY); GL.Vertex3(Vector3.UnitY + new Vector3(-0.125f, -0.125f, 0.0f)); //z GL.Color3(Color.Blue); GL.Vertex3(Vector3.Zero); GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ + new Vector3(0, -0.125f, -0.125f)); GL.Vertex3(Vector3.UnitZ); GL.Vertex3(Vector3.UnitZ + new Vector3(0, 0.125f, -0.125f)); GL.End(); } if (Model != null) { GL.PushMatrix(); GL.PushAttrib(AttribMask.PolygonBit | AttribMask.EnableBit | AttribMask.LightingBit | AttribMask.CurrentBit); GL.UseProgram(shaderProgram); GL.Enable(EnableCap.DepthTest); GL.Disable(EnableCap.CullFace); GL.Enable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.FrontFace(FrontFaceDirection.Cw); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, 0); int loc = GL.GetUniformLocation(shaderProgram, "colorMap"); GL.Uniform1(loc, 0); for (int i = 0; i < Model.Meshes.Length; ++i) { Mesh mesh = Model.Meshes[i]; //pin handles to stream data GCHandle[] streamDataGCHandles = new GCHandle[mesh.VertexStreams.Length]; for (int j = 0; j < streamDataGCHandles.Length; ++j) { streamDataGCHandles[j] = GCHandle.Alloc(mesh.VertexStreams[j].Data, GCHandleType.Pinned); } //fetch material definition and vertex layout VertexLayout vertexLayout = mesh.GetVertexLayout(0); GL.Color3(meshColors[i % meshColors.Length]); switch (RenderMode) { case RenderModes.Wireframe: { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } break; case RenderModes.Smooth: { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } break; } //position VertexLayout.Entry.DataTypes positionDataType = VertexLayout.Entry.DataTypes.None; int positionStream = 0; int positionOffset = 0; bool positionExists = vertexLayout.GetEntryInfo(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStream, out positionOffset); if (positionExists) { IntPtr positionData = streamDataGCHandles[positionStream].AddrOfPinnedObject(); GL.EnableClientState(ArrayCap.VertexArray); GL.VertexPointer(3, VertexPointerType.Float, mesh.VertexStreams[positionStream].BytesPerVertex, positionData + positionOffset); } //normal VertexLayout.Entry.DataTypes normalDataType = VertexLayout.Entry.DataTypes.None; int normalStream = 0; int normalOffset = 0; bool normalExists = vertexLayout.GetEntryInfo(VertexLayout.Entry.DataUsages.Normal, 0, out normalDataType, out normalStream, out normalOffset); if (normalExists) { IntPtr normalData = streamDataGCHandles[normalStream].AddrOfPinnedObject(); GL.EnableClientState(ArrayCap.NormalArray); GL.NormalPointer(NormalPointerType.Float, mesh.VertexStreams[normalStream].BytesPerVertex, normalData + normalOffset); } //texture coordiantes VertexLayout.Entry.DataTypes texCoord0DataType = VertexLayout.Entry.DataTypes.None; int texCoord0Stream = 0; int texCoord0Offset = 0; bool texCoord0Exists = vertexLayout.GetEntryInfo(VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0Stream, out texCoord0Offset); if (texCoord0Exists) { IntPtr texCoord0Data = streamDataGCHandles[texCoord0Stream].AddrOfPinnedObject(); GL.EnableClientState(ArrayCap.TextureCoordArray); TexCoordPointerType texCoord0PointerType = TexCoordPointerType.Float; switch (texCoord0DataType) { case VertexLayout.Entry.DataTypes.Float2: texCoord0PointerType = TexCoordPointerType.Float; break; case VertexLayout.Entry.DataTypes.float16_2: texCoord0PointerType = TexCoordPointerType.HalfFloat; break; default: break; } GL.TexCoordPointer(2, texCoord0PointerType, mesh.VertexStreams[texCoord0Stream].BytesPerVertex, texCoord0Data + texCoord0Offset); } //indices GCHandle indexDataHandle = GCHandle.Alloc(mesh.IndexData, GCHandleType.Pinned); IntPtr indexData = indexDataHandle.AddrOfPinnedObject(); GL.DrawElements(BeginMode.Triangles, (int)mesh.IndexCount, DrawElementsType.UnsignedShort, indexData); indexDataHandle.Free(); GL.DisableClientState(ArrayCap.VertexArray); GL.DisableClientState(ArrayCap.NormalArray); GL.DisableClientState(ArrayCap.TextureCoordArray); //free stream data handles for (int j = 0; j < streamDataGCHandles.Length; ++j) { streamDataGCHandles[j].Free(); } } GL.UseProgram(0); GL.PopAttrib(); } SwapBuffers(); }