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 + -
显示快捷键?