private static void AddCircleInZCross(MeshBuilder mb, Point3D centre, double radius, int div)
        {
            var points = MeshBuilder.GetCircle(div);

            var vectors = new Point3DCollection();
            var normals = new Vector3DCollection();
            var textures = new PointCollection();

            vectors.Add(new Point3D(centre.X, centre.Y, 0));
            normals.Add(new Vector3D(0, 0, 1));
            textures.Add(new Point(0.5, 0.5));

            for (int i = 0; i < points.Count - 1; i++)
            {
                vectors.Add(new Point3D(points[i].X * radius + centre.X, points[i].Y * radius + centre.Y, centre.Z));
                normals.Add(new Vector3D(0, 0, -1));
                textures.Add(new Point(points[i].X * 0.5 + 0.5, points[i].Y * 0.5 + 0.5));

                vectors.Add(new Point3D(points[i + 1].X * radius + centre.X, points[i + 1].Y * radius + centre.Y, centre.Z));
                normals.Add(new Vector3D(0, 0, 01));
                textures.Add(new Point(points[i + 1].X * 0.5 + 0.5, points[i + 1].Y * 0.5 + 0.5));
            }

            mb.AddTriangleFan(vectors, normals, textures);
        }
        public static MeshGeometry3D CreateRectangle(double height, double width)
        {
            var vertices = new Point3DCollection();
            var normals = new Vector3DCollection();
            var facets = new Int32Collection();
            var textureCoords = new PointCollection();
            vertices.Add(new Point3D(-width / 2, 0, -height / 2));
            vertices.Add(new Point3D(-width / 2, 0, height / 2));
            vertices.Add(new Point3D(width / 2, 0, -height / 2));
            vertices.Add(new Point3D(width / 2, 0, height / 2));

            normals.Add(new Vector3D(0, -1, 0));
            normals.Add(new Vector3D(0, -1, 0));
            normals.Add(new Vector3D(0, -1, 0));
            normals.Add(new Vector3D(0, -1, 0));

            textureCoords.Add(new Point(1,1));
            textureCoords.Add(new Point(1, 0));
            textureCoords.Add(new Point(0,1));
            textureCoords.Add(new Point(0,0));

            facets.Add(0); facets.Add(1); facets.Add(2); facets.Add(3); facets.Add(2); facets.Add(1);
            var rectangle = new MeshGeometry3D();
            rectangle.Positions = vertices;
            rectangle.Normals = normals;
            rectangle.TriangleIndices = facets;
            rectangle.TextureCoordinates = textureCoords;
            return rectangle;
        }
Example #3
0
 public static Vector3DCollection CombineVectorCollection(Vector3DCollection initialVectors, List<XbimVector3D> points)
 {
     var ret = new Vector3DCollection(initialVectors.Count + points.Count);
     foreach (var enumVector in initialVectors)
     {
         ret.Add(enumVector);
     }
     foreach (var enumPoint in points)
     {
         ret.Add(new Vector3D(enumPoint.X, enumPoint.Y, enumPoint.Z));
     }
     return ret;
 }
Example #4
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);
        }
        /// <summary>
        /// Calculates the normal vectors.
        /// </summary>
        /// <param name="positions">
        /// The positions.
        /// </param>
        /// <param name="triangleIndices">
        /// The triangle indices.
        /// </param>
        /// <returns>
        /// Collection of normal vectors.
        /// </returns>
        public static Vector3DCollection CalculateNormals(IList<Point3D> positions, IList<int> triangleIndices)
        {
            var normals = new Vector3DCollection(positions.Count);
            for (int i = 0; i < positions.Count; i++)
            {
                normals.Add(new Vector3D());
            }

            for (int i = 0; i < triangleIndices.Count; i += 3)
            {
                int index0 = triangleIndices[i];
                int index1 = triangleIndices[i + 1];
                int index2 = triangleIndices[i + 2];
                var p0 = positions[index0];
                var p1 = positions[index1];
                var p2 = positions[index2];
                Vector3D u = p1 - p0;
                Vector3D v = p2 - p0;
                Vector3D w = Vector3D.CrossProduct(u, v);
                w.Normalize();
                normals[index0] += w;
                normals[index1] += w;
                normals[index2] += w;
            }

            for (int i = 0; i < normals.Count; i++)
            {
                var w = normals[i];
                w.Normalize();
                normals[i] = w;
            }

            return normals;
        }
Example #6
0
 public static Vector3DCollection GetVectorCollection(List<XbimVector3D> points)
 {
     var ret = new Vector3DCollection(points.Count);
     foreach (var enumPoint in points)
     {
         ret.Add(new Vector3D(enumPoint.X, enumPoint.Y, enumPoint.Z));
     }
     return ret;
 }
Example #7
0
File: D3Object.cs Project: mnisl/OD
		public Vector3DCollection GenerateNormals() {
			Vector3DCollection vectors=new Vector3DCollection();
			Vector3D vector;
			for(int i=0;i<VertexNormals.Count;i++) {
				vector=new Vector3D(VertexNormals[i].Normal.X,VertexNormals[i].Normal.Y,VertexNormals[i].Normal.Z);
				vectors.Add(vector);
			}
			return vectors;
		}
        public static void AddGeometry(this ModelVisual3D visual, GeometryModel3D geometry)
        {
            if (visual.Content == null)
                visual.Content = geometry;
            else
            {
                if (visual.Content is Model3DGroup)
                {
                    GeometryModel3D m3d = (GeometryModel3D)((Model3DGroup)visual.Content).Children.First();
                    MeshGeometry3D main = (MeshGeometry3D)(m3d.Geometry);
                    MeshGeometry3D toAdd = (MeshGeometry3D)(geometry.Geometry);
                    Point3DCollection pc = new Point3DCollection(main.Positions.Count + toAdd.Positions.Count);
                    foreach (var pt in main.Positions) pc.Add(pt);
                    foreach (var pt in toAdd.Positions)
                    {
                        pc.Add(geometry.Transform.Transform(pt));
                    }
                    main.Positions = pc;

                    Vector3DCollection vc = new Vector3DCollection(main.Normals.Count + toAdd.Normals.Count);
                    foreach (var v in main.Normals) vc.Add(v);
                    foreach (var norm in toAdd.Normals) vc.Add(norm);
                    main.Normals = vc;

                    int maxIndices = main.Positions.Count; //we need to increment all indices by this amount
                    foreach (var i in toAdd.TriangleIndices) main.TriangleIndices.Add(i + maxIndices);
                    Int32Collection tc = new Int32Collection(main.TriangleIndices.Count + toAdd.TriangleIndices.Count);
                    foreach (var i in main.TriangleIndices) tc.Add(i);
                    foreach (var i in toAdd.TriangleIndices) tc.Add(i + maxIndices);
                    main.TriangleIndices = tc;

                }
                //it is not a group but now needs to be
                else
                {
                    Model3DGroup m3dGroup = new Model3DGroup();
                    m3dGroup.Children.Add(visual.Content);
                    m3dGroup.Children.Add(geometry);
                    visual.Content = m3dGroup;
                }
            }
        }
        public static void AddCylindarZ(this MeshBuilder mb, Point3D bottomCentre, double radius, double length, int div)
        {
            var points = MeshBuilder.GetCircle(div);

            var vectors = new Point3DCollection();
            var normals = new Vector3DCollection();
            var textures = new PointCollection();

            for (int i = 0; i < points.Count; i++)
            {
                var p = points[i];
                vectors.Add(new Point3D(p.X * radius + bottomCentre.X, p.Y * radius + bottomCentre.Y, bottomCentre.Z));
                vectors.Add(new Point3D(p.X * radius + bottomCentre.X, p.Y * radius + bottomCentre.Y, bottomCentre.Z + length));
                normals.Add(new Vector3D(0, 0, 1));
                normals.Add(new Vector3D(0, 0, 1));
                textures.Add(new Point((double)i / (div - 1), 0));
                textures.Add(new Point((double)i / (div - 1), 1));
            }

            mb.AddTriangleStrip(vectors, normals, textures);
        }
        public static void AddCircleInZCross(this MeshBuilder mb, Point3D centre, double radius, int div, bool reversed)
        {
            var points = MeshBuilder.GetCircle(div);

            var vectors = new Point3DCollection();
            var normals = new Vector3DCollection();
            var textures = new PointCollection();

            vectors.Add(centre);
            normals.Add(new Vector3D(0, 0, 1));
            textures.Add(new Point(0.5, 0.5));

            for (int i = 0; i < points.Count; i++)
            {
                var p = reversed ? points[points.Count - 1 - i] : points[i];
                vectors.Add(new Point3D(p.X * radius + centre.X, p.Y * radius + centre.Y, centre.Z));
                normals.Add(new Vector3D(0, 0, -1));
                textures.Add(new Point(p.X * 0.5 + 0.5, p.Y * 0.5 + 0.5));
            }

            mb.AddTriangleFan(vectors, normals, textures);
        }
Example #11
0
        public TriangleMeshAdapater(MFnMesh mesh)
        {
            MIntArray indices = new MIntArray();
            MIntArray triangleCounts = new MIntArray();
            MPointArray points = new MPointArray();

            mesh.getTriangles(triangleCounts, indices);
            mesh.getPoints(points);

            // Get the triangle indices
            Indices = new Int32Collection((int)indices.length);
            for (int i = 0; i < indices.length; ++i)
                Indices.Add(indices[i]);

            // Get the control points (vertices)
            Points = new Point3DCollection((int)points.length);
            for (int i = 0; i < (int)points.length; ++i)
            {
                MPoint pt = points[i];
                Points.Add(new Point3D(pt.x, pt.y, pt.z));
            }

            // Get the number of triangle faces and polygon faces 
            Debug.Assert(indices.length % 3 == 0);
            int triFaces = (int)indices.length / 3;
            int polyFaces = mesh.numPolygons;

            // We have normals per polygon, we want one per triangle. 
            Normals = new Vector3DCollection(triFaces);
            int nCurrentTriangle = 0;

            // Iterate over each polygon
            for (int i = 0; i < polyFaces; ++i)
            {
                // Get the polygon normal
                var maya_normal = new MVector();
                mesh.getPolygonNormal((int)i, maya_normal);
                System.Windows.Media.Media3D.Vector3D normal = new System.Windows.Media.Media3D.Vector3D(maya_normal.x, maya_normal.y, maya_normal.z);

                // Iterate over each tri in the current polygon
                int nTrisAtFace = triangleCounts[i];
                for (int j = 0; j < nTrisAtFace; ++j)
                {
                    Debug.Assert(nCurrentTriangle < triFaces);
                    Normals.Add(normal);
                    nCurrentTriangle++;
                }
            }
            Debug.Assert(nCurrentTriangle == triFaces);
        }
        /// <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 y = Length - stack * Length / Stacks;

                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);

                    normals.Add(new Vector3D(x, 0, z));
                    vertices.Add(new Point3D(x, y, z));
                    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);
                }
            }
        }
Example #13
0
        public ArrayList decode()
        {
            ArrayList array = new ArrayList();
            _mesh = new Point3DCollection();
            _normals = new Vector3DCollection();
            array.Add(_mesh);
            array.Add(_normals);

            for (int i = 0; i < _parser.numTriangles; i++)
            {
                ArrayList collection = _parser.index(i);
                _mesh.Add((Point3D)collection[INDEX_VERTEX0]);
                _mesh.Add((Point3D)collection[INDEX_VERTEX1]);
                _mesh.Add((Point3D)collection[INDEX_VERTEX2]);
                _normals.Add((Vector3D)collection[INDEX_NORMAL]);
            }
            return array;
        }
Example #14
0
        [FriendAccessAllowed] // Built into Core, also used by Framework.
        internal static object DeserializeFrom(BinaryReader reader)
        {
            // Get the size.
            uint count = reader.ReadUInt32() ; 
            
            Vector3DCollection collection = new Vector3DCollection( (int) count) ; 
            
            for ( uint i = 0; i < count ; i ++ ) 
            {

                Vector3D point = new Vector3D(
                                             XamlSerializationHelper.ReadDouble( reader ), 
                                             XamlSerializationHelper.ReadDouble( reader ) , 
                                             XamlSerializationHelper.ReadDouble( reader ) ) ; 

                collection.Add( point );                 
            }

            return collection ; 
        }
Example #15
0
        public static MeshGeometry3D CreateMesh(int xVertices, int yVertices)
        {
            Vector3DCollection normals = new Vector3DCollection();
            PointCollection textCoords = new PointCollection();
            for (int y = 0; y < yVertices; y++)
            {
                for (int x = 0; x < xVertices; x++)
                {
                    // Normals
                    Vector3D n1 = new Vector3D(0, 0, 1);
                    normals.Add(n1);

                    // Texture Coordinates
                    textCoords.Add(GetTextureCoordinate(xVertices, yVertices, y, x));
                }
            }
            Int32Collection indices = GetTriangleIndices(xVertices, yVertices);

            MeshGeometry3D mesh = new MeshGeometry3D();
            mesh.Normals = normals;
            mesh.TriangleIndices = indices;
            mesh.TextureCoordinates = textCoords;
            return mesh;
        }
Example #16
0
        public void CreateMesh()
        {
            Point3DCollection point3DCollection = new Point3DCollection();
              //Front
              point3DCollection.Add(new Point3D(m_min.X, m_min.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_min.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_max.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_max.Y, m_min.Z));
              //Back
              point3DCollection.Add(new Point3D(m_min.X, m_min.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_min.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_max.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_max.Y, m_max.Z));
              //Left
              point3DCollection.Add(new Point3D(m_min.X, m_min.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_min.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_max.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_max.Y, m_max.Z));
              //Right
              point3DCollection.Add(new Point3D(m_max.X, m_min.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_min.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_max.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_max.Y, m_max.Z));
              //Bottom
              point3DCollection.Add(new Point3D(m_min.X, m_min.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_min.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_min.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_min.Y, m_min.Z));
              //Top
              point3DCollection.Add(new Point3D(m_min.X, m_max.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_max.Y, m_max.Z));
              point3DCollection.Add(new Point3D(m_max.X, m_max.Y, m_min.Z));
              point3DCollection.Add(new Point3D(m_min.X, m_max.Y, m_min.Z));

              Vector3DCollection normals = new Vector3DCollection();
              normals.Add(new Vector3D(0, 0, 1));
              normals.Add(new Vector3D(0, 0, 1));
              normals.Add(new Vector3D(0, 0, 1));
              normals.Add(new Vector3D(0, 0, 1));

              normals.Add(new Vector3D(0, 0, -1));
              normals.Add(new Vector3D(0, 0, -1));
              normals.Add(new Vector3D(0, 0, -1));
              normals.Add(new Vector3D(0, 0, -1));

              normals.Add(new Vector3D(-1, 0, 0));
              normals.Add(new Vector3D(-1, 0, 0));
              normals.Add(new Vector3D(-1, 0, 0));
              normals.Add(new Vector3D(-1, 0, 0));

              normals.Add(new Vector3D(1, 0, 0));
              normals.Add(new Vector3D(1, 0, 0));
              normals.Add(new Vector3D(1, 0, 0));
              normals.Add(new Vector3D(1, 0, 0));

              normals.Add(new Vector3D(0, -1, 0));
              normals.Add(new Vector3D(0, -1, 0));
              normals.Add(new Vector3D(0, -1, 0));
              normals.Add(new Vector3D(0, -1, 0));

              normals.Add(new Vector3D(0, 1, 0));
              normals.Add(new Vector3D(0, 1, 0));
              normals.Add(new Vector3D(0, 1, 0));
              normals.Add(new Vector3D(0, 1, 0));

              Int32Collection triangles = new Int32Collection();

              //for (int i = 1; i < 6; i += 2)
              //{
              //  triangles.Add(0 + (i * 4));
              //  triangles.Add(1 + (i * 4));
              //  triangles.Add(3 + (i * 4));
              //  triangles.Add(1 + (i * 4));
              //  triangles.Add(2 + (i * 4));
              //  triangles.Add(3 + (i * 4));
              //}

              //for (int i = 0; i < 6; i += 2)
              //{
              //  triangles.Add(3 + (i * 4));
              //  triangles.Add(1 + (i * 4));
              //  triangles.Add(0 + (i * 4));
              //  triangles.Add(3 + (i * 4));
              //  triangles.Add(2 + (i * 4));
              //  triangles.Add(1 + (i * 4));
              //}

              for (int i = 0; i < 6; i++)
              {
            triangles.Add(0 + (i * 4));
            triangles.Add(1 + (i * 4));
            triangles.Add(0 + (i * 4));
            triangles.Add(1 + (i * 4));
            triangles.Add(2 + (i * 4));
            triangles.Add(1 + (i * 4));
            triangles.Add(2 + (i * 4));
            triangles.Add(3 + (i * 4));
            triangles.Add(2 + (i * 4));
            triangles.Add(3 + (i * 4));
            triangles.Add(0 + (i * 4));
            triangles.Add(3 + (i * 4));
              }

              MeshGeometry3D meshGeometry3D = new MeshGeometry3D
            {
              Positions = point3DCollection,
              Normals = normals,
              TriangleIndices = triangles
            };

              m_geometryModel3D = new GeometryModel3D();
              GeometryModel3D.Geometry = meshGeometry3D.ToWireframe(0.1);
              GeometryModel3D.Material = new DiffuseMaterial(new SolidColorBrush(m_color));
        }
        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;
                }
            }
        }
        /// <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);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="normals"></param>
        /// <param name="indices"></param>
        /// <param name="textures"></param>
        protected void TriangleSubdivide(Point3DCollection vertices,
                                         Vector3DCollection normals,
                                         Int32Collection indices,
                                         PointCollection textures)
        {
            for (int i = 0; i < 3; i++)
            {
                verticesBase[2 - i] = vertices[vertices.Count - 1];
                normalsBase[2 - i] = normals[vertices.Count - 1];
                texturesBase[2 - i] = textures[vertices.Count - 1];

                vertices.RemoveAt(vertices.Count - 1);
                normals.RemoveAt(normals.Count - 1);
                indices.RemoveAt(indices.Count - 1);
                textures.RemoveAt(textures.Count - 1);
            }

            int indexStart = vertices.Count;

            for (int slice = 0; slice <= Slices; slice++)
            {
                double weight = (double)slice / Slices;

                Point3D vertex1 = Point3DWeight(verticesBase[0], verticesBase[1], weight);
                Point3D vertex2 = Point3DWeight(verticesBase[0], verticesBase[2], weight);

                Vector3D normal1 = Vector3DWeight(normalsBase[0], normalsBase[1], weight);
                Vector3D normal2 = Vector3DWeight(normalsBase[0], normalsBase[2], weight);

                Point texture1 = PointWeight(texturesBase[0], texturesBase[1], weight);
                Point texture2 = PointWeight(texturesBase[0], texturesBase[2], weight);

                for (int i = 0; i <= slice; i++)
                {
                    weight = (double)i / slice;

                    if (Double.IsNaN(weight))
                        weight = 0;

                    vertices.Add(Point3DWeight(vertex1, vertex2, weight));
                    normals.Add(Vector3DWeight(normal1, normal2, weight));
                    textures.Add(PointWeight(texture1, texture2, weight));
                }
            }

            for (int slice = 0; slice < Slices; slice++)
            {
                int base1 = (slice + 1) * slice / 2;
                int base2 = base1 + slice + 1;

                for (int i = 0; i <= 2 * slice; i++)
                {
                    int half = i / 2;

                    if ((i & 1) == 0)         // even
                    {
                        indices.Add(indexStart + base1 + half);
                        indices.Add(indexStart + base2 + half);
                        indices.Add(indexStart + base2 + half + 1);
                    }
                    else                    // odd
                    {
                        indices.Add(indexStart + base1 + half);
                        indices.Add(indexStart + base2 + half + 1);
                        indices.Add(indexStart + base1 + half + 1);
                    }
                }
            }
        }
Example #20
0
        private Model3DGroup GenerateTileStitching(PointCloudTileSource tileSource, TileInfo3D tileInfo)
        {
            PointCloudTile tile = tileInfo.Tile;
            MeshGeometry3D mesh = GetTileMeshGeometry(tileInfo.CurrentGeometry);
            Grid<float> grid = tileInfo.CurrentGrid;

            //Model3DGroup stitchingGroup = new Model3DGroup();

            bool hasTop = false;
            bool hasLeft = false;

            Point3D topCornerPoint = default(Point3D);
            Point3D leftCornerPoint = default(Point3D);

            Vector3D topCornerNormal = default(Vector3D);
            Vector3D leftCornerNormal = default(Vector3D);

            // connect to left tile (if available)
            if (tile.Col > 0)
            {
                PointCloudTile leftTile = tileSource.TileSet.GetTile(tile.Row, tile.Col - 1);
                TileInfo3D leftTileInfo = null;
                if (leftTile != null && m_tileInfo.TryGetValue(leftTile, out leftTileInfo) && leftTileInfo.CurrentGrid == grid)
                {
                    MeshGeometry3D leftMesh = GetTileMeshGeometry(leftTileInfo.CurrentGeometry);
                    int leftPositionsStart = leftMesh.Positions.Count - grid.SizeY;

                    hasLeft = true;
                    leftCornerPoint = leftMesh.Positions[leftPositionsStart];
                    leftCornerNormal = leftMesh.Normals[leftPositionsStart];

                    if (!tileInfo.HasStitching(TileStitchingEdge.Left))
                    {
                        MeshGeometry3D stitchingMesh = new MeshGeometry3D();

                        int positionCount = grid.SizeY * 2;
                        Point3DCollection positions = new Point3DCollection(positionCount);
                        Vector3DCollection normals = new Vector3DCollection(positionCount);

                        for (int edgePosition = 0; edgePosition < grid.SizeY; edgePosition++)
                        {
                            positions.Add(leftMesh.Positions[leftPositionsStart + edgePosition]);
                            normals.Add(leftMesh.Normals[leftPositionsStart + edgePosition]);

                            positions.Add(mesh.Positions[edgePosition]);
                            normals.Add(mesh.Normals[edgePosition]);
                        }
                        stitchingMesh.Positions = positions;
                        stitchingMesh.Normals = normals;

                        Int32Collection indices = new Int32Collection((grid.SizeY - 1) * 6);
                        for (int i = 0; i < grid.SizeY - 1; i++)
                        {
                            int j = 2 * i;
                            indices.Add(j);
                            indices.Add(j + 1);
                            indices.Add(j + 2);

                            indices.Add(j + 2);
                            indices.Add(j + 1);
                            indices.Add(j + 3);
                        }
                        stitchingMesh.TriangleIndices = indices;

                        stitchingMesh.TextureCoordinates = MeshUtils.GeneratePlanarTextureCoordinates(stitchingMesh, m_overallCenteredExtent, MathUtils.ZAxis);

                        GeometryModel3D stitchingModel = new GeometryModel3D(stitchingMesh, m_overviewMaterial);
                        stitchingModel.Freeze();

                        tileInfo.UpdateStitching(stitchingModel, leftTileInfo.CurrentGrid, TileStitchingEdge.Left);
                        //stitchingGroup.Children.Add(stitchingModel);
                    }
                }
            }

            // connect to top tile (if available)
            if (tile.Row > 0)
            {
                PointCloudTile topTile = tileSource.TileSet.GetTile(tile.Row - 1, tile.Col);
                TileInfo3D topTileInfo = null;
                if (topTile != null && m_tileInfo.TryGetValue(topTile, out topTileInfo) && topTileInfo.CurrentGrid == grid)
                {
                    MeshGeometry3D topMesh = GetTileMeshGeometry(topTileInfo.CurrentGeometry);

                    hasTop = true;
                    topCornerPoint = topMesh.Positions[grid.SizeY - 1];
                    topCornerNormal = topMesh.Normals[grid.SizeY - 1];

                    if (!tileInfo.HasStitching(TileStitchingEdge.Top))
                    {
                        MeshGeometry3D stitchingMesh = new MeshGeometry3D();

                        int positionCount = grid.SizeX * 2;
                        Point3DCollection positions = new Point3DCollection(positionCount);
                        Vector3DCollection normals = new Vector3DCollection(positionCount);

                        for (int edgePosition = 0; edgePosition < mesh.Positions.Count; edgePosition += grid.SizeY)
                        {
                            positions.Add(topMesh.Positions[edgePosition + grid.SizeY - 1]);
                            normals.Add(topMesh.Normals[edgePosition + grid.SizeY - 1]);

                            positions.Add(mesh.Positions[edgePosition]);
                            normals.Add(mesh.Normals[edgePosition]);
                        }
                        stitchingMesh.Positions = positions;
                        stitchingMesh.Normals = normals;

                        Int32Collection indices = new Int32Collection((grid.SizeX - 1) * 6);
                        for (int i = 0; i < grid.SizeX - 1; i++)
                        {
                            int j = 2 * i;

                            indices.Add(j);
                            indices.Add(j + 2);
                            indices.Add(j + 1);

                            indices.Add(j + 2);
                            indices.Add(j + 3);
                            indices.Add(j + 1);
                        }
                        stitchingMesh.TriangleIndices = indices;

                        stitchingMesh.TextureCoordinates = MeshUtils.GeneratePlanarTextureCoordinates(stitchingMesh, m_overallCenteredExtent, MathUtils.ZAxis);

                        GeometryModel3D stitchingModel = new GeometryModel3D(stitchingMesh, m_overviewMaterial);
                        stitchingModel.Freeze();

                        tileInfo.UpdateStitching(stitchingModel, topTileInfo.CurrentGrid, TileStitchingEdge.Top);
                        //stitchingGroup.Children.Add(stitchingModel);
                    }
                }
            }

            // connect to top left tile (if available)
            if (hasTop && hasLeft && !tileInfo.HasStitching(TileStitchingEdge.TopLeft))
            {
                PointCloudTile topleftTile = tileSource.TileSet.GetTile(tile.Row - 1, tile.Col - 1);
                TileInfo3D topleftTileInfo = null;
                if (topleftTile != null && m_tileInfo.TryGetValue(topleftTile, out topleftTileInfo))
                {
                    MeshGeometry3D topleftMesh = GetTileMeshGeometry(topleftTileInfo.CurrentGeometry);
                    MeshGeometry3D stitchingMesh = new MeshGeometry3D();

                    Point3DCollection positions = new Point3DCollection(4);
                    Vector3DCollection normals = new Vector3DCollection(4);
                    {
                        positions.Add(topleftMesh.Positions[topleftMesh.Positions.Count - 1]);
                        normals.Add(topleftMesh.Normals[topleftMesh.Positions.Count - 1]);

                        positions.Add(topCornerPoint);
                        normals.Add(topCornerNormal);

                        positions.Add(leftCornerPoint);
                        normals.Add(leftCornerNormal);

                        positions.Add(mesh.Positions[0]);
                        normals.Add(mesh.Normals[0]);
                    }
                    stitchingMesh.Positions = positions;
                    stitchingMesh.Normals = normals;

                    Int32Collection indices = new Int32Collection(6);
                    indices.Add(0);
                    indices.Add(1);
                    indices.Add(2);
                    indices.Add(2);
                    indices.Add(1);
                    indices.Add(3);
                    stitchingMesh.TriangleIndices = indices;

                    stitchingMesh.TextureCoordinates = MeshUtils.GeneratePlanarTextureCoordinates(stitchingMesh, m_overallCenteredExtent, MathUtils.ZAxis);

                    GeometryModel3D stitchingModel = new GeometryModel3D(stitchingMesh, m_overviewMaterial);
                    stitchingModel.Freeze();

                    tileInfo.UpdateStitching(stitchingModel, topleftTileInfo.CurrentGrid, TileStitchingEdge.TopLeft);
                    //stitchingGroup.Children.Add(stitchingModel);
                }
            }

            return tileInfo.GetNewStitching();
        }
Example #21
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);
            }
        }
        public static void DrawLibGGraphicItem(NodeModel node, object geom, string tag, RenderDescription rd,  Octree.OctreeSearch.Octree octree)
        {
            var selected = DynamoSelection.Instance.Selection.Contains(node);
            var g = geom as GraphicItem;

            if (g is CoordinateSystem)
            {
                #region draw coordinate systems

                var line_strip_vertices = g.line_strip_vertices_threadsafe();

                for (int i = 0; i < line_strip_vertices.Count; i += 6)
                {
                    var p1 = new Point3D(
                        line_strip_vertices[i],
                        line_strip_vertices[i + 1],
                        line_strip_vertices[i + 2]);

                    var p2 = new Point3D(
                        line_strip_vertices[i + 3],
                        line_strip_vertices[i + 4],
                        line_strip_vertices[i + 5]);

                    if (i < 6)
                    {
                        rd.XAxisPoints.Add(p1);
                        rd.XAxisPoints.Add(p2);
                    }
                    else if (i >= 6 && i < 12)
                    {
                        rd.YAxisPoints.Add(p1);
                        rd.YAxisPoints.Add(p2);
                    }
                    else
                    {
                        rd.ZAxisPoints.Add(p1);
                        rd.ZAxisPoints.Add(p2);
                    }
                }

                #endregion
            }
            else
            {
                #region draw points

                var point_vertices = g.point_vertices_threadsafe();

                for (int i = 0; i < point_vertices.Count; i += 3)
                {
                    var pos = new Point3D(point_vertices[i],
                        point_vertices[i + 1], point_vertices[i + 2]);

                    if (selected)
                    {
                        rd.SelectedPoints.Add(pos);
                    }
                    else
                    {
                        rd.Points.Add(pos);
                    }

                    if (node.DisplayLabels)
                    {
                        rd.Text.Add(new BillboardTextItem { Text = tag, Position = pos });
                    }
                }

                #endregion

                #region draw lines

                FloatList line_strip_vertices = g.line_strip_vertices_threadsafe();

                for (int i = 0; i < line_strip_vertices.Count-3; i += 3)
                {
                    var start = new Point3D(
                            line_strip_vertices[i],
                            line_strip_vertices[i + 1],
                            line_strip_vertices[i + 2]);

                    var end = new Point3D(
                            line_strip_vertices[i + 3],
                            line_strip_vertices[i + 4],
                            line_strip_vertices[i + 5]);

                    //draw a label at the start of the curve
                    if (node.DisplayLabels && i == 0)
                    {
                        rd.Text.Add(new BillboardTextItem { Text = tag, Position = start });
                    }

                    if (selected)
                    {
                        rd.SelectedLines.Add(start);
                        rd.SelectedLines.Add(end);
                    }
                    else
                    {
                        rd.Lines.Add(start);
                        rd.Lines.Add(end);
                    }
                }

                #endregion

                #region draw surface

                //var sw = new Stopwatch();
                //sw.Start();

                var builder = new MeshBuilder();
                var points = new Point3DCollection();
                var tex = new PointCollection();
                var norms = new Vector3DCollection();
                var tris = new List<int>();

                FloatList triangle_vertices = g.triangle_vertices_threadsafe();
                FloatList triangle_normals = g.triangle_normals_threadsafe();

                for (int i = 0; i < triangle_vertices.Count; i+=3)
                {
                    var new_point = new Point3D(triangle_vertices[i],
                                                triangle_vertices[i + 1],
                                                triangle_vertices[i + 2]);

                    var normal = new Vector3D(triangle_normals[i],
                                                triangle_normals[i + 1],
                                                triangle_normals[i + 2]);

                    //find a matching point
                    //compare the angle between the normals
                    //to discern a 'break' angle for adjacent faces
                    //int foundIndex = -1;
                    //for (int j = 0; j < points.Count; j++)
                    //{
                    //    var testPt = points[j];
                    //    var testNorm = norms[j];
                    //    var ang = Vector3D.AngleBetween(normal, testNorm);

                    //    if (new_point.X == testPt.X &&
                    //        new_point.Y == testPt.Y &&
                    //        new_point.Z == testPt.Z &&
                    //        ang > 90.0000)
                    //    {
                    //        foundIndex = j;
                    //        break;
                    //    }
                    //}

                    //if (foundIndex != -1)
                    //{
                    //    tris.Add(foundIndex);
                    //    continue;
                    //}

                    tris.Add(points.Count);
                    points.Add(new_point);
                    norms.Add(normal);
                    tex.Add(new System.Windows.Point(0,0));

                    octree.AddNode(new_point.X, new_point.Y, new_point.Z, node.GUID.ToString());
                }

                //builder.AddTriangles(points, norms, tex);
                builder.Append(points, tris, norms, tex);

                //sw.Stop();
                //Debug.WriteLine(string.Format("{0} elapsed for drawing geometry.", sw.Elapsed));

                //don't add empty meshes
                if (builder.Positions.Count > 0)
                {
                    if (selected)
                    {
                        rd.SelectedMeshes.Add(builder.ToMesh(true));
                    }
                    else
                    {
                        rd.Meshes.Add(builder.ToMesh(true));
                    }
                }

                #endregion
            }
        }
Example #23
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;
                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;
                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 = 0;
                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);
                        }
                    }
                }
            }
        }
Example #24
0
        private void AddFace(string values)
        {
            // A polygonal face. The numbers are indexes into the arrays of vertex positions, 
            // texture coordinates, and normals respectively. A number may be omitted if, 
            // for example, texture coordinates are not being defined in the model.
            // There is no maximum number of vertices that a single polygon may contain. 
            // The .obj file specification says that each face must be flat and convex. 

            var fields = values.Split(' ');
            var pts = new Point3DCollection();
            var tex = new PointCollection();
            var norm = new Vector3DCollection();
            foreach (var field in fields)
            {
                if (String.IsNullOrEmpty(field))
                    continue;
                var ff = field.Split('/');
                int vi = int.Parse(ff[0]);
                int vti = ff.Length > 1 && ff[1].Length > 0 ? int.Parse(ff[1]) : -1;
                int vni = ff.Length > 2 && ff[2].Length > 0 ? int.Parse(ff[2]) : -1;
                pts.Add(Points[vi - 1]);
                if (vti >= 0)
                    tex.Add(TexCoords[vti - 1]);
                if (vni >= 0)
                    norm.Add(Normals[vni - 1]);
            }
            if (tex.Count == 0) tex = null;
            if (norm.Count == 0) norm = null;

            // QUAD
            if (pts.Count == 4)
            {
                CurrentGroup.MeshBuilder.AddQuads(pts, norm, tex);
                return;
            }

            // TRIANGLE
            if (pts.Count == 3)
            {
                CurrentGroup.MeshBuilder.AddTriangles(pts, norm, tex);
                return;
            }

            // POLYGONS (flat and convex)
            var poly3D = new Polygon3D(pts);
            // Transform the polygon to 2D
            var poly2D = poly3D.Flatten();
            // Triangulate
            var tri = poly2D.Triangulate();
            if (tri != null)
            {
                // Add the triangle indices with the 3D points
                var mesh = new MeshBuilder();
                mesh.Append(pts, tri);
                CurrentGroup.MeshBuilder.Append(mesh);
            }
        }
Example #25
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);
                }
            }
        }
Example #26
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);
                        }
                    }
                }
            }
        }
Example #27
0
        private void CreateFaceModels(IFCItem item, Vector3D center)
        {
            while (item != null) {
                if (item.ifcID != IntPtr.Zero && item.noVerticesForFaces != 0 && item.noPrimitivesForFaces != 0) {
                    var positions = new Point3DCollection();
                    var normals = new Vector3DCollection();
                    if (item.verticesForFaces != null) {
                        for (int i = 0; i < item.noVerticesForFaces; i++) {
                            var point = new Point3D(item.verticesForFaces[6 * i + 0] - center.X, item.verticesForFaces[6 * i + 1] - center.Y, item.verticesForFaces[6 * i + 2] - center.Z);
                            var normal = new Vector3D(item.verticesForFaces[6 * i + 3], item.verticesForFaces[6 * i + 4], item.verticesForFaces[6 * i + 5]);
                            positions.Add(point);
                            normals.Add(normal);
                        }

                        Debug.Assert(item.verticesForFaces.Length == item.noVerticesForFaces * 6);
                    }

                    var indices = new Int32Collection();
                    if (item.indicesForFaces != null) {
                        for (int i = 0; i < 3 * item.noPrimitivesForFaces; i++) {
                            indices.Add(item.indicesForFaces[i]);
                        }
                    }

                    MeshGeometry3D meshGeometry = new MeshGeometry3D();
                    meshGeometry.Positions = positions;
                    meshGeometry.Normals = normals;
                    meshGeometry.TriangleIndices = indices;
                    MeshGeometryVisual3D mesh = new MeshGeometryVisual3D();
                    mesh.MeshGeometry = meshGeometry;
                    item.Mesh3d = mesh;
                    _meshToIfcItems[mesh] = item;
            #if DEBUG
                    OutputObj(item.ifcID.ToString(), meshGeometry);
            #endif
                    FillMeshByIfcColor(item);

                    hVp3D.Children.Add(mesh);
                }

                CreateFaceModels(item.child, center);
                item = item.next;
            }
        }
Example #28
0
        public static Model3D CreateModel3D(List<Mesh> meshGroups, BitmapSource texture, AnimData pose, int frame)
        {
            GeometryModel3D model = new GeometryModel3D();
            var mesh3D = new MeshGeometry3D();

            int numVertices = 0;
            foreach (var meshGroup in meshGroups)
            {
                numVertices += meshGroup.Positions.Count;
            }
            var triangleIndices = new Int32Collection();
            var positions = new Point3DCollection(numVertices);
            var normals = new Vector3DCollection(numVertices);
            var uvCoords = new PointCollection(numVertices);
            int vstart = 0;

            foreach (var meshGroup in meshGroups)
            {
                Boolean hasVertexWeights = meshGroup.vertexWeights.Count > 0;
                int vwNum = 0;
                VertexWeight vw = new VertexWeight();
                if (meshGroup.vertexWeights.Count > 0)
                {
                    vw = meshGroup.vertexWeights[vwNum];
                }
                int vnum = 0;
                foreach (var vertex in meshGroup.Positions)
                {
                    var point = vertex;
                    if (frame >= 0 && pose != null) {
                        if (vw.endVertex < vnum)
                        {
                            ++vwNum;
                            vw = meshGroup.vertexWeights[vwNum];
                            if (vnum < vw.startVertex || vnum > vw.endVertex)
                            {
                                Debug.Fail("Vertex " + vnum + " out of range of bone weights " + vw.startVertex + " -> " + vw.endVertex);
                            }
                        }
                        int bone1No = vw.bone1;
                        Point3D bindingPos1 = pose.bindingPose[bone1No];
                        AnimMeshPose bone1Pose = pose.perFrameFKPoses[frame, bone1No];
                        var joint1Pos = bone1Pose.Position;
                        if (vw.bone2 == 0xFF) {
                            if (bone1No == 1)
                            {
                                bone1No = 1;
                            }
                            Matrix3D m = Matrix3D.Identity;
                            m.Translate(new Vector3D(-bindingPos1.X, -bindingPos1.Y, -bindingPos1.Z));   // Inverse binding matrix
                            m.Rotate(bone1Pose.Rotation);
                            m.Translate(new Vector3D(bone1Pose.Position.X, bone1Pose.Position.Y, bone1Pose.Position.Z));
                            point = m.Transform(point);
                        } else {
                            // multi-bone
                            int bone2No = vw.bone2;
                            Point3D bindingPos2 = pose.bindingPose[bone2No];
                            AnimMeshPose bone2Pose = pose.perFrameFKPoses[frame, bone2No];
                            double boneSum = vw.boneWeight1 + vw.boneWeight2;
                            double bone1Coeff = vw.boneWeight1 / boneSum;
                            double bone2Coeff = vw.boneWeight2 / boneSum;

                            Matrix3D m = Matrix3D.Identity;
                            m.Translate(new Vector3D(-bindingPos1.X, -bindingPos1.Y, -bindingPos1.Z));   // Inverse binding matrix
                            m.Rotate(bone1Pose.Rotation);
                            m.Translate(new Vector3D(bone1Pose.Position.X, bone1Pose.Position.Y, bone1Pose.Position.Z));
                            var point1 = m.Transform(point);

                            // Now rotate
                            Matrix3D m2 = Matrix3D.Identity;
                            m2.Translate(new Vector3D(-bindingPos2.X, -bindingPos2.Y, -bindingPos2.Z));   // Inverse binding matrix
                            m2.Rotate(bone2Pose.Rotation);
                            m2.Translate(new Vector3D(bone2Pose.Position.X, bone2Pose.Position.Y, bone2Pose.Position.Z));
                            var point2 = m2.Transform(point);

                            point = new Point3D(point1.X * bone1Coeff + point2.X * bone2Coeff, point1.Y * bone1Coeff + point2.Y * bone2Coeff, point1.Z * bone1Coeff + point2.Z * bone2Coeff);
                        }
                    }
                    positions.Add(point);
                    ++vnum;
                }
                foreach (var normal in meshGroup.Normals)
                {
                    normals.Add(normal);
                }
                foreach (var ti in meshGroup.TriangleIndices) {
                    triangleIndices.Add(ti+vstart);
                }
                foreach (var uv in meshGroup.TextureCoordinates) {
                    uvCoords.Add(uv);
                }
                vstart += meshGroup.Positions.Count;
            }
            mesh3D.TriangleIndices = triangleIndices;
            mesh3D.Positions = positions;
            mesh3D.TextureCoordinates = uvCoords;
            mesh3D.Normals = normals;
            model.Geometry = mesh3D;
            var dm = new DiffuseMaterial();
            if (texture != null && texture.Width > 0 && texture.Height > 0)
            {
                var ib = new ImageBrush(texture);
                ib.ViewportUnits = BrushMappingMode.Absolute;
                // May be needed at a later point
                //ib.TileMode = TileMode.Tile;
                dm.Brush = ib;
            }
            else
            {
                var dg = new DrawingGroup();
                // Background
                dg.Children.Add(new GeometryDrawing()
                {
                    Brush = new SolidColorBrush(Colors.Black),
                    Geometry = new RectangleGeometry(new Rect(0, 0, 2, 2))
                });

                // Tiles
                dg.Children.Add(new GeometryDrawing()
                {
                    Brush = new SolidColorBrush(Colors.Violet),
                    Geometry = new RectangleGeometry(new Rect(0, 0, 1, 1))
                });
                dg.Children.Add(new GeometryDrawing()
                {
                    Brush = new SolidColorBrush(Colors.Violet),
                    Geometry = new RectangleGeometry(new Rect(1, 1, 1, 1))
                });

                dm.Brush = new DrawingBrush(dg){ TileMode = TileMode.Tile, Transform = new ScaleTransform(0.1,0.1)};
            }
            model.Material = dm;
            return model;
        }
Example #29
0
        public MeshGeometry3D createAlternativeMesh()
        {
            //this.mesh is the relevant mesh that we are setting.

            //Define list of triangle indices over the whole model.
            var triangleIndices = new List<int>();

            //Define Vector3D normals.
            Vector3DCollection myNormalCollection = new Vector3DCollection();
            myNormalCollection.Add(new Vector3D(0, 0, 1));
            myNormalCollection.Add(new Vector3D(0, 1, 1));
            myNormalCollection.Add(new Vector3D(1, 1, 1));

            //iterate over each 3 points and create a triangle with the relevant indices.
            for (int i = 0; i < this.cloudList[0].Count-3; i+=3)
            {
                this.mesh.Positions.Add(this.cloudList[0][i]);
                this.mesh.Positions.Add(this.cloudList[0][i + 1]);
                this.mesh.Positions.Add(this.cloudList[0][i + 2]);

                //set triangle normals on the mesh.
                triangleIndices.Add(0);
                triangleIndices.Add(1);
                triangleIndices.Add(2);
            }

            return new MeshGeometry3D()
            {
                Positions = new Point3DCollection(this.cloudList[0]),
                //TextureCoordinates = new System.Windows.Media.PointCollection(this.textureCoordinates),
                TriangleIndices = new Int32Collection(triangleIndices),
                Normals = myNormalCollection
            };
        }
Example #30
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);
                }
            }
        }