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

📄 subdivisionbutterfly.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			Vector vert = new Vector(bufferElementSize); 
			vert.populateFromBuffer(vb, vertexIndex);
			//c = 1 - (1/((double)k-1))*Math.sin(theta)*Math.sin((double)i*theta) / (1d-Math.cos(theta)); 
			c = 1d - (Math.sin(theta)*Math.sin((double)i*theta))/((double)k*(1d-Math.cos(theta)));
			vert.multLocal((float)c);
			result.addLocal(vert);
			
			for (j=0; j < valence; j++) {
				
				vert.populateFromBuffer(vb, v[j]);
				
				if (j == 0 || j == (valence-1)) { 
					//c = 1d/4d * Math.cos((double)i*theta) - (1d/4d*(double)(k-1))*Math.sin(2d*theta)*Math.sin(2d*(double)i*theta) / (Math.cos(theta)-Math.cos(2d*theta));
					c = 1d/4d * Math.cos((double)i*theta) - ( Math.sin(2d*theta)*Math.sin(2d*(double)i*theta) )/(4d*(double)k*(Math.cos(theta) - Math.cos(2d*theta)));
					if (j == (valence-1)) c = -c;
				} else {
					//c = (1d/(double)k)*(Math.sin((double)i*theta)*Math.sin((double)j*theta) + (1d/2d) * Math.sin(2d*(double)i*theta)*Math.sin(2d*(double)j*theta));
					c = 1d/(double)k * (Math.sin((double)i*theta)*Math.sin((double)j*theta) + (1d/2d)*Math.sin(2d*(double)i*theta)*Math.sin(2d*(double)j*theta));
				}
				
				vert.multLocal((float)c);
				result.addLocal(vert);
			}
			return result;
		}
		
		private static Vector regularCreaseCrease(Edge edge, FloatBuffer vb, int bufferElementSize, ArrayList<Edge>[] vertexEdgeMap) {	
			Vector result = new Vector(bufferElementSize);
			Vector vert;
			
			boolean rule1 = false;
			
			ArrayList<Edge> edges0, edges1, tempEdges;
			edges0 = vertexEdgeMap[edge.vertexIndex[0]];
			edges1 = vertexEdgeMap[edge.vertexIndex[1]];
			
			// If we are the base of a triangle in a corner 
			// (i.e. if the two vertices are joined by a third crease vertex)
			// We do crease-crease rule 1, else we do 4-point crease rule (which also approximates crease-crease rule 2, for now)
			int vertex0 = -1, vertex1 = -1;
			if (edges0.get(0).otherVertex(edge.vertexIndex[0]) == edges1.get(3).otherVertex(edge.vertexIndex[1])) {
				// Rule 1
				rule1 = true;
				vertex0 = edge.vertexIndex[0]; // corner vertex is the most clockwise edge
				vertex1 = edge.vertexIndex[1]; // corner vertex is the most counter-clockwise edge
			} else if (edges0.get(3).otherVertex(edge.vertexIndex[0]) == edges1.get(0).otherVertex(edge.vertexIndex[1])) {
				// Rule 2
				rule1 = true;
				vertex0 = edge.vertexIndex[1]; // corner vertex is the most clockwise edge
				vertex1 = edge.vertexIndex[0]; // corner vertex is the most counter-clockwise edge
				// Flip also the edgelists
				tempEdges = edges1;	edges1 = edges0; edges0 = tempEdges; tempEdges = null;
			} else {
				// 4-point regular butterfly rule
				rule1 = false;
			}
			if (rule1) {
				// edges0.get(0) is the corner vertex, also the most clockwise edge
				// edges1.get(3) is the corner vertex, also the most counter-clockwise edge
				// Do the first vertex of the splitting edge
				vert = new Vector(bufferElementSize); 
				vert.populateFromBuffer(vb, vertex0);
				vert.multLocal(1f/2f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, edges0.get(2).otherVertex(vertex0));
				vert.multLocal(1f/4f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, edges0.get(3).otherVertex(vertex0));
				vert.multLocal(-1f/8f);
				result.addLocal(vert);
				
				// Do the second vertex of the splitting edge
				vert.populateFromBuffer(vb, vertex1);
				vert.multLocal(1f/2f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, edges1.get(0).otherVertex(vertex1));
				vert.multLocal(-1f/8f);
				result.addLocal(vert);
				
				// finished Crease-Crease Rule 1
				
			} else {
				// 4-point regular butterfly rule ( +---+-*-+---+ )
				if (edges0.get(0).equals(edge)) {
					vertex0 = edge.vertexIndex[1]; 
					vertex1 = edge.vertexIndex[0]; 
					// Flip also the edgelists
					tempEdges = edges1;	edges1 = edges0; edges0 = tempEdges; tempEdges = null;
				} else {
					vertex0 = edge.vertexIndex[0]; 
					vertex1 = edge.vertexIndex[1]; 
				}
				vert = new Vector(bufferElementSize); 
				// Do the first vertex of the splitting edge
				vert.populateFromBuffer(vb, vertex0);
				vert.multLocal(9f/16f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, edges0.get(0).otherVertex(vertex0));
				vert.multLocal(-1f/16f);
				result.addLocal(vert);
				
				// Do the second vertex of the splitting edge
				vert.populateFromBuffer(vb, vertex1);
				vert.multLocal(9f/16f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, edges1.get(3).otherVertex(vertex1));
				vert.multLocal(-1f/16f);
				result.addLocal(vert);
				
				// finished 4-point regular butterfly rule
			}
			return result;
		}
		
		private static Vector regularInteriorCrease(Edge edge, int vertexIndex, FloatBuffer vb, int bufferElementSize, ArrayList<Edge> interiorEdges, ArrayList<Edge> creaseEdges) {
			Vector result = new Vector(bufferElementSize);
			Vector vert;
			
			int v[] = new int[6];
			
			// First take care of the interior vertex
			// Fast forward the edgeMap to the edge we're starting at
			Iterator<Edge> it = interiorEdges.iterator();
			while (it.hasNext() && (!edge.equals(it.next())));		
			
			// circle around the interior vertex counter clock wise and find all vertices 
			for (int i=0 ; i<6 ; i++) {
				if (!it.hasNext()) 
					it = interiorEdges.iterator();
				v[i] = it.next().otherVertex(vertexIndex);
			}
			// v[0] is the first vertex counted CCW from the edge to split
			vert = new Vector(bufferElementSize); 
			vert.populateFromBuffer(vb, vertexIndex);
			vert.multLocal(5f/8f);
			result.addLocal(vert);
			vert.populateFromBuffer(vb, v[0]);
			vert.multLocal(3f/16f);
			result.addLocal(vert);
			vert.populateFromBuffer(vb, v[1]);
			vert.multLocal(-1f/8f);
			result.addLocal(vert);
			vert.populateFromBuffer(vb, v[3]);
			vert.multLocal(-1f/16f);
			result.addLocal(vert);
			vert.populateFromBuffer(vb, v[4]);
			vert.multLocal(1f/16f);
			result.addLocal(vert);
			vert.populateFromBuffer(vb, v[5]);
			vert.multLocal(3f/8f);
			result.addLocal(vert);
			
			// now the crease/boundary vertex
			// Since it's a crease-edge we know that the first index in the map is the edge 
			// that is the most clock-wise 
			vert.populateFromBuffer(vb, creaseEdges.get(0).otherVertex(edge.otherVertex(vertexIndex)));
			vert.multLocal(-1f/16f);
			result.addLocal(vert);			
			
			return result;
		}
		
		private static Vector extraordinaryInterior(Edge edge, int vertexIndex, FloatBuffer vb, int bufferElementSize, ArrayList<Edge> edges, ArrayList<Triangle> triangles) {
			Vector result = new Vector(bufferElementSize);
			int valence = edges.size();
			int v[] = new int[valence];
			Edge tempEdge = null;
			
			// spola fram i edgeMappen till edgen a1-a2
			Iterator<Edge> it = edges.iterator();
			while (it.hasNext() && (!edge.equals(tempEdge = it.next())));			
			
			// circle around the vertex counter clock-wise and find all vertices 
			for (int i=0 ; i<valence ; i++) {
				v[i] = tempEdge.otherVertex(vertexIndex);
				if (!it.hasNext()) 
					it = edges.iterator();
				tempEdge = it.next();
			}
			
			
			Vector vert = new Vector(bufferElementSize);
			if (valence == 3) {
				vert.populateFromBuffer(vb, vertexIndex);
				vert.multLocal(3f/4f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, v[0]);
				vert.multLocal(5f/12f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, v[1]);
				vert.multLocal(-(1f/12f));
				result.addLocal(vert);
				vert.populateFromBuffer(vb, v[2]);
				vert.multLocal(-(1f/12f));
				result.addLocal(vert);
				
			} else if (valence == 4) {
				vert.populateFromBuffer(vb, vertexIndex);
				vert.multLocal(3f/4f);
				result.addLocal(vert);
				vert.populateFromBuffer(vb, v[0]);
				vert.multLocal(3f/8f);
				result.addLocal(vert);
				//vert.populateFromBuffer(vb, v[1]);
				//vert.multLocal(0f);
				//result.addLocal(vert);
				vert.populateFromBuffer(vb, v[2]);
				vert.multLocal(-1f/8f);
				result.addLocal(vert);
				//vert.populateFromBuffer(vb, v[3]);
				//vert.multLocal(0f);
				//result.addLocal(vert);
			} else {
				vert.populateFromBuffer(vb, vertexIndex);
				vert.multLocal(3f/4f);
				result.addLocal(vert);
				int n;
				n = valence;
				for (int j=0; j<n; j++) {
					vert.populateFromBuffer(vb, v[j]);
					vert.multLocal((float)(	1f/4f + 
							Math.cos(2f*Math.PI*(float)j/(float)n) + 
							1f/2f * Math.cos(4f*Math.PI*(float)j/(float)n)));
					vert.multLocal( 1f/(float)n );
					result.addLocal(vert);
				}
			}
			return result;
		}
		
		
		private static Vector regularButterfly(Edge edge, int vertexIndex, FloatBuffer vb, int bufferElementSize, ArrayList<Edge> edges) {
			Vector result = new Vector(bufferElementSize);
			int v[] = new int[6]; // v[0] = b1, 1=c1, 2=d, 3=c2, 4=b2, 5=other_a
			
			// spola fram i edgeMappen till edgen a1-a2
			Iterator<Edge> it = edges.iterator();
			while (it.hasNext() && (!edge.equals(it.next())));		
			
			// circle around the vertex counter clock wise and find all vertices 
			for (int i=0 ; i<6 ; i++) {
				if (!it.hasNext()) 
					it = edges.iterator();
				v[i] = it.next().otherVertex(vertexIndex);
			}		
			
			Vector vert = new Vector(bufferElementSize);
			vert.populateFromBuffer(vb, vertexIndex);
			vert.multLocal(1f/2f - WEIGHT);
			result.addLocal(vert);
			
			vert.populateFromBuffer(vb, v[0]);
			vert.multLocal((1f/8f + 2*WEIGHT) / 2); // divided by 2 because it will be visited again
			result.addLocal(vert);
			
			vert.populateFromBuffer(vb, v[1]);
			vert.multLocal((-1f/16f) - WEIGHT);
			result.addLocal(vert);
			
			vert.populateFromBuffer(vb, v[2]);
			vert.multLocal(WEIGHT);
			result.addLocal(vert);
			
			vert.populateFromBuffer(vb, v[3]);
			vert.multLocal((-1f/16f) - WEIGHT);
			result.addLocal(vert);
			
			vert.populateFromBuffer(vb, v[4]);
			vert.multLocal((1f/8f + 2*WEIGHT) / 2); // divided by 2 because it will be visited again
			result.addLocal(vert);
			
			return result;
		}
		
		static int standard = 0;
		static int regularCreaseCrease = 0;
		static int regularInteriorCrease = 0;
		static int extraordinaryAverage = 0;
		static int extraordinaryInterior = 0;
		static int extraordinaryCrease = 0;
		
		/**
		 * @return A String showing some statistics on the number of types of vertices of the subdivision
		 */
		public static String stats() {
			return "standard = " + standard + ", regularCreaseCrease = " + regularCreaseCrease + ", regularInteriorCrease = " + regularInteriorCrease + ", extraordinaryAverage = " + extraordinaryAverage + ", extraordinaryInterior = " + extraordinaryInterior + ", extraordinaryCrease = " + extraordinaryCrease;
		}
		
	}
	
	/**
	 * Whether the vertex is interior or lies on a boundary
	 * 
	 * @author Tobias
	 */	  
	public enum Location {
		INTERIOR,
		CREASE
	}
	
	/**
	 * Regular: Valence==6 for interior vertices, Valence==4 for boundary/crease vertices
	 * Extraordinary: Everything else
	 * 
	 * @author Tobias
	 */
	public enum Valence {
		REGULAR,
		EXTRAORDINARY;
		
		/**
		 * Calculates whether a vertex is REGULAR or EXTRAORDINARY, given the Location and valence(degree) of the vertex
		 * @param location
		 * @param valence
		 * @return <code>Valence.REGULAR</code> or <code>Valence.EXTRAORDINARY</code>
		 */
		public static Valence getValence(Location location, int valence) {
			if (location == Location.INTERIOR) {
				if (valence == 6) return Valence.REGULAR;
			} else {
				if (valence == 4) return Valence.REGULAR;
			}
			return Valence.EXTRAORDINARY;
		}
	}
	
	/**
	 * Helper class to calculate which <code>Rule</code> to use
	 * when splitting an <code>Edge</code> whose vertices have
	 * <code>Location</code> and <code>Valence</code> 
	 * 
	 * Call: <code>VertexType.getRule(valence1, location1, valence2, location2);</code>
	 * 
	 * @author Tobias
	 */
	public enum VertexType {
		REGULAR_INTERIOR,
		REGULAR_CREASE,
		EXTRAORDINARY_INTERIOR,
		EXTRAORDINARY_CREASE;
		
		private static VertexType getVertexType(Valence valence, Location location) {
			if (location == Location.INTERIOR)
				if (valence == Valence.REGULAR) return REGULAR_INTERIOR; 	else return EXTRAORDINARY_INTERIOR;
			else if (valence == Valence.REGULAR) return REGULAR_CREASE; 	else return EXTRAORDINARY_CREASE;
		}
		
		/**
		 * Calculates which subdivision Rule to use on an edge whose vertices have the provided Locations and 
		 * Valances
		 * 
		 * @param valence1
		 * @param location1
		 * @param valence2
		 * @param location2
		 * @return The Rule to use on an edge with the provided Locations and Valances
		 */
		public static Rule getRule(Valence valence1, Location location1, Valence valence2, Location location2) {
			return getRule(getVertexType(valence1, location1), getVertexType(valence2, location2));
		}
		
		private static Rule getRule(VertexType type1, VertexType type2) {	 
			if (isSame(type1,type2,REGULAR_INTERIOR,REGULAR_INTERIOR))
				return Rule.STANDARD;
			if (isSame(type1,type2,REGULAR_INTERIOR,REGULAR_CREASE))
				return Rule.REGULAR_INTERIOR_CREASE;
			if (isSame(type1,type2,REGULAR_CREASE,REGULAR_CREASE))
				return Rule.REGULAR_CREASE_CREASE;
			if (isSame(type1,type2,EXTRAORDINARY_INTERIOR,EXTRAORDINARY_INTERIOR))
				return Rule.EXTRAORDINARY_AVERAGE;
			if (isSame(type1,type2,EXTRAORDINARY_INTERIOR,EXTRAORDINARY_CREASE))
				return Rule.EXTRAORDINARY_AVERAGE;
			if (isSame(type1,type2,EXTRAORDINARY_CREASE,EXTRAORDINARY_CREASE))
				return Rule.EXTRAORDINARY_AVERAGE;
			if (isSame(type1,type2,REGULAR_INTERIOR,EXTRAORDINARY_INTERIOR))
				return Rule.EXTRAORDINARY_INTERIOR;
			if (isSame(type1,type2,REGULAR_INTERIOR,EXTRAORDINARY_CREASE))
				return Rule.EXTRAORDINARY_CREASE;
			if (isSame(type1,type2,EXTRAORDINARY_INTERIOR,REGULAR_CREASE))
				return Rule.EXTRAORDINARY_INTERIOR;
			if (isSame(type1,type2,REGULAR_CREASE,EXTRAORDINARY_CREASE))
				return Rule.EXTRAORDINARY_CREASE;
			
			logger.info("Warning: unknown rule for " + type1 + " and " + type2);
			return Rule.EXTRAORDINARY_AVERAGE;
		}
		
		/**
		 * Compares the permutations of the types
		 * 
		 * @param type1
		 * @param type2
		 * @param comp1
		 * @param comp2
		 * @return <code>true</code> if they are equivalent
		 */
		public static boolean isSame(VertexType type1, VertexType type2, VertexType comp1, VertexType comp2) {
			return (((type1 == comp1) && (type2 == comp2)) || ((type1 == comp2) && (type2 == comp1)));
		}
	}
}

⌨️ 快捷键说明

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