use of com.jme3.scene.VertexBuffer in project jmonkeyengine by jMonkeyEngine.
the class SkeletonControl method applySkinningTangents.
/**
* Specific method for skinning with tangents to avoid cluttering the
* classic skinning calculation with null checks that would slow down the
* process even if tangents don't have to be computed. Also the iteration
* has additional indexes since tangent has 4 components instead of 3 for
* pos and norm
*
* @param maxWeightsPerVert maximum number of weights per vertex
* @param mesh the mesh
* @param offsetMatrices the offsetMaytrices to apply
* @param tb the tangent vertexBuffer
*/
private void applySkinningTangents(Mesh mesh, Matrix4f[] offsetMatrices, VertexBuffer tb) {
int maxWeightsPerVert = mesh.getMaxNumWeights();
if (maxWeightsPerVert <= 0) {
throw new IllegalStateException("Max weights per vert is incorrectly set!");
}
int fourMinusMaxWeights = 4 - maxWeightsPerVert;
// NOTE: This code assumes the vertex buffer is in bind pose
// resetToBind() has been called this frame
VertexBuffer vb = mesh.getBuffer(Type.Position);
FloatBuffer fvb = (FloatBuffer) vb.getData();
fvb.rewind();
VertexBuffer nb = mesh.getBuffer(Type.Normal);
FloatBuffer fnb = (FloatBuffer) nb.getData();
fnb.rewind();
FloatBuffer ftb = (FloatBuffer) tb.getData();
ftb.rewind();
// get boneIndexes and weights for mesh
ByteBuffer ib = (ByteBuffer) mesh.getBuffer(Type.BoneIndex).getData();
FloatBuffer wb = (FloatBuffer) mesh.getBuffer(Type.BoneWeight).getData();
ib.rewind();
wb.rewind();
float[] weights = wb.array();
byte[] indices = ib.array();
int idxWeights = 0;
TempVars vars = TempVars.get();
float[] posBuf = vars.skinPositions;
float[] normBuf = vars.skinNormals;
float[] tanBuf = vars.skinTangents;
int iterations = (int) FastMath.ceil(fvb.limit() / ((float) posBuf.length));
int bufLength = 0;
int tanLength = 0;
for (int i = iterations - 1; i >= 0; i--) {
// read next set of positions and normals from native buffer
bufLength = Math.min(posBuf.length, fvb.remaining());
tanLength = Math.min(tanBuf.length, ftb.remaining());
fvb.get(posBuf, 0, bufLength);
fnb.get(normBuf, 0, bufLength);
ftb.get(tanBuf, 0, tanLength);
int verts = bufLength / 3;
int idxPositions = 0;
//tangents has their own index because of the 4 components
int idxTangents = 0;
// iterate vertices and apply skinning transform for each effecting bone
for (int vert = verts - 1; vert >= 0; vert--) {
// Skip this vertex if the first weight is zero.
if (weights[idxWeights] == 0) {
idxTangents += 4;
idxPositions += 3;
idxWeights += 4;
continue;
}
float nmx = normBuf[idxPositions];
float vtx = posBuf[idxPositions++];
float nmy = normBuf[idxPositions];
float vty = posBuf[idxPositions++];
float nmz = normBuf[idxPositions];
float vtz = posBuf[idxPositions++];
float tnx = tanBuf[idxTangents++];
float tny = tanBuf[idxTangents++];
float tnz = tanBuf[idxTangents++];
// skipping the 4th component of the tangent since it doesn't have to be transformed
idxTangents++;
float rx = 0, ry = 0, rz = 0, rnx = 0, rny = 0, rnz = 0, rtx = 0, rty = 0, rtz = 0;
for (int w = maxWeightsPerVert - 1; w >= 0; w--) {
float weight = weights[idxWeights];
Matrix4f mat = offsetMatrices[indices[idxWeights++] & 0xff];
rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
rz += (mat.m20 * vtx + mat.m21 * vty + mat.m22 * vtz + mat.m23) * weight;
rnx += (nmx * mat.m00 + nmy * mat.m01 + nmz * mat.m02) * weight;
rny += (nmx * mat.m10 + nmy * mat.m11 + nmz * mat.m12) * weight;
rnz += (nmx * mat.m20 + nmy * mat.m21 + nmz * mat.m22) * weight;
rtx += (tnx * mat.m00 + tny * mat.m01 + tnz * mat.m02) * weight;
rty += (tnx * mat.m10 + tny * mat.m11 + tnz * mat.m12) * weight;
rtz += (tnx * mat.m20 + tny * mat.m21 + tnz * mat.m22) * weight;
}
idxWeights += fourMinusMaxWeights;
idxPositions -= 3;
normBuf[idxPositions] = rnx;
posBuf[idxPositions++] = rx;
normBuf[idxPositions] = rny;
posBuf[idxPositions++] = ry;
normBuf[idxPositions] = rnz;
posBuf[idxPositions++] = rz;
idxTangents -= 4;
tanBuf[idxTangents++] = rtx;
tanBuf[idxTangents++] = rty;
tanBuf[idxTangents++] = rtz;
//once again skipping the 4th component of the tangent
idxTangents++;
}
fvb.position(fvb.position() - bufLength);
fvb.put(posBuf, 0, bufLength);
fnb.position(fnb.position() - bufLength);
fnb.put(normBuf, 0, bufLength);
ftb.position(ftb.position() - tanLength);
ftb.put(tanBuf, 0, tanLength);
}
vars.release();
vb.updateData(fvb);
nb.updateData(fnb);
tb.updateData(ftb);
}
use of com.jme3.scene.VertexBuffer in project jmonkeyengine by jMonkeyEngine.
the class VertexBuffer method clone.
/**
* Creates a deep clone of this VertexBuffer but overrides the
* {@link Type}.
*
* @param overrideType The type of the cloned VertexBuffer
* @return A deep clone of the buffer
*/
public VertexBuffer clone(Type overrideType) {
VertexBuffer vb = new VertexBuffer(overrideType);
vb.components = components;
vb.componentsLength = componentsLength;
// Make sure to pass a read-only buffer to clone so that
// the position information doesn't get clobbered by another
// reading thread during cloning (and vice versa) since this is
// a purely read-only operation.
vb.data = BufferUtils.clone(getDataReadOnly());
vb.format = format;
vb.handleRef = new Object();
vb.id = -1;
vb.normalized = normalized;
vb.instanceSpan = instanceSpan;
vb.offset = offset;
vb.stride = stride;
vb.updateNeeded = true;
vb.usage = usage;
return vb;
}
use of com.jme3.scene.VertexBuffer in project jmonkeyengine by jMonkeyEngine.
the class GLRenderer method renderMeshDefault.
private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) {
// Here while count is still passed in. Can be removed when/if
// the method is collapsed again. -pspeed
count = Math.max(mesh.getInstanceCount(), count);
VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData);
if (interleavedData != null && interleavedData.isUpdateNeeded()) {
updateBufferData(interleavedData);
}
VertexBuffer indices;
if (mesh.getNumLodLevels() > 0) {
indices = mesh.getLodLevel(lod);
} else {
indices = mesh.getBuffer(Type.Index);
}
if (instanceData != null) {
for (VertexBuffer vb : instanceData) {
setVertexAttrib(vb, null);
}
}
for (VertexBuffer vb : mesh.getBufferList().getArray()) {
if (vb.getBufferType() == Type.InterleavedData || // ignore cpu-only buffers
vb.getUsage() == Usage.CpuOnly || vb.getBufferType() == Type.Index) {
continue;
}
if (vb.getStride() == 0) {
// not interleaved
setVertexAttrib(vb);
} else {
// interleaved
setVertexAttrib(vb, interleavedData);
}
}
clearVertexAttribs();
if (indices != null) {
drawTriangleList(indices, mesh, count);
} else {
drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
}
}
use of com.jme3.scene.VertexBuffer in project jmonkeyengine by jMonkeyEngine.
the class GLRenderer method renderMeshVertexArray.
private void renderMeshVertexArray(Mesh mesh, int lod, int count, VertexBuffer instanceData) {
if (mesh.getId() == -1) {
updateVertexArray(mesh, instanceData);
} else {
// TODO: Check if it was updated
}
if (context.boundVertexArray != mesh.getId()) {
gl3.glBindVertexArray(mesh.getId());
context.boundVertexArray = mesh.getId();
}
// IntMap<VertexBuffer> buffers = mesh.getBuffers();
VertexBuffer indices;
if (mesh.getNumLodLevels() > 0) {
indices = mesh.getLodLevel(lod);
} else {
indices = mesh.getBuffer(Type.Index);
}
if (indices != null) {
drawTriangleList(indices, mesh, count);
} else {
drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
}
clearVertexAttribs();
}
use of com.jme3.scene.VertexBuffer in project jmonkeyengine by jMonkeyEngine.
the class TangentBinormalGenerator method processTriangles.
private static List<VertexData> processTriangles(Mesh mesh, int[] index, Vector3f[] v, Vector2f[] t, boolean splitMirrored) {
IndexBuffer indexBuffer = mesh.getIndexBuffer();
FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
if (mesh.getBuffer(Type.TexCoord) == null) {
throw new IllegalArgumentException("Can only generate tangents for " + "meshes with texture coordinates");
}
FloatBuffer textureBuffer = (FloatBuffer) mesh.getBuffer(Type.TexCoord).getData();
List<VertexData> vertices = initVertexData(vertexBuffer.limit() / 3);
for (int i = 0; i < indexBuffer.size() / 3; i++) {
for (int j = 0; j < 3; j++) {
index[j] = indexBuffer.get(i * 3 + j);
populateFromBuffer(v[j], vertexBuffer, index[j]);
populateFromBuffer(t[j], textureBuffer, index[j]);
}
TriangleData triData = processTriangle(index, v, t);
if (splitMirrored) {
triData.setIndex(index);
triData.triangleOffset = i * 3;
}
vertices.get(index[0]).triangles.add(triData);
vertices.get(index[1]).triangles.add(triData);
vertices.get(index[2]).triangles.add(triData);
}
return vertices;
}
Aggregations