OSDN Git Service

Some improvement of bone matrix calculation.
authorKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Tue, 12 Jun 2012 22:34:56 +0000 (07:34 +0900)
committerKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Tue, 12 Jun 2012 22:34:56 +0000 (07:34 +0900)
src/projectkyoto/jme3/mmd/PMDGeometry.java
src/projectkyoto/jme3/mmd/PMDLoaderGLSLSkinning2.java
src/projectkyoto/jme3/mmd/PMDMesh.java
src/projectkyoto/jme3/mmd/PMDNode.java
src/projectkyoto/jme3/mmd/PMDSkinMesh.java

index 0e2cbb0..5be3b60 100755 (executable)
@@ -38,7 +38,9 @@ import com.jme3.math.Matrix4f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer.Type;
+import com.jme3.util.BufferUtils;
 import java.io.IOException;
+import java.nio.FloatBuffer;
 import projectkyoto.mmd.file.PMDMaterial;
 
 /**
@@ -112,6 +114,10 @@ public class PMDGeometry extends Geometry {
             newMesh.bound = oldMesh.bound.clone();
             newMesh.setBuffer(oldMesh.getBuffer(Type.Index));
             newPMDGeometry.setMesh(newMesh);
+
+            newMesh.setBoneIndexBuffer(oldMesh.getBoneIndexBuffer());
+            FloatBuffer fb = BufferUtils.createFloatBuffer(oldMesh.getBoneMatrixBuffer().capacity());
+            newMesh.setBoneMatrixBuffer(fb);
         } else {
             PMDMesh oldMesh = (PMDMesh)mesh;
             PMDMesh newMesh = new PMDMesh();
@@ -135,6 +141,10 @@ public class PMDGeometry extends Geometry {
             if (oldMesh.getBuffer(Type.InterleavedData) != null)
             newMesh.setBuffer(oldMesh.getBuffer(Type.InterleavedData));
             newPMDGeometry.setMesh(newMesh);
+            
+            newMesh.setBoneIndexBuffer(oldMesh.getBoneIndexBuffer());
+            FloatBuffer fb = BufferUtils.createFloatBuffer(oldMesh.getBoneMatrixBuffer().capacity());
+            newMesh.setBoneMatrixBuffer(fb);
 //            newMesh.setInterleaved();
         }
         newPMDGeometry.glslSkinningMaterial = glslSkinningMaterial.clone();
index c58b1a1..0c4bf40 100755 (executable)
@@ -312,11 +312,18 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
         ib.setupData(VertexBuffer.Usage.Static, 1, VertexBuffer.Format.UnsignedShort, isb);
         mesh.setBuffer(ib);
         mesh.setBoneIndexArray(skinIndexArray);
+        ShortBuffer boneIndexBuffer = BufferUtils.createShortBuffer(skinIndexArray.length);
+        for(int i=0;i<skinIndexArray.length;i++) {
+            boneIndexBuffer.put((short)skinIndexArray[i]);
+        }
+        mesh.setBoneIndexBuffer(boneIndexBuffer);
         mesh.setBoneMatrixArray(new Matrix4f[skinIndexArray.length]);
         for (int i = 0; i < mesh.getBoneMatrixArray().length; i++) {
             mesh.getBoneMatrixArray()[i] = new Matrix4f();
             mesh.getBoneMatrixArray()[i].loadIdentity();
         }
+        FloatBuffer boneMatrixBuffer = BufferUtils.createFloatBuffer(skinIndexArray.length * 16);
+        mesh.setBoneMatrixBuffer(boneMatrixBuffer);
         return mesh;
     }
 
@@ -413,19 +420,26 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
         mesh.setBuffer(ib);
         mesh.setBuffer(bib);
         int[] indexArray = new int[md.getBoneList().size()];
+        ShortBuffer indexBuffer = BufferUtils.createShortBuffer(md.getBoneList().size());
         for (int i = 0; i < indexArray.length; i++) {
             if (i < md.getBoneList().size()) {
                 indexArray[i] = md.getBoneList().get(i).shortValue();
             } else {
                 indexArray[i] = 0;
             }
+            indexBuffer.put((short)indexArray[i]);
         }
         mesh.setBoneIndexArray(indexArray);
+        mesh.setBoneIndexBuffer(indexBuffer);
+        FloatBuffer boneMatrixBuffer = BufferUtils.createFloatBuffer(16 * indexArray.length);
         mesh.setBoneMatrixArray(new Matrix4f[indexArray.length]);
+        mesh.setBoneMatrixBuffer(boneMatrixBuffer);
         for (int i = 0; i < mesh.getBoneMatrixArray().length; i++) {
             mesh.getBoneMatrixArray()[i] = new Matrix4f();
             mesh.getBoneMatrixArray()[i].loadIdentity();
+            mesh.getBoneMatrixArray()[i].fillFloatBuffer(boneMatrixBuffer, true);
         }
+        boneMatrixBuffer.position(0);
         return mesh;
     }
 
index 7b93ec9..a40161e 100755 (executable)
@@ -42,6 +42,7 @@ import com.jme3.scene.VertexBuffer;
 import com.jme3.util.BufferUtils;
 import java.io.IOException;
 import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
 
 /**
  *
@@ -53,6 +54,8 @@ public class PMDMesh extends Mesh {
     Matrix4f boneMatrixArray[];
     VertexBuffer vbBackup;
     VertexBuffer nbBackup;
+    ShortBuffer boneIndexBuffer;
+    FloatBuffer boneMatrixBuffer;
     
     int boneMatricesParamIndex = -1;
 
@@ -178,5 +181,21 @@ public class PMDMesh extends Mesh {
         OutputCapsule c = ex.getCapsule(this);
         c.write(boneIndexArray, "boneIndexArray", null);
     }
+
+    public ShortBuffer getBoneIndexBuffer() {
+        return boneIndexBuffer;
+    }
+
+    public void setBoneIndexBuffer(ShortBuffer boneIndexBuffer) {
+        this.boneIndexBuffer = boneIndexBuffer;
+    }
+
+    public FloatBuffer getBoneMatrixBuffer() {
+        return boneMatrixBuffer;
+    }
+
+    public void setBoneMatrixBuffer(FloatBuffer boneMatrixBuffer) {
+        this.boneMatrixBuffer = boneMatrixBuffer;
+    }
     
 }
index c78775d..5ccea30 100755 (executable)
@@ -58,6 +58,7 @@ import com.jme3.scene.control.BillboardControl;
 import com.jme3.scene.debug.SkeletonWire;
 import com.jme3.scene.shape.Box;
 import com.jme3.shader.VarType;
+import com.jme3.util.BufferUtils;
 import java.nio.ShortBuffer;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -95,6 +96,7 @@ public class PMDNode extends Node {
 //    int skinBoneArray[];
     AssetManager assetManager;
     Matrix4f[] offsetMatrices;
+    FloatBuffer offsetMatrixbuffer;
     boolean updateNeeded = true;
     boolean skinUpdateNeeded = true;
     boolean wireFrame = false;
@@ -270,6 +272,13 @@ public class PMDNode extends Node {
 
     public Matrix4f[] calcOffsetMatrices() {
         offsetMatrices = skeleton.computeSkinningMatrices();
+        if (offsetMatrixbuffer == null) {
+            offsetMatrixbuffer = BufferUtils.createFloatBuffer(offsetMatrices.length * 16);
+        }
+        offsetMatrixbuffer.position(0);
+        for(Matrix4f m : offsetMatrices) {
+            m.fillFloatBuffer(offsetMatrixbuffer, true);
+        }
         return offsetMatrices;
     }
 boolean setBoneMatricesFlag = true;
@@ -289,18 +298,35 @@ boolean setBoneMatricesFlag = true;
                 PMDMesh pmdMesh = (PMDMesh)g.getMesh();
                 int boneIndexArray[] = pmdMesh.getBoneIndexArray();
                 Matrix4f[] boneMatrixArray = pmdMesh.getBoneMatrixArray();
-                for (int i = pmdMesh.getBoneIndexArray().length-1; i >=0; i--) {
-                    boneMatrixArray[i] = (offsetMatrices[boneIndexArray[i]]);
-                }
+//                for (int i = pmdMesh.getBoneIndexArray().length-1; i >=0; i--) {
+//                    boneMatrixArray[i] = (offsetMatrices[boneIndexArray[i]]);
+//                }
+                
                 if (glslSkinning) {
+//                    if (pmdMesh.boneMatricesParamIndex < 0) {
+//                        m.setParam("BoneMatrices", VarType.Matrix4Array, pmdMesh.getBoneMatrixArray());
+//                        pmdMesh.boneMatricesParamIndex = g.getMaterial().getParamIndex("BoneMatrices");
+//                    } else {
+//                        m.setParam(pmdMesh.boneMatricesParamIndex, VarType.Matrix4Array, pmdMesh.getBoneMatrixArray());
+//                    }
+                    FloatBuffer fb = pmdMesh.getBoneMatrixBuffer();
+                    fb.position(0);
+//                    for(int i=0;i<pmdMesh.getBoneIndexArray().length;i++) {
+//                        offsetMatrices[pmdMesh.getBoneIndexBuffer().get(i)].fillFloatBuffer(fb, true);
+////                        pmdMesh.getBoneMatrixArray()[i].fillFloatBuffer(fb, true);
+//                    }
+                    projectkyoto.jme3.mmd.nativelib.SkinUtil.copyBoneMatrix(offsetMatrixbuffer, fb, pmdMesh.getBoneIndexBuffer());
+
+//                    fb.position(0);
                     if (pmdMesh.boneMatricesParamIndex < 0) {
-                        m.setParam("BoneMatrices", VarType.Matrix4Array, pmdMesh.getBoneMatrixArray());
+                        m.setParam("BoneMatrices", VarType.Matrix4Array, pmdMesh.getBoneMatrixBuffer());
                         pmdMesh.boneMatricesParamIndex = g.getMaterial().getParamIndex("BoneMatrices");
                     } else {
-                        m.setParam(pmdMesh.boneMatricesParamIndex, VarType.Matrix4Array, pmdMesh.getBoneMatrixArray());
+                        m.setParam(pmdMesh.boneMatricesParamIndex, VarType.Matrix4Array, pmdMesh.getBoneMatrixBuffer());
                     }
                 }
             }
+            FloatBuffer fb = null;
             for(int i=getChildren().size()-1;i>=0;i--) {
                 Spatial sp = getChild(i);
                 if (sp instanceof PMDGeometry) {
@@ -310,16 +336,21 @@ boolean setBoneMatricesFlag = true;
                         PMDSkinMesh skinMesh = (PMDSkinMesh)mesh;
                         Material m = g.getMaterial();
                         int boneIndexArray[] = skinMesh.getBoneIndexArray();
-                        Matrix4f[] boneMatrixArray = skinMesh.getBoneMatrixArray();
-                        for (int i2 = skinMesh.getBoneIndexArray().length-1; i2 >=0; i2--) {
-                            boneMatrixArray[i2] = (offsetMatrices[boneIndexArray[i2]]);
+//                        Matrix4f[] boneMatrixArray = skinMesh.getBoneMatrixArray();
+//                        for (int i2 = skinMesh.getBoneIndexArray().length-1; i2 >=0; i2--) {
+//                            boneMatrixArray[i2] = (offsetMatrices[boneIndexArray[i2]]);
+//                        }
+                        if (fb == null) {
+                            fb = skinMesh.getBoneMatrixBuffer();
+                            fb.position(0);
+                            projectkyoto.jme3.mmd.nativelib.SkinUtil.copyBoneMatrix(offsetMatrixbuffer, fb, skinMesh.getBoneIndexBuffer());
                         }
                         if (glslSkinning) {
                             if (skinMesh.boneMatricesParamIndex < 0) {
-                                m.setParam("BoneMatrices", VarType.Matrix4Array, skinMesh.getBoneMatrixArray());
+                                m.setParam("BoneMatrices", VarType.Matrix4Array, fb);
                                 skinMesh.boneMatricesParamIndex = g.getMaterial().getParamIndex("BoneMatrices");
                             } else {
-                                m.setParam(skinMesh.boneMatricesParamIndex, VarType.Matrix4Array, skinMesh.getBoneMatrixArray());
+                                m.setParam(skinMesh.boneMatricesParamIndex, VarType.Matrix4Array, fb);
                             }
                         }
                     }
index dafd716..09ef8b1 100755 (executable)
@@ -41,6 +41,7 @@ import com.jme3.scene.VertexBuffer;
 import com.jme3.util.BufferUtils;
 import java.io.IOException;
 import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
 
 /**
  *
@@ -53,6 +54,8 @@ public class PMDSkinMesh extends Mesh {
     VertexBuffer skinvb2;
     VertexBuffer skinnb2;
     int boneMatricesParamIndex = -1;
+    ShortBuffer boneIndexBuffer;
+    FloatBuffer boneMatrixBuffer;
     public PMDSkinMesh() {
         super();
     }
@@ -88,6 +91,22 @@ public class PMDSkinMesh extends Mesh {
     public void setSkinvb2(VertexBuffer skinvb2) {
         this.skinvb2 = skinvb2;
     }
+
+    public ShortBuffer getBoneIndexBuffer() {
+        return boneIndexBuffer;
+    }
+
+    public void setBoneIndexBuffer(ShortBuffer boneIndexBuffer) {
+        this.boneIndexBuffer = boneIndexBuffer;
+    }
+
+    public FloatBuffer getBoneMatrixBuffer() {
+        return boneMatrixBuffer;
+    }
+
+    public void setBoneMatrixBuffer(FloatBuffer boneMatrixBuffer) {
+        this.boneMatrixBuffer = boneMatrixBuffer;
+    }
     
     BoundingVolume bound = new BoundingBox(Vector3f.ZERO, 20, 20, 20);