clodcreator.java

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

JAVA
876
字号
			//      if(!( 0 <= m_iVCurrent && m_iVCurrent < m_akVertex.length )) throw new AssertionError();
			iV = ((Integer) it.next()).intValue();
			//      if(!( 0 <= iV && iV < m_akVertex.length )) throw new AssertionError();
			orderedVertices[currentVertex] = iV;
			permuteVertices[iV] = currentVertex;
			currentVertex--;
		}

		// Save the collapse information for use in constructing the final
		// collapse records for the caller of the constructor of this class.
		CollapseRecord kCR = new CollapseRecord(iVKeep, iVThrow,
				deletedVertices.size(), iTDeletions);
		deletedEdges.add(kCR);
	}

	public void flushVertices() {
		Iterator it = vertexMap.keySet().iterator();
		while (it.hasNext()) {
			Integer val = (Integer) it.next();
			orderedVertices[currentVertex] = val.intValue();
			permuteVertices[val.intValue()] = currentVertex;
			currentVertex--;
		}

		//    if (!(m_iVCurrent == -1)) throw new AssertionError();
	}

	public void flushTriangles() {
		Iterator it = triangleMap.entrySet().iterator();
		while (it.hasNext()) {
			Entry entry = (Entry) it.next();
			TriangleAttribute pkTA = (TriangleAttribute) entry.getValue();
			int iTIndex = ((Integer) pkTA.data).intValue();
			if (iTIndex >= 0) {
				//        if (!(m_iTCurrent >= 0)) throw new AssertionError();
				newIndices[3 * currentTriangle] = indices.get(3 * iTIndex);
				newIndices[3 * currentTriangle + 1] = indices
						.get(3 * iTIndex + 1);
				newIndices[3 * currentTriangle + 2] = indices
						.get(3 * iTIndex + 2);
				currentTriangle--;
			}
		}

		//    if (!(m_iTCurrent == -1)) throw new AssertionError();
	}

	public void reorder() {
		// permute the vertices and copy to the original array
		int i;
		float[] akNewVertex = new float[vertQuantity * 3];
		for (i = 0; i < vertQuantity; i++) {
			int index = orderedVertices[i] * 3;

			akNewVertex[i * 3] = vertices.get(index);
			akNewVertex[i * 3 + 1] = vertices.get(index + 1);
			akNewVertex[i * 3 + 2] = vertices.get(index + 2);
		}
		vertices.clear();
		vertices.put(akNewVertex);
		akNewVertex = null;

		// permute the normal vectors (if any)
		if (normals != null) {
			float[] akNewNormal = new float[vertQuantity * 3];
			for (i = 0; i < vertQuantity; i++) {
				int index = orderedVertices[i] * 3;

				akNewNormal[i * 3] = normals.get(index);
				akNewNormal[i * 3 + 1] = normals.get(index + 1);
				akNewNormal[i * 3 + 2] = normals.get(index + 2);
			}
			normals.rewind();
			normals.put(akNewNormal);
			akNewNormal = null;
		}

		// permute the colors (if any)
		if (colors != null) {
			float[] akNewColor = new float[vertQuantity * 4];
			for (i = 0; i < vertQuantity; i++) {
				int index = orderedVertices[i] * 4;

				akNewColor[i * 4] = colors.get(index);
				akNewColor[i * 4 + 1] = colors.get(index + 1);
				akNewColor[i * 4 + 2] = colors.get(index + 2);
				akNewColor[i * 4 + 3] = colors.get(index + 3);
			}
			colors.rewind();
			colors.put(akNewColor);
			akNewColor = null;
		}

		// permute the texture coordinates (if any)
		if (textures != null) {
			float[] akNewTexture = new float[vertQuantity * 2];
			for (i = 0; i < vertQuantity; i++) {
				int index = orderedVertices[i] * 2;

				akNewTexture[i * 2] = textures.get(index);
				akNewTexture[i * 2 + 1] = textures.get(index + 1);
			}
			textures.rewind();
			textures.put(akNewTexture);
			akNewTexture = null;
		}

		// permute the connectivity array and copy to the original array
		indices.rewind();
		for (i = 0; i < 3 * numbTriangles; i++)
			indices.put(permuteVertices[newIndices[i]]);

		// permute the keep/throw pairs
		for (i = 0; i < deletedEdges.size(); i++) {
			CollapseRecord rkCR = deletedEdges.get(i);
			rkCR.vertToKeep = permuteVertices[rkCR.vertToKeep];
			rkCR.vertToThrow = permuteVertices[rkCR.vertToThrow];
		}
	}

	public CollapseRecord[] computeRecords() {
		// build the collapse records for the caller
		int riCQuantity = deletedEdges.size() + 1;
		CollapseRecord[] rakCRecord = new CollapseRecord[riCQuantity];
		for (int i = 0; i < riCQuantity; i++)
			rakCRecord[i] = new CollapseRecord();

		// initial record only stores the initial vertex and triangle quantities
		rakCRecord[0].numbVerts = vertQuantity;
		rakCRecord[0].numbTriangles = numbTriangles;

		// construct the replacement arrays
		int iVQuantity = vertQuantity, iTQuantity = numbTriangles;
		int iR, i;
		for (iR = 0; iR < deletedEdges.size(); iR++) {
			CollapseRecord rkERecord = deletedEdges.get(iR);
			CollapseRecord rkRecord = rakCRecord[iR + 1];

			iVQuantity -= rkERecord.numbVerts;
			iTQuantity -= rkERecord.numbTriangles;

			rkRecord.vertToKeep = rkERecord.vertToKeep;
			rkRecord.vertToThrow = rkERecord.vertToThrow;
			rkRecord.numbVerts = iVQuantity;
			rkRecord.numbTriangles = iTQuantity;
			rkRecord.numbIndices = 0;

			if (iTQuantity > 0) {
				int iIMax = 3 * iTQuantity;
				int[] aiIndex = new int[iIMax];
				for (i = 0; i < iIMax; i++) {
					if (indices.get(i) == rkRecord.vertToThrow) {
						indices.put(i, rkRecord.vertToKeep);
						aiIndex[rkRecord.numbIndices++] = i;
					}
				}

				if (rkRecord.numbIndices > 0) {
					rkRecord.indices = new int[rkRecord.numbIndices];
					for (i = 0; i < rkRecord.numbIndices; i++)
						rkRecord.indices[i] = aiIndex[i];
				}

				aiIndex = null;
			} else {
				rkRecord.indices = null;
			}
		}

		// expand mesh back to original
		for (iR = riCQuantity - 1; iR > 0; iR--) {
			// restore indices in connectivity array
			CollapseRecord rkRecord = rakCRecord[iR];
			for (i = 0; i < rkRecord.numbIndices; i++) {
				int iC = rkRecord.indices[i];
				//        if (!(m_aiConnect[iC] == rkRecord.vertToKeep)) throw new AssertionError();
				indices.put(iC, rkRecord.vertToThrow);
			}
		}
		return rakCRecord;
	}

	// ---------------------- heap operations ----------------------

	public void initializeHeap() {
		// It is possible that during an edge collapse, the number of *temporary*
		// edges is larger than the original number of edges in the mesh.  To
		// make sure there is enough heap space, allocate two times the number of
		// original edges.
		heapSize = edgeMap.size();
		heapArray = new HeapRecord[2 * heapSize];

		int iHIndex = 0;
		Iterator it = edgeMap.entrySet().iterator();
		while (it.hasNext()) {
			Entry entry = (Entry) it.next();
			Edge pkE = (Edge) entry.getKey();
			EdgeAttribute pkEA = (EdgeAttribute) entry.getValue();
			heapArray[iHIndex] = (HeapRecord) pkEA.data;
			heapArray[iHIndex].m_kEdge = pkE;
			heapArray[iHIndex].m_iHIndex = iHIndex;
			heapArray[iHIndex].m_fMetric = getMetric(pkE, pkEA);
			iHIndex++;
		}

		sort();
	}

	public void sort() {
		int iLast = heapSize - 1;
		for (int iLeft = iLast / 2; iLeft >= 0; iLeft--) {
			HeapRecord pkRecord = heapArray[iLeft];
			int iPa = iLeft, iCh = 2 * iLeft + 1;
			while (iCh <= iLast) {
				if (iCh < iLast) {
					if (heapArray[iCh].m_fMetric > heapArray[iCh + 1].m_fMetric)
						iCh++;
				}

				if (heapArray[iCh].m_fMetric >= pkRecord.m_fMetric)
					break;

				heapArray[iCh].m_iHIndex = iPa;
				heapArray[iPa] = heapArray[iCh];
				iPa = iCh;
				iCh = 2 * iCh + 1;
			}

			pkRecord.m_iHIndex = iPa;
			heapArray[iPa] = pkRecord;
		}
	}

	public void add(float fMetric) {
		// Under normal heap operations, you would have to make sure that the
		// heap storage grows if necessary.  Increased storage demand will not
		// happen in this application.  The creation of the heap record itself is
		// done in OnEdgeCreate.
		heapSize++;

		int iCh = heapSize - 1;
		HeapRecord pkRecord = heapArray[iCh];
		pkRecord.m_fMetric = fMetric;
		while (iCh > 0) {
			int iPa = (iCh - 1) / 2;
			if (heapArray[iPa].m_fMetric <= fMetric)
				break;

			heapArray[iPa].m_iHIndex = iCh;
			heapArray[iCh] = heapArray[iPa];
			pkRecord.m_iHIndex = iPa;
			pkRecord.m_fMetric = fMetric;
			heapArray[iPa] = pkRecord;
			iCh = iPa;
		}

		heapArray[iCh].m_fMetric = fMetric;
	}

	public void remove() {
		HeapRecord pkRoot = heapArray[0];

		int iLast = heapSize - 1;
		HeapRecord pkRecord = heapArray[iLast];
		int iPa = 0, iCh = 1;
		while (iCh <= iLast) {
			if (iCh < iLast) {
				int iChP = iCh + 1;
				if (heapArray[iCh].m_fMetric > heapArray[iChP].m_fMetric)
					iCh = iChP;
			}

			if (heapArray[iCh].m_fMetric >= pkRecord.m_fMetric)
				break;

			heapArray[iCh].m_iHIndex = iPa;
			heapArray[iPa] = heapArray[iCh];
			iPa = iCh;
			iCh = 2 * iCh + 1;
		}

		pkRecord.m_iHIndex = iPa;
		heapArray[iPa] = pkRecord;
		heapSize--;

		// To notify OnEdgeDestroy that this edge was already removed from the
		// heap, but the object must be deleted by that callback.
		pkRoot.m_iHIndex = -1;
	}

	public void update(int iHIndex, float fMetric) {
		HeapRecord pkRecord = heapArray[iHIndex];
		int iPa, iCh, iChP, iMaxCh;

		if (fMetric > pkRecord.m_fMetric) {
			pkRecord.m_fMetric = fMetric;

			// new weight larger than old, propagate it towards the leaves
			iPa = iHIndex;
			iCh = 2 * iPa + 1;
			while (iCh < heapSize) {
				// at least one child exists
				if (iCh < heapSize - 1) {
					// two children exist
					iChP = iCh + 1;
					if (heapArray[iCh].m_fMetric <= heapArray[iChP].m_fMetric)
						iMaxCh = iCh;
					else
						iMaxCh = iChP;
				} else {
					// one child exists
					iMaxCh = iCh;
				}

				if (heapArray[iMaxCh].m_fMetric >= fMetric)
					break;

				heapArray[iMaxCh].m_iHIndex = iPa;
				heapArray[iPa] = heapArray[iMaxCh];
				pkRecord.m_iHIndex = iMaxCh;
				heapArray[iMaxCh] = pkRecord;
				iPa = iMaxCh;
				iCh = 2 * iPa + 1;
			}
		} else if (fMetric < pkRecord.m_fMetric) {
			pkRecord.m_fMetric = fMetric;

			// new weight smaller than old, propagate it towards the root
			iCh = iHIndex;
			while (iCh > 0) {
				// a parent exists
				iPa = (iCh - 1) / 2;

				if (heapArray[iPa].m_fMetric <= fMetric)
					break;

				heapArray[iPa].m_iHIndex = iCh;
				heapArray[iCh] = heapArray[iPa];
				pkRecord.m_iHIndex = iPa;
				pkRecord.m_fMetric = fMetric;
				heapArray[iPa] = pkRecord;
				iCh = iPa;
			}
		}
	}

	public boolean isValidHeap(int iStart, int iFinal) {
		for (int iC = iStart; iC <= iFinal; iC++) {
			int iP = (iC - 1) / 2;
			if (iP > iStart) {
				if (heapArray[iP].m_fMetric > heapArray[iC].m_fMetric)
					return false;

				if (heapArray[iP].m_iHIndex != iP)
					return false;
			}
		}

		return true;
	}

	public boolean isValidHeap() {
		return isValidHeap(0, heapSize - 1);
	}

	// mesh insert/remove callbacks

	public void onVertexInsert(Integer vert, boolean bCreate,
			VertexAttribute att) {
		// It is possible that a 'keep' vertex was removed because the triangles
		// sharing the collapse edge were removed first, but then the insertion
		// of a modified triangle reinserts the 'keep' vertex.
		if (bCreate && collapsing)
			deletedVertices.remove(vert);
	}

	public void onVertexRemove(Integer vert, boolean bDestroy,
			VertexAttribute att) {
		// Keep track of vertices removed during the edge collapse.
		if (bDestroy && collapsing)
			deletedVertices.add(vert);
	}

	public void onEdgeInsert(Edge rkE, boolean bCreate, EdgeAttribute att) {
		if (bCreate) {
			att.data = new HeapRecord();
			if (collapsing) {
				heapArray[heapSize] = (HeapRecord) att.data;
				heapArray[heapSize].m_kEdge = rkE;
				heapArray[heapSize].m_iHIndex = heapSize;
				add(getMetric(rkE, edgeMap.get(rkE)));
			}
		} else {
			if (collapsing) {
				HeapRecord pkRecord = (HeapRecord) att.data;
				//        if (!(pkRecord.m_kEdge.equals(rkE))) throw new AssertionError();
				if (pkRecord.m_iHIndex >= 0) {
					update(pkRecord.m_iHIndex, getMetric(rkE,
							edgeMap.get(rkE)));
				} else {
					//          if (!(pkRecord.m_iHIndex == -1)) throw new AssertionError();
					pkRecord.m_iHIndex = heapSize;
					add(getMetric(rkE, edgeMap.get(rkE)));
				}
			}
		}
	}

	public void onEdgeRemove(Edge rkE, boolean bDestroy, EdgeAttribute att) {
		// Remove the edge from the heap.  The metric of the edge is set to
		// -INFINITY so that it has the minimum value of all edges.  The update
		// call bubbles the edge to the root of the heap.  The edge is then
		// removed from the root.

		if (bDestroy) {
			HeapRecord pkRecord = (HeapRecord) att.data;
			if (pkRecord.m_iHIndex >= 0) {
				update(pkRecord.m_iHIndex, -Float.MAX_VALUE);
				remove();
			}
			pkRecord = null;
		}
	}

	public void onTriangleInsert(Triangle tri, boolean bCreate,
			TriangleAttribute att) {
		if (bCreate)
			att.data = new Integer(-1);
	}

	public void onTriangleRemove(Triangle tri, boolean bDestroy,
			TriangleAttribute att) {
		if (bDestroy)
			att.data = null;
	}

}

⌨️ 快捷键说明

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