⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 normalgenerator.java

📁 JAVA3D矩陈的相关类
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
  // The original data was in quads.  We converted it to triangles to  // calculate normals.  Now we need to convert it back to quads.   private void convertTriToQuad(GeometryInfo geom)  {    // Create the new arrays    geom.setCoordinateIndices(      triToQuadIndices(geom.getCoordinateIndices()));    geom.setColorIndices(triToQuadIndices(geom.getColorIndices()));    geom.setNormalIndices(triToQuadIndices(geom.getNormalIndices()));    int num = geom.getTexCoordSetCount();    for (int i = 0 ; i < num ; i++) {      geom.setTextureCoordinateIndices(i,	triToQuadIndices(geom.getTextureCoordinateIndices(i)));    }    geom.setPrimitive(gi.QUAD_ARRAY);  } // End of convertTriToQuad()  // The original data was in fans and we converted it to triangles to  // calculate the normals.  Now we are converting it back to fans.  // We have already calculated the new stripCounts, so now we need  // to change the index lists so they match up with the stripCounts.  // It's a very simple algorithm.  The paramater oldList is the   // index list being compressed back into fans (could be coordinate,  // color, normal, or texCoord indices) and numVerts is the pre-  // calculated total of all entries of the stripCounts array.  private int[] triToFanIndices(int sc[], int oldList[], int numVerts)  {    if (oldList == null) return null;    int newList[] = new int[numVerts];		// index list to pass back    int vert1 = 0;				// 1st vertex of triangle    int n = 0;					// index into newList    // Cycle through each fan in the new list    for (int f = 0 ; f < sc.length ; f++) {      // Copy entire first triangle into new array      newList[n++] = oldList[vert1++];      newList[n++] = oldList[vert1++];      newList[n++] = oldList[vert1++];      // Each additional triangle in the fan only needs one vertex      for (int t = 3 ; t < sc[f] ; t++) {	newList[n++] = oldList[vert1 + 2];	vert1 += 3;      }    }    return newList;  } // End of triToFanIndices  //  // The original data was in fans.  We converted it to triangles to  // calculate normals.  Now we need to convert it back to fans.   // The hard part is that, if we found a hard edge in the middle of  // a fan, we need to split the fan into two.  To tell if there's  // a hard edge there, we compare the normal indices of both  // vertices comprising the edge.  private void convertTriToFan(GeometryInfo geom, int oldStripCounts[])  {    int ni[] = geom.getNormalIndices();    //    // Calculate new stripCounts array    //    int tri = 0;	// Which triangle currently being converted    ArrayList newStripCounts;    newStripCounts = new ArrayList(oldStripCounts.length + 100);    // Use the original stripCounts array    for (int f = 0 ; f < oldStripCounts.length ; f++) {      int stripCount = 3;      // Cycle through each triangle in the fan, comparing to the      // next triangle in the fan.  Compare the normal indices of      // both vertices of the edge to see if the two triangles      // can be mated      for (int t = 0 ; t < oldStripCounts[f] - 3 ; t++) {	// The first vertex of this triangle must match the first	// vertex of the next, AND the third vertex of this	// triangle must match the second vertex of the next.	if ((ni[tri * 3] == ni[(tri+1) * 3]) &&	    (ni[tri * 3 + 2] == ni[(tri+1) * 3 + 1])) {	  // OK to extend fan	  stripCount++;	} else {	  // hard edge within fan	  newStripCounts.add(new Integer(stripCount));	  stripCount = 3;	}	tri++;      }      tri++;      newStripCounts.add(new Integer(stripCount));    }    // Convert from ArrayList to int[]    int sc[] = new int[newStripCounts.size()];    for (int i = 0 ; i < sc.length ; i++)      sc[i] = ((Integer)newStripCounts.get(i)).intValue();    newStripCounts = null;    //    // Change the index lists so they match up with the new stripCounts    //    // See how many vertices we'll need    int c = 0;    for (int i = 0 ; i < sc.length ; i++) c += sc[i];    // Create the new arrays    geom.setCoordinateIndices(      triToFanIndices(sc, geom.getCoordinateIndices(), c));    geom.setColorIndices(triToFanIndices(sc, geom.getColorIndices(), c));    geom.setNormalIndices(triToFanIndices(sc, geom.getNormalIndices(), c));    int num = geom.getTexCoordSetCount();    for (int i = 0 ; i < num ; i++) {      geom.setTextureCoordinateIndices(i, 	triToFanIndices(sc, geom.getTextureCoordinateIndices(i), c));    }    if ((DEBUG & 8) != 0) {      System.out.print("Old stripCounts:");      for (int i = 0 ; i < oldStripCounts.length ; i++) {	System.out.print(" " + oldStripCounts[i]);      }      System.out.println();      System.out.print("New stripCounts:");      for (int i = 0 ; i < sc.length ; i++) {	System.out.print(" " + sc[i]);      }      System.out.println();    }    geom.setStripCounts(sc);    geom.setPrimitive(gi.TRIANGLE_FAN_ARRAY);  } // End of convertTriToFan()  // The original data was in strips and we converted it to triangles to  // calculate the normals.  Now we are converting it back to strips.  // We have already calculated the new stripCounts, so now we need  // to change the index lists so they match up with the stripCounts.  // It's a very simple algorithm.  The paramater oldList is the   // index list being compressed back into strips (could be coordinate,  // color, normal, or texCoord indices) and numVerts is the pre-  // calculated total of all entries of the stripCounts array.  private int[] triToStripIndices(int sc[], int oldList[], int numVerts)  {    if (oldList == null) return null;    int newList[] = new int[numVerts];		// index list to pass back    int vert1 = 0;				// 1st vertex of triangle    int n = 0;					// index into newList    // Cycle through each strip in the new list    for (int f = 0 ; f < sc.length ; f++) {      // Copy entire first triangle into new array      newList[n++] = oldList[vert1++];      newList[n++] = oldList[vert1++];      newList[n++] = oldList[vert1++];      // Each additional triangle in the fan only needs one vertex      for (int t = 3 ; t < sc[f] ; t++) {	// Every other triangle has been reversed to preserve winding	newList[n++] = oldList[vert1 + 2 - (t % 2)];	vert1 += 3;      }    }    return newList;  } // End of triToStripIndices  private void convertTriToStrip(GeometryInfo geom, int oldStripCounts[])  {    int ni[] = geom.getNormalIndices();    //    // Calculate new stripCounts array    //    int tri = 0;	// Which triangle currently being converted    ArrayList newStripCounts;    newStripCounts = new ArrayList(oldStripCounts.length + 100);    // Use the original stripCounts array    for (int f = 0 ; f < oldStripCounts.length ; f++) {      int stripCount = 3;      // Cycle through each triangle in the strip, comparing to the      // next triangle in the strip.  Compare the normal indices of      // both vertices of the edge to see if the two triangles      // can be mated.      for (int t = 0 ; t < oldStripCounts[f] - 3 ; t++) {	// Every other triangle has been reversed to preserve winding	if (t % 2 == 0) {	  // The middle vertex of this triangle needs to match the	  // first vertex of the next, AND the third vertices of	  // the two triangles must match	  if ((ni[tri * 3 + 1] == ni[(tri+1) * 3]) &&	      (ni[tri * 3 + 2] == ni[(tri+1) * 3 + 2])) {	    // OK to extend strip	    stripCount++;	  } else {	    // hard edge within strip	    newStripCounts.add(new Integer(stripCount));	    stripCount = 3;	    // Can't start a new strip on an odd edge so output	    // isolated triangle	    if (t < oldStripCounts[f] - 4) {	      newStripCounts.add(new Integer(3));	      t++;	    }	  }	} else {	  // The middle vertex of this triangle must match the middle 	  // vertex of the next, AND the third vertex of this triangle	  // must match the first vertex of the next	  if ((ni[tri * 3 + 1] == ni[(tri+1) * 3 + 1]) &&	      (ni[tri * 3 + 2] == ni[(tri+1) * 3])) {	    // OK to extend strip	    stripCount++;	  } else {	    // hard edge within strip	    newStripCounts.add(new Integer(stripCount));	    stripCount = 3;	  }	}	tri++;      }      tri++;      newStripCounts.add(new Integer(stripCount));    }    // Convert from ArrayList to int[]    int sc[] = new int[newStripCounts.size()];    for (int i = 0 ; i < sc.length ; i++)      sc[i] = ((Integer)newStripCounts.get(i)).intValue();    newStripCounts = null;    //    // Change the index lists so they match up with the new stripCounts    //    // See how many vertices we'll need    int c = 0;    for (int i = 0 ; i < sc.length ; i++) c += sc[i];    // Create the new arrays    geom.setCoordinateIndices(      triToStripIndices(sc, geom.getCoordinateIndices(), c));    geom.setColorIndices(triToStripIndices(sc, geom.getColorIndices(), c));    geom.setNormalIndices(triToStripIndices(sc, geom.getNormalIndices(), c));    int num = geom.getTexCoordSetCount();    for (int i = 0 ; i < num ; i++) {      geom.setTextureCoordinateIndices(i, 	triToStripIndices(sc, geom.getTextureCoordinateIndices(i), c));    }    if ((DEBUG & 8) != 0) {      System.out.print("Old stripCounts:");      for (int i = 0 ; i < oldStripCounts.length ; i++) {	System.out.print(" " + oldStripCounts[i]);      }      System.out.println();      System.out.print("New stripCounts:");      for (int i = 0 ; i < sc.length ; i++) {	System.out.print(" " + sc[i]);      }      System.out.println();    }    geom.setStripCounts(sc);    geom.setPrimitive(gi.TRIANGLE_STRIP_ARRAY);  }// End of convertTriToStrip()  /**   * Used when the user calls the NormalGenerator and not   * the Stripifier or Triangulator.   We had to convert   * the user's data to indexed triangles before we could   * generate normals, so now we need to switch back to   * the original format.   */  void convertBackToOldPrim(GeometryInfo geom, int oldPrim,			    int oldStripCounts[])  {    if (oldPrim == geom.TRIANGLE_ARRAY) return;    switch (oldPrim) {    case GeometryInfo.QUAD_ARRAY:      convertTriToQuad(geom);      break;    case GeometryInfo.TRIANGLE_FAN_ARRAY:      convertTriToFan(geom, oldStripCounts);      break;    case GeometryInfo.TRIANGLE_STRIP_ARRAY:      convertTriToStrip(geom, oldStripCounts);      break;    }    if ((DEBUG & 64) != 0) {      System.out.println("Coordinate and normal indices (original):");      for (int i = 0 ; i < coordInds.length ; i++) {	System.out.println(i + "  " + coordInds[i] + "  " + normalInds[i]);      }    }  } // End of convertBackToOldPrim  /**   * Generate normals for the GeometryInfo object.  If the GeometryInfo   * object didn't previously contain indexed data, indexes are made   * by collapsing identical positions into a single index.  Any   * normal information previously contained in the GeometryInfo    * object is lost.  Strips and Fans are converted into individual   * triangles for Normal generation, but are stitched back together   * if GeometryInfo.getGeometryArray() (or getIndexedGeometryArray())   * is called without stripifying first.   */  public void generateNormals(GeometryInfo geom)  {    gi = geom;    gi.setNormals((Vector3f[])null);    gi.setNormalIndices(null);    long time = 0L;    if ((DEBUG & 16) != 0) {      time = System.currentTimeMillis();    }    if (gi.getPrimitive() == gi.POLYGON_ARRAY) {      if (tr == null) tr = new Triangulator();      tr.triangulate(gi);    } else {      // NOTE:  We should calculate facet normals before converting to      // triangles.      gi.rememberOldPrim();      gi.convertToIndexedTriangles();    }    // Cache some of the GeometryInfo fields    coordInds = gi.getCoordinateIndices();    colorInds = gi.getColorIndices();    normalInds = gi.getNormalIndices();    numTexSets = gi.getTexCoordSetCount();    texInds = new int[numTexSets][];    for (int i = 0 ; i < numTexSets ; i++) {      texInds[i] = gi.getTextureCoordinateIndices(i);    }    stripCounts = gi.getStripCounts();    if ((DEBUG & 16) != 0) {      t1 += System.currentTimeMillis() - time;      System.out.println("Convert to triangles: " + t1 + " ms");      time = System.currentTimeMillis();    }          calculatefacetNorms();    if ((DEBUG & 16) != 0) {      t2 += System.currentTimeMillis() - time;      System.out.println("Calculate Facet Normals: " + t2 + " ms");      time = System.currentTimeMillis();    }          int maxShare = createHardEdges();    if ((DEBUG & 16) != 0) {      t3 += System.currentTimeMillis() - time;      System.out.println("Hard Edges: " + t3 + " ms");      time = System.currentTimeMillis();    }          calculateVertexNormals(maxShare);    if ((DEBUG & 16) != 0) {      t5 += System.currentTimeMillis() - time;      System.out.println("Vertex Normals: " + t5 + " ms");      time = System.currentTimeMillis();    }    if ((DEBUG & 64) != 0) {      System.out.println("Coordinate and normal indices (triangles):");      for (int i = 0 ; i < coordInds.length ; i++) {	System.out.println(i + "  " + coordInds[i] + "  " + normalInds[i]);      }    }          // We have been caching some info from the GeometryInfo, so we need    // to update it.    gi.setCoordinateIndices(coordInds);    gi.setColorIndices(colorInds);    gi.setNormalIndices(normalInds);    for (int i = 0 ; i < numTexSets ; i++) {      gi.setTextureCoordinateIndices(i, texInds[i]);    }    gi.setStripCounts(stripCounts);  } // End of generateNormals  /**   * Set the crease angle.     * If two triangles' normals differ by more than   * creaseAngle, then the vertex will get two separate normals, creating a    * discontinuous crease in the model.  This is perfect for the edge   * of a table or the corner of a cube, for instance.  Clamped to   * 0 <= creaseAngle <= PI.  Optimizations are made for creaseAngle == 0   * (facet normals) and creaseAngle == PI (smooth shading).   */  public void setCreaseAngle(double radians)  {    if (radians > Math.PI) radians = Math.PI;    if (radians < 0.0) radians = 0.0;    creaseAngle = radians;  } // End of setCreaseAngle  /**   * Returns the current value of the crease angle, in radians.   */  public double getCreaseAngle()  {    return creaseAngle;  } // End of getCreaseAngle  /**   * Constructor.  Construct a NormalGenerator object with creaseAngle   * set to the given value.   */  public NormalGenerator(double radians)  {    creaseAngle = radians;  } // End of NormalGenerator(double)  /**   * Constructor.  Construct a NormalGenerator object with creaseAngle   * set to 44 degrees (0.767944871 radians).   */  public NormalGenerator()  {    this(44.0 * Math.PI / 180.0);  } // End of NormalGenerator()} // End of class NormalGenerator// End of file NormalGenerator.java

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -