void ParseVertex(XmlNode xVert)
        {
            XmlNode  xcoor = xVert["coordinates"];
            float    x     = float.Parse(xcoor["x"].InnerText) * m_scaleFactor;
            float    y     = float.Parse(xcoor["y"].InnerText) * m_scaleFactor;
            float    z     = float.Parse(xcoor["z"].InnerText) * m_scaleFactor;
            Point3d  pt    = new Point3d(x, y, z);
            PointAmf pamf  = new PointAmf();

            pamf.pt = pt;

            // add normal if exists
            XmlNode xnorm = xVert["normal"];

            if (xnorm != null)
            {
                m_smoothObj = true;
                x           = float.Parse(xnorm["nx"].InnerText);
                y           = float.Parse(xnorm["ny"].InnerText);
                z           = float.Parse(xnorm["nz"].InnerText);
                pamf.normal = new Vector3d(x, y, z);
            }

            m_pointList.Add(pamf);
        }
        // split edge v1-v2. v3 is the last corner in the triangle and is used for computing normals

/*        int SplitEdge(int v1, int v2, int v3)
 *      {
 *          Vector3d norm1 = CalcNormal(v1, v2, v3);
 *          Vector3d norm2 = CalcNormal(v2, v3, v1);
 *          EdgeAmf edge = m_pointList[v1].FindEdge(v2);
 *          if (edge == null)
 *          {
 *              edge = m_pointList[v2].FindEdge(v1);
 *              if (edge != null)
 *              {
 *                  // swap verteces tomatch edge
 *                  int tv = v1;
 *                  v1 = v2;
 *                  v2 = tv;
 *                  Vector3d tnorm = norm1;
 *                  norm1 = norm2;
 *                  norm2 = tnorm;
 *              }
 *          }
 *
 *          Vector3d t1, t2;
 *          PointAmf pamf1 = m_pointList[v1];
 *          PointAmf pamf2 = m_pointList[v2];
 *          Point3d pt1 = pamf1.pt;
 *          Point3d pt2 = pamf2.pt;
 *          PointAmf pamf;
 *          float x, y, z;
 *
 *          // calculate edge vector
 *          x = pt2.x - pt1.x;
 *          y = pt2.y - pt1.y;
 *          z = pt2.z - pt1.z;
 *          Vector3d edgeDir = new Vector3d(x, y, z);
 *
 *          // first see if we have an edge for this segment
 *          if (edge != null)
 *          {
 *              // if this edge was already split, return result
 *              if (edge.v12 >= 0)
 *                  return edge.v12;
 *              t1 = edge.t1;
 *              t2 = edge.t2;
 *          }
 *          /*else if ((pamf1.normal == null) && (pamf2.normal == null))
 *          {
 *              // its a linear line, return the center
 *              x = (pamf1.pt.x + pamf2.pt.x) / 2.0f;
 *              y = (pamf1.pt.y + pamf2.pt.y) / 2.0f;
 *              z = (pamf1.pt.z + pamf2.pt.z) / 2.0f;
 *              pamf = new PointAmf();
 *              pamf.pt = new Point3d(x, y, z);
 *              m_pointList.Add(pamf);
 *              return m_pointList.Count - 1;
 *          }
 *          else
 *          {
 *              // calculate tangets from normals.
 *              //edgeDir.Normalize();
 *              t1 = GetTangetFromNormal(norm1, edgeDir);
 *              t2 = GetTangetFromNormal(norm2, edgeDir);
 *              /*if (pamf1.normal == null)
 *                  pamf1.normal = norm1;
 *              if (pamf2.normal == null)
 *                  pamf2.normal = norm2;
 *          }
 *
 *          float d = edgeDir.Mag();
 *
 *          // calculate mid point using Hermite interpolation
 *          x = 0.5f * pt1.x + 0.125f * t1.x * d + 0.5f * pt2.x - 0.125f * t2.x * d;
 *          y = 0.5f * pt1.y + 0.125f * t1.y * d + 0.5f * pt2.y - 0.125f * t2.y * d;
 *          z = 0.5f * pt1.z + 0.125f * t1.z * d + 0.5f * pt2.z - 0.125f * t2.z * d;
 *
 *          pamf = new PointAmf();
 *          pamf.pt = new Point3d(x, y, z);
 *          int v = m_pointList.Count;
 *          m_pointList.Add(pamf);
 *
 *          // calculate new tanget and new normal
 *          x = -1.5f * pt1.x - 0.25f * t1.x * d + 1.5f * pt2.x - 0.25f * t2.x * d;
 *          y = -1.5f * pt1.y - 0.25f * t1.y * d + 1.5f * pt2.y - 0.25f * t2.y * d;
 *          z = -1.5f * pt1.z - 0.25f * t1.z * d + 1.5f * pt2.z - 0.25f * t2.z * d;
 *          Vector3d tanget = new Vector3d(x, y, z);
 *          tanget.Normalize();
 *
 *          Vector3d tvec = (norm1 * 0.5f) + (norm2 * 0.5f);
 *          tvec = Vector3d.cross(tvec, tanget);
 *          pamf.normal = Vector3d.cross(tanget, tvec);
 *
 *          if (edge == null)
 *          {
 *              //pamf.normal = GetNormalFromTanget(norm1, tanget);
 *              // create an edge for this segment
 *              edge = new EdgeAmf();
 *              edge.v1 = v1;
 *              edge.v2 = v2;
 *              edge.t1 = t1;
 *              edge.t2 = t2;
 *              pamf1.AddEdge(edge);
 *          }
 *          edge.v12 = m_pointList.Count - 1; // saves double computation
 *
 *          //tanget.Normalize();
 *          // save 2 split edges
 *          EdgeAmf edge1 = new EdgeAmf();
 *          edge1.v1 = v1;
 *          edge1.v2 = v;
 *          edge1.t1 = t1;
 *          edge1.t2 = tanget;
 *          pamf1.AddEdge(edge1);
 *
 *          EdgeAmf edge2 = new EdgeAmf();
 *          edge2.v1 = v;
 *          edge2.v2 = v2;
 *          edge2.t1 = tanget;
 *          edge2.t2 = t2;
 *          pamf.AddEdge(edge2);
 *
 *          return v;
 *      }*/

        // calc normal at corner v (looking at the triangle when corner v is at the bottom, v1 at top right, and v2 is at to left
        Vector3d CalcNormal(int v, int v1, int v2)
        {
            PointAmf pamf = m_pointList[v];

            if (pamf.normal != null)
            {
                return(pamf.normal);
            }
            Vector3d t1     = GetTanget(v, v1);
            Vector3d t2     = GetTanget(v, v2);
            Vector3d normal = Vector3d.cross(t1, t2);

            normal.Normalize();
            return(normal);
        }
        // split edge v1-v2. v3 is the last corner in the triangle and is used for computing normals
        int SplitEdge(int v1, int v2, Vector3d norm1, Vector3d norm2, out Vector3d norm12)
        {
            EdgeAmf edge = m_pointList[v1].FindEdge(v2);

            if (edge == null)
            {
                edge = m_pointList[v2].FindEdge(v1);
                if (edge != null)
                {
                    // swap verteces to match edge
                    int tv = v1;
                    v1 = v2;
                    v2 = tv;
                    Vector3d tnorm = norm1;
                    norm1 = norm2;
                    norm2 = tnorm;
                }
            }

            Vector3d t1, t2;
            PointAmf pamf1 = m_pointList[v1];
            PointAmf pamf2 = m_pointList[v2];
            Point3d  pt1   = pamf1.pt;
            Point3d  pt2   = pamf2.pt;
            PointAmf pamf;
            float    x, y, z;

            // calculate edge vector
            x = pt2.x - pt1.x;
            y = pt2.y - pt1.y;
            z = pt2.z - pt1.z;
            Vector3d edgeDir = new Vector3d(x, y, z);

            // first see if we have an edge for this segment
            if (edge != null)
            {
                // if this edge was already split, return result
                if (edge.v12 >= 0)
                {
                    norm12 = CalcCenterNormal(norm1, norm2, edge.t12);
                    return(edge.v12);
                }
                t1 = edge.t1;
                t2 = edge.t2;
            }
            else
            {
                t1 = GetTangetFromNormal(norm1, edgeDir);
                t2 = GetTangetFromNormal(norm2, edgeDir);
            }

            float d = edgeDir.Mag();

            // calculate mid point using Hermite interpolation
            x = 0.5f * pt1.x + 0.125f * t1.x * d + 0.5f * pt2.x - 0.125f * t2.x * d;
            y = 0.5f * pt1.y + 0.125f * t1.y * d + 0.5f * pt2.y - 0.125f * t2.y * d;
            z = 0.5f * pt1.z + 0.125f * t1.z * d + 0.5f * pt2.z - 0.125f * t2.z * d;

            pamf    = new PointAmf();
            pamf.pt = new Point3d(x, y, z);
            int v = m_pointList.Count;

            m_pointList.Add(pamf);

            // calculate new tanget and new normal
            x = -1.5f * pt1.x - 0.25f * t1.x * d + 1.5f * pt2.x - 0.25f * t2.x * d;
            y = -1.5f * pt1.y - 0.25f * t1.y * d + 1.5f * pt2.y - 0.25f * t2.y * d;
            z = -1.5f * pt1.z - 0.25f * t1.z * d + 1.5f * pt2.z - 0.25f * t2.z * d;
            Vector3d tanget = new Vector3d(x, y, z);

            tanget.Normalize();

            norm12 = CalcCenterNormal(norm1, norm2, tanget);

            if (edge == null)
            {
                //pamf.normal = GetNormalFromTanget(norm1, tanget);
                // create an edge for this segment
                edge    = new EdgeAmf();
                edge.v1 = v1;
                edge.v2 = v2;
                edge.t1 = t1;
                edge.t2 = t2;
                pamf1.AddEdge(edge);
            }
            edge.t12 = tanget;
            edge.v12 = m_pointList.Count - 1; // saves double computation

            //tanget.Normalize();
            // save 2 split edges
            EdgeAmf edge1 = new EdgeAmf();

            edge1.v1 = v1;
            edge1.v2 = v;
            edge1.t1 = t1;
            edge1.t2 = tanget;
            pamf1.AddEdge(edge1);

            EdgeAmf edge2 = new EdgeAmf();

            edge2.v1 = v;
            edge2.v2 = v2;
            edge2.t1 = tanget;
            edge2.t2 = t2;
            pamf.AddEdge(edge2);

            return(v);
        }
        // split edge v1-v2. v3 is the last corner in the triangle and is used for computing normals
        int SplitEdge(int v1, int v2, Vector3d norm1, Vector3d norm2, out Vector3d norm12)
        {
            EdgeAmf edge = m_pointList[v1].FindEdge(v2);
            if (edge == null)
            {
                edge = m_pointList[v2].FindEdge(v1);
                if (edge != null)
                {
                    // swap verteces to match edge
                    int tv = v1;
                    v1 = v2;
                    v2 = tv;
                    Vector3d tnorm = norm1;
                    norm1 = norm2;
                    norm2 = tnorm;
                }
            }

            Vector3d t1, t2;
            PointAmf pamf1 = m_pointList[v1];
            PointAmf pamf2 = m_pointList[v2];
            Point3d pt1 = pamf1.pt;
            Point3d pt2 = pamf2.pt;
            PointAmf pamf;
            float x, y, z;

            // calculate edge vector
            x = pt2.x - pt1.x;
            y = pt2.y - pt1.y;
            z = pt2.z - pt1.z;
            Vector3d edgeDir = new Vector3d(x, y, z);

            // first see if we have an edge for this segment
            if (edge != null)
            {
                // if this edge was already split, return result
                if (edge.v12 >= 0)
                {
                    norm12 = CalcCenterNormal(norm1, norm2, edge.t12);
                    return edge.v12;
                }
                t1 = edge.t1;
                t2 = edge.t2;
            }
             else
            {
                t1 = GetTangetFromNormal(norm1, edgeDir);
                t2 = GetTangetFromNormal(norm2, edgeDir);
            }

            float d = edgeDir.Mag();

            // calculate mid point using Hermite interpolation
            x = 0.5f * pt1.x + 0.125f * t1.x * d + 0.5f * pt2.x - 0.125f * t2.x * d;
            y = 0.5f * pt1.y + 0.125f * t1.y * d + 0.5f * pt2.y - 0.125f * t2.y * d;
            z = 0.5f * pt1.z + 0.125f * t1.z * d + 0.5f * pt2.z - 0.125f * t2.z * d;

            pamf = new PointAmf();
            pamf.pt = new Point3d(x, y, z);
            int v = m_pointList.Count;
            m_pointList.Add(pamf);

            // calculate new tanget and new normal
            x = -1.5f * pt1.x - 0.25f * t1.x * d + 1.5f * pt2.x - 0.25f * t2.x * d;
            y = -1.5f * pt1.y - 0.25f * t1.y * d + 1.5f * pt2.y - 0.25f * t2.y * d;
            z = -1.5f * pt1.z - 0.25f * t1.z * d + 1.5f * pt2.z - 0.25f * t2.z * d;
            Vector3d tanget = new Vector3d(x, y, z);
            tanget.Normalize();

            norm12 = CalcCenterNormal(norm1, norm2, tanget);
            
            if (edge == null)
            {
                //pamf.normal = GetNormalFromTanget(norm1, tanget);
                // create an edge for this segment
                edge = new EdgeAmf();
                edge.v1 = v1;
                edge.v2 = v2;
                edge.t1 = t1;
                edge.t2 = t2;
                pamf1.AddEdge(edge);
            }
            edge.t12 = tanget;
            edge.v12 = m_pointList.Count - 1; // saves double computation 

            //tanget.Normalize();
            // save 2 split edges
            EdgeAmf edge1 = new EdgeAmf();
            edge1.v1 = v1;
            edge1.v2 = v;
            edge1.t1 = t1;
            edge1.t2 = tanget;
            pamf1.AddEdge(edge1);

            EdgeAmf edge2 = new EdgeAmf();
            edge2.v1 = v;
            edge2.v2 = v2;
            edge2.t1 = tanget;
            edge2.t2 = t2;
            pamf.AddEdge(edge2);

            return v;
        }
        void ParseVertex(XmlNode xVert)
        {
            XmlNode xcoor = xVert["coordinates"];
            float x = float.Parse(xcoor["x"].InnerText) * m_scaleFactor;
            float y = float.Parse(xcoor["y"].InnerText) * m_scaleFactor;
            float z = float.Parse(xcoor["z"].InnerText) * m_scaleFactor;
            Point3d pt = new Point3d(x, y, z);
            PointAmf pamf= new PointAmf();
            pamf.pt = pt;

            // add normal if exists
            XmlNode xnorm = xVert["normal"];
            if (xnorm != null)
            {
                m_smoothObj = true;
                x = float.Parse(xnorm["nx"].InnerText);
                y = float.Parse(xnorm["ny"].InnerText);
                z = float.Parse(xnorm["nz"].InnerText);
                pamf.normal = new Vector3d(x, y, z);
            }

            m_pointList.Add(pamf);
        }