/**
  * Recalculate the vertex normal, by averagin the normals of the neighboring triangles. The
  * neighbor list holds only triangles that we want to average with this vertex.
  *
  * @see GL_Object.registerNeighbors()
  * @param neighbors neighboring triangles for this vert
  * @return vertex normal
  */
 public GL_Vector recalcVertexNormal(ArrayList neighbors) {
   float nx = 0;
   float ny = 0;
   float nz = 0;
   GL_Triangle tri;
   GL_Vector wn = new GL_Vector();
   // for each neighbor triangle, average the normals
   for (int i = 0; i < neighbors.size(); i++) {
     tri = (GL_Triangle) neighbors.get(i);
     wn = tri.getWeightedNormal();
     nx += wn.x;
     ny += wn.y;
     nz += wn.z;
   }
   GL_Vector vertn = new GL_Vector(nx, ny, nz);
   vertn.normalize();
   return vertn;
 }
 // MJN: have to clone the vertices, otherwise the cloned triangle
 // points back to the same verts as the original triangle.
 // WARNING: this means that the triangle verts aren't references to the
 // verts in the vertex array.  The triangle verts are copies, so if
 // changes are made to the verts (ie. rebuild() assigns ids to them),
 // these copies won't be affected.
 public GL_Triangle makeClone() {
   GL_Triangle clone = new GL_Triangle(p1.makeClone(), p2.makeClone(), p3.makeClone());
   clone.norm1 = norm1.getClone();
   clone.norm2 = norm2.getClone();
   clone.norm3 = norm3.getClone();
   clone.uvw1 = uvw1.getClone();
   clone.uvw2 = uvw2.getClone();
   clone.uvw3 = uvw3.getClone();
   clone.neighborsP1 = (ArrayList) neighborsP1.clone();
   clone.neighborsP2 = (ArrayList) neighborsP2.clone();
   clone.neighborsP3 = (ArrayList) neighborsP3.clone();
   return clone;
 }
 public GL_Vector getWeightedNormal() {
   return GL_Vector.vectorProduct(p1.pos, p2.pos, p3.pos);
 }
 /** Calculate the face normal for this triangle */
 public void recalcFaceNormal() {
   n = GL_Vector.getNormal(p1.pos, p2.pos, p3.pos);
 }
 /**
  * Return true if two triangles should be smoothed as one surface. cos_angle is the minumum angle
  * for smoothing. If the angle between the faces is > cos_angle, then the faces are considered to
  * be a continuous surface. Ie. 90 degrees is a sharp corner, 180 degrees is a flat surface.
  */
 public static boolean onSameSurface(GL_Triangle t1, GL_Triangle t2, float cos_angle) {
   float dot = GL_Vector.dotProduct(t1.n, t2.n);
   // System.out.println("surface: compare dot=" +dot + " cos-angle=" + cos_angle + " return " +
   // (dot > cos_angle));
   return (dot > cos_angle);
 }