public Mesh(GeometryData data) { VertexCount = data.VertexCount; VertexArrayObject = GL.GenVertexArray(); if (VertexArrayObject == 0) { throw new Exception(GL.GetError().ToString()); } GL.BindVertexArray(VertexArrayObject); Buffer = GL.GenBuffer(); if (Buffer == 0) { throw new Exception(GL.GetError().ToString()); } GL.BindBuffer(BufferTarget.ArrayBuffer, Buffer); GL.BufferData(BufferTarget.ArrayBuffer, data.Data.Length, data.Data, BufferUsageHint.StaticDraw); ElementBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, data.Indices.Length * 4, data.Indices, BufferUsageHint.StaticDraw); MeshHelper.ApplyVertexAttribs(data.Attribs, InstanceBuffer); ElementBufferSize = data.Indices.Length; GL.BindVertexArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); }
public static GeometryData FromCollada(float[] vertices, int[] indices, int indicesPerFace, float[] normals, int[] normalIndices, float[] uv, int[] uvIndices, List <Dictionary <string, float> > vertexWeights, List <Bone> bones, float[] bindShapeMatrix = null) { var data = new PositionNormalUV0SkinVertex[indices.Length]; var meshIndices = new int[indices.Length]; for (var i = 0; i < indices.Length; i++) { var vertex = (bindShapeMatrix != null) ? new float[] { vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2] }.VectorTransform(bindShapeMatrix) : new float[] { vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2] }; data[i].PosX = vertex[0]; data[i].PosY = vertex[1]; data[i].PosZ = vertex[2]; data[i].NormalX = normals[normalIndices[i] * 3]; data[i].NormalY = normals[normalIndices[i] * 3 + 1]; data[i].NormalZ = normals[normalIndices[i] * 3 + 2]; data[i].UvX = uv[uvIndices[i] * 2]; data[i].UvY = 1f - uv[uvIndices[i] * 2 + 1]; // skinning var weight = 0; foreach (var b in vertexWeights[indices[i]].OrderByDescending(a => a.Value).Select(a => a.Key)) { if (vertexWeights[indices[i]][b] > 0) { if (weight == 0) { data[i].BoneId1 = bones.TakeWhile(a => a.Id != b).Count(); data[i].Weight1 = vertexWeights[indices[i]][b]; } else if (weight == 1) { data[i].BoneId2 = bones.TakeWhile(a => a.Id != b).Count(); data[i].Weight2 = vertexWeights[indices[i]][b]; } else if (weight == 2) { data[i].BoneId3 = bones.TakeWhile(a => a.Id != b).Count(); data[i].Weight3 = vertexWeights[indices[i]][b]; } else if (weight == 3) { data[i].BoneId4 = bones.TakeWhile(a => a.Id != b).Count(); data[i].Weight4 = vertexWeights[indices[i]][b]; } weight += 1; } } // normalize weights var totalWeights = data[i].Weight1 + data[i].Weight2 + data[i].Weight3 + data[i].Weight4; if (totalWeights != 1f) { var normalizedWeight = 1.0f / totalWeights; data[i].Weight1 *= normalizedWeight; data[i].Weight2 *= normalizedWeight; data[i].Weight3 *= normalizedWeight; data[i].Weight4 *= normalizedWeight; } meshIndices[i] = i; } // check if we need to triangulate the mesh if (indicesPerFace == 4) { meshIndices = MeshHelper.QuadIndicesToTriangles(meshIndices); } var result = new GeometryData() { VertexCount = data.Length, Indices = meshIndices }; using (var stream = new System.IO.MemoryStream()) using (var writer = new System.IO.BinaryWriter(stream)) { for (int i = 0; i < data.Length; i++) { writer.Write(data[i].PosX); writer.Write(data[i].PosY); writer.Write(data[i].PosZ); writer.Write(data[i].NormalX); writer.Write(data[i].NormalY); writer.Write(data[i].NormalZ); writer.Write(data[i].UvX); writer.Write(data[i].UvY); writer.Write(data[i].BoneId1); writer.Write(data[i].BoneId2); writer.Write(data[i].BoneId3); writer.Write(data[i].BoneId4); writer.Write(data[i].Weight1); writer.Write(data[i].Weight2); writer.Write(data[i].Weight3); writer.Write(data[i].Weight4); } result.Data = stream.ToArray(); } // add vertex attribs result.Attribs = new VertexAttrib[] { new VertexAttrib() { Size = 3, Type = (int)OpenTK.Graphics.OpenGL4.VertexAttribPointerType.Float, Stride = 16 * sizeof(float), Offset = 0 }, new VertexAttrib() { Size = 3, Type = (int)OpenTK.Graphics.OpenGL4.VertexAttribPointerType.Float, Stride = 16 * sizeof(float), Offset = 3 * sizeof(float) }, new VertexAttrib() { Size = 2, Type = (int)OpenTK.Graphics.OpenGL4.VertexAttribPointerType.Float, Stride = 16 * sizeof(float), Offset = 6 * sizeof(float) }, new VertexAttrib() { Size = 4, Type = (int)OpenTK.Graphics.OpenGL4.VertexAttribIntegerType.Int, Stride = 16 * sizeof(float), Offset = 8 * sizeof(float) }, new VertexAttrib() { Size = 4, Type = (int)OpenTK.Graphics.OpenGL4.VertexAttribPointerType.Float, Stride = 16 * sizeof(float), Offset = 12 * sizeof(float) } }; return(result); }
public static Mesh FromFBX(float[] vertices, int[] indices, int indicesPerFace, float[] normals, float[] uv, int[] uvIndices) { var mesh = new Mesh(); var data = new MeshHelper.PositionNormalUV0Vertex[indices.Length]; var meshIndices = new int[indices.Length]; // the normals are referred to the indices, not the vertices if //MappingInformationType //- ByPolygonVertex //ReferenceInformationType //- Direct // UV //MappingInformationType //- ByPolygonVertex //ReferenceInformationType //- IndexToDirect for (var i = 0; i < indices.Length; i++) { data[i].PosX = vertices[indices[i] * 3]; data[i].PosY = vertices[indices[i] * 3 + 1]; data[i].PosZ = vertices[indices[i] * 3 + 2]; data[i].NormalX = normals[i * 3]; data[i].NormalY = normals[i * 3 + 1]; data[i].NormalZ = normals[i * 3 + 2]; data[i].UvX = uv[uvIndices[i] * 2]; data[i].UvY = 1f - uv[uvIndices[i] * 2 + 1]; meshIndices[i] = i; } // check if we need to triangulate the mesh if (indicesPerFace == 4) { meshIndices = MeshHelper.QuadIndicesToTriangles(meshIndices); } mesh.VertexCount = data.Length; mesh.VertexArrayObject = GL.GenVertexArray(); GL.BindVertexArray(mesh.VertexArrayObject); mesh.Buffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, mesh.Buffer); GL.BufferData(BufferTarget.ArrayBuffer, 32 * data.Length, data, BufferUsageHint.StaticDraw); mesh.ElementBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, mesh.ElementBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, meshIndices.Length * 4, meshIndices, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 0); GL.EnableVertexAttribArray(0); GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), 3 * sizeof(float)); GL.EnableVertexAttribArray(1); GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), 6 * sizeof(float)); GL.EnableVertexAttribArray(2); mesh.ElementBufferSize = meshIndices.Length; GL.BindVertexArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); return(mesh); }
public static SkinnedMesh FromFBX(float[] vertices, int[] indices, int indicesPerFace, float[] normals, float[] uv, int[] uvIndices, List <CoreFBX.FBX.Deformer> deformers, List <Bone> bones, float[] bindShapeMatrix = null) { var mesh = new SkinnedMesh(); var data = new MeshHelper.PositionNormalUV0SkinVertex[indices.Length]; var meshIndices = new int[indices.Length]; // the normals are referred to the indices, not the vertices if //MappingInformationType //- ByPolygonVertex //ReferenceInformationType //- Direct // UV //MappingInformationType //- ByPolygonVertex //ReferenceInformationType //- IndexToDirect for (var i = 0; i < indices.Length; i++) { var vertex = (bindShapeMatrix != null) ? new float[] { vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2] }.VectorTransform(bindShapeMatrix) : new float[] { vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2] }; data[i].PosX = vertex[0]; data[i].PosY = vertex[1]; data[i].PosZ = vertex[2]; data[i].NormalX = normals[i * 3]; data[i].NormalY = normals[i * 3 + 1]; data[i].NormalZ = normals[i * 3 + 2]; data[i].UvX = uv[uvIndices[i] * 2]; data[i].UvY = 1f - uv[uvIndices[i] * 2 + 1]; meshIndices[i] = i; } mesh.Bones = bones; // add skin information for (int b = 0; b < deformers.Count; b++) { var bone = bones.Where(a => a.Id == deformers[b].BoneId).FirstOrDefault(); var boneId = bones.IndexOf(bone); bone.InverseBindMatrix = deformers[b].TransformLink.MatrixInverse().TransposeMatrix(); //deformers[b].Transform.MatrixProduct(deformers[b].TransformLink.MatrixInverse());// deformers[b].TransformLink.TransposeMatrix().MatrixInverse().MatrixProduct(deformers[b].TransformLink.TransposeMatrix()); for (int indexId = 0; indexId < deformers[b].Indexes.Length; indexId++) { // the weight could be needed in more than one vertex for (var i = 0; i < indices.Length; i++) { if (indices[i] == deformers[b].Indexes[indexId]) { if (data[i].Weight1 == 0) { data[i].BoneId1 = boneId; data[i].Weight1 = deformers[b].Weights[indexId]; } else if (data[i].Weight2 == 0) { data[i].BoneId2 = boneId; data[i].Weight2 = deformers[b].Weights[indexId]; } else if (data[i].Weight3 == 0) { data[i].BoneId3 = boneId; data[i].Weight3 = deformers[b].Weights[indexId]; } else if (data[i].Weight4 == 0) { data[i].BoneId4 = boneId; data[i].Weight4 = deformers[b].Weights[indexId]; } } } } } // normalize weights for (int i = 0; i < data.Length; i++) { var totalWeights = data[i].Weight1 + data[i].Weight2 + data[i].Weight3 + data[i].Weight4; if (totalWeights != 1f) { var normalizedWeight = 1.0f / totalWeights; data[i].Weight1 *= normalizedWeight; data[i].Weight2 *= normalizedWeight; data[i].Weight3 *= normalizedWeight; data[i].Weight4 *= normalizedWeight; } } // check if we need to triangulate the mesh if (indicesPerFace == 4) { meshIndices = MeshHelper.QuadIndicesToTriangles(meshIndices); } mesh.VertexCount = data.Length; mesh.VertexArrayObject = GL.GenVertexArray(); GL.BindVertexArray(mesh.VertexArrayObject); mesh.Buffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ArrayBuffer, mesh.Buffer); GL.BufferData(BufferTarget.ArrayBuffer, 16 * 4 * data.Length, data, BufferUsageHint.StaticDraw); mesh.ElementBuffer = GL.GenBuffer(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, mesh.ElementBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, meshIndices.Length * 4, meshIndices, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 16 * sizeof(float), 0); GL.EnableVertexAttribArray(0); GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 16 * sizeof(float), 3 * sizeof(float)); GL.EnableVertexAttribArray(1); GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 16 * sizeof(float), 6 * sizeof(float)); GL.EnableVertexAttribArray(2); GL.VertexAttribIPointer(3, 4, VertexAttribIntegerType.Int, 16 * sizeof(float), IntPtr.Add(IntPtr.Zero, 8 * sizeof(float))); GL.EnableVertexAttribArray(3); GL.VertexAttribPointer(4, 4, VertexAttribPointerType.Float, false, 16 * sizeof(float), 12 * sizeof(float)); GL.EnableVertexAttribArray(4); mesh.ElementBufferSize = meshIndices.Length; GL.BindVertexArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); return(mesh); }
public XYPlaneMesh(float[] bindShapeMatrix = null) : base(MeshHelper.CreateXYPlane(bindShapeMatrix)) { }