use of com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData in project jmonkeyengine by jMonkeyEngine.
the class TemporalMesh method prepareFacesGeometry.
/**
* The method creates geometries from faces.
* @param result
* the list where new geometries will be appended
* @param meshHelper
* the mesh helper
*/
protected void prepareFacesGeometry(List<Geometry> result, MeshHelper meshHelper) {
LOGGER.fine("Preparing faces geometries.");
this.triangulate();
Vector3f[] tempVerts = new Vector3f[3];
Vector3f[] tempNormals = new Vector3f[3];
byte[][] tempVertColors = new byte[3][];
List<Map<Float, Integer>> boneBuffers = new ArrayList<Map<Float, Integer>>(3);
LOGGER.log(Level.FINE, "Appending {0} faces to mesh buffers.", faces.size());
Map<Integer, MeshBuffers> faceMeshes = new HashMap<Integer, MeshBuffers>();
for (Face face : faces) {
MeshBuffers meshBuffers = faceMeshes.get(face.getMaterialNumber());
if (meshBuffers == null) {
meshBuffers = new MeshBuffers(face.getMaterialNumber());
faceMeshes.put(face.getMaterialNumber(), meshBuffers);
}
List<List<Integer>> triangulatedIndexes = face.getCurrentIndexes();
List<byte[]> vertexColors = face.getVertexColors();
for (List<Integer> indexes : triangulatedIndexes) {
assert indexes.size() == 3 : "The mesh has not been properly triangulated!";
Vector3f normal = null;
if (!face.isSmooth()) {
normal = FastMath.computeNormal(vertices.get(indexes.get(0)), vertices.get(indexes.get(1)), vertices.get(indexes.get(2)));
}
boneBuffers.clear();
for (int i = 0; i < 3; ++i) {
int vertIndex = indexes.get(i);
tempVerts[i] = vertices.get(vertIndex);
tempNormals[i] = normal != null ? normal : normals.get(vertIndex);
tempVertColors[i] = vertexColors != null ? vertexColors.get(face.getIndexes().indexOf(vertIndex)) : null;
if (boneIndexes.size() > 0 && vertexGroups.size() > 0) {
Map<Float, Integer> boneBuffersForVertex = new HashMap<Float, Integer>();
Map<String, Float> vertexGroupsForVertex = vertexGroups.get(vertIndex);
for (Entry<String, Integer> entry : boneIndexes.entrySet()) {
if (vertexGroupsForVertex.containsKey(entry.getKey())) {
float weight = vertexGroupsForVertex.get(entry.getKey());
if (weight > MINIMUM_BONE_WEIGHT) {
// only values of weight greater than MINIMUM_BONE_WEIGHT are used
// if all non zero weights were used, and they were samm enough, problems with normalisation would occur
// because adding a very small value to 1.0 will give 1.0
// so in order to avoid such errors, which can cause severe animation artifacts we need to use some minimum weight value
boneBuffersForVertex.put(weight, entry.getValue());
}
}
}
if (boneBuffersForVertex.size() == 0) {
// attach the vertex to zero-indexed bone so that it does not collapse to (0, 0, 0)
boneBuffersForVertex.put(1.0f, 0);
}
boneBuffers.add(boneBuffersForVertex);
}
}
Map<String, List<Vector2f>> uvs = meshHelper.selectUVSubset(face, indexes.toArray(new Integer[indexes.size()]));
meshBuffers.append(face.isSmooth(), tempVerts, tempNormals, uvs, tempVertColors, boneBuffers);
}
}
LOGGER.fine("Converting mesh buffers to geometries.");
Map<Geometry, MeshBuffers> geometryToBuffersMap = new HashMap<Geometry, MeshBuffers>();
for (Entry<Integer, MeshBuffers> entry : faceMeshes.entrySet()) {
MeshBuffers meshBuffers = entry.getValue();
Mesh mesh = new Mesh();
if (meshBuffers.isShortIndexBuffer()) {
mesh.setBuffer(Type.Index, 1, (ShortBuffer) meshBuffers.getIndexBuffer());
} else {
mesh.setBuffer(Type.Index, 1, (IntBuffer) meshBuffers.getIndexBuffer());
}
mesh.setBuffer(meshBuffers.getPositionsBuffer());
mesh.setBuffer(meshBuffers.getNormalsBuffer());
if (meshBuffers.areVertexColorsUsed()) {
mesh.setBuffer(Type.Color, 4, meshBuffers.getVertexColorsBuffer());
mesh.getBuffer(Type.Color).setNormalized(true);
}
BoneBuffersData boneBuffersData = meshBuffers.getBoneBuffers();
if (boneBuffersData != null) {
mesh.setMaxNumWeights(boneBuffersData.maximumWeightsPerVertex);
mesh.setBuffer(boneBuffersData.verticesWeights);
mesh.setBuffer(boneBuffersData.verticesWeightsIndices);
LOGGER.fine("Generating bind pose and normal buffers.");
mesh.generateBindPose(true);
// change the usage type of vertex and normal buffers from Static to Stream
mesh.getBuffer(Type.Position).setUsage(Usage.Stream);
mesh.getBuffer(Type.Normal).setUsage(Usage.Stream);
// creating empty buffers for HW skinning; the buffers will be setup if ever used
VertexBuffer verticesWeightsHW = new VertexBuffer(Type.HWBoneWeight);
VertexBuffer verticesWeightsIndicesHW = new VertexBuffer(Type.HWBoneIndex);
mesh.setBuffer(verticesWeightsHW);
mesh.setBuffer(verticesWeightsIndicesHW);
}
Geometry geometry = new Geometry(name + (result.size() + 1), mesh);
if (properties != null && properties.getValue() != null) {
meshHelper.applyProperties(geometry, properties);
}
result.add(geometry);
geometryToBuffersMap.put(geometry, meshBuffers);
}
LOGGER.fine("Applying materials to geometries.");
for (Entry<Geometry, MeshBuffers> entry : geometryToBuffersMap.entrySet()) {
int materialIndex = entry.getValue().getMaterialIndex();
Geometry geometry = entry.getKey();
if (materialIndex >= 0 && materials != null && materials.length > materialIndex && materials[materialIndex] != null) {
materials[materialIndex].applyMaterial(geometry, meshStructure.getOldMemoryAddress(), entry.getValue().getUvCoords(), blenderContext);
} else {
Material defaultMaterial = blenderContext.getDefaultMaterial().clone();
defaultMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
geometry.setMaterial(defaultMaterial);
}
}
}
use of com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData in project jmonkeyengine by jMonkeyEngine.
the class MeshBuffers method getBoneBuffers.
/**
* @return bone buffers
*/
public BoneBuffersData getBoneBuffers() {
BoneBuffersData result = null;
if (maximumWeightsPerVertex > 0) {
this.normalizeBoneBuffers(MAXIMUM_WEIGHTS_PER_VERTEX);
maximumWeightsPerVertex = MAXIMUM_WEIGHTS_PER_VERTEX;
FloatBuffer weightsFloatData = BufferUtils.createFloatBuffer(boneWeightAndIndexes.size() * MAXIMUM_WEIGHTS_PER_VERTEX);
ByteBuffer indicesData = BufferUtils.createByteBuffer(boneWeightAndIndexes.size() * MAXIMUM_WEIGHTS_PER_VERTEX);
int index = 0;
for (Map<Float, Integer> boneBuffersData : boneWeightAndIndexes) {
if (boneBuffersData.size() > 0) {
int count = 0;
for (Entry<Float, Integer> entry : boneBuffersData.entrySet()) {
weightsFloatData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX + count, entry.getKey());
indicesData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX + count, entry.getValue().byteValue());
++count;
}
} else {
// if no bone is assigned to this vertex then attach it to the 0-indexed root bone
weightsFloatData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX, 1.0f);
indicesData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX, (byte) 0);
}
++index;
}
VertexBuffer verticesWeights = new VertexBuffer(Type.BoneWeight);
verticesWeights.setupData(Usage.CpuOnly, maximumWeightsPerVertex, Format.Float, weightsFloatData);
VertexBuffer verticesWeightsIndices = new VertexBuffer(Type.BoneIndex);
verticesWeightsIndices.setupData(Usage.CpuOnly, maximumWeightsPerVertex, Format.UnsignedByte, indicesData);
result = new BoneBuffersData(maximumWeightsPerVertex, verticesWeights, verticesWeightsIndices);
}
return result;
}
Aggregations