/// <summary>Create an OpenGL/OpenTK VAO for a mesh</summary> /// <param name="isDynamic"></param> public static void CreateVAO(ref Mesh mesh, bool isDynamic) { var hint = isDynamic ? BufferUsageHint.DynamicDraw : BufferUsageHint.StaticDraw; var vertexData = new List <LibRenderVertex>(); var indexData = new List <ushort>(); var normalsVertexData = new List <LibRenderVertex>(); var normalsIndexData = new List <ushort>(); for (int i = 0; i < mesh.Faces.Length; i++) { mesh.Faces[i].IboStartIndex = indexData.Count; mesh.Faces[i].NormalsIboStartIndex = normalsIndexData.Count; foreach (var vertex in mesh.Faces[i].Vertices) { var data = new LibRenderVertex { Position = mesh.Vertices[vertex.Index].Coordinates, Normal = vertex.Normal, UV = new Vector2f(mesh.Vertices[vertex.Index].TextureCoordinates) }; var coloredVertex = mesh.Vertices[vertex.Index] as ColoredVertex; if (coloredVertex != null) { data.Color = coloredVertex.Color; } else { data.Color = Color128.White; } vertexData.Add(data); var normalsData = new LibRenderVertex[2]; normalsData[0].Position = data.Position; normalsData[1].Position = data.Position + data.Normal; for (int j = 0; j < normalsData.Length; j++) { normalsData[j].Color = Color128.White; } normalsVertexData.AddRange(normalsData); } indexData.AddRange(Enumerable.Range(mesh.Faces[i].IboStartIndex, mesh.Faces[i].Vertices.Length).Select(x => (ushort)x)); normalsIndexData.AddRange(Enumerable.Range(mesh.Faces[i].NormalsIboStartIndex, mesh.Faces[i].Vertices.Length * 2).Select(x => (ushort)x)); } VertexArrayObject VAO = (VertexArrayObject)mesh.VAO; VAO?.UnBind(); VAO?.Dispose(); VAO = new VertexArrayObject(); VAO.Bind(); VAO.SetVBO(new VertexBufferObject(vertexData.ToArray(), hint)); VAO.SetIBO(new IndexBufferObject(indexData.ToArray(), hint)); VAO.UnBind(); mesh.VAO = VAO; VertexArrayObject NormalsVAO = (VertexArrayObject)mesh.NormalsVAO; NormalsVAO?.UnBind(); NormalsVAO?.Dispose(); NormalsVAO = new VertexArrayObject(); NormalsVAO.Bind(); NormalsVAO.SetVBO(new VertexBufferObject(normalsVertexData.ToArray(), hint)); NormalsVAO.SetIBO(new IndexBufferObject(normalsIndexData.ToArray(), hint)); NormalsVAO.UnBind(); mesh.NormalsVAO = NormalsVAO; }
/// <summary>Create an OpenGL/OpenTK VAO for a mesh</summary> /// <param name="isDynamic"></param> public static void CreateVAO(ref Mesh mesh, bool isDynamic, VertexLayout vertexLayout, BaseRenderer renderer) { try { var hint = isDynamic ? BufferUsageHint.DynamicDraw : BufferUsageHint.StaticDraw; var vertexData = new List <LibRenderVertex>(); var indexData = new List <uint>(); var normalsVertexData = new List <LibRenderVertex>(); var normalsIndexData = new List <uint>(); for (int i = 0; i < mesh.Faces.Length; i++) { mesh.Faces[i].IboStartIndex = indexData.Count; mesh.Faces[i].NormalsIboStartIndex = normalsIndexData.Count; foreach (var vertex in mesh.Faces[i].Vertices) { var data = new LibRenderVertex { Position = mesh.Vertices[vertex.Index].Coordinates, Normal = vertex.Normal, UV = new Vector2f(mesh.Vertices[vertex.Index].TextureCoordinates) }; var coloredVertex = mesh.Vertices[vertex.Index] as ColoredVertex; if (coloredVertex != null) { data.Color = coloredVertex.Color; } else { data.Color = Color128.Transparent; } vertexData.Add(data); var normalsData = new LibRenderVertex[2]; normalsData[0].Position = data.Position; normalsData[1].Position = data.Position + data.Normal; for (int j = 0; j < normalsData.Length; j++) { normalsData[j].Color = Color128.White; } normalsVertexData.AddRange(normalsData); } indexData.AddRange(Enumerable.Range(mesh.Faces[i].IboStartIndex, mesh.Faces[i].Vertices.Length).Select(x => (uint)x)); normalsIndexData.AddRange(Enumerable.Range(mesh.Faces[i].NormalsIboStartIndex, mesh.Faces[i].Vertices.Length * 2).Select(x => (uint)x)); } VertexArrayObject VAO = (VertexArrayObject)mesh.VAO; VAO?.UnBind(); VAO?.Dispose(); VAO = new VertexArrayObject(); VAO.Bind(); VAO.SetVBO(new VertexBufferObject(vertexData.ToArray(), hint)); if (indexData.Count > 65530) { //Marginal headroom, although it probably doesn't matter VAO.SetIBO(new IndexBufferObjectI(indexData.ToArray(), hint)); } else { VAO.SetIBO(new IndexBufferObjectU(indexData.Select(x => (ushort)x).ToArray(), hint)); } VAO.SetAttributes(vertexLayout); VAO.UnBind(); mesh.VAO = VAO; VertexArrayObject NormalsVAO = (VertexArrayObject)mesh.NormalsVAO; NormalsVAO?.UnBind(); NormalsVAO?.Dispose(); NormalsVAO = new VertexArrayObject(); NormalsVAO.Bind(); NormalsVAO.SetVBO(new VertexBufferObject(normalsVertexData.ToArray(), hint)); if (normalsIndexData.Count > 65530) { //Marginal headroom, although it probably doesn't matter NormalsVAO.SetIBO(new IndexBufferObjectI(normalsIndexData.ToArray(), hint)); } else { NormalsVAO.SetIBO(new IndexBufferObjectU(normalsIndexData.Select(x => (ushort)x).ToArray(), hint)); } NormalsVAO.SetAttributes(vertexLayout); NormalsVAO.UnBind(); mesh.NormalsVAO = NormalsVAO; } catch (Exception e) { renderer.ForceLegacyOpenGL = true; renderer.currentHost.AddMessage(MessageType.Error, false, "Creating VAO failed with the following error: " + e); } }