diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java index 40b36ac22..2eedcc37d 100644 --- a/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java +++ b/engine/src/blender/com/jme3/scene/plugins/blender/modifiers/ArmatureModifier.java @@ -200,6 +200,8 @@ import com.jme3.util.BufferUtils; mesh.setBuffer(buffers[0]); mesh.setBuffer(buffers[1]); + //FIXME @Kaelthas this should be replaced by a call to + //mesh.generateBindPos(true) VertexBuffer bindNormalBuffer = meshContext.getBindNormalBuffer(materialIndex); if (bindNormalBuffer != null) { mesh.setBuffer(bindNormalBuffer); @@ -212,6 +214,14 @@ import com.jme3.util.BufferUtils; // 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); } } catch (BlenderFileException e) { LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e); diff --git a/engine/src/core-data/Common/ShaderLib/Skinning.glsllib b/engine/src/core-data/Common/ShaderLib/Skinning.glsllib index 399e9e3fb..66a9ff73b 100644 --- a/engine/src/core-data/Common/ShaderLib/Skinning.glsllib +++ b/engine/src/core-data/Common/ShaderLib/Skinning.glsllib @@ -6,38 +6,38 @@ #define NUM_WEIGHTS_PER_VERT 4 -attribute vec4 inBoneWeight; -attribute vec4 inBoneIndex; +attribute vec4 inHWBoneWeight; +attribute vec4 inHWBoneIndex; uniform mat4 m_BoneMatrices[NUM_BONES]; - + void Skinning_Compute(inout vec4 position){ - if (inBoneWeight.x != 0.0) { + if (inHWBoneWeight.x != 0.0) { #if NUM_WEIGHTS_PER_VERT == 1 - position = m_BoneMatrices[int(inBoneIndex.x)] * position; + position = m_BoneMatrices[int(inHWBoneIndex.x)] * position; #else mat4 mat = mat4(0.0); - mat += m_BoneMatrices[int(inBoneIndex.x)] * inBoneWeight.x; - mat += m_BoneMatrices[int(inBoneIndex.y)] * inBoneWeight.y; - mat += m_BoneMatrices[int(inBoneIndex.z)] * inBoneWeight.z; - mat += m_BoneMatrices[int(inBoneIndex.w)] * inBoneWeight.w; + mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x; + mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y; + mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z; + mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w; position = mat * position; #endif } } void Skinning_Compute(inout vec4 position, inout vec3 normal){ - if (inBoneWeight.x != 0.0) { + if (inHWBoneWeight.x != 0.0) { #if NUM_WEIGHTS_PER_VERT == 1 - position = m_BoneMatrices[int(inBoneIndex.x)] * position; - normal = (mat3(m_BoneMatrices[int(inBoneIndex.x)][0].xyz, - m_BoneMatrices[int(inBoneIndex.x)][1].xyz, - m_BoneMatrices[int(inBoneIndex.x)][2].xyz) * normal); + position = m_BoneMatrices[int(inHWBoneIndex.x)] * position; + normal = (mat3(m_BoneMatrices[int(inHWBoneIndex.x)][0].xyz, + m_BoneMatrices[int(inHWBoneIndex.x)][1].xyz, + m_BoneMatrices[int(inHWBoneIndex.x)][2].xyz) * normal); #else mat4 mat = mat4(0.0); - mat += m_BoneMatrices[int(inBoneIndex.x)] * inBoneWeight.x; - mat += m_BoneMatrices[int(inBoneIndex.y)] * inBoneWeight.y; - mat += m_BoneMatrices[int(inBoneIndex.z)] * inBoneWeight.z; - mat += m_BoneMatrices[int(inBoneIndex.w)] * inBoneWeight.w; + mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x; + mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y; + mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z; + mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w; position = mat * position; mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz); @@ -47,19 +47,19 @@ void Skinning_Compute(inout vec4 position, inout vec3 normal){ } void Skinning_Compute(inout vec4 position, inout vec3 tangent, inout vec3 normal){ - if (inBoneWeight.x != 0.0) { + if (inHWBoneWeight.x != 0.0) { #if NUM_WEIGHTS_PER_VERT == 1 - position = m_BoneMatrices[int(inBoneIndex.x)] * position; - tangent = m_BoneMatrices[int(inBoneIndex.x)] * tangent; - normal = (mat3(m_BoneMatrices[int(inBoneIndex.x)][0].xyz, - m_BoneMatrices[int(inBoneIndex.x)][1].xyz, - m_BoneMatrices[int(inBoneIndex.x)][2].xyz) * normal); + position = m_BoneMatrices[int(inHWBoneIndex.x)] * position; + tangent = m_BoneMatrices[int(inHWBoneIndex.x)] * tangent; + normal = (mat3(m_BoneMatrices[int(inHWBoneIndex.x)][0].xyz, + m_BoneMatrices[int(inHWBoneIndex.x)][1].xyz, + m_BoneMatrices[int(inHWBoneIndex.x)][2].xyz) * normal); #else mat4 mat = mat4(0.0); - mat += m_BoneMatrices[int(inBoneIndex.x)] * inBoneWeight.x; - mat += m_BoneMatrices[int(inBoneIndex.y)] * inBoneWeight.y; - mat += m_BoneMatrices[int(inBoneIndex.z)] * inBoneWeight.z; - mat += m_BoneMatrices[int(inBoneIndex.w)] * inBoneWeight.w; + mat += m_BoneMatrices[int(inHWBoneIndex.x)] * inHWBoneWeight.x; + mat += m_BoneMatrices[int(inHWBoneIndex.y)] * inHWBoneWeight.y; + mat += m_BoneMatrices[int(inHWBoneIndex.z)] * inHWBoneWeight.z; + mat += m_BoneMatrices[int(inHWBoneIndex.w)] * inHWBoneWeight.w; position = mat * position; mat3 rotMat = mat3(mat[0].xyz, mat[1].xyz, mat[2].xyz); diff --git a/engine/src/core/com/jme3/scene/Mesh.java b/engine/src/core/com/jme3/scene/Mesh.java index 7076b7fdc..527e103c5 100644 --- a/engine/src/core/com/jme3/scene/Mesh.java +++ b/engine/src/core/com/jme3/scene/Mesh.java @@ -353,28 +353,6 @@ public class Mesh implements Savable, Cloneable { */ public void prepareForAnim(boolean forSoftwareAnim){ if (forSoftwareAnim) { - // convert indices to ubytes on the heap - VertexBuffer indices = getBuffer(Type.BoneIndex); - if (!indices.getData().hasArray()) { - ByteBuffer originalIndex = (ByteBuffer) indices.getData(); - ByteBuffer arrayIndex = ByteBuffer.allocate(originalIndex.capacity()); - originalIndex.clear(); - arrayIndex.put(originalIndex); - indices.updateData(arrayIndex); - } - indices.setUsage(Usage.CpuOnly); - - // convert weights on the heap - VertexBuffer weights = getBuffer(Type.BoneWeight); - if (!weights.getData().hasArray()) { - FloatBuffer originalWeight = (FloatBuffer) weights.getData(); - FloatBuffer arrayWeight = FloatBuffer.allocate(originalWeight.capacity()); - originalWeight.clear(); - arrayWeight.put(originalWeight); - weights.updateData(arrayWeight); - } - weights.setUsage(Usage.CpuOnly); - // position, normal, and tanget buffers to be in "Stream" mode VertexBuffer positions = getBuffer(Type.Position); VertexBuffer normals = getBuffer(Type.Normal); @@ -387,25 +365,27 @@ public class Mesh implements Savable, Cloneable { tangents.setUsage(Usage.Stream); } } else { - VertexBuffer indices = getBuffer(Type.BoneIndex); - if (!indices.getData().isDirect()) { + //if HWBoneIndex and HWBoneWieght are empty, we setup them as direct + //buffers with software anim buffers data + VertexBuffer indicesHW = getBuffer(Type.HWBoneIndex); + if(indicesHW.getData() == null){ + VertexBuffer indices = getBuffer(Type.BoneIndex); ByteBuffer originalIndex = (ByteBuffer) indices.getData(); ByteBuffer directIndex = BufferUtils.createByteBuffer(originalIndex.capacity()); originalIndex.clear(); directIndex.put(originalIndex); - indices.updateData(directIndex); + indicesHW.setupData(Usage.Static, indices.getNumComponents(), indices.getFormat(), directIndex); } - indices.setUsage(Usage.Static); - VertexBuffer weights = getBuffer(Type.BoneWeight); - if (!weights.getData().isDirect()) { + VertexBuffer weightsHW = getBuffer(Type.HWBoneWeight); + if(weightsHW.getData() == null){ + VertexBuffer weights = getBuffer(Type.BoneWeight); FloatBuffer originalWeight = (FloatBuffer) weights.getData(); FloatBuffer directWeight = BufferUtils.createFloatBuffer(originalWeight.capacity()); originalWeight.clear(); directWeight.put(originalWeight); - weights.updateData(directWeight); - } - weights.setUsage(Usage.Static); + weightsHW.setupData(Usage.Static, weights.getNumComponents(), weights.getFormat(), directWeight); + } // position, normal, and tanget buffers to be in "Static" mode VertexBuffer positions = getBuffer(Type.Position); diff --git a/engine/src/core/com/jme3/scene/VertexBuffer.java b/engine/src/core/com/jme3/scene/VertexBuffer.java index 6405fd7aa..2ea6ab871 100644 --- a/engine/src/core/com/jme3/scene/VertexBuffer.java +++ b/engine/src/core/com/jme3/scene/VertexBuffer.java @@ -135,7 +135,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { /** * Bone weights, used with animation (4 floats). - * If used with software skinning, the usage should be + * Only used for software skinning, the usage should be * {@link Usage#CpuOnly}, and the buffer should be allocated * on the heap. */ @@ -143,10 +143,9 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { /** * Bone indices, used with animation (4 ubytes). - * If used with software skinning, the usage should be + * Only used for software skinning, the usage should be * {@link Usage#CpuOnly}, and the buffer should be allocated - * on the heap as a ubytes buffer. For Hardware skinning this should be - * either an int or float buffer due to shader attribute types restrictions. + * on the heap as a ubytes buffer. */ BoneIndex, @@ -193,6 +192,19 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { * on the heap. */ BindPoseTangent, + + /** + * Bone weights, used with animation (4 floats). + * for Hardware Skinning only + */ + HWBoneWeight, + + /** + * Bone indices, used with animation (4 ubytes). + * for Hardware Skinning only + * either an int or float buffer due to shader attribute types restrictions. + */ + HWBoneIndex, } /** diff --git a/engine/src/ogre/com/jme3/scene/plugins/ogre/MeshLoader.java b/engine/src/ogre/com/jme3/scene/plugins/ogre/MeshLoader.java index 70e73709b..5f2653281 100644 --- a/engine/src/ogre/com/jme3/scene/plugins/ogre/MeshLoader.java +++ b/engine/src/ogre/com/jme3/scene/plugins/ogre/MeshLoader.java @@ -72,7 +72,6 @@ public class MeshLoader extends DefaultHandler implements AssetLoader { private static final Logger logger = Logger.getLogger(MeshLoader.class.getName()); public static boolean AUTO_INTERLEAVE = true; - public static boolean HARDWARE_SKINNING = false; private static final Type[] TEXCOORD_TYPES = new Type[]{ Type.TexCoord, @@ -371,24 +370,28 @@ public class MeshLoader extends DefaultHandler implements AssetLoader { // each vertex has // - 4 bone weights // - 4 bone indices - if (HARDWARE_SKINNING) { - weightsFloatData = BufferUtils.createFloatBuffer(vertCount * 4); - indicesData = BufferUtils.createByteBuffer(vertCount * 4); - } else { - // create array-backed buffers if software skinning for access speed - weightsFloatData = FloatBuffer.allocate(vertCount * 4); - indicesData = ByteBuffer.allocate(vertCount * 4); - } + // create array-backed buffers for software skinning for access speed + weightsFloatData = FloatBuffer.allocate(vertCount * 4); + indicesData = ByteBuffer.allocate(vertCount * 4); VertexBuffer weights = new VertexBuffer(Type.BoneWeight); VertexBuffer indices = new VertexBuffer(Type.BoneIndex); - Usage usage = HARDWARE_SKINNING ? Usage.Static : Usage.CpuOnly; - weights.setupData(usage, 4, Format.Float, weightsFloatData); - indices.setupData(usage, 4, Format.UnsignedByte, indicesData); - + weights.setupData(Usage.CpuOnly, 4, Format.Float, weightsFloatData); + indices.setupData(Usage.CpuOnly, 4, Format.UnsignedByte, indicesData); + mesh.setBuffer(weights); mesh.setBuffer(indices); + + //creating empty buffers for HW skinning + //the buffers will be setup if ever used. + VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight); + VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex); + //setting usage to cpuOnly so that the buffer is not send empty to the GPU + indicesHW.setUsage(Usage.CpuOnly); + weightsHW.setUsage(Usage.CpuOnly); + mesh.setBuffer(weightsHW); + mesh.setBuffer(indicesHW); } private void startVertexBuffer(Attributes attribs) throws SAXException { @@ -773,10 +776,6 @@ public class MeshLoader extends DefaultHandler implements AssetLoader { m.extractVertexData(sharedMesh); } - // Old code for buffer sharer - //if (sharedMesh != null && isUsingSharedVerts(g)) { - // m.setBound(sharedMesh.getBound().clone()); - //} model.attachChild(geoms.get(i)); } @@ -785,26 +784,19 @@ public class MeshLoader extends DefaultHandler implements AssetLoader { if (animData != null) { // This model uses animation - // Old code for buffer sharer - // generate bind pose for mesh - // ONLY if not using shared geometry - // This includes the shared geoemtry itself actually - //if (sharedMesh != null) { - // sharedMesh.generateBindPose(!HARDWARE_SKINNING); - //} - for (int i = 0; i < geoms.size(); i++) { Geometry g = geoms.get(i); Mesh m = geoms.get(i).getMesh(); + + //FIXME the parameter is now useless. + //It was !HADWARE_SKINNING before, but since toggleing + //HW skinning does not happen at load time it was always true. + //We should use something similar as for the HWBoneIndex and + //HWBoneWeight : create the vertex buffers empty so that they + //are put in the cache, and really populate them the first time + //software skinning is used on the mesh. + m.generateBindPose(true); - m.generateBindPose(!HARDWARE_SKINNING); - - // Old code for buffer sharer - //boolean useShared = isUsingSharedVerts(g); - //if (!useShared) { - // create bind pose - //m.generateBindPose(!HARDWARE_SKINNING); - //} } // Put the animations in the AnimControl