static void UpdateVertexBounds(VertexAttribute buffer, int index, VertexBounds bounds) { if (buffer == null && index <= 0) { return; } if (bounds == null) { bounds = new VertexBounds(); } Vector3 vertex; var offset = (index - 1) * buffer.ElementSize; vertex.X = buffer.ElementSize > 0 ? buffer[offset + 0] : 0; vertex.Y = buffer.ElementSize > 1 ? buffer[offset + 1] : 0; vertex.Z = buffer.ElementSize > 2 ? buffer[offset + 2] : 0; bounds.Add(ref vertex); }
static float[] GetVertices(Assimp.Mesh resource, out int stride, out VertexBounds bounds) { stride = 0; bounds = new VertexBounds(); if (resource.HasVertices) { stride += ElementSizeVector3D; } for (int i = 0; i < resource.TextureCoordinateChannelCount; i++) { stride += resource.UVComponentCount[i]; } stride += resource.VertexColorChannelCount * ElementSizeColor4D; if (resource.HasNormals) { stride += ElementSizeVector3D; } var vertices = new float[resource.VertexCount * stride]; for (int i = 0, v = 0; i < resource.VertexCount; i++) { if (resource.HasVertices) { var vertex = resource.Vertices[i]; vertices[v++] = vertex.X; vertices[v++] = vertex.Y; vertices[v++] = vertex.Z; bounds.Add(vertex.X, vertex.Y, vertex.Z); } for (int k = 0; k < resource.TextureCoordinateChannelCount; k++) { var texCoord = resource.TextureCoordinateChannels[k][i]; vertices[v++] = texCoord.X; vertices[v++] = texCoord.Y; if (resource.UVComponentCount[k] > 2) { vertices[v++] = texCoord.Z; } } for (int c = 0; c < resource.VertexColorChannelCount; c++) { var color = resource.VertexColorChannels[c][i]; vertices[v++] = color.R; vertices[v++] = color.G; vertices[v++] = color.B; vertices[v++] = color.A; } if (resource.HasNormals) { var normal = resource.Normals[i]; vertices[v++] = normal.X; vertices[v++] = normal.Y; vertices[v++] = normal.Z; } } stride *= BlittableValueType <float> .Stride; return(vertices); }
internal static void ReadObject(Mesh mesh, StreamReader stream) { string line; var faceLength = 0; uint vertexCount = 0; VertexBounds bounds = new VertexBounds(); VertexAttribute position = null; VertexAttribute texCoord = null; VertexAttribute normals = null; var vertices = new List <float>(); var indices = new List <uint>(); var indexMap = new Dictionary <Index, uint>(); while ((line = stream.ReadLine()) != null) { var values = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (values.Length == 0) { continue; } switch (values[0]) { case "v": ParseValues(ref position, values); break; case "vt": ParseValues(ref texCoord, values); break; case "vn": ParseValues(ref normals, values); break; case "f": var length = values.Length - 1; if (faceLength == 0) { faceLength = length; } else if (faceLength != length) { throw new InvalidOperationException("Invalid face specification. All faces must have the same number of vertices."); } for (int i = 1; i < values.Length; i++) { uint index; var face = Index.Create(values[i]); if (!indexMap.TryGetValue(face, out index)) { AddVertexAttribute(position, face.V, vertices); UpdateVertexBounds(position, face.V, bounds); if (texCoord != null) { AddVertexAttribute(texCoord, face.VT, vertices); } AddVertexAttribute(normals, face.VN, vertices); index = vertexCount++; indexMap.Add(face, index); } indices.Add(index); } break; default: continue; } } var attrib = 0; var offset = 0; var stride = GetElementSize(position) + GetElementSize(texCoord) + GetElementSize(normals); stride = stride * BlittableValueType <float> .Stride; mesh.EnsureElementArray(); mesh.VertexCount = indices.Count; mesh.Bounds = new Bounds(bounds.Center, bounds.Extents); mesh.DrawMode = faceLength == 4 ? PrimitiveType.Quads : PrimitiveType.Triangles; GL.BindVertexArray(mesh.VertexArray); GL.BindBuffer(BufferTarget.ArrayBuffer, mesh.VertexBuffer); GL.BindBuffer(BufferTarget.ElementArrayBuffer, mesh.ElementArray); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vertices.Count * BlittableValueType <float> .Stride), vertices.ToArray(), BufferUsageHint.StaticDraw); if (vertexCount <= byte.MaxValue) { mesh.ElementArrayType = DrawElementsType.UnsignedByte; GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(indices.Count * BlittableValueType <byte> .Stride), indices.Select(x => (byte)x).ToArray(), BufferUsageHint.StaticDraw); } else if (vertexCount <= ushort.MaxValue) { mesh.ElementArrayType = DrawElementsType.UnsignedShort; GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(indices.Count * BlittableValueType <ushort> .Stride), indices.Select(x => (ushort)x).ToArray(), BufferUsageHint.StaticDraw); } else { mesh.ElementArrayType = DrawElementsType.UnsignedInt; GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(indices.Count * BlittableValueType <uint> .Stride), indices.ToArray(), BufferUsageHint.StaticDraw); } if (position != null) { offset = PushAttribArray(position, attrib++, stride, offset); } if (texCoord != null) { offset = PushAttribArray(texCoord, attrib++, stride, offset); } if (normals != null) { offset = PushAttribArray(normals, attrib++, stride, offset); } GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindVertexArray(0); }