private void BuildLine(IGeometry <T> geometry, ITessellationHints hints, Vector3[] colors, IPath path)
        {
            var vertexDataList = new List <T>();
            var indexDataList  = new List <uint>();

            // Draw a line
            for (var i = 0; i < path.PathLocations.Length; ++i)
            {
                var vtx = new T();
                vtx.SetPosition(path.PathLocations[i]);
                vtx.SetNormal(Vector3.UnitX);
                vtx.SetTexCoord(Vector2.Zero);
                vtx.SetColor3(colors[0]);
                vertexDataList.Add(vtx);

                indexDataList.Add((uint)i);
            }

            geometry.VertexData = vertexDataList.ToArray();
            geometry.IndexData  = indexDataList.ToArray();

            geometry.VertexLayout = VertexLayoutHelpers.GetLayoutDescription(typeof(T));

            var pSet = DrawElements <T> .Create(
                geometry,
                PrimitiveTopology.LineStrip,
                (uint)geometry.IndexData.Length,
                1,
                0,
                0,
                0);

            geometry.PrimitiveSets.Add(pSet);
        }
        private void BuildCylinder(IGeometry <T> geometry, ITessellationHints hints, Vector3[] colors, IPath path)
        {
            var tangents = Util.Math.ComputePathTangents(path.PathLocations);

            var nSegments = (int)System.Math.Floor(10f * hints.DetailRatio);

            if (nSegments < 4)
            {
                nSegments = 4;
            }

            var shape = new Vector2[nSegments];

            for (var i = 0; i < nSegments; ++i)
            {
                var theta = i * 2 * System.Math.PI / nSegments;
                var r     = hints.Radius;

                shape[i] = new Vector2((float)(r * System.Math.Sin(theta)), (float)(r * System.Math.Cos(theta)));
            }

            var extrusion = Math.ExtrudeShape(shape, path.PathLocations);

            // Build from quad strips
            for (var j = 0; j < nSegments - 1; ++j)
            {
                Begin();

                BuildFromIndicies(j, j + 1, extrusion, path);

                End();
            }

            // Join the last bit...
            BuildFromIndicies(nSegments - 1, 0, extrusion, path);

            BuildVertexAndIndexArrays(out var vertexArray, out var indexArray, colors);

            geometry.VertexData = vertexArray;
            geometry.IndexData  = indexArray;

            geometry.VertexLayout = VertexLayoutHelpers.GetLayoutDescription(typeof(T));

            var pSet = DrawElements <T> .Create(
                geometry,
                PrimitiveTopology.TriangleList,
                (uint)geometry.IndexData.Length,
                1,
                0,
                0,
                0);

            geometry.PrimitiveSets.Add(pSet);
        }
Пример #3
0
        internal void Build(IGeometry <T> geometry, ITessellationHints hints, Vector3[] colors, ISphere sphere)
        {
            if (hints.NormalsType == NormalsType.PerFace)
            {
                throw new ArgumentException("Per-Face Normals are not supported for spheres");
            }

            if (hints.ColorsType == ColorsType.ColorPerFace)
            {
                throw new ArgumentException("Per-Face Colors are not supported for spheres");
            }

            if (hints.ColorsType == ColorsType.ColorPerVertex)
            {
                throw new ArgumentException("Per-Vertex Colors are not supported for spheres");
            }

            if (colors.Length < 1)
            {
                throw new ArgumentException("Must provide at least one color for spheres");
            }

            uint numSegments = 40;
            uint numRows     = 20;

            var ratio = hints.DetailRatio;

            if (ratio > 0.0f && ratio != 1.0f)
            {
                numRows = (uint)(numRows * ratio);
                if (numRows < MIN_NUM_ROWS)
                {
                    numRows = MIN_NUM_ROWS;
                }
                numSegments = (uint)(numSegments * ratio);
                if (numSegments < MIN_NUM_SEGMENTS)
                {
                    numSegments = MIN_NUM_SEGMENTS;
                }
            }

            var lDelta = (float)System.Math.PI / (float)numRows;
            var vDelta = 1.0f / (float)numRows;

            var angleDelta        = (float)System.Math.PI * 2.0f / numSegments;
            var texCoordHorzDelta = 1.0f / numSegments;

            if (hints.CreateBackFace)
            {
                var lBase      = -(float)System.Math.PI * 0.5f;
                var rBase      = 0.0f;
                var zBase      = -sphere.Radius;
                var vBase      = 0.0f;
                var nzBase     = -1.0f;
                var nRatioBase = 0.0f;

                for (uint rowi = 0; rowi < numRows; ++rowi)
                {
                    var lTop      = (float)(lBase + lDelta);
                    var rTop      = (float)System.Math.Cos(lTop) * sphere.Radius;
                    var zTop      = (float)System.Math.Sin(lTop) * sphere.Radius;
                    var vTop      = vBase + vDelta;
                    var nzTop     = (float)System.Math.Sin(lTop);
                    var nRatioTop = (float)System.Math.Cos(lTop);

                    Begin();

                    var angle    = 0.0f;
                    var texCoord = 0.0f;

                    for (uint topi = 0; topi < numSegments;
                         ++topi, angle += angleDelta, texCoord += texCoordHorzDelta)
                    {
                        var c = (float)System.Math.Cos(angle);
                        var s = (float)System.Math.Sin(angle);

                        Normal3f(-c * nRatioBase, -s * nRatioBase, -nzBase);
                        TexCoord2f(texCoord, vBase);
                        Vertex3f(c * rBase, s * rBase, zBase);

                        Normal3f(-c * nRatioTop, -s * nRatioTop, -nzTop);

                        TexCoord2f(texCoord, vTop);
                        Vertex3f(c * rTop, s * rTop, zTop);
                    }

                    // do last point by hand to ensure no round off errors.
                    Normal3f(-nRatioBase, 0.0f, -nzBase);
                    TexCoord2f(1.0f, vBase);
                    Vertex3f(rBase, 0.0f, zBase);

                    Normal3f(-nRatioTop, 0.0f, -nzTop);
                    TexCoord2f(1.0f, vTop);
                    Vertex3f(rTop, 0.0f, zTop);

                    End();

                    lBase      = lTop;
                    rBase      = rTop;
                    zBase      = zTop;
                    vBase      = vTop;
                    nzBase     = nzTop;
                    nRatioBase = nRatioTop;
                }
            }
            if (hints.CreateFrontFace)
            {
                var lBase      = -(float)System.Math.PI * 0.5f;
                var rBase      = 0.0f;
                var zBase      = -sphere.Radius;
                var vBase      = 0.0f;
                var nzBase     = -1.0f;
                var nRatioBase = 0.0f;

                for (uint rowi = 0; rowi < numRows; ++rowi)
                {
                    var lTop      = lBase + lDelta;
                    var rTop      = (float)System.Math.Cos(lTop) * sphere.Radius;
                    var zTop      = (float)System.Math.Sin(lTop) * sphere.Radius;
                    var vTop      = vBase + vDelta;
                    var nzTop     = (float)System.Math.Sin(lTop);
                    var nRatioTop = (float)System.Math.Cos(lTop);

                    Begin();

                    var angle    = 0.0f;
                    var texCoord = 0.0f;

                    for (uint topi = 0; topi < numSegments;
                         ++topi, angle += angleDelta, texCoord += texCoordHorzDelta)
                    {
                        float c = (float)System.Math.Cos(angle);
                        float s = (float)System.Math.Sin(angle);

                        Normal3f(c * nRatioTop, s * nRatioTop, nzTop);
                        TexCoord2f(texCoord, vTop);
                        Vertex3f(c * rTop, s * rTop, zTop);

                        Normal3f(c * nRatioBase, s * nRatioBase, nzBase);
                        TexCoord2f(texCoord, vBase);
                        Vertex3f(c * rBase, s * rBase, zBase);
                    }

                    // do last point by hand to ensure no round off errors.
                    Normal3f(nRatioTop, 0.0f, nzTop);
                    TexCoord2f(1.0f, vTop);
                    Vertex3f(rTop, 0.0f, zTop);

                    Normal3f(nRatioBase, 0.0f, nzBase);
                    TexCoord2f(1.0f, vBase);
                    Vertex3f(rBase, 0.0f, zBase);

                    End();

                    lBase      = lTop;
                    rBase      = rTop;
                    zBase      = zTop;
                    vBase      = vTop;
                    nzBase     = nzTop;
                    nRatioBase = nRatioTop;
                }
            }

            BuildVertexAndIndexArrays(out var vertexArray, out var indexArray, colors);

            geometry.VertexData = vertexArray;
            geometry.IndexData  = indexArray;

            geometry.VertexLayout = VertexLayoutHelpers.GetLayoutDescription(typeof(T));

            var pSet = DrawElements <T> .Create(
                geometry,
                PrimitiveTopology.TriangleList,
                (uint)geometry.IndexData.Length,
                1,
                0,
                0,
                0);

            geometry.PrimitiveSets.Add(pSet);
        }
        internal static void Build(IGeometry <T> geometry, ITessellationHints hints, Vector3 [] colors, IBox box)
        {
            var dx = box.HalfLengths.X;
            var dy = box.HalfLengths.Y;
            var dz = box.HalfLengths.Z;

            var normVec = Vector3.Normalize(box.HalfLengths);

            var nx = normVec.X;
            var ny = normVec.Y;
            var nz = normVec.Z;

            var vertices = new Vector3[8]
            {
                new Vector3(-dx, +dy, -dz),   // T1, L1, Bk2
                new Vector3(+dx, +dy, -dz),   // T2, R2, Bk1
                new Vector3(+dx, +dy, +dz),   // T3, R1, F2
                new Vector3(-dx, +dy, +dz),   // T4, L2, F1
                new Vector3(-dx, -dy, -dz),   // B4, L4, Bk3
                new Vector3(+dx, -dy, -dz),   // B3, R3, Bk4
                new Vector3(+dx, -dy, +dz),   // B2, R4, F3
                new Vector3(-dx, -dy, +dz),   // B1, L3, F4
            };

            Vector3[] normals;
            if (hints.NormalsType == NormalsType.PerVertex)
            {
                normals = new Vector3[8]
                {
                    new Vector3(-nx, +ny, -nz),   // T1, L1, Bk2
                    new Vector3(+nx, +ny, -nz),   // T2, R2, Bk1
                    new Vector3(+nx, +ny, +nz),   // T3, R1, F2
                    new Vector3(-nx, +ny, +nz),   // T4, L2, F1
                    new Vector3(-nx, -ny, -nz),   // B4, L4, Bk3
                    new Vector3(+nx, -ny, -nz),   // B3, R3, Bk4
                    new Vector3(+nx, -ny, +nz),   // B2, R4, F3
                    new Vector3(-nx, -ny, +nz),   // B1, L3, F4
                };
            }
            else
            {
                normals = new Vector3[6]
                {
                    new Vector3(0, 1, 0),         // T
                    new Vector3(0, -1, 0),        // B
                    new Vector3(1, 0, 0),         // R
                    new Vector3(-1, 0, 0),        // L
                    new Vector3(0, 0, 1),         // F
                    new Vector3(0, 0, -1)         // Bk
                };
            }

            var texcoords = new Vector2[4]
            {
                new Vector2(+0, +0),
                new Vector2(+0, +1),
                new Vector2(+1, +1),
                new Vector2(+1, +0)
            };

            var faces = new Face[6]
            {
                new Face(),  // T
                new Face(),  // B
                new Face(),  // R
                new Face(),  // L
                new Face(),  // F
                new Face()   // B
            };

            // Set Positions
            {
                faces[0].VertexIndices.AddRange(new uint[] { 0, 1, 2, 3 });  // T
                faces[1].VertexIndices.AddRange(new uint[] { 7, 6, 5, 4 });  // B
                faces[2].VertexIndices.AddRange(new uint[] { 2, 1, 5, 6 });  // R
                faces[3].VertexIndices.AddRange(new uint[] { 0, 3, 7, 4 });  // L
                faces[4].VertexIndices.AddRange(new uint[] { 3, 2, 6, 7 });  // F
                faces[5].VertexIndices.AddRange(new uint[] { 1, 0, 4, 5 });  // B
            }

            // Set Tex Coords
            {
                for (uint i = 0; i < 6; ++i)
                {
                    faces[i].TexCoordIndices.AddRange(new uint[] { 0, 1, 2, 3 });
                }
            }

            // Set Normals
            if (hints.NormalsType == NormalsType.PerVertex)
            {
                faces[0].NormalIndices.AddRange(new uint[] { 0, 1, 2, 3 });  // T
                faces[1].NormalIndices.AddRange(new uint[] { 7, 6, 5, 4 });  // B
                faces[2].NormalIndices.AddRange(new uint[] { 2, 1, 5, 6 });  // R
                faces[3].NormalIndices.AddRange(new uint[] { 0, 3, 7, 4 });  // L
                faces[4].NormalIndices.AddRange(new uint[] { 3, 2, 6, 7 });  // F
                faces[5].NormalIndices.AddRange(new uint[] { 1, 0, 4, 5 });  // B
            }
            else // Per face Normals
            {
                for (uint i = 0; i < 6; ++i)
                {
                    faces[i].NormalIndices.AddRange(new uint[] { i, i, i, i });
                }
            }


            // Set Colors
            {
                switch (hints.ColorsType)
                {
                case ColorsType.ColorOverall:
                default:
                {
                    if (colors.Length < 1)
                    {
                        throw new Exception("Not enough colors specified");
                    }

                    for (uint i = 0; i < 6; ++i)
                    {
                        faces[i].ColorIndices.AddRange(new uint[] { 0, 0, 0, 0 });
                    }

                    break;
                }

                case ColorsType.ColorPerFace:
                {
                    if (colors.Length < 6)
                    {
                        throw new Exception("Not enough colors specified for per-face coloring");
                    }

                    for (uint i = 0; i < 6; ++i)
                    {
                        faces[i].ColorIndices.AddRange(new uint[] { i, i, i, i });
                    }

                    break;
                }

                case ColorsType.ColorPerVertex:
                {
                    if (colors.Length < 8)
                    {
                        throw new Exception("Not enough colors specified for per-vertex coloring");
                    }

                    faces[0].ColorIndices.AddRange(new uint[] { 0, 1, 2, 3 });    // T
                    faces[1].ColorIndices.AddRange(new uint[] { 7, 6, 5, 4 });    // B
                    faces[2].ColorIndices.AddRange(new uint[] { 2, 1, 5, 6 });    // R
                    faces[3].ColorIndices.AddRange(new uint[] { 0, 3, 7, 4 });    // L
                    faces[4].ColorIndices.AddRange(new uint[] { 3, 2, 6, 7 });    // F
                    faces[5].ColorIndices.AddRange(new uint[] { 1, 0, 4, 5 });    // B
                    break;
                }
                }
            }

            var vertexDataList = new List <T>();

            foreach (var face in faces)
            {
                for (var i = 0; i < face.VertexIndices.Count; ++i)
                {
                    var vtx = new T();
                    vtx.SetPosition(vertices[face.VertexIndices[i]]);
                    vtx.SetNormal(normals[face.NormalIndices[i]]);
                    vtx.SetColor3(colors[face.ColorIndices[i]]);
                    vtx.SetTexCoord(texcoords[face.TexCoordIndices[i]]);
                    vertexDataList.Add(vtx);
                }
            }

            geometry.VertexData = vertexDataList.ToArray();

            uint[] indices =
            {
                0,   1,  2,  0,  2,  3,
                4,   5,  6,  4,  6,  7,
                8,   9, 10,  8, 10, 11,
                12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23,
            };

            geometry.IndexData = indices;

            geometry.VertexLayout = VertexLayoutHelpers.GetLayoutDescription(typeof(T));

            var pSet = DrawElements <T> .Create(
                geometry,
                PrimitiveTopology.TriangleList,
                (uint)geometry.IndexData.Length,
                1,
                0,
                0,
                0);

            geometry.PrimitiveSets.Add(pSet);
        }