OSDN Git Service

add Savable support
authorKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Thu, 2 Feb 2012 06:59:52 +0000 (15:59 +0900)
committerKazuhiko Kobayashi <chototsu_moushinp@yahoo.co.jp>
Thu, 2 Feb 2012 06:59:52 +0000 (15:59 +0900)
fix clone bug
fix MeshConverter bug
add vertex lighting support
add unified physcs world support

51 files changed:
nbproject/project.properties
src/MatDefs/pmd/pmd.frag
src/MatDefs/pmd/pmd.j3md
src/MatDefs/pmd/pmd.vert
src/MatDefs/pmd/pmd_alpha.j3md
src/MatDefs/pmd/pmd_cartoon.vert
src/MatDefs/pmd/pmd_no_skinning.j3md
src/MatDefs/pmd/pmd_non_adero.frag [new file with mode: 0644]
src/projectkyoto/jme3/mmd/PMDGeometry.java
src/projectkyoto/jme3/mmd/PMDLoaderGLSLSkinning2.java
src/projectkyoto/jme3/mmd/PMDMesh.java
src/projectkyoto/jme3/mmd/PMDNode.java
src/projectkyoto/jme3/mmd/PMDSkinMesh.java
src/projectkyoto/jme3/mmd/PmdUtil.java [new file with mode: 0644]
src/projectkyoto/jme3/mmd/Skin.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/VMDCallable.java
src/projectkyoto/jme3/mmd/vmd/VMDControl.java
src/projectkyoto/jme3/mmd/vmd/VMDControlMT.java
src/projectkyoto/mmd/file/Coords2d.java
src/projectkyoto/mmd/file/PMDBone.java
src/projectkyoto/mmd/file/PMDBoneDisp.java
src/projectkyoto/mmd/file/PMDBoneDispList.java
src/projectkyoto/mmd/file/PMDBoneDispNameList.java
src/projectkyoto/mmd/file/PMDBoneList.java
src/projectkyoto/mmd/file/PMDHeaderEnglish.java
src/projectkyoto/mmd/file/PMDIKData.java
src/projectkyoto/mmd/file/PMDIKList.java
src/projectkyoto/mmd/file/PMDJoint.java
src/projectkyoto/mmd/file/PMDJointList.java
src/projectkyoto/mmd/file/PMDMaterial.java
src/projectkyoto/mmd/file/PMDModel.java
src/projectkyoto/mmd/file/PMDRigidBody.java
src/projectkyoto/mmd/file/PMDRigidBodyList.java
src/projectkyoto/mmd/file/PMDSkinData.java
src/projectkyoto/mmd/file/PMDSkinDispList.java
src/projectkyoto/mmd/file/PMDSkinVertData.java
src/projectkyoto/mmd/file/PMDToonTextureList.java
src/projectkyoto/mmd/file/PMDVertex.java
src/projectkyoto/mmd/file/VMDFile.java
src/projectkyoto/mmd/file/VMDMotion.java
src/projectkyoto/mmd/file/VMDSkin.java
src/projectkyoto/mmd/file/XColorRGB.java
src/projectkyoto/mmd/file/XColorRGBA.java
src/projectkyoto/mmd/file/XMaterial.java
src/projectkyoto/mmd/file/util2/MeshConverter.java
src/projectkyoto/mmd/file/util2/SavableUtil.java [new file with mode: 0644]
src/projectkyoto/mmd/file/util2/SkinMeshData.java

index 28ed4e6..296a540 100755 (executable)
@@ -26,9 +26,11 @@ dist.jar=${dist.dir}/MMDLoaderJME3-lib.jar
 dist.javadoc.dir=${dist.dir}/javadoc
 endorsed.classpath=
 excludes=
+file.reference.jMonkeyEngine3.jar=/Users/kobayasi/NetBeansProjects/MMD/MikuMikuStudio/mikumikustudio/engine/dist/jMonkeyEngine3.jar
 includes=**
 jar.compress=false
 javac.classpath=\
+    ${file.reference.jMonkeyEngine3.jar}:\
     ${libs.jme3-libraries.classpath}:\
     ${libs.jme3.classpath}
 # Space-separated list of extra javac options
index ddd449b..6e93cc6 100755 (executable)
@@ -65,7 +65,6 @@ varying vec3 lightVec;
 \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
@@ -123,6 +122,7 @@ vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec3 w
    return vec2(diffuseFactor, specularFactor) * vec2(att);\r
 }\r
 #endif\r
+    varying vec4 refVec;\r
 vec2 Optics_SphereCoord2(in vec3 dir){\r
     float dzplus1 = dir.z + 1.0;\r
     float m = 2.0 * sqrt(dir.x * dir.x + dir.y * dir.y + dzplus1 * dzplus1);\r
@@ -158,7 +158,7 @@ void main(){
     #ifdef ALPHAMAP\r
        alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;\r
     #endif\r
-    if(alpha < m_AlphaDiscardThreshold){\r
+    if(alpha < 0.1 /*m_AlphaDiscardThreshold*/){\r
         discard;\r
     }\r
 \r
@@ -190,18 +190,16 @@ void main(){
        #ifdef COLORRAMP\r
            // light.x = texture2D(m_ColorRamp, vec2(light.x, 0.0)).r;\r
            // light.y = texture2D(m_ColorRamp, vec2(light.y, 0.0)).r;\r
-           light.x = texture2D(m_ColorRamp, vec2(0.0,light.x)).r;\r
-           light.y = texture2D(m_ColorRamp, vec2(0.0,light.y)).r;\r
+           diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(0.0,light. x)).rgb;\r
+           //specularColor.rgb *= texture2D(m_ColorRamp, vec2(0.0,light. y)).rgb;\r
        #endif\r
+// adero200\r
+       //if (light.y != light.y) {\r
+       //     light.y = 0.0;\r
+       //}\r
+       vec4 output_color = (((AmbientSum + DiffuseSum) * diffuseColor)\r
+                      + SpecularSum * specularColor * light.y );\r
 \r
-       gl_FragColor =  AmbientSum * diffuseColor + \r
-                       DiffuseSum * diffuseColor  * light.x +\r
-                       SpecularSum * specularColor * light.y;\r
-           diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(0.0,light.x)).rgb;\r
-           specularColor.rgb *= texture2D(m_ColorRamp, vec2(0.0,light.y)).rgb;\r
-       gl_FragColor =  AmbientSum * diffuseColor + \r
-                       DiffuseSum * diffuseColor   +\r
-                       SpecularSum * specularColor ;\r
     #else\r
        vec4 lightDir = vLightDir;\r
        lightDir.xyz = normalize(lightDir.xyz);\r
@@ -249,9 +247,17 @@ void main(){
 #endif\r
 \r
     #endif\r
+#ifdef SPHERE_MAP_A\r
+        vec2 v2 = Optics_SphereCoord(normalize(refVec.xyz));\r
+        v2.y = 1.0 - v2.y;\r
+        output_color.xyz +=  (texture2D(m_SphereMap_A, v2).xyz);\r
+        // output_color.xyz = vec3(normalize(refVec.xyz).x);\r
+#endif\r
+#ifdef SPHERE_MAP_H\r
+        vec2 v2 = Optics_SphereCoord(normalize(refVec.xyz));\r
+        v2.y = 1.0 - v2.y;\r
+        output_color.xyz *= (texture2D(m_SphereMap_H, v2).xyz);\r
+#endif\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 0136f63..8d44a18 100755 (executable)
@@ -137,7 +137,7 @@ MaterialDef pmd {
             USE_REFLECTION : EnvMap\r
             SPHERE_MAP : SphereMap\r
 \r
-            // NUM_BONES : NumBones\r
+            NUM_BONES : NumBones\r
             USE_HWSKINNING\r
             SPHERE_MAP_A : SphereMap_A\r
             SPHERE_MAP_H : SphereMap_H\r
@@ -188,7 +188,7 @@ MaterialDef pmd {
             USE_REFLECTION : EnvMap\r
             SPHERE_MAP : SphereMap\r
 \r
-            // NUM_BONES : NumBones\r
+            NUM_BONES : NumBones\r
             USE_HWSKINNING\r
         }\r
         RenderState {\r
index 3d47909..63104b3 100755 (executable)
@@ -1,6 +1,6 @@
 // #import "MatDefs/pmd/Skinning.glsllib"\r
 #ifdef USE_HWSKINNING\r
-uniform mat4 m_BoneMatrices[20];\r
+uniform mat4 m_BoneMatrices[NUM_BONES];\r
 #endif\r
 #define ATTENUATION\r
 // #define HQ_ATTENUATION\r
@@ -129,8 +129,8 @@ void Skinning_Compute(inout vec4 position, inout vec4 normal){
     vec4 index  = inBoneIndex;\r
     vec4 weight = inBoneWeight;\r
 \r
-    vec4 newPos    = vec4(0.0);\r
-    vec4 newNormal = vec4(0.0);\r
+    vec4 newPos    = vec4(0.0,0.0,0.0,0.0);\r
+    vec4 newNormal = vec4(0.0,0.0,0.0,0.0);\r
 \r
     //for (float i = 1.0; i < 2.0; i += 1.0){\r
         mat4 skinMat = m_BoneMatrices[int(index.x)];\r
@@ -218,7 +218,7 @@ void main(){
        vec2 light = computeLighting(wvPosition, wvNormal, viewDir, wvLightPos);\r
 \r
        AmbientSum.a  = light.x;\r
-       SpecularSum.a = light.y;\r
+       SpecularSum.a = light.y * 0.3;\r
     #endif\r
 \r
     #if defined(USE_REFLECTION) || defined(SPHERE_MAP_A) || defined(SPHERE_MAP_H)\r
index 14cca0b..85132c3 100755 (executable)
@@ -137,7 +137,7 @@ MaterialDef pmd {
             USE_REFLECTION : EnvMap\r
             SPHERE_MAP : SphereMap\r
 \r
-            // NUM_BONES : NumBones\r
+            NUM_BONES : NumBones\r
             USE_HWSKINNING\r
             SPHERE_MAP_A : SphereMap_A\r
             SPHERE_MAP_H : SphereMap_H\r
index 64a4146..f385368 100755 (executable)
@@ -1,5 +1,5 @@
 #ifdef USE_HWSKINNING\r
-uniform mat4 m_BoneMatrices[20];\r
+uniform mat4 m_BoneMatrices[NUM_BONES];\r
 #endif\r
 uniform float m_EdgeSize; \r
 // #import "MatDefs/pmd/Skinning.glsllib"\r
@@ -26,8 +26,8 @@ void Skinning_Compute(inout vec4 position, inout vec4 normal){
     vec4 index  = inBoneIndex;\r
     vec4 weight = inBoneWeight;\r
 \r
-    vec4 newPos    = vec4(0.0);\r
-    vec4 newNormal = vec4(0.0);\r
+    vec4 newPos    = vec4(0.0,0.0,0.0,0.0);\r
+    vec4 newNormal = vec4(0.0,0.0,0.0,0.0);\r
 \r
     //for (float i = 1.0; i < 2.0; i += 1.0){\r
         mat4 skinMat = m_BoneMatrices[int(index.x)];\r
index 322d56d..1b29e3c 100755 (executable)
@@ -35,7 +35,7 @@ MaterialDef pmd {
         Boolean WardIso\r
 \r
         // Use vertex color as an additional diffuse color.\r
-        Boolean UseVertexColor\r
+        Boolean UseVertexColor : false\r
 \r
         // Ambient color\r
         Color Ambient (MaterialAmbient)\r
diff --git a/src/MatDefs/pmd/pmd_non_adero.frag b/src/MatDefs/pmd/pmd_non_adero.frag
new file mode 100644 (file)
index 0000000..2c3181f
--- /dev/null
@@ -0,0 +1,255 @@
+#import "Common/ShaderLib/Optics.glsllib"\r
+\r
+#ifdef SPHERE_MAP_A\r
+  uniform sampler2D m_SphereMap_A;\r
+#endif\r
+#ifdef SPHERE_MAP_H\r
+  uniform sampler2D m_SphereMap_H;\r
+#endif\r
+\r
+\r
+#define ATTENUATION\r
+//#define HQ_ATTENUATION\r
+\r
+\r
+varying vec2 texCoord;\r
+\r
+varying vec4 AmbientSum;\r
+varying vec4 DiffuseSum;\r
+varying vec4 SpecularSum;\r
+\r
+#ifndef VERTEX_LIGHTING\r
+  varying vec3 vPosition;\r
+  varying vec3 vViewDir;\r
+  varying vec4 vLightDir;\r
+#endif\r
+\r
+#ifdef DIFFUSEMAP\r
+  uniform sampler2D m_DiffuseMap;\r
+#endif\r
+\r
+#ifdef SPECULARMAP\r
+  uniform sampler2D m_SpecularMap;\r
+#endif\r
+\r
+#ifdef PARALLAXMAP\r
+  uniform sampler2D m_ParallaxMap;\r
+#endif\r
+  \r
+#ifdef NORMALMAP\r
+  uniform sampler2D m_NormalMap;\r
+#else\r
+  varying vec3 vNormal;\r
+#endif\r
+\r
+#ifdef ALPHAMAP\r
+  uniform sampler2D m_AlphaMap;\r
+#endif\r
+\r
+#ifdef COLORRAMP\r
+  uniform sampler2D m_ColorRamp;\r
+#endif\r
+uniform float m_AlphaDiscardThreshold;\r
+#ifndef VERTEX_LIGHTING\r
+uniform float m_Shininess;\r
+\r
+#ifdef HQ_ATTENUATION\r
+uniform vec4 g_LightPosition;\r
+varying vec3 lightVec;\r
+#endif\r
+\r
+#ifdef USE_REFLECTION \r
+    uniform float m_ReflectionPower;\r
+    uniform float m_ReflectionIntensity;\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
+    #ifdef V_TANGENT\r
+        d = 1.0 - d*d;\r
+        return step(0.0, d) * sqrt(d);\r
+    #else\r
+        return d;\r
+    #endif\r
+}\r
+\r
+float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){\r
+    #ifdef MINNAERT\r
+        float NdotL = max(0.0, dot(norm, lightdir));\r
+        float NdotV = max(0.0, dot(norm, viewdir));\r
+        return NdotL * pow(max(NdotL * NdotV, 0.1), -1.0) * 0.5;\r
+    #else\r
+        return max(0.0, dot(norm, lightdir));\r
+    #endif\r
+}\r
+\r
+float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){\r
+    #ifdef LOW_QUALITY\r
+       // Blinn-Phong\r
+       // Note: preferably, H should be computed in the vertex shader\r
+       vec3 H = (viewdir + lightdir) * vec3(0.5);\r
+       return pow(max(tangDot(H, norm), 0.0), shiny);\r
+    #elif defined(WARDISO)\r
+        // Isotropic Ward\r
+        vec3 halfVec = normalize(viewdir + lightdir);\r
+        float NdotH  = max(0.001, tangDot(norm, halfVec));\r
+        float NdotV  = max(0.001, tangDot(norm, viewdir));\r
+        float NdotL  = max(0.001, tangDot(norm, lightdir));\r
+        float a      = tan(acos(NdotH));\r
+        float p      = max(shiny/128.0, 0.001);\r
+        return NdotL * (1.0 / (4.0*3.14159265*p*p)) * (exp(-(a*a)/(p*p)) / (sqrt(NdotV * NdotL)));\r
+    #else\r
+       // Standard Phong\r
+       vec3 R = reflect(-lightdir, norm);\r
+       return pow(max(tangDot(R, viewdir), 0.0), shiny);\r
+    #endif\r
+}\r
+\r
+vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec3 wvLightDir){\r
+   float diffuseFactor = lightComputeDiffuse(wvNorm, wvLightDir, wvViewDir);\r
+   float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir, m_Shininess);\r
+   specularFactor *= step(1.0, m_Shininess);\r
+\r
+   #ifdef HQ_ATTENUATION\r
+    float att = clamp(1.0 - g_LightPosition.w * length(lightVec), 0.0, 1.0);\r
+   #else\r
+    float att = vLightDir.w;\r
+   #endif\r
+\r
+   return vec2(diffuseFactor, specularFactor) * vec2(att);\r
+}\r
+#endif\r
+vec2 Optics_SphereCoord2(in vec3 dir){\r
+    float dzplus1 = dir.z + 1.0;\r
+    float m = 2.0 * sqrt(dir.x * dir.x + dir.y * dir.y + dzplus1 * dzplus1);\r
+    return vec2(dir.x / m + 0.5, dir.y / m + 0.5);\r
+}\r
+\r
+void main(){\r
+    vec2 newTexCoord;\r
\r
+    #if defined(PARALLAXMAP) || defined(NORMALMAP_PARALLAX)\r
+       float h;\r
+       #ifdef PARALLAXMAP\r
+          h = texture2D(m_ParallaxMap, texCoord).r;\r
+       #else\r
+          h = texture2D(m_NormalMap, texCoord).a;\r
+       #endif\r
+       float heightScale = 0.05;\r
+       float heightBias = heightScale * -0.5;\r
+       vec3 normView = normalize(vViewDir);\r
+       h = (h * heightScale + heightBias) * normView.z;\r
+       newTexCoord = texCoord + (h * -normView.xy);\r
+    #else\r
+       newTexCoord = texCoord;\r
+    #endif\r
+    \r
+   #ifdef DIFFUSEMAP\r
+      vec4 diffuseColor = texture2D(m_DiffuseMap, newTexCoord);\r
+    #else\r
+      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
+    if(alpha < m_AlphaDiscardThreshold){\r
+        discard;\r
+    }\r
+\r
+    // ***********************\r
+    // Read from textures\r
+    // ***********************\r
+    #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)\r
+      vec4 normalHeight = texture2D(m_NormalMap, newTexCoord);\r
+      vec3 normal = (normalHeight.xyz * vec3(2.0) - vec3(1.0));\r
+      #ifdef LATC\r
+        normal.z = sqrt(1.0 - (normal.x * normal.x) - (normal.y * normal.y));\r
+      #endif\r
+      normal.y = -normal.y;\r
+    #elif !defined(VERTEX_LIGHTING)\r
+      vec3 normal = vNormal;\r
+      #if !defined(LOW_QUALITY) && !defined(V_TANGENT)\r
+         normal = normalize(normal);\r
+      #endif\r
+    #endif\r
+\r
+    #ifdef SPECULARMAP\r
+      vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);\r
+    #else\r
+      vec4 specularColor = vec4(1.0);\r
+    #endif\r
+\r
+    #ifdef VERTEX_LIGHTING\r
+       vec2 light = vec2(AmbientSum.a, SpecularSum.a);\r
+       #ifdef COLORRAMP\r
+           // light.x = texture2D(m_ColorRamp, vec2(light.x, 0.0)).r;\r
+           // light.y = texture2D(m_ColorRamp, vec2(light.y, 0.0)).r;\r
+           diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(0.0,light. x)).rgb;\r
+           //specularColor.rgb *= texture2D(m_ColorRamp, vec2(0.0,light. y)).rgb;\r
+       #endif\r
+// adero200\r
+       //if (light.y != light.y) {\r
+       //     light.y = 0.0;\r
+       //}\r
+       gl_FragColor = (((AmbientSum + DiffuseSum) * diffuseColor)\r
+                      + SpecularSum * specularColor * light.y );\r
+\r
+    #else\r
+       vec4 lightDir = vLightDir;\r
+       lightDir.xyz = normalize(lightDir.xyz);\r
+\r
+       vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz);\r
+       #ifdef COLORRAMP\r
+           // diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;\r
+           // specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;\r
+           diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(0.0,light. x)).rgb;\r
+           specularColor.rgb *= texture2D(m_ColorRamp, vec2(0.0,light. y)).rgb;\r
+       #endif\r
+\r
+       // Workaround, since it is not possible to modify varying variables\r
+       vec4 SpecularSum2 = SpecularSum;\r
+       #ifdef USE_REFLECTION\r
+            vec4 refColor = Optics_GetEnvColor(m_EnvMap, refVec.xyz);\r
+\r
+            // Interpolate light specularity toward reflection color\r
+            // Multiply result by specular map\r
+            specularColor = mix(SpecularSum2 * light.y, refColor, refVec.w) * specularColor;\r
+\r
+            SpecularSum2 = vec4(1.0);\r
+            light.y = 1.0;\r
+       #endif\r
+//       if (isnan(light.y)) {\r
+       if (light.y != light.y) {\r
+            light.y = 0.0;\r
+       }\r
+//       gl_FragColor =  (AmbientSum * diffuseColor +\r
+//                       DiffuseSum * diffuseColor + //* light.x +\r
+//                       SpecularSum2 * specularColor * light.y ) * 0.8;\r
+       vec4 output_color = (((AmbientSum + DiffuseSum) * diffuseColor)  +\r
+                       SpecularSum2 * specularColor * light.y );\r
+// output_color=vec4(0);\r
+#ifdef SPHERE_MAP_A\r
+        vec2 v2 = Optics_SphereCoord(normalize(refVec.xyz));\r
+        v2.y = 1.0 - v2.y;\r
+        output_color.xyz +=  (texture2D(m_SphereMap_A, v2).xyz);\r
+        // output_color.xyz = vec3(normalize(refVec.xyz).x);\r
+#endif\r
+#ifdef SPHERE_MAP_H\r
+        vec2 v2 = Optics_SphereCoord(normalize(refVec.xyz));\r
+        v2.y = 1.0 - v2.y;\r
+        output_color.xyz *= (texture2D(m_SphereMap_H, v2).xyz);\r
+#endif\r
+\r
+    #endif\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 8ae2aae..6995dbc 100755 (executable)
  */
 package projectkyoto.jme3.mmd;
 
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
 import com.jme3.material.Material;
+import com.jme3.math.Matrix4f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer.Type;
+import java.io.IOException;
 import projectkyoto.mmd.file.PMDMaterial;
 
 /**
@@ -43,7 +50,6 @@ public class PMDGeometry extends Geometry {
     PMDMaterial pmdMaterial;
     Material glslSkinningMaterial;
     Material noSkinningMaterial;
-    PMDMesh pmdMesh;
 
     public PMDGeometry(String name, Mesh mesh) {
         super(name, mesh);
@@ -82,8 +88,43 @@ public class PMDGeometry extends Geometry {
 
     @Override
     public PMDGeometry clone() {
+        Mesh meshBackup = mesh;
+        mesh = new Mesh();
         PMDGeometry newPMDGeometry = (PMDGeometry)super.clone(false);
-        newPMDGeometry.setMesh(getMesh().clone());
+        mesh = meshBackup;
+//        newPMDGeometry.setMesh(getMesh().clone());
+        if (mesh instanceof PMDSkinMesh) {
+            PMDSkinMesh oldMesh = (PMDSkinMesh)mesh;
+            PMDSkinMesh newMesh = new PMDSkinMesh();
+            newMesh.boneIndexArray = oldMesh.boneIndexArray;
+//            newMesh.boneMatrixArray = new Matrix4f[mesh.boneMatrixArray.length];
+//            for(int i=0;i<mesh.boneMatrixArray.length;i++) {
+//                newMesh.boneMatrixArray[i] = new Matrix4f();
+//                newMesh.boneMatrixArray[i].loadIdentity();
+//            }
+            newMesh.bound = oldMesh.bound.clone();
+            newMesh.setBuffer(oldMesh.getBuffer(Type.Index));
+            newPMDGeometry.setMesh(newMesh);
+        } else {
+            PMDMesh oldMesh = (PMDMesh)mesh;
+            PMDMesh newMesh = new PMDMesh();
+            newMesh.boneIndexArray = oldMesh.boneIndexArray;
+            newMesh.boneMatrixArray = new Matrix4f[oldMesh.boneMatrixArray.length];
+            for (int i = 0; i < newMesh.boneMatrixArray.length; i++) {
+                newMesh.boneMatrixArray[i] = new Matrix4f();
+                newMesh.boneMatrixArray[i].set(oldMesh.boneMatrixArray[i]);
+            }
+            newMesh.setMode(Mesh.Mode.Triangles);
+            newMesh.setVbBackup(oldMesh.getVbBackup());
+            newMesh.setNbBackup(oldMesh.getNbBackup());
+            newMesh.setBuffer(oldMesh.getVbBackup());
+            newMesh.setBuffer(oldMesh.getNbBackup());
+            newMesh.setBuffer(oldMesh.getBuffer(Type.Index));
+            newMesh.setBuffer(oldMesh.getBuffer(Type.TexCoord));
+            newMesh.setBuffer(oldMesh.getBuffer(Type.BoneIndex));
+            newMesh.setBuffer(oldMesh.getBuffer(Type.BoneWeight));
+            newPMDGeometry.setMesh(newMesh);
+        }
         newPMDGeometry.glslSkinningMaterial = glslSkinningMaterial.clone();
         newPMDGeometry.noSkinningMaterial = noSkinningMaterial.clone();
         return newPMDGeometry;
@@ -94,12 +135,37 @@ public class PMDGeometry extends Geometry {
         return clone();
     }
 
+//    @Override
+//    public void setMesh(Mesh mesh) {
+//        super.setMesh(mesh);
+//        if (mesh instanceof PMDMesh) {
+//            pmdMesh = (PMDMesh)mesh;
+//        }
+//    }
+
     @Override
-    public void setMesh(Mesh mesh) {
-        super.setMesh(mesh);
+    public void setMaterial(Material material) {
+        super.setMaterial(material);
         if (mesh instanceof PMDMesh) {
-            pmdMesh = (PMDMesh)mesh;
+            PMDMesh pmdMesh = (PMDMesh)mesh;
+            pmdMesh.boneMatricesParamIndex = -1;
         }
     }
+
+    @Override
+    public void read(JmeImporter im) throws IOException {
+        super.read(im);
+        InputCapsule c = im.getCapsule(this);
+        glslSkinningMaterial = (Material)c.readSavable("glslSkinningMaterial", null);
+        noSkinningMaterial = (Material)c.readSavable("noSkinningMaterial", null);
+    }
+
+    @Override
+    public void write(JmeExporter ex) throws IOException {
+        super.write(ex);
+        OutputCapsule c = ex.getCapsule(this);
+        c.write(glslSkinningMaterial, "glslSkinningMaterial", null);
+        c.write(noSkinningMaterial, "noSkinningMaterial", null);
+    }
     
 }
index d6f87c8..a2e40c7 100755 (executable)
@@ -35,6 +35,7 @@ import com.jme3.asset.AssetInfo;
 import com.jme3.asset.AssetLoader;
 import com.jme3.asset.AssetManager;
 import com.jme3.asset.AssetNotFoundException;
+import com.jme3.asset.DesktopAssetManager;
 import com.jme3.material.Material;
 import com.jme3.material.RenderState.BlendMode;
 import com.jme3.material.RenderState.FaceCullMode;
@@ -98,10 +99,22 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
 //        System.out.println("faceVertCount = " + model.getFaceVertCount());
 //        assetManager.registerLoader(com.jme3.texture.plugins.AWTLoader.class, "sph", "spa");
     }
+    public PMDLoaderGLSLSkinning2(AssetManager assetManager, MeshConverter mc) {
+        this.assetManager = assetManager;
+        this.model = mc.getModel();
+        this.meshConverter = mc;
+        folderName = "/Model/";
+//        System.out.println("vertexCount = " + model.getVertCount());
+//        System.out.println("faceVertCount = " + model.getFaceVertCount());
+//        assetManager.registerLoader(com.jme3.texture.plugins.AWTLoader.class, "sph", "spa");
+    }
     public void init() {
 //        model = null;
         node = null;
-        meshConverter = new MeshConverter(model);
+        if (meshConverter == null) {
+            meshConverter = new MeshConverter(model);
+            meshConverter.convertMesh();
+        }
         meshCount = 1;
 //        assetManager = null;
 //        folderName = null;
@@ -120,11 +133,11 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
         init();
         node = new PMDNode(name, model, assetManager);
         meshCount = 1;
-        meshConverter.convertMesh();
 //        System.out.println("child size = "+node.getChildren().size()+" "+meshList.size()+" "+skinMeshList.size());
         node.pmdGeometryArray = new PMDGeometry[meshConverter.getMeshDataList().size()];
         int pmdGeometryIndex = 0;
-        for (MeshData md : meshConverter.getMeshDataList()) {
+        for(int i=0;i<meshConverter.getMeshDataList().size();i++) {
+            MeshData md = meshConverter.getMeshDataList().get(i);
             PMDMesh mesh = createMesh(md);
             PMDGeometry geom = new PMDGeometry("geom" + meshCount++);
             geom.setMesh(mesh);
@@ -133,6 +146,7 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
             System.out.println(node.attachChild(geom));
             meshList.add(mesh);
             node.pmdGeometryArray[pmdGeometryIndex++] = geom;
+            meshConverter.getMeshDataList().set(i, null);
         }
         createSkinCommonVertData();
         for (PMDMaterial pmdMaterial : meshConverter.getSkinMeshData().getIndexMap().keySet()) {
@@ -319,6 +333,9 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
                 mat = new Material(assetManager, "MatDefs/pmd/pmd.j3md");
             }
         }
+        if (skinning) {
+            mat.setInt("NumBones", meshConverter.getMaxBoneSize());
+        }
         float alpha = m.getMaterial().getFaceColor().getAlpha();
         if (alpha > 0.99f) {
             alpha = 1f;
@@ -365,7 +382,7 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
             String extToonName = model.getToonTextureList().getToonFileName()[toonIndex];
             try {
                 toonTexture = assetManager.loadTexture(folderName + extToonName);
-            } catch (AssetNotFoundException ex) {
+            } catch (Exception ex) {
                 String toonname = null;
                 switch (toonIndex) {
                     case 0:
@@ -418,7 +435,7 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
         } else {
             mat.setFloat("EdgeSize", 0f);
         }
-//        mat.setParam("VertexLighting", VarType.Int, new Integer(1));
+        mat.setParam("VertexLighting", VarType.Boolean, true);
 //        geom.setMaterial(mat);
 //        geom.setPmdMaterial(m);
 //        mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
@@ -542,31 +559,51 @@ public class PMDLoaderGLSLSkinning2 implements AssetLoader{
         boolean errFlag = false;
         for(;;) {
             try {
-                this.assetManager = ai.getManager();
-                model = new PMDModel(ai.openStream());
-                folderName = ai.getKey().getFolder();
-                meshConverter = new MeshConverter(model);
-                PMDNode pmdNode = createNode(ai.getKey().getName());
-                if (JmeSystem.getFullName().indexOf("Android") == -1) {
-                    try {
-                        String vendor = GL11.glGetString(GL11.GL_VENDOR);
-                        if (vendor != null && vendor.toLowerCase().contains("intel")) {
-                            pmdNode.setGlslSkinning(false);
-                        } else {
-                            pmdNode.setGlslSkinning(true);
-                        }
-                    } catch(Exception ex) {
-                        pmdNode.setGlslSkinning(false);
-                    }
-                }
-                return pmdNode;
+                PMDLoaderGLSLSkinning2 loader = new PMDLoaderGLSLSkinning2();
+                return loader.load2(ai);
             }catch(OutOfMemoryError ex) {
                 if (errFlag) {
                     throw new RuntimeException(ex);
                 }
                 errFlag = true;
+                if (ai.getManager() instanceof DesktopAssetManager) {
+                    ((DesktopAssetManager)ai.getManager()).clearCache();
+                }
                 System.gc();
+                System.runFinalization();
             }
         }
     }
+    private Object load2(AssetInfo ai) throws IOException {
+        this.assetManager = ai.getManager();
+        model = new PMDModel(ai.openStream());
+        folderName = ai.getKey().getFolder();
+        meshConverter = new MeshConverter(model);
+        meshConverter.convertMesh();
+        model.setVertexList(null);
+        model.setFaceVertIndex(null);
+        PMDNode pmdNode = createNode(ai.getKey().getName());
+        if (JmeSystem.getFullName().indexOf("Android") == -1) {
+            try {
+                String vendor = GL11.glGetString(GL11.GL_VENDOR);
+                if (vendor != null && vendor.toLowerCase().contains("intel")) {
+                    pmdNode.setGlslSkinning(false);
+                } else {
+                    pmdNode.setGlslSkinning(true);
+                }
+            } catch(Exception ex) {
+                pmdNode.setGlslSkinning(false);
+            }
+        }
+        return pmdNode;
+    }
+
+    public void setFolderName(String folderName) {
+        this.folderName = folderName;
+    }
+
+    public String getFolderName() {
+        return folderName;
+    }
+   
 }
index 8a76d5c..7b93ec9 100755 (executable)
@@ -31,11 +31,16 @@ package projectkyoto.jme3.mmd;
 
 import com.jme3.bounding.BoundingBox;
 import com.jme3.bounding.BoundingVolume;
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer;
 import com.jme3.util.BufferUtils;
+import java.io.IOException;
 import java.nio.FloatBuffer;
 
 /**
@@ -80,10 +85,14 @@ public class PMDMesh extends Mesh {
     @Override
     public PMDMesh clone() {
         PMDMesh newMesh = (PMDMesh) super.clone();
+        boneMatricesParamIndex = -1;
         newMesh.boneMatrixArray = new Matrix4f[boneMatrixArray.length];
         for (int i = 0; i < newMesh.boneMatrixArray.length; i++) {
             newMesh.boneMatrixArray[i] = new Matrix4f();
         }
+        newMesh.setBuffer(getBuffer(VertexBuffer.Type.BoneIndex));
+        newMesh.setBuffer(getBuffer(VertexBuffer.Type.TexCoord));
+        releaseSoftwareSkinningBufferes();
         return newMesh;
     }
 
@@ -150,4 +159,24 @@ public class PMDMesh extends Mesh {
         clearBuffer(VertexBuffer.Type.Normal);
         setBuffer(nbBackup);
     }
+
+    @Override
+    public void read(JmeImporter im) throws IOException {
+        super.read(im);
+        InputCapsule c = im.getCapsule(this);
+        boneIndexArray = c.readIntArray("boneIndexArray", null);
+        boneMatrixArray = new Matrix4f[boneIndexArray.length];
+        for(int i=0;i<boneMatrixArray.length;i++) {
+            boneMatrixArray[i] = new Matrix4f();
+            boneMatrixArray[i].loadIdentity();
+        }
+    }
+
+    @Override
+    public void write(JmeExporter ex) throws IOException {
+        super.write(ex);
+        OutputCapsule c = ex.getCapsule(this);
+        c.write(boneIndexArray, "boneIndexArray", null);
+    }
+    
 }
index e9a678c..1c66f7a 100755 (executable)
@@ -32,6 +32,11 @@ package projectkyoto.jme3.mmd;
 import com.jme3.animation.Bone;
 import com.jme3.animation.Skeleton;
 import com.jme3.asset.AssetManager;
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.export.Savable;
 import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.FastMath;
@@ -45,6 +50,7 @@ import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.scene.VertexBuffer;
 import com.jme3.util.TempVars;
+import java.io.IOException;
 import java.nio.FloatBuffer;
 import projectkyoto.mmd.file.PMDModel;
 import com.jme3.scene.VertexBuffer.*;
@@ -58,10 +64,14 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import projectkyoto.mmd.file.PMDBone;
 import projectkyoto.mmd.file.PMDException;
+import projectkyoto.mmd.file.PMDSkinData;
 import projectkyoto.mmd.file.PMDSkinVertData;
 import projectkyoto.mmd.file.PMDVertex;
+import projectkyoto.mmd.file.util2.SavableUtil;
 
 /**
  *
@@ -97,6 +107,118 @@ public class PMDNode extends Node {
     Node jointNode;
     boolean glslSkinning = true;
 
+    @Override
+    public void read(JmeImporter e) throws IOException {
+        super.read(e);
+        InputCapsule c = e.getCapsule(this);
+        pmdModel = (PMDModel)SavableUtil.read(c, "pmdModel", null);
+        skeleton = (Skeleton)c.readSavable("skeleton", null);
+        skinMap = (Map<String, Skin>)c.readStringSavableMap("skinMap", new HashMap<String, Savable>());
+        skinBoneWeightArray = c.readFloatArray("skinBoneWeightArray", new float[0]);
+        skinBoneArray = c.readIntArray("skinBoneArray", new int[0]);
+        edgeSize = c.readFloat("edgeSize", 1.0f);
+        int pmdGeometryArrayLength = c.readInt("pmdGeometryArrayLength", 0);
+        pmdGeometryArray = new PMDGeometry[pmdGeometryArrayLength];
+        targets = new PMDMesh[pmdGeometryArrayLength];
+        int skinTargetsLength = c.readInt("skinTargetsLength", 0);
+        skinTargets = new PMDSkinMesh[skinTargetsLength];
+        VertexBuffer skinvb = (VertexBuffer)c.readSavable("skinvb", null);
+        VertexBuffer skinnb = (VertexBuffer)c.readSavable("skinnb", null);
+        VertexBuffer skintb = (VertexBuffer)c.readSavable("skintb", null);
+        VertexBuffer skinvb2 = skinvb.clone();
+        VertexBuffer skinnb2 = skinnb.clone();
+        int meshCount = 0;
+        int skinMeshCount = 0;
+            for(Spatial sp : getChildren()) {
+                Spatial newSp = sp;//.clone();
+//                newPMDNode.attachChild(newSp);
+                if (sp instanceof PMDGeometry) {
+                    Mesh mesh = ((Geometry)newSp).getMesh();
+                    if (mesh instanceof PMDMesh) {
+                        PMDMesh pmdMesh = (PMDMesh)mesh;
+                        pmdMesh.setVbBackup(pmdMesh.getBuffer(Type.Position));
+                        pmdMesh.setNbBackup(pmdMesh.getBuffer(Type.Normal));
+                        pmdGeometryArray[meshCount] = (PMDGeometry)sp;
+                        targets[meshCount++] = (PMDMesh)mesh;
+                    } else if (mesh instanceof PMDSkinMesh) {
+//                        mesh.setMode(Mesh.Mode.Triangles);
+                        PMDSkinMesh skinMesh = (PMDSkinMesh)mesh;
+                        if (skinMeshCount != 0) {
+                            skinMesh.setBuffer(skinvb);
+                            skinMesh.setSkinvb2(skinvb2);
+                            skinMesh.setBuffer(skinnb);
+                            skinMesh.setSkinnb2(skinnb2);
+                            skinMesh.setBuffer(skintb);
+                        } else {
+                            skinMesh.setBuffer(skinvb);
+                            skinMesh.setSkinvb2(skinvb2);
+                            skinMesh.setBuffer(skinnb);
+                            skinMesh.setSkinnb2(skinnb2);
+                            skinMesh.setBuffer(skintb);
+                        }
+                        skinTargets[skinMeshCount++] = (PMDSkinMesh)mesh;
+                    }
+                }
+            }
+            calcOffsetMatrices();
+            Savable[] sa = c.readSavableArray("skinArray", new Skin[0]);
+            skinArray = new Skin[sa.length];
+            for(int i=0;i<sa.length;i++) {
+                Skin skin = (Skin)sa[i];
+                skinArray[i] = skin;
+                skin.pmdNode = this;
+                l2:
+                for(int i2=0;i2<pmdModel.getSkinCount();i2++){
+                    if (pmdModel.getSkinData()[i2].getSkinName().equals(skin.getSkinName())) {
+                        skin.skinData = pmdModel.getSkinData()[i2];
+                        break l2;
+                    }
+                }
+                skin.setWeight(0f);
+                skin.setUpdateNeeded(true);
+                skinMap.put(skin.skinName, skin);
+            }
+            skinPosArray = (javax.vecmath.Vector3f[])SavableUtil.read(c, "skinPosArray", null);
+            skinPosArrayOrig = new javax.vecmath.Vector3f[skinPosArray.length];
+            for(int i=0;i<skinPosArray.length;i++) {
+                skinPosArrayOrig[i] = new javax.vecmath.Vector3f(skinPosArray[i]);
+            }
+            skinNormalArray = (javax.vecmath.Vector3f[])SavableUtil.read(c, "skinNormalArray", null);
+            skinNormalArrayOrig = new javax.vecmath.Vector3f[skinNormalArray.length];
+            for(int i=0;i<skinNormalArray.length;i++) {
+                skinNormalArrayOrig[i] = new javax.vecmath.Vector3f(skinNormalArray[i]);
+            }
+            skinBoneArray = c.readIntArray("skinBoneArray", skinBoneArray);
+            skinBoneWeightArray = c.readFloatArray("skinBoneWeightArray", skinBoneWeightArray);
+    }
+
+    @Override
+    public void write(JmeExporter e) throws IOException {
+        super.write(e);
+        OutputCapsule c = e.getCapsule(this);
+        c.write(1, "version", 1);
+        SavableUtil.write(c, pmdModel, "pmdModel");
+        c.write(skeleton, "skeleton", new Skeleton());
+        c.writeStringSavableMap(skinMap, "skinMap", new HashMap<String, Skin>());
+        c.write(skinBoneWeightArray, "skinBoneWeightArray", null);
+        c.write(skinBoneArray, "skinBoneArray", null);
+        c.write(edgeSize, "edgeSize", 1.0f);
+        c.write(pmdGeometryArray.length, "pmdGeometryArrayLength",0);
+        c.write(skinTargets.length, "skinTargetsLength",0);
+        if (skinTargets != null && skinTargets.length > 0) {
+            PMDSkinMesh mesh = skinTargets[0];
+            c.write(mesh.getSkinvb2(),"skinvb",null);
+            c.write(mesh.getSkinnb2(),"skinnb",null);
+            c.write(mesh.getBuffer(Type.TexCoord),"skintb",null);
+        }
+        c.write(skinArray, "skinArray", null);
+        SavableUtil.write(c, skinPosArrayOrig,"skinPosArray");
+        SavableUtil.write(c, skinNormalArrayOrig, "skinNormalArray");
+        c.write(skinBoneArray, "skinBoneArray", null);
+        c.write(skinBoneWeightArray, "skinBoneWeightArray", null);
+        
+    }
+
     public PMDNode(String name, PMDModel pmdModel, AssetManager assetManager) {
         super(name);
         this.pmdModel = pmdModel;
@@ -163,7 +285,7 @@ boolean setBoneMatricesFlag = true;
 //            offsetMatrices = skeleton.computeSkinningMatrices();
             for(PMDGeometry g : pmdGeometryArray) {
                 Material m = g.getMaterial();
-                PMDMesh pmdMesh = g.pmdMesh;
+                PMDMesh pmdMesh = (PMDMesh)g.getMesh();
                 int boneIndexArray[] = pmdMesh.getBoneIndexArray();
                 Matrix4f[] boneMatrixArray = pmdMesh.getBoneMatrixArray();
                 for (int i = pmdMesh.getBoneIndexArray().length-1; i >=0; i--) {
@@ -217,6 +339,9 @@ boolean setBoneMatricesFlag = true;
         }
     }
     private void swapSkinMesh() {
+        if (skinTargets.length == 0) {
+            return;
+        }
         VertexBuffer vb = skinTargets[0].getBuffer(VertexBuffer.Type.Position);
         VertexBuffer nb = skinTargets[0].getBuffer(VertexBuffer.Type.Normal);
         skinTargets[0].skinvb2.setUpdateNeeded();
@@ -328,6 +453,9 @@ boolean setBoneMatricesFlag = true;
 //        mesh.updateBound();
     }
     public void updateSkinBackData() {
+        if (skinTargets.length == 0) {
+            return;
+        }
         PMDSkinMesh skinMesh = skinTargets[0];
         VertexBuffer vb = skinMesh.getSkinvb2(); //.getBuffer(Type.Position);
         FloatBuffer fvb = (FloatBuffer) vb.getData();
@@ -783,6 +911,11 @@ boolean setBoneMatricesFlag = true;
 
     @Override
     public PMDNode clone() {
+        Logger.getLogger(this.getClass().getName()).log(Level.INFO,"clone PMDNode "+pmdModel.getModelName());
+//        if (true) {
+//            PMDNode newPMDNode = (PMDNode)super.clone();
+//            return newPMDNode;
+//        }
         try {
             PMDNode newPMDNode = (PMDNode)super.clone();
 //            newPMDNode.pmdModel = pmdModel;
@@ -794,6 +927,7 @@ boolean setBoneMatricesFlag = true;
                 newBone.getLocalRotation().set(bone.getLocalRotation());
                 newBone.getLocalScale().set(bone.getLocalScale());
             }
+            newPMDNode.pmdGeometryArray = new PMDGeometry[pmdGeometryArray.length];
             newPMDNode.targets = new PMDMesh[targets.length];
             newPMDNode.skinTargets = new PMDSkinMesh[skinTargets.length];
             int meshCount=0;
@@ -804,9 +938,27 @@ boolean setBoneMatricesFlag = true;
                 if (sp instanceof PMDGeometry) {
                     Mesh mesh = ((Geometry)newSp).getMesh();
                     if (mesh instanceof PMDMesh) {
-                        pmdGeometryArray[meshCount] = (PMDGeometry)sp;
+                       newPMDNode.pmdGeometryArray[meshCount] = (PMDGeometry)sp;
                        newPMDNode.targets[meshCount++] = (PMDMesh)mesh;
                     } else if (mesh instanceof PMDSkinMesh) {
+                        mesh.setMode(Mesh.Mode.Triangles);
+                        if (skinMeshCount != 0) {
+                            PMDSkinMesh skinMesh = (PMDSkinMesh)mesh;
+                            PMDSkinMesh skinMesh0 = newPMDNode.skinTargets[0];
+                            skinMesh.setBuffer(skinMesh0.getBuffer(Type.Position));
+                            skinMesh.setSkinvb2(skinMesh0.getSkinvb2());
+                            skinMesh.setBuffer(skinMesh0.getBuffer(Type.Normal));
+                            skinMesh.setSkinnb2(skinMesh0.getSkinnb2());
+                            skinMesh.setBuffer(skinMesh0.getBuffer(Type.TexCoord));
+                        } else {
+                            PMDSkinMesh skinMesh = (PMDSkinMesh)mesh;
+                            PMDSkinMesh skinMesh0 = skinTargets[0];
+                            skinMesh.setBuffer(skinMesh0.getBuffer(Type.Position).clone());
+                            skinMesh.setSkinvb2(skinMesh0.getSkinvb2().clone());
+                            skinMesh.setBuffer(skinMesh0.getBuffer(Type.Normal).clone());
+                            skinMesh.setSkinnb2(skinMesh0.getSkinnb2().clone());
+                            skinMesh.setBuffer(skinMesh0.getBuffer(Type.TexCoord).clone());
+                        }
                         newPMDNode.skinTargets[skinMeshCount++] = (PMDSkinMesh)mesh;
                     }
                 }
@@ -815,6 +967,7 @@ boolean setBoneMatricesFlag = true;
             for(String skinName : skinMap.keySet()) {
                 Skin skin = skinMap.get(skinName);
                 skin = skin.clone();
+                skin.pmdNode = newPMDNode;
                 newPMDNode.skinMap.put(skinName, skin);
             }
             newPMDNode.skinArray = newPMDNode.skinMap.values().toArray(new Skin[newPMDNode.skinMap.size()]);
@@ -839,5 +992,16 @@ boolean setBoneMatricesFlag = true;
             throw new PMDException(ex);
         }
     }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        if (pmdModel != null) {
+            Logger.getLogger(this.getClass().getName()).log(Level.INFO,"finalize PMDNode "+pmdModel.getModelName());
+//            System.out.println("finalize PMDNode "+pmdModel.getModelName());
+        } else {
+            Logger.getLogger(this.getClass().getName()).log(Level.INFO,"finalize PMDNode");
+        }
+    }
     
 }
index 4e8d504..5b26385 100755 (executable)
@@ -31,11 +31,15 @@ package projectkyoto.jme3.mmd;
 
 import com.jme3.bounding.BoundingBox;
 import com.jme3.bounding.BoundingVolume;
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
 import com.jme3.math.Matrix4f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer;
 import com.jme3.util.BufferUtils;
+import java.io.IOException;
 import java.nio.FloatBuffer;
 
 /**
@@ -44,7 +48,7 @@ import java.nio.FloatBuffer;
  */
 public class PMDSkinMesh extends Mesh {
 
-    short boneIndexArray[];
+    int boneIndexArray[];
     Matrix4f boneMatrixArray[];
     VertexBuffer skinvb2;
     VertexBuffer skinnb2;
@@ -53,11 +57,11 @@ public class PMDSkinMesh extends Mesh {
         super();
     }
 
-    public short[] getBoneIndexArray() {
+    public int[] getBoneIndexArray() {
         return boneIndexArray;
     }
 
-    public void setBoneIndexArray(short[] boneIndexArray) {
+    public void setBoneIndexArray(int[] boneIndexArray) {
         this.boneIndexArray = boneIndexArray;
     }
 
@@ -119,4 +123,22 @@ public class PMDSkinMesh extends Mesh {
 
         return newMesh;
     }
+
+    @Override
+    public void read(JmeImporter im) throws IOException {
+        super.read(im);
+//        InputCapsule c = im.getCapsule(this);
+//        boneIndexArray = c.readIntArray("boneIndexArray", null);
+//        boneMatrixArray = new Matrix4f[boneIndexArray.length];
+//        for(int i=0;i<boneMatrixArray.length;i++) {
+//            boneMatrixArray[i] = new Matrix4f();
+//            boneMatrixArray[i].loadIdentity();
+//        }
+    }
+
+    @Override
+    public void write(JmeExporter ex) throws IOException {
+        
+        super.write(ex);
+    }
 }
diff --git a/src/projectkyoto/jme3/mmd/PmdUtil.java b/src/projectkyoto/jme3/mmd/PmdUtil.java
new file mode 100644 (file)
index 0000000..ef5db59
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package projectkyoto.jme3.mmd;
+
+import com.jme3.asset.AssetManager;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import projectkyoto.jme3.mmd.PMDLoaderGLSLSkinning2;
+import projectkyoto.jme3.mmd.PMDNode;
+import projectkyoto.mmd.file.PMDModel;
+import projectkyoto.mmd.file.util2.MeshConverter;
+
+/**
+ *
+ * @author kobayasi
+ */
+public class PmdUtil {
+    public static void output(MeshConverter mc) throws IOException {
+        ObjectOutputStream os = new ObjectOutputStream(
+                new BufferedOutputStream(
+                new FileOutputStream("/tmp/out.serial")));
+        os.writeObject(mc);
+        os.close();
+    }
+
+    public static MeshConverter input() throws IOException {
+        ObjectInputStream is = new ObjectInputStream(
+                new BufferedInputStream(
+                new FileInputStream("/tmp/out.serial")));
+        try {
+            return (MeshConverter) is.readObject();
+        } catch (ClassNotFoundException ex) {
+            throw new IOException("class not found.", ex);
+        } finally {
+            is.close();
+        }
+    }
+    public static PMDNode readNode(AssetManager assetManager, String folderName, ObjectInputStream is) {
+        try {
+            MeshConverter mc = (MeshConverter) is.readObject();
+            PMDLoaderGLSLSkinning2 loader = new PMDLoaderGLSLSkinning2(assetManager, mc);
+            loader.setFolderName(folderName);
+            return loader.createNode("model");
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        } catch (ClassNotFoundException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}
index 86b0ff5..fd1fb0f 100755 (executable)
  */
 package projectkyoto.jme3.mmd;
 
+import com.jme3.export.InputCapsule;
+import com.jme3.export.JmeExporter;
+import com.jme3.export.JmeImporter;
+import com.jme3.export.OutputCapsule;
+import com.jme3.export.Savable;
+import java.io.IOException;
 import projectkyoto.mmd.file.PMDSkinData;
 
 /**
  *
  * @author kobayasi
  */
-public class Skin implements Cloneable{
+public class Skin implements Cloneable, Savable{
 
     String skinName;
     float weight = 0f;
@@ -91,5 +97,19 @@ public class Skin implements Cloneable{
     protected Skin clone() throws CloneNotSupportedException {
         return (Skin)super.clone();
     }
-    
+
+    @Override
+    public void write(JmeExporter ex) throws IOException {
+        OutputCapsule c = ex.getCapsule(this);
+        c.write(skinName, "skinName", "");
+        c.write(weight, "weight", 0f);
+        
+    }
+
+    @Override
+    public void read(JmeImporter im) throws IOException {
+        InputCapsule c = im.getCapsule(this);
+        skinName = c.readString("skinName", "");
+        weight = c.readFloat("weight", 0f);
+    }
 }
index d6466cd..9e93141 100755 (executable)
@@ -118,8 +118,12 @@ public class IKControl extends AbstractControl{
                     Vector3f targetModelPos = tmpV2.set(ikBone.getModelSpacePosition());
                     boolean hizaFlag = pmdModel.getBoneList().getBones()[ikData.getIkChildBoneIndex()[boneCount]].isHiza();
                     if (hizaFlag) {
-                        hizaIK(ikData);
-                        break l2;
+                        if (ikData.getIkChainLength() < 2) {
+                            pmdModel.getBoneList().getBones()[ikData.getIkChildBoneIndex()[boneCount]].setHiza(false);
+                        } else {
+                            hizaIK(ikData);
+                            break l2;
+                        }
                     }
 //                    hizaFlag = false;
 //                    if (hizaFlag)
index 18ac7f1..475be86 100755 (executable)
@@ -137,18 +137,19 @@ public class PMDPhysicsWorld {
     }
 
     public void removePMDNode(PMDNode pmdNode) {
-        PMDRigidBody[] rigidBodyArray = rigidBodyMap.remove(pmdNode);
-        if (rigidBodyArray != null) {
-            for (PMDRigidBody rb : rigidBodyArray) {
-                physicsSpace.remove(rb);
-            }
-        }
         SixDofJoint[] constArray = constraintMap.remove(pmdNode);
         if (constArray != null) {
             for (SixDofJoint joint : constArray) {
                 physicsSpace.remove(joint);
             }
         }
+        PMDRigidBody[] rigidBodyArray = rigidBodyMap.remove(pmdNode);
+        if (rigidBodyArray != null) {
+            for (PMDRigidBody rb : rigidBodyArray) {
+                physicsSpace.remove(rb);
+            }
+        }
+        nodeRigidBodyArray = rigidBodyMap.values().toArray(new PMDRigidBody[rigidBodyMap.size()][]);
     }
     float[] buf = new float[3];
 
index 0fec652..3b491d9 100755 (executable)
@@ -80,8 +80,27 @@ public class PMDRigidBody extends PhysicsRigidBody {
         } else {
             centerFlag = false;
         }
+        if (bone != null) {
+            if (!isKinematic()) {
+                bone.setUseModelSpaceVectors(true);
+            }else {
+                bone.setUseModelSpaceVectors(false);
+            }
+        }
     }
 
+    @Override
+    public void setKinematic(boolean kinematic) {
+        super.setKinematic(kinematic);
+        if (bone != null) {
+            if (!isKinematic()) {
+                bone.setUseModelSpaceVectors(true);
+            }else {
+                bone.setUseModelSpaceVectors(false);
+            }
+        }
+    }
+    
     public void update() {
         if (isKinematic()) {
             updateFromBoneMatrix();
@@ -143,6 +162,9 @@ public class PMDRigidBody extends PhysicsRigidBody {
 //                System.out.println("updateToBoneMatrix:tmpV = "+tmpV);
 //                tmpV.addLocal(invPos);
 //                tmpQ.multLocal(invRot);
+                    bone.setUseModelSpaceVectors(false);
+                    bone.updateWorldVectors();
+                    bone.setUseModelSpaceVectors(true);
                     m2.toRotationMatrix(tmpMatrix3f);
                     bone.getModelSpaceRotation().fromRotationMatrix(tmpMatrix3f);
 //                    m2.toRotationQuat(bone.getModelSpaceRotation());
index 8a79845..15868c7 100755 (executable)
@@ -42,13 +42,13 @@ public class PhysicsControl extends AbstractControl {
 
     PMDNode pmdNode;
     PMDPhysicsWorld world;
-
+    public PhysicsControl() {
+        world = new PMDPhysicsWorld();
+    }
     public PhysicsControl(PMDNode pmdNode) {
         this.pmdNode = pmdNode;
         world = new PMDPhysicsWorld();
-//        world.init();
         world.addPMDNode(pmdNode);
-//        world.stepSimulation(1f);
     }
 
     @Override
index 8629c04..29b7d47 100644 (file)
@@ -6,6 +6,7 @@ package projectkyoto.jme3.mmd.vmd;
 
 import java.util.concurrent.Callable;
 import projectkyoto.jme3.mmd.PMDNode;
+import projectkyoto.jme3.mmd.nativebullet.PhysicsControl;
 import projectkyoto.jme3.mmd.vmd.VMDControl;
 import projectkyoto.mmd.file.VMDFile;
 
@@ -21,6 +22,10 @@ public class VMDCallable implements Callable<Void> {
         this.pmdNode = pmdNode;
         vmdControl = new VMDControl(pmdNode, vmdFile);
     }
+    public VMDCallable(PMDNode pmdNode, VMDFile vmdFile, PhysicsControl physicsControl, boolean addPmdNodeFlag) {
+        this.pmdNode = pmdNode;
+        vmdControl = new VMDControl(pmdNode, vmdFile, physicsControl, addPmdNodeFlag);
+    }
     
     public Void call() throws Exception {
         vmdControl.update(tpf);
index c12dbe7..d0d708b 100755 (executable)
@@ -83,25 +83,63 @@ public class VMDControl extends AbstractControl {
     float currentTime = 0f;
 
     public VMDControl(PMDNode pmdNode, VMDFile vmdFile) {
+        this(pmdNode, vmdFile, new PhysicsControl());
+    }
+    public VMDControl(PMDNode pmdNode, VMDFile vmdFile, PhysicsControl physicsControl) {
+        this(pmdNode, vmdFile, physicsControl,true);
+    }
+    public VMDControl(PMDNode pmdNode, VMDFile vmdFile, PhysicsControl physicsControl, boolean addPmdNodeFlag) {
         this.pmdNode = pmdNode;
         this.vmdFile = vmdFile;
-        initMotionMap();
-        physicsControl = new PhysicsControl(pmdNode);
+        this.physicsControl = physicsControl;
+        if (addPmdNodeFlag) {
+            physicsControl.getWorld().addPMDNode(pmdNode);
+        }
 //         physicsControl.getWorld().getPhysicsSpace().addTickListener(tl);
         ikControl = new IKControl(pmdNode);
         boneEnabled = new int[pmdNode.getSkeleton().getBoneCount()];
         for(int i=0;i<boneEnabled.length;i++) {
             boneEnabled[i] = 1;
         }
+        for(projectkyoto.mmd.file.PMDRigidBody rb : pmdNode.getPmdModel().getRigidBodyList().getRigidBodyArray()) {
+            if (rb.getRigidBodyType() != 0 && rb.getRelBoneIndex() != 0xffff) {
+                boneEnabled[rb.getRelBoneIndex()] = 0;
+            }
+        }
+        for(int i=0;i<pmdNode.getPmdModel().getBoneList().getBones().length;i++) {
+            int i2 = i;
+            for(;;) {
+                PMDBone bone = pmdNode.getPmdModel().getBoneList().getBones()[i2];
+                if (bone.getParentBoneIndex() == 0xffff) {
+                    break;
+                }
+                if (boneEnabled[i2] == 0) {
+//                    boneEnabled[i] = 0;
+                    break;
+                }
+                i2 = bone.getParentBoneIndex();
+            }
+        }
         for (PMDIKData ikData : pmdNode.getPmdModel().getIkList().getPmdIKData()) {
             int targetBoneIndex = ikData.getIkTargetBoneIndex();
             for(projectkyoto.mmd.file.PMDRigidBody rb : pmdNode.getPmdModel().getRigidBodyList().getRigidBodyArray()) {
-                if (rb.getRelBoneIndex() == targetBoneIndex && rb.getRigidBodyType() != 0) {
+                if ((rb.getRelBoneIndex() == targetBoneIndex && rb.getRigidBodyType() != 0)
+                        || boneEnabled[targetBoneIndex] == 0) {
                     boneEnabled[targetBoneIndex] = 0;
+                    boneEnabled[ikData.getIkBoneIndex()] = 0;
+                    for(int i:ikData.getIkChildBoneIndex()) {
+//                        boneEnabled[i] = 0;
+                    }
                     break;
                 }
             }
         }
+        for(int i=0;i<pmdNode.getPmdModel().getBoneList().getBones().length;i++) {
+            PMDBone bone = pmdNode.getPmdModel().getBoneList().getBones()[i];
+//            if (bone.getBoneName().indexOf("胸") >=0) {
+//                System.out.println(bone.getBoneName()+" "+boneEnabled[i]);
+//            }
+        }
         ikControl.setBoneEnabled(boneEnabled);
         for(int i=pmdNode.getSkeleton().getBoneCount()-1;i>=0;i--) {
             if (boneEnabled[i] == 1) {
@@ -109,6 +147,7 @@ public class VMDControl extends AbstractControl {
                 bone.setUserControl(true);
             }
         }
+        initMotionMap();
     }
 
     private void initMotionMap() {
@@ -148,6 +187,11 @@ public class VMDControl extends AbstractControl {
                 }
             }
         }
+        for(int i=0;i<boneEnabled.length;i++) {
+            if (boneEnabled[i] == 0) {
+                motionMap.remove(pmdNode.getPmdModel().getBoneList().getBones()[i].getBoneName());
+            }
+        }
         for (BoneMotionList ml : motionMap.values()) {
             Collections.sort(ml, vmc);
             ml.setCurrentCount(0);
@@ -173,6 +217,9 @@ public class VMDControl extends AbstractControl {
     }
     Quat4f tmpq1 = new Quat4f();
     Quat4f tmpq2 = new Quat4f();
+    Quat4f tmpq3 = new Quat4f();
+    Quaternion tmpq4 = new Quaternion();
+    Quaternion tmpq5 = new Quaternion();
     Point3f tmpp1 = new Point3f();
     Point3f tmpp2 = new Point3f();
     float prevTpf = 0;
@@ -236,7 +283,9 @@ public class VMDControl extends AbstractControl {
                 physicsControl.getWorld().getPhysicsSpace().distributeEvents();
                 needUpdateSkin = true;
             }
+//            System.out.println("X = "+pmdNode.getSkeleton().getBone("前髪").getModelSpacePosition().getX());
             physicsControl.getWorld().applyResultToBone();
+//            pmdNode.getSkeleton().updateWorldVectors();
             prevTpf = tpf;
             if (needUpdateSkin) {
                 resetSkins();
@@ -271,7 +320,11 @@ public class VMDControl extends AbstractControl {
 
     void calcBonePosition() {
         for(int i=pmdNode.getSkeleton().getBoneCount()-1;i>=0;i--) {
-            if (boneEnabled[i] == 1) {
+            int i2 = i; //boneEnabled.length -1 - i;
+            if (boneEnabled[i2] == 1) {
+                if (!pmdNode.getSkeleton().getBone(i).getName().equals(pmdNode.getPmdModel().getBoneList().getBones()[i2].getBoneName())) {
+                    System.out.println("ERROR "+pmdNode.getSkeleton().getBone(i).getName()+" "+pmdNode.getPmdModel().getBoneList().getBones()[i2].getBoneName());
+                }
                 Bone bone = pmdNode.getSkeleton().getBone(i);
                 bone.getLocalRotation().loadIdentity();
             }
@@ -327,11 +380,17 @@ public class VMDControl extends AbstractControl {
                         float f2 = currentTime - m1.getFrameNo() / 30f;
                         assert (f2 >= 0);
                         float f3 = f2 / f;
+                        assert (f3 >= 0 && f3 <= 1);
                         float fx = IPUtil.calcIp(bml, f3, 0);//calcIp(m2.getInterpolation(), f3, 0);
                         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);
-                        tmpq1.interpolate(m1.getRotation(), m2.getRotation(), fr);
+                        tmpq4.set(m1.getRotation().x,m1.getRotation().y,m1.getRotation().z,m1.getRotation().w);
+                        tmpq4.normalizeLocal();
+                        tmpq5.set(m2.getRotation().x,m2.getRotation().y,m2.getRotation().z,m2.getRotation().w);
+                        tmpq5.normalizeLocal();
+                        tmpq4.slerp(tmpq5, fr);
+                        tmpq1.set(tmpq4.getX(),tmpq4.getY(),tmpq4.getZ(),tmpq4.getW());
                         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;
index 871bd1e..c8360de 100644 (file)
@@ -15,6 +15,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import projectkyoto.jme3.mmd.PMDNode;
+import projectkyoto.jme3.mmd.nativebullet.PhysicsControl;
 import projectkyoto.jme3.mmd.vmd.VMDControl;
 import projectkyoto.mmd.file.PMDModel;
 import projectkyoto.mmd.file.VMDFile;
@@ -35,9 +36,22 @@ public class VMDControlMT extends AbstractControl {
         callable = new VMDCallable(pmdNode, vmdFile);
         this.pmdNode = pmdNode;
     }
+    public VMDControlMT(ScheduledThreadPoolExecutor executor, PMDNode pmdNode, VMDFile vmdFile, PhysicsControl physicsControl) {
+        this(executor, pmdNode, vmdFile, physicsControl, true);
+    }
+    public VMDControlMT(ScheduledThreadPoolExecutor executor, PMDNode pmdNode, VMDFile vmdFile, PhysicsControl physicsControl, boolean addPmdNodeFlag) {
+        this.executor = executor;
+        callable = new VMDCallable(pmdNode, vmdFile, physicsControl, addPmdNodeFlag);
+        this.pmdNode = pmdNode;
+    }
 
     @Override
     protected void controlUpdate(float f) {
+        sync();
+        callable.setTpf(f);
+        future = executor.submit(callable);
+    }
+    public synchronized void sync() {
         if (future != null) {
             try {
                 future.get();
@@ -51,10 +65,7 @@ public class VMDControlMT extends AbstractControl {
                 future = null;
             }
         }
-        callable.setTpf(f);
-        future = executor.submit(callable);
     }
-
     public VMDCallable getCallable() {
         return callable;
     }
@@ -66,4 +77,22 @@ public class VMDControlMT extends AbstractControl {
     public Control cloneForSpatial(Spatial sptl) {
         throw new UnsupportedOperationException("Not supported yet.");
     }
+
+    @Override
+    public void setSpatial(Spatial spatial) {
+        super.setSpatial(spatial);
+        if (spatial == null) {
+            Logger.getLogger(VMDControlMT.class.getName()).log(Level.INFO,"remove");
+            if (future != null) {
+                try {
+                    future.get();
+                } catch (InterruptedException ex) {
+                    Logger.getLogger(VMDControlMT.class.getName()).log(Level.SEVERE, null, ex);
+                } catch (ExecutionException ex) {
+                    Logger.getLogger(VMDControlMT.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+//            callable.vmdControl.getPhysicsControl().getWorld().removePMDNode(pmdNode);
+        }
+    }
 }
index aa8b2f9..826f905 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class Coords2d {
+public class Coords2d implements Serializable{
     private float u;
     private float v;
 
index fb79f94..bd15c00 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 import javax.vecmath.Vector3f;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class PMDBone {
+public class PMDBone implements Serializable{
 
     private String boneName;
     private int parentBoneIndex;
index 7fb80e3..b0b221d 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDBoneDisp {
+public class PMDBoneDisp implements Serializable{
     private int boneIndex;
     private int boneDispFrameIndex;
     public PMDBoneDisp(DataInputStreamLittleEndian is) throws IOException {
index 474c956..64c4ab9 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDBoneDispList {
+public class PMDBoneDispList implements Serializable{
     private int boneDispCount;
     private PMDBoneDisp boneDispArray[];
     public PMDBoneDispList(DataInputStreamLittleEndian is) throws IOException {
index 65e5bae..486a124 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDBoneDispNameList {
+public class PMDBoneDispNameList implements Serializable{
     private int boneDispNameCount;
     private String[] dispNameArray;
     public PMDBoneDispNameList(DataInputStreamLittleEndian is) throws IOException {
index d52ea33..2cb9544 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class PMDBoneList {
+public class PMDBoneList implements Serializable{
     private int boneCount;
     private PMDBone[] bones;
     public PMDBoneList(DataInputStreamLittleEndian is) throws IOException {
index 17d274b..64c0277 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDHeaderEnglish {
+public class PMDHeaderEnglish implements Serializable{
 
     private int englishNameCompatibility;
     private String modelName;
index 38ba39b..39ad808 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDIKData {
+public class PMDIKData implements Serializable{
     private int ikBoneIndex;
     private int ikTargetBoneIndex;
     private int ikChainLength;
index 540604e..a6c8a84 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDIKList {
+public class PMDIKList implements Serializable{
     private int ikDataCount;
     private PMDIKData pmdIKData[];
     public PMDIKList(DataInputStreamLittleEndian is) throws IOException {
index fae39c5..da276f1 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 import javax.vecmath.Vector3f;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDJoint {
+public class PMDJoint implements Serializable{
 
     private String jointName;
     private int rigidBodyA;
index 1c0136d..c906c04 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDJointList {
+public class PMDJointList implements Serializable{
     private int jointCount;
     private PMDJoint jointArray[];
 
+    public PMDJointList() {
+        jointCount = 0;
+        jointArray = new PMDJoint[0];
+    }
+
     public PMDJointList(DataInputStreamLittleEndian is) throws IOException {
         jointCount = is.readInt();
         jointArray = new PMDJoint[jointCount];
index ed6a2dc..42ba691 100755 (executable)
@@ -34,13 +34,14 @@ package projectkyoto.mmd.file;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.net.URL;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class PMDMaterial {
+public class PMDMaterial implements Serializable{
     private XMaterial material;
     private byte toonIndex;
     private byte edgeFlag;
index 0782a1b..222ea9d 100755 (executable)
@@ -32,13 +32,14 @@ package projectkyoto.mmd.file;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.net.URL;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class PMDModel {
+public class PMDModel implements Serializable{
     // PMD Header
 
     private String id; // char[3] "Pmd"
@@ -136,7 +137,9 @@ public class PMDModel {
         toonTextureList = new PMDToonTextureList(is);
         rigidBodyList = new PMDRigidBodyList(is);
         jointList = new PMDJointList(is);
-
+//        toonTextureList = new PMDToonTextureList();
+//        rigidBodyList = new PMDRigidBodyList();
+//        jointList = new PMDJointList();
     }
 
     @Override
index 07cfb1d..d9f1fdb 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 import javax.vecmath.Vector3f;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDRigidBody {
+public class PMDRigidBody implements Serializable{
     private String rigidBodyName;
     private int relBoneIndex;
     private int rigidBodyGroupIndex;
index a9444c9..cc9dbb7 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDRigidBodyList {
+public class PMDRigidBodyList implements Serializable{
 
     private int rigidBodyCount;
     private PMDRigidBody[] rigidBodyArray;
 
+    public PMDRigidBodyList() {
+        rigidBodyCount = 0;
+        rigidBodyArray = new PMDRigidBody[0];
+    }
+
     public PMDRigidBodyList(DataInputStreamLittleEndian is) throws IOException {
         rigidBodyCount = is.readInt();
         rigidBodyArray = new PMDRigidBody[rigidBodyCount];
index ba97d26..8b8b4d8 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDSkinData {
+public class PMDSkinData implements Serializable{
     private String skinName; //20文字
     private int skinVertCount;
     private int skinType; // byte
index 78131e1..ae5ce36 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDSkinDispList {
+public class PMDSkinDispList implements Serializable{
     private int skinDispCount;
     private short skinIndexArray[];
     public PMDSkinDispList(DataInputStreamLittleEndian is) throws IOException {
index 4c5cac4..8e5f2f6 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 import javax.vecmath.Vector3f;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDSkinVertData {
+public class PMDSkinVertData implements Serializable{
     private int skinVertIndex;
     private Vector3f skinVertPos;
 
index 951258f..6a1d4af 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class PMDToonTextureList {
+public class PMDToonTextureList implements Serializable{
     private String toonFileName[] = new String[10];
+
+    public PMDToonTextureList() {
+        for(int i=0;i<10;i++) {
+            toonFileName[i] = "";
+        }
+    }
+    
     public PMDToonTextureList(DataInputStreamLittleEndian is) throws IOException {
         for(int i=0;i<10;i++) {
             toonFileName[i] = is.readString(100);
index 32f680c..9acd8c6 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 import javax.vecmath.Vector3f;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class PMDVertex {
+public class PMDVertex implements Serializable{
 
     private Vector3f pos; // 位置
     private Vector3f normal; // 法線
index d5da368..c126ba7 100755 (executable)
@@ -35,13 +35,14 @@ package projectkyoto.mmd.file;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.net.URL;
 
 /**
  *
  * @author kobayasi
  */
-public class VMDFile {
+public class VMDFile implements Serializable{
     private String vmdHeader; // char[30] Vocaloid Motion Data 0002
     private String vmdModelName; // char[20]
     private int motionCount;
index 23005a5..9ca0f51 100755 (executable)
@@ -33,6 +33,7 @@
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 import javax.vecmath.Point3f;
 import javax.vecmath.Quat4f;
 
@@ -40,7 +41,7 @@ import javax.vecmath.Quat4f;
  *
  * @author kobayasi
  */
-public class VMDMotion {
+public class VMDMotion implements Serializable{
 
     private String boneName; // char[15]
     private int frameNo;
index a433521..3c5c89f 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author kobayasi
  */
-public class VMDSkin {
+public class VMDSkin implements Serializable{
 
     private String skinName; // char[15]
     private int flameNo;
index f08d0b7..ea02003 100755 (executable)
@@ -33,6 +33,7 @@
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /*
  * To change this template, choose Tools | Templates
@@ -43,7 +44,7 @@ import java.io.IOException;
  *
  * @author Kazuhiko Kobayashi
  */
-public class XColorRGB {
+public class XColorRGB implements Serializable{
     private float red;
     private float green;
     private float blue;
index 1dfa301..40774f1 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class XColorRGBA extends XColorRGB {
+public class XColorRGBA extends XColorRGB implements Serializable{
 
     private float alpha;
 
index 0f932ff..97b257d 100755 (executable)
 package projectkyoto.mmd.file;
 
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  *
  * @author Kazuhiko Kobayashi
  */
-public class XMaterial {
+public class XMaterial implements Serializable{
     private XColorRGBA faceColor;
     private float power;
     private XColorRGB specularColor;
index 6371958..1200470 100755 (executable)
@@ -32,6 +32,7 @@
 
 package projectkyoto.mmd.file.util2;
 
+import java.io.Serializable;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -48,10 +49,11 @@ import projectkyoto.mmd.file.PMDVertex;
  *
  * @author kobayasi
  */
-public class MeshConverter {
+public class MeshConverter implements Serializable{
 
     PMDModel model;
-    int maxBoneSize = 20;
+    public static int DEFAULT_MAX_BONE_SIZE = 20;
+    int maxBoneSize = DEFAULT_MAX_BONE_SIZE;
     List<MeshData> meshDataList = new ArrayList<MeshData>();
     SkinMeshData skinMeshData;
     HashMap<PMDVertex, Integer> meshTmpVertMap = new HashMap<PMDVertex, Integer>();
@@ -92,6 +94,7 @@ public class MeshConverter {
     public void convertMesh() {
         int faceVertNo = 0;
         for (int materialNo = 0; materialNo < model.getMaterialCount(); materialNo++) {
+            meshTmpVertMap.clear();
             PMDMaterial material = model.getMaterial()[materialNo];
             // find same material
             MeshData meshData = new MeshData(model, maxBoneSize, material);
@@ -131,26 +134,8 @@ public class MeshConverter {
                 meshDataList.remove(meshDataList.size()-1);
             }
         }
-        int vertSizeSum = 0;
-        int boneSizeSum = 0;
-        int indexSizeSum = 0;
-//        System.out.println("material size " + model.getMaterialCount() + " " + meshDataList.size());
-        for (MeshData meshData : meshDataList) {
-            vertSizeSum += meshData.getVertexList().size();
-            boneSizeSum += meshData.getBoneList().size();
-            indexSizeSum += meshData.getIndexList().size();
-//            printMeshData(meshData);
-//            System.out.println("mesh size = "+meshData.vertexList.size());
-        }
-//        System.out.println("-----------------------skin");
-//        System.out.println("index " + model.getFaceVertCount() + " " + indexSizeSum
-//                + " vertSizeSum = " + model.getVertCount() + " " + vertSizeSum
-//                + " boneSizeSum = " + model.getBoneList().getBoneCount() + " " + boneSizeSum);
-//        printFaceVertSize();
-        for(MeshData meshData : meshDataList) {
-//            meshData.printTrinangles();
-        }
-        System.out.println("meshDataCount = "+meshDataList.size());
+        meshTmpVertMap = null;
+        skinTmpVertMap = null;
     }
     void printMeshData(MeshData meshData) {
             System.out.println("vertSize = " + meshData.getVertexList().size()
@@ -222,7 +207,7 @@ public class MeshConverter {
     }
     
 }
-class VertIndex {
+class VertIndex implements Serializable{
     int index;
 
     public VertIndex(int index) {
diff --git a/src/projectkyoto/mmd/file/util2/SavableUtil.java b/src/projectkyoto/mmd/file/util2/SavableUtil.java
new file mode 100644 (file)
index 0000000..d590330
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package projectkyoto.mmd.file.util2;
+
+import com.jme3.export.InputCapsule;
+import com.jme3.export.OutputCapsule;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author kobayasi
+ */
+public class SavableUtil {
+    
+    public static void write(OutputCapsule c, Serializable obj, String name) {
+        ObjectOutputStream oos = null;
+        try {
+            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            oos = new ObjectOutputStream(os);
+            oos.writeObject(obj);
+            oos.close();
+            byte buf[] = os.toByteArray();
+            c.write(buf, name, null);
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+    public static Object read(InputCapsule c, String name, Object defVal) {
+        try {
+            byte[] buf = c.readByteArray(name, null);
+            if (buf != null) {
+                ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(buf));
+                return is.readObject();
+            }        
+            return defVal;
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}
index 057579a..2f2b4b8 100755 (executable)
@@ -32,6 +32,7 @@
 
 package projectkyoto.mmd.file.util2;
 
+import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -45,7 +46,7 @@ import projectkyoto.mmd.file.PMDVertex;
  *
  * @author kobayasi
  */
-public class SkinMeshData {
+public class SkinMeshData implements Serializable{
 
     PMDModel model;
     List<Integer> boneList = new ArrayList<Integer>();