modules/graphics/src/main/java/com/sun/prism/impl/BaseMesh.java
Print this page
@@ -155,12 +155,14 @@
return buildNativeGeometry(vertexBuffer,
numberOfVertices * VERTEX_SIZE_VB, indexBufferShort, nFaces * 3);
}
}
- private float[] tangents;
- private float[] bitangents;
+ private boolean[] dirtyVertices;
+ private float[] cachedNormals;
+ private float[] cachedTangents;
+ private float[] cachedBitangents;
private float[] vertexBuffer;
private int[] indexBuffer;
private short[] indexBufferShort;
private int indexBufferSize;
private int numberOfVertices;
@@ -268,10 +270,49 @@
return buildNativeGeometry(vertexBuffer,
numberOfVertices * VERTEX_SIZE_VB, indexBufferShort, nFaces * 3);
}
}
+ private void convertNormalsToQuats(MeshTempState instance, int numberOfVertices,
+ float[] normals, float[] tangents, float[] bitangents,
+ float[] vertexBuffer, boolean[] dirtys) {
+
+ Vec3f normal = instance.vec3f1;
+ Vec3f tangent = instance.vec3f2;
+ Vec3f bitangent = instance.vec3f3;
+ for (int i = 0, vbIndex = 0; i < numberOfVertices; i++, vbIndex += VERTEX_SIZE_VB) {
+ // Note: If dirtys isn't null, dirtys.length == numberOfVertices is true
+ if (dirtys == null || dirtys[i]) {
+ int index = i * NORMAL_SIZE;
+
+ normal.x = normals[index];
+ normal.y = normals[index + 1];
+ normal.z = normals[index + 2];
+ normal.normalize();
+
+ // tangent and bitangent have been normalized.
+ tangent.x = tangents[index];
+ tangent.y = tangents[index + 1];
+ tangent.z = tangents[index + 2];
+ bitangent.x = bitangents[index];
+ bitangent.y = bitangents[index + 1];
+ bitangent.z = bitangents[index + 2];
+
+ instance.triNormals[0].set(normal);
+ instance.triNormals[1].set(tangent);
+ instance.triNormals[2].set(bitangent);
+ MeshUtil.fixTSpace(instance.triNormals);
+ buildVSQuat(instance.triNormals, instance.quat);
+
+ vertexBuffer[vbIndex + 5] = instance.quat.x;
+ vertexBuffer[vbIndex + 6] = instance.quat.y;
+ vertexBuffer[vbIndex + 7] = instance.quat.z;
+ vertexBuffer[vbIndex + 8] = instance.quat.w;
+ }
+ }
+ }
+
// Build PointNormalTexCoordGeometry
private boolean doBuildPNTGeometry(float[] points, float[] normals,
float[] texCoords, int[] faces) {
if (point2vbMap == null) {
@@ -305,18 +346,27 @@
Integer mf2vb;
BaseMesh.MeshGeomComp2VB mp2vb;
BaseMesh.MeshGeomComp2VB mn2vb;
BaseMesh.MeshGeomComp2VB mt2vb;
// Allocate an initial size, may grow as we process the faces array.
- tangents = new float[numPoints * NORMAL_SIZE];
- bitangents = new float[numPoints * NORMAL_SIZE];
+ cachedNormals = new float[numPoints * NORMAL_SIZE];
+ cachedTangents = new float[numPoints * NORMAL_SIZE];
+ cachedBitangents = new float[numPoints * NORMAL_SIZE];
vertexBuffer = new float[numPoints * VERTEX_SIZE_VB];
indexBuffer = new int[numFaces * 3];
int ibCount = 0;
int vbCount = 0;
MeshTempState instance = MeshTempState.getInstance();
+ for (int i = 0; i < 3; i++) {
+ if (instance.triPoints[i] == null) {
+ instance.triPoints[i] = new Vec3f();
+ }
+ if (instance.triTexCoords[i] == null) {
+ instance.triTexCoords[i] = new Vec2f();
+ }
+ }
for (int faceCount = 0; faceCount < numFaces; faceCount++) {
int faceIndex = faceCount * faceIndexSize;
for (int i = 0; i < 3; i++) {
int vertexIndex = faceIndex + (i * vertexIndexSize);
@@ -329,17 +379,20 @@
if (vertexBuffer.length <= vbCount) {
final int incrementedSize = vbCount + 20; // Let's increment by 20
float[] temp = new float[incrementedSize * VERTEX_SIZE_VB];
System.arraycopy(vertexBuffer, 0, temp, 0, vertexBuffer.length);
vertexBuffer = temp;
- // Enlarge tangents and bitangents too
+ // Enlarge cachedNormals, cachedTangents and cachedBitangents too
+ temp = new float[incrementedSize * 3];
+ System.arraycopy(cachedNormals, 0, temp, 0, cachedNormals.length);
+ cachedNormals = temp;
temp = new float[incrementedSize * 3];
- System.arraycopy(tangents, 0, temp, 0, tangents.length);
- tangents = temp;
+ System.arraycopy(cachedTangents, 0, temp, 0, cachedTangents.length);
+ cachedTangents = temp;
temp = new float[incrementedSize * 3];
- System.arraycopy(bitangents, 0, temp, 0, bitangents.length);
- bitangents = temp;
+ System.arraycopy(cachedBitangents, 0, temp, 0, cachedBitangents.length);
+ cachedBitangents = temp;
}
int pointOffset = faces[pointIndex] * POINT_SIZE;
int normalOffset = faces[normalIndex] * NORMAL_SIZE;
int texCoordOffset = faces[texCoordIndex] * TEXCOORD_SIZE;
@@ -351,15 +404,15 @@
vertexBuffer[vbCount] = points[pointOffset];
vertexBuffer[vbCount + 1] = points[pointOffset + 1];
vertexBuffer[vbCount + 2] = points[pointOffset + 2];
vertexBuffer[vbCount + 3] = texCoords[texCoordOffset];
vertexBuffer[vbCount + 4] = texCoords[texCoordOffset + 1];
- // Temporarily store the normal in the quaterion slot
- vertexBuffer[vbCount + 5] = normals[normalOffset];
- vertexBuffer[vbCount + 6] = normals[normalOffset + 1];
- vertexBuffer[vbCount + 7] = normals[normalOffset + 2];
- vertexBuffer[vbCount + 8] = 0;
+ // Store the normal in the cachedNormals array
+ int index = instance.triVerts[i] * NORMAL_SIZE;
+ cachedNormals[index] = normals[normalOffset];
+ cachedNormals[index + 1] = normals[normalOffset + 1];
+ cachedNormals[index + 2] = normals[normalOffset + 2];
vbCount += VERTEX_SIZE_VB;
mp2vb = point2vbMap.get(pointOffset);
if (mp2vb == null) {
@@ -396,19 +449,13 @@
}
// This is the best time to compute the tangent and bitangent for each
// of the vertex. Go thro. the 3 vertices of a triangle
for (int i = 0; i < 3; i++) {
- if (instance.triPoints[i] == null) {
- instance.triPoints[i] = new Vec3f();
- }
instance.triPoints[i].x = points[instance.triPointIndex[i]];
instance.triPoints[i].y = points[instance.triPointIndex[i] + 1];
instance.triPoints[i].z = points[instance.triPointIndex[i] + 2];
- if (instance.triTexCoords[i] == null) {
- instance.triTexCoords[i] = new Vec2f();
- }
instance.triTexCoords[i].x = texCoords[instance.triTexCoordIndex[i]];
instance.triTexCoords[i].y = texCoords[instance.triTexCoordIndex[i] + 1];
}
MeshUtil.computeTBNNormalized(instance.triPoints[0], instance.triPoints[1],
@@ -416,51 +463,24 @@
instance.triTexCoords[1], instance.triTexCoords[2],
instance.triNormals);
for (int i = 0; i < 3; i++) {
int index = instance.triVerts[i] * NORMAL_SIZE;
- tangents[index] = instance.triNormals[1].x;
- tangents[index + 1] = instance.triNormals[1].y;
- tangents[index + 2] = instance.triNormals[1].z;
- bitangents[index] = instance.triNormals[2].x;
- bitangents[index + 1] = instance.triNormals[2].y;
- bitangents[index + 2] = instance.triNormals[2].z;
+ cachedTangents[index] = instance.triNormals[1].x;
+ cachedTangents[index + 1] = instance.triNormals[1].y;
+ cachedTangents[index + 2] = instance.triNormals[1].z;
+ cachedBitangents[index] = instance.triNormals[2].x;
+ cachedBitangents[index + 1] = instance.triNormals[2].y;
+ cachedBitangents[index + 2] = instance.triNormals[2].z;
}
}
numberOfVertices = vbCount / VERTEX_SIZE_VB;
- Vec3f normal = instance.vec3f1;
- Vec3f tangent = instance.vec3f2;
- Vec3f bitangent = instance.vec3f3;
- for (int i = 0, vbIndex = 0; i < numberOfVertices; i++, vbIndex += VERTEX_SIZE_VB) {
- normal.x = vertexBuffer[vbIndex + 5];
- normal.y = vertexBuffer[vbIndex + 6];
- normal.z = vertexBuffer[vbIndex + 7];
- normal.normalize();
-
- int index = i * NORMAL_SIZE;
- // tangent and bitangent have been normalized.
- tangent.x = tangents[index];
- tangent.y = tangents[index + 1];
- tangent.z = tangents[index + 2];
- bitangent.x = bitangents[index];
- bitangent.y = bitangents[index + 1];
- bitangent.z = bitangents[index + 2];
-
- instance.triNormals[0].set(normal);
- instance.triNormals[1].set(tangent);
- instance.triNormals[2].set(bitangent);
- MeshUtil.fixTSpace(instance.triNormals);
- buildVSQuat(instance.triNormals, instance.quat);
-
- vertexBuffer[vbIndex + 5] = instance.quat.x;
- vertexBuffer[vbIndex + 6] = instance.quat.y;
- vertexBuffer[vbIndex + 7] = instance.quat.z;
- vertexBuffer[vbIndex + 8] = instance.quat.w;
- }
+ convertNormalsToQuats(instance, numberOfVertices,
+ cachedNormals, cachedTangents, cachedBitangents, vertexBuffer, null);
indexBufferSize = numFaces * 3;
if (numberOfVertices > 0x10000) { // > 64K
return buildNativeGeometry(vertexBuffer,
@@ -484,10 +504,18 @@
// Update PointNormalTexCoordGeometry
private boolean updatePNTGeometry(float[] points, int[] pointsFromAndLengthIndices,
float[] normals, int[] normalsFromAndLengthIndices,
float[] texCoords, int[] texCoordsFromAndLengthIndices) {
+
+ if (dirtyVertices == null) {
+ // Create a dirty array of size equal to number of vertices in vertexBuffer.
+ dirtyVertices = new boolean[numberOfVertices];
+ }
+ // Clear dirty array before use.
+ Arrays.fill(dirtyVertices, false);
+
// Find out the list of modified points
int startPoint = pointsFromAndLengthIndices[0] / POINT_SIZE;
int numPoints = (pointsFromAndLengthIndices[1] / POINT_SIZE);
if ((pointsFromAndLengthIndices[1] % POINT_SIZE) > 0) {
numPoints++;
@@ -506,17 +534,19 @@
for (int j = 0; j < validLocs; j++) {
int vbIndex = locs[j] * VERTEX_SIZE_VB;
vertexBuffer[vbIndex] = points[pointOffset];
vertexBuffer[vbIndex + 1] = points[pointOffset + 1];
vertexBuffer[vbIndex + 2] = points[pointOffset + 2];
+ dirtyVertices[locs[j]] = true;
}
} else {
int loc = mp2vb.getLoc();
int vbIndex = loc * VERTEX_SIZE_VB;
vertexBuffer[vbIndex] = points[pointOffset];
vertexBuffer[vbIndex + 1] = points[pointOffset + 1];
vertexBuffer[vbIndex + 2] = points[pointOffset + 2];
+ dirtyVertices[loc] = true;
}
}
}
}
@@ -539,16 +569,18 @@
if (locs != null) {
for (int j = 0; j < validLocs; j++) {
int vbIndex = (locs[j] * VERTEX_SIZE_VB) + POINT_SIZE_VB;
vertexBuffer[vbIndex] = texCoords[texCoordOffset];
vertexBuffer[vbIndex + 1] = texCoords[texCoordOffset + 1];
+ dirtyVertices[locs[j]] = true;
}
} else {
int loc = mt2vb.getLoc();
int vbIndex = (loc * VERTEX_SIZE_VB) + POINT_SIZE_VB;
vertexBuffer[vbIndex] = texCoords[texCoordOffset];
vertexBuffer[vbIndex + 1] = texCoords[texCoordOffset + 1];
+ dirtyVertices[loc] = true;
}
}
}
}
@@ -569,56 +601,75 @@
if (mn2vb != null) {
int[] locs = mn2vb.getLocs();
int validLocs = mn2vb.getValidLocs();
if (locs != null) {
for (int j = 0; j < validLocs; j++) {
- int vbIndex = (locs[j] * VERTEX_SIZE_VB)
- + POINT_SIZE_VB + TEXCOORD_SIZE_VB;
-
- instance.triNormals[0].x = normals[normalOffset];
- instance.triNormals[0].y = normals[normalOffset + 1];
- instance.triNormals[0].z = normals[normalOffset + 2];
- instance.triNormals[0].normalize();
- instance.triNormals[1].x = tangents[normalOffset];
- instance.triNormals[1].y = tangents[normalOffset + 1];
- instance.triNormals[1].z = tangents[normalOffset + 2];
- instance.triNormals[2].x = bitangents[normalOffset];
- instance.triNormals[2].y = bitangents[normalOffset + 1];
- instance.triNormals[2].z = bitangents[normalOffset + 2];
- MeshUtil.fixTSpace(instance.triNormals);
- buildVSQuat(instance.triNormals, instance.quat);
- vertexBuffer[vbIndex] = instance.quat.x;
- vertexBuffer[vbIndex + 1] = instance.quat.y;
- vertexBuffer[vbIndex + 2] = instance.quat.z;
- vertexBuffer[vbIndex + 3] = instance.quat.w;
+ int index = locs[j] * NORMAL_SIZE;
+ cachedNormals[index] = normals[normalOffset];
+ cachedNormals[index + 1] = normals[normalOffset + 1];
+ cachedNormals[index + 2] = normals[normalOffset + 2];
+ dirtyVertices[locs[j]] = true;
}
} else {
int loc = mn2vb.getLoc();
- int vbIndex = (loc * VERTEX_SIZE_VB)
- + POINT_SIZE_VB + TEXCOORD_SIZE_VB;
+ int index = loc * NORMAL_SIZE;
+ cachedNormals[index] = normals[normalOffset];
+ cachedNormals[index + 1] = normals[normalOffset + 1];
+ cachedNormals[index + 2] = normals[normalOffset + 2];
+ dirtyVertices[loc] = true;
+ }
+ }
+ }
+ }
- instance.triNormals[0].x = normals[normalOffset];
- instance.triNormals[0].y = normals[normalOffset + 1];
- instance.triNormals[0].z = normals[normalOffset + 2];
- instance.triNormals[0].normalize();
- instance.triNormals[1].x = tangents[normalOffset];
- instance.triNormals[1].y = tangents[normalOffset + 1];
- instance.triNormals[1].z = tangents[normalOffset + 2];
- instance.triNormals[2].x = bitangents[normalOffset];
- instance.triNormals[2].y = bitangents[normalOffset + 1];
- instance.triNormals[2].z = bitangents[normalOffset + 2];
- MeshUtil.fixTSpace(instance.triNormals);
- buildVSQuat(instance.triNormals, instance.quat);
- vertexBuffer[vbIndex] = instance.quat.x;
- vertexBuffer[vbIndex + 1] = instance.quat.y;
- vertexBuffer[vbIndex + 2] = instance.quat.z;
- vertexBuffer[vbIndex + 3] = instance.quat.w;
+ // Prepare process all dirty vertices
+ MeshTempState instance = MeshTempState.getInstance();
+ for (int i = 0; i < 3; i++) {
+ if (instance.triPoints[i] == null) {
+ instance.triPoints[i] = new Vec3f();
+ }
+ if (instance.triTexCoords[i] == null) {
+ instance.triTexCoords[i] = new Vec2f();
}
}
+ // Every 3 vertices form a triangle
+ for (int j = 0; j < numberOfVertices; j += 3) {
+ // Only process the triangle that has one of more dirty vertices
+ if (dirtyVertices[j] || dirtyVertices[j+1] || dirtyVertices[j+2]) {
+ int vbIndex = j * VERTEX_SIZE_VB;
+ // Go thro. the 3 vertices of a triangle
+ for (int i = 0; i < 3; i++) {
+ instance.triPoints[i].x = vertexBuffer[vbIndex];
+ instance.triPoints[i].y = vertexBuffer[vbIndex + 1];
+ instance.triPoints[i].z = vertexBuffer[vbIndex + 2];
+ instance.triTexCoords[i].x = vertexBuffer[vbIndex + POINT_SIZE_VB];
+ instance.triTexCoords[i].y = vertexBuffer[vbIndex + POINT_SIZE_VB + 1];
+ vbIndex += VERTEX_SIZE_VB;
+ }
+
+ MeshUtil.computeTBNNormalized(instance.triPoints[0], instance.triPoints[1],
+ instance.triPoints[2], instance.triTexCoords[0],
+ instance.triTexCoords[1], instance.triTexCoords[2],
+ instance.triNormals);
+
+ int index = j * NORMAL_SIZE;
+ for (int i = 0; i < 3; i++) {
+ cachedTangents[index] = instance.triNormals[1].x;
+ cachedTangents[index + 1] = instance.triNormals[1].y;
+ cachedTangents[index + 2] = instance.triNormals[1].z;
+ cachedBitangents[index] = instance.triNormals[2].x;
+ cachedBitangents[index + 1] = instance.triNormals[2].y;
+ cachedBitangents[index + 2] = instance.triNormals[2].z;
+ index += NORMAL_SIZE;
+ }
+
}
}
+ convertNormalsToQuats(instance, numberOfVertices,
+ cachedNormals, cachedTangents, cachedBitangents, vertexBuffer, dirtyVertices);
+
if (indexBuffer != null) {
return buildNativeGeometry(vertexBuffer,
numberOfVertices * VERTEX_SIZE_VB, indexBuffer, indexBufferSize);
} else {
return buildNativeGeometry(vertexBuffer,