OSDN Git Service

support multi thread
authorKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Thu, 4 Aug 2011 00:28:47 +0000 (09:28 +0900)
committerKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Thu, 4 Aug 2011 00:28:47 +0000 (09:28 +0900)
sphere map bug fix

13 files changed:
src/MatDefs/pmd/pmd.frag
src/MatDefs/pmd/pmd.vert
src/MatDefs/pmd/pmd_no_skinning.vert
src/projectkyoto/jme3/mmd/PMDLoaderGLSLSkinning2.java
src/projectkyoto/jme3/mmd/PMDNode.java
src/projectkyoto/jme3/mmd/PMDSkinMesh.java
src/projectkyoto/jme3/mmd/RigidBodyConverter.java
src/projectkyoto/jme3/mmd/UpdateControl.java
src/projectkyoto/jme3/mmd/ik/IKControl.java
src/projectkyoto/jme3/mmd/nativebullet/PMDPhysicsWorld.java
src/projectkyoto/jme3/mmd/vmd/VMDCallable.java [new file with mode: 0644]
src/projectkyoto/jme3/mmd/vmd/VMDControl.java
src/projectkyoto/jme3/mmd/vmd/VMDControlMT.java [new file with mode: 0644]

index c8fa002..dc0756f 100755 (executable)
@@ -123,6 +123,11 @@ vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec3 w
    return vec2(diffuseFactor, specularFactor) * vec2(att);\r
 }\r
 #endif\r
+vec2 Optics_SphereCoord2(in vec3 dir){\r
+    float dzplus1 = dir.z + 1.0;\r
+    float m = 2 * sqrt(dir.x * dir.x + dir.y * dir.y + dzplus1 * dzplus1);\r
+    return vec2(dir.x / m + 0.5, dir.y / m + 0.5);\r
+}\r
 \r
 void main(){\r
     vec2 newTexCoord;\r
@@ -229,15 +234,17 @@ void main(){
 //                       SpecularSum2 * specularColor * light.y ) * 0.8;\r
        vec4 output_color = (((AmbientSum + DiffuseSum) * diffuseColor)  +\r
                        SpecularSum2 * specularColor * light.y );\r
+// output_color=vec4(0);\r
 #ifdef SPHERE_MAP_A\r
         vec2 v2 = Optics_SphereCoord(normalize(refVec.xyz));\r
         v2.y = 1 - v2.y;\r
         output_color.xyz +=  (texture2D(m_SphereMap_A, v2).xyz);\r
+        // output_color.xyz = vec3(normalize(refVec.xyz).x);\r
 #endif\r
 #ifdef SPHERE_MAP_H\r
         vec2 v2 = Optics_SphereCoord(normalize(refVec.xyz));\r
         v2.y = 1 - v2.y;\r
-        output_color.xyz *= texture2D(m_SphereMap_H, v2).xyz;\r
+        output_color.xyz *= (texture2D(m_SphereMap_H, v2).xyz);\r
 #endif\r
 \r
     #endif\r
index af6adf2..b45f60f 100755 (executable)
@@ -70,10 +70,10 @@ attribute vec3 inNormal;
      * varying refVec\r
      */\r
     void computeRef(in vec4 position, in vec4 normal){\r
-        vec3 worldPos = (g_WorldMatrix * vec4(position.xyz,1.0)).xyz;\r
+        vec3 worldPos = (g_WorldMatrix * vec4(normalize(position.xyz),1.0)).xyz;\r
 \r
         vec3 I = normalize( g_CameraPosition - worldPos  ).xyz;\r
-        vec3 N = normalize( (g_WorldMatrix * vec4(normal.xyz, 0.0)).xyz );\r
+        vec3 N = normalize( (g_WorldMatrix * vec4(normalize(normal.xyz), 0.0)).xyz );\r
 \r
         refVec.xyz = reflect(I, N);\r
         refVec.w   = 1;//m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);\r
@@ -218,7 +218,7 @@ void main(){
        SpecularSum.a = light.y;\r
     #endif\r
 \r
-    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_A)\r
+    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_H)\r
         computeRef(pos,normal);\r
     #endif \r
 }\r
index 5d21e19..768ee66 100755 (executable)
@@ -68,10 +68,10 @@ attribute vec3 inNormal;
      * varying refVec\r
      */\r
     void computeRef(in vec4 position, in vec4 normal){\r
-        vec3 worldPos = (g_WorldMatrix * vec4(position.xyz,1.0)).xyz;\r
+        vec3 worldPos = (g_WorldMatrix * vec4(normalize(position.xyz),1.0)).xyz;\r
 \r
         vec3 I = normalize( g_CameraPosition - worldPos  ).xyz;\r
-        vec3 N = normalize( (g_WorldMatrix * vec4(normal.xyz, 0.0)).xyz );\r
+        vec3 N = normalize( (g_WorldMatrix * vec4(normalize(normal.xyz), 0.0)).xyz );\r
 \r
         refVec.xyz = reflect(I, N);\r
         refVec.w   = 1;//m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);\r
@@ -214,7 +214,7 @@ void main(){
        SpecularSum.a = light.y;\r
     #endif\r
 \r
-    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_A)\r
+    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_H)\r
         computeRef(pos,normal);\r
     #endif \r
 }\r
index a01a10f..74fde61 100755 (executable)
@@ -75,7 +75,9 @@ public class PMDLoaderGLSLSkinning2 {
     List<PMDMesh> meshList = new ArrayList<PMDMesh>();
     List<PMDSkinMesh> skinMeshList = new ArrayList<PMDSkinMesh>();
     VertexBuffer skinvb;
+    VertexBuffer skinvb2;
     VertexBuffer skinnb;
+    VertexBuffer skinnb2;
     VertexBuffer skintb;
     Skin skinArray[];
     SkeletonControl skeletonControl;
@@ -86,7 +88,7 @@ public class PMDLoaderGLSLSkinning2 {
 //        System.out.println("vertexCount = " + model.getVertCount());
 //        System.out.println("faceVertCount = " + model.getFaceVertCount());
         meshConverter = new MeshConverter(model);
-        assetManager.registerLoader(com.jme3.texture.plugins.AWTLoader.class, "sph","spa");
+        assetManager.registerLoader(com.jme3.texture.plugins.AWTLoader.class, "sph", "spa");
     }
 
     public PMDNode createNode(String name) {
@@ -124,10 +126,18 @@ public class PMDLoaderGLSLSkinning2 {
         FloatBuffer skinvfb = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
         skinvb.setupData(VertexBuffer.Usage.Static, 3, VertexBuffer.Format.Float, skinvfb);
 
+        skinvb2 = new VertexBuffer(VertexBuffer.Type.Position);
+        FloatBuffer skinvfb2 = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
+        skinvb2.setupData(VertexBuffer.Usage.Static, 3, VertexBuffer.Format.Float, skinvfb2);
+        
         skinnb = new VertexBuffer(VertexBuffer.Type.Normal);
         FloatBuffer skinnfb = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
         skinnb.setupData(VertexBuffer.Usage.Static, 3, VertexBuffer.Format.Float, skinnfb);
 
+        skinnb2 = new VertexBuffer(VertexBuffer.Type.Normal);
+        FloatBuffer skinnfb2 = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
+        skinnb2.setupData(VertexBuffer.Usage.Static, 3, VertexBuffer.Format.Float, skinnfb2);
+        
         skintb = new VertexBuffer(VertexBuffer.Type.TexCoord);
         FloatBuffer skintfb = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 2);
         skintb.setupData(VertexBuffer.Usage.Static, 2, VertexBuffer.Format.Float, skintfb);
@@ -144,7 +154,9 @@ public class PMDLoaderGLSLSkinning2 {
         List<Integer> indexList = meshConverter.getSkinMeshData().getIndexMap().get(pmdMaterial);
         mesh.setMode(Mesh.Mode.Triangles);
         mesh.setBuffer(skinvb);
+        mesh.setSkinvb2(skinvb2);
         mesh.setBuffer(skinnb);
+        mesh.setSkinnb2(skinnb2);
         mesh.setBuffer(skintb);
         VertexBuffer ib = new VertexBuffer(VertexBuffer.Type.Index);
         ShortBuffer isb = BufferUtils.createShortBuffer(indexList.size());
@@ -290,22 +302,24 @@ public class PMDLoaderGLSLSkinning2 {
         mat.setFloat("Shininess", m.getMaterial().getPower());
         if (m.getTextureFileName().length() > 0) {
             StringTokenizer st = new StringTokenizer(m.getTextureFileName(), "*");
-            System.out.println("m.getTextureFileName() = "+m.getTextureFileName());
-            while(st.hasMoreElements()) {
+            System.out.println("m.getTextureFileName() = " + m.getTextureFileName());
+            while (st.hasMoreElements()) {
                 String fileName = st.nextToken();
-                System.out.println("fileName = "+fileName);
-                String s = fileName.substring(fileName.indexOf('.')+1);
+                System.out.println("fileName = " + fileName);
+                String s = fileName.substring(fileName.indexOf('.') + 1);
                 Texture texture = assetManager.loadTexture("Model/" + fileName /*
                          * m.getTextureFileName()
                          */);
                 s = s.toLowerCase();
                 if (s.equals("spa")) {
-                     mat.setTexture("SphereMap_A", texture);
+                    texture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
+                    mat.setTexture("SphereMap_A", texture);
                 } else if (s.equals("sph")) {
-                     mat.setTexture("SphereMap_H", texture);
+                    texture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
+                    mat.setTexture("SphereMap_H", texture);
                 } else {
 //                    texture.setWrap(Texture.WrapMode.Repeat);
-                     mat.setTexture("DiffuseMap", texture);
+                    mat.setTexture("DiffuseMap", texture);
                 }
             }
         }
@@ -314,8 +328,8 @@ public class PMDLoaderGLSLSkinning2 {
         if (toonIndex >= 0) {
             String extToonName = model.getToonTextureList().getToonFileName()[toonIndex];
             try {
-                toonTexture = assetManager.loadTexture("/Model/"+extToonName);
-            } catch(AssetNotFoundException ex) {
+                toonTexture = assetManager.loadTexture("/Model/" + extToonName);
+            } catch (AssetNotFoundException ex) {
                 String toonname = null;
                 switch (toonIndex) {
                     case 0:
@@ -373,16 +387,16 @@ public class PMDLoaderGLSLSkinning2 {
 //        mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
 //        mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
 //        mat.getAdditionalRenderState().setWireframe(true);
-                if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
-                    mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
-                    mat.getAdditionalRenderState().setAlphaTest(true);
+        if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
+            mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
+            mat.getAdditionalRenderState().setAlphaTest(true);
 //                    mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
-                } else {
-                    mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
+        } else {
+            mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
 //                    mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
 //                    mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
-                    mat.getAdditionalRenderState().setAlphaTest(true);
-                }
+            mat.getAdditionalRenderState().setAlphaTest(true);
+        }
         return mat;
     }
 
index 0c297b5..6b6ffa3 100755 (executable)
@@ -81,6 +81,7 @@ public class PMDNode extends Node {
     AssetManager assetManager;
     Matrix4f[] offsetMatrices;
     boolean updateNeeded = true;
+    boolean skinUpdateNeeded = true;
     boolean wireFrame = false;
     float edgeSize = 1.0f;
     boolean skeletonWireVisible = false;
@@ -177,7 +178,11 @@ public class PMDNode extends Node {
                     softwareSkinUpdate(mesh);
                 }
             }
-            updateSkinMesh(skinTargets[0]);
+//            updateSkinMesh(skinTargets[0]);
+//            if (skinUpdateNeeded) {
+//                updateSkinBackData();
+//            }
+            swapSkinMesh();
             if (skeletonWireGeom != null) {
                 ((SkeletonWire) skeletonWireGeom.getMesh()).updateGeometry();
             }
@@ -205,7 +210,28 @@ public class PMDNode extends Node {
             }
         }
     }
-
+    private void swapSkinMesh() {
+        VertexBuffer vb = skinTargets[0].getBuffer(VertexBuffer.Type.Position);
+        vb.setUsage(Usage.CpuOnly);
+        VertexBuffer nb = skinTargets[0].getBuffer(VertexBuffer.Type.Normal);
+        nb.setUsage(Usage.CpuOnly);
+        skinTargets[0].skinvb2.setUpdateNeeded();
+        skinTargets[0].skinvb2.setUsage(Usage.Static);
+        skinTargets[0].skinnb2.setUpdateNeeded();
+        skinTargets[0].skinnb2.setUsage(Usage.Static);
+        for(PMDSkinMesh skinMesh : skinTargets) {
+            skinMesh.clearBuffer(Type.Position);
+            skinMesh.clearBuffer(Type.Normal);
+            skinMesh.setBuffer(skinTargets[0].getSkinvb2());
+            skinMesh.setBuffer(skinTargets[0].getSkinnb2());
+        }
+        skinTargets[0].skinvb2 = vb;
+        skinTargets[0].skinnb2 = nb;
+        vb = skinTargets[0].getBuffer(VertexBuffer.Type.Position);
+        nb = skinTargets[0].getBuffer(VertexBuffer.Type.Normal);
+        vb.setUpdateNeeded();
+        nb.setUpdateNeeded();
+    }
     private void softwareSkinUpdate(PMDMesh mesh) {
         int maxWeightsPerVert = 2;//mesh.getMaxNumWeights();
         int fourMinusMaxWeights = 4 - maxWeightsPerVert;
@@ -294,6 +320,75 @@ public class PMDNode extends Node {
         vars.release();
 //        mesh.updateBound();
     }
+    public void updateSkinBackData() {
+        PMDSkinMesh skinMesh = skinTargets[0];
+        VertexBuffer vb = skinMesh.getSkinvb2(); //.getBuffer(Type.Position);
+        FloatBuffer fvb = (FloatBuffer) vb.getData();
+        VertexBuffer nb = skinMesh.getSkinnb2(); //skinMesh.getBuffer(Type.Normal);
+        FloatBuffer fnb = (FloatBuffer) nb.getData();
+
+        for (Skin skin : skinMap.values()) {
+            if (true || skin.isUpdateNeeded()) {
+                if (skin.getWeight() != 0f) {
+                    for (PMDSkinVertData svd : skin.getSkinData().getSkinVertData()) {
+                        javax.vecmath.Vector3f dist = skinPosArray[svd.getSkinVertIndex()];
+                        dist.set(svd.getSkinVertPos());
+                        dist.scale(skin.getWeight());
+                        dist.add(skinPosArrayOrig[svd.getSkinVertIndex()]);
+                    }
+                }
+                skin.setUpdateNeeded(false);
+            }
+        }
+
+        fvb.position(0);
+        fnb.position(0);
+        TempVars vars = TempVars.get();
+        for (int i = 0; i < skinPosArray.length; i++) {
+            int idxWeights = 0;
+
+            float[] posBuf = vars.skinPositions;
+            float[] normBuf = vars.skinNormals;
+
+            // read next set of positions and normals from native buffer
+            int idxPositions = 0;
+
+            // iterate vertices and apply skinning transform for each effecting bone
+            float nmx = skinNormalArray[i].x;//normBuf[idxPositions];
+            float vtx = skinPosArray[i].x;//posBuf[idxPositions++];
+            float nmy = skinNormalArray[i].y;//normBuf[idxPositions];
+            float vty = skinPosArray[i].y;//posBuf[idxPositions++];
+            float nmz = skinNormalArray[i].z;//normBuf[idxPositions];
+            float vtz = skinPosArray[i].z;//posBuf[idxPositions++];
+
+            float rx = 0, ry = 0, rz = 0, rnx = 0, rny = 0, rnz = 0;
+
+            for (int w = 2 - 1; w >= 0; w--) {
+                float weight = skinBoneWeightArray[i];//(float) v.getBoneWeight();//weights[idxWeights];
+                if (w == 1) {
+                    weight = 1f - weight;
+                }
+                //weight = weight / 100f;
+
+                Matrix4f mat = offsetMatrices[skinBoneArray[i * 2 + w]];
+
+                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;
+            }
+
+            fnb.put(rnx).put(rny).put(rnz);
+            fvb.put(rx).put(ry).put(rz);
+        }
+        vars.release();
+        vb.setUpdateNeeded();
+        nb.setUpdateNeeded();
+        skinUpdateNeeded = false;
+    }
 
     void updateSkinMesh(PMDSkinMesh skinMesh) {
         VertexBuffer vb = skinMesh.getBuffer(Type.Position);
@@ -413,7 +508,26 @@ public class PMDNode extends Node {
         vb.setUpdateNeeded();
         nb.setUpdateNeeded();
     }
+    void resetToBindSkinBackData(PMDSkinMesh mesh) {
+        VertexBuffer vb = mesh.getSkinvb2(); // mesh.getBuffer(VertexBuffer.Type.Position);
+        FloatBuffer vfb = (FloatBuffer) vb.getData();
+        VertexBuffer nb = mesh.getSkinnb2(); //mesh.getBuffer(VertexBuffer.Type.Normal);
+        FloatBuffer nfb = (FloatBuffer) nb.getData();
 
+        VertexBuffer bvb = mesh.getBuffer(VertexBuffer.Type.BindPosePosition);
+        FloatBuffer bvfb = (FloatBuffer) bvb.getData();
+        VertexBuffer bnb = mesh.getBuffer(VertexBuffer.Type.BindPoseNormal);
+        FloatBuffer bnfb = (FloatBuffer) bnb.getData();
+
+        for (int i = 0; i < vfb.capacity(); i++) {
+            vfb.put(i, bvfb.get(i));
+        }
+        for (int i = 0; i < nfb.capacity(); i++) {
+            nfb.put(i, bnfb.get(i));
+        }
+        vb.setUpdateNeeded();
+        nb.setUpdateNeeded();
+    }
     public Set<String> getSkinSet() {
         return skinMap.keySet();
     }
@@ -426,6 +540,7 @@ public class PMDNode extends Node {
         Skin skin = skinMap.get(skinName);
         if (skin != null) {
             skin.setWeight(weight);
+            skinUpdateNeeded = true;
 //            for (PMDSkinVertData svd : skin.getSkinData().getSkinVertData()) {
 //                javax.vecmath.Vector3f dist = skinPosArray[svd.getSkinVertIndex()];
 //                dist.set(svd.getSkinVertPos());
index d42abbd..2c177d6 100755 (executable)
@@ -34,6 +34,7 @@ import com.jme3.bounding.BoundingVolume;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer;
 
 /**
  *
@@ -43,6 +44,8 @@ public class PMDSkinMesh extends Mesh {
 
     short boneIndexArray[];
     Matrix4f boneMatrixArray[];
+    VertexBuffer skinvb2;
+    VertexBuffer skinnb2;
 
     public PMDSkinMesh() {
         super();
@@ -63,6 +66,23 @@ public class PMDSkinMesh extends Mesh {
     public void setBoneMatrixArray(Matrix4f[] boneMatrixArray) {
         this.boneMatrixArray = boneMatrixArray;
     }
+
+    public VertexBuffer getSkinnb2() {
+        return skinnb2;
+    }
+
+    public void setSkinnb2(VertexBuffer skinnb2) {
+        this.skinnb2 = skinnb2;
+    }
+
+    public VertexBuffer getSkinvb2() {
+        return skinvb2;
+    }
+
+    public void setSkinvb2(VertexBuffer skinvb2) {
+        this.skinvb2 = skinvb2;
+    }
+    
     BoundingVolume bound = new BoundingBox(Vector3f.ZERO, 20, 20, 20);
 
     @Override
index 81d2312..19b489f 100755 (executable)
@@ -31,7 +31,6 @@ package projectkyoto.jme3.mmd;
 
 import com.jme3.asset.AssetManager;
 import com.jme3.material.Material;
-import com.jme3.material.RenderState.BlendMode;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.queue.RenderQueue.Bucket;
@@ -69,8 +68,7 @@ public class RigidBodyConverter {
 
     public void createRigidBodyGeom(PMDRigidBody rigidBody) {
         Geometry geom = new Geometry(rigidBody.getRigidBodyName());
-        Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
-        mat.setBoolean("UseMaterialColors", true);
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
         Mesh mesh;
         switch (rigidBody.getShapeType()) {
             case 0:
@@ -93,19 +91,19 @@ public class RigidBodyConverter {
         }
         switch (rigidBody.getRigidBodyType()) {
             case 0:
-                mat.setColor("Diffuse", ColorRGBA.Blue);
+                mat.setColor("Color", ColorRGBA.Blue);
                 break;
             case 1:
-                mat.setColor("Diffuse", ColorRGBA.Red);
+                mat.setColor("Color", ColorRGBA.Red);
                 break;
             case 2:
-                mat.setColor("Diffuse", ColorRGBA.Green);
+                mat.setColor("Color", ColorRGBA.Green);
                 break;
         }
         geom.setMesh(mesh);
         geom.setMaterial(mat);
-//        mat.getAdditionalRenderState().setWireframe(true);
-//        mat.getAdditionalRenderState().setDepthTest(false);
+        mat.getAdditionalRenderState().setWireframe(true);
+        mat.getAdditionalRenderState().setDepthTest(false);
 
 //        geom.rotate(rigidBody.getRot().x, rigidBody.getRot().y, rigidBody.getRot().z);
         Vector3f v = new Vector3f(rigidBody.getPos().x, rigidBody.getPos().y, rigidBody.getPos().z);
@@ -122,16 +120,5 @@ public class RigidBodyConverter {
 //            System.out.println(rigidBody.getRigidBodyName()+" "+rigidBody.getRigidBodyGroupIndex()+ " "+ rigidBody.getRigidBodyGroupTarget());
         }
         node.attachChild(geom);
-        System.out.println("rigidBody.getRigidBodyName() = "+rigidBody.getRigidBodyName());
-        if(!rigidBody.getRigidBodyName().contains("スカート")) {
-            ColorRGBA color = new ColorRGBA();
-            color.set(0,0,0,0f);
-            mat.setColor("Diffuse", color);
-            mat.setColor("Ambient", color);
-            mat.setColor("Specular", color);
-            mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
-            mat.getAdditionalRenderState().setAlphaTest(true);
-        }
-
     }
 }
index d1a1e81..61398e1 100755 (executable)
@@ -49,6 +49,8 @@ public class UpdateControl extends AbstractControl {
 
     @Override
     protected void controlUpdate(float tpf) {
+        pmdNode.calcOffsetMatrices();
+        pmdNode.updateSkinBackData();
         pmdNode.update();
     }
 
index f48b269..1407387 100755 (executable)
@@ -60,6 +60,7 @@ import projectkyoto.mmd.file.PMDModel;
  */
 public class IKControl extends AbstractControl{
     PMDNode pmdNode;
+    int boneEnabled[];
 
     public IKControl(PMDNode pmdNode) {
         this.pmdNode = pmdNode;
@@ -99,6 +100,9 @@ public class IKControl extends AbstractControl{
 //        skeleton.updateWorldVectors();
         l1:
         for (PMDIKData ikData : pmdModel.getIkList().getPmdIKData()) {
+            if (boneEnabled != null && boneEnabled[ikData.getIkBoneIndex()] != 1) {
+                continue l1;
+            }
             Bone ikBone = skeleton.getBone(ikData.getIkBoneIndex());
             Bone targetBone = skeleton.getBone(ikData.getIkTargetBoneIndex());
             l2:
@@ -354,5 +358,13 @@ public class IKControl extends AbstractControl{
             updateWorldVectors(childBone);
         }
     }
+
+    public int[] getBoneEnabled() {
+        return boneEnabled;
+    }
+
+    public void setBoneEnabled(int[] boneEnabled) {
+        this.boneEnabled = boneEnabled;
+    }
     
 }
index 5e883ab..dc4a49e 100755 (executable)
@@ -65,7 +65,7 @@ public class PMDPhysicsWorld {
     PhysicsSpace physicsSpace;
     Map<PMDNode, PMDRigidBody[]> rigidBodyMap = new HashMap<PMDNode, PMDRigidBody[]>();
     Map<PMDNode, SixDofJoint[]> constraintMap = new HashMap<PMDNode, SixDofJoint[]>();
-    float accuracy = 1f / 240;
+    float accuracy = 1f / 180;
 
     public PMDPhysicsWorld() {
         float dist = 400f;
@@ -216,7 +216,7 @@ public class PMDPhysicsWorld {
                 throw new PMDException("Invalid getShapeType:" + fileRigidBody.getRigidBodyName() + " "
                         + fileRigidBody.getShapeType());
         }
-        cs.setMargin(0.1f);
+        cs.setMargin(0.08f);
         if (fileRigidBody.getRigidBodyType() != 0) {
             mass = fileRigidBody.getWeight();
             kinematic = false;
@@ -249,10 +249,10 @@ public class PMDPhysicsWorld {
 //        rb.setPhysicsRotation(Quaternion.ZERO);
 //        rb.setPhysicsLocation(Vector3f.ZERO);
         rb.updateFromBoneMatrix();
-//        rb.setMass(mass * 1000f);
+        rb.setMass(mass);
         rb.setDamping(fileRigidBody.getPosDim(), fileRigidBody.getRotDim());
         rb.setRestitution(fileRigidBody.getRecoil());
-//        rb.setFriction(fileRigidBody.getFriction());
+        rb.setFriction(fileRigidBody.getFriction());
 
 //        rb.setWorldTransform(worldTrans);
         if (kinematic) {
@@ -270,12 +270,21 @@ public class PMDPhysicsWorld {
         return rb;
     }
 
-    void _convPMDEuler(Matrix3f out, float x, float y, float z) {
-        Quaternion q = new Quaternion();
-        q.fromAngles(x, y, z);
-        q.toRotationMatrix(out);
-    }
     void convPMDEuler(Matrix3f out, float x, float y, float z) {
+        Quaternion qx = new Quaternion();
+        Quaternion qy = new Quaternion();
+        Quaternion qz = new Quaternion();
+
+        qx.fromAngles(x, 0, 0);
+        qy.fromAngles(0, y, 0);
+        qz.fromAngles(0, 0, z);
+
+        qz.multLocal(qy);
+        qz.multLocal(qx);
+
+        qz.toRotationMatrix(out);
+    }
+    void _convPMDEuler(Matrix3f out, float x, float y, float z) {
 //        Matrix3f m = new Matrix3f();
 //        m.loadIdentity();
 //
@@ -404,36 +413,36 @@ public class PMDPhysicsWorld {
         constraint.setLinearLowerLimit(convVec(pmdJoint.getConstPos1()));
         constraint.setLinearUpperLimit(convVec(pmdJoint.getConstPos2()));
         Vector3f constRot1 = convVec(pmdJoint.getConstRot1());
-        if (constRot1.getX() <= -FastMath.PI / 1.0f) {
-            constRot1.setX(-FastMath.PI * 1f);
-            System.out.println("constRot1 x must > -90");
-        }
+//        if (constRot1.getX() <= -FastMath.PI / 1.0f) {
+//            constRot1.setX(-FastMath.PI * 1f);
+//            System.out.println("constRot1 x must > -90");
+//        }
         if (constRot1.getY() <= -FastMath.PI / 0.5f) {
             constRot1.setY(-FastMath.PI * 0.5f);
             System.out.println("constRot1 y must > -90");
         }
-        if (constRot1.getZ() <= -FastMath.PI / 1.0f) {
-            constRot1.setZ(-FastMath.PI * 1f);
-            System.out.println("constRot1 z must > -90");
-        }
+//        if (constRot1.getZ() <= -FastMath.PI / 1.0f) {
+//            constRot1.setZ(-FastMath.PI * 1f);
+//            System.out.println("constRot1 z must > -90");
+//        }
         constraint.setAngularLowerLimit(constRot1);
 
         Vector3f constRot2 = convVec(pmdJoint.getConstRot2());
-        if (constRot2.getX() >= FastMath.PI / 1.0f) {
-            constRot2.setX(FastMath.PI * 1f);
-            System.out.println("constRot2 x must < 90");
-        }
+//        if (constRot2.getX() >= FastMath.PI / 1.0f) {
+//            constRot2.setX(FastMath.PI * 1f);
+//            System.out.println("constRot2 x must < 90");
+//        }
         if (constRot2.getY() >= FastMath.PI / 0.5f) {
             constRot2.setY(FastMath.PI * 0.5f);
             System.out.println("constRot2 y must < 90");
         }
-        if (constRot2.getZ() >= FastMath.PI / 1.0f) {
-            constRot2.setZ(FastMath.PI * 1f);
-            System.out.println("constRot2 z must < 90");
-        }
+//        if (constRot2.getZ() >= FastMath.PI / 1.0f) {
+//            constRot2.setZ(FastMath.PI * 1f);
+//            System.out.println("constRot2 z must < 90");
+//        }
 
         constraint.setAngularUpperLimit(constRot2);
-//        constraint.setEquilibriumPoint();
+        constraint.setEquilibriumPoint();
 //        constraint.setCollisionBetweenLinkedBodys(false);
         for (int i = 0; i < 6; i++) {
             float f = pmdJoint.getStiffness()[i];
@@ -462,15 +471,15 @@ public class PMDPhysicsWorld {
 //                        t.mul(rb.getTrans());
 //                        rb.setCenterOfMassTransform(t);
                 }
-                Node rigidBodyNode = pmdNode.getRigidBodyNode();
-                if (rigidBodyNode != null) {
-//                        rb.getCenterOfMassTransform(t);
-//                        t.getRotation(rot);
-//                        rot2.set(rot.x, rot.y, rot.z, rot.w);
-                    Spatial spaital = rigidBodyNode.getChild(i);
-                    spaital.setLocalRotation(rb.getPhysicsRotation());
-                    spaital.setLocalTranslation(rb.getPhysicsLocation());
-                }
+//                Node rigidBodyNode = pmdNode.getRigidBodyNode();
+//                if (rigidBodyNode != null) {
+////                        rb.getCenterOfMassTransform(t);
+////                        t.getRotation(rot);
+////                        rot2.set(rot.x, rot.y, rot.z, rot.w);
+//                    Spatial spaital = rigidBodyNode.getChild(i);
+//                    spaital.setLocalRotation(rb.getPhysicsRotation());
+//                    spaital.setLocalTranslation(rb.getPhysicsLocation());
+//                }
             }
         }
     }
@@ -512,22 +521,21 @@ public class PMDPhysicsWorld {
 //                    bone.getModelSpacePosition().set(t.origin.x, t.origin.y, t.origin.z);
 ////                    bone.getModelSpacePosition().set(0f,0f,0f);
                     PMDNode pmdNode = rb.getPmdNode();
-                    Node rigidBodyNode = pmdNode.getRigidBodyNode();
+//                    Node rigidBodyNode = pmdNode.getRigidBodyNode();
                     rb.updateToBoneMatrix();
-                    if (rigidBodyNode != null) {
-//                        rb.getCenterOfMassTransform(t);
-//                        t.getRotation(rot);
-//                        rot2.set(rot.x, rot.y, rot.z, rot.w);
-                        Spatial spaital = rigidBodyNode.getChild(i);
-                        spaital.setLocalRotation(rb.getPhysicsRotation());
-                        spaital.setLocalTranslation(rb.getPhysicsLocation());
-                    }
+//                    if (rigidBodyNode != null) {
+////                        rb.getCenterOfMassTransform(t);
+////                        t.getRotation(rot);
+////                        rot2.set(rot.x, rot.y, rot.z, rot.w);
+//                        Spatial spaital = rigidBodyNode.getChild(i);
+//                        spaital.setLocalRotation(rb.getPhysicsRotation());
+//                        spaital.setLocalTranslation(rb.getPhysicsLocation());
+//                    }
                 } else {
                 }
             }
         }
     }
-
     public void resetRigidBodyPos() {
         for (PMDRigidBody rbarray[] : rigidBodyMap.values()) {
             for (int i = 0; i < rbarray.length; i++) {
@@ -537,6 +545,18 @@ public class PMDPhysicsWorld {
                     Node rigidBodyNode = pmdNode.getRigidBodyNode();
                     rb.updateFromBoneMatrix();
                     rb.setLinearVelocity(Vector3f.ZERO);
+                    rb.setAngularVelocity(Vector3f.ZERO);
+                }
+            }
+        }
+    }
+    public void updateRigidBodyPos() {
+        for (PMDRigidBody rbarray[] : rigidBodyMap.values()) {
+            for (int i = 0; i < rbarray.length; i++) {
+                PMDRigidBody rb = rbarray[i];
+                if (true) {
+                    PMDNode pmdNode = rb.getPmdNode();
+                    Node rigidBodyNode = pmdNode.getRigidBodyNode();
                     if (rigidBodyNode != null) {
                         Spatial spaital = rigidBodyNode.getChild(i);
                         spaital.setLocalRotation(rb.getPhysicsRotation());
diff --git a/src/projectkyoto/jme3/mmd/vmd/VMDCallable.java b/src/projectkyoto/jme3/mmd/vmd/VMDCallable.java
new file mode 100644 (file)
index 0000000..0243599
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package projectkyoto.jme3.mmd.vmd;
+
+import java.util.concurrent.Callable;
+import projectkyoto.jme3.mmd.PMDNode;
+import projectkyoto.jme3.mmd.vmd.VMDControl;
+import projectkyoto.mmd.file.VMDFile;
+
+/**
+ *
+ * @author kobayasi
+ */
+public class VMDCallable implements Callable<Void> {
+    final PMDNode pmdNode;
+    final VMDControl vmdControl;
+    float tpf;
+    public VMDCallable(PMDNode pmdNode, VMDFile vmdFile) {
+        this.pmdNode = pmdNode;
+        vmdControl = new VMDControl(pmdNode, vmdFile);
+    }
+    
+    public Void call() throws Exception {
+        vmdControl.update(tpf);
+//        pmdNode.getSkeleton().updateWorldVectors();
+        pmdNode.calcOffsetMatrices();
+//        pmdNode.setSkinWeight("笑い", 1f);
+        pmdNode.updateSkinBackData();
+        return null;
+    }
+
+    public float getTpf() {
+        return tpf;
+    }
+
+    public void setTpf(float tpf) {
+        this.tpf = tpf;
+    }
+
+    public PMDNode getPmdNode() {
+        return pmdNode;
+    }
+
+    public VMDControl getVmdControl() {
+        return vmdControl;
+    }
+
+    
+}
index 5a5d2ad..60e9cb7 100755 (executable)
@@ -52,6 +52,7 @@ import projectkyoto.jme3.mmd.PMDNode;
 import projectkyoto.jme3.mmd.ik.IKControl;
 import projectkyoto.jme3.mmd.nativebullet.PhysicsControl;
 import projectkyoto.mmd.file.PMDBone;
+import projectkyoto.mmd.file.PMDIKData;
 import projectkyoto.mmd.file.VMDFile;
 import projectkyoto.mmd.file.VMDMotion;
 import projectkyoto.mmd.file.VMDSkin;
@@ -73,6 +74,7 @@ public class VMDControl extends AbstractControl {
     static final VMDMotionComparator vmc = new VMDMotionComparator();
     static final VMDSkinComparator vmsc = new VMDSkinComparator();
     final PhysicsControl physicsControl;
+    int boneEnabled[];
     final IKControl ikControl;
     TickListener tl = new TickListener();
 
@@ -83,6 +85,20 @@ public class VMDControl extends AbstractControl {
         physicsControl = new PhysicsControl(pmdNode);
         physicsControl.getWorld().getPhysicsSpace().addTickListener(tl);
         ikControl = new IKControl(pmdNode);
+        boneEnabled = new int[pmdNode.getSkeleton().getBoneCount()];
+        for(int i=0;i<boneEnabled.length;i++) {
+            boneEnabled[i] = 1;
+        }
+        for (PMDIKData ikData : pmdNode.getPmdModel().getIkList().getPmdIKData()) {
+            int targetBoneIndex = ikData.getIkTargetBoneIndex();
+            for(projectkyoto.mmd.file.PMDRigidBody rb : pmdNode.getPmdModel().getRigidBodyList().getRigidBodyArray()) {
+                if (rb.getRelBoneIndex() == targetBoneIndex && rb.getRigidBodyType() != 0) {
+                    boneEnabled[targetBoneIndex] = 0;
+                    break;
+                }
+            }
+        }
+        ikControl.setBoneEnabled(boneEnabled);
     }
 
     private void initMotionMap() {
@@ -91,6 +107,12 @@ public class VMDControl extends AbstractControl {
             if (motionList == null) {
                 motionList = new BoneMotionList();
                 motionList.boneName = m.getBoneName();
+                for(int i=0;i<pmdNode.getSkeleton().getBoneCount();i++) {
+                    if (pmdNode.getSkeleton().getBone(i).getName().equals(m.getBoneName())) {
+                        motionList.boneIndex = i;
+                        break;
+                    }
+                }
                 motionMap.put(m.getBoneName(), motionList);
             }
             motionList.add(m);
@@ -184,13 +206,15 @@ public class VMDControl extends AbstractControl {
 
     void calcBonePosition(int frameNo, Skeleton skeleton) {
         for(int i=0;i<pmdNode.getSkeleton().getBoneCount();i++) {
-            Bone bone = pmdNode.getSkeleton().getBone(i);
-            bone.getLocalRotation().loadIdentity();
+            if (boneEnabled[i] == 1) {
+                Bone bone = pmdNode.getSkeleton().getBone(i);
+                bone.getLocalRotation().loadIdentity();
+            }
         }
         boneLoop:
         for (BoneMotionList bml : motionMap.values()) {
             Bone bone = pmdNode.getSkeleton().getBone(bml.boneName);
-            if (bone != null) {
+            if (bone != null && boneEnabled[bml.boneIndex] == 1) {
                 bone.setUserControl(true);
                 if (bml.size() - 1 < bml.currentCount) {
                     VMDMotion m1 = bml.get(bml.size() - 1);
@@ -259,7 +283,7 @@ public class VMDControl extends AbstractControl {
         ikControl.updateIKBoneRotation();
         for(int i=0;i<pmdNode.getPmdModel().getBoneList().getBoneCount();i++) {
             PMDBone pmdBone = pmdNode.getPmdModel().getBoneList().getBones()[i];
-            if (pmdBone.getBoneType() == 5) {
+            if (pmdBone.getBoneType() == 5 && boneEnabled[i] == 1) {
                 // under-rotation
                 Bone bone = pmdNode.getSkeleton().getBone(i);
 //                if (motionMap.get(pmdBone.getBoneName()) == null) {
@@ -387,6 +411,7 @@ class BoneMotionList extends ArrayList<VMDMotion> {
 
     static final int IPTABLESIZE = 64;
     String boneName;
+    int boneIndex;
     int currentCount;
     int boneType;
     final float ipTable[][][] = new float[4][IPTABLESIZE][2];
diff --git a/src/projectkyoto/jme3/mmd/vmd/VMDControlMT.java b/src/projectkyoto/jme3/mmd/vmd/VMDControlMT.java
new file mode 100644 (file)
index 0000000..871bd1e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package projectkyoto.jme3.mmd.vmd;
+
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.ViewPort;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.control.AbstractControl;
+import com.jme3.scene.control.Control;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import projectkyoto.jme3.mmd.PMDNode;
+import projectkyoto.jme3.mmd.vmd.VMDControl;
+import projectkyoto.mmd.file.PMDModel;
+import projectkyoto.mmd.file.VMDFile;
+
+/**
+ *
+ * @author kobayasi
+ */
+public class VMDControlMT extends AbstractControl {
+
+    final ScheduledThreadPoolExecutor executor;
+    final VMDCallable callable;
+    final PMDNode pmdNode;
+    Future<Void> future;
+
+    public VMDControlMT(ScheduledThreadPoolExecutor executor, PMDNode pmdNode, VMDFile vmdFile) {
+        this.executor = executor;
+        callable = new VMDCallable(pmdNode, vmdFile);
+        this.pmdNode = pmdNode;
+    }
+
+    @Override
+    protected void controlUpdate(float f) {
+        if (future != null) {
+            try {
+                future.get();
+                callable.vmdControl.getPhysicsControl().getWorld().updateRigidBodyPos();
+                pmdNode.update();
+            } catch (InterruptedException ex) {
+                Logger.getLogger(VMDControlMT.class.getName()).log(Level.SEVERE, null, ex);
+            } catch (ExecutionException ex) {
+                Logger.getLogger(VMDControlMT.class.getName()).log(Level.SEVERE, null, ex);
+            } finally {
+                future = null;
+            }
+        }
+        callable.setTpf(f);
+        future = executor.submit(callable);
+    }
+
+    public VMDCallable getCallable() {
+        return callable;
+    }
+
+    @Override
+    protected void controlRender(RenderManager rm, ViewPort vp) {
+    }
+
+    public Control cloneForSpatial(Spatial sptl) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+}