Esempio n. 1
0
        public void UpdateLine2Mesh()
        {
            if (adaptivePoints.Count == 0)
            {
                UpdateTubeMesh();
            }

            var vertexFormat = Line2Mesh.VertexBufferRange.VertexFormat;
            var position     = vertexFormat.FindAttribute(VertexUsage.Position, 0);
            var color        = vertexFormat.FindAttribute(VertexUsage.Color, 0);

            line2VertexWriter.BeginEdit();
            line2IndexWriter.BeginEdit();

            foreach (float t in adaptivePoints)
            {
                Vector3 pos = curve.PositionAt(t);

                float r, g, b;
                RenderStack.Math.Conversions.HSVtoRGB(360.0f * t, 1.0f, 1.0f, out r, out g, out b);

                line2IndexWriter.Line(line2VertexWriter.CurrentIndex, line2VertexWriter.CurrentIndex + 1);
                line2IndexWriter.CurrentIndex += 2;
                line2VertexWriter.Set(color, r, g, b, 1.0f);
                line2VertexWriter.Set(position, pos.X, pos.Y, pos.Z); ++line2VertexWriter.CurrentIndex;
                line2VertexWriter.Set(color, r, g, b, 1.0f);
                line2VertexWriter.Set(position, pos.X, 0.0f, pos.Z); ++line2VertexWriter.CurrentIndex;
            }
            line2VertexWriter.EndEdit();
            line2IndexWriter.EndEdit();
        }
Esempio n. 2
0
        public void UpdatePointMesh()
        {
            if (adaptivePoints.Count == 0)
            {
                UpdateTubeMesh();
            }

            var vertexFormat = PointMesh.VertexBufferRange.VertexFormat;
            var position     = vertexFormat.FindAttribute(VertexUsage.Position, 0);
            var color        = vertexFormat.FindAttribute(VertexUsage.Color, 0);

            pointVertexWriter.BeginEdit();
            pointIndexWriter.BeginEdit();

            foreach (float t in adaptivePoints)
            {
                Vector3 pos = curve.PositionAt(t);

                pointVertexWriter.Set(position, pos.X, pos.Y, pos.Z);
                pointVertexWriter.Set(color, 1.0f, 1.0f, 1.0f, 1.0f);
                pointIndexWriter.Point(pointVertexWriter.CurrentIndex);
                ++pointVertexWriter.CurrentIndex;
                ++pointIndexWriter.CurrentIndex;
            }
            pointVertexWriter.EndEdit();
            pointIndexWriter.EndEdit();
        }
Esempio n. 3
0
        public void Place(
            float x0,
            float y0,
            float z0,
            float width,
            float height
            )
        {
            //xOffset = x0;
            size = new Vector2(width, height);

            IBufferRange vertexBufferRange = mesh.VertexBufferRange;

            var position = vertexBufferRange.VertexFormat.FindAttribute(VertexUsage.Position, 0);
            var texCoord = vertexBufferRange.VertexFormat.FindAttribute(VertexUsage.TexCoord, 0);

            vertexWriter.BeginEdit();

            float[] b = new float[4];
            b[0] = 0.0f;
            b[1] = style.Border;
            b[2] = 1.0f - style.Border;
            b[3] = 1.0f;

            float[] x = new float[4];
            x[0] = x0;
            x[1] = x0 + style.Border * style.Texture.Size.Width;
            x[2] = x0 + width - style.Border * style.Texture.Size.Width;
            x[3] = x0 + width;

            float[] y = new float[4];
            y[0] = y0;
            y[1] = y0 + style.Border * style.Texture.Size.Height;
            y[2] = y0 + height - style.Border * style.Texture.Size.Height;
            y[3] = y0 + height;

            for (int yi = 0; yi < 4; ++yi)
            {
                for (int xi = 0; xi < 4; ++xi)
                {
                    vertexWriter.Set(position, x[xi], y[yi], z0);
                    vertexWriter.Set(texCoord, b[xi], b[3 - yi]);
                    ++vertexWriter.CurrentIndex;
                }
            }

            vertexWriter.EndEdit();

            //  \todo optimize
            //  \bug
            //vertexBufferRange.Buffer.UpdateAll();
        }
Esempio n. 4
0
 public void Line(Vector3 start, Vector3 end, Vector4 rgba)
 {
     indexWriter.Line(vertexWriter.CurrentIndex, vertexWriter.CurrentIndex + 1);
     indexWriter.CurrentIndex += 2;
     vertexWriter.Set(edgeColor, rgba.X, rgba.Y, rgba.Z, rgba.W);
     vertexWriter.Set(position, start.X, start.Y, start.Z);   ++vertexWriter.CurrentIndex;
     vertexWriter.Set(edgeColor, rgba.X, rgba.Y, rgba.Z, rgba.W);
     vertexWriter.Set(position, end.X, end.Y, end.Z);     ++vertexWriter.CurrentIndex;
 }
Esempio n. 5
0
        public void UpdateLineMesh()
        {
            var vertexFormat = LineMesh.VertexBufferRange.VertexFormat;
            var position     = vertexFormat.FindAttribute(VertexUsage.Position, 0);
            var color        = vertexFormat.FindAttribute(VertexUsage.Color, 0);

            lineVertexWriter.BeginEdit();
            for (int i = 0; i < curve.Count; ++i)
            {
                lineVertexWriter.Set(color, 1.0f, 1.0f, 1.0f, 1.0f);
                lineVertexWriter.Set(position, curve[i].Position); ++lineVertexWriter.CurrentIndex;
            }

            for (int i = 0; i < curve.Count; ++i)
            {
                lineVertexWriter.Set(color, 1.0f, 0.0f, 0.0f, 1.0f);
                lineVertexWriter.Set(position, curve[i].Position); ++lineVertexWriter.CurrentIndex;
                lineVertexWriter.Set(color, 0.0f, 0.0f, 1.0f, 1.0f);
                lineVertexWriter.Set(position, curve[i].Position.X, 0.0f, curve[i].Position.Z); ++lineVertexWriter.CurrentIndex;
            }
            lineVertexWriter.EndEdit();
        }
Esempio n. 6
0
        public void LowPrint(
            VertexBufferWriter vertexWriter,
            IndexBufferWriter indexWriter,
            float x,
            float y,
            float z,
            string text
            )
        {
            if (string.IsNullOrEmpty(text) == true)
            {
                return;
            }
            y += common.Base;
            FontChar fontChar = null;

            for (int i = 0; i < text.Length; ++i)
            {
                char c = text[i];

                fontChar = chars[c];
                if (fontChar == null)
                {
                    continue;
                }

                float a  = fontChar.XAdvance;
                float w  = fontChar.Width;
                float h  = fontChar.Height;
                float ox = fontChar.XOffset;
                float oy = fontChar.YOffset;

                indexWriter.Quad(
                    vertexWriter.CurrentIndex,
                    vertexWriter.CurrentIndex + 1,
                    vertexWriter.CurrentIndex + 2,
                    vertexWriter.CurrentIndex + 3
                    );
                indexWriter.CurrentIndex += 6;
                vertexWriter.Set(position, x + ox, y - oy, z);
                vertexWriter.Set(texCoord, fontChar.U, fontChar.V);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + ox, y - oy);

                vertexWriter.Set(position, x + w + ox, y - oy, z);
                vertexWriter.Set(texCoord, fontChar.U2, fontChar.V);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + w + ox, y - oy);

                vertexWriter.Set(position, x + w + ox, y - h - oy, z);
                vertexWriter.Set(texCoord, fontChar.U2, fontChar.V2);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + w + ox, y - h - oy);

                vertexWriter.Set(position, x + ox, y - h - oy, z);
                vertexWriter.Set(texCoord, fontChar.U, fontChar.V2);
                vertexWriter.Set(color, 1.0f, 1.0f, 1.0f);
                ++vertexWriter.CurrentIndex;
                Bounds.Extend(x + ox, y - h - oy);

                x += a;

                if (
                    (i + 1 < text.Length - 1) &&
                    (fontChar.Kernings != null)
                    )
                {
                    char next = text[i + 1];

                    FontKerning compare = new FontKerning((short)next);

                    int index = fontChar.Kernings.BinarySearch(compare);

                    if (index >= 0)
                    {
                        short amount = fontChar.Kernings[index].Amount;
                        x += (float)(amount);
                    }
                }
            }
        }
Esempio n. 7
0
 //   b-----c
 //   |\    |
 //   |  \  |
 //   |    \|
 //   a-----d
 public void Quad(Vector3 bottomLeft, Vector3 topRight, Vector4 rgba)
 {
     indexWriter.Quad(
         vertexWriter.CurrentIndex,
         vertexWriter.CurrentIndex + 1,
         vertexWriter.CurrentIndex + 2,
         vertexWriter.CurrentIndex + 3
         );
     indexWriter.CurrentIndex += 6;
     vertexWriter.Set(color, rgba.X, rgba.Y, rgba.Z, rgba.W);
     vertexWriter.Set(texcoord, 0.0f, 0.0f);
     vertexWriter.Set(position, bottomLeft.X, bottomLeft.Y, bottomLeft.Z);   ++vertexWriter.CurrentIndex;
     vertexWriter.Set(color, rgba.X, rgba.Y, rgba.Z, rgba.W);
     vertexWriter.Set(texcoord, 0.0f, 1.0f);
     vertexWriter.Set(position, bottomLeft.X, topRight.Y, bottomLeft.Z);   ++vertexWriter.CurrentIndex;
     vertexWriter.Set(color, rgba.X, rgba.Y, rgba.Z, rgba.W);
     vertexWriter.Set(texcoord, 1.0f, 1.0f);
     vertexWriter.Set(position, topRight.X, topRight.Y, bottomLeft.Z);   ++vertexWriter.CurrentIndex;
     vertexWriter.Set(color, rgba.X, rgba.Y, rgba.Z, rgba.W);
     vertexWriter.Set(texcoord, 1.0f, 0.0f);
     vertexWriter.Set(position, topRight.X, bottomLeft.Y, bottomLeft.Z);   ++vertexWriter.CurrentIndex;
 }
Esempio n. 8
0
        public void GenerateTubeVerticesForCusp(Vector3 T1, Vector3 T2, float t0, float t1)
        {
            float tm = t0 + (t1 - t0) * 0.5f;

            Vector3 cross = Vector3.Cross(T1, T2);

            //  Special case: cross product is 0, there is no unique axis
            //  for rotation. Pick 'any' perpendicular vector.
            if (cross.LengthSquared < 0.001f)
            {
                cross = Vector3.Cross(T1, T1.MinAxis);
            }
            Vector3 axis  = Vector3.Normalize(cross);
            float   dot   = Vector3.Dot(T1, T2);
            float   theta = (float)Math.Acos(dot);
            Vector3 pos   = curve.PositionAt(tm);

            float qtStep = 1.0f / (float)8.0;

            for (float qt = 0.0f; qt <= 1.0f; qt += qtStep)
            {
                Matrix4 R = Matrix4.CreateRotation(qt * theta, axis);
                Vector3 T = R * T1;
                Vector3 B = Vector3.Normalize(Vector3.Cross(T, LastN));
                LastN = Vector3.Normalize(Vector3.Cross(B, T));

                ++TubeStackCount;
                for (int slice = 0; slice < tubeSliceCount; ++slice)
                {
                    float relPhi = (float)slice / (float)tubeSliceCount;
                    float phi    = (float)Math.PI * 2.0f * relPhi;
                    float sinPhi = (float)Math.Sin(phi);
                    float cosPhi = (float)Math.Cos(phi);

                    Vector3 v = pos;
                    Vector3 n = LastN * sinPhi + B * cosPhi;
                    v += n * TubeRadius;

                    float r, g, b;
                    RenderStack.Math.Conversions.HSVtoRGB(360.0f * tm, 1.0f, 1.0f, out r, out g, out b);

                    tubeVertexWriter.Set(tubePosition, v.X, v.Y, v.Z);
                    tubeVertexWriter.Set(tubeNormal, n.X, n.Y, n.Z);
                    tubeVertexWriter.Set(tubeTangent, T.X, T.Y, T.Z);
                    //tubeVertexWriter.Set(tubeTangent, B.X, B.Y, B.Z);
                    tubeVertexWriter.Set(tubeColor, r, g, b, 1.0f);
                    tubeVertexWriter.Set(tubeT, tm);
                    tubeVertexWriter.Set(tubeId, 0);
                    ++tubeVertexWriter.CurrentIndex;
                }
            }
        }
Esempio n. 9
0
        public void CubeFace(Vector3 A, Vector3 B, Vector3 C, Vector3 D, byte u, byte v, UInt32 col, float l)
        {
            indexWriter.Quad(
                vertexWriter.CurrentIndex, vertexWriter.CurrentIndex + 1,
                vertexWriter.CurrentIndex + 2, vertexWriter.CurrentIndex + 3
                );
            indexWriter.CurrentIndex += 6;
#if false
            byte r = 80;
            byte g = 200;
            byte b = 80;
            byte a = 255;
#else
            float r = l * (float)((col & 0xff0000) >> 16) / 255.0f;
            float g = l * (float)((col & 0xff00) >> 8) / 255.0f;
            float b = l * (float)((col & 0xff)) / 255.0f;
            float a = 1.0f;
#endif
            float u0 = (float)u * 1.0f / 16.0f;
            float v0 = (float)v * 1.0f / 16.0f;
            float u1 = (float)(u + 1) * 1.0f / 16.0f;
            float v1 = (float)(v + 1) * 1.0f / 16.0f;

            //
            vertexWriter.Set(position, D.X, D.Y, D.Z);
            vertexWriter.Set(texcoord, u0, v1);
            vertexWriter.Set(color, r, g, b, a);
            ++vertexWriter.CurrentIndex;

            vertexWriter.Set(position, C.X, C.Y, C.Z);
            vertexWriter.Set(texcoord, u1, v1);
            vertexWriter.Set(color, r, g, b, a);
            ++vertexWriter.CurrentIndex;

            vertexWriter.Set(position, B.X, B.Y, B.Z);
            vertexWriter.Set(texcoord, u1, v0);
            vertexWriter.Set(color, r, g, b, a);
            ++vertexWriter.CurrentIndex;

            vertexWriter.Set(position, A.X, A.Y, A.Z);
            vertexWriter.Set(texcoord, u0, v0);
            vertexWriter.Set(color, r, g, b, a);
            ++vertexWriter.CurrentIndex;
        }
Esempio n. 10
0
        public void BuildMeshFromGeometry(
            BufferUsageHint bufferUsageHint,
            NormalStyle normalStyle,
            VertexFormat vertexFormat
            )
        {
            if (Geometry.PolygonAttributes.Contains <Vector3>("polygon_normals") == false)
            {
                Geometry.ComputePolygonNormals();
            }
            Geometry.ComputePointNormals("point_normals_smooth");

            if (Geometry.PointAttributes.Contains <Vector3>("polygon_centroids") == false)
            {
                Geometry.ComputePolygonCentroids();
            }

            var polygonIdsVector3 = Geometry.PolygonAttributes.FindOrCreate <Vector3>("polygon_ids_vec3");
            var polygonIdsUInt32  = (RenderStack.Graphics.Configuration.useIntegerPolygonIDs)
                                    ? Geometry.PolygonAttributes.FindOrCreate <UInt32>("polygon_ids_uint")
                                    : null;

            Dictionary <Corner, Vector3> cornerNormals      = null;
            Dictionary <Point, Vector3>  pointNormals       = null;
            Dictionary <Point, Vector3>  pointNormalsSmooth = Geometry.PointAttributes.Find <Vector3>("point_normals_smooth");

            bool normalsFound = false;

            if (Geometry.CornerAttributes.Contains <Vector3>("corner_normals"))
            {
                cornerNormals = Geometry.CornerAttributes.Find <Vector3>("corner_normals");
                normalsFound  = true;
            }
            if (Geometry.PointAttributes.Contains <Vector3>("point_normals"))
            {
                pointNormals = Geometry.PointAttributes.Find <Vector3>("point_normals");
                normalsFound = true;
            }
            if (normalsFound == false)
            {
                //Geometry.ComputeCornerNormals(0.0f * (float)System.Math.PI);
                Geometry.SmoothNormalize("corner_normals", "polygon_normals", (0.0f * (float)System.Math.PI));
                cornerNormals = Geometry.CornerAttributes.Find <Vector3>("corner_normals");
            }

            Dictionary <Corner, Vector2> cornerTexcoords = null;
            Dictionary <Point, Vector2>  pointTexcoords  = null;

            if (Geometry.CornerAttributes.Contains <Vector2>("corner_texcoords"))
            {
                cornerTexcoords = Geometry.CornerAttributes.Find <Vector2>("corner_texcoords");
            }
            if (Geometry.PointAttributes.Contains <Vector2>("point_texcoords"))
            {
                pointTexcoords = Geometry.PointAttributes.Find <Vector2>("point_texcoords");
            }

            //Dictionary<Corner, Vector4> cornerColors = null;
            var cornerColors = default(Dictionary <Corner, Vector4>);
            Dictionary <Point, Vector4> pointColors = null;

            if (Geometry.CornerAttributes.Contains <Vector4>("corner_colors"))
            {
                cornerColors = Geometry.CornerAttributes.Find <Vector4>("corner_colors");
            }
            if (Geometry.PointAttributes.Contains <Vector4>("point_colors"))
            {
                pointColors = Geometry.PointAttributes.Find <Vector4>("point_colors");
            }

            var polygonNormals   = Geometry.PolygonAttributes.Find <Vector3>("polygon_normals");
            var polygonCentroids = Geometry.PolygonAttributes.Find <Vector3>("polygon_centroids");
            var pointLocations   = Geometry.PointAttributes.Find <Vector3>("point_locations");
            var cornerIndices    = Geometry.CornerAttributes.FindOrCreate <uint>("corner_indices");

            var attributePosition     = vertexFormat.FindAttribute(VertexUsage.Position, 0);
            var attributeNormal       = vertexFormat.FindAttribute(VertexUsage.Normal, 0);       /*  content normals     */
            var attributeNormalFlat   = vertexFormat.FindAttribute(VertexUsage.Normal, 1);       /*  flat normals        */
            var attributeNormalSmooth = vertexFormat.FindAttribute(VertexUsage.Normal, 2);       /*  smooth normals      */
            var attributeColor        = vertexFormat.FindAttribute(VertexUsage.Color, 0);
            var attributeTexcoord     = vertexFormat.FindAttribute(VertexUsage.TexCoord, 0);
            var attributeIdVec3       = vertexFormat.FindAttribute(VertexUsage.Id, 0);
            var attributeIdUInt       = vertexFormat.FindAttribute(VertexUsage.Id, 0);

            // \note work in progress
            GetMesh = new Mesh();
            IBuffer vertexBuffer = BufferPool.Instance.GetVertexBuffer(vertexFormat, bufferUsageHint);

            GetMesh.VertexBufferRange = vertexBuffer.CreateVertexBufferRange();
            IBuffer indexBuffer = BufferPool.Instance.GetIndexBuffer(DrawElementsType.UnsignedInt, bufferUsageHint);

            #region prepare index buffers
            var polygonFillIndices = GetMesh.FindOrCreateIndexBufferRange(
                MeshMode.PolygonFill,
                indexBuffer,
                BeginMode.Triangles
                );
            var edgeLineIndices = GetMesh.FindOrCreateIndexBufferRange(
                MeshMode.EdgeLines,
                indexBuffer,
                BeginMode.Lines
                );

            /*BufferRange silhouetteLineIndices = GetMesh.FindOrCreateIndexBuffer(
             *  MeshMode.EdgeLines,
             *  indexBuffer,
             *  BeginMode.Lines
             * );*/
            var cornerPointIndices = GetMesh.FindOrCreateIndexBufferRange(
                MeshMode.CornerPoints,
                indexBuffer,
                BeginMode.Points
                );
            var polygonCentroidIndices = GetMesh.FindOrCreateIndexBufferRange(
                MeshMode.PolygonCentroids,
                indexBuffer,
                BeginMode.Points
                );
            #endregion prepare index buffers

            var vertexWriter               = new VertexBufferWriter(GetMesh.VertexBufferRange);
            var polygonFillIndexWriter     = new IndexBufferWriter(polygonFillIndices);
            var edgeLineIndexWriter        = new IndexBufferWriter(edgeLineIndices);
            var cornerPointIndexWriter     = new IndexBufferWriter(cornerPointIndices);
            var polygonCentroidIndexWriter = new IndexBufferWriter(polygonCentroidIndices);

            vertexWriter.BeginEdit();
            polygonFillIndexWriter.BeginEdit();
            edgeLineIndexWriter.BeginEdit();
            cornerPointIndexWriter.BeginEdit();
            polygonCentroidIndexWriter.BeginEdit();

            UInt32 polygonIndex = 0;

            #region polygons
            cornerIndices.Clear();
            foreach (Polygon polygon in Geometry.Polygons)
            {
                if (RenderStack.Graphics.Configuration.useIntegerPolygonIDs)
                {
                    polygonIdsUInt32[polygon] = polygonIndex;
                }
                polygonIdsVector3[polygon] = Vector3.Vector3FromUint(polygonIndex);

                Vector3 polygonNormal = Vector3.UnitY;

                if (polygon.Corners.Count > 2 && polygonNormals != null && polygonNormals.ContainsKey(polygon))
                {
                    polygonNormal = polygonNormals[polygon];
                }

                uint firstIndex    = vertexWriter.CurrentIndex;
                uint previousIndex = firstIndex;

                #region corners
                foreach (Corner corner in polygon.Corners)
                {
                    //  Position
                    vertexWriter.Position(pointLocations[corner.Point]);

                    //  Normal
                    Vector3 normal = Vector3.UnitY;
                    if (
                        (cornerNormals != null) &&
                        (polygon.Corners.Count > 2) &&
                        (cornerNormals.ContainsKey(corner) == true)
                        )
                    {
                        normal = cornerNormals[corner];
                    }
                    else if (pointNormals != null && pointNormals.ContainsKey(corner.Point))
                    {
                        normal = pointNormals[corner.Point];
                    }
                    else if (pointNormalsSmooth != null && pointNormalsSmooth.ContainsKey(corner.Point))
                    {
                        normal = pointNormalsSmooth[corner.Point];
                    }
                    Vector3 pointNormal = Vector3.UnitY;
                    if (pointNormals != null && pointNormals.ContainsKey(corner.Point))
                    {
                        pointNormal = pointNormals[corner.Point];
                    }
                    else if (pointNormalsSmooth != null && pointNormalsSmooth.ContainsKey(corner.Point))
                    {
                        pointNormal = pointNormalsSmooth[corner.Point];
                    }

                    switch (normalStyle)
                    {
                    case NormalStyle.CornerNormals:     vertexWriter.Normal(normal); break;

                    case NormalStyle.PointNormals:      vertexWriter.Normal(pointNormal); break;

                    case NormalStyle.PolygonNormals:    vertexWriter.Normal(polygonNormal); break;
                    }

                    if (attributeNormalFlat != null)
                    {
                        vertexWriter.Set(attributeNormalFlat, polygonNormal);
                    }
                    if (attributeNormalSmooth != null)
                    {
                        vertexWriter.Set(attributeNormalSmooth, pointNormalsSmooth[corner.Point]);
                    }

                    //  Texcoord
                    if (attributeTexcoord != null)
                    {
                        if (
                            (cornerTexcoords != null) &&
                            (cornerTexcoords.ContainsKey(corner) == true)
                            )
                        {
                            vertexWriter.Set(attributeTexcoord, cornerTexcoords[corner]);
                        }
                        else if (
                            (pointTexcoords != null) &&
                            (pointTexcoords.ContainsKey(corner.Point) == true)
                            )
                        {
                            vertexWriter.Set(attributeTexcoord, pointTexcoords[corner.Point]);
                        }
                    }

                    //  Vertex Color
                    if (attributeColor != null)
                    {
                        if (
                            (cornerColors != null) &&
                            (cornerColors.ContainsKey(corner) == true)
                            )
                        {
                            vertexWriter.Set(attributeColor, cornerColors[corner]);
                        }
                        else if (
                            (pointColors != null) &&
                            (pointColors.ContainsKey(corner.Point) == true)
                            )
                        {
                            vertexWriter.Set(attributeColor, pointColors[corner.Point]);
                        }
                        else
                        {
                            vertexWriter.Set(attributeColor, Vector4.One);
                        }
                    }

                    //  PolygonId
                    if (RenderStack.Graphics.Configuration.useIntegerPolygonIDs && (attributeIdUInt != null))
                    {
                        vertexWriter.Set(attributeIdUInt, polygonIndex);
                    }
                    if (attributeIdVec3 != null)
                    {
                        Vector3 v = Vector3.Vector3FromUint(polygonIndex);
                        vertexWriter.Set(attributeIdVec3, v);
                    }

                    cornerPointIndexWriter.Point(vertexWriter.CurrentIndex);
                    cornerPointIndexWriter.CurrentIndex++;

                    cornerIndices[corner] = vertexWriter.CurrentIndex;

                    if (previousIndex != firstIndex)
                    {
                        polygonFillIndexWriter.Triangle(firstIndex, vertexWriter.CurrentIndex, previousIndex);
                        polygonFillIndexWriter.CurrentIndex += 3;
                    }

                    previousIndex = vertexWriter.CurrentIndex;

                    ++vertexWriter.CurrentIndex;
                }
                #endregion corners

                ++polygonIndex;
            }
            #endregion polygons

            #region edges
            Geometry.BuildEdges();

            foreach (Edge edge in Geometry.Edges.Keys)
            {
                if (
                    cornerIndices.ContainsKey(edge.A.Corners[0]) &&
                    cornerIndices.ContainsKey(edge.B.Corners[0])
                    )
                {
                    uint i0 = cornerIndices[edge.A.Corners[0]];
                    uint i1 = cornerIndices[edge.B.Corners[0]];
                    edgeLineIndexWriter.Line(i0, i1);
                    edgeLineIndexWriter.CurrentIndex += 2;
                }
            }
            #endregion edges

            #region polygon centroids
            foreach (Polygon polygon in Geometry.Polygons)
            {
                Vector3 normal;

                if (polygon.Corners.Count > 2)
                {
                    normal = polygonNormals[polygon];
                }
                else
                {
                    normal = new Vector3(0.0f, 1.0f, 0.0f);
                }

                vertexWriter.Position(polygonCentroids[polygon]);
                if (attributeNormal != null)
                {
                    vertexWriter.Set(attributeNormal, normal);
                }
                if (attributeNormalFlat != null)
                {
                    vertexWriter.Set(attributeNormalFlat, normal);
                }
                polygonCentroidIndexWriter.Point(vertexWriter.CurrentIndex);
                ++vertexWriter.CurrentIndex;
                ++polygonCentroidIndexWriter.CurrentIndex;
            }
            #endregion polygon centroids

            vertexWriter.EndEdit();
            polygonFillIndexWriter.EndEdit();
            edgeLineIndexWriter.EndEdit();
            cornerPointIndexWriter.EndEdit();
            polygonCentroidIndexWriter.EndEdit();
        }