stripifier.java

来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 1,365 行 · 第 1/3 页

JAVA
1,365
字号
	// Returns the (at most) two vertices shared between the two faces
	//
	static void getSharedVertices(FaceInfo faceA, FaceInfo faceB, int[] vertex) {
		vertex[0] = -1;
		vertex[1] = -1;

		int facev0 = faceB.m_v0;
		if (facev0 == faceA.m_v0 || facev0 == faceA.m_v1
				|| facev0 == faceA.m_v2) {
			if (vertex[0] == -1)
				vertex[0] = facev0;
			else {
				vertex[1] = facev0;
				return;
			}
		}

		int facev1 = faceB.m_v1;
		if (facev1 == faceA.m_v0 || facev1 == faceA.m_v1
				|| facev1 == faceA.m_v2) {
			if (vertex[0] == -1)
				vertex[0] = facev1;
			else {
				vertex[1] = facev1;
				return;
			}
		}

		int facev2 = faceB.m_v2;
		if (facev2 == faceA.m_v0 || facev2 == faceA.m_v1
				|| facev2 == faceA.m_v2) {
			if (vertex[0] == -1)
				vertex[0] = facev2;
			else {
				vertex[1] = facev2;
				return;
			}
		}

	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// CommitStrips()
	//
	// "Commits" the input strips by setting their m_experimentId to -1 and
	// adding to the allStrips
	//  vector
	//
	static void commitStrips(StripInfoVec allStrips, StripInfoVec strips) {
		// Iterate through strips
		int numStrips = strips.size();
		for (int i = 0; i < numStrips; i++) {

			// Tell the strip that it is now real
			StripInfo strip = strips.at(i);
			strip.m_experimentId = -1;

			// add to the list of real strips
			allStrips.add(strip);

			// Iterate through the faces of the strip
			// Tell the faces of the strip that they belong to a real strip now
			FaceInfoVec faces = strips.at(i).m_faces;
			int numFaces = faces.size();

			for (int j = 0; j < numFaces; j++) {
				strip.markTriangle(faces.at(j));
			}
		}
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// NextIsCW()
	//
	// Returns true if the next face should be ordered in CW fashion
	//
	static boolean nextIsCW(int numIndices) {
		return ((numIndices % 2) == 0);
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// UpdateCacheFace()
	//
	// Updates the input vertex cache with this face's vertices
	//
	static void updateCacheFace(VertexCache vcache, FaceInfo face) {
		if (!vcache.inCache(face.m_v0))
			vcache.addEntry(face.m_v0);

		if (!vcache.inCache(face.m_v1))
			vcache.addEntry(face.m_v1);

		if (!vcache.inCache(face.m_v2))
			vcache.addEntry(face.m_v2);
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// UpdateCacheStrip()
	//
	// Updates the input vertex cache with this strip's vertices
	//
	static void updateCacheStrip(VertexCache vcache, StripInfo strip) {
		for (int i = 0; i < strip.m_faces.size(); ++i) {
			if (!vcache.inCache(strip.m_faces.at(i).m_v0))
				vcache.addEntry(strip.m_faces.at(i).m_v0);

			if (!vcache.inCache(strip.m_faces.at(i).m_v1))
				vcache.addEntry(strip.m_faces.at(i).m_v1);

			if (!vcache.inCache(strip.m_faces.at(i).m_v2))
				vcache.addEntry(strip.m_faces.at(i).m_v2);
		}
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// CalcNumHitsStrip()
	//
	// returns the number of cache hits per face in the strip
	//
	static float calcNumHitsStrip(VertexCache vcache, StripInfo strip) {
		int numHits = 0;
		int numFaces = 0;

		for (int i = 0; i < strip.m_faces.size(); i++) {
			if (vcache.inCache(strip.m_faces.at(i).m_v0))
				++numHits;

			if (vcache.inCache(strip.m_faces.at(i).m_v1))
				++numHits;

			if (vcache.inCache(strip.m_faces.at(i).m_v2))
				++numHits;

			numFaces++;
		}

		return ((float) numHits / (float) numFaces);
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// AvgStripSize()
	//
	// Finds the average strip size of the input vector of strips
	//
	static float avgStripSize(StripInfoVec strips) {
		int sizeAccum = 0;
		int numStrips = strips.size();
		for (int i = 0; i < numStrips; i++) {
			StripInfo strip = strips.at(i);
			sizeAccum += strip.m_faces.size();
			sizeAccum -= strip.m_numDegenerates;
		}
		return ((float) sizeAccum) / ((float) numStrips);
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// CalcNumHitsFace()
	//
	// returns the number of cache hits in the face
	//
	static int calcNumHitsFace(VertexCache vcache, FaceInfo face) {
		int numHits = 0;

		if (vcache.inCache(face.m_v0))
			numHits++;

		if (vcache.inCache(face.m_v1))
			numHits++;

		if (vcache.inCache(face.m_v2))
			numHits++;

		return numHits;
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// NumNeighbors()
	//
	// Returns the number of neighbors that this face has
	//
	static int numNeighbors(FaceInfo face, EdgeInfoVec edgeInfoVec) {
		int numNeighbors = 0;

		if (findOtherFace(edgeInfoVec, face.m_v0, face.m_v1, face) != null) {
			numNeighbors++;
		}

		if (findOtherFace(edgeInfoVec, face.m_v1, face.m_v2, face) != null) {
			numNeighbors++;
		}

		if (findOtherFace(edgeInfoVec, face.m_v2, face.m_v0, face) != null) {
			numNeighbors++;
		}

		return numNeighbors;
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// IsCW()
	//
	// Returns true if the face is ordered in CW fashion
	//
	static boolean isCW(FaceInfo faceInfo, int v0, int v1) {
		if (faceInfo.m_v0 == v0)
			return (faceInfo.m_v1 == v1);
		else if (faceInfo.m_v1 == v0)
			return (faceInfo.m_v2 == v1);
		else
			return (faceInfo.m_v0 == v1);

	}

	static boolean faceContainsIndex(FaceInfo face, int index) {
		return ((face.m_v0 == index) || (face.m_v1 == index) || (face.m_v2 == index));
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// FindTraversal()
	//
	// Finds the next face to start the next strip on.
	//
	static boolean findTraversal(FaceInfoVec faceInfos, EdgeInfoVec edgeInfos,
			StripInfo strip, StripStartInfo startInfo) {

		// if the strip was v0.v1 on the edge, then v1 will be a vertex in the
		// next edge.
		int v = (strip.m_startInfo.m_toV1 ? strip.m_startInfo.m_startEdge.m_v1
				: strip.m_startInfo.m_startEdge.m_v0);

		FaceInfo untouchedFace = null;
		EdgeInfo edgeIter = edgeInfos.at(v);
		while (edgeIter != null) {
			FaceInfo face0 = edgeIter.m_face0;
			FaceInfo face1 = edgeIter.m_face1;
			if ((face0 != null && !strip.isInStrip(face0)) && face1 != null
					&& !strip.isMarked(face1)) {
				untouchedFace = face1;
				break;
			}
			if ((face1 != null && !strip.isInStrip(face1)) && face0 != null
					&& !strip.isMarked(face0)) {
				untouchedFace = face0;
				break;
			}

			// find the next edgeIter
			edgeIter = (edgeIter.m_v0 == v ? edgeIter.m_nextV0
					: edgeIter.m_nextV1);
		}

		startInfo.m_startFace = untouchedFace;
		startInfo.m_startEdge = edgeIter;
		if (edgeIter != null) {
			if (strip.sharesEdge(startInfo.m_startFace, edgeInfos))
				startInfo.m_toV1 = (edgeIter.m_v0 == v); //note! used to be
			// m_v1
			else
				startInfo.m_toV1 = (edgeIter.m_v1 == v);
		}
		return (startInfo.m_startFace != null);
	}

	////////////////////////////////////////////////////////////////////////////////////////
	// RemoveSmallStrips()
	//
	// allStrips is the whole strip vector...all small strips will be deleted
	// from this list, to avoid leaking mem
	// allBigStrips is an out parameter which will contain all strips above
	// minStripLength
	// faceList is an out parameter which will contain all faces which were
	// removed from the striplist
	//
	void removeSmallStrips(StripInfoVec allStrips, StripInfoVec allBigStrips,
			FaceInfoVec faceList) {
		faceList.clear();
		allBigStrips.clear(); //make sure these are empty
		FaceInfoVec tempFaceList = new FaceInfoVec();

		for (int i = 0; i < allStrips.size(); i++) {
			if (allStrips.at(i).m_faces.size() < minStripLength) {
				//strip is too small, add faces to faceList
				for (int j = 0; j < allStrips.at(i).m_faces.size(); j++)
					tempFaceList.add(allStrips.at(i).m_faces.at(j));

			} else {
				allBigStrips.add(allStrips.at(i));
			}
		}

		boolean[] bVisitedList = new boolean[tempFaceList.size()];

		VertexCache vcache = new VertexCache(cacheSize);

		int bestNumHits = -1;
		int numHits;
		int bestIndex = -9999;

		while (true) {
			bestNumHits = -1;

			//find best face to add next, given the current cache
			for (int i = 0; i < tempFaceList.size(); i++) {
				if (bVisitedList[i])
					continue;

				numHits = calcNumHitsFace(vcache, tempFaceList.at(i));
				if (numHits > bestNumHits) {
					bestNumHits = numHits;
					bestIndex = i;
				}
			}

			if (bestNumHits == -1.0f)
				break;
			bVisitedList[bestIndex] = true;
			updateCacheFace(vcache, tempFaceList.at(bestIndex));
			faceList.add(tempFaceList.at(bestIndex));
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////
	// CreateStrips()
	//
	// Generates actual strips from the list-in-strip-order.
	//
	int createStrips(StripInfoVec allStrips, IntVec stripIndices,
			boolean bStitchStrips) {
		int numSeparateStrips = 0;

		FaceInfo tLastFace = new FaceInfo(0, 0, 0);
		int nStripCount = allStrips.size();
		
		//we infer the cw/ccw ordering depending on the number of indices
		//this is screwed up by the fact that we insert -1s to denote changing
		// strips
		//this is to account for that
		int accountForNegatives = 0;

		for (int i = 0; i < nStripCount; i++) {
			StripInfo strip = allStrips.at(i);
			int nStripFaceCount = strip.m_faces.size();
			
			// Handle the first face in the strip
			{
				FaceInfo tFirstFace = new FaceInfo(strip.m_faces.at(0).m_v0,
						strip.m_faces.at(0).m_v1, strip.m_faces.at(0).m_v2);

				// If there is a second face, reorder vertices such that the
				// unique vertex is first
				if (nStripFaceCount > 1) {
					int nUnique = getUniqueVertexInB(strip.m_faces.at(1),
							tFirstFace);
					if (nUnique == tFirstFace.m_v1) {
						int tmp = tFirstFace.m_v0;
						tFirstFace.m_v0 = tFirstFace.m_v1;
						tFirstFace.m_v1 = tmp;
					} else if (nUnique == tFirstFace.m_v2) {
						int tmp = tFirstFace.m_v0;
						tFirstFace.m_v0 = tFirstFace.m_v2;
						tFirstFace.m_v2 = tmp;
					}

					// If there is a third face, reorder vertices such that the
					// shared vertex is last
					if (nStripFaceCount > 2) {
						if (isDegenerate(strip.m_faces.at(1))) {
							int pivot = strip.m_faces.at(1).m_v1;
							if (tFirstFace.m_v1 == pivot) {
								int tmp = tFirstFace.m_v1;
								tFirstFace.m_v1 = tFirstFace.m_v2;
								tFirstFace.m_v2 = tmp;
							}
						} else {
							int[] nShared = new int[2];
							getSharedVertices(strip.m_faces.at(2), tFirstFace,
									nShared);
							if ((nShared[0] == tFirstFace.m_v1)
									&& (nShared[1] == -1)) {
								int tmp = tFirstFace.m_v1;
								tFirstFace.m_v1 = tFirstFace.m_v2;
								tFirstFace.m_v2 = tmp;
							}
						}
					}
				}

				if ((i == 0) || !bStitchStrips) {
					if (!isCW(strip.m_faces.at(0), tFirstFace.m_v0,
							tFirstFace.m_v1))
						stripIndices.add(tFirstFace.m_v0);
				} else {
					// Double tap the first in the new strip
					stripIndices.add(tFirstFace.m_v0);

					// Check CW/CCW ordering
					if (nextIsCW(stripIndices.size() - accountForNegatives) != isCW(
							strip.m_faces.at(0), tFirstFace.m_v0,
							tFirstFace.m_v1)) {
						stripIndices.add(tFirstFace.m_v0);
					}
				}

				stripIndices.add(tFirstFace.m_v0);
				stripIndices.add(tFirstFace.m_v1);
				stripIndices.add(tFirstFace.m_v2);

				// Update last face info
				tLastFace.set(tFirstFace);
			}

			for (int j = 1; j < nStripFaceCount; j++) {
				int nUnique = getUniqueVertexInB(tLastFace, strip.m_faces.at(j));
				if (nUnique != -1) {
					stripIndices.add(nUnique);

					// Update last face info
					tLastFace.m_v0 = tLastFace.m_v1;
					tLastFace.m_v1 = tLastFace.m_v2;
					tLastFace.m_v2 = nUnique;
				} else {
					//we've hit a degenerate
					stripIndices.add(strip.m_faces.at(j).m_v2);
					tLastFace.m_v0 = strip.m_faces.at(j).m_v0; //tLastFace.m_v1;
					tLastFace.m_v1 = strip.m_faces.at(j).m_v1; //tLastFace.m_v2;
					tLastFace.m_v2 = strip.m_faces.at(j).m_v2; //tLastFace.m_v1;

				}
			}

			// Double tap between strips.
			if (bStitchStrips) {
				if (i != nStripCount - 1)
					stripIndices.add(tLastFace.m_v2);
			} else {
				//-1 index indicates next strip
				stripIndices.add(-1);
				accountForNegatives++;
				numSeparateStrips++;
			}

			// Update last face info
			tLastFace.m_v0 = tLastFace.m_v1;
			tLastFace.m_v1 = tLastFace.m_v2;
			tLastFace.m_v2 = tLastFace.m_v2;
		}

		if (bStitchStrips)
			numSeparateStrips = 1;
		return numSeparateStrips;
	}

	///////////////////////////////////////////////////////////////////////////////////////////
	// FindAllStrips()
	//

⌨️ 快捷键说明

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