/// <summary>
        /// Returns true if vertex lies on the edge of triangle mesh
        /// </summary>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public static bool IsOnEdge(Vector3 vertex, SceneBrep scene)
        {
            bool onEdge = false;

            var        handle      = scene.GetVertex(vertex);
            List <int> trianglePtr = new List <int>();

            // get triangles
            for (int i = 0; i < scene.vertexPtr.Count; i++)
            {
                if (scene.vertexPtr[i] == handle)
                {
                    if (i % 3 == 0)
                    {
                        trianglePtr.Add(i / 3);
                    }
                    else if (i % 3 == 1)
                    {
                        trianglePtr.Add((i - 1) / 3);
                    }
                    else if (i % 3 == 2)
                    {
                        trianglePtr.Add((i - 2) / 3);
                    }
                }
            }

            // is triangle on edge?

            foreach (var ptr in trianglePtr)
            {
                // get handle of corners of triangle
                var c1 = Scene3D.SceneBrep.tCorner(ptr);
                var c2 = c1 + 1;
                var c3 = c1 + 2;



                if (scene.cOpposite(c1) == -1)
                {
                    onEdge = true;
                }
                else if (scene.cOpposite(c2) == -1)
                {
                    onEdge = true;
                }
                else if (scene.cOpposite(c3) == -1)
                {
                    onEdge = true;
                }
            }

            return(onEdge);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Do Loop subdivision of the input control triangle mesh.
        /// </summary>
        /// <param name="scene">Input scene (must not be changed).</param>
        /// <param name="epsilon">Reference error toleration (size of undivided triangle).</param>
        /// <param name="normals">Generate normals? (optional)</param>
        /// <param name="colors">Generate colors? (optional)</param>
        /// <param name="txtcoord">Generate texture coordinates? (optional)</param>
        /// <param name="time">Current time for animation (optional)</param>
        /// <param name="param">Optional additional parameters.</param>
        /// <returns>Number of generated points.</returns>
        public int Subdivide(SceneBrep scene, float epsilon, bool normals, bool colors, bool txtcoord, float time, string param)
        {
            result = scene.Clone();

            // !!!{{ TODO: put your Loop subdivision code here

            // pilot: do one (trivial) division
            int triangles = result.Triangles;
            int tr;

            for (tr = 0; tr < triangles; tr++)
            {
                int A, B, C;
                result.GetTriangleVertices(tr, out A, out B, out C);
                Vector3 vA = result.GetVertex(A);
                Vector3 vB = result.GetVertex(B);
                Vector3 vC = result.GetVertex(C);

                Vector3 vA2 = (vB + vC) * 0.5f;
                Vector3 vB2 = (vA + vC) * 0.5f;
                Vector3 vC2 = (vA + vB) * 0.5f;
                int     A2  = result.AddVertex(vA2);
                int     B2  = result.AddVertex(vB2);
                int     C2  = result.AddVertex(vC2);

                result.AddTriangle(B2, C2, A2);
                result.AddTriangle(B2, A2, C);
                result.AddTriangle(C2, B, A2);
                result.SetTriangleVertices(tr, A, C2, B2);
            }

            //result.BuildCornerTable();

            return(result.Vertices);

            // !!!}}
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Writes the whole B-rep scene to a given text stream (uses text variant of Wavefront OBJ format).
        /// </summary>
        /// <param name="writer">Already open text writer</param>
        /// <param name="scene">Scene to write</param>
        public void WriteBrep(StreamWriter writer, SceneBrep scene)
        {
            if (scene == null || scene.Triangles < 1)
            {
                return;
            }

            int i;

            for (i = 0; i < scene.Vertices; i++)
            {
                Vector3 v = scene.GetVertex(i);
                writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}",
                                               new object[] { VERTEX, v.X, v.Y, v.Z }));
            }

            bool hasNormals = scene.Normals > 0;

            if (hasNormals)
            {
                for (i = 0; i < scene.Vertices; i++)
                {
                    Vector3 n = scene.GetNormal(i);
                    writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}",
                                                   new object[] { VERTEX_NORMAL, n.X, n.Y, n.Z }));
                }
            }

            for (i = 0; i < scene.Triangles; i++)
            {
                int A, B, C;
                scene.GetTriangleVertices(i, out A, out B, out C);
                A++;
                B++;
                C++;
                if (hasNormals)
                {
                    writer.WriteLine("{0} {1}//{1} {2}//{2} {3}//{3}", FACE, A, B, C);
                }
                else
                {
                    writer.WriteLine("{0} {1} {2} {3}", FACE, A, B, C);
                }
            }
        }
Ejemplo n.º 4
0
        public EarClipping(List <int> pointers, Scene3D.SceneBrep scene)
        {
            // Polygon has at least 3 vertices
            if (pointers.Count < 3)
            {
                return;
            }

            this.Scene = scene;

            // Get coordinates from vertex pointers
            PolygonVertices = new List <Vector3>();
            pointers.ForEach(x => PolygonVertices.Add(Scene.GetVertex(x)));

            PrepareNormal(PolygonVertices);
            polygon = new Polygon();
            copy    = new Polygon();
            CreatePolygon(polygon, PolygonVertices);
            CreatePolygon(copy, PolygonVertices);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Writes the whole B-rep scene to a given text stream (uses text variant of Wavefront OBJ format).
        /// </summary>
        /// <param name="writer">Already open text writer</param>
        /// <param name="scene">Scene to write</param>
        public void WriteBrep( StreamWriter writer, SceneBrep scene )
        {
            if ( scene == null || scene.Triangles < 1 ) return;

              int i;
              for ( i = 0; i < scene.Vertices; i++ )
              {
            Vector3 v = scene.GetVertex( i );
            writer.WriteLine( String.Format( CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX, v.X, v.Y, v.Z } ) );
              }

              bool hasNormals = scene.Normals > 0;
              if ( hasNormals )
            for ( i = 0; i < scene.Vertices; i++ )
            {
              Vector3 n = scene.GetNormal( i );
              writer.WriteLine( String.Format( CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX_NORMAL, n.X, n.Y, n.Z } ) );
            }

              for ( i = 0; i < scene.Triangles; i++ )
              {
            int A, B, C;
            scene.GetTriangleVertices( i, out A, out B, out C );
            A++; B++; C++;
            if ( hasNormals )
              writer.WriteLine( "{0} {1}//{1} {2}//{2} {3}//{3}", FACE, A, B, C );
            else
              writer.WriteLine( "{0} {1} {2} {3}", FACE, A, B, C );
              }
        }
Ejemplo n.º 6
0
        public void Render(Bitmap output, SceneBrep scene)
        {
            if (output == null ||
                scene == null)
            {
                return;
            }

            Vector3 center;
            float   diameter = scene.GetDiameter(out center);

            if (Distance < diameter)
            {
                Distance = diameter;
            }

            // and the rest of projection matrix goes here:
            int    width  = output.Width;
            int    height = output.Height;
            float  aspect = width / (float)height;
            double az     = Azimuth / 180.0 * Math.PI;
            double el     = Elevation / 180.0 * Math.PI;

            Vector3 eye = new Vector3((float)(center.X + Distance * Math.Sin(az) * Math.Cos(el)),
                                      (float)(center.Y + Distance * Math.Sin(el)),
                                      (float)(center.Z + Distance * Math.Cos(az) * Math.Cos(el)));
            Matrix4 modelView = Matrix4.LookAt(eye, center, Vector3.UnitY);
            Matrix4 proj;

            if (Perspective)
            {
                float vv = (float)(2.0 * Math.Atan2(diameter * 0.5, Distance));
                proj = Matrix4.CreatePerspectiveFieldOfView(vv, aspect, 1.0f, 50.0f);
            }
            else
            {
                float vHalf = diameter * 0.52f;
                proj = Matrix4.CreateOrthographicOffCenter(-vHalf, vHalf,
                                                           -vHalf / aspect, vHalf / aspect,
                                                           1.0f, 50.0f);
            }

            Matrix4 compound = Matrix4.Mult(modelView, proj);
            Matrix4 viewport = Geometry.SetViewport(0, 0, width, height);

            compound = Matrix4.Mult(compound, viewport);

            // wireframe rendering:
            Graphics gr  = Graphics.FromImage(output);
            Pen      pen = new Pen(Color.FromArgb(255, 255, 80), 1.0f);
            int      n   = scene.Triangles;

            for (int i = 0; i < n; i++)
            {
                Vector4 A, B, C;
                scene.GetTriangleVertices(i, out A, out B, out C);
                A = Vector4.Transform(A, compound);
                B = Vector4.Transform(B, compound);
                C = Vector4.Transform(C, compound);
                Vector2 a = new Vector2(A.X / A.W, A.Y / A.W);
                Vector2 b = new Vector2(B.X / B.W, B.Y / B.W);
                Vector2 c = new Vector2(C.X / C.W, C.Y / C.W);
                gr.DrawLine(pen, a.X, a.Y, b.X, b.Y);
                gr.DrawLine(pen, b.X, b.Y, c.X, c.Y);
                gr.DrawLine(pen, c.X, c.Y, a.X, a.Y);
            }

            if (DrawNormals && scene.Normals > 0)
            {
                pen = new Pen(Color.FromArgb(255, 80, 80), 1.0f);
                n   = scene.Vertices;
                for (int i = 0; i < n; i++)
                {
                    Vector4 V = new Vector4(scene.GetVertex(i), 1.0f);
                    Vector3 N = scene.GetNormal(i);
                    N.Normalize();
                    N *= diameter * 0.03f;
                    Vector4 W = V + new Vector4(N);
                    V = Vector4.Transform(V, compound);
                    W = Vector4.Transform(W, compound);
                    Vector2 v = new Vector2(V.X / V.W, V.Y / V.W);
                    Vector2 w = new Vector2(W.X / W.W, W.Y / W.W);
                    gr.DrawLine(pen, v.X, v.Y, w.X, w.Y);
                }
            }
        }
Ejemplo n.º 7
0
        public void Render( Bitmap output, SceneBrep scene )
        {
            if ( output == null ||
               scene  == null ) return;

              // center of the object = point to look at:
              double cx = 0.0;
              double cy = 0.0;
              double cz = 0.0;
              float minx = float.MaxValue;
              float miny = float.MaxValue;
              float minz = float.MaxValue;
              float maxx = float.MinValue;
              float maxy = float.MinValue;
              float maxz = float.MinValue;
              int n = scene.Vertices;
              int i;

              for ( i = 0; i < n; i++ )
              {
            Vector3 vi = scene.GetVertex( i );
            cx += vi.X;
            cy += vi.Y;
            cz += vi.Z;
            if ( vi.X < minx ) minx = vi.X;
            if ( vi.Y < miny ) miny = vi.Y;
            if ( vi.Z < minz ) minz = vi.Z;
            if ( vi.X > maxx ) maxx = vi.X;
            if ( vi.Y > maxy ) maxy = vi.Y;
            if ( vi.Z > maxz ) maxz = vi.Z;
              }
              Vector3 center = new Vector3( (float)(cx / n),
                                    (float)(cy / n),
                                    (float)(cz / n) );
              float diameter = (float)Math.Sqrt( (maxx - minx) * (maxx - minx) +
                                         (maxy - miny) * (maxy - miny) +
                                         (maxz - minz) * (maxz - minz) );
              if ( Distance < diameter ) Distance = diameter;

              // and the rest of projection matrix goes here:
              int width    = output.Width;
              int height   = output.Height;
              float aspect = width / (float)height;
              double az    = Azimuth / 180.0 * Math.PI;
              double el    = Elevation / 180.0 * Math.PI;

              Vector3 eye   = new Vector3( (float)(center.X + Distance * Math.Sin( az ) * Math.Cos( el )),
                                   (float)(center.Y + Distance * Math.Sin( el )),
                                   (float)(center.Z + Distance * Math.Cos( az ) * Math.Cos( el )) );
              Matrix4 modelView = Matrix4.LookAt( eye, center, Vector3.UnitY );
              Matrix4 proj;

              if ( Perspective )
              {
            float vv = (float)(2.0 * Math.Atan2( diameter * 0.5, Distance ));
            proj = Matrix4.CreatePerspectiveFieldOfView( vv, aspect, 1.0f, 50.0f );
              }
              else
              {
            float vHalf = diameter * 0.52f;
            proj = Matrix4.CreateOrthographicOffCenter( -vHalf, vHalf,
                                                    -vHalf / aspect, vHalf / aspect,
                                                    1.0f, 50.0f );
              }

              Matrix4 compound = Matrix4.Mult( modelView, proj );
              Matrix4 viewport = Geometry.SetViewport( 0, 0, width, height );
              compound = Matrix4.Mult( compound, viewport );

              // wireframe rendering:
              Graphics gr = Graphics.FromImage( output );
              Pen pen = new Pen( Color.FromArgb( 255, 255, 80 ), 1.0f );
              n = scene.Triangles;
              for ( i = 0; i < n; i++ )
              {
            Vector4 A, B, C;
            scene.GetTriangleVertices( i, out A, out B, out C );
            A = Vector4.Transform( A, compound );
            B = Vector4.Transform( B, compound );
            C = Vector4.Transform( C, compound );
            Vector2 a = new Vector2( A.X / A.W, A.Y / A.W );
            Vector2 b = new Vector2( B.X / B.W, B.Y / B.W );
            Vector2 c = new Vector2( C.X / C.W, C.Y / C.W );
            gr.DrawLine( pen, a.X, a.Y, b.X, b.Y );
            gr.DrawLine( pen, b.X, b.Y, c.X, c.Y );
            gr.DrawLine( pen, c.X, c.Y, a.X, a.Y );
              }

              if ( DrawNormals && scene.Normals > 0 )
              {
            pen = new Pen( Color.FromArgb( 255, 80, 80 ), 1.0f );
            n = scene.Vertices;
            for ( i = 0; i < n; i++ )
            {
              Vector4 V = new Vector4( scene.GetVertex( i ), 1.0f );
              Vector3 N = scene.GetNormal( i );
              N.Normalize();
              N *= diameter * 0.03f;
              Vector4 W = V + new Vector4( N );
              V = Vector4.Transform( V, compound );
              W = Vector4.Transform( W, compound );
              Vector2 v = new Vector2( V.X / V.W, V.Y / V.W );
              Vector2 w = new Vector2( W.X / W.W, W.Y / W.W );
              gr.DrawLine( pen, v.X, v.Y, w.X, w.Y );
            }
              }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Writes the whole B-rep scene to a given text stream (uses text variant of Stanford PLY format).
        /// </summary>
        /// <param name="writer">Already open text writer</param>
        /// <param name="scene">Scene to write</param>
        public void WriteBrepSelection(StreamWriter writer, SceneBrep scene, Selection selection,
                                       IProgress <string> progress, CancellationToken cancel, out List <int> trianglePointers, out List <int> vertexPointers)
        {
            DoNormals   = true;
            DoTxtCoords = true;
            DoColors    = true;

            vertexPointers   = new List <int>();
            trianglePointers = new List <int>();

            if (scene == null || selection.GetCount() < 3)
            {
                return;
            }

            vertexPointers = selection.SelectionPointers;

            Debug.Assert(TextFormat);
            if (!NativeNewLine)
            {
                writer.NewLine = "\r";     // CR only
            }
            bool writeNormals   = DoNormals && scene.HasNormals();
            bool writeTxtCoords = DoTxtCoords && scene.HasTxtCoords();
            bool writeColors    = DoColors && scene.HasColors();

            writer.WriteLine(HEADER);
            writer.WriteLine(FORMAT_TEXT);

            // vertex-header:
            writer.WriteLine("{0} {1} {2}", ELEMENT, VERTEX, selection.GetCount());
            writer.WriteLine("{0} float x", PROPERTY);
            writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? 'z' : 'y');
            writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? 'y' : 'z');
            if (writeNormals)
            {
                writer.WriteLine("{0} float {1}", PROPERTY, NORMAL_X);
                writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? NORMAL_Z : NORMAL_Y);
                writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? NORMAL_Y : NORMAL_Z);
            }
            if (writeTxtCoords)
            {
                writer.WriteLine("{0} float {1}", PROPERTY, TEXTURE_S);
                writer.WriteLine("{0} float {1}", PROPERTY, TEXTURE_T);
            }
            if (writeColors)
            {
                writer.WriteLine("{0} float {1}", PROPERTY, COLOR_R);
                writer.WriteLine("{0} float {1}", PROPERTY, COLOR_G);
                writer.WriteLine("{0} float {1}", PROPERTY, COLOR_B);
            }

            var triangles = selection.GetSelectedTriangles();
            var list      = new List <int>();

            int A, B, C;

            for (int j = 0; j < triangles.Count; j++)
            {
                scene.GetTriangleVertices(triangles[j], out A, out B, out C);
                int Anew = selection.SelectionPointers.IndexOf(A);
                int Bnew = selection.SelectionPointers.IndexOf(B);
                int Cnew = selection.SelectionPointers.IndexOf(C);

                // if this vertex was not selected, do not export the triangle containing it
                if (Anew == -1 || Bnew == -1 || Cnew == -1)
                {
                    continue;
                }

                // save vertex indices of triangles that were selected
                // this supports bach export
                trianglePointers.Add(triangles[j]);

                // otherwise add vertices with their new indices to list
                list.Add(Anew);
                list.Add(Bnew);
                list.Add(Cnew);

                cancel.ThrowIfCancellationRequested();
            }

            // face-header:
            writer.WriteLine("{0} {1} {2}", ELEMENT, FACE, list.Count / 3);
            writer.WriteLine("{0} list uchar int vertex_indices", PROPERTY);

            writer.WriteLine(END_HEADER);

            // vertex-data:
            int           i;
            Vector3       v3;
            Vector2       v2;
            StringBuilder sb            = new StringBuilder();
            var           selectionEnum = selection.GetEnumerator();

            int totalCount = selection.GetCount() + list.Count / 3;

            for (i = 0; i < selection.GetCount(); i++)
            {
                cancel.ThrowIfCancellationRequested();

                selectionEnum.MoveNext();
                v3 = scene.GetVertex(selectionEnum.Current);

                sb.Clear();
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0} {1} {2}", v3.X, v3.Y, v3.Z);
                if (writeNormals)
                {
                    v3 = scene.GetNormal(selectionEnum.Current);
                    sb.AppendFormat(CultureInfo.InvariantCulture, " {0} {1} {2}", v3.X, v3.Y, v3.Z);
                }
                if (writeTxtCoords)
                {
                    v2 = scene.GetTxtCoord(selectionEnum.Current);
                    sb.AppendFormat(CultureInfo.InvariantCulture, " {0} {1}", v2.X, v2.Y);
                }
                if (writeColors)
                {
                    v3 = scene.GetColor(selectionEnum.Current);
                    sb.AppendFormat(CultureInfo.InvariantCulture, " {0} {1} {2}", v3.X, v3.Y, v3.Z);
                }
                writer.WriteLine(sb.ToString());

                if (progress != null)
                {
                    progress.Report((i * 100 / totalCount).ToString());
                }
            }

            // face-data:
            for (i = 0; i < list.Count; i += 3)
            {
                writer.WriteLine("3 {0} {1} {2}", list[i], Orientation ? list[i + 2] : list[i + 1], Orientation ? list[i + 1] : list[i + 2]);

                if (progress != null)
                {
                    progress.Report(((i / 3 + selection.GetCount()) * 100 / totalCount).ToString());
                }

                cancel.ThrowIfCancellationRequested();
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Writes the whole B-rep scene to a given text stream (uses text variant of Stanford PLY format).
        /// </summary>
        /// <param name="writer">Already open text writer</param>
        /// <param name="scene">Scene to write</param>
        public void WriteBrep(StreamWriter writer, SceneBrep scene)
        {
            DoNormals   = true;
            DoTxtCoords = true;
            DoColors    = true;

            if (scene == null ||
                scene.Triangles < 1)
            {
                return;
            }

            Debug.Assert(TextFormat);
            if (!NativeNewLine)
            {
                writer.NewLine = "\r";     // CR only
            }
            bool writeNormals   = DoNormals && scene.HasNormals();
            bool writeTxtCoords = DoTxtCoords && scene.HasTxtCoords();
            bool writeColors    = DoColors && scene.HasColors();

            writer.WriteLine(HEADER);
            writer.WriteLine(FORMAT_TEXT);

            // vertex-header:
            writer.WriteLine("{0} {1} {2}", ELEMENT, VERTEX, scene.Vertices);
            writer.WriteLine("{0} float x", PROPERTY);
            writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? 'z' : 'y');
            writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? 'y' : 'z');
            if (writeNormals)
            {
                writer.WriteLine("{0} float {1}", PROPERTY, NORMAL_X);
                writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? NORMAL_Z : NORMAL_Y);
                writer.WriteLine("{0} float {1}", PROPERTY, Orientation ? NORMAL_Y : NORMAL_Z);
            }
            if (writeTxtCoords)
            {
                writer.WriteLine("{0} float {1}", PROPERTY, TEXTURE_S);
                writer.WriteLine("{0} float {1}", PROPERTY, TEXTURE_T);
            }
            if (writeColors)
            {
                writer.WriteLine("{0} float {1}", PROPERTY, COLOR_R);
                writer.WriteLine("{0} float {1}", PROPERTY, COLOR_G);
                writer.WriteLine("{0} float {1}", PROPERTY, COLOR_B);
            }

            // face-header:
            writer.WriteLine("{0} {1} {2}", ELEMENT, FACE, scene.Triangles);
            writer.WriteLine("{0} list uchar int vertex_indices", PROPERTY);

            writer.WriteLine(END_HEADER);

            // vertex-data:
            int           i;
            Vector3       v3;
            Vector2       v2;
            StringBuilder sb = new StringBuilder();

            for (i = 0; i < scene.Vertices; i++)
            {
                v3 = scene.GetVertex(i);
                sb.Clear();
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0} {1} {2}", v3.X, v3.Y, v3.Z);
                if (writeNormals)
                {
                    v3 = scene.GetNormal(i);
                    sb.AppendFormat(CultureInfo.InvariantCulture, " {0} {1} {2}", v3.X, v3.Y, v3.Z);
                }
                if (writeTxtCoords)
                {
                    v2 = scene.GetTxtCoord(i);
                    sb.AppendFormat(CultureInfo.InvariantCulture, " {0} {1}", v2.X, v2.Y);
                }
                if (writeColors)
                {
                    v3 = scene.GetColor(i);
                    sb.AppendFormat(CultureInfo.InvariantCulture, " {0} {1} {2}", v3.X, v3.Y, v3.Z);
                }
                writer.WriteLine(sb.ToString());
            }

            // face-data:
            int A, B, C;

            for (i = 0; i < scene.Triangles; i++)
            {
                scene.GetTriangleVertices(i, out A, out B, out C);
                writer.WriteLine("3 {0} {1} {2}", A, Orientation ? C : B, Orientation ? B : C);
            }
        }
Ejemplo n.º 10
0
        public void WriteBrepSelection(StreamWriter writer, SceneBrep scene, Selection selection,
                                       IProgress <string> progress, CancellationToken cancel, out List <int> trianglePointers, out List <int> vertexPointers)
        {
            vertexPointers   = selection.SelectionPointers;
            trianglePointers = new List <int>();

            if (scene == null || selection.GetCount() < 1)
            {
                return;
            }


            int i;
            var selectionEnum = selection.GetEnumerator();

            var triangles = selection.GetSelectedTriangles();
            var list      = new List <int>();

            // get vertex pointers in new mesh
            // they are dependent on its order in SelectionPointers list
            int A, B, C;

            for (int j = 0; j < triangles.Count; j++)
            {
                cancel.ThrowIfCancellationRequested();

                scene.GetTriangleVertices(triangles[j], out A, out B, out C);
                int Anew = selection.SelectionPointers.IndexOf(A);
                int Bnew = selection.SelectionPointers.IndexOf(B);
                int Cnew = selection.SelectionPointers.IndexOf(C);

                // not selected vertex
                if (Anew == -1 || Bnew == -1 || Cnew == -1)
                {
                    continue;
                }

                trianglePointers.Add(triangles[j]);

                list.Add(Anew + 1);
                list.Add(Bnew + 1);
                list.Add(Cnew + 1);
            }

            int totalCount = selection.GetCount() * 2 + list.Count / 3;

            for (i = 0; i < selection.GetCount(); i++)
            {
                cancel.ThrowIfCancellationRequested();

                selectionEnum.MoveNext();
                Vector3 v = scene.GetVertex(selectionEnum.Current);
                writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX, v.X, v.Y, v.Z }));

                if (progress != null)
                {
                    progress.Report((i / totalCount).ToString());
                }
            }

            bool hasNormals = scene.Normals > 0;

            selectionEnum = selection.GetEnumerator();
            if (hasNormals)
            {
                for (i = 0; i < selection.GetCount(); i++)
                {
                    cancel.ThrowIfCancellationRequested();

                    selectionEnum.MoveNext();
                    Vector3 n = scene.GetNormal(selectionEnum.Current);
                    writer.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", new object[] { VERTEX_NORMAL, n.X, n.Y, n.Z }));

                    if (progress != null)
                    {
                        progress.Report(((selection.GetCount() + i) * 100 / totalCount).ToString());
                    }
                }
            }

            for (i = 0; i < list.Count; i += 3)
            {
                /*if ( hasNormals )
                 * {
                 *  writer.WriteLine( "{0} {1}//{1} {2}//{2} {3}//{3}", FACE, list[ i ], list[ i + 1 ], list[ i + 2 ] );
                 * }
                 *
                 * else*/
                writer.WriteLine("{0} {1} {2} {3}", FACE, list[i], list[i + 1], list[i + 2]);

                if (progress != null)
                {
                    progress.Report(((selection.GetCount() * 2 + i / 3) * 100 / totalCount).ToString());
                }
            }
        }