Exemple #1
0
        public Sphere ComputeBoundingSphereNaive()
        {
            var pointPositions = PointAttributes.FindOrCreate <Vector3>("point_locations");

            //  FIRST PASS: Find 6 minima/maxima points
            BoundingBox box = new BoundingBox();

            box.Clear();
            foreach (Point point in Points)
            {
                box.ExtendBy(pointPositions[point]);
            }

            float maxRadiusSquare = 0.0f;

            foreach (Point point in Points)
            {
                Vector3 p            = pointPositions[point];
                float   radiusSquare = box.Center.DistanceSquared(pointPositions[point]);
                if (radiusSquare > maxRadiusSquare)
                {
                    maxRadiusSquare = radiusSquare;
                }
            }
            return(new Sphere(box.Center, (float)System.Math.Sqrt(maxRadiusSquare)));
        }
Exemple #2
0
        public void Noise(NoiseGenerator noise)
        {
            ComputePolygonNormals();
            ComputePointNormals("point_normals_smooth");

            var pointLocations = PointAttributes.FindOrNull <Vector3>("point_locations");
            var pointNormals   = PointAttributes.FindOrNull <Vector3>("point_normals_smooth");

            foreach (Point point in Points)
            {
                if (
                    (pointLocations != null) &&
                    pointLocations.ContainsKey(point)
                    )
                {
                    var pos    = pointLocations[point];
                    var normal = Vector3.Normalize(pointLocations[point]);
                    pointLocations[point] = pos + noise.Generate(pos) * normal;
                }
            }

            ComputePolygonCentroids();
            ComputePolygonNormals();
            SmoothNormalize("corner_normals", "polygon_normals", (2.0f * (float)System.Math.PI));
            BuildEdges();
        }
Exemple #3
0
        public Polygon MakePolygon(List <int> pointIndices)
        {
            Polygon polygon = MakePolygon();

            /*  Sanity check  */
            for (int i = 0; i < pointIndices.Count; ++i)
            {
                for (int j = 0; j < pointIndices.Count; ++j)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (pointIndices[i] == pointIndices[j])
                    {
                        throw new System.Exception("duplicate polygon corner point indices");
                    }
                }
            }

            foreach (int pointIndex in pointIndices)
            {
                Point point = Points[pointIndex];
                polygon.MakeCorner(point);
            }
#if DEBUG_CHECK
            var pointLocations = PointAttributes.Find <Vector3>("point_locations");
            if (polygon.DebugCheck(pointLocations) == false)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = pointIndices.Length - 1; i >= 0; --i)
                {
                    sb.Append(pointIndices[i].ToString());
                    if (i > 0)
                    {
                        sb.Append(", ");
                    }
                }
                Logger.Log(sb.ToString() + ");");
            }
            else
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = 0; i < pointIndices.Length; i++)
                {
                    sb.Append(pointIndices[i].ToString());
                    if (i < pointIndices.Length - 1)
                    {
                        sb.Append(", ");
                    }
                }
                Logger.Log(sb.ToString() + ");");
            }
#endif
            return(polygon);
        }
Exemple #4
0
        /// Compute polygon centroids based on point position attributes
        /// Results are stored in internally stored attribute map named "polygon_centroids".
        public void ComputePolygonCentroids()
        {
            var polygonCentroids = PolygonAttributes.FindOrCreate <Vector3>("polygon_centroids");
            var pointLocations   = PointAttributes.Find <Vector3>("point_locations");

            polygonCentroids.Clear();
            foreach (Polygon polygon in Polygons)
            {
                polygon.ComputeCentroid(polygonCentroids, pointLocations);
            }
        }
Exemple #5
0
        /// Compute polygon normals based on point position attributes.
        /// Results are stored in internally stored attribute map named "polygon_normals".
        public void ComputePolygonNormals()
        {
            var polygonNormals = PolygonAttributes.FindOrCreate <Vector3>("polygon_normals");
            var pointLocations = PointAttributes.Find <Vector3>("point_locations");

            polygonNormals.Clear();
            foreach (Polygon polygon in Polygons)
            {
                polygon.ComputeNormal(polygonNormals, pointLocations);
            }
        }
Exemple #6
0
        public Point MakePoint(Vector3 p)
        {
            Point point          = MakePoint();
            var   pointPositions = PointAttributes.FindOrCreate <Vector3>("point_locations");

#if ENABLE_CREATE_TRANSFORM
            pointPositions[point] = MakePointTransform * new Vector3(p.x, p.y, p.z);
#else
            pointPositions[point] = new Vector3(p.X, p.Y, p.Z);
#endif
            return(point);
        }
Exemple #7
0
        /// \brief Constructs a new Point and assosiates a position attribute for it.
        public Point MakePoint(float x, float y, float z)
        {
            Point point          = MakePoint();
            var   pointPositions = PointAttributes.FindOrCreate <Vector3>("point_locations");

#if ENABLE_CREATE_TRANSFORM
            pointPositions[point] = MakePointTransform * new Vector3(x, y, z);
#else
            pointPositions[point] = new Vector3(x, y, z);
#endif
            return(point);
        }
Exemple #8
0
        /// \brief Constructs a new Point and assosiates a position attribute for it.
        public Point MakePoint(double x, double y, double z)
        {
            Point point          = MakePoint();
            var   pointPositions = PointAttributes.FindOrCreate <Vector3>("point_locations");

#if ENABLE_CREATE_TRANSFORM
            pointPositions[point] = MakePointTransform * Vector3((float)x, (float)y, (float)z);
#else
            pointPositions[point] = new Vector3((float)x, (float)y, (float)z);
#endif
            return(point);
        }
Exemple #9
0
        /// \warning This is inefficient! Try not to use this
        public void MergePoints()
        {
            Dictionary <Point, Point> removedPointToRemainingPoint = new Dictionary <Point, Point>();
            var   pointLocations = PointAttributes.FindOrNull <Vector3>("point_locations");
            float pointEpsilon   = 0.0000001f;

            //  Merge points
            foreach (Point p1 in Points)
            {
                Vector3 pos1 = pointLocations[p1];

                bool alreadyUsed = false;
                foreach (Point p2 in Points)
                {
                    if (p1 == p2)
                    {
                        continue;
                    }
                    if (removedPointToRemainingPoint.ContainsKey(p1))
                    {
                        continue;
                    }
                    Vector3 pos2 = pointLocations[p2];

                    float distanceSquared = pos1.DistanceSquared(pos2);

                    if (distanceSquared < pointEpsilon)
                    {
                        if (alreadyUsed)
                        {
                            System.Diagnostics.Debug.WriteLine("point already used");
                        }
                        removedPointToRemainingPoint[p2] = p1;
                        alreadyUsed = true;
                    }
                }
            }

            //  Merge polygons
            foreach (var polygon in Polygons)
            {
                polygon.ReplacePoints(removedPointToRemainingPoint);
            }

            foreach (var point in removedPointToRemainingPoint.Keys)
            {
                Points.Remove(point);
            }
        }
Exemple #10
0
        public void ComputePointNormals(string mapName)
        {
            var pointNormals   = PointAttributes.FindOrCreate <Vector3>(mapName);
            var polygonNormals = PolygonAttributes.Find <Vector3>("polygon_normals");

            pointNormals.Clear();
            foreach (Point point in Points)
            {
                Vector3 normalSum = new Vector3(0.0f, 0.0f, 0.0f);
                foreach (Corner corner in point.Corners)
                {
                    normalSum += polygonNormals[corner.Polygon];
                }
                Vector3 averageNormal = normalSum / (float)point.Corners.Count;
                pointNormals[point] = averageNormal;
            }
        }
Exemple #11
0
        public void Transform(Matrix4 transform)
        {
            Matrix4 inverseTransposeTransform = Matrix4.Transpose(Matrix4.Invert(transform));

            //  Check.. Did I forget something?
            //  \todo Mark each attributemap how they should be transformed
            var polygonCentroids = PolygonAttributes.FindOrNull <Vector3>("polygon_centroids");
            var polygonNormals   = PolygonAttributes.FindOrNull <Vector3>("polygon_normals");
            var pointLocations   = PointAttributes.FindOrNull <Vector3>("point_locations");
            var pointNormals     = PointAttributes.FindOrNull <Vector3>("point_normals");
            var cornerNormals    = CornerAttributes.FindOrNull <Vector3>("corner_normals");

            //  Make copies of old points
            foreach (Point point in Points)
            {
                if (pointLocations != null && pointLocations.ContainsKey(point))
                {
                    pointLocations[point] = transform.TransformPoint(pointLocations[point]);
                }
                if (pointNormals != null && pointNormals.ContainsKey(point))
                {
                    pointNormals[point] = inverseTransposeTransform.TransformDirection(pointNormals[point]);
                }
            }
            foreach (Polygon polygon in Polygons)
            {
                if (polygonCentroids != null && polygonCentroids.ContainsKey(polygon))
                {
                    polygonCentroids[polygon] = transform.TransformPoint(polygonCentroids[polygon]);
                }
                if (polygonNormals != null && polygonNormals.ContainsKey(polygon))
                {
                    polygonNormals[polygon] = inverseTransposeTransform.TransformDirection(polygonNormals[polygon]);
                }
                if (cornerNormals != null)
                {
                    foreach (Corner corner in polygon.Corners)
                    {
                        if (cornerNormals.ContainsKey(corner))
                        {
                            cornerNormals[corner] = inverseTransposeTransform.TransformDirection(cornerNormals[corner]);
                        }
                    }
                }
            }
        }
Exemple #12
0
        public HeightField(float[,] heights, float scaleX, float scaleZ)
        {
            var pointLocations = PointAttributes.FindOrCreate <Vector3>("point_locations");
            var pointTexcoords = PointAttributes.FindOrCreate <Vector2>("point_texcoords");

            //  Generate vertices
            int xCount = heights.GetLength(0);
            int zCount = heights.GetLength(1);

            for (int x = 0; x < xCount; x++)
            {
                float s  = (float)x / (float)xCount;
                float xP = (float)x * scaleX;
                for (int z = 0; z < zCount; z++)
                {
                    float t  = (float)z / (float)zCount;
                    float zP = (float)z * scaleZ;
                    float yP = heights[x, z];

                    var point = MakePoint();

                    pointLocations[point] = new Vector3(xP, yP, zP);
                    pointTexcoords[point] = new Vector2(s, t);

                    Points[x * zCount + z] = point;
                }
            }

            //  Generate quads
            for (int x = 0; x < xCount - 1; x++)
            {
                for (int z = 0; z < zCount - 1; z++)
                {
                    var pol = MakePolygon();
                    pol.MakeCorner(Points[(x + 1) * zCount + z]);
                    pol.MakeCorner(Points[(x + 1) * zCount + z + 1]);
                    pol.MakeCorner(Points[(x) * zCount + z + 1]);
                    pol.MakeCorner(Points[(x) * zCount + z]);
                }
            }

            ComputePolygonCentroids();
            ComputePolygonNormals();
            SmoothNormalize("corner_normals", "polygon_normals", (2.0f * (float)System.Math.PI));
        }
Exemple #13
0
        public Corner ClosestPolygonCorner(Polygon polygon, Vector3 position)
        {
            Corner closestCorner          = null;
            float  closestDistanceSquared = float.MaxValue;
            var    pointLocations         = PointAttributes.Find <Vector3>("point_locations");

            foreach (Corner corner in polygon.Corners)
            {
                Vector3 cornerLocation  = pointLocations[corner.Point];
                float   distanceSquared = cornerLocation.DistanceSquared(position);
                if (distanceSquared < closestDistanceSquared)
                {
                    closestDistanceSquared = distanceSquared;
                    closestCorner          = corner;
                }
            }

            return(closestCorner);
        }
Exemple #14
0
        private bool AllInSphere(Vector3 center, ref float radius)
        {
            var   pointPositions     = PointAttributes.FindOrCreate <Vector3>("point_locations");
            float r2                 = radius * radius;
            float maxDistanceSquared = 0.0f;

            foreach (Point point in Points)
            {
                float distanceSquared = center.DistanceSquared(pointPositions[point]);
                if (distanceSquared > r2)
                {
                    return(false);
                }
                if (distanceSquared > maxDistanceSquared)
                {
                    maxDistanceSquared = distanceSquared;
                }
            }
            radius = (float)System.Math.Sqrt(maxDistanceSquared);
            return(true);
        }
Exemple #15
0
        /// \brief Construct a new Polygon from a given set of Point indices
        /// \param pointIndices Indices to Points that are connected to the new Polygon</param>
        /// \return Newly created Polygon
        public Polygon MakePolygon(params int[] pointIndices)
        {
            Polygon polygon = MakePolygon();

            foreach (int pointIndex in pointIndices)
            {
                Point point = Points[pointIndex];
                polygon.MakeCorner(point);
            }
#if DEBUG_CHECK
            var pointLocations = PointAttributes.Find <Vector3>("point_locations");
            if (polygon.DebugCheck(pointLocations) == false)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = pointIndices.Length - 1; i >= 0; --i)
                {
                    sb.Append(pointIndices[i].ToString());
                    if (i > 0)
                    {
                        sb.Append(", ");
                    }
                }
                Logger.Log(sb.ToString() + ");");
            }
            else
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = 0; i < pointIndices.Length; i++)
                {
                    sb.Append(pointIndices[i].ToString());
                    if (i < pointIndices.Length - 1)
                    {
                        sb.Append(", ");
                    }
                }
                Logger.Log(sb.ToString() + ");");
            }
#endif
            return(polygon);
        }
Exemple #16
0
        public void SmoothAverage(
            string cornerAttribute,
            string pointNormalName
            )
        {
            var cornerAttributes = CornerAttributes.FindOrCreate <Vector4>(cornerAttribute);
            var cornerNormals    = CornerAttributes.FindOrCreate <Vector3>("corner_normals");
            var pointNormals     = PointAttributes.Find <Vector3>(pointNormalName);

            var newCornerAttributes = CornerAttributes.FindOrCreate <Vector4>("temp");

            foreach (Polygon polygon in Polygons)
            {
                polygon.SmoothAverage(
                    newCornerAttributes,
                    cornerAttributes,
                    cornerNormals,
                    pointNormals
                    );
            }
            CornerAttributes.Replace(cornerAttribute, "temp");
        }
Exemple #17
0
        public Cube(Vector3 size, IVector3 div, float p)
        {
            int x;
            int y;
            int z;

            MakeInfo info = new MakeInfo(0.5f * size, div, p);

            info.pointLocations   = PointAttributes.FindOrCreate <Vector3>("point_locations");
            info.pointNormals     = PointAttributes.FindOrCreate <Vector3>("point_normals");
            info.pointTexcoords   = PointAttributes.FindOrCreate <Vector2>("point_texcoords");
            info.cornerNormals    = CornerAttributes.FindOrCreate <Vector3>("corner_normals");
            info.cornerTexcoords  = CornerAttributes.FindOrCreate <Vector2>("corner_texcoords");
            info.polygonCentroids = PolygonAttributes.FindOrCreate <Vector3>("polygon_centroids");
            info.polygonNormals   = PolygonAttributes.FindOrCreate <Vector3>("polygon_normals");

            //  Generate vertices
            //  Top and bottom
            for (x = -info.Div.X; x <= info.Div.X; x++)
            {
                float relX = 0.5f + (float)x / info.Size.X;
                for (z = -info.Div.Z; z <= info.Div.Z; z++)
                {
                    float relZ = 0.5f + (float)z / info.Size.Z;
                    MakePoint(info, x, info.Div.Y, z, Vector3.UnitY, relX, relZ);
                    MakePoint(info, x, -info.Div.Y, z, -Vector3.UnitY, relX, relZ);
                }
                for (y = -info.Div.Y; y <= info.Div.Y; y++)
                {
                    float relY = 0.5f + (float)y / info.Size.Y;

                    MakePoint(info, x, y, info.Div.Z, Vector3.UnitZ, relX, relY);
                    MakePoint(info, x, y, -info.Div.Z, -Vector3.UnitZ, relX, relY);
                }
            }

            //  Left and right
            for (z = -info.Div.Z; z <= info.Div.Z; z++)
            {
                float relZ = 0.5f + (float)z / info.Size.Z;
                for (y = -info.Div.Y; y <= info.Div.Y; y++)
                {
                    float relY = 0.5f + (float)y / info.Size.Y;
                    MakePoint(info, info.Div.X, y, z, Vector3.UnitX, relY, relZ);
                    MakePoint(info, -info.Div.X, y, z, -Vector3.UnitX, relY, relZ);
                }
            }

            //  Generate quads
            //  Top and bottom
            for (x = -info.Div.X; x < info.Div.X; x++)
            {
                float relX1 = 0.5f + (float)x / info.Size.X;
                float relX2 = 0.5f + (float)(x + 1) / info.Size.X;
                for (z = -info.Div.Z; z < info.Div.Z; z++)
                {
                    float relZ1 = 0.5f + (float)z / info.Size.Z;
                    float relZ2 = 0.5f + (float)(z + 1) / info.Size.Z;
                    var   top   = MakePolygon();
                    MakeCorner(info, top, x + 1, info.Div.Y, z, Vector3.UnitY, relX2, relZ1);
                    MakeCorner(info, top, x + 1, info.Div.Y, z + 1, Vector3.UnitY, relX2, relZ2);
                    MakeCorner(info, top, x, info.Div.Y, z + 1, Vector3.UnitY, relX1, relZ2);
                    MakeCorner(info, top, x, info.Div.Y, z, Vector3.UnitY, relX1, relZ1);
                    var bottom = MakePolygon();
                    MakeCorner(info, bottom, x, -info.Div.Y, z, -Vector3.UnitY, relX1, relZ1);
                    MakeCorner(info, bottom, x, -info.Div.Y, z + 1, -Vector3.UnitY, relX1, relZ2);
                    MakeCorner(info, bottom, x + 1, -info.Div.Y, z + 1, -Vector3.UnitY, relX2, relZ2);
                    MakeCorner(info, bottom, x + 1, -info.Div.Y, z, -Vector3.UnitY, relX2, relZ1);
                    info.polygonNormals[top]    = Vector3.UnitY;
                    info.polygonNormals[bottom] = -Vector3.UnitY;
                }
                for (y = -info.Div.Y; y < info.Div.Y; y++)
                {
                    float relY1 = 0.5f + (float)y / info.Size.Y;
                    float relY2 = 0.5f + (float)(y + 1) / info.Size.Y;
                    var   back  = MakePolygon();
                    MakeCorner(info, back, x, y, info.Div.Z, Vector3.UnitZ, relX1, relY1);
                    MakeCorner(info, back, x, y + 1, info.Div.Z, Vector3.UnitZ, relX1, relY2);
                    MakeCorner(info, back, x + 1, y + 1, info.Div.Z, Vector3.UnitZ, relX2, relY2);
                    MakeCorner(info, back, x + 1, y, info.Div.Z, Vector3.UnitZ, relX2, relY1);
                    var front = MakePolygon();
                    MakeCorner(info, front, x + 1, y, -info.Div.Z, -Vector3.UnitZ, relX2, relY1);
                    MakeCorner(info, front, x + 1, y + 1, -info.Div.Z, -Vector3.UnitZ, relX2, relY2);
                    MakeCorner(info, front, x, y + 1, -info.Div.Z, -Vector3.UnitZ, relX1, relY2);
                    MakeCorner(info, front, x, y, -info.Div.Z, -Vector3.UnitZ, relX1, relY1);
                    info.polygonNormals[back]  = Vector3.UnitZ;
                    info.polygonNormals[front] = -Vector3.UnitZ;
                }
            }

            //  Left and right
            for (z = -info.Div.Z; z < info.Div.Z; z++)
            {
                float relZ1 = 0.5f + (float)z / info.Size.Z;
                float relZ2 = 0.5f + (float)(z + 1) / info.Size.Z;
                for (y = -info.Div.Y; y < info.Div.Y; y++)
                {
                    float relY1 = 0.5f + (float)y / info.Size.Y;
                    float relY2 = 0.5f + (float)(y + 1) / info.Size.Y;
                    var   right = MakePolygon();
                    MakeCorner(info, right, info.Div.X, y, z, Vector3.UnitX, relY1, relZ1);
                    MakeCorner(info, right, info.Div.X, y, z + 1, Vector3.UnitX, relY1, relZ2);
                    MakeCorner(info, right, info.Div.X, y + 1, z + 1, Vector3.UnitX, relY2, relZ2);
                    MakeCorner(info, right, info.Div.X, y + 1, z, Vector3.UnitX, relY2, relZ1);
                    var left = MakePolygon();
                    MakeCorner(info, left, -info.Div.X, y + 1, z, -Vector3.UnitX, relY2, relZ1);
                    MakeCorner(info, left, -info.Div.X, y + 1, z + 1, -Vector3.UnitX, relY2, relZ2);
                    MakeCorner(info, left, -info.Div.X, y, z + 1, -Vector3.UnitX, relY1, relZ2);
                    MakeCorner(info, left, -info.Div.X, y, z, -Vector3.UnitX, relY1, relZ1);
                    info.polygonNormals[right] = Vector3.UnitX;
                    info.polygonNormals[left]  = -Vector3.UnitX;
                }
            }
            ComputePolygonCentroids();
        }
Exemple #18
0
        public SuperEllipsoid(Vector3 radius, double n1, double n2, int sliceCount, int stackDivision)
        {
            MakeInfo info = new MakeInfo(radius, n1, n2, sliceCount, stackDivision);

            info.pointLocations   = PointAttributes.FindOrCreate <Vector3>("point_locations");
            info.pointNormals     = PointAttributes.FindOrCreate <Vector3>("point_normals");
            info.pointTexcoords   = PointAttributes.FindOrCreate <Vector2>("point_texcoords");
            info.polygonCentroids = PolygonAttributes.FindOrCreate <Vector3>("polygon_centroids");
            info.polygonNormals   = PolygonAttributes.FindOrCreate <Vector3>("polygon_normals");
            info.cornerTexcoords  = CornerAttributes.FindOrCreate <Vector2>("corner_texcoords");

            int slice;
            int stack;

            for (slice = 0; slice < sliceCount; ++slice)
            {
                double relSlice = (double)(slice) / (double)(sliceCount);
                for (stack = -stackDivision; stack <= stackDivision; ++stack)
                {
                    double relStack = (double)(stack) / (double)(stackDivision + 1);
                    Point  point    = MakePoint(info, relSlice, relStack);

                    info.points.Add(point);
                }
            }
            info.bottom = MakePoint(info, 0.5f, -1.0f);
            info.top    = MakePoint(info, 0.5f, 1.0f);

            #region bottom fan
            {
                for (slice = 0; slice < sliceCount; ++slice)
                {
                    int nextSlice  = (slice + 1);
                    int stackBase0 = 0;

                    double relSlice = ((double)(slice) + 0.5) / (double)(sliceCount);
                    double relStack = -1.0 + (0.5 / (double)(stackDivision + 1));

                    Point centroid = MakePoint(info, relSlice, relStack);

                    var polygon = MakePolygon();
#if CCW
                    MakeCorner(info, polygon, slice, stackBase0);
                    MakeCorner(info, polygon, slice, info.stackBase0Bottom);
                    MakeCorner(info, polygon, nextSlice, stackBase0);
#else
                    MakeCorner(info, polygon, nextSlice, stackBase0);
                    MakeCorner(info, polygon, slice, info.stackBase0Bottom);
                    MakeCorner(info, polygon, slice, stackBase0);
#endif

                    info.polygonCentroids[polygon] = info.pointLocations[centroid];
                    info.polygonNormals  [polygon] = info.pointNormals  [centroid];
                }
            }
            #endregion

            #region middle quads, bottom up
            for (
                stack = -stackDivision;
                stack < stackDivision;
                ++stack
                )
            {
                int stackBase0     = stack + stackDivision;
                int nextStackBase0 = stackBase0 + 1;

                double relStack = ((double)(stack) + 0.5) / (double)(stackDivision + 1);

                for (slice = 0; slice < sliceCount; ++slice)
                {
                    int    nextSlice = (slice + 1);
                    double relSlice  = ((double)(slice) + 0.5) / (double)(sliceCount);
                    Point  centroid  = MakePoint(info, relSlice, relStack);

                    var polygon = MakePolygon();
#if CCW
                    MakeCorner(info, polygon, nextSlice, nextStackBase0);
                    MakeCorner(info, polygon, slice, nextStackBase0);
                    MakeCorner(info, polygon, slice, stackBase0);
                    MakeCorner(info, polygon, nextSlice, stackBase0);
#else
                    MakeCorner(info, polygon, nextSlice, stackBase0);
                    MakeCorner(info, polygon, slice, stackBase0);
                    MakeCorner(info, polygon, slice, nextStackBase0);
                    MakeCorner(info, polygon, nextSlice, nextStackBase0);
#endif

                    info.polygonCentroids[polygon] = info.pointLocations[centroid];
                    info.polygonNormals  [polygon] = info.pointNormals  [centroid];
                }
            }
            #endregion

            #region top fan
            for (slice = 0; slice < sliceCount; ++slice)
            {
                int nextSlice  = (slice + 1);
                int stackBase0 = stackDivision + stackDivision;

                double relSlice = ((double)(slice) + 0.5) / (double)(sliceCount);
                double relStack = 1.0 - (0.5 / (double)(stackDivision + 1));

                Point centroid = MakePoint(info, relSlice, relStack);

                var polygon = MakePolygon();
#if CCW
                MakeCorner(info, polygon, slice, info.stackBase0Top);
                MakeCorner(info, polygon, slice, stackBase0);
                MakeCorner(info, polygon, nextSlice, stackBase0);
#else
                MakeCorner(info, polygon, nextSlice, stackBase0);
                MakeCorner(info, polygon, slice, stackBase0);
                MakeCorner(info, polygon, slice, info.stackBase0Top);
#endif

                info.polygonCentroids[polygon] = info.pointLocations[centroid];
                info.polygonNormals  [polygon] = info.pointNormals  [centroid];
            }
            #endregion
        }
Exemple #19
0
        public Disc(
            double outerRadius,
            double innerRadius,
            int sliceCount,
            int stackCount
            )
        {
            MakeInfo info = new MakeInfo(outerRadius, innerRadius, sliceCount, stackCount);

            info.pointLocations   = PointAttributes.FindOrCreate <Vector3>("point_locations");
            info.pointNormals     = PointAttributes.FindOrCreate <Vector3>("point_normals");
            info.pointTexcoords   = PointAttributes.FindOrCreate <Vector2>("point_texcoords");
            info.polygonCentroids = PolygonAttributes.FindOrCreate <Vector3>("polygon_centroids");
            info.polygonNormals   = PolygonAttributes.FindOrCreate <Vector3>("polygon_normals");
            info.cornerNormals    = CornerAttributes.FindOrCreate <Vector3>("corner_normals");
            info.cornerTexcoords  = CornerAttributes.FindOrCreate <Vector2>("corner_texcoords");

            /*  Make points  */
            for (int stack = 0; stack < stackCount; ++stack)
            {
                double relStack = (stackCount == 1) ? 1.0 : (double)stack / (double)(stackCount - 1);
                for (int slice = 0; slice <= sliceCount; ++slice)
                {
                    double relSlice = (double)slice / (double)sliceCount;

                    info.points[new KeyValuePair <int, int>(slice, stack)] = MakePoint(info, relSlice, relStack);
                }
            }

            /*  Special case without center point  */
            if (stackCount == 1)
            {
                Polygon polygon = MakePolygon();
                info.polygonCentroids[polygon] = Vector3.Zero;
                info.polygonNormals  [polygon] = Vector3.UnitZ;

                for (int slice = sliceCount - 1; slice >= 0; --slice)
                {
                    MakeCorner(info, polygon, slice, 0);
                }
                return;
            }

            /*  Make center point if needed  */
            if (innerRadius == 0.0f)
            {
                info.center = MakePoint(0.0, 0.0, 0.0);
            }

            /*  Quads/triangles  */
            for (int stack = 0; stack < stackCount - 1; ++stack)
            {
                double relStackCentroid = (stackCount == 1) ? 0.5 : (double)stack / (double)(stackCount - 1);

                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    double  relSliceCentroid = ((double)(slice) + 0.5) / (double)(sliceCount);
                    Point   centroid         = MakePoint(info, relSliceCentroid, relStackCentroid);
                    Polygon polygon          = MakePolygon();

                    info.polygonCentroids[polygon] = info.pointLocations[centroid];
                    info.polygonNormals  [polygon] = Vector3.UnitZ;
                    if ((stack == 0) && (innerRadius == 0.0))
                    {
                        Corner tip = MakeCorner(info, polygon, slice, stack);
                        MakeCorner(info, polygon, slice + 1, stack + 1);
                        MakeCorner(info, polygon, slice, stack + 1);

                        Vector2 t1 = info.pointTexcoords[GetPoint(info, slice, stack)];
                        Vector2 t2 = info.pointTexcoords[GetPoint(info, slice + 1, stack)];
                        Vector2 averageTexcoord = (t1 + t2) / 2.0f;
                        info.cornerTexcoords[tip] = averageTexcoord;
                    }
                    else
                    {
                        MakeCorner(info, polygon, slice + 1, stack + 1);
                        MakeCorner(info, polygon, slice, stack + 1);
                        MakeCorner(info, polygon, slice, stack);
                        MakeCorner(info, polygon, slice + 1, stack);
                    }
                }
            }
            BuildEdges();
        }
Exemple #20
0
        public Tube(
            IParametricCurve curve,
            float radius,
            int sliceCount,
            int stackCount
            )
        {
            float tStep = 1.0f / 512.0f;

            //  Compute initial N
            Vector3 pos      = curve.PositionAt(0.0f);
            Vector3 posNext  = curve.PositionAt(0.0f + tStep);
            Vector3 posNext2 = curve.PositionAt(0.0f + tStep + tStep);
            Vector3 d1       = posNext - pos;
            Vector3 d2       = (posNext2 - posNext) - d1;
            Vector3 T        = Vector3.Normalize(d1);
            Vector3 N        = Vector3.Normalize(d2);
            Vector3 B        = Vector3.Normalize(Vector3.Cross(T, N));

            N = Vector3.Normalize(Vector3.Cross(B, T));

            var pointLocations = PointAttributes.FindOrCreate <Vector3>("point_locations");
            var pointNormals   = PointAttributes.FindOrCreate <Vector3>("point_normals");
            var pointTexCoords = PointAttributes.FindOrCreate <Vector2>("point_texcoords");
            var cornerNormals  = CornerAttributes.FindOrCreate <Vector3>("corner_normals");
            //var cornerTexCoords     = CornerAttributes.FindOrCreate<Vector2>("corner_texcoords");

            /*  Other vertices  */
            List <Point> points = new List <Point>();

            for (int stack = 0; stack <= stackCount; ++stack)
            {
                float t = (float)stack / (float)stackCount;

                pos     = curve.PositionAt(t);
                posNext = curve.PositionAt(t + tStep);
                d1      = posNext - pos;
                T       = Vector3.Normalize(d1);
                B       = Vector3.Normalize(Vector3.Cross(T, N));
                N       = Vector3.Normalize(Vector3.Cross(B, T));

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

                    Vector3 v = pos;
                    v += N * sinPhi * radius;
                    v += B * cosPhi * radius;

                    Point point = MakePoint();

                    pointLocations[point] = v;
                    pointNormals  [point] = N * sinPhi + B * cosPhi;
                    pointTexCoords[point] = new Vector2(relPhi, t);

                    points.Add(point);
                }
            }

            /*  Bottom parts  */
            {
                Vector3 bottomPosition     = curve.PositionAt(0.0f);
                Vector3 bottomPositionNext = curve.PositionAt(tStep);
                Vector3 bottomTangent      = Vector3.Normalize(bottomPosition - bottomPositionNext);
                Polygon polygon            = MakePolygon();

                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    int stack        = 0;
                    int reverseSlice = sliceCount - 1 - slice;

                    Corner corner = polygon.MakeCorner(
                        points[(stack * (sliceCount)) + reverseSlice]
                        );

                    cornerNormals[corner] = bottomTangent;
                }
            }

            /*  Middle quads, t = 0 ... t = 1  */
            for (int stack = 0; stack < stackCount; ++stack)
            {
                int nextStack = stack + 1;

                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    int nextSlice = (slice + 1) % sliceCount;

                    MakePolygon(
                        points[(nextStack * (sliceCount)) + nextSlice],
                        points[(nextStack * (sliceCount)) + slice],
                        points[(stack * (sliceCount)) + slice],
                        points[(stack * (sliceCount)) + nextSlice]
                        );
                }
            }

            /*  Top parts  */
            {
                Vector3 topPosition     = curve.PositionAt(1.0f);
                Vector3 topPositionPrev = curve.PositionAt(1.0f - tStep);
                Vector3 topTangent      = Vector3.Normalize(topPosition - topPositionPrev);
                Polygon polygon         = MakePolygon();

                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    int stack = stackCount;

                    Corner corner = polygon.MakeCorner(
                        points[(stack * (sliceCount)) + slice]
                        );

                    cornerNormals[corner] = topTangent;
                }
            }
        }
Exemple #21
0
        /// \todo Accelerate by sorting along major axis
        public void Merge(Geometry other)
        {
            Dictionary <Point, Point> otherPointsToNewPoints = new Dictionary <Point, Point>();

            var   pointLocationsSelf  = PointAttributes.FindOrNull <Vector3>("point_locations");
            var   pointLocationsOther = other.PointAttributes.FindOrNull <Vector3>("point_locations");
            float pointEpsilon        = 0.0001f;

            //  Merge points
            foreach (Point otherPoint in other.Points)
            {
                Vector3 otherPosition = pointLocationsOther[otherPoint];

                bool existingPointCloseEnough = false;
                foreach (Point existingPoint in Points)
                {
                    Vector3 existingPosition = pointLocationsSelf[existingPoint];

                    float distanceSquared = existingPosition.DistanceSquared(otherPosition);

                    if (distanceSquared < pointEpsilon)
                    {
                        existingPointCloseEnough           = true;
                        otherPointsToNewPoints[otherPoint] = existingPoint;
                        break;
                    }
                }
                if (existingPointCloseEnough == false)
                {
                    otherPointsToNewPoints[otherPoint] = MakePoint(otherPosition);
                }
            }

            //  Merge polygons
            foreach (Polygon otherPolygon in other.Polygons)
            {
                //  Test if we can find at least single matching polygon
                Polygon matchingPolygon = null;
                foreach (Polygon existingPolygon in Polygons)
                {
                    //  Test that all other corners can be found
                    bool missingCorners = false;
                    foreach (Corner otherCorner in otherPolygon.Corners)
                    {
                        Point newPoint    = otherPointsToNewPoints[otherCorner.Point];
                        bool  cornerFound = false;
                        //  Find matching corner
                        foreach (Corner existingCorner in existingPolygon.Corners)
                        {
                            if (newPoint == existingCorner.Point)
                            {
                                cornerFound = true;
                                break;
                            }
                        }
                        //  No matching corner found, continue
                        if (cornerFound == false)
                        {
                            missingCorners = true;
                            break;
                        }
                    }
                    if (missingCorners == true)
                    {
                        continue;
                    }
                    //  No missing corners - polygons match
                    matchingPolygon = existingPolygon;
                    break;
                }

                if (matchingPolygon != null)
                {
                    //  There was a matching polygon, delete it and do not create new from other
                    RemovePolygon(matchingPolygon);
                    //Polygons.Remove(matchingPolygon);
                }
                else
                {
                    //  There was no match, add new from other
                    Polygon newPolygon = MakePolygon();
                    foreach (Corner otherCorner in otherPolygon.Corners)
                    {
                        Point otherPoint = otherCorner.Point;
                        Point newPoint   = otherPointsToNewPoints[otherPoint];
                        newPolygon.MakeCorner(newPoint);
                    }
                }
            }

            //  Finally, remove unused points
            HashSet <Point> usedPoints = new HashSet <Point>();

            foreach (Polygon polygon in Polygons)
            {
                foreach (Corner corner in polygon.Corners)
                {
                    usedPoints.Add(corner.Point);
                }
            }
            List <Point> pointsToRemove = new List <Point>();

            foreach (Point point in Points)
            {
                if (usedPoints.Contains(point) == false)
                {
                    pointsToRemove.Add(point);
                }
            }
            foreach (Point pointToRemove in pointsToRemove)
            {
                Points.Remove(pointToRemove);
            }
        }
Exemple #22
0
        public void MergeFast(Geometry other, Polygon thisPolygon, Polygon otherPolygon)
        {
            Dictionary <Point, Point> otherPointsToNewPoints = new Dictionary <Point, Point>();

            var   pointLocationsSelf  = PointAttributes.FindOrNull <Vector3>("point_locations");
            var   pointLocationsOther = other.PointAttributes.FindOrNull <Vector3>("point_locations");
            float pointEpsilon        = 0.0001f;

            //  Merge points
            foreach (Point otherPoint in other.Points)
            {
                Vector3 otherPosition = pointLocationsOther[otherPoint];

                bool existingPointCloseEnough = false;
                foreach (Corner existingCorner in thisPolygon.Corners)
                {
                    Point   existingPoint    = existingCorner.Point;
                    Vector3 existingPosition = pointLocationsSelf[existingPoint];

                    float distanceSquared = existingPosition.DistanceSquared(otherPosition);

                    if (distanceSquared < pointEpsilon)
                    {
                        existingPointCloseEnough           = true;
                        otherPointsToNewPoints[otherPoint] = existingPoint;
                        break;
                    }
                }
                if (existingPointCloseEnough == false)
                {
                    otherPointsToNewPoints[otherPoint] = MakePoint(otherPosition);
                }
            }

            RemovePolygon(thisPolygon);

            //  Merge polygons
            foreach (Polygon otherPolygon2 in other.Polygons)
            {
                if (otherPolygon != otherPolygon2)
                {
                    Polygon newPolygon = MakePolygon();
                    foreach (Corner otherCorner in otherPolygon.Corners)
                    {
                        Point otherPoint = otherCorner.Point;
                        Point newPoint   = otherPointsToNewPoints[otherPoint];
                        newPolygon.MakeCorner(newPoint);
                    }
                }
            }

            //  Finally, remove unused points
            HashSet <Point> usedPoints = new HashSet <Point>();

            foreach (Polygon polygon in Polygons)
            {
                foreach (Corner corner in polygon.Corners)
                {
                    usedPoints.Add(corner.Point);
                }
            }
            List <Point> pointsToRemove = new List <Point>();

            foreach (Point point in Points)
            {
                if (usedPoints.Contains(point) == false)
                {
                    pointsToRemove.Add(point);
                }
            }
            foreach (Point pointToRemove in pointsToRemove)
            {
                Points.Remove(pointToRemove);
            }
        }
Exemple #23
0
        public void Geodesate(float radius)
        {
            float rInv             = 1.0f / radius;
            var   polygonCentroids = PolygonAttributes.FindOrNull <Vector3>("polygon_centroids");
            var   polygonNormals   = PolygonAttributes.FindOrNull <Vector3>("polygon_normals");
            var   pointLocations   = PointAttributes.FindOrNull <Vector3>("point_locations");
            var   pointNormals     = PointAttributes.FindOrNull <Vector3>("point_normals");
            var   cornerNormals    = CornerAttributes.FindOrNull <Vector3>("corner_normals");

            //  Make copies of old points
            foreach (Point point in Points)
            {
                if (
                    (pointLocations != null) &&
                    pointLocations.ContainsKey(point)
                    )
                {
                    Vector3 newNormal = Vector3.Normalize(pointLocations[point]);
                    pointLocations[point] = radius * newNormal;
                    if (
                        (pointNormals != null) &&
                        pointNormals.ContainsKey(point)
                        )
                    {
                        pointNormals[point] = newNormal;
                    }
                }
            }
            foreach (Polygon polygon in Polygons)
            {
                if (
                    (polygonCentroids != null) &&
                    polygonCentroids.ContainsKey(polygon)
                    )
                {
                    Vector3 newNormalizedCentroid = Vector3.Normalize(polygonCentroids[polygon]);
                    polygonCentroids[polygon] = radius * newNormalizedCentroid;
                    if (
                        (polygonNormals != null) &&
                        polygonNormals.ContainsKey(polygon)
                        )
                    {
                        polygonNormals[polygon] = newNormalizedCentroid;
                    }
                }
                if (cornerNormals != null)
                {
                    foreach (Corner corner in polygon.Corners)
                    {
                        if (
                            cornerNormals.ContainsKey(corner)
                            )
                        {
                            if (pointNormals.ContainsKey(corner.Point))
                            {
                                cornerNormals[corner] = pointNormals[corner.Point];
                            }
                            else if (pointLocations.ContainsKey(corner.Point))
                            {
                                cornerNormals[corner] = pointLocations[corner.Point] * rInv;
                            }
                        }
                    }
                }
            }
        }
Exemple #24
0
        public Sphere ComputeBoundingSphereRitter()
        {
            //  An Efficient Bounding Sphere
            //  by Jack Ritter
            //  from "Graphics Gems", Academic Press, 1990

            //  Routine to calculate near-optimal bounding
            //  sphere over a set of points in 3D
            //  Code written by Jack Ritter and Lyle Rains.

            var pointPositions = PointAttributes.FindOrCreate <Vector3>("point_locations");

            //  FIRST PASS: Find 6 minima/maxima points
            Vector3 xmin, xmax, ymin, ymax, zmin, zmax;

            xmin = ymin = zmin = Vector3.MaxValue;
            xmax = ymax = zmax = Vector3.MinValue;
            foreach (Point point in Points)
            {
                Vector3 p = pointPositions[point];
                if (p.X < xmin.X)
                {
                    xmin = p;
                }
                if (p.X > xmax.X)
                {
                    xmax = p;
                }
                if (p.Y < ymin.Y)
                {
                    ymin = p;
                }
                if (p.Y > ymax.Y)
                {
                    ymax = p;
                }
                if (p.Z < zmin.Z)
                {
                    zmin = p;
                }
                if (p.Z > zmax.Z)
                {
                    zmax = p;
                }
            }

            //  Set span.X = distance between the 2 points xmin & xmax (squared)
            Vector3 span;
            Vector3 d;

            d.X    = xmax.X - xmin.X;
            d.Y    = xmax.Y - xmin.Y;
            d.Z    = xmax.Z - xmin.Z;
            span.X = d.LengthSquared;

            //  Same for Y & Z spans
            d.X    = ymax.X - ymin.X;
            d.Y    = ymax.Y - ymin.Y;
            d.Z    = ymax.Z - ymin.Z;
            span.Y = d.LengthSquared;

            d.X    = zmax.X - zmin.X;
            d.Y    = zmax.Y - zmin.Y;
            d.Z    = zmax.Z - zmin.Z;
            span.Z = d.LengthSquared;

            //  Set points dia1 & dia2 to the maximally separated pair
            Vector3 dia1    = xmin;
            Vector3 dia2    = xmax; //  Assume xspan biggest
            float   maxspan = span.X;

            if (span.Y > maxspan)
            {
                maxspan = span.Y;
                dia1    = ymin;
                dia2    = ymax;
            }
            if (span.Z > maxspan)
            {
                dia1 = zmin;
                dia2 = zmax;
            }

            //  dia1, dia2 is a diameter of initial sphere
            //  Calculate initial center
            Vector3 cen = (dia1 + dia2) / 2.0f;

            //  Calculate initial radius^2 and radius
            d = dia2 - cen;  //  Radius vector
            float rad_sq = d.LengthSquared;;
            float rad    = d.LengthSquared;

            //  SECOND PASS: Increment current sphere
            foreach (Point point in Points)
            {
                Vector3 p = pointPositions[point];
                d = p - cen;
                float old_to_p_sq = d.LengthSquared;

                //  Do r^2 test first
                if (old_to_p_sq > rad_sq)
                {
                    //  This point is outside of current sphere
                    float old_to_p = (float)System.Math.Sqrt(old_to_p_sq);

                    //  Calc radius of new sphere
                    rad = (rad + old_to_p) / 2.0f;

                    //  For next r^2 compare
                    rad_sq = rad * rad;
                    float old_to_new = old_to_p - rad;

                    //  Calculate center of new sphere
                    cen = (rad * cen + old_to_new * p) / old_to_p;

                    //  Suppress if desired
#if false
                    System.Diagnostics.Debug.WriteLine(
                        " New sphere: cen,rad = "
                        + cen.ToString() + " "   + rad
                        );
#endif
                }
            }

            //  THIRD PASS: Adjust the sphere along major axis for potential improvements
            Sphere s = new Sphere(cen, rad);
            AdjustBoundingSphere(ref s, -Vector3.UnitX);
            AdjustBoundingSphere(ref s, Vector3.UnitX);
            AdjustBoundingSphere(ref s, -Vector3.UnitY);
            AdjustBoundingSphere(ref s, Vector3.UnitY);
            AdjustBoundingSphere(ref s, -Vector3.UnitZ);
            AdjustBoundingSphere(ref s, Vector3.UnitZ);

            return(s);
        }
Exemple #25
0
        public Cone(
            double minX,
            double maxX,
            double bottomRadius,
            double topRadius,
            bool useBottom,
            bool useTop,
            int sliceCount,
            int stackDivision
            )
        {
            MakeInfo info = new MakeInfo(minX, maxX, bottomRadius, topRadius, useBottom, useTop, sliceCount, stackDivision);

            info.pointLocations   = PointAttributes.FindOrCreate <Vector3>("point_locations");
            info.pointNormals     = PointAttributes.FindOrCreate <Vector3>("point_normals");
            info.pointTexcoords   = PointAttributes.FindOrCreate <Vector2>("point_texcoords");
            info.polygonCentroids = PolygonAttributes.FindOrCreate <Vector3>("polygon_centroids");
            info.polygonNormals   = PolygonAttributes.FindOrCreate <Vector3>("polygon_normals");
            info.cornerNormals    = CornerAttributes.FindOrCreate <Vector3>("corner_normals");
            info.cornerTexcoords  = CornerAttributes.FindOrCreate <Vector2>("corner_texcoords");

            /*  Other vertices  */
            for (int slice = 0; slice <= sliceCount; ++slice)
            {
                double relSlice = (double)slice / (double)sliceCount;
                for (int stack = -stackDivision - info.bottomNotSingular; stack <= stackDivision + info.topNotSingular; ++stack)
                {
                    double relStack = (double)stack / (double)(stackDivision + 1);

                    info.points[new KeyValuePair <int, int>(slice, stack)] = ConePoint(info, relSlice, relStack);
                }
            }

            /*  Bottom parts  */
            if (bottomRadius == 0.0)
            {
                info.bottom = MakePoint(minX, 0.0, 0.0);  /*  apex  */
                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    int     stack            = -stackDivision;      //  second last stack, bottom is -stackDivision - 1
                    double  relSliceCentroid = ((double)slice + 0.5) / (double)sliceCount;
                    double  relStackCentroid = -1.0 + (0.5 / (double)(stackDivision + 1));
                    Point   centroid         = ConePoint(info, relSliceCentroid, relStackCentroid);
                    Polygon polygon          = MakePolygon();

                    MakeCorner(info, polygon, slice + 1, stack);
                    MakeCorner(info, polygon, slice, stack);
                    Corner tip = MakeCorner(info, polygon, slice, -stackDivision - 1);

                    Vector3 n1            = info.pointNormals[GetPoint(info, slice, stack)];
                    Vector3 n2            = info.pointNormals[GetPoint(info, slice + 1, stack)];
                    Vector3 averageNormal = Vector3.Normalize(n1 + n2);
                    info.cornerNormals[tip] = averageNormal;

                    Vector2 t1 = info.pointTexcoords[GetPoint(info, slice, stack)];
                    Vector2 t2 = info.pointTexcoords[GetPoint(info, slice + 1, stack)];
                    Vector2 averageTexCoord = (t1 + t2) / 2.0f;
                    info.cornerTexcoords[tip] = averageTexCoord;

                    info.polygonCentroids[polygon] = info.pointLocations[centroid];
                    info.polygonNormals  [polygon] = info.pointNormals  [centroid];
                }
            }
            else
            {
                if (useBottom == true)
                {
                    Polygon polygon = MakePolygon();
                    info.polygonCentroids[polygon] = new Vector3((float)minX, 0.0f, 0.0f);
                    info.polygonNormals  [polygon] = new Vector3(-1.0f, 0.0f, 0.0f);

                    for (int slice = 0; slice < sliceCount; ++slice)
                    {
                        int reverseSlice = sliceCount - 1 - slice;

                        MakeCorner(info, polygon, reverseSlice, -stackDivision - 1, true);
                    }
                }
            }

            /*  Middle quads, bottom up  */
            for (
                int stack = -stackDivision - info.bottomNotSingular;
                stack < stackDivision + info.topNotSingular;
                ++stack
                )
            {
                double relStackCentroid = ((double)stack + 0.5) / (double)(stackDivision + 1);

                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    double relSliceCentroid = ((double)(slice) + 0.5) / (double)(sliceCount);

                    Point centroid = ConePoint(info, relSliceCentroid, relStackCentroid);

                    Polygon polygon = MakePolygon();
                    MakeCorner(info, polygon, slice + 1, stack + 1);
                    MakeCorner(info, polygon, slice, stack + 1);
                    MakeCorner(info, polygon, slice, stack);
                    MakeCorner(info, polygon, slice + 1, stack);

                    info.polygonCentroids[polygon] = info.pointLocations[centroid];
                    info.polygonNormals  [polygon] = info.pointNormals  [centroid];
                }
            }

            /*  Top parts  */
            if (topRadius == 0.0)
            {
                info.top = MakePoint(maxX, 0.0, 0.0);  /*  apex  */

                for (int slice = 0; slice < sliceCount; ++slice)
                {
                    int     stack            = stackDivision;
                    double  relSliceCentroid = ((double)(slice) + 0.5) / (double)(sliceCount);
                    double  relStackCentroid = 1.0 - (0.5 / (double)(stackDivision + 1));
                    Point   centroid         = ConePoint(info, relSliceCentroid, relStackCentroid);
                    Polygon polygon          = MakePolygon();

                    Corner tip = MakeCorner(info, polygon, slice, stackDivision + 1);
                    MakeCorner(info, polygon, slice, stack);
                    MakeCorner(info, polygon, slice + 1, stack);

                    Vector3 n1            = info.pointNormals[GetPoint(info, slice, stack)];
                    Vector3 n2            = info.pointNormals[GetPoint(info, slice + 1, stack)];
                    Vector3 averageNormal = Vector3.Normalize(n1 + n2);
                    info.cornerNormals[tip] = averageNormal;

                    Vector2 t1 = info.pointTexcoords[GetPoint(info, slice, stack)];
                    Vector2 t2 = info.pointTexcoords[GetPoint(info, slice + 1, stack)];
                    Vector2 averageTexcoord = (t1 + t2) / 2.0f;
                    info.cornerTexcoords[tip] = averageTexcoord;

                    info.polygonCentroids[polygon] = info.pointLocations[centroid];
                    info.polygonNormals  [polygon] = info.pointNormals  [centroid];
                }
            }
            else
            {
                if (useTop == true)
                {
                    Polygon polygon = MakePolygon();
                    info.polygonCentroids[polygon] = new Vector3((float)maxX, 0.0f, 0.0f);
                    info.polygonNormals  [polygon] = new Vector3(1.0f, 0.0f, 0.0f);

                    for (int slice = 0; slice < sliceCount; ++slice)
                    {
                        MakeCorner(info, polygon, slice, stackDivision + 1, true);
                    }
                }
            }

            //MergePoints();
        }