예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }