Пример #1
0
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            MeshGeometry3D mesh = MeshGenerator.Geometry;

            foreach (Point3D vertex in mesh.Positions)
            {
                vertices.Add(vertex);
            }

            foreach (Vector3D normal in mesh.Normals)
            {
                normals.Add(normal);
            }

            foreach (int index in mesh.TriangleIndices)
            {
                indices.Add(index);
            }

            foreach (Point texture in mesh.TextureCoordinates)
            {
                textures.Add(texture);
            }
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            // Clear all four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Fill the vertices, normals, and textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                double phi   = Math.PI / 2 - stack * Math.PI / Stacks;
                double y     = Radius * Math.Sin(phi);
                double scale = -Radius *Math.Cos(phi);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    double theta = slice * 2 * Math.PI / Slices;
                    double x     = scale * Math.Sin(theta);
                    double z     = scale * Math.Cos(theta);

                    Vector3D normal = new Vector3D(x, y, z);
                    normals.Add(normal);
                    vertices.Add(normal.ToPoint3D());
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    if (stack != 0)
                    {
                        indices.Add((stack + 0) * (Slices + 1) + slice);
                        indices.Add((stack + 1) * (Slices + 1) + slice);
                        indices.Add((stack + 0) * (Slices + 1) + slice + 1);
                    }

                    if (stack != Stacks - 1)
                    {
                        indices.Add((stack + 0) * (Slices + 1) + slice + 1);
                        indices.Add((stack + 1) * (Slices + 1) + slice);
                        indices.Add((stack + 1) * (Slices + 1) + slice + 1);
                    }
                }
            }
        }
Пример #3
0
/*
 *      // Static method called for any property change.
 *      static void PropertyChanged(DependencyObject obj,
 *                                  DependencyPropertyChangedEventArgs args)
 *      {
 *          (obj as TorusMesh).PropertyChanged(args);
 *      }
 */
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            // Clear all four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Fill the vertices, normals, and textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                double phi = stack * 2 * Math.PI / Stacks;

                double  xCenter     = Radius * Math.Sin(phi);
                double  yCenter     = Radius * Math.Cos(phi);
                Point3D pointCenter = new Point3D(xCenter, yCenter, 0);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    double theta = slice * 2 * Math.PI / Slices + Math.PI;
                    double x     = (Radius + TubeRadius * Math.Cos(theta)) * Math.Sin(phi);
                    double y     = (Radius + TubeRadius * Math.Cos(theta)) * Math.Cos(phi);
                    double z     = -TubeRadius *Math.Sin(theta);

                    Point3D point = new Point3D(x, y, z);

                    vertices.Add(point);
                    normals.Add(point - pointCenter);
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add((stack + 0) * (Slices + 1) + slice);
                    indices.Add((stack + 1) * (Slices + 1) + slice);
                    indices.Add((stack + 0) * (Slices + 1) + slice + 1);

                    indices.Add((stack + 0) * (Slices + 1) + slice + 1);
                    indices.Add((stack + 1) * (Slices + 1) + slice);
                    indices.Add((stack + 1) * (Slices + 1) + slice + 1);
                }
            }
        }
Пример #4
0
        public void CopyTo(Int32Collection value)
        {
            if (value == null || object.ReferenceEquals(value, this))
            {
                return;
            }

            value.Clear();

            foreach (int i in this)
            {
                value.Add(i);
            }
        }
Пример #5
0
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Variables for vertices collection.
            Vector3D UL      = (Vector3D)UpperLeft;
            Vector3D UR      = (Vector3D)UpperRight;
            Vector3D LL      = (Vector3D)LowerLeft;
            Vector3D LR      = (Vector3D)LowerRight;
            int      product = Slices * Stacks;

            // Variables for textures collection
            Point  ptOrigin  = new Point(0, 0);
            Vector vectSlice = (new Point(1, 0) - ptOrigin) / Slices;
            Vector vectStack = (new Point(0, 1) - ptOrigin) / Stacks;

            for (int stack = 0; stack <= Stacks; stack++)
            {
                for (int slice = 0; slice <= Slices; slice++)
                {
                    vertices.Add((Point3D)(((Stacks - stack) * (Slices - slice) * UL +
                                            stack * (Slices - slice) * LL +
                                            (Stacks - stack) * slice * UR +
                                            stack * slice * LR) / product));

                    textures.Add(ptOrigin + stack * vectStack + slice * vectSlice);

                    if (slice < Slices && stack < Stacks)
                    {
                        indices.Add((Slices + 1) * stack + slice);
                        indices.Add((Slices + 1) * (stack + 1) + slice);
                        indices.Add((Slices + 1) * stack + slice + 1);

                        indices.Add((Slices + 1) * stack + slice + 1);
                        indices.Add((Slices + 1) * (stack + 1) + slice);
                        indices.Add((Slices + 1) * (stack + 1) + slice + 1);
                    }
                }
            }
        }
Пример #6
0
        void Recalculate()
        {
            GeometryModel3D   model  = Content as GeometryModel3D;
            MeshGeometry3D    mesh   = model.Geometry as MeshGeometry3D;
            Point3DCollection points = mesh.Positions;

            mesh.Positions = null;
            points.Clear();

            Int32Collection indices = mesh.TriangleIndices;

            mesh.TriangleIndices = null;
            indices.Clear();

            int indicesBase         = 0;
            Point3DCollection lines = LineCollection;

            for (int line = 0; line < lines.Count - 1; line += 2)
            {
                Point3D pt1 = lines[line + 0];
                Point3D pt2 = lines[line + 1];

                DoLine(pt1, pt2, points, indices, ref indicesBase);

                if (line == 0 &&
                    (ArrowEnds & ArrowEnds.Start) == ArrowEnds.Start)
                {
                    DoArrow(pt2, pt1, points, indices, ref indicesBase);
                }

                if (line > lines.Count - 4 &&
                    (ArrowEnds & ArrowEnds.End) == ArrowEnds.End)
                {
                    DoArrow(pt1, pt2, points, indices, ref indicesBase);
                }
            }

            mesh.TriangleIndices = indices;
            mesh.Positions       = points;
        }
Пример #7
0
        //Calculate grouped rows and columns
        #region Calculate grouped rows and columns
        /// <summary>
        /// Calculate grouped columns
        /// </summary>
        /// <returns></returns>
        public int GetGroupedColumns()
        {
            _GroupColumns.Clear();

            if (this.RootGroupInfo == null)
            {
                return(1);
            }

            int nCols = 0;

            if (this._ShowRowIndicators)
            {
                nCols += 1;
            }

            this.RootGroupInfo.IsSectionOutSide = this.SectionInOneRow;

            this.GetGroupedColumns(this.RootGroupInfo, ref nCols);

            return(nCols);
        }
Пример #8
0
        // Calculates the TriangleIndices collection
        void GenerateTriangleIndices()
        {
            MeshGeometry3D  mesh    = (MeshGeometry3D)Geometry;
            Int32Collection indices = mesh.TriangleIndices;

            mesh.TriangleIndices = null;
            indices.Clear();

            int slices         = Slices;
            int stacks         = Stacks;
            int indexTopPoints = (stacks + 3) * (slices + 1);

            for (int i = 0; i < slices; i++)
            {
                for (int j = 0; j < stacks; j++)
                {
                    // Triangles running length of cylinder
                    indices.Add((stacks + 3) * i + j);
                    indices.Add((stacks + 3) * i + j + stacks + 3);
                    indices.Add((stacks + 3) * i + j + 1);

                    indices.Add((stacks + 3) * i + j + 1);
                    indices.Add((stacks + 3) * i + j + stacks + 3);
                    indices.Add((stacks + 3) * i + j + stacks + 3 + 1);
                }

                // Triangles on top of cylinder
                indices.Add(indexTopPoints + 2 * i);
                indices.Add((stacks + 3) * i + (stacks + 3) * 2 - 2);
                indices.Add((stacks + 3) * i + (stacks + 3) - 2);

                // Triangles on bottom of cylinder
                indices.Add(indexTopPoints + 2 * i + 1);
                indices.Add((stacks + 3) * i + (stacks + 3) - 1);
                indices.Add((stacks + 3) * i + (stacks + 3) * 2 - 1);
            }
            mesh.TriangleIndices = indices;
        }
Пример #9
0
        public override void UpdateGeometric()
        {
            if (model == null)
            {
                return;
            }

            positions.Clear();
            indices.Clear();
            texcoords.Clear();

            for (int i = 0; i < particles.Count; ++i)
            {
                int      positionIndex = i * 4;
                int      indexIndex    = i * 6;
                Particle p             = particles[i];

                ComputePositions(p, positions);

                texcoords.Add(new System.Windows.Point(0.0, 0.0));
                texcoords.Add(new System.Windows.Point(0.0, 1.0));
                texcoords.Add(new System.Windows.Point(1.0, 1.0));
                texcoords.Add(new System.Windows.Point(1.0, 0.0));

                indices.Add(positionIndex);
                indices.Add(positionIndex + 2);
                indices.Add(positionIndex + 1);
                indices.Add(positionIndex);
                indices.Add(positionIndex + 3);
                indices.Add(positionIndex + 2);
            }

            //((MeshGeometry3D)model.Geometry).Positions = positions;
            //((MeshGeometry3D)model.Geometry).TriangleIndices = indices;
            //((MeshGeometry3D)model.Geometry).TextureCoordinates = texcoords;
        }
Пример #10
0
        /// <summary>
        /// Noktaları / üçgenleri temizleyin ve yeniler
        /// </summary>
        /// <param name="grid"></param>
        private void InitializePointsAndTriangles()
        {
            _ptBuffer1.Clear();
            _ptBuffer2.Clear();
            _triangleIndices.Clear();

            int nCurrIndex = 0;     // March through 1-D arrays

            for (int row = 0; row < _dimension; row++)
            {
                for (int col = 0; col < _dimension; col++)
                {
                    //ızgarada, X / Y değerleri yalnızca satır / sütun sayılarıdır
                    _ptBuffer1.Add(new Point3D(col, 0.0, row));

                    // Yeni kare tamamlandığında, 2 üçgen ekleyin
                    if ((row > 0) && (col > 0))
                    {
                        // Triangle 1
                        _triangleIndices.Add(nCurrIndex - _dimension - 1);
                        _triangleIndices.Add(nCurrIndex);
                        _triangleIndices.Add(nCurrIndex - _dimension);

                        // Triangle 2
                        _triangleIndices.Add(nCurrIndex - _dimension - 1);
                        _triangleIndices.Add(nCurrIndex - 1);
                        _triangleIndices.Add(nCurrIndex);
                    }

                    nCurrIndex++;
                }
            }

            //2. tampon, yalnızca 2. Z değeri setine sahip
            _ptBuffer2 = _ptBuffer1.Clone();
        }
Пример #11
0
        /// <summary>
        /// Clear out points/triangles and regenerates
        /// </summary>
        ///<param name = "grid" ></ param >
        private void InitializePointsAndTriangles()
        {
            _ptBuffer1.Clear();
            _ptBuffer2.Clear();
            _triangleIndices.Clear();

            int nCurrIndex = 0;     // March through 1-D arrays

            for (int row = 0; row < _dimension; row++)
            {
                for (int col = 0; col < _dimension; col++)
                {
                    // In grid, X/Y values are just row/col numbers
                    _ptBuffer1.Add(new Point3D(col, 0.0, row));

                    // Completing new square, add 2 triangles
                    if ((row > 0) && (col > 0))
                    {
                        // Triangle 1
                        _triangleIndices.Add(nCurrIndex - _dimension - 1);
                        _triangleIndices.Add(nCurrIndex);
                        _triangleIndices.Add(nCurrIndex - _dimension);

                        // Triangle 2
                        _triangleIndices.Add(nCurrIndex - _dimension - 1);
                        _triangleIndices.Add(nCurrIndex - 1);
                        _triangleIndices.Add(nCurrIndex);
                    }

                    nCurrIndex++;
                }
            }

            // 2nd buffer exists only to have 2nd set of Z values
            _ptBuffer2 = _ptBuffer1.Clone();
        }
Пример #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            Vector3D normal = new Vector3D(0, 0, 1);
            double   angleInner = 2 * Math.PI / Sides;
            double   radius = Length / 2 / Math.Sin(angleInner / 2);
            double   angle = 3 * Math.PI / 2 + angleInner / 2;
            double   xMin = 0, xMax = 0, yMin = 0, yMax = 0;

            for (int side = 0; side < Sides; side++)
            {
                double x = Math.Cos(angle);
                double y = Math.Sin(angle);

                xMin = Math.Min(xMin, x);
                xMax = Math.Max(xMax, x);
                yMin = Math.Min(yMin, y);
                yMax = Math.Max(yMax, y);

                angle += angleInner;
            }

            angle = 3 * Math.PI / 2 + angleInner / 2;

            for (int side = 0; side < Sides; side++)
            {
                vertices.Add(new Point3D(0, 0, 0));
                textures.Add(new Point(-xMin / (xMax - xMin), yMax / (yMax - yMin)));
                normals.Add(normal);

                double x = Math.Cos(angle);
                double y = Math.Sin(angle);
                vertices.Add(new Point3D(x, y, 0));
                textures.Add(new Point((x - xMin) / (xMax - xMin),
                                       (yMax - y) / (yMax - yMin)));
                normals.Add(normal);

                angle += angleInner;
                x      = Math.Cos(angle);
                y      = Math.Sin(angle);
                vertices.Add(new Point3D(x, y, 0));
                textures.Add(new Point((x - xMin) / (xMax - xMin),
                                       (yMax - y) / (yMax - yMin)));
                normals.Add(normal);

                int index = vertices.Count - 3;
                indices.Add(index);
                indices.Add(index + 1);
                indices.Add(index + 2);

                if (Slices > 1)
                {
                    TriangleSubdivide(vertices, normals, indices, textures);
                }
            }
        }
Пример #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            // Clear all four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            double x, y, z;
            int    indexBase = 0;

            // Front side.
            // -----------
            z = Depth / 2;

            // Fill the vertices, normals, textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                y = Height / 2 - stack * Height / Stacks;

                for (int slice = 0; slice <= Slices; slice++)
                {
                    x = -Width / 2 + slice * Width / Slices;
                    Point3D point = new Point3D(x, y, z);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(x, y, 0));
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add((stack + 0) * (Slices + 1) + slice);
                    indices.Add((stack + 1) * (Slices + 1) + slice);
                    indices.Add((stack + 0) * (Slices + 1) + slice + 1);

                    indices.Add((stack + 0) * (Slices + 1) + slice + 1);
                    indices.Add((stack + 1) * (Slices + 1) + slice);
                    indices.Add((stack + 1) * (Slices + 1) + slice + 1);
                }
            }

            // Rear side.
            // -----------
            indexBase = vertices.Count;
            z         = -Depth / 2;

            // Fill the vertices, normals, textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                y = Height / 2 - stack * Height / Stacks;

                for (int slice = 0; slice <= Slices; slice++)
                {
                    x = Width / 2 - slice * Width / Slices;
                    Point3D point = new Point3D(x, y, z);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(x, y, 0));
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add(indexBase + (stack + 0) * (Slices + 1) + slice);
                    indices.Add(indexBase + (stack + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (stack + 0) * (Slices + 1) + slice + 1);

                    indices.Add(indexBase + (stack + 0) * (Slices + 1) + slice + 1);
                    indices.Add(indexBase + (stack + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (stack + 1) * (Slices + 1) + slice + 1);
                }
            }

            // Left side.
            // -----------
            indexBase = vertices.Count;
            x         = -Width / 2;

            // Fill the vertices, normals, textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                y = Height / 2 - stack * Height / Stacks;

                for (int layer = 0; layer <= Layers; layer++)
                {
                    z = -Depth / 2 + layer * Depth / Layers;
                    Point3D point = new Point3D(x, y, z);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(0, y, z));
                    textures.Add(new Point((double)layer / Layers,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int layer = 0; layer < Layers; layer++)
                {
                    indices.Add(indexBase + (stack + 0) * (Layers + 1) + layer);
                    indices.Add(indexBase + (stack + 1) * (Layers + 1) + layer);
                    indices.Add(indexBase + (stack + 0) * (Layers + 1) + layer + 1);

                    indices.Add(indexBase + (stack + 0) * (Layers + 1) + layer + 1);
                    indices.Add(indexBase + (stack + 1) * (Layers + 1) + layer);
                    indices.Add(indexBase + (stack + 1) * (Layers + 1) + layer + 1);
                }
            }

            // Right side.
            // -----------
            indexBase = vertices.Count;
            x         = Width / 2;

            // Fill the vertices, normals, textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                y = Height / 2 - stack * Height / Stacks;

                for (int layer = 0; layer <= Layers; layer++)
                {
                    z = Depth / 2 - layer * Depth / Layers;
                    Point3D point = new Point3D(x, y, z);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(0, y, z));
                    textures.Add(new Point((double)layer / Layers,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int layer = 0; layer < Layers; layer++)
                {
                    indices.Add(indexBase + (stack + 0) * (Layers + 1) + layer);
                    indices.Add(indexBase + (stack + 1) * (Layers + 1) + layer);
                    indices.Add(indexBase + (stack + 0) * (Layers + 1) + layer + 1);

                    indices.Add(indexBase + (stack + 0) * (Layers + 1) + layer + 1);
                    indices.Add(indexBase + (stack + 1) * (Layers + 1) + layer);
                    indices.Add(indexBase + (stack + 1) * (Layers + 1) + layer + 1);
                }
            }

            // Top side.
            // -----------
            indexBase = vertices.Count;
            y         = Height / 2;

            // Fill the vertices, normals, textures collections.
            for (int layer = 0; layer <= Layers; layer++)
            {
                z = -Depth / 2 + layer * Depth / Layers;

                for (int slice = 0; slice <= Slices; slice++)
                {
                    x = -Width / 2 + slice * Width / Slices;
                    Point3D point = new Point3D(x, y, z);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(x, 0, z));
                    textures.Add(new Point((double)slice / Slices,
                                           (double)layer / Layers));
                }
            }

            // Fill the indices collection.
            for (int layer = 0; layer < Layers; layer++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add(indexBase + (layer + 0) * (Slices + 1) + slice);
                    indices.Add(indexBase + (layer + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (layer + 0) * (Slices + 1) + slice + 1);

                    indices.Add(indexBase + (layer + 0) * (Slices + 1) + slice + 1);
                    indices.Add(indexBase + (layer + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (layer + 1) * (Slices + 1) + slice + 1);
                }
            }

            // Bottom side.
            // -----------
            indexBase = vertices.Count;
            y         = -Height / 2;

            // Fill the vertices, normals, textures collections.
            for (int layer = 0; layer <= Layers; layer++)
            {
                z = Depth / 2 - layer * Depth / Layers;

                for (int slice = 0; slice <= Slices; slice++)
                {
                    x = -Width / 2 + slice * Width / Slices;
                    Point3D point = new Point3D(x, y, z);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(x, 0, z));
                    textures.Add(new Point((double)slice / Slices,
                                           (double)layer / Layers));
                }
            }

            // Fill the indices collection.
            for (int layer = 0; layer < Layers; layer++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add(indexBase + (layer + 0) * (Slices + 1) + slice);
                    indices.Add(indexBase + (layer + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (layer + 0) * (Slices + 1) + slice + 1);

                    indices.Add(indexBase + (layer + 0) * (Slices + 1) + slice + 1);
                    indices.Add(indexBase + (layer + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (layer + 1) * (Slices + 1) + slice + 1);
                }
            }
        }
Пример #14
0
        void PropertyChanged(DependencyPropertyChangedEventArgs args)
        {
            // Get references to all four collections.
            Point3DCollection  vertices = mesh.Positions;
            Vector3DCollection normals  = mesh.Normals;
            Int32Collection    indices  = mesh.TriangleIndices;
            PointCollection    textures = mesh.TextureCoordinates;

            // Set the MeshGeometry3D properties to null to inhibit notifications.
            mesh.Positions          = null;
            mesh.Normals            = null;
            mesh.TriangleIndices    = null;
            mesh.TextureCoordinates = null;

            // Clear the four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Fill the vertices, normals, and textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                double phi   = Math.PI / 2 - stack * Math.PI / Stacks;
                double y     = Radius * Math.Sin(phi);
                double scale = -Radius *Math.Cos(phi);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    double theta = slice * 2 * Math.PI / Slices;
                    double x     = scale * Math.Sin(theta);
                    double z     = scale * Math.Cos(theta);

                    Vector3D normal = new Vector3D(x, y, z);
                    normals.Add(normal);
                    vertices.Add(normal + Center);
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                int top = (stack + 0) * (Slices + 1);
                int bot = (stack + 1) * (Slices + 1);

                for (int slice = 0; slice < Slices; slice++)
                {
                    if (stack != 0)
                    {
                        indices.Add(top + slice);
                        indices.Add(bot + slice);
                        indices.Add(top + slice + 1);
                    }

                    if (stack != Stacks - 1)
                    {
                        indices.Add(top + slice + 1);
                        indices.Add(bot + slice);
                        indices.Add(bot + slice + 1);
                    }
                }
            }

            // Set the collections back to the properties.
            mesh.TextureCoordinates = textures;
            mesh.TriangleIndices    = indices;
            mesh.Normals            = normals;
            mesh.Positions          = vertices;
        }
Пример #15
0
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Front.
            for (int iy = 0; iy <= Stacks; iy++)
            {
                double y = Origin.Y + Height - iy * Height / Stacks;

                for (int ix = 0; ix <= Slices; ix++)
                {
                    double x = Origin.X + ix * Width / Slices;
                    vertices.Add(new Point3D(x, y, Origin.Z + Depth));
                }
            }

            // Back
            for (int iy = 0; iy <= Stacks; iy++)
            {
                double y = Origin.Y + Height - iy * Height / Stacks;

                for (int ix = 0; ix <= Slices; ix++)
                {
                    double x = Origin.X + Width - ix * Width / Slices;
                    vertices.Add(new Point3D(x, y, Origin.Z));
                }
            }

            // Left
            for (int iy = 0; iy <= Stacks; iy++)
            {
                double y = Origin.Y + Height - iy * Height / Stacks;

                for (int iz = 0; iz <= Slivers; iz++)
                {
                    double z = Origin.Z + iz * Depth / Slivers;
                    vertices.Add(new Point3D(Origin.X, y, z));
                }
            }

            // Right
            for (int iy = 0; iy <= Stacks; iy++)
            {
                double y = Origin.Y + Height - iy * Height / Stacks;

                for (int iz = 0; iz <= Slivers; iz++)
                {
                    double z = Origin.Z + Depth - iz * Depth / Slivers;
                    vertices.Add(new Point3D(Origin.X + Width, y, z));
                }
            }

            // Top
            for (int iz = 0; iz <= Slivers; iz++)
            {
                double z = Origin.Z + iz * Depth / Slivers;

                for (int ix = 0; ix <= Slices; ix++)
                {
                    double x = Origin.X + ix * Width / Slices;
                    vertices.Add(new Point3D(x, Origin.Y + Height, z));
                }
            }

            // Top
            for (int iz = 0; iz <= Slivers; iz++)
            {
                double z = Origin.Z + Depth - iz * Depth / Slivers;

                for (int ix = 0; ix <= Slices; ix++)
                {
                    double x = Origin.X + ix * Width / Slices;
                    vertices.Add(new Point3D(x, Origin.Y, z));
                }
            }

            for (int side = 0; side < 6; side++)
            {
                for (int iy = 0; iy <= Stacks; iy++)
                {
                    double y = (double)iy / Stacks;

                    for (int ix = 0; ix <= Slices; ix++)
                    {
                        double x = (double)ix / Slices;
                        textures.Add(new Point(x, y));
                    }
                }
            }

            // Front, back, left, right
            for (int side = 0; side < 6; side++)
            {
                for (int iy = 0; iy < Stacks; iy++)
                {
                    for (int ix = 0; ix < Slices; ix++)
                    {
                        indices.Add(side * (Slices + 1) * (Stacks + 1) + iy * (Slices + 1) + ix);
                        indices.Add(side * (Slices + 1) * (Stacks + 1) + (iy + 1) * (Slices + 1) + ix);
                        indices.Add(side * (Slices + 1) * (Stacks + 1) + iy * (Slices + 1) + ix + 1);

                        indices.Add(side * (Slices + 1) * (Stacks + 1) + iy * (Slices + 1) + ix + 1);
                        indices.Add(side * (Slices + 1) * (Stacks + 1) + (iy + 1) * (Slices + 1) + ix);
                        indices.Add(side * (Slices + 1) * (Stacks + 1) + (iy + 1) * (Slices + 1) + ix + 1);
                    }
                }
            }
        }
Пример #16
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            // Clear all four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            double x, y;
            int    indexBase = 0;

            // Front side.
            // -----------

            // Fill the vertices, normals, textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                y = Height / 2 - stack * Height / Stacks;

                for (int slice = 0; slice <= Slices; slice++)
                {
                    x = -Width / 2 + slice * Width / Slices;
                    Point3D point = new Point3D(x, y, 0);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(x, y, 0));
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add((stack + 0) * (Slices + 1) + slice);
                    indices.Add((stack + 1) * (Slices + 1) + slice);
                    indices.Add((stack + 0) * (Slices + 1) + slice + 1);

                    indices.Add((stack + 0) * (Slices + 1) + slice + 1);
                    indices.Add((stack + 1) * (Slices + 1) + slice);
                    indices.Add((stack + 1) * (Slices + 1) + slice + 1);
                }
            }

            // Rear side.
            // -----------
            indexBase = vertices.Count;

            // Fill the vertices, normals, textures collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                y = Height / 2 - stack * Height / Stacks;

                for (int slice = 0; slice <= Slices; slice++)
                {
                    x = Width / 2 - slice * Width / Slices;
                    Point3D point = new Point3D(x, y, 0);
                    vertices.Add(point);

                    normals.Add(point - new Point3D(x, y, 0));
                    textures.Add(new Point((double)slice / Slices,
                                           (double)stack / Stacks));
                }
            }

            // Fill the indices collection.
            for (int stack = 0; stack < Stacks; stack++)
            {
                for (int slice = 0; slice < Slices; slice++)
                {
                    indices.Add(indexBase + (stack + 0) * (Slices + 1) + slice);
                    indices.Add(indexBase + (stack + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (stack + 0) * (Slices + 1) + slice + 1);

                    indices.Add(indexBase + (stack + 0) * (Slices + 1) + slice + 1);
                    indices.Add(indexBase + (stack + 1) * (Slices + 1) + slice);
                    indices.Add(indexBase + (stack + 1) * (Slices + 1) + slice + 1);
                }
            }
        }
Пример #17
0
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Copy properties to local variables to improve speed
            int     slices = Slices;
            int     stacks = Stacks;
            double  radius = Radius;
            Point3D ctr    = Center;

            double lat1 = Math.Max(LatitudeFrom, LatitudeTo); // default is 90
            double lat2 = Math.Min(LatitudeFrom, LatitudeTo); // default is -90

            double lng1 = LongitudeFrom;                      // default is -180
            double lng2 = LongitudeTo;                        // default is 180

            for (int lat = 0; lat <= stacks; lat++)
            {
                double degrees = lat1 - lat * (lat1 - lat2) / stacks;

                double angle = Math.PI * degrees / 180;
                double y     = radius * Math.Sin(angle);
                double scale = Math.Cos(angle);

                for (int lng = 0; lng <= slices; lng++)
                {
                    double diff = lng2 - lng1;

                    if (diff < 0)
                    {
                        diff += 360;
                    }

                    degrees = lng1 + lng * diff / slices;
                    angle   = Math.PI * degrees / 180;
                    double x = radius * scale * Math.Sin(angle);
                    double z = radius * scale * Math.Cos(angle);

                    Vector3D vect = new Vector3D(x, y, z);
                    vertices.Add(ctr + vect);
                    normals.Add(vect);
                    textures.Add(new Point((double)lng / slices,
                                           (double)lat / stacks));
                }
            }

            for (int lat = 0; lat < stacks; lat++)
            {
                int start = lat * (slices + 1);
                int next  = start + slices + 1;

                for (int lng = 0; lng < slices; lng++)
                {
                    indices.Add(start + lng);
                    indices.Add(next + lng);
                    indices.Add(next + lng + 1);

                    indices.Add(start + lng);
                    indices.Add(next + lng + 1);
                    indices.Add(start + lng + 1);
                }
            }
        }
Пример #18
0
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // vectRearRadius points towards -Z (when possible).
            Vector3D vectCylinder = Point2 - Point1;
            Vector3D vectRearRadius;

            if (vectCylinder.X == 0 && vectCylinder.Y == 0)
            {
                // Special case: set rear-radius vector
                vectRearRadius = new Vector3D(0, -1, 0);
            }
            else
            {
                // Find vector axis 90 degrees from cylinder where Z == 0
                rotate.Axis  = Vector3D.CrossProduct(vectCylinder, new Vector3D(0, 0, 1));
                rotate.Angle = -90;

                // Rotate cylinder 90 degrees to find radius vector
                vectRearRadius = vectCylinder * xform.Value;
                vectRearRadius.Normalize();
            }

            // Will rotate radius around cylinder axis
            rotate.Axis = -vectCylinder;

            // Begin at the top end. Fill the collections.
            for (int stack = 0; stack <= EndStacks; stack++)
            {
                double   radius     = stack * Radius1 / EndStacks;
                Vector3D vectRadius = radius * vectRearRadius;
                int      top        = (stack + 0) * (Slices + 1);
                int      bot        = (stack + 1) * (Slices + 1);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    rotate.Angle = slice * 360.0 / Slices;
                    vertices.Add(Point1 + vectRadius * xform.Value);
                    normals.Add(-vectCylinder);
                    textures.Add(new Point((double)slice / Slices,
                                           Fold1 * stack / EndStacks));

                    if (stack < EndStacks && slice < Slices)
                    {
                        if (stack != 0)
                        {
                            indices.Add(top + slice);
                            indices.Add(bot + slice);
                            indices.Add(top + slice + 1);
                        }
                        indices.Add(top + slice + 1);
                        indices.Add(bot + slice);
                        indices.Add(bot + slice + 1);
                    }
                }
            }

            int offset = vertices.Count;

            // Go down length of cylinder and fill in the collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                double   radius     = ((Stacks - stack) * Radius1 + stack * Radius2) / Stacks;
                Vector3D vectRadius = radius * vectRearRadius;
                Point3D  center     = (Point3D)(Point1 + stack * vectCylinder / Stacks);
                int      top        = offset + (stack + 0) * (Slices + 1);
                int      bot        = offset + (stack + 1) * (Slices + 1);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    rotate.Angle = slice * 360.0 / Slices;
                    Vector3D normal = vectRadius * xform.Value;
                    normals.Add(normal);
                    vertices.Add(center + normal);
                    textures.Add(new Point((double)slice / Slices,
                                           Fold1 + (Fold2 - Fold1) * stack / Stacks));

                    if (stack < Stacks && slice < Slices)
                    {
                        indices.Add(top + slice);
                        indices.Add(bot + slice);
                        indices.Add(top + slice + 1);

                        indices.Add(top + slice + 1);
                        indices.Add(bot + slice);
                        indices.Add(bot + slice + 1);
                    }
                }
            }

            offset = vertices.Count;

            // Finish with bottom.
            for (int stack = 0; stack <= EndStacks; stack++)
            {
                double   radius     = Radius2 * (1 - (double)stack / EndStacks);
                Vector3D vectRadius = radius * vectRearRadius;
                int      top        = offset + (stack + 0) * (Slices + 1);
                int      bot        = offset + (stack + 1) * (Slices + 1);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    rotate.Angle = slice * 360.0 / Slices;
                    vertices.Add(Point2 + vectRadius * xform.Value);
                    normals.Add(vectCylinder);
                    textures.Add(new Point((double)slice / Slices,
                                           Fold2 + (1 - Fold2) * stack / EndStacks));

                    if (stack < EndStacks && slice < Slices)
                    {
                        indices.Add(top + slice);
                        indices.Add(bot + slice);
                        indices.Add(top + slice + 1);

                        if (stack != EndStacks - 1)
                        {
                            indices.Add(top + slice + 1);
                            indices.Add(bot + slice);
                            indices.Add(bot + slice + 1);
                        }
                    }
                }
            }
        }
Пример #19
0
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            Point3D[,] faces = Faces;
            PointCollection texturesBase  = TextureCoordinates;
            int             indexTextures = 0;

            for (int face = 0; face < faces.GetLength(0); face++)
            {
                Vector3D normal = Vector3D.CrossProduct(faces[face, 1] - faces[face, 0],
                                                        faces[face, 2] - faces[face, 0]);

                // For faces that are triangles.
                if (faces.GetLength(1) == 3)
                {
                    int indexBase = vertices.Count;

                    for (int i = 0; i < 3; i++)
                    {
                        vertices.Add(faces[face, i]);
                        normals.Add(normal);
                        indices.Add(indexBase + i);

                        if (texturesBase != null && texturesBase.Count > 0)
                        {
                            textures.Add(texturesBase[indexTextures]);
                            indexTextures = (indexTextures + 1) % texturesBase.Count;
                        }
                    }

                    if (Slices > 1)
                    {
                        TriangleSubdivide(vertices, normals, indices, textures);
                    }
                }

                // For faces that are not triangles.
                else
                {
                    for (int i = 0; i < faces.GetLength(1) - 1; i++)
                    {
                        int indexBase = vertices.Count;
                        int num       = faces.GetLength(1) - 1;

                        vertices.Add(faces[face, 0]);
                        vertices.Add(faces[face, i + 1]);
                        vertices.Add(faces[face, (i + 1) % num + 1]);

                        if (texturesBase != null && texturesBase.Count >= faces.GetLength(1))
                        {
                            textures.Add(texturesBase[indexTextures + 0]);
                            textures.Add(texturesBase[indexTextures + i + 1]);
                            textures.Add(texturesBase[indexTextures + (i + 1) % num + 1]);
                        }

                        normals.Add(normal);
                        normals.Add(normal);
                        normals.Add(normal);

                        indices.Add(indexBase + 0);
                        indices.Add(indexBase + 1);
                        indices.Add(indexBase + 2);

                        if (Slices > 1)
                        {
                            TriangleSubdivide(vertices, normals, indices, textures);
                        }
                    }
                    if (texturesBase != null && texturesBase.Count > 0)
                    {
                        indexTextures = (indexTextures + faces.GetLength(1)) % texturesBase.Count;
                    }
                }
            }
        }
Пример #20
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            // Clear all four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Begin at the top end. Fill the collections.
            for (int stack = 0; stack <= EndStacks; stack++)
            {
                double y      = Length / 2;
                double radius = stack * Radius / EndStacks;
                int    top    = (stack + 0) * (Slices + 1);
                int    bot    = (stack + 1) * (Slices + 1);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    double theta = slice * 2 * Math.PI / Slices;
                    double x     = -radius *Math.Sin(theta);

                    double z = -radius *Math.Cos(theta);

                    vertices.Add(new Point3D(x, y, z));
                    normals.Add(new Vector3D(0, 1, 0));
                    textures.Add(new Point((double)slice / Slices,
                                           Fold * stack / EndStacks));

                    if (stack < EndStacks && slice < Slices)
                    {
                        if (stack != 0)
                        {
                            indices.Add(top + slice);
                            indices.Add(bot + slice);
                            indices.Add(top + slice + 1);
                        }

                        indices.Add(top + slice + 1);
                        indices.Add(bot + slice);
                        indices.Add(bot + slice + 1);
                    }
                }
            }

            int offset = vertices.Count;

            // Length of the cylinder: Fill in the collections.
            for (int stack = 0; stack <= Stacks; stack++)
            {
                double y   = Length - stack * Length / Stacks - Length / 2;
                int    top = offset + (stack + 0) * (Slices + 1);
                int    bot = offset + (stack + 1) * (Slices + 1);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    double theta = slice * 2 * Math.PI / Slices;
                    double x     = -Radius *Math.Sin(theta);

                    double z = -Radius *Math.Cos(theta);

                    vertices.Add(new Point3D(x, y, z));
                    normals.Add(new Vector3D(x, 0, z));
                    textures.Add(new Point((double)slice / Slices,
                                           Fold + (1 - 2 * Fold) * stack / Stacks));

                    if (stack < Stacks && slice < Slices)
                    {
                        indices.Add(top + slice);
                        indices.Add(bot + slice);
                        indices.Add(top + slice + 1);

                        indices.Add(top + slice + 1);
                        indices.Add(bot + slice);
                        indices.Add(bot + slice + 1);
                    }
                }
            }

            offset = vertices.Count;

            // Finish with the bottom end. Fill the collections.
            for (int stack = 0; stack <= EndStacks; stack++)
            {
                double y      = -Length / 2;
                double radius = (EndStacks - stack) * Radius / EndStacks;
                int    top    = offset + (stack + 0) * (Slices + 1);
                int    bot    = offset + (stack + 1) * (Slices + 1);

                for (int slice = 0; slice <= Slices; slice++)
                {
                    double theta = slice * 2 * Math.PI / Slices;
                    double x     = -radius *Math.Sin(theta);

                    double z = -radius *Math.Cos(theta);

                    vertices.Add(new Point3D(x, y, z));
                    normals.Add(new Vector3D(0, -1, 0));
                    textures.Add(new Point((double)slice / Slices,
                                           (1 - Fold) + Fold * stack / EndStacks));

                    if (stack < EndStacks && slice < Slices)
                    {
                        indices.Add(top + slice);
                        indices.Add(bot + slice);
                        indices.Add(top + slice + 1);

                        if (stack != EndStacks - 1)
                        {
                            indices.Add(top + slice + 1);
                            indices.Add(bot + slice);
                            indices.Add(bot + slice + 1);
                        }
                    }
                }
            }
        }
Пример #21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args">
        ///     The DependencyPropertyChangedEventArgs object originally
        ///     passed to the PropertyChanged handler that initiated this
        ///     recalculation.
        /// </param>
        /// <param name="vertices">
        ///     The Point3DCollection corresponding to the Positions property
        ///     of the MeshGeometry3D.
        /// </param>
        /// <param name="normals">
        ///     The Vector3DCollection corresponding to the Normals property
        ///     of the MeshGeometry3D.
        /// </param>
        /// <param name="indices">
        ///     The Int32Collection corresponding to the TriangleIndices
        ///     property of the MeshGeometry3D.
        /// </param>
        /// <param name="textures">
        ///     The PointCollection corresponding to the TextureCoordinates
        ///     property of the MeshGeometry3D.
        /// </param>
        protected override void Triangulate(DependencyPropertyChangedEventArgs args,
                                            Point3DCollection vertices,
                                            Vector3DCollection normals,
                                            Int32Collection indices,
                                            PointCollection textures)
        {
            // Clear all four collections.
            vertices.Clear();
            normals.Clear();
            indices.Clear();
            textures.Clear();

            // Loop for outside (side = 1) and inside (side = -1).
            for (int side = 1; side >= -1; side -= 2)
            {
                int offset = vertices.Count;

                // Begin at the top end. Fill the collections.
                for (int stack = 0; stack <= EndStacks; stack++)
                {
                    double y      = Length;
                    double radius = Radius + side * stack * Thickness / 2 / EndStacks;
                    int    top    = offset + (stack + 0) * (Slices + 1);
                    int    bot    = offset + (stack + 1) * (Slices + 1);

                    for (int slice = 0; slice <= Slices; slice++)
                    {
                        double theta = slice * 2 * Math.PI / Slices;
                        double x     = -radius *Math.Sin(theta);

                        double z = -radius *Math.Cos(theta);

                        vertices.Add(new Point3D(x, y, z));
                        normals.Add(new Vector3D(0, side, 0));
                        textures.Add(new Point((double)slice / Slices,
                                               Fold * stack / EndStacks));

                        if (stack < EndStacks && slice < Slices)
                        {
                            indices.Add(top + slice);
                            indices.Add(bot + slice);
                            indices.Add(top + slice + 1);

                            indices.Add(top + slice + 1);
                            indices.Add(bot + slice);
                            indices.Add(bot + slice + 1);
                        }
                    }
                }

                offset = vertices.Count;

                // Length of the tube: Fill in the collections.
                for (int stack = 0; stack <= Stacks; stack++)
                {
                    double y   = Length - stack * Length / Stacks;
                    int    top = offset + (stack + 0) * (Slices + 1);
                    int    bot = offset + (stack + 1) * (Slices + 1);

                    for (int slice = 0; slice <= Slices; slice++)
                    {
                        double theta = slice * 2 * Math.PI / Slices;
                        double x     = -(Radius + side * Thickness / 2) * Math.Sin(theta);
                        double z     = -(Radius + side * Thickness / 2) * Math.Cos(theta);

                        vertices.Add(new Point3D(x, y, z));
                        normals.Add(new Vector3D(side * x, 0, side * z));
                        textures.Add(new Point((double)slice / Slices,
                                               Fold + (1 - 2 * Fold) * stack / Stacks));

                        if (stack < Stacks && slice < Slices)
                        {
                            indices.Add(top + slice);
                            indices.Add(bot + slice);
                            indices.Add(top + slice + 1);

                            indices.Add(top + slice + 1);
                            indices.Add(bot + slice);
                            indices.Add(bot + slice + 1);
                        }
                    }
                }

                offset = vertices.Count;

                // Finish with the bottom end. Fill the collections.
                for (int stack = 0; stack <= EndStacks; stack++)
                {
                    double y      = 0;
                    double radius = Radius + side * Thickness / 2 * (1 - (double)stack / EndStacks);
                    int    top    = offset + (stack + 0) * (Slices + 1);
                    int    bot    = offset + (stack + 1) * (Slices + 1);

                    for (int slice = 0; slice <= Slices; slice++)
                    {
                        double theta = slice * 2 * Math.PI / Slices;
                        double x     = -radius *Math.Sin(theta);

                        double z = -radius *Math.Cos(theta);

                        vertices.Add(new Point3D(x, y, z));
                        normals.Add(new Vector3D(0, -side, 0));
                        textures.Add(new Point((double)slice / Slices,
                                               (1 - Fold) + Fold * stack / EndStacks));

                        if (stack < EndStacks && slice < Slices)
                        {
                            indices.Add(top + slice);
                            indices.Add(bot + slice);
                            indices.Add(top + slice + 1);

                            indices.Add(top + slice + 1);
                            indices.Add(bot + slice);
                            indices.Add(bot + slice + 1);
                        }
                    }
                }
            }
        }