OSDN Git Service

use Material#setParam(int paramIndex, VarType type, Object value)
[mikumikustudio/MikuMikuStudio.git] / src / projectkyoto / jme3 / mmd / PMDNode.java
1 /*
2  * Copyright (c) 2011 Kazuhiko Kobayashi All rights reserved.
3  * <p/>
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * 
7  * * Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * <p/>
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * <p/>
14  * * Neither the name of 'MMDLoaderJME' nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  * <p/>
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 package projectkyoto.jme3.mmd;
31
32 import com.jme3.animation.Bone;
33 import com.jme3.animation.Skeleton;
34 import com.jme3.asset.AssetManager;
35 import com.jme3.material.Material;
36 import com.jme3.math.ColorRGBA;
37 import com.jme3.math.FastMath;
38 import com.jme3.math.Matrix4f;
39 import com.jme3.math.Quaternion;
40 import com.jme3.math.Vector3f;
41 import com.jme3.renderer.queue.RenderQueue.Bucket;
42 import com.jme3.scene.Geometry;
43 import com.jme3.scene.Mesh;
44 import com.jme3.scene.Node;
45 import com.jme3.scene.Spatial;
46 import com.jme3.scene.VertexBuffer;
47 import com.jme3.util.TempVars;
48 import java.nio.FloatBuffer;
49 import projectkyoto.mmd.file.PMDModel;
50 import com.jme3.scene.VertexBuffer.*;
51 import com.jme3.scene.control.BillboardControl;
52 import com.jme3.scene.debug.SkeletonWire;
53 import com.jme3.scene.shape.Box;
54 import com.jme3.shader.VarType;
55 import java.nio.ShortBuffer;
56 import java.util.Arrays;
57 import java.util.HashMap;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.Set;
61 import projectkyoto.mmd.file.PMDBone;
62 import projectkyoto.mmd.file.PMDException;
63 import projectkyoto.mmd.file.PMDSkinVertData;
64 import projectkyoto.mmd.file.PMDVertex;
65
66 /**
67  *
68  * @author kobayasi
69  */
70 public class PMDNode extends Node {
71
72     PMDModel pmdModel;
73     Skeleton skeleton;
74     PMDMesh[] targets;
75     PMDSkinMesh[] skinTargets;
76     PMDGeometry[] pmdGeometryArray;
77     Map<String, Skin> skinMap = new HashMap<String, Skin>();
78     Skin[] skinArray = new Skin[0];
79     javax.vecmath.Vector3f skinPosArray[];
80     javax.vecmath.Vector3f skinNormalArray[];
81     javax.vecmath.Vector3f skinPosArrayOrig[];
82     javax.vecmath.Vector3f skinNormalArrayOrig[];
83     float skinBoneWeightArray[];
84     int skinBoneArray[];
85     AssetManager assetManager;
86     Matrix4f[] offsetMatrices;
87     boolean updateNeeded = true;
88     boolean skinUpdateNeeded = true;
89     boolean wireFrame = false;
90     float edgeSize = 1.0f;
91     boolean skeletonWireVisible = false;
92     Geometry skeletonWireGeom;
93     boolean bonePositionVisible = false;
94     Node bonePositionNode;
95     Geometry bonePositionGeomArray[];
96     Node rigidBodyNode;
97     Node jointNode;
98     boolean glslSkinning = true;
99
100     public PMDNode(String name, PMDModel pmdModel, AssetManager assetManager) {
101         super(name);
102         this.pmdModel = pmdModel;
103         this.assetManager = assetManager;
104     }
105
106     public PMDNode() {
107     }
108
109     public void init() {
110 //        initBtWorld();
111 //        initRigidBodyArray();
112         initMaterials();
113         resetToBind();
114     }
115
116     void setSkinData(PMDSkinMesh[] skinTargets, List<PMDVertex> skinVertexList, Skin[] skinAray) {
117         this.skinTargets = skinTargets;
118         for (Skin skin : skinAray) {
119             skinMap.put(skin.getSkinName(), skin);
120         }
121         int skinVertSize = skinVertexList.size();
122         skinPosArray = new javax.vecmath.Vector3f[skinVertSize];
123         skinNormalArray = new javax.vecmath.Vector3f[skinVertSize];
124         skinPosArrayOrig = new javax.vecmath.Vector3f[skinVertSize];
125         skinNormalArrayOrig = new javax.vecmath.Vector3f[skinVertSize];
126         skinBoneWeightArray = new float[skinVertSize];
127         skinBoneArray = new int[skinVertSize * 2];
128         for (int i = 0; i < skinVertSize; i++) {
129             PMDVertex v = skinVertexList.get(i);
130             skinPosArrayOrig[i] = v.getPos();
131             skinPosArray[i] = new javax.vecmath.Vector3f(v.getPos());
132             skinNormalArrayOrig[i] = v.getNormal();
133             skinNormalArray[i] = new javax.vecmath.Vector3f(v.getNormal());
134             skinBoneWeightArray[i] = (float) v.getBoneWeight() / 100f;
135             skinBoneArray[i * 2] = v.getBoneNum1();
136             skinBoneArray[i * 2 + 1] = v.getBoneNum2();
137         }
138     }
139
140     public PMDModel getPmdModel() {
141         return pmdModel;
142     }
143
144     public void setPmdModel(PMDModel pmdModel) {
145         this.pmdModel = pmdModel;
146     }
147
148     public Matrix4f[] calcOffsetMatrices() {
149         offsetMatrices = skeleton.computeSkinningMatrices();
150         return offsetMatrices;
151     }
152 boolean setBoneMatricesFlag = true;
153     public void update() {
154 //        skeleton.reset(); // reset skeleton to bind pose
155         if (true /*
156                  * updateNeeded
157                  */) {
158             updateNeeded = false;
159 //            skeleton.updateWorldVectors();
160 //            updateIKBoneRotation();
161             // here update the targets verticles if no hardware skinning supported
162
163 //            offsetMatrices = skeleton.computeSkinningMatrices();
164             for(PMDGeometry g : pmdGeometryArray) {
165                 Material m = g.getMaterial();
166                 PMDMesh pmdMesh = g.pmdMesh;
167                 int boneIndexArray[] = pmdMesh.getBoneIndexArray();
168                 Matrix4f[] boneMatrixArray = pmdMesh.getBoneMatrixArray();
169                 for (int i = pmdMesh.getBoneIndexArray().length-1; i >=0; i--) {
170                     boneMatrixArray[i] = (offsetMatrices[boneIndexArray[i]]);
171                 }
172                 if (glslSkinning) {
173                     if (pmdMesh.boneMatricesParamIndex < 0) {
174                         m.setParam("BoneMatrices", VarType.Matrix4Array, pmdMesh.getBoneMatrixArray());
175                         pmdMesh.boneMatricesParamIndex = g.getMaterial().getParamIndex("BoneMatrices");
176                     } else {
177                         m.setParam(pmdMesh.boneMatricesParamIndex, VarType.Matrix4Array, pmdMesh.getBoneMatrixArray());
178                     }
179                 }
180             }
181             
182             if (!glslSkinning) {
183                 for (PMDMesh mesh : targets) {
184                     softwareSkinUpdate(mesh);
185                 }
186             }
187 //            updateSkinMesh(skinTargets[0]);
188 //            if (skinUpdateNeeded) {
189 //                updateSkinBackData();
190 //            }
191             swapSkinMesh();
192             if (skeletonWireGeom != null) {
193                 ((SkeletonWire) skeletonWireGeom.getMesh()).updateGeometry();
194             }
195             if (bonePositionVisible) {
196                 for (int i = 0; i < bonePositionGeomArray.length; i++) {
197                     Geometry bonePosGeom = bonePositionGeomArray[i];
198 //                    Mesh mesh = bonePosGeom.getMesh();
199 //                    VertexBuffer vb = mesh.getBuffer(Type.Position);
200 //                    FloatBuffer posBuf = (FloatBuffer)vb.getData();
201 //                    posBuf.clear();
202                     Bone bone = skeleton.getBone(i);
203                     Vector3f bonePos = bone.getModelSpacePosition();
204 //                    posBuf.position(0);
205 //                    posBuf.put(bonePos.x);
206 //                    posBuf.put(bonePos.y);
207 //                    posBuf.put(bonePos.z);
208 //                    vb.setUpdateNeeded();
209 //                    mesh.updateCounts();
210 //                    mesh.updateBound();
211 //                    bonePosGeom.setModelBound(new BoundingBox(bonePos, 10f,10f,10f));
212 //                    bonePosGeom.updateModelBound();
213 //                    bonePosGeom.setMesh(new Box(bonePos, 0.1f,0.1f,0.1f));
214                     bonePosGeom.setLocalTranslation(bonePos);
215                 }
216             }
217         }
218     }
219     private void swapSkinMesh() {
220         VertexBuffer vb = skinTargets[0].getBuffer(VertexBuffer.Type.Position);
221         VertexBuffer nb = skinTargets[0].getBuffer(VertexBuffer.Type.Normal);
222         skinTargets[0].skinvb2.setUpdateNeeded();
223         skinTargets[0].skinnb2.setUpdateNeeded();
224         for(PMDSkinMesh skinMesh : skinTargets) {
225 //            skinMesh.clearBuffer(Type.Position);
226 //            skinMesh.clearBuffer(Type.Normal);
227             skinMesh.setBuffer(skinTargets[0].getSkinvb2());
228             skinMesh.setBuffer(skinTargets[0].getSkinnb2());
229         }
230         skinTargets[0].skinvb2 = vb;
231         skinTargets[0].skinnb2 = nb;
232         vb = skinTargets[0].getBuffer(VertexBuffer.Type.Position);
233         nb = skinTargets[0].getBuffer(VertexBuffer.Type.Normal);
234         vb.setUpdateNeeded();
235         nb.setUpdateNeeded();
236     }
237     private void softwareSkinUpdate(PMDMesh mesh){
238         int maxWeightsPerVert = 2;//mesh.getMaxNumWeights();
239         int fourMinusMaxWeights = 4 - maxWeightsPerVert;
240 //        Matrix4f[] offsetMatrices = mesh.getBoneMatrixArray();
241
242         // NOTE: This code assumes the vertex buffer is in bind pose
243         // resetToBind() has been called this frame
244         resetToBind(mesh);
245         VertexBuffer vb = mesh.getBuffer(VertexBuffer.Type.Position);
246         FloatBuffer fvb = (FloatBuffer) vb.getData();
247         fvb.rewind();
248
249         VertexBuffer nb = mesh.getBuffer(VertexBuffer.Type.Normal);
250         FloatBuffer fnb = (FloatBuffer) nb.getData();
251         fnb.rewind();
252         
253         FloatBuffer fvb2 = (FloatBuffer)mesh.getVbBackup().getData();
254         fvb2.rewind();
255         FloatBuffer fnb2 = (FloatBuffer)mesh.getNbBackup().getData();
256         fnb2.rewind();
257         
258         // get boneIndexes and weights for mesh
259         ShortBuffer ib = (ShortBuffer) mesh.getBuffer(VertexBuffer.Type.BoneIndex).getData();
260         FloatBuffer wb = (FloatBuffer) mesh.getBuffer(VertexBuffer.Type.BoneWeight).getData();
261
262         ib.rewind();
263         wb.rewind();
264
265 //        float[] weights = wb.array();
266 //        short[] indices = ib.array();
267         int idxWeights = 0;
268
269         TempVars vars = TempVars.get();
270         float[] posBuf = vars.skinPositions;
271         float[] normBuf = vars.skinNormals;
272
273         int iterations = (int) FastMath.ceil(fvb.capacity() / ((float)posBuf.length));
274         int bufLength = posBuf.length * 3;
275         for (int i = iterations-1; i >= 0; i--){
276             // read next set of positions and normals from native buffer
277             bufLength = Math.min(posBuf.length, fvb.remaining());
278             fvb2.get(posBuf, 0, bufLength);
279             fnb2.get(normBuf, 0, bufLength);
280             int verts = bufLength / 3;
281             int idxPositions = 0;
282
283             // iterate vertices and apply skinning transform for each effecting bone
284             for (int vert = verts - 1; vert >= 0; vert--){
285                 float nmx = normBuf[idxPositions];
286                 float vtx = posBuf[idxPositions++];
287                 float nmy = normBuf[idxPositions];
288                 float vty = posBuf[idxPositions++];
289                 float nmz = normBuf[idxPositions];
290                 float vtz = posBuf[idxPositions++];
291
292                 float rx=0, ry=0, rz=0, rnx=0, rny=0, rnz=0;
293
294                 for (int w = maxWeightsPerVert - 1; w >= 0; w--){
295                     float weight = wb.get(idxWeights); //weights[idxWeights];
296                     Matrix4f mat = mesh.getBoneMatrixArray()[ib.get(idxWeights++)];//offsetMatrices[indices[idxWeights++]];
297
298                     rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
299                     ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
300                     rz += (mat.m20 * vtx + mat.m21 * vty + mat.m22 * vtz + mat.m23) * weight;
301
302                     rnx += (nmx * mat.m00 + nmy * mat.m01 + nmz * mat.m02) * weight;
303                     rny += (nmx * mat.m10 + nmy * mat.m11 + nmz * mat.m12) * weight;
304                     rnz += (nmx * mat.m20 + nmy * mat.m21 + nmz * mat.m22) * weight;
305                 }
306
307                 idxWeights += fourMinusMaxWeights;
308
309                 idxPositions -= 3;
310                 normBuf[idxPositions] = rnx;
311                 posBuf[idxPositions++] = rx;
312                 normBuf[idxPositions] = rny;
313                 posBuf[idxPositions++] = ry;
314                 normBuf[idxPositions] = rnz;
315                 posBuf[idxPositions++] = rz;
316             }
317
318
319 //            fvb.position(fvb2.position()-bufLength);
320             fvb.put(posBuf, 0, bufLength);
321 //            fnb.position(fnb2.position()-bufLength);
322             fnb.put(normBuf, 0, bufLength);
323         }
324         vb.setUpdateNeeded();
325         nb.setUpdateNeeded();
326         vars.release();
327         
328 //        mesh.updateBound();
329     }
330     public void updateSkinBackData() {
331         PMDSkinMesh skinMesh = skinTargets[0];
332         VertexBuffer vb = skinMesh.getSkinvb2(); //.getBuffer(Type.Position);
333         FloatBuffer fvb = (FloatBuffer) vb.getData();
334         VertexBuffer nb = skinMesh.getSkinnb2(); //skinMesh.getBuffer(Type.Normal);
335         FloatBuffer fnb = (FloatBuffer) nb.getData();
336
337         for(int i=skinPosArray.length-1;i>=0;i--) {
338             skinPosArray[i].set(skinPosArrayOrig[i]);
339         }
340         for (Skin skin : skinArray) {
341             if (true || skin.isUpdateNeeded()) {
342                 if (skin.getWeight() != 0f) {
343                     for (PMDSkinVertData svd : skin.getSkinData().getSkinVertData()) {
344                         javax.vecmath.Vector3f dist = skinPosArray[svd.getSkinVertIndex()];
345                         dist.set(svd.getSkinVertPos());
346                         dist.scale(skin.getWeight());
347                         dist.add(skinPosArrayOrig[svd.getSkinVertIndex()]);
348                     }
349                 }
350                 skin.setUpdateNeeded(false);
351             }
352         }
353
354         fvb.position(0);
355         fnb.position(0);
356         TempVars vars = TempVars.get();
357         for (int i = 0; i < skinPosArray.length; i++) {
358             int idxWeights = 0;
359
360             float[] posBuf = vars.skinPositions;
361             float[] normBuf = vars.skinNormals;
362
363             // read next set of positions and normals from native buffer
364             int idxPositions = 0;
365
366             // iterate vertices and apply skinning transform for each effecting bone
367             float nmx = skinNormalArray[i].x;//normBuf[idxPositions];
368             float vtx = skinPosArray[i].x;//posBuf[idxPositions++];
369             float nmy = skinNormalArray[i].y;//normBuf[idxPositions];
370             float vty = skinPosArray[i].y;//posBuf[idxPositions++];
371             float nmz = skinNormalArray[i].z;//normBuf[idxPositions];
372             float vtz = skinPosArray[i].z;//posBuf[idxPositions++];
373
374             float rx = 0, ry = 0, rz = 0, rnx = 0, rny = 0, rnz = 0;
375
376             for (int w = 2 - 1; w >= 0; w--) {
377                 float weight = skinBoneWeightArray[i];//(float) v.getBoneWeight();//weights[idxWeights];
378                 if (w == 1) {
379                     weight = 1f - weight;
380                 }
381                 //weight = weight / 100f;
382
383                 Matrix4f mat = offsetMatrices[skinBoneArray[i * 2 + w]];
384
385                 rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
386                 ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
387                 rz += (mat.m20 * vtx + mat.m21 * vty + mat.m22 * vtz + mat.m23) * weight;
388
389                 rnx += (nmx * mat.m00 + nmy * mat.m01 + nmz * mat.m02) * weight;
390                 rny += (nmx * mat.m10 + nmy * mat.m11 + nmz * mat.m12) * weight;
391                 rnz += (nmx * mat.m20 + nmy * mat.m21 + nmz * mat.m22) * weight;
392             }
393
394             fnb.put(rnx).put(rny).put(rnz);
395             fvb.put(rx).put(ry).put(rz);
396         }
397         vars.release();
398         vb.setUpdateNeeded();
399         nb.setUpdateNeeded();
400         skinUpdateNeeded = false;
401     }
402
403     void updateSkinMesh(PMDSkinMesh skinMesh) {
404         VertexBuffer vb = skinMesh.getBuffer(Type.Position);
405         FloatBuffer fvb = (FloatBuffer) vb.getData();
406         VertexBuffer nb = skinMesh.getBuffer(Type.Normal);
407         FloatBuffer fnb = (FloatBuffer) nb.getData();
408
409         for (Skin skin : skinArray) {
410             if (skin.isUpdateNeeded()) {
411                 if (skin.getWeight() != 1f) {
412                     for (PMDSkinVertData svd : skin.getSkinData().getSkinVertData()) {
413                         javax.vecmath.Vector3f dist = skinPosArray[svd.getSkinVertIndex()];
414                         dist.set(svd.getSkinVertPos());
415                         dist.scale(skin.getWeight());
416                         dist.add(skinPosArrayOrig[svd.getSkinVertIndex()]);
417                     }
418                 }
419                 skin.setUpdateNeeded(false);
420             }
421         }
422
423         fvb.position(0);
424         fnb.position(0);
425         TempVars vars = TempVars.get();
426         for (int i = 0; i < skinPosArray.length; i++) {
427             int idxWeights = 0;
428
429             float[] posBuf = vars.skinPositions;
430             float[] normBuf = vars.skinNormals;
431
432             // read next set of positions and normals from native buffer
433             int idxPositions = 0;
434
435             // iterate vertices and apply skinning transform for each effecting bone
436             float nmx = skinNormalArray[i].x;//normBuf[idxPositions];
437             float vtx = skinPosArray[i].x;//posBuf[idxPositions++];
438             float nmy = skinNormalArray[i].y;//normBuf[idxPositions];
439             float vty = skinPosArray[i].y;//posBuf[idxPositions++];
440             float nmz = skinNormalArray[i].z;//normBuf[idxPositions];
441             float vtz = skinPosArray[i].z;//posBuf[idxPositions++];
442
443             float rx = 0, ry = 0, rz = 0, rnx = 0, rny = 0, rnz = 0;
444
445             for (int w = 2 - 1; w >= 0; w--) {
446                 float weight = skinBoneWeightArray[i];//(float) v.getBoneWeight();//weights[idxWeights];
447                 if (w == 1) {
448                     weight = 1f - weight;
449                 }
450                 //weight = weight / 100f;
451
452                 Matrix4f mat = offsetMatrices[skinBoneArray[i * 2 + w]];
453
454                 rx += (mat.m00 * vtx + mat.m01 * vty + mat.m02 * vtz + mat.m03) * weight;
455                 ry += (mat.m10 * vtx + mat.m11 * vty + mat.m12 * vtz + mat.m13) * weight;
456                 rz += (mat.m20 * vtx + mat.m21 * vty + mat.m22 * vtz + mat.m23) * weight;
457
458                 rnx += (nmx * mat.m00 + nmy * mat.m01 + nmz * mat.m02) * weight;
459                 rny += (nmx * mat.m10 + nmy * mat.m11 + nmz * mat.m12) * weight;
460                 rnz += (nmx * mat.m20 + nmy * mat.m21 + nmz * mat.m22) * weight;
461             }
462
463             fnb.put(rnx).put(rny).put(rnz);
464             fvb.put(rx).put(ry).put(rz);
465         }
466         vars.release();
467         vb.setUpdateNeeded();
468         nb.setUpdateNeeded();
469     }
470
471     public void resetToBind() {
472         for (int i = 0; i < skeleton.getBoneCount(); i++) {
473             Bone bone = skeleton.getBone(i);
474             PMDBone pmdBone = pmdModel.getBoneList().getBones()[i];
475             if (pmdBone.getParentBoneIndex() < skeleton.getBoneCount()) {
476                 Bone parentBone = skeleton.getBone(pmdBone.getParentBoneIndex());
477                 PMDBone parentPMDBone = pmdModel.getBoneList().getBones()[pmdBone.getParentBoneIndex()];
478 //                parentBone.addChild(bone);
479                 Vector3f v1 = new Vector3f();
480                 Vector3f v2 = new Vector3f();
481                 v1.set(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
482                 v2.set(parentPMDBone.getBoneHeadPos().x, parentPMDBone.getBoneHeadPos().y, parentPMDBone.getBoneHeadPos().z);
483                 v1.subtractLocal(v2);
484
485                 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
486             } else {
487                 Vector3f v1 = new Vector3f();
488                 v1.set(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
489                 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
490             }
491         }
492         for (PMDMesh mesh : targets) {
493             resetToBind(mesh);
494         }
495         for (Skin skin : skinArray) {
496             skin.setWeight(0f);
497         }
498         setUpdateNeeded(true);
499     }
500
501     void resetToBind(PMDMesh mesh) {
502     }
503     void _resetToBind(PMDMesh mesh) {
504         VertexBuffer vb = mesh.getBuffer(VertexBuffer.Type.Position);
505         FloatBuffer vfb = (FloatBuffer) vb.getData();
506         VertexBuffer nb = mesh.getBuffer(VertexBuffer.Type.Normal);
507         FloatBuffer nfb = (FloatBuffer) nb.getData();
508
509         VertexBuffer bvb = mesh.getBuffer(VertexBuffer.Type.BindPosePosition);
510         FloatBuffer bvfb = (FloatBuffer) bvb.getData();
511         VertexBuffer bnb = mesh.getBuffer(VertexBuffer.Type.BindPoseNormal);
512         FloatBuffer bnfb = (FloatBuffer) bnb.getData();
513
514         for (int i = 0; i < vfb.capacity(); i++) {
515             vfb.put(i, bvfb.get(i));
516         }
517         for (int i = 0; i < nfb.capacity(); i++) {
518             nfb.put(i, bnfb.get(i));
519         }
520         vb.setUpdateNeeded();
521         nb.setUpdateNeeded();
522     }
523     void resetToBindSkinBackData(PMDSkinMesh mesh) {
524         VertexBuffer vb = mesh.getSkinvb2(); // mesh.getBuffer(VertexBuffer.Type.Position);
525         FloatBuffer vfb = (FloatBuffer) vb.getData();
526         VertexBuffer nb = mesh.getSkinnb2(); //mesh.getBuffer(VertexBuffer.Type.Normal);
527         FloatBuffer nfb = (FloatBuffer) nb.getData();
528
529         VertexBuffer bvb = mesh.getBuffer(VertexBuffer.Type.BindPosePosition);
530         FloatBuffer bvfb = (FloatBuffer) bvb.getData();
531         VertexBuffer bnb = mesh.getBuffer(VertexBuffer.Type.BindPoseNormal);
532         FloatBuffer bnfb = (FloatBuffer) bnb.getData();
533
534         for (int i = 0; i < vfb.capacity(); i++) {
535             vfb.put(i, bvfb.get(i));
536         }
537         for (int i = 0; i < nfb.capacity(); i++) {
538             nfb.put(i, bnfb.get(i));
539         }
540         vb.setUpdateNeeded();
541         nb.setUpdateNeeded();
542     }
543     public Set<String> getSkinSet() {
544         return skinMap.keySet();
545     }
546     public Map<String, Skin> getSkinMap() {
547         return skinMap;
548     }
549
550     public float getSkinWeight(String skinName) {
551         return skinMap.get(skinName).getWeight();
552     }
553
554     public void setSkinWeight(String skinName, float weight) {
555         Skin skin = skinMap.get(skinName);
556         if (skin != null) {
557             skin.setWeight(weight);
558             skinUpdateNeeded = true;
559 //            for (PMDSkinVertData svd : skin.getSkinData().getSkinVertData()) {
560 //                javax.vecmath.Vector3f dist = skinPosArray[svd.getSkinVertIndex()];
561 //                dist.set(svd.getSkinVertPos());
562 //                dist.scale(weight);
563 //                dist.add(skinPosArrayOrig[svd.getSkinVertIndex()]);
564 //            }
565         }
566     }
567
568     public boolean isUpdateNeeded() {
569         return updateNeeded;
570     }
571
572     public void setUpdateNeeded(boolean updateNeeded) {
573         this.updateNeeded = updateNeeded;
574     }
575
576     public Skeleton getSkeleton() {
577         return skeleton;
578     }
579
580     public void setSkeleton(Skeleton skeleton) {
581         this.skeleton = skeleton;
582     }
583
584     public void setWireFrame(boolean wireFrame) {
585         for (Spatial sp : getChildren()) {
586             if (sp instanceof Geometry) {
587                 Geometry geom = (Geometry) sp;
588                 geom.getMaterial().getAdditionalRenderState().setWireframe(wireFrame);
589             }
590         }
591         this.wireFrame = wireFrame;
592     }
593
594     public boolean isWireFrame() {
595         return wireFrame;
596     }
597
598     public void setEdgeWidth(float edgeSize) {
599         for (Spatial sp : getChildren()) {
600             if (sp instanceof PMDGeometry) {
601                 PMDGeometry geom = (PMDGeometry) sp;
602                 if (geom.getPmdMaterial().getEdgeFlag() != 0) {
603                     geom.getMaterial().setFloat("EdgeSize", edgeSize);
604                 }
605             }
606         }
607         this.edgeSize = edgeSize;
608     }
609
610     public void setSkeletonWireVisible(boolean skeletonWireVisible) {
611         if (skeletonWireVisible) {
612             if (skeletonWireGeom == null) {
613                 SkeletonWire skeletonWire = new SkeletonWire(skeleton);
614                 skeletonWireGeom = new Geometry("skeletonWire", skeletonWire);
615                 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
616                 mat.setColor("Color", ColorRGBA.Green);
617                 mat.getAdditionalRenderState().setDepthTest(false);
618                 mat.getAdditionalRenderState().setDepthWrite(false);
619                 skeletonWireGeom.setMaterial(mat);
620                 skeletonWireGeom.setQueueBucket(Bucket.Transparent);
621                 attachChild(skeletonWireGeom);
622                 skeletonWire.updateGeometry();
623             }
624         } else {
625             if (skeletonWireGeom != null) {
626                 skeletonWireGeom.removeFromParent();
627                 skeletonWireGeom = null;
628             }
629         }
630         this.skeletonWireVisible = skeletonWireVisible;
631     }
632
633     public void setBonePositionVisible(boolean bonePositionVisible) {
634         if (bonePositionVisible) {
635             if (bonePositionNode == null) {
636                 bonePositionNode = new Node("bonePositionNode");
637                 bonePositionGeomArray = new Geometry[pmdModel.getBoneList().getBoneCount()];
638                 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
639                 mat.setColor("Color", ColorRGBA.Red);
640                 mat.getAdditionalRenderState().setDepthTest(false);
641                 mat.getAdditionalRenderState().setDepthWrite(false);
642                 Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
643                 mat2.setColor("Color", ColorRGBA.Blue);
644                 mat2.getAdditionalRenderState().setDepthTest(false);
645                 mat2.getAdditionalRenderState().setDepthWrite(false);
646                 Material mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
647                 mat3.setColor("Color", ColorRGBA.Green);
648                 mat3.getAdditionalRenderState().setDepthTest(false);
649                 mat3.getAdditionalRenderState().setDepthWrite(false);
650                 for (int i = 0; i < bonePositionGeomArray.length; i++) {
651                     Mesh mesh = new Mesh();
652 //                    mesh.setMode(Mesh.Mode.Points);
653 //                    VertexBuffer pb = new VertexBuffer(Type.Position);
654 //                    FloatBuffer fpb = BufferUtils.createFloatBuffer(3);
655 //                    fpb.put(0f).put(0f).put(0f);
656 //                    pb.setupData(Usage.Static, 3, Format.Float, fpb);
657 //                    mesh.setBuffer(pb);
658 //                    mesh.setPointSize(7);
659 //                    mesh.updateCounts();
660                     Geometry geom = new Geometry(pmdModel.getBoneList().getBones()[i].getBoneName(), new Box(0.1f, 0.1f, 0.0f));
661                     geom.setMaterial(mat);
662                     geom.setQueueBucket(Bucket.Transparent);
663                     bonePositionGeomArray[i] = geom;
664                     bonePositionNode.attachChild(geom);
665                     geom.addControl(new BillboardControl());
666                     if (pmdModel.getBoneList().getBones()[i].getBoneType() == 2) {
667                         geom.setMaterial(mat2);
668                     }
669                     if (pmdModel.getBoneList().getBones()[i].getBoneType() == 6) {
670                         geom.setMaterial(mat3);
671                     }
672                 }
673                 attachChild(bonePositionNode);
674             }
675
676         } else {
677             if (bonePositionNode != null) {
678                 bonePositionNode.removeFromParent();
679                 bonePositionNode = null;
680                 bonePositionGeomArray = null;
681             }
682         }
683         setUpdateNeeded(true);
684         this.bonePositionVisible = bonePositionVisible;
685     }
686
687     public Node getBonePositionNode() {
688         return bonePositionNode;
689     }
690
691     public Matrix4f[] getOffsetMatrices() {
692         return offsetMatrices;
693     }
694
695     public void setRigidBodyVisible(boolean flag) {
696         if (flag) {
697             if (rigidBodyNode != null) {
698                 return;
699             }
700             RigidBodyConverter rbc = new RigidBodyConverter(pmdModel, assetManager);
701             rigidBodyNode = rbc.convert("rigidBody");
702             attachChild(rigidBodyNode);
703         } else {
704             if (rigidBodyNode != null) {
705                 detachChild(rigidBodyNode);
706                 rigidBodyNode = null;
707             }
708         }
709     }
710
711     public Node getRigidBodyNode() {
712         return rigidBodyNode;
713     }
714     // bullet physics
715 //    PMDRigidBody rigidBodyArray[];
716
717     void initMaterials() {
718         for (Spatial sp : getChildren()) {
719             if (sp instanceof PMDGeometry) {
720                 PMDGeometry geom = (PMDGeometry) sp;
721                 Mesh mesh = geom.getMesh();
722                 if (mesh instanceof PMDMesh) {
723                     if (glslSkinning) {
724                         geom.setMaterial(geom.getGlslSkinningMaterial());
725                     } else {
726                         geom.setMaterial(geom.getNoSkinningMaterial());
727                     }
728                 }
729             }
730         }
731     }
732
733     public Node getJointNode() {
734         return jointNode;
735     }
736
737     public void setJointNode(Node jointNode) {
738         this.jointNode = jointNode;
739     }
740
741 //    PMDRigidBody createRigidBody(projectkyoto.mmd.file.PMDRigidBody fileRigidBody, Bone bone) {
742 //        return null;
743 //    }
744     public boolean isGlslSkinning() {
745         return glslSkinning;
746     }
747
748     public void setGlslSkinning(boolean glslSkinning) {
749         this.glslSkinning = glslSkinning;
750         for (Spatial sp : getChildren()) {
751             if (sp instanceof PMDGeometry) {
752                 Mesh mesh = ((PMDGeometry) sp).getMesh();
753                 if (mesh instanceof PMDMesh) {
754                     PMDMesh pmdMesh = (PMDMesh)mesh;
755                     resetToBind(pmdMesh);
756                     if (glslSkinning) {
757                         pmdMesh.releaseSoftwareSkinningBufferes();
758                         mesh.getBuffer(Type.Position).setUsage(Usage.Static);
759                         mesh.getBuffer(Type.Normal).setUsage(Usage.Static);
760                     } else {
761                         pmdMesh.createSoftwareSkinningBuffers();
762                         mesh.getBuffer(Type.Position).setUsage(Usage.Dynamic);
763                         mesh.getBuffer(Type.Normal).setUsage(Usage.Dynamic);
764                     }
765                 }
766             }
767         }
768         initMaterials();
769     }
770
771     @Override
772     public boolean equals(Object obj) {
773         if (this == obj) {
774             return true;
775         }
776         return false;
777     }
778
779     @Override
780     public int hashCode() {
781         return pmdModel.getModelName().hashCode();
782     }
783
784     @Override
785     public PMDNode clone() {
786         try {
787             PMDNode newPMDNode = (PMDNode)super.clone();
788 //            newPMDNode.pmdModel = pmdModel;
789             newPMDNode.skeleton = new Skeleton(skeleton);
790             for(int i=0;i<skeleton.getBoneCount();i++) {
791                 Bone newBone = newPMDNode.skeleton.getBone(i);
792                 Bone bone = skeleton.getBone(i);
793                 newBone.getLocalPosition().set(bone.getLocalPosition());
794                 newBone.getLocalRotation().set(bone.getLocalRotation());
795                 newBone.getLocalScale().set(bone.getLocalScale());
796             }
797             newPMDNode.targets = new PMDMesh[targets.length];
798             newPMDNode.skinTargets = new PMDSkinMesh[skinTargets.length];
799             int meshCount=0;
800             int skinMeshCount = 0;
801             for(Spatial sp : newPMDNode.getChildren()) {
802                 Spatial newSp = sp;//.clone();
803 //                newPMDNode.attachChild(newSp);
804                 if (sp instanceof PMDGeometry) {
805                     Mesh mesh = ((Geometry)newSp).getMesh();
806                     if (mesh instanceof PMDMesh) {
807                         pmdGeometryArray[meshCount] = (PMDGeometry)sp;
808                        newPMDNode.targets[meshCount++] = (PMDMesh)mesh;
809                     } else if (mesh instanceof PMDSkinMesh) {
810                         newPMDNode.skinTargets[skinMeshCount++] = (PMDSkinMesh)mesh;
811                     }
812                 }
813             }
814             newPMDNode.skinMap = new HashMap<String, Skin>();
815             for(String skinName : skinMap.keySet()) {
816                 Skin skin = skinMap.get(skinName);
817                 skin = skin.clone();
818                 newPMDNode.skinMap.put(skinName, skin);
819             }
820             newPMDNode.skinArray = newPMDNode.skinMap.values().toArray(new Skin[newPMDNode.skinMap.size()]);
821             newPMDNode.skinPosArray = new javax.vecmath.Vector3f[skinPosArray.length];
822             for(int i=0;i<skinPosArray.length;i++) {
823                 newPMDNode.skinPosArray[i] = new javax.vecmath.Vector3f(skinPosArray[i]);
824             }
825             newPMDNode.skinNormalArray = new javax.vecmath.Vector3f[skinNormalArray.length];
826             for(int i=0;i<skinNormalArray.length;i++) {
827                 newPMDNode.skinNormalArray[i] = new javax.vecmath.Vector3f(skinNormalArray[i]);
828             }
829 //            newPMDNode.offsetMatrices = new Matrix4f[offsetMatrices.length];
830             newPMDNode.setGlslSkinning(newPMDNode.glslSkinning);
831             newPMDNode.skeleton.updateWorldVectors();
832             newPMDNode.calcOffsetMatrices();
833             newPMDNode.updateSkinBackData();
834             newPMDNode.update();
835             newPMDNode.updateSkinBackData();
836             newPMDNode.update();
837             return newPMDNode;
838         } catch(CloneNotSupportedException ex) {
839             throw new PMDException(ex);
840         }
841     }
842     
843 }