OSDN Git Service

support sphere map
authorKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Mon, 1 Aug 2011 21:31:47 +0000 (06:31 +0900)
committerKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Mon, 1 Aug 2011 21:31:47 +0000 (06:31 +0900)
support alpha bending
VMD:interporation bug fix

24 files changed:
src/MatDefs/pmd/pmd.frag
src/MatDefs/pmd/pmd.j3md
src/MatDefs/pmd/pmd.vert
src/MatDefs/pmd/pmd_alpha.j3md [new file with mode: 0755]
src/MatDefs/pmd/pmd_cartoon.frag
src/MatDefs/pmd/pmd_cartoon.vert
src/MatDefs/pmd/pmd_no_skinning.j3md
src/MatDefs/pmd/pmd_no_skinning.vert [new file with mode: 0755]
src/MatDefs/pmd/pmd_no_skinning_alpha.j3md [new file with mode: 0755]
src/projectkyoto/jme3/mmd/PMDLoaderGLSLSkinning2.java
src/projectkyoto/jme3/mmd/PMDNode.java
src/projectkyoto/jme3/mmd/RigidBodyConverter.java
src/projectkyoto/jme3/mmd/ik/IKControl.java
src/projectkyoto/jme3/mmd/nativebullet/PMDPhysicsWorld.java
src/projectkyoto/jme3/mmd/nativebullet/PMDRigidBody.java
src/projectkyoto/jme3/mmd/nativebullet/PhysicsControl.java
src/projectkyoto/jme3/mmd/vmd/IPUtil.java
src/projectkyoto/jme3/mmd/vmd/VMDControl.java
src/projectkyoto/mmd/file/PMDBone.java
src/projectkyoto/mmd/file/PMDMaterial.java
src/projectkyoto/mmd/file/PMDVertex.java
src/projectkyoto/mmd/file/util2/MeshConverter.java
src/projectkyoto/mmd/file/util2/MeshData.java
src/projectkyoto/mmd/file/util2/SkinMeshData.java

index 9a10235..c8fa002 100755 (executable)
@@ -1,10 +1,10 @@
 #import "Common/ShaderLib/Optics.glsllib"\r
 \r
 #ifdef SPHERE_MAP_A\r
-  uniform sampler2D m_SphereMap_a;\r
+  uniform sampler2D m_SphereMap_A;\r
 #endif\r
 #ifdef SPHERE_MAP_H\r
-  uniform sampler2D m_SphereMap_h;\r
+  uniform sampler2D m_SphereMap_H;\r
 #endif\r
 \r
 \r
@@ -61,10 +61,11 @@ varying vec3 lightVec;
 #ifdef USE_REFLECTION \r
     uniform float m_ReflectionPower;\r
     uniform float m_ReflectionIntensity;\r
-    varying vec4 refVec;\r
+//    varying vec4 refVec;\r
 \r
     uniform ENVMAP m_EnvMap;\r
 #endif\r
+    varying vec4 refVec;\r
 \r
 float tangDot(in vec3 v1, in vec3 v2){\r
     float d = dot(v1,v2);\r
@@ -148,6 +149,7 @@ void main(){
       vec4 diffuseColor = vec4(1.0);\r
     #endif\r
     float alpha = DiffuseSum.a * diffuseColor.a;\r
+    //float alpha = (DiffuseSum.a + diffuseColor.a)/2;\r
     #ifdef ALPHAMAP\r
        alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;\r
     #endif\r
@@ -219,19 +221,29 @@ void main(){
             SpecularSum2 = vec4(1.0);\r
             light.y = 1.0;\r
        #endif\r
-\r
+       if (isnan(light.y)) {\r
+            light.y = 0;\r
+       }\r
 //       gl_FragColor =  (AmbientSum * diffuseColor +\r
 //                       DiffuseSum * diffuseColor + //* light.x +\r
 //                       SpecularSum2 * specularColor * light.y ) * 0.8;\r
-       gl_FragColor =  (((AmbientSum + DiffuseSum) * diffuseColor)  +\r
-                       SpecularSum2 * specularColor * light.y * 0.8)  ;\r
+       vec4 output_color = (((AmbientSum + DiffuseSum) * diffuseColor)  +\r
+                       SpecularSum2 * specularColor * light.y );\r
 #ifdef SPHERE_MAP_A\r
-        gl_FragColor += texture2D(m_SphereMap_a, Optics_SphereCoord(reflect(normView, normal));\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
 #endif\r
 #ifdef SPHERE_MAP_H\r
-        gl_FragColor *= texture2D(m_SphereMap_h, Optics_SphereCoord(reflect(normView, normal));\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
 #endif\r
 \r
     #endif\r
-    gl_FragColor.a = alpha;\r
+    output_color.a = alpha;\r
+    // output_color.a = diffuseColor.a;\r
+\r
+    // gl_FragColor = 0.5 + 0.5 * light.x;//output_color;\r
+    gl_FragColor = output_color;\r
 }\r
index 714580e..0bd9667 100755 (executable)
@@ -139,11 +139,11 @@ MaterialDef pmd {
 \r
             // NUM_BONES : NumBones\r
             USE_HWSKINNING\r
-            SPHERE_MAP_A : SphereMap_a\r
-            SPHERE_MAP_H : SphereMap_h\r
+            SPHERE_MAP_A : SphereMap_A\r
+            SPHERE_MAP_H : SphereMap_H\r
         }\r
         RenderState {\r
-            FaceCull Off\r
+            FaceCull Back\r
         }\r
     }\r
 \r
index 6638425..af6adf2 100755 (executable)
@@ -1,5 +1,7 @@
 // #import "MatDefs/pmd/Skinning.glsllib"\r
+#ifdef USE_HWSKINNING\r
 uniform mat4 m_BoneMatrices[20];\r
+#endif\r
 #define ATTENUATION\r
 // #define HQ_ATTENUATION\r
 \r
@@ -49,7 +51,7 @@ attribute vec3 inNormal;
   varying vec4 vLightDir;\r
 #endif\r
 \r
-#ifdef USE_REFLECTION\r
+// #ifdef USE_REFLECTION\r
     uniform vec3 g_CameraPosition;\r
     uniform mat4 g_WorldMatrix;\r
 \r
@@ -74,9 +76,9 @@ attribute vec3 inNormal;
         vec3 N = normalize( (g_WorldMatrix * vec4(normal.xyz, 0.0)).xyz );\r
 \r
         refVec.xyz = reflect(I, N);\r
-        refVec.w   = m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);\r
+        refVec.w   = 1;//m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);\r
     }\r
-#endif\r
+// #endif\r
 \r
 // JME3 lights in world space\r
 void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){\r
@@ -121,7 +123,7 @@ vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 w
 attribute vec4 inBoneWeight;\r
 attribute vec4 inBoneIndices;\r
 attribute vec4 inBoneIndex;\r
-\r
+#ifdef USE_HWSKINNING\r
 void Skinning_Compute(inout vec4 position, inout vec4 normal){\r
 //    vec4 index  = inBoneIndices;\r
     vec4 index  = inBoneIndex;\r
@@ -141,11 +143,13 @@ void Skinning_Compute(inout vec4 position, inout vec4 normal){
     position = newPos;\r
     normal = newNormal;\r
 }\r
-\r
+#endif\r
 void main(){\r
    vec4 pos = vec4(inPosition, 1.0);\r
    vec4 normal = vec4(inNormal,0.0);\r
+#ifdef USE_HWSKINNING\r
    Skinning_Compute(pos, normal);\r
+#endif\r
 //    pos = m_BoneMatrices[0] * pos;\r
    gl_Position = g_WorldViewProjectionMatrix * pos;\r
    texCoord = inTexCoord;\r
@@ -214,7 +218,7 @@ void main(){
        SpecularSum.a = light.y;\r
     #endif\r
 \r
-    #ifdef USE_REFLECTION\r
+    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_A)\r
         computeRef(pos,normal);\r
     #endif \r
 }\r
diff --git a/src/MatDefs/pmd/pmd_alpha.j3md b/src/MatDefs/pmd/pmd_alpha.j3md
new file mode 100755 (executable)
index 0000000..8fc5ed3
--- /dev/null
@@ -0,0 +1,243 @@
+MaterialDef pmd {\r
+\r
+    MaterialParameters {\r
+\r
+        // Compute vertex lighting in the shader\r
+        // For better performance\r
+        Boolean VertexLighting\r
+\r
+        // Use more efficent algorithms to improve performance\r
+        Boolean LowQuality\r
+\r
+        // Improve quality at the cost of performance\r
+        Boolean HighQuality\r
+\r
+        // Output alpha from the diffuse map\r
+        Boolean UseAlpha\r
+\r
+        // Apha threshold for fragment discarding\r
+        Float AlphaDiscardThreshold\r
+\r
+        // Normal map is in BC5/ATI2n/LATC/3Dc compression format\r
+        Boolean LATC\r
+\r
+        // Use the provided ambient, diffuse, and specular colors\r
+        Boolean UseMaterialColors\r
+\r
+        // Activate shading along the tangent, instead of the normal\r
+        // Requires tangent data to be available on the model.\r
+        Boolean VTangent\r
+\r
+        // Use minnaert diffuse instead of lambert\r
+        Boolean Minnaert\r
+\r
+        // Use ward specular instead of phong\r
+        Boolean WardIso\r
+\r
+        // Use vertex color as an additional diffuse color.\r
+        Boolean UseVertexColor\r
+\r
+        // Ambient color\r
+        Color Ambient\r
+\r
+        // Diffuse color\r
+        Color Diffuse : Color\r
+\r
+        // Specular color\r
+        Color Specular\r
+\r
+        // Specular power/shininess\r
+        Float Shininess\r
+\r
+        // Diffuse map\r
+        Texture2D DiffuseMap\r
+\r
+        // Normal map\r
+        Texture2D NormalMap\r
+\r
+        // Specular/gloss map\r
+        Texture2D SpecularMap\r
+\r
+        // Parallax/height map\r
+        Texture2D ParallaxMap\r
+\r
+        // Texture that specifies alpha values\r
+        Texture2D AlphaMap\r
+\r
+        // Color ramp, will map diffuse and specular values through it.\r
+        Texture2D ColorRamp\r
+\r
+        // Texture of the glowing parts of the material\r
+        Texture2D GlowMap\r
+\r
+        // The glow color of the object\r
+        Color GlowColor\r
+\r
+        // Parameters for fresnel\r
+        // X = bias\r
+        // Y = scale\r
+        // Z = power\r
+        Vector3 FresnelParams\r
+\r
+        // Env Map for reflection\r
+        TextureCubeMap EnvMap\r
+\r
+        // the env map is a spheremap and not a cube map\r
+        Boolean EnvMapAsSphereMap\r
+\r
+        Matrix4Array BoneMatrices\r
+        Int NumBones\r
+        Texture2D BoneParameter\r
+\r
+        Float EdgeSize\r
+        Texture2D SphereMap_A\r
+        Texture2D SphereMap_H\r
+    }\r
+\r
+    Technique {\r
+\r
+        LightMode MultiPass\r
+\r
+        VertexShader GLSL100:   MatDefs/pmd/pmd.vert\r
+        FragmentShader GLSL100: MatDefs/pmd/pmd.frag\r
+        // VertexShader GLSL120:   MatDefs/pmd/pmd_cartoon.vert\r
+        // FragmentShader GLSL120: MatDefs/pmd/pmd_cartoon.frag\r
+\r
+        // VertexShader GLSL100:   Common/MatDefs/Light/Lighting.vert\r
+        // FragmentShader GLSL100: Common/MatDefs/Light/Lighting.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            NormalMatrix\r
+            WorldViewMatrix\r
+            ViewMatrix\r
+            CameraPosition\r
+            WorldMatrix\r
+        }\r
+\r
+        Defines {\r
+            LATC : LATC\r
+            VERTEX_COLOR : UseVertexColor\r
+            VERTEX_LIGHTING : VertexLighting\r
+            ATTENUATION : Attenuation\r
+            MATERIAL_COLORS : UseMaterialColors\r
+            V_TANGENT : VTangent\r
+            MINNAERT  : Minnaert\r
+            WARDISO   : WardIso\r
+            LOW_QUALITY : LowQuality\r
+            HQ_ATTENUATION : HighQuality\r
+\r
+            DIFFUSEMAP : DiffuseMap\r
+            NORMALMAP : NormalMap\r
+            SPECULARMAP : SpecularMap\r
+            PARALLAXMAP : ParallaxMap\r
+            ALPHAMAP : AlphaMap\r
+            COLORRAMP : ColorRamp\r
+\r
+            USE_REFLECTION : EnvMap\r
+            SPHERE_MAP : SphereMap\r
+\r
+            // NUM_BONES : NumBones\r
+            USE_HWSKINNING\r
+            SPHERE_MAP_A : SphereMap_A\r
+            SPHERE_MAP_H : SphereMap_H\r
+        }\r
+        RenderState {\r
+            FaceCull Off\r
+        }\r
+    }\r
+\r
+\r
+    Technique PreShadow {\r
+\r
+        // VertexShader GLSL100 :   Common/MatDefs/Shadow/PreShadow.vert\r
+        FragmentShader GLSL100 : Common/MatDefs/Shadow/PreShadow.frag\r
+        VertexShader GLSL100:   MatDefs/pmd/pmd.vert\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            WorldViewMatrix\r
+        }\r
+\r
+        Defines {\r
+            DIFFUSEMAP_ALPHA : DiffuseMap\r
+            USE_HWSKINNING\r
+        }\r
+\r
+        RenderState {\r
+            FaceCull Off\r
+            DepthTest On\r
+            DepthWrite On\r
+            PolyOffset 5 0\r
+            ColorWrite Off\r
+        }\r
+\r
+    }\r
+\r
+  Technique PreNormalPass {\r
+\r
+        VertexShader GLSL100 :   Common/MatDefs/SSAO/normal.vert\r
+        FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            WorldViewMatrix\r
+            NormalMatrix\r
+        }\r
+\r
+        Defines {\r
+            DIFFUSEMAP_ALPHA : DiffuseMap\r
+        }\r
+\r
+        RenderState {\r
+\r
+        }\r
+\r
+    }\r
+\r
+    Technique GBuf {\r
+\r
+        VertexShader GLSL100:   Common/MatDefs/Light/GBuf.vert\r
+        FragmentShader GLSL100: Common/MatDefs/Light/GBuf.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            NormalMatrix\r
+            WorldViewMatrix\r
+            WorldMatrix\r
+        }\r
+\r
+        Defines {\r
+            VERTEX_COLOR : UseVertexColor\r
+            MATERIAL_COLORS : UseMaterialColors\r
+            V_TANGENT : VTangent\r
+            MINNAERT  : Minnaert\r
+            WARDISO   : WardIso\r
+\r
+            DIFFUSEMAP : DiffuseMap\r
+            NORMALMAP : NormalMap\r
+            SPECULARMAP : SpecularMap\r
+            PARALLAXMAP : ParallaxMap\r
+        }\r
+    }\r
+\r
+    Technique FixedFunc {\r
+        LightMode FixedPipeline\r
+    }\r
+\r
+    Technique Glow {\r
+\r
+        VertexShader GLSL100:   Common/MatDefs/Misc/SimpleTextured.vert\r
+        FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+        }\r
+\r
+        Defines {\r
+            HAS_GLOWMAP : GlowMap\r
+            HAS_GLOWCOLOR : GlowColor\r
+        }\r
+    }\r
+\r
+}
\ No newline at end of file
index e298f7b..9974f21 100755 (executable)
@@ -1,3 +1,3 @@
 void main(){\r
-    gl_FragColor = vec4(0.0);\r
+    gl_FragColor = vec4(0,0,0,1);\r
 }\r
index 36c51a1..5df1ca8 100755 (executable)
@@ -44,6 +44,7 @@ void Skinning_Compute(inout vec4 position, inout vec4 normal){
 #endif\r
 \r
 void main(){\r
+    if (m_EdgeSize != 0.0) {\r
    vec4 pos = vec4(inPosition, 1.0);\r
    vec4 normal = vec4(inNormal,0.0);\r
 #ifdef USE_HWSKINNING\r
@@ -52,4 +53,7 @@ void main(){
    normal = normalize(normal);\r
    pos = pos + normal * m_EdgeSize;\r
    gl_Position = g_WorldViewProjectionMatrix * pos;\r
+   } else {\r
+     gl_Position = vec4(1000.0,1000.0,1000.0,1000.0);\r
+   }\r
 }\r
index c4af7de..2315f1d 100755 (executable)
@@ -90,13 +90,15 @@ MaterialDef pmd {
         Texture2D BoneParameter\r
 \r
         Float EdgeSize\r
+        Texture2D SphereMap_A\r
+        Texture2D SphereMap_H\r
     }\r
 \r
     Technique {\r
 \r
         LightMode MultiPass\r
 \r
-        VertexShader GLSL100:   Common/MatDefs/Light/Lighting.vert\r
+        VertexShader GLSL100:   MatDefs/pmd/pmd.vert\r
         FragmentShader GLSL100: MatDefs/pmd/pmd.frag\r
 \r
         // VertexShader GLSL100:   Common/MatDefs/Light/Lighting.vert\r
@@ -134,7 +136,13 @@ MaterialDef pmd {
             SPHERE_MAP : SphereMap\r
 \r
             // NUM_BONES : NumBones\r
-            USE_HWSKINNING\r
+            // USE_HWSKINNING\r
+\r
+            SPHERE_MAP_A : SphereMap_A\r
+            SPHERE_MAP_H : SphereMap_H\r
+        }\r
+        RenderState {\r
+            FaceCull Back\r
         }\r
     }\r
 \r
diff --git a/src/MatDefs/pmd/pmd_no_skinning.vert b/src/MatDefs/pmd/pmd_no_skinning.vert
new file mode 100755 (executable)
index 0000000..5d21e19
--- /dev/null
@@ -0,0 +1,220 @@
+// #import "MatDefs/pmd/Skinning.glsllib"\r
+uniform mat4 m_BoneMatrices[20];\r
+#define ATTENUATION\r
+// #define HQ_ATTENUATION\r
+\r
+uniform mat4 g_WorldViewProjectionMatrix;\r
+uniform mat4 g_WorldViewMatrix;\r
+uniform mat3 g_NormalMatrix;\r
+uniform mat4 g_ViewMatrix;\r
+\r
+uniform vec4 m_Ambient;\r
+uniform vec4 m_Diffuse;\r
+uniform vec4 m_Specular;\r
+uniform float m_Shininess;\r
+\r
+uniform vec4 g_LightColor;\r
+uniform vec4 g_LightPosition;\r
+uniform vec4 g_AmbientLightColor;\r
+\r
+varying vec2 texCoord;\r
+\r
+varying vec4 AmbientSum;\r
+varying vec4 DiffuseSum;\r
+varying vec4 SpecularSum;\r
+\r
+attribute vec3 inPosition;\r
+attribute vec2 inTexCoord;\r
+attribute vec3 inNormal;\r
+\r
+// uniform Sampler2D m_BoneParameter;\r
+// uniform sampler2D m_BoneParameter;\r
+\r
+#ifdef HQ_ATTENUATION\r
+  varying vec3 lightVec;\r
+#endif\r
+\r
+#ifdef VERTEX_COLOR\r
+  attribute vec4 inColor;\r
+#endif\r
+\r
+#ifndef VERTEX_LIGHTING\r
+  attribute vec4 inTangent;\r
+\r
+  #ifndef NORMALMAP\r
+    varying vec3 vNormal;\r
+  #endif\r
+  varying vec3 vPosition;\r
+  varying vec3 vViewDir;\r
+  varying vec4 vLightDir;\r
+#endif\r
+\r
+// #ifdef USE_REFLECTION\r
+    uniform vec3 g_CameraPosition;\r
+    uniform mat4 g_WorldMatrix;\r
+\r
+    uniform vec3 m_FresnelParams;\r
+    varying vec4 refVec;\r
+\r
+\r
+    /**\r
+     * Input:\r
+     * attribute inPosition\r
+     * attribute inNormal\r
+     * uniform g_WorldMatrix\r
+     * uniform g_CameraPosition\r
+     *\r
+     * Output:\r
+     * varying refVec\r
+     */\r
+    void computeRef(in vec4 position, in vec4 normal){\r
+        vec3 worldPos = (g_WorldMatrix * vec4(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
+\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
+    }\r
+// #endif\r
+\r
+// JME3 lights in world space\r
+void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){\r
+    float posLight = step(0.5, color.w);\r
+    vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);\r
+    #ifdef ATTENUATION\r
+     float dist = length(tempVec);\r
+     lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);\r
+     lightDir.xyz = tempVec / vec3(dist);\r
+     #ifdef HQ_ATTENUATION\r
+       lightVec = tempVec;\r
+     #endif\r
+    #else\r
+     lightDir = vec4(normalize(tempVec), 1.0);\r
+    #endif\r
+}\r
+\r
+#ifdef VERTEX_LIGHTING\r
+  float lightComputeDiffuse(in vec3 norm, in vec3 lightdir){\r
+      return max(0.0, dot(norm, lightdir));\r
+  }\r
+\r
+  float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){\r
+      #ifndef LOW_QUALITY\r
+        vec3 H = (viewdir + lightdir) * vec3(0.5);\r
+        return pow(max(dot(H, norm), 0.0), shiny);\r
+      #else\r
+        return 0.0;\r
+      #endif\r
+  }\r
+\r
+vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightPos){\r
+     vec4 lightDir;\r
+     lightComputeDir(wvPos, g_LightColor, wvLightPos, lightDir);\r
+\r
+     float diffuseFactor = lightComputeDiffuse(wvNorm, lightDir.xyz);\r
+     float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, lightDir.xyz, m_Shininess);\r
+     //specularFactor *= step(0.01, diffuseFactor);\r
+     return vec2(diffuseFactor, specularFactor) * vec2(lightDir.w);\r
+  }\r
+#endif\r
+attribute vec4 inBoneWeight;\r
+attribute vec4 inBoneIndices;\r
+attribute vec4 inBoneIndex;\r
+\r
+void Skinning_Compute(inout vec4 position, inout vec4 normal){\r
+//    vec4 index  = inBoneIndices;\r
+    vec4 index  = inBoneIndex;\r
+    vec4 weight = inBoneWeight;\r
+\r
+    vec4 newPos    = vec4(0.0);\r
+    vec4 newNormal = vec4(0.0);\r
+\r
+    for (float i = 0.0; i < 2.0; i += 1.0){\r
+        mat4 skinMat = m_BoneMatrices[int(index.x)];\r
+        newPos    += weight.x * (skinMat * position);\r
+        newNormal += weight.x * (skinMat * normal);\r
+        index = index.yzwx;\r
+        weight = weight.yzwx;\r
+    }\r
+\r
+    position = newPos;\r
+    normal = newNormal;\r
+}\r
+\r
+void main(){\r
+   vec4 pos = vec4(inPosition, 1.0);\r
+   vec4 normal = vec4(inNormal,0.0);\r
+//   Skinning_Compute(pos, normal);\r
+//    pos = m_BoneMatrices[0] * pos;\r
+   gl_Position = g_WorldViewProjectionMatrix * pos;\r
+   texCoord = inTexCoord;\r
+\r
+   vec3 wvPosition = (g_WorldViewMatrix * pos).xyz;\r
+   vec3 wvNormal  = normalize(g_NormalMatrix * normal.xyz);\r
+\r
+//   vec3 wvPosition = (g_WorldViewMatrix * pos).xyz;\r
+//   vec3 wvNormal  = normalize(g_NormalMatrix * inNormal);\r
+\r
+   vec3 viewDir = normalize(-wvPosition);\r
+\r
+       //vec4 lightColor = g_LightColor[gl_InstanceID];\r
+       //vec4 lightPos   = g_LightPosition[gl_InstanceID];\r
+       //vec4 wvLightPos = (g_ViewMatrix * vec4(lightPos.xyz, lightColor.w));\r
+       //wvLightPos.w = lightPos.w;\r
+\r
+   vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz, g_LightColor.w));\r
+   wvLightPos.w = g_LightPosition.w;\r
+   vec4 lightColor = g_LightColor;\r
+\r
+   #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)\r
+     vec3 wvTangent = normalize(g_NormalMatrix * inTangent.xyz);\r
+     vec3 wvBinormal = cross(wvNormal, wvTangent);\r
+\r
+     mat3 tbnMat = mat3(wvTangent, wvBinormal * -inTangent.w,wvNormal);\r
+     \r
+     vPosition = wvPosition * tbnMat;\r
+     vViewDir  = viewDir * tbnMat;\r
+     lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);\r
+     vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;\r
+   #elif !defined(VERTEX_LIGHTING)\r
+     vNormal = wvNormal;\r
+\r
+     vPosition = wvPosition;\r
+     vViewDir = viewDir;\r
+\r
+     lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);\r
+\r
+     #ifdef V_TANGENT\r
+        vNormal = normalize(g_NormalMatrix * inTangent.xyz);\r
+        vNormal = -cross(cross(vLightDir.xyz, vNormal), vNormal);\r
+     #endif\r
+   #endif\r
+\r
+   lightColor.w = 1.0;\r
+   #ifdef MATERIAL_COLORS\r
+      AmbientSum  = m_Ambient  * g_AmbientLightColor;\r
+      DiffuseSum  = m_Diffuse  * lightColor;\r
+      SpecularSum = m_Specular * lightColor;\r
+    #else\r
+      AmbientSum  = vec4(0.2, 0.2, 0.2, 1.0) * g_AmbientLightColor; // Default: ambient color is dark gray\r
+      DiffuseSum  = lightColor;\r
+      SpecularSum = lightColor;\r
+    #endif\r
+\r
+    #ifdef VERTEX_COLOR\r
+      AmbientSum *= inColor;\r
+      DiffuseSum *= inColor;\r
+    #endif\r
+\r
+    #ifdef VERTEX_LIGHTING\r
+       vec2 light = computeLighting(wvPosition, wvNormal, viewDir, wvLightPos);\r
+\r
+       AmbientSum.a  = light.x;\r
+       SpecularSum.a = light.y;\r
+    #endif\r
+\r
+    #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_A)\r
+        computeRef(pos,normal);\r
+    #endif \r
+}\r
diff --git a/src/MatDefs/pmd/pmd_no_skinning_alpha.j3md b/src/MatDefs/pmd/pmd_no_skinning_alpha.j3md
new file mode 100755 (executable)
index 0000000..2cff028
--- /dev/null
@@ -0,0 +1,240 @@
+MaterialDef pmd {\r
+\r
+    MaterialParameters {\r
+\r
+        // Compute vertex lighting in the shader\r
+        // For better performance\r
+        Boolean VertexLighting\r
+\r
+        // Use more efficent algorithms to improve performance\r
+        Boolean LowQuality\r
+\r
+        // Improve quality at the cost of performance\r
+        Boolean HighQuality\r
+\r
+        // Output alpha from the diffuse map\r
+        Boolean UseAlpha\r
+\r
+        // Apha threshold for fragment discarding\r
+        Float AlphaDiscardThreshold\r
+\r
+        // Normal map is in BC5/ATI2n/LATC/3Dc compression format\r
+        Boolean LATC\r
+\r
+        // Use the provided ambient, diffuse, and specular colors\r
+        Boolean UseMaterialColors\r
+\r
+        // Activate shading along the tangent, instead of the normal\r
+        // Requires tangent data to be available on the model.\r
+        Boolean VTangent\r
+\r
+        // Use minnaert diffuse instead of lambert\r
+        Boolean Minnaert\r
+\r
+        // Use ward specular instead of phong\r
+        Boolean WardIso\r
+\r
+        // Use vertex color as an additional diffuse color.\r
+        Boolean UseVertexColor\r
+\r
+        // Ambient color\r
+        Color Ambient\r
+\r
+        // Diffuse color\r
+        Color Diffuse : Color\r
+\r
+        // Specular color\r
+        Color Specular\r
+\r
+        // Specular power/shininess\r
+        Float Shininess\r
+\r
+        // Diffuse map\r
+        Texture2D DiffuseMap\r
+\r
+        // Normal map\r
+        Texture2D NormalMap\r
+\r
+        // Specular/gloss map\r
+        Texture2D SpecularMap\r
+\r
+        // Parallax/height map\r
+        Texture2D ParallaxMap\r
+\r
+        // Texture that specifies alpha values\r
+        Texture2D AlphaMap\r
+\r
+        // Color ramp, will map diffuse and specular values through it.\r
+        Texture2D ColorRamp\r
+\r
+        // Texture of the glowing parts of the material\r
+        Texture2D GlowMap\r
+\r
+        // The glow color of the object\r
+        Color GlowColor\r
+\r
+        // Parameters for fresnel\r
+        // X = bias\r
+        // Y = scale\r
+        // Z = power\r
+        Vector3 FresnelParams\r
+\r
+        // Env Map for reflection\r
+        TextureCubeMap EnvMap\r
+\r
+        // the env map is a spheremap and not a cube map\r
+        Boolean EnvMapAsSphereMap\r
+\r
+        Matrix4Array BoneMatrices\r
+        Int NumBones\r
+        Texture2D BoneParameter\r
+\r
+        Float EdgeSize\r
+        Texture2D SphereMap_A\r
+        Texture2D SphereMap_H\r
+    }\r
+\r
+    Technique {\r
+\r
+        LightMode MultiPass\r
+\r
+        VertexShader GLSL100:   MatDefs/pmd/pmd.vert\r
+        FragmentShader GLSL100: MatDefs/pmd/pmd.frag\r
+\r
+        // VertexShader GLSL100:   Common/MatDefs/Light/Lighting.vert\r
+        // FragmentShader GLSL100: Common/MatDefs/Light/Lighting.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            NormalMatrix\r
+            WorldViewMatrix\r
+            ViewMatrix\r
+            CameraPosition\r
+            WorldMatrix\r
+        }\r
+\r
+        Defines {\r
+            LATC : LATC\r
+            VERTEX_COLOR : UseVertexColor\r
+            VERTEX_LIGHTING : VertexLighting\r
+            ATTENUATION : Attenuation\r
+            MATERIAL_COLORS : UseMaterialColors\r
+            V_TANGENT : VTangent\r
+            MINNAERT  : Minnaert\r
+            WARDISO   : WardIso\r
+            LOW_QUALITY : LowQuality\r
+            HQ_ATTENUATION : HighQuality\r
+\r
+            DIFFUSEMAP : DiffuseMap\r
+            NORMALMAP : NormalMap\r
+            SPECULARMAP : SpecularMap\r
+            PARALLAXMAP : ParallaxMap\r
+            ALPHAMAP : AlphaMap\r
+            COLORRAMP : ColorRamp\r
+\r
+            USE_REFLECTION : EnvMap\r
+            SPHERE_MAP : SphereMap\r
+\r
+            // NUM_BONES : NumBones\r
+            // USE_HWSKINNING\r
+\r
+            SPHERE_MAP_A : SphereMap_A\r
+            SPHERE_MAP_H : SphereMap_H\r
+        }\r
+        RenderState {\r
+            FaceCull Off\r
+        }\r
+    }\r
+\r
+\r
+    Technique PreShadow {\r
+\r
+        VertexShader GLSL100 :   Common/MatDefs/Shadow/PreShadow.vert\r
+        FragmentShader GLSL100 : Common/MatDefs/Shadow/PreShadow.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            WorldViewMatrix\r
+        }\r
+\r
+        Defines {\r
+            DIFFUSEMAP_ALPHA : DiffuseMap\r
+        }\r
+\r
+        RenderState {\r
+            FaceCull Off\r
+            DepthTest On\r
+            DepthWrite On\r
+            PolyOffset 5 0\r
+            ColorWrite Off\r
+        }\r
+\r
+    }\r
+\r
+  Technique PreNormalPass {\r
+\r
+        VertexShader GLSL100 :   Common/MatDefs/SSAO/normal.vert\r
+        FragmentShader GLSL100 : Common/MatDefs/SSAO/normal.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            WorldViewMatrix\r
+            NormalMatrix\r
+        }\r
+\r
+        Defines {\r
+            DIFFUSEMAP_ALPHA : DiffuseMap\r
+        }\r
+\r
+        RenderState {\r
+\r
+        }\r
+\r
+    }\r
+\r
+    Technique GBuf {\r
+\r
+        VertexShader GLSL100:   Common/MatDefs/Light/GBuf.vert\r
+        FragmentShader GLSL100: Common/MatDefs/Light/GBuf.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+            NormalMatrix\r
+            WorldViewMatrix\r
+            WorldMatrix\r
+        }\r
+\r
+        Defines {\r
+            VERTEX_COLOR : UseVertexColor\r
+            MATERIAL_COLORS : UseMaterialColors\r
+            V_TANGENT : VTangent\r
+            MINNAERT  : Minnaert\r
+            WARDISO   : WardIso\r
+\r
+            DIFFUSEMAP : DiffuseMap\r
+            NORMALMAP : NormalMap\r
+            SPECULARMAP : SpecularMap\r
+            PARALLAXMAP : ParallaxMap\r
+        }\r
+    }\r
+\r
+    Technique FixedFunc {\r
+        LightMode FixedPipeline\r
+    }\r
+\r
+    Technique Glow {\r
+\r
+        VertexShader GLSL100:   Common/MatDefs/Misc/SimpleTextured.vert\r
+        FragmentShader GLSL100: Common/MatDefs/Light/Glow.frag\r
+\r
+        WorldParameters {\r
+            WorldViewProjectionMatrix\r
+        }\r
+\r
+        Defines {\r
+            HAS_GLOWMAP : GlowMap\r
+            HAS_GLOWCOLOR : GlowColor\r
+        }\r
+    }\r
+\r
+}
\ No newline at end of file
index 72670e4..a01a10f 100755 (executable)
@@ -32,11 +32,15 @@ package projectkyoto.jme3.mmd;
 import com.jme3.animation.Bone;
 import com.jme3.animation.Skeleton;
 import com.jme3.asset.AssetManager;
+import com.jme3.asset.AssetNotFoundException;
 import com.jme3.material.Material;
+import com.jme3.material.RenderState.BlendMode;
+import com.jme3.material.RenderState.FaceCullMode;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
+import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
@@ -44,6 +48,7 @@ import com.jme3.scene.VertexBuffer;
 import com.jme3.scene.debug.SkeletonPoints;
 import com.jme3.scene.debug.SkeletonWire;
 import com.jme3.scene.shape.Box;
+import com.jme3.shader.VarType;
 import com.jme3.texture.Texture;
 import com.jme3.util.BufferUtils;
 import com.jme3.util.TempVars;
@@ -51,6 +56,7 @@ import java.nio.FloatBuffer;
 import java.nio.ShortBuffer;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.StringTokenizer;
 import projectkyoto.mmd.file.*;
 import projectkyoto.mmd.file.util2.MeshConverter;
 import projectkyoto.mmd.file.util2.MeshData;
@@ -80,6 +86,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");
     }
 
     public PMDNode createNode(String name) {
@@ -209,9 +216,7 @@ public class PMDLoaderGLSLSkinning2 {
         mesh.setBuffer(wb);
         mesh.setBuffer(ib);
         mesh.setBuffer(bib);
-        short[] indexArray = new short[20/*
-                 * md.getBoneList().size()
-                 */];
+        short[] indexArray = new short[meshConverter.getMaxBoneSize()];
         for (int i = 0; i < indexArray.length; i++) {
             if (i < md.getBoneList().size()) {
                 indexArray[i] = md.getBoneList().get(i).shortValue();
@@ -244,83 +249,116 @@ public class PMDLoaderGLSLSkinning2 {
             geom.setNoSkinningMaterial(mat);
         }
         geom.setPmdMaterial(m);
+        if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
+            geom.setQueueBucket(Bucket.Transparent);
+        } else {
+            geom.setQueueBucket(Bucket.Inherit);
+        }
     }
 
     Material createMaterial(PMDMaterial m, boolean skinning) {
         Material mat;
-        if (!skinning) {
-            mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning.j3md");
+        if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
+            if (!skinning) {
+                mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning_alpha.j3md");
+            } else {
+                mat = new Material(assetManager, "MatDefs/pmd/pmd_alpha.j3md");
+            }
         } else {
-            mat = new Material(assetManager, "MatDefs/pmd/pmd.j3md");
+            if (!skinning) {
+                mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning.j3md");
+            } else {
+                mat = new Material(assetManager, "MatDefs/pmd/pmd.j3md");
+            }
+        }
+        float alpha = m.getMaterial().getFaceColor().getAlpha();
+        if (alpha > 0.99f) {
+            alpha = 1f;
         }
         ColorRGBA ambientColor = new ColorRGBA(m.getMaterial().getAmbientColor().getRed(),
-                m.getMaterial().getAmbientColor().getGreen(), m.getMaterial().getAmbientColor().getBlue(), 1f);
+                m.getMaterial().getAmbientColor().getGreen(), m.getMaterial().getAmbientColor().getBlue(), alpha);
         ColorRGBA diffuseColor = new ColorRGBA(m.getMaterial().getFaceColor().getRed(),
-                m.getMaterial().getFaceColor().getGreen(), m.getMaterial().getFaceColor().getBlue(), m.getMaterial().getFaceColor().getAlpha());
+                m.getMaterial().getFaceColor().getGreen(), m.getMaterial().getFaceColor().getBlue(), alpha);
         ColorRGBA ambientAndDiffuseColor = ambientColor.add(diffuseColor);
         ambientAndDiffuseColor.multLocal(0.5f);
+        ambientAndDiffuseColor.a = alpha;
         mat.setBoolean("UseMaterialColors", true);
         mat.setColor("Ambient", ambientAndDiffuseColor);
         mat.setColor("Specular", new ColorRGBA(m.getMaterial().getSpecularColor().getRed(),
-                m.getMaterial().getSpecularColor().getGreen(), m.getMaterial().getSpecularColor().getBlue(), 1f));
+                m.getMaterial().getSpecularColor().getGreen(), m.getMaterial().getSpecularColor().getBlue(), alpha));
         mat.setColor("Diffuse", ambientAndDiffuseColor);
         mat.setFloat("Shininess", m.getMaterial().getPower());
-        if (m.getTextureFileName().length() > 0 /*
-                 * && m.getTextureData() != null
-                 */) {
-            String fileName = m.getTextureFileName();
-            int i = fileName.indexOf("*");
-            if (i >= 0) {
-                fileName = fileName.substring(0, i);
+        if (m.getTextureFileName().length() > 0) {
+            StringTokenizer st = new StringTokenizer(m.getTextureFileName(), "*");
+            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);
+                Texture texture = assetManager.loadTexture("Model/" + fileName /*
+                         * m.getTextureFileName()
+                         */);
+                s = s.toLowerCase();
+                if (s.equals("spa")) {
+                     mat.setTexture("SphereMap_A", texture);
+                } else if (s.equals("sph")) {
+                     mat.setTexture("SphereMap_H", texture);
+                } else {
+//                    texture.setWrap(Texture.WrapMode.Repeat);
+                     mat.setTexture("DiffuseMap", texture);
+                }
             }
-//                mat = new Material(assetManager,"Common/MatDefs/Misc/Unshaded.j3md");
-
-            Texture texture = assetManager.loadTexture("Model/" + fileName /*
-                     * m.getTextureFileName()
-                     */);
-            texture.setWrap(Texture.WrapMode.Repeat);
-            mat.setTexture("DiffuseMap", texture);
-//                mat.setTexture("ColorMap", texture);
         }
         int toonIndex = m.getToonIndex();
-        //toonIndex +=1;
-        String toonname = "toon0.bmp";
-        switch (toonIndex) {
-            case 0:
-                toonname = "toon01.bmp";
-                break;
-            case 1:
-                toonname = "toon02.bmp";
-                break;
-            case 2:
-                toonname = "toon03.bmp";
-                break;
-            case 3:
-                toonname = "toon04.bmp";
-                break;
-            case 4:
-                toonname = "toon05.bmp";
-                break;
-            case 5:
-                toonname = "toon06.bmp";
-                break;
-            case 6:
-                toonname = "toon07.bmp";
-                break;
-            case 7:
-                toonname = "toon08.bmp";
-                break;
-            case 8:
-                toonname = "toon09.bmp";
-                break;
-            case 9:
-                toonname = "toon10.bmp";
-                break;
+        Texture toonTexture = null;
+        if (toonIndex >= 0) {
+            String extToonName = model.getToonTextureList().getToonFileName()[toonIndex];
+            try {
+                toonTexture = assetManager.loadTexture("/Model/"+extToonName);
+            } catch(AssetNotFoundException ex) {
+                String toonname = null;
+                switch (toonIndex) {
+                    case 0:
+                        toonname = "toon01.bmp";
+                        break;
+                    case 1:
+                        toonname = "toon02.bmp";
+                        break;
+                    case 2:
+                        toonname = "toon03.bmp";
+                        break;
+                    case 3:
+                        toonname = "toon04.bmp";
+                        break;
+                    case 4:
+                        toonname = "toon05.bmp";
+                        break;
+                    case 5:
+                        toonname = "toon06.bmp";
+                        break;
+                    case 6:
+                        toonname = "toon07.bmp";
+                        break;
+                    case 7:
+                        toonname = "toon08.bmp";
+                        break;
+                    case 8:
+                        toonname = "toon09.bmp";
+                        break;
+                    case 9:
+                        toonname = "toon10.bmp";
+                        break;
+                }
+                if (toonname != null) {
+                    toonTexture = assetManager.loadTexture("toon/" + toonname);
+                }
+            }
+        }
+        if (toonTexture != null) {
+            toonTexture.setWrap(Texture.WrapAxis.S, Texture.WrapMode.EdgeClamp);
+            toonTexture.setWrap(Texture.WrapAxis.T, Texture.WrapMode.EdgeClamp);
+            mat.setTexture("ColorRamp", toonTexture);
         }
-        Texture texture = assetManager.loadTexture("toon/" + toonname);
-        texture.setWrap(Texture.WrapAxis.S, Texture.WrapMode.EdgeClamp);
-        texture.setWrap(Texture.WrapAxis.T, Texture.WrapMode.EdgeClamp);
-        mat.setTexture("ColorRamp", texture);
         if (m.getEdgeFlag() != 0 /*
                  * && !(geom.getMesh() instanceof PMDSkinMesh)
                  */) {
@@ -332,8 +370,19 @@ public class PMDLoaderGLSLSkinning2 {
 //        mat.setParam("VertexLighting", VarType.Int, new Integer(1));
 //        geom.setMaterial(mat);
 //        geom.setPmdMaterial(m);
-//        mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
+//        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);
+//                    mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
+                } else {
+                    mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
+//                    mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
+//                    mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
+                    mat.getAdditionalRenderState().setAlphaTest(true);
+                }
         return mat;
     }
 
@@ -346,9 +395,6 @@ public class PMDLoaderGLSLSkinning2 {
             bone.setUserControl(true);
             Vector3f translation = new Vector3f(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
             Quaternion rotation = new Quaternion();
-//            rotation.loadIdentity();
-//            translation.zero();
-//            bone.setBindTransforms(translation, rotation,new Vector3f(1,1,1));
             boneArray[boneIndex++] = bone;
         }
         boneIndex = 0;
@@ -365,64 +411,20 @@ public class PMDLoaderGLSLSkinning2 {
                 v1.subtractLocal(v2);
 
                 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
-//                bone.setBindTransforms(v1, Quaternion.IDENTITY);
             } else {
                 Vector3f v1 = temp.vect1; //new Vector3f();
                 v1.set(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
                 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
             }
 
-//            boneArray[boneIndex] = bone;
             boneIndex++;
         }
 
         Skeleton skeleton = new Skeleton(boneArray);
         PMDMesh meshes[] = meshList.toArray(new PMDMesh[meshList.size()]);
-//        skeletonControl = new PMDControl2(node, meshes,
-//                skinMeshList.toArray(new PMDSkinMesh[skinMeshList.size()]),
-//                meshConverter.getSkinMeshData().getVertexList(),
-//                skinArray,
-//                skeleton,
-//                assetManager);
-//        node.addControl(skeletonControl);
-//        skeletonControl.resetToBind();
-//        skeleton.updateWorldVectors();
 
         Quaternion q = new Quaternion();
         q = q.fromAngleNormalAxis((float) Math.PI / 8, new Vector3f(0, 0, 1));
-        for (int i = 0; i < skeleton.getBoneCount(); i++) {
-            Bone bone = skeleton.getBone(i);
-//            if (bone.getName().equals("左髪1")) {
-//                bone.setUserControl(true);
-////                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, new Vector3f(0, 0, 0));
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, Vector3f.ZERO);
-//            }
-//            if (bone.getName().equals("首")) {
-//                bone.setUserControl(true);
-////                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, new Vector3f(0, 0, 0));
-////                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, Vector3f.ZERO);
-//            }
-//            if (bone.getName().equals("上半身")) {
-//                bone.setUserControl(true);
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, new Vector3f(0, 0, 0));
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, Vector3f.ZERO);
-//            }
-//            if (bone.getName().equals("右ひじ")) {
-//                bone.setUserControl(true);
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, new Vector3f(0, 0, 0));
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, Vector3f.ZERO);
-//            }
-//            if (bone.getName().equals("右ひじ")) {
-//                bone.setUserControl(true);
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, new Vector3f(0, 0, 0));
-//                bone.setUserTransforms(new Vector3f(0f, 0f, 0f), q, Vector3f.ZERO);
-//            }
-        }
-//        skeletonControl.setSkinWeight("笑い", 1f);
-//        skeletonControl.setSkinWeight("あ", 1f);
-//        skeletonControl.setSkinWeight("困る", 1f);
-
-//        skeleton.setBindingPose();
         node.skeleton = skeleton;
     }
 
index e96ae13..0c297b5 100755 (executable)
@@ -303,11 +303,13 @@ public class PMDNode extends Node {
 
         for (Skin skin : skinMap.values()) {
             if (skin.isUpdateNeeded()) {
-                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()]);
+                if (skin.getWeight() != 1f) {
+                    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);
             }
@@ -315,10 +317,10 @@ public class PMDNode extends Node {
 
         fvb.position(0);
         fnb.position(0);
+        TempVars vars = TempVars.get();
         for (int i = 0; i < skinPosArray.length; i++) {
             int idxWeights = 0;
 
-            TempVars vars = TempVars.get();
             float[] posBuf = vars.skinPositions;
             float[] normBuf = vars.skinNormals;
 
@@ -355,8 +357,8 @@ public class PMDNode extends Node {
 
             fnb.put(rnx).put(rny).put(rnz);
             fvb.put(rx).put(ry).put(rz);
-            vars.release();
         }
+        vars.release();
         vb.setUpdateNeeded();
         nb.setUpdateNeeded();
     }
@@ -582,7 +584,6 @@ public class PMDNode extends Node {
     // bullet physics
 //    PMDRigidBody rigidBodyArray[];
 
-
     void initMaterials() {
         for (Spatial sp : getChildren()) {
             if (sp instanceof PMDGeometry) {
@@ -610,7 +611,6 @@ public class PMDNode extends Node {
 //    PMDRigidBody createRigidBody(projectkyoto.mmd.file.PMDRigidBody fileRigidBody, Bone bone) {
 //        return null;
 //    }
-
     public boolean isGlslSkinning() {
         return glslSkinning;
     }
index 19b489f..81d2312 100755 (executable)
@@ -31,6 +31,7 @@ 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;
@@ -68,7 +69,8 @@ public class RigidBodyConverter {
 
     public void createRigidBodyGeom(PMDRigidBody rigidBody) {
         Geometry geom = new Geometry(rigidBody.getRigidBodyName());
-        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
+        mat.setBoolean("UseMaterialColors", true);
         Mesh mesh;
         switch (rigidBody.getShapeType()) {
             case 0:
@@ -91,19 +93,19 @@ public class RigidBodyConverter {
         }
         switch (rigidBody.getRigidBodyType()) {
             case 0:
-                mat.setColor("Color", ColorRGBA.Blue);
+                mat.setColor("Diffuse", ColorRGBA.Blue);
                 break;
             case 1:
-                mat.setColor("Color", ColorRGBA.Red);
+                mat.setColor("Diffuse", ColorRGBA.Red);
                 break;
             case 2:
-                mat.setColor("Color", ColorRGBA.Green);
+                mat.setColor("Diffuse", 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);
@@ -120,5 +122,16 @@ 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 dc488eb..f48b269 100755 (executable)
@@ -96,7 +96,7 @@ public class IKControl extends AbstractControl{
     public void updateIKBoneRotation() {
         PMDModel pmdModel = pmdNode.getPmdModel();
         Skeleton skeleton = pmdNode.getSkeleton();
-        skeleton.updateWorldVectors();
+//        skeleton.updateWorldVectors();
         l1:
         for (PMDIKData ikData : pmdModel.getIkList().getPmdIKData()) {
             Bone ikBone = skeleton.getBone(ikData.getIkBoneIndex());
index d8ae086..82af16c 100755 (executable)
@@ -38,6 +38,7 @@ import com.jme3.bullet.collision.shapes.CollisionShape;
 import com.jme3.bullet.collision.shapes.SphereCollisionShape;
 import com.jme3.bullet.joints.SixDofJoint;
 import com.jme3.bullet.joints.SixDofSpringJoint;
+import com.jme3.math.FastMath;
 import com.jme3.math.Matrix3f;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Quaternion;
@@ -64,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 / 180f;
+    float accuracy = 1f / 240;
 
     public PMDPhysicsWorld() {
         float dist = 400f;
@@ -73,9 +74,10 @@ public class PMDPhysicsWorld {
                 new Vector3f(dist, dist, dist),
                 PhysicsSpace.BroadphaseType.AXIS_SWEEP_3);
 //        physicsSpace.setGravity(new Vector3f(0f, -9.8f * 2*2*2, 20f));
-        physicsSpace.setGravity(new Vector3f(0f, -9.8f * 4, 0f));
+//        physicsSpace.setGravity(new Vector3f(0f, -9.8f * 2, 0f));
+        physicsSpace.setGravity(new Vector3f(0f, -9.8f * 1f, 0f));
 //        physicsSpace.create();
-        physicsSpace.update(dist, 1);
+//        physicsSpace.update(dist, 1);
         physicsSpace.setAccuracy(accuracy);
     }
 
@@ -113,7 +115,6 @@ public class PMDPhysicsWorld {
 //            btWorld.addRigidBody(rb, (short) (1 << fileRigidBody.getRigidBodyGroupIndex()),
 //                    (short) fileRigidBody.getRigidBodyGroupTarget());
             rb.setCollisionGroup(1 << (fileRigidBody.getRigidBodyGroupIndex()));
-//            rb.removeCollideWithGroup(0);
             rb.setCollideWithGroups(fileRigidBody.getRigidBodyGroupTarget());
 //                  rb.setCollideWithGroups(0 );
             physicsSpace.addCollisionObject(rb);
@@ -126,7 +127,7 @@ public class PMDPhysicsWorld {
             constArray[i] = constraint;
             physicsSpace.add(constraint);
         }
-        physicsSpace.update(1 / 60f, 1);
+//        physicsSpace.update(1 / 60f, 1);
     }
 
     public void removePMDNode(PMDNode pmdNode) {
@@ -198,22 +199,24 @@ public class PMDPhysicsWorld {
         trans.setRotationQuaternion(q);
         trans.setTranslation(v);
         CollisionShape cs;
+        float margin = 0.00f;
         switch (fileRigidBody.getShapeType()) {
             case 0:
-                cs = new SphereCollisionShape(fileRigidBody.getShapeW());
+                cs = new SphereCollisionShape(fileRigidBody.getShapeW() - margin);
                 break;
             case 1:
-                cs = new BoxCollisionShape(new Vector3f(fileRigidBody.getShapeW(),
-                        fileRigidBody.getShapeH(),
-                        fileRigidBody.getShapeD()));
+                cs = new BoxCollisionShape(new Vector3f(fileRigidBody.getShapeW() - margin,
+                        fileRigidBody.getShapeH() - margin,
+                        fileRigidBody.getShapeD() - margin));
                 break;
             case 2:
-                cs = new CapsuleCollisionShape(fileRigidBody.getShapeW(), fileRigidBody.getShapeH());
+                cs = new CapsuleCollisionShape(fileRigidBody.getShapeW() - margin, fileRigidBody.getShapeH() - margin);
                 break;
             default:
                 throw new PMDException("Invalid getShapeType:" + fileRigidBody.getRigidBodyName() + " "
                         + fileRigidBody.getShapeType());
         }
+        cs.setMargin(0.1f);
         if (fileRigidBody.getRigidBodyType() != 0) {
             mass = fileRigidBody.getWeight();
             kinematic = false;
@@ -243,14 +246,13 @@ public class PMDPhysicsWorld {
 //        worldTrans.origin.add(localInertia)
 //        PMDRigidBody rb = new PMDRigidBody(pmdNode, bone, trans2, trans, kinematic, ci);
         PMDRigidBody rb = new PMDRigidBody(pmdNode, bone, fileRigidBody.getRigidBodyType(), trans2.toTranslationVector(), trans2.toRotationQuat(), cs, mass);
-        rb.setPhysicsRotation(Quaternion.ZERO);
-        rb.setPhysicsLocation(Vector3f.ZERO);
+//        rb.setPhysicsRotation(Quaternion.ZERO);
+//        rb.setPhysicsLocation(Vector3f.ZERO);
         rb.updateFromBoneMatrix();
-        rb.updateFromBoneMatrix(); // because native bullet has a bug.
-        rb.setMass(mass);
+//        rb.setMass(mass * 1000f);
         rb.setDamping(fileRigidBody.getPosDim(), fileRigidBody.getRotDim());
         rb.setRestitution(fileRigidBody.getRecoil());
-        rb.setFriction(fileRigidBody.getFriction());
+//        rb.setFriction(fileRigidBody.getFriction());
 
 //        rb.setWorldTransform(worldTrans);
         if (kinematic) {
@@ -268,6 +270,11 @@ 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) {
 //        Matrix3f m = new Matrix3f();
 //        m.loadIdentity();
@@ -292,7 +299,6 @@ public class PMDPhysicsWorld {
 
         qy.toRotationMatrix(out);
     }
-
     Vector3f convVec(javax.vecmath.Vector3f v) {
         return new Vector3f(v.x, v.y, v.z);
     }
@@ -349,28 +355,85 @@ public class PMDPhysicsWorld {
         transA.setTranslation(rba.getPhysicsLocation());
 //        transA.inverse();
         transA.invertLocal();
-//        transA.multLocal(trans);
-        transA = transA.mult(trans);
+        transA.multLocal(trans);
+//        transA = transA.mult(trans);
         Matrix4f transB = new Matrix4f();
         transB.loadIdentity();
 //        rbb.getWorldTransform(transB);
         transB.setTranslation(rbb.getPhysicsLocation());
         transB.setRotationQuaternion(rbb.getPhysicsRotation());
         transB.invertLocal();
-//        transB.multLocal(trans);
-        transB = transB.mult(trans);
+        transB.multLocal(trans);
+//        transB = transB.mult(trans);
 //        Generic6DofSpringConstraint constraint = new Generic6DofSpringConstraint(rba, rbb, transA, transB, true);
+//        SixDofSpringJoint constraint = new SixDofSpringJoint(rba, rbb,
+//                transA.toTranslationVector(),
+//                transB.toTranslationVector(),
+//                transA.toRotationMatrix(),
+//                transB.toRotationMatrix(),
+//                true);
+
+        Matrix4f transJ = new Matrix4f();
+        transJ.loadIdentity();
+        transJ.setTranslation(pmdJoint.getJointPos().x, pmdJoint.getJointPos().y, pmdJoint.getJointPos().z);
+        convPMDEuler(m2, pmdJoint.getJointRot().x, pmdJoint.getJointRot().y, pmdJoint.getJointRot().z);
+        q.fromRotationMatrix(m2);
+//        q.fromAngles(pmdJoint.getJointRot().x, pmdJoint.getJointRot().y, pmdJoint.getJointRot().z);
+        transJ.setRotationQuaternion(q);
+
+        Matrix4f centerA = new Matrix4f();
+        centerA.setRotationQuaternion(rba.getPhysicsRotation());
+        centerA.setTranslation(rba.getPhysicsLocation());
+        Matrix4f invCenterA = centerA.invert();
+        
+        Matrix4f centerB = new Matrix4f();
+        centerB.setRotationQuaternion(rbb.getPhysicsRotation());
+        centerB.setTranslation(rbb.getPhysicsLocation());
+        Matrix4f invCenterB = centerB.invert();
+        
+        Matrix4f frameInA = invCenterA.mult(transJ);
+        Matrix4f frameInB = invCenterB.mult(transJ);
+        
         SixDofSpringJoint constraint = new SixDofSpringJoint(rba, rbb,
-                transA.toTranslationVector(),
-                transB.toTranslationVector(),
-                transA.toRotationMatrix(),
-                transB.toRotationMatrix(),
+                frameInA.toTranslationVector(),
+                frameInB.toTranslationVector(),
+                frameInA.toRotationMatrix(),
+                frameInB.toRotationMatrix(),
                 true);
 //        Generic6DofConstraint constraint = new Generic6DofConstraint(rba, rbb, transA, transB, true);
         constraint.setLinearLowerLimit(convVec(pmdJoint.getConstPos1()));
         constraint.setLinearUpperLimit(convVec(pmdJoint.getConstPos2()));
-        constraint.setAngularLowerLimit(convVec(pmdJoint.getConstRot1()));
-        constraint.setAngularUpperLimit(convVec(pmdJoint.getConstRot2()));
+        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.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");
+        }
+        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.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");
+        }
+
+        constraint.setAngularUpperLimit(constRot2);
+        constraint.setEquilibriumPoint();
 //        constraint.setCollisionBetweenLinkedBodys(false);
         for (int i = 0; i < 6; i++) {
             float f = pmdJoint.getStiffness()[i];
@@ -382,7 +445,7 @@ public class PMDPhysicsWorld {
         return constraint;
     }
 
-    void setKinematicPos() {
+    public void updateKinematicPos() {
         for (PMDRigidBody rbarray[] : rigidBodyMap.values()) {
             for (int i = 0; i < rbarray.length; i++) {
                 PMDRigidBody rb = rbarray[i];
@@ -413,7 +476,7 @@ public class PMDPhysicsWorld {
     }
 
     void stepSimulation(float timeStep) {
-        setKinematicPos();
+//        setKinematicPos();
 //        float time = timeStep;
 //        for(;time>0;time-=accuracy) {
 //            physicsSpace.update(accuracy, 2);
@@ -424,13 +487,13 @@ public class PMDPhysicsWorld {
 //            applyResultToBone();
 //        }
         physicsSpace.update(timeStep, 10);
-        applyResultToBone();
+//        applyResultToBone();
     }
     Transform t = new Transform();
     Quaternion rot2 = new Quaternion();
     Quat4f rot = new Quat4f();
 
-    void applyResultToBone() {
+    public void applyResultToBone() {
 //        for(int i=0;i<btWorld.getNumCollisionObjects();i++) {
 //            CollisionObject obj = btWorld.getCollisionObjectArray().getQuick(i);
 //            if (obj instanceof PMDRigidBody) {
@@ -473,6 +536,7 @@ public class PMDPhysicsWorld {
                     PMDNode pmdNode = rb.getPmdNode();
                     Node rigidBodyNode = pmdNode.getRigidBodyNode();
                     rb.updateFromBoneMatrix();
+                    rb.setLinearVelocity(Vector3f.ZERO);
                     if (rigidBodyNode != null) {
                         Spatial spaital = rigidBodyNode.getChild(i);
                         spaital.setLocalRotation(rb.getPhysicsRotation());
index 2352780..9e51a58 100755 (executable)
@@ -52,6 +52,8 @@ public class PMDRigidBody extends PhysicsRigidBody {
     final Quaternion invRot = new Quaternion();
     final Vector3f tmpV = new Vector3f();
     final Quaternion tmpQ = new Quaternion();
+    final Bone centerBone;
+    final boolean centerFlag;
     Matrix4f m = new Matrix4f();
     Matrix4f invM = new Matrix4f();
 
@@ -71,6 +73,12 @@ public class PMDRigidBody extends PhysicsRigidBody {
         m.set(invM);
         invM.invertLocal();
         m2.loadIdentity();
+        centerBone = pmdNode.getSkeleton().getBone("センター");
+        if (bone == centerBone) {
+            centerFlag = true;
+        } else {
+            centerFlag = false;
+        }
     }
 
     public void update() {
@@ -93,7 +101,6 @@ public class PMDRigidBody extends PhysicsRigidBody {
             super.setPhysicsLocation(m2.toTranslationVector());
             super.setPhysicsRotation(m2.toRotationQuat());
         } else {
-            Bone centerBone = pmdNode.getSkeleton().getBone("センター");
             tmpV.set(centerBone.getModelSpacePosition());
             tmpV.addLocal(pos);
             tmpQ.set(centerBone.getModelSpaceRotation());
@@ -107,6 +114,12 @@ public class PMDRigidBody extends PhysicsRigidBody {
         }
 //        System.out.println("objectId = "+objectId+(bone != null ? " name = "+bone.getName() : "")+" pos = "+getPhysicsLocation());
     }
+    public void reset() {
+        updateFromBoneMatrix();
+        setLinearVelocity(Vector3f.ZERO);
+        setAngularVelocity(Vector3f.ZERO);
+        clearForces();
+    }
     Matrix4f m2 = new Matrix4f();
     Matrix4f m3 = new Matrix4f();
 
@@ -114,7 +127,7 @@ public class PMDRigidBody extends PhysicsRigidBody {
 //        System.out.println("objectId = "+objectId+" name = "+bone.getName()+" pos = "+getPhysicsLocation());
         if (bone != null) {
             if (rigidBodyType == 2) {
-                if (!bone.getName().contains("センター")) {
+                if (true/*!bone.getName().contains("センター")*/) {
                     tmpV.set(super.getPhysicsLocation());
                     tmpQ.set(super.getPhysicsRotation());
                     m2.setRotationQuaternion(tmpQ);
@@ -130,7 +143,7 @@ public class PMDRigidBody extends PhysicsRigidBody {
 //                super.getPhysicsRotation();
                 }
             } else {
-                if (!bone.getName().contains("センター")) {
+                if (rigidBodyType == 1 && !centerFlag) {
                     tmpV.set(super.getPhysicsLocation());
                     tmpQ.set(super.getPhysicsRotation());
                     m2.setRotationQuaternion(tmpQ);
index 66aed36..8a79845 100755 (executable)
@@ -48,16 +48,16 @@ public class PhysicsControl extends AbstractControl {
         world = new PMDPhysicsWorld();
 //        world.init();
         world.addPMDNode(pmdNode);
-        world.stepSimulation(1f);
+//        world.stepSimulation(1f);
     }
 
     @Override
     protected void controlUpdate(float tpf) {
-        pmdNode.getSkeleton().updateWorldVectors();
-        world.updateJointPosition(pmdNode);
+//        pmdNode.getSkeleton().updateWorldVectors();
+//        world.updateJointPosition(pmdNode);
         world.stepSimulation(tpf);
 //        world.applyResultToBone();
-        pmdNode.calcOffsetMatrices();
+//        pmdNode.calcOffsetMatrices();
 //        pmdNode.update();
     }
 
index f628fc0..d3885d4 100755 (executable)
@@ -14,7 +14,7 @@
 /*   copyright notice, this list of conditions and the following     */
 /*   disclaimer in the documentation and/or other materials provided */
 /*   with the distribution.                                          */
-/* - Neither the name of the MMDLoaderJME3 project team nor the names of  */
+/* - Neither the name of the MMDLoaderJME project team nor the names of  */
 /*   its contributors may be used to endorse or promote products     */
 /*   derived from this software without specific prior written       */
 /*   permission.                                                     */
@@ -36,8 +36,6 @@
 
 package projectkyoto.jme3.mmd.vmd;
 
-import com.jme3.math.FastMath;
-
 /**
  *
  * @author kobayasi
@@ -51,7 +49,6 @@ public class IPUtil {
     static float ipfuncd(float t, float p1, float p2) {
         return ((3 + 9 * p1 - 9 * p2) * t * t + (6 * p2 - 12 * p1) * t + 3 * p1);
     }
-    /* VMD::setInterpolationTable: set up motion interpolation parameter */
 
     static float calcIp(BoneMotionList bml, float x, int offset) {
         if (x <= 0) {
@@ -60,73 +57,41 @@ public class IPUtil {
         if (x >=1) {
             return 1f;
         }
-        int i = (int)((float)BoneMotionList.IPTABLESIZE * x);
-        if (i >= BoneMotionList.IPTABLESIZE) {
-            return 1f;
-        }
-        float f1,f2;
-        f1 = bml.ipTable[offset][i];
-        if (i < BoneMotionList.IPTABLESIZE-1) {
-            f2 = bml.ipTable[offset][i+1];
-        } else {
-            f2 = 1f;
-        }
-        return f1 + (f2 - f1) * (x * (float)BoneMotionList.IPTABLESIZE - (float)i);
-    }
-    static float calcIp(byte ip[], float x, int offset) {
-        short i, d;
-        float x1, x2, y1, y2;
-        float inval, t, v, tt;
-
-        /*
-         * check if they are just a linear function
-         */
-        if (ip[0 + offset] == ip[4 + offset] && ip[8 + offset] == ip[12 + offset]) {
-            // linear
-//            return x;
-        }
-
-        /*
-         * xの近似解を求める。
-         */
-        //for (i = 0; i < 4; i++) {
-        x1 = (float) ip[offset] / 127.0f;
-        y1 = (float) ip[ 4 + offset] / 127.0f;
-        x2 = (float) ip[ 8 + offset] / 127.0f;
-        y2 = (float) ip[12 + offset] / 127.0f;
-        // for (d = 0; d < kInterpolationTableSize; d++) {
-        inval = x; //((float) d + 0.5f) / (float) kInterpolationTableSize;
-         /*
-         * get Y value for given inval
-         */
-        t = inval;
-        for (int i2 = 0; i2 < 1000; i2++) {
-            v = ipfunc(t, x1, x2) - inval;
-            if (Math.abs(v) < 0.0001f) {
-                break;
+        int ipTableSize = bml.ipTable[offset].length;
+        for(int i=0;i<ipTableSize;i++) {
+            if (bml.ipTable[offset][i][0] == x) {
+                return bml.ipTable[offset][i][1];
             }
-            tt = ipfuncd(t, x1, x2);
-            if (tt == 0.0f) {
-                break;
+            if (bml.ipTable[offset][i][0] > x) {
+                float x1,x2,y1,y2;
+                if (i == 0) {
+                    x1 = 0;
+                    y1 = 0;
+                } else {
+                    x1 = bml.ipTable[offset][i-1][0];
+                    y1 = bml.ipTable[offset][i-1][1];
+                }
+                x2 = bml.ipTable[offset][i][0];
+                y2 = bml.ipTable[offset][i][1];
+                return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
             }
-            t -= v / tt;
         }
-        return ipfunc(t, y1, y2);
+        return 1f;
     }
-
-    static void createInterpolationTable(byte ip[], int ipTableSize, float ipTable[][]) {
-        short i, d;
+    static void createInterpolationTable(byte ip[], float ipTable[][][]) {
+        int i, d;
         float x1, x2, y1, y2;
         float inval, t, v, tt;
-
         /*
          * check if they are just a linear function
          */
         for (i = 0; i < 4; i++) {
+            int ipTableSize = ipTable[i].length;
             if (ip[0 + i] == ip[4 + i] && ip[8 + i] == ip[12 + i]) {
                 // linear
                 for (d = 0; d < ipTableSize; d++) {
-                    ipTable[i][d] = (float) d / ipTableSize;
+                    ipTable[i][d][0] = (float) d / ipTableSize;
+                    ipTable[i][d][1] = (float) d / ipTableSize;
                 }
             } else {
                 x1 = ip[   i] / 127.0f;
@@ -134,25 +99,16 @@ public class IPUtil {
                 x2 = ip[ 8 + i] / 127.0f;
                 y2 = ip[12 + i] / 127.0f;
                 for (d = 0; d < ipTableSize; d++) {
-                    inval = ((float) d + 0.5f) / (float) ipTableSize;
+                    inval = ((float) d ) / (float) ipTableSize;
                     /*
                      * get Y value for given inval
                      */
                     t = inval;
-                    for (int i2=0;i2<1000;i2++) {
-                        v = ipfunc(t, x1, x2) - inval;
-                        if (FastMath.abs(v) < 0.0001f) {
-                            break;
-                        }
-                        tt = ipfuncd(t, x1, x2);
-                        if (tt == 0.0f) {
-                            break;
-                        }
-                        t -= v / tt;
-                    }
-                    ipTable[i][d] = ipfunc(t, y1, y2);
+                    ipTable[i][d][0] = ipfunc(t, x1, x2);
+                    ipTable[i][d][1] = ipfunc(t, y1, y2);
                 }
             }
         }
     }
+
 }
index 8a1f217..5a5d2ad 100755 (executable)
@@ -1,31 +1,39 @@
 /*
- * Copyright (c) 2011 Kazuhiko Kobayashi All rights reserved. <p/>
+ * Copyright (c) 2011 Kazuhiko Kobayashi All rights reserved.
+ * <p/>
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
- * 
+ * <p/>
  * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer. <p/> *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution. <p/> * Neither the
- * name of 'MMDLoaderJME' nor the names of its contributors may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission. <p/> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
- * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * this list of conditions and the following disclaimer.
+ * <p/>
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * <p/>
+ * * Neither the name of 'MMDLoaderJME' nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * <p/>
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 package projectkyoto.jme3.mmd.vmd;
 
 import com.jme3.animation.Bone;
 import com.jme3.animation.Skeleton;
+import com.jme3.bullet.PhysicsSpace;
+import com.jme3.bullet.PhysicsTickListener;
+import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.RenderManager;
 import com.jme3.renderer.ViewPort;
@@ -66,12 +74,14 @@ public class VMDControl extends AbstractControl {
     static final VMDSkinComparator vmsc = new VMDSkinComparator();
     final PhysicsControl physicsControl;
     final IKControl ikControl;
+    TickListener tl = new TickListener();
 
     public VMDControl(PMDNode pmdNode, VMDFile vmdFile) {
         this.pmdNode = pmdNode;
         this.vmdFile = vmdFile;
         initMotionMap();
         physicsControl = new PhysicsControl(pmdNode);
+        physicsControl.getWorld().getPhysicsSpace().addTickListener(tl);
         ikControl = new IKControl(pmdNode);
     }
 
@@ -135,8 +145,10 @@ public class VMDControl extends AbstractControl {
 //        for(;time > 0; time -= physicsControl.getWorld().accuracy) {
 //            controlUpdate2(physicsControl.getWorld().accuracy);
 //        }
-        if (time != 0) {
-            controlUpdate2(time);
+        if (time != 0 && !pause) {
+//            controlUpdate2(time);
+            physicsControl.update(tpf);
+//            physicsControl.getWorld().applyResultToBone();
         }
     }
 
@@ -151,7 +163,9 @@ public class VMDControl extends AbstractControl {
                 }
             }
             calcBonePosition(currentFrameNo, pmdNode.getSkeleton());
-            physicsControl.update(tpf);
+            physicsControl.getWorld().updateKinematicPos();
+//            pmdNode.getSkeleton().updateWorldVectors();
+            // physicsControl.update(tpf);
 
 //            timeFromCurrentFrameNo = 0;
 //            i++;
@@ -169,14 +183,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();
+        }
         boneLoop:
         for (BoneMotionList bml : motionMap.values()) {
             Bone bone = pmdNode.getSkeleton().getBone(bml.boneName);
             if (bone != null) {
                 bone.setUserControl(true);
-//                if (bone.getName().equals("左足") || bone.getName().contains("ひざ")) {
-//                    continue;
-//                } else
                 if (bml.size() - 1 < bml.currentCount) {
                     VMDMotion m1 = bml.get(bml.size() - 1);
                     Quat4f q = m1.getRotation();
@@ -224,13 +239,7 @@ public class VMDControl extends AbstractControl {
                         float fy = IPUtil.calcIp(bml, f3, 1); //calcIp(m2.getInterpolation(), f3, 1);
                         float fz = IPUtil.calcIp(bml, f3, 2); //calcIp(m2.getInterpolation(), f3, 2);
                         float fr = IPUtil.calcIp(bml, f3, 3); //calcIp(m2.getInterpolation(), f3, 3);
-//                        float fx = f3;
-//                        float fy = f3;
-//                        float fz = f3;
-//                        float fr = f3;
                         tmpq1.interpolate(m1.getRotation(), m2.getRotation(), fr);
-//                        Quat4f q = m1.getRotation();
-//                        tmpp1.interpolate(m1.getLocation(), m2.getLocation(), f3);
                         tmpp1.x = m1.getLocation().x + (m2.getLocation().x - m1.getLocation().x) * fx;
                         tmpp1.y = m1.getLocation().y + (m2.getLocation().y - m1.getLocation().y) * fy;
                         tmpp1.z = m1.getLocation().z + (m2.getLocation().z - m1.getLocation().z) * fz;
@@ -246,7 +255,21 @@ public class VMDControl extends AbstractControl {
                 }
             }
         }
+        pmdNode.getSkeleton().updateWorldVectors();
         ikControl.updateIKBoneRotation();
+        for(int i=0;i<pmdNode.getPmdModel().getBoneList().getBoneCount();i++) {
+            PMDBone pmdBone = pmdNode.getPmdModel().getBoneList().getBones()[i];
+            if (pmdBone.getBoneType() == 5) {
+                // under-rotation
+                Bone bone = pmdNode.getSkeleton().getBone(i);
+//                if (motionMap.get(pmdBone.getBoneName()) == null) {
+//                    bone.getLocalRotation().loadIdentity();
+//                }
+                Bone targetBone = pmdNode.getSkeleton().getBone(pmdBone.getTargetBone());
+                bone.getLocalRotation().multLocal(targetBone.getLocalRotation());
+                bone.updateWorldVectors();
+            }
+        }
         for (SkinList skinList : skinMap.values()) {
             float w1 = 0f, w2 = 0f;
             int c1 = 0, c2 = 0;
@@ -311,7 +334,7 @@ public class VMDControl extends AbstractControl {
             }
         }
         resetSkins();
-        calcBonePosition(currentFrameNo, pmdNode.getSkeleton());
+//        calcBonePosition(currentFrameNo, pmdNode.getSkeleton());
         physicsControl.getWorld().resetRigidBodyPos();
 //        pmdNode.update();
     }
@@ -345,15 +368,28 @@ public class VMDControl extends AbstractControl {
     public PhysicsControl getPhysicsControl() {
         return physicsControl;
     }
+    class TickListener implements PhysicsTickListener {
+
+        @Override
+        public void prePhysicsTick(PhysicsSpace ps, float f) {
+            controlUpdate2(f);
+        }
+
+        @Override
+        public void physicsTick(PhysicsSpace ps, float f) {
+            physicsControl.getWorld().applyResultToBone();
+        }
+        
+    }
 }
 
 class BoneMotionList extends ArrayList<VMDMotion> {
 
-    static final int IPTABLESIZE = 16;
+    static final int IPTABLESIZE = 64;
     String boneName;
     int currentCount;
     int boneType;
-    final float ipTable[][] = new float[4][IPTABLESIZE];
+    final float ipTable[][][] = new float[4][IPTABLESIZE][2];
     int frame1, frame2;
     final float val1[] = new float[4];
     final float val2[] = new float[4];
@@ -362,7 +398,7 @@ class BoneMotionList extends ArrayList<VMDMotion> {
         if (currentCount != newCount) {
             currentCount = newCount;
             if (newCount >= 0 && newCount < size()) {
-                IPUtil.createInterpolationTable(get(currentCount).getInterpolation(), IPTABLESIZE, ipTable);
+                IPUtil.createInterpolationTable(get(currentCount).getInterpolation(), ipTable);
             }
         }
     }
index a4fcecc..fb79f94 100755 (executable)
@@ -29,7 +29,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
@@ -46,16 +45,17 @@ public class PMDBone {
     private int tailPosBoneIndex;
     private int boneType;   // 0:回転のみ 1:回転と移動 2:IK 3:不明 4:IK影響下 5:回転影響下
     //6:IK接続先 7:非表示 8:捻り 9:回転運動
-    private int dummy;
+    private int targetBone;
     private Vector3f boneHeadPos;
     private boolean hiza;
+
     @Override
     public String toString() {
         return "{boneName = " + boneName
                 + " parentBoneIndex = " + parentBoneIndex
                 + " tailPosBoneIndex = " + tailPosBoneIndex
                 + " boneType = " + boneType
-                + " dummy = " + dummy
+                + " targetBone = " + targetBone
                 + " boneHeadPos = {" + (boneHeadPos == null ? "null" : "{"
                 + boneHeadPos.x + " " + boneHeadPos.y + " " + boneHeadPos.z)
                 + "}"
@@ -67,10 +67,10 @@ public class PMDBone {
         parentBoneIndex = is.readUnsignedShort();
         tailPosBoneIndex = is.readUnsignedShort();
         boneType = is.readByte();
-        dummy = is.readShort();
+        targetBone = is.readShort();
         boneHeadPos = new Vector3f(is.readFloat(), is.readFloat(),
                 -is.readFloat());
-        if (boneName.indexOf("ひざ") >=0) {
+        if (boneName.indexOf("ひざ") >= 0) {
             hiza = true;
         } else {
             hiza = false;
@@ -101,12 +101,12 @@ public class PMDBone {
         this.boneType = boneType;
     }
 
-    public int getDummy() {
-        return dummy;
+    public int getTargetBone() {
+        return targetBone;
     }
 
-    public void setDummy(int dummy) {
-        this.dummy = dummy;
+    public void setTargetBone(int targetBone) {
+        this.targetBone = targetBone;
     }
 
     public int getParentBoneIndex() {
@@ -132,5 +132,4 @@ public class PMDBone {
     public void setHiza(boolean hiza) {
         this.hiza = hiza;
     }
-    
 }
index 3cd73cb..6ad2af7 100755 (executable)
@@ -59,7 +59,7 @@ public class PMDMaterial {
 //        if (textureFileName.length() != 0) {
 //            texture = TextureIO.newTexture(new URL(is.url ,textureFileName), true,"bmp");
 //        }
-        if (!textureFileName.isEmpty()) {
+        if ( false && !textureFileName.isEmpty()) {
             InputStream textureIs = null;
             try {
                 textureIs = new URL(is.url ,textureFileName).openStream();
index 02a483b..02f0b77 100755 (executable)
@@ -136,35 +136,36 @@ public class PMDVertex {
         if (this == obj) {
             return true;
         }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final PMDVertex other = (PMDVertex) obj;
-        if (this.pos != other.pos && (this.pos == null || !this.pos.equals(other.pos))) {
-            return false;
-        }
-        if (this.normal != other.normal && (this.normal == null || !this.normal.equals(other.normal))) {
-            return false;
-        }
-        if (this.uv != other.uv && (this.uv == null || !this.uv.equals(other.uv))) {
-            return false;
-        }
-        if (this.boneNum1 != other.boneNum1) {
-            return false;
-        }
-        if (this.boneNum2 != other.boneNum2) {
-            return false;
-        }
-        if (this.boneWeight != other.boneWeight) {
-            return false;
-        }
-        if (this.edgeFlag != other.edgeFlag) {
-            return false;
-        }
-        return true;
+        return false;
+//        if (obj == null) {
+//            return false;
+//        }
+//        if (getClass() != obj.getClass()) {
+//            return false;
+//        }
+//        final PMDVertex other = (PMDVertex) obj;
+//        if (this.pos != other.pos && (this.pos == null || !this.pos.equals(other.pos))) {
+//            return false;
+//        }
+//        if (this.normal != other.normal && (this.normal == null || !this.normal.equals(other.normal))) {
+//            return false;
+//        }
+//        if (this.uv != other.uv && (this.uv == null || !this.uv.equals(other.uv))) {
+//            return false;
+//        }
+//        if (this.boneNum1 != other.boneNum1) {
+//            return false;
+//        }
+//        if (this.boneNum2 != other.boneNum2) {
+//            return false;
+//        }
+//        if (this.boneWeight != other.boneWeight) {
+//            return false;
+//        }
+//        if (this.edgeFlag != other.edgeFlag) {
+//            return false;
+//        }
+//        return true;
     }
 
     @Override
index 7a1832a..bf36b2b 100755 (executable)
@@ -34,10 +34,15 @@ package projectkyoto.mmd.file.util2;
 
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import projectkyoto.mmd.file.PMDMaterial;
 import projectkyoto.mmd.file.PMDModel;
 import projectkyoto.mmd.file.PMDSkinData;
+import projectkyoto.mmd.file.PMDVertex;
 
 /**
  *
@@ -49,10 +54,24 @@ public class MeshConverter {
     int maxBoneSize = 20;
     List<MeshData> meshDataList = new ArrayList<MeshData>();
     SkinMeshData skinMeshData;
+    HashMap<PMDVertex, Integer> meshTmpVertMap = new HashMap<PMDVertex, Integer>();
+    HashMap<PMDVertex, Integer> skinTmpVertMap = new HashMap<PMDVertex, Integer>();
 
     public MeshConverter(PMDModel model) {
         this.model = model;
-        skinMeshData = new SkinMeshData(model);
+        skinMeshData = new SkinMeshData(this, model);
+        initSkinVertSet();
+    }
+    private final void initSkinVertSet() {
+        for(int skinCount = 0;skinCount<model.getSkinCount();skinCount++) {
+            PMDSkinData skinData = model.getSkinData()[skinCount];
+            if (skinData.getSkinType() == 0) {
+                for(int skinVertCount = 0;skinVertCount<skinData.getSkinVertCount();skinVertCount++) {
+                    VertIndex vi = new VertIndex(skinData.getSkinVertData()[skinVertCount].getSkinVertIndex());
+                    skinVertSet.add(vi);
+                }
+            }
+        }
     }
 
     public void checkDupMaterial() {
@@ -83,10 +102,11 @@ public class MeshConverter {
                 if (containsSkin(i1, i2, i3)) {
                     addSkinTriangle(material, i1, i2, i3);
                 } else {
-                    if (!meshData.addTriangle(i1, i2, i3)) {
+                    if (!meshData.addTriangle(this, i1, i2, i3)) {
                         meshData = new MeshData(model, maxBoneSize, material);
+                        meshTmpVertMap.clear();
                         meshDataList.add(meshData);
-                        meshData.addTriangle(i1, i2, i3);
+                        meshData.addTriangle(this, i1, i2, i3);
                     }
                 }
             }
@@ -105,6 +125,7 @@ public class MeshConverter {
 //        System.out.println("index " + model.getFaceVertCount() + " " + indexSizeSum
 //                + " vertSizeSum = " + model.getVertCount() + " " + vertSizeSum
 //                + " boneSizeSum = " + model.getBoneList().getBoneCount() + " " + boneSizeSum);
+//        printFaceVertSize();
         for(MeshData meshData : meshDataList) {
 //            meshData.printTrinangles();
         }
@@ -122,8 +143,12 @@ public class MeshConverter {
         }
         return false;
     }
-
+    VertIndex tmpvi = new VertIndex(0);
     boolean containsSkin(int i) {
+        tmpvi.index = i;
+        return skinVertSet.contains(tmpvi);
+    }
+    boolean _containsSkin(int i) {
         for(int skinCount = 0;skinCount<model.getSkinCount();skinCount++) {
             PMDSkinData skinData = model.getSkinData()[skinCount];
             if (skinData.getSkinType() == 0) {
@@ -136,8 +161,10 @@ public class MeshConverter {
         }
         return false;
     }
+    Set<VertIndex> skinVertSet = new java.util.HashSet<VertIndex> ();
+    
     void addSkinTriangle(PMDMaterial material, int i1,int i2,int i3) {
-        skinMeshData.addTriangle(material, i1, i2, i3);
+        skinMeshData.addTriangle(this, material, i1, i2, i3);
     }
 
     public int getMaxBoneSize() {
@@ -173,3 +200,32 @@ public class MeshConverter {
     }
     
 }
+class VertIndex {
+    int index;
+
+    public VertIndex(int index) {
+        this.index = index;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+//        if (obj == null) {
+//            return false;
+//        }
+//        if (getClass() != obj.getClass()) {
+//            return false;
+//        }
+        final VertIndex other = (VertIndex) obj;
+        if (this.index != other.index) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 53 * hash + this.index;
+        return hash;
+    }
+}
index 0030c44..e378496 100755 (executable)
@@ -57,15 +57,15 @@ public class MeshData {
         this.maxBoneSize = maxBoneSize;
         this.material = material;
     }
-    public boolean addTriangle(int i1,int i2,int i3) {
+    public boolean addTriangle(MeshConverter mc, int i1,int i2,int i3) {
         int boneListSizeBefore = boneList.size();
         addBoneList(i1);
         addBoneList(i2);
         addBoneList(i3);
         if (boneList.size() <= maxBoneSize) {
-            addVertex(i1);
-            addVertex(i2);
-            addVertex(i3);
+            addVertex(mc, i1);
+            addVertex(mc, i2);
+            addVertex(mc, i3);
             return true;
         }
         for(int i=boneList.size();i>boneListSizeBefore;i--) {
@@ -81,14 +81,16 @@ public class MeshData {
         if (!boneList.contains(v.getBoneNum2()))
             boneList.add(v.getBoneNum2());
     }
-    private void addVertex(int vertIndex) {
+    private void addVertex(MeshConverter mc, int vertIndex) {
         PMDVertex v = model.getVertexList()[vertIndex];
         int newVertIndex;
-        if (vertexList.contains(v)) {
-            newVertIndex = vertexList.indexOf(v);
+        Integer index = mc.meshTmpVertMap.get(v);
+        if (index != null /*vertexList.contains(v)*/) {
+            newVertIndex = index.intValue();//vertexList.indexOf(v);
         } else {
             newVertIndex = vertexList.size();
             vertexList.add(v);
+            mc.meshTmpVertMap.put(v, index);
         }
         indexList.add(newVertIndex);
     }
index 46f6cb4..d484d94 100755 (executable)
@@ -52,19 +52,20 @@ public class SkinMeshData {
     List<PMDVertex> vertexList = new ArrayList<PMDVertex>();
     Map<PMDMaterial, List<Integer>> indexMap = new HashMap<PMDMaterial, List<Integer>>();
 
-    public SkinMeshData(PMDModel model) {
+    public SkinMeshData(MeshConverter mc, PMDModel model) {
         this.model = model;
         for(PMDSkinData sd : model.getSkinData()) {
             if (sd.getSkinType() == 0) {
                 for(int i=0;i<sd.getSkinVertCount();i++) {
                     PMDVertex v = model.getVertexList()[sd.getSkinVertData()[i].getSkinVertIndex()];
                     vertexList.add(v);
+                    mc.skinTmpVertMap.put(v, i);
                 }
             }
         }
     }
 
-    public void addTriangle(PMDMaterial material, int i1, int i2, int i3) {
+    public void addTriangle(MeshConverter mc, PMDMaterial material, int i1, int i2, int i3) {
         addBoneList(i1);
         addBoneList(i2);
         addBoneList(i3);
@@ -73,9 +74,9 @@ public class SkinMeshData {
             indexList = new ArrayList<Integer>();
             indexMap.put(material, indexList);
         }
-        addVertex(indexList,i1);
-        addVertex(indexList,i2);
-        addVertex(indexList,i3);
+        addVertex(mc, indexList,i1);
+        addVertex(mc, indexList,i2);
+        addVertex(mc, indexList,i3);
     }
 
     private void addBoneList(int vertIndex) {
@@ -88,16 +89,19 @@ public class SkinMeshData {
         }
     }
 
-    private void addVertex(List<Integer>indexList, int vertIndex) {
+    private void addVertex(MeshConverter mc, List<Integer>indexList, int vertIndex) {
         PMDVertex v = model.getVertexList()[vertIndex];
+        Integer index = mc.skinTmpVertMap.get(v);
         int newVertIndex;
-        if (vertexList.contains(v)) {
-            newVertIndex = vertexList.indexOf(v);
+        if (index != null /*vertexList.contains(v)*/) {
+            newVertIndex = index.intValue(); //vertexList.indexOf(v);
         } else {
             newVertIndex = vertexList.size();
             vertexList.add(v);
+            mc.skinTmpVertMap.put(v, newVertIndex);
+            index = newVertIndex;
         }
-        indexList.add(newVertIndex);
+        indexList.add(index/*newVertIndex*/);
     }
 
     public List<Integer> getBoneList() {