OSDN Git Service

d6f87c8bc00a4bf33679e9aabd04487b98abd264
[mikumikustudio/MikuMikuStudio.git] / src / projectkyoto / jme3 / mmd / PMDLoaderGLSLSkinning2.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.AssetInfo;
35 import com.jme3.asset.AssetLoader;
36 import com.jme3.asset.AssetManager;
37 import com.jme3.asset.AssetNotFoundException;
38 import com.jme3.material.Material;
39 import com.jme3.material.RenderState.BlendMode;
40 import com.jme3.material.RenderState.FaceCullMode;
41 import com.jme3.math.ColorRGBA;
42 import com.jme3.math.Matrix4f;
43 import com.jme3.math.Quaternion;
44 import com.jme3.math.Vector3f;
45 import com.jme3.renderer.queue.RenderQueue.Bucket;
46 import com.jme3.scene.Mesh;
47 import com.jme3.scene.Node;
48 import com.jme3.scene.Spatial;
49 import com.jme3.scene.VertexBuffer;
50 import com.jme3.scene.debug.SkeletonPoints;
51 import com.jme3.scene.debug.SkeletonWire;
52 import com.jme3.scene.shape.Box;
53 import com.jme3.shader.VarType;
54 import com.jme3.system.JmeSystem;
55 import com.jme3.texture.Texture;
56 import com.jme3.util.BufferUtils;
57 import com.jme3.util.TempVars;
58 import java.io.IOException;
59 import java.nio.FloatBuffer;
60 import java.nio.ShortBuffer;
61 import java.util.ArrayList;
62 import java.util.List;
63 import java.util.StringTokenizer;
64 import org.lwjgl.opengl.GL11;
65 import projectkyoto.mmd.file.*;
66 import projectkyoto.mmd.file.util2.MeshConverter;
67 import projectkyoto.mmd.file.util2.MeshData;
68
69 /**
70  *
71  * @author kobayasi
72  */
73 public class PMDLoaderGLSLSkinning2 implements AssetLoader{
74
75     PMDModel model;
76     PMDNode node;
77     MeshConverter meshConverter;
78     int meshCount = 1;
79     AssetManager assetManager;
80     String folderName;
81     List<PMDMesh> meshList = new ArrayList<PMDMesh>();
82     List<PMDSkinMesh> skinMeshList = new ArrayList<PMDSkinMesh>();
83     VertexBuffer skinvb;
84     VertexBuffer skinvb2;
85     VertexBuffer skinnb;
86     VertexBuffer skinnb2;
87     VertexBuffer skintb;
88     Skin skinArray[];
89     SkeletonControl skeletonControl;
90
91     public PMDLoaderGLSLSkinning2() {
92     }
93     public PMDLoaderGLSLSkinning2(AssetManager assetManager, PMDModel model) {
94         this.assetManager = assetManager;
95         this.model = model;
96         folderName = "/Model/";
97 //        System.out.println("vertexCount = " + model.getVertCount());
98 //        System.out.println("faceVertCount = " + model.getFaceVertCount());
99 //        assetManager.registerLoader(com.jme3.texture.plugins.AWTLoader.class, "sph", "spa");
100     }
101     public void init() {
102 //        model = null;
103         node = null;
104         meshConverter = new MeshConverter(model);
105         meshCount = 1;
106 //        assetManager = null;
107 //        folderName = null;
108         meshList.clear();
109         skinMeshList.clear();
110         skinvb = null;
111         skinvb2 = null;
112         skinnb = null;
113         skinnb2 = null;
114         skintb = null;
115         skeletonControl = null;
116         skinArray = null;
117     }
118
119     public PMDNode createNode(String name) {
120         init();
121         node = new PMDNode(name, model, assetManager);
122         meshCount = 1;
123         meshConverter.convertMesh();
124 //        System.out.println("child size = "+node.getChildren().size()+" "+meshList.size()+" "+skinMeshList.size());
125         node.pmdGeometryArray = new PMDGeometry[meshConverter.getMeshDataList().size()];
126         int pmdGeometryIndex = 0;
127         for (MeshData md : meshConverter.getMeshDataList()) {
128             PMDMesh mesh = createMesh(md);
129             PMDGeometry geom = new PMDGeometry("geom" + meshCount++);
130             geom.setMesh(mesh);
131             PMDMaterial pmdMaterial = md.getMaterial();
132             setupMaterial(pmdMaterial, geom);
133             System.out.println(node.attachChild(geom));
134             meshList.add(mesh);
135             node.pmdGeometryArray[pmdGeometryIndex++] = geom;
136         }
137         createSkinCommonVertData();
138         for (PMDMaterial pmdMaterial : meshConverter.getSkinMeshData().getIndexMap().keySet()) {
139             PMDSkinMesh mesh = createSkinMesh(pmdMaterial);
140             PMDGeometry geom = new PMDGeometry("geom" + meshCount++);
141             geom.setMesh(mesh);
142             setupMaterial(pmdMaterial, geom);
143             System.out.println(node.attachChild(geom));
144             skinMeshList.add(mesh);
145         }
146         System.out.println("child size = "+node.getChildren().size()+" "+meshList.size()+" "+skinMeshList.size());
147         createSkinArray();
148         createSkeleton();
149         node.setSkinData(skinMeshList.toArray(new PMDSkinMesh[skinMeshList.size()]), meshConverter.getSkinMeshData().getVertexList(), skinArray);
150         node.targets = meshList.toArray(new PMDMesh[meshList.size()]);
151         node.init();
152         node.calcOffsetMatrices();
153         node.update();
154         return node;
155     }
156
157     void createSkinCommonVertData() {
158         skinvb = new VertexBuffer(VertexBuffer.Type.Position);
159         FloatBuffer skinvfb = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
160         skinvb.setupData(VertexBuffer.Usage.Dynamic, 3, VertexBuffer.Format.Float, skinvfb);
161
162         skinvb2 = new VertexBuffer(VertexBuffer.Type.Position);
163         FloatBuffer skinvfb2 = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
164         skinvb2.setupData(VertexBuffer.Usage.Dynamic, 3, VertexBuffer.Format.Float, skinvfb2);
165         
166         skinnb = new VertexBuffer(VertexBuffer.Type.Normal);
167         FloatBuffer skinnfb = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
168         skinnb.setupData(VertexBuffer.Usage.Dynamic, 3, VertexBuffer.Format.Float, skinnfb);
169
170         skinnb2 = new VertexBuffer(VertexBuffer.Type.Normal);
171         FloatBuffer skinnfb2 = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 3);
172         skinnb2.setupData(VertexBuffer.Usage.Dynamic, 3, VertexBuffer.Format.Float, skinnfb2);
173         
174         skintb = new VertexBuffer(VertexBuffer.Type.TexCoord);
175         FloatBuffer skintfb = BufferUtils.createFloatBuffer(meshConverter.getSkinMeshData().getVertexList().size() * 2);
176         skintb.setupData(VertexBuffer.Usage.Static, 2, VertexBuffer.Format.Float, skintfb);
177         for (PMDVertex v : meshConverter.getSkinMeshData().getVertexList()) {
178             skinvfb.put(v.getPos().x).put(v.getPos().y).put(v.getPos().z);
179             skinnfb.put(v.getNormal().x).put(v.getNormal().y).put(v.getNormal().z);
180             skintfb.put(v.getUv().getU()).put(1f - v.getUv().getV());
181         }
182         skintb.setUpdateNeeded();
183     }
184
185     PMDSkinMesh createSkinMesh(PMDMaterial pmdMaterial) {
186         PMDSkinMesh mesh = new PMDSkinMesh();
187         List<Integer> indexList = meshConverter.getSkinMeshData().getIndexMap().get(pmdMaterial);
188         mesh.setMode(Mesh.Mode.Triangles);
189         mesh.setBuffer(skinvb);
190         mesh.setSkinvb2(skinvb2);
191         mesh.setBuffer(skinnb);
192         mesh.setSkinnb2(skinnb2);
193         mesh.setBuffer(skintb);
194         VertexBuffer ib = new VertexBuffer(VertexBuffer.Type.Index);
195         ShortBuffer isb = BufferUtils.createShortBuffer(indexList.size());
196         for (Integer index : indexList) {
197             isb.put(index.shortValue());
198         }
199         ib.setupData(VertexBuffer.Usage.Static, 1, VertexBuffer.Format.UnsignedShort, isb);
200         mesh.setBuffer(ib);
201         return mesh;
202     }
203
204     PMDMesh createMesh(MeshData md) {
205         PMDMesh mesh = new PMDMesh();
206         mesh.setMode(Mesh.Mode.Triangles);
207         VertexBuffer vb = new VertexBuffer(VertexBuffer.Type.Position);
208         FloatBuffer vfb = BufferUtils.createFloatBuffer(md.getVertexList().size() * 3);
209         VertexBuffer nb = new VertexBuffer(VertexBuffer.Type.Normal);
210         FloatBuffer nfb = BufferUtils.createFloatBuffer(md.getVertexList().size() * 3);
211
212 //        VertexBuffer bvb = new VertexBuffer(VertexBuffer.Type.BindPosePosition);
213 //        FloatBuffer bvfb = BufferUtils.createFloatBuffer(md.getVertexList().size() * 3);
214 //        VertexBuffer bnb = new VertexBuffer(VertexBuffer.Type.BindPoseNormal);
215 //        FloatBuffer bnfb = BufferUtils.createFloatBuffer(md.getVertexList().size() * 3);
216
217         VertexBuffer tb = new VertexBuffer(VertexBuffer.Type.TexCoord);
218
219         FloatBuffer tfb = BufferUtils.createFloatBuffer(md.getVertexList().size() * 2);
220         VertexBuffer wb = new VertexBuffer(VertexBuffer.Type.BoneWeight);
221         FloatBuffer wfb = BufferUtils.createFloatBuffer(md.getVertexList().size() * 4);
222         VertexBuffer ib = new VertexBuffer(VertexBuffer.Type.Index);
223         ShortBuffer isb = BufferUtils.createShortBuffer(md.getIndexList().size());
224         VertexBuffer bib = new VertexBuffer(VertexBuffer.Type.BoneIndex);
225         ShortBuffer bisb = BufferUtils.createShortBuffer(md.getIndexList().size() * 4);
226         for (PMDVertex v : md.getVertexList()) {
227             vfb.put(v.getPos().x).put(v.getPos().y).put(v.getPos().z);
228             nfb.put(v.getNormal().x).put(v.getNormal().y).put(v.getNormal().z);
229
230 //            bvfb.put(v.getPos().x).put(v.getPos().y).put(v.getPos().z);
231 //            bnfb.put(v.getNormal().x).put(v.getNormal().y).put(v.getNormal().z);
232
233             tfb.put(v.getUv().getU()).put(1f - v.getUv().getV());
234             float weight = (float) v.getBoneWeight() / 100.0f;
235             wfb.put(weight).put(1f - weight).put(0).put(0);
236             bisb.put((short) md.getBoneList().indexOf(v.getBoneNum1())).put((short) md.getBoneList().indexOf(v.getBoneNum2())).put((short) 0).put((short) 0);
237         }
238         for (Integer index : md.getIndexList()) {
239             isb.put(index.shortValue());
240 //            System.out.println("index = "+index);
241         }
242 //        System.out.println("isb.capacity() = " + isb.capacity());
243 //        System.out.println("isb.capacity() = " + md.getIndexList().size());
244         vb.setupData(VertexBuffer.Usage.Dynamic, 3, VertexBuffer.Format.Float, vfb);
245         nb.setupData(VertexBuffer.Usage.Dynamic, 3, VertexBuffer.Format.Float, nfb);
246
247 //        bvb.setupData(VertexBuffer.Usage.CpuOnly, 3, VertexBuffer.Format.Float, bvfb);
248 //        bnb.setupData(VertexBuffer.Usage.CpuOnly, 3, VertexBuffer.Format.Float, bnfb);
249
250         tb.setupData(VertexBuffer.Usage.Static, 2, VertexBuffer.Format.Float, tfb);
251         wb.setupData(VertexBuffer.Usage.Static, 4, VertexBuffer.Format.Float, wfb);
252         ib.setupData(VertexBuffer.Usage.Static, 1, VertexBuffer.Format.UnsignedShort, isb);
253         bib.setupData(VertexBuffer.Usage.Static, 4, VertexBuffer.Format.Short, bisb);
254         mesh.setBuffer(vb);
255         mesh.setBuffer(nb);
256         
257         mesh.setVbBackup(vb);
258         mesh.setNbBackup(nb);
259
260 //        mesh.setBuffer(bvb);
261 //        mesh.setBuffer(bnb);
262
263         mesh.setBuffer(tb);
264         mesh.setBuffer(wb);
265         mesh.setBuffer(ib);
266         mesh.setBuffer(bib);
267         int[] indexArray = new int[meshConverter.getMaxBoneSize()];
268         for (int i = 0; i < indexArray.length; i++) {
269             if (i < md.getBoneList().size()) {
270                 indexArray[i] = md.getBoneList().get(i).shortValue();
271             } else {
272                 indexArray[i] = 0;
273             }
274         }
275         mesh.setBoneIndexArray(indexArray);
276         mesh.setBoneMatrixArray(new Matrix4f[indexArray.length]);
277         for (int i = 0; i < mesh.getBoneMatrixArray().length; i++) {
278             mesh.getBoneMatrixArray()[i] = new Matrix4f();
279             mesh.getBoneMatrixArray()[i].loadIdentity();
280         }
281         return mesh;
282     }
283
284     void setupMaterial(PMDMaterial m, PMDGeometry geom) {
285         Material mat;
286         if (geom.getMesh() instanceof PMDSkinMesh) {
287 //            mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
288             mat = createMaterial(m, false);
289             geom.setMaterial(mat);
290             geom.setGlslSkinningMaterial(mat);
291             geom.setNoSkinningMaterial(mat);
292         } else {
293             mat = createMaterial(m, true);
294             geom.setMaterial(mat);
295             geom.setGlslSkinningMaterial(mat);
296             mat = createMaterial(m, false);
297             geom.setNoSkinningMaterial(mat);
298         }
299         geom.setPmdMaterial(m);
300         if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
301             geom.setQueueBucket(Bucket.Transparent);
302         } else {
303             geom.setQueueBucket(Bucket.Inherit);
304         }
305     }
306
307     Material createMaterial(PMDMaterial m, boolean skinning) {
308         Material mat;
309         if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
310             if (!skinning) {
311                 mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning_alpha.j3md");
312             } else {
313                 mat = new Material(assetManager, "MatDefs/pmd/pmd_alpha.j3md");
314             }
315         } else {
316             if (!skinning) {
317                 mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning.j3md");
318             } else {
319                 mat = new Material(assetManager, "MatDefs/pmd/pmd.j3md");
320             }
321         }
322         float alpha = m.getMaterial().getFaceColor().getAlpha();
323         if (alpha > 0.99f) {
324             alpha = 1f;
325         }
326         ColorRGBA ambientColor = new ColorRGBA(m.getMaterial().getAmbientColor().getRed(),
327                 m.getMaterial().getAmbientColor().getGreen(), m.getMaterial().getAmbientColor().getBlue(), alpha);
328         ColorRGBA diffuseColor = new ColorRGBA(m.getMaterial().getFaceColor().getRed(),
329                 m.getMaterial().getFaceColor().getGreen(), m.getMaterial().getFaceColor().getBlue(), alpha);
330         ColorRGBA ambientAndDiffuseColor = ambientColor.add(diffuseColor);
331         ambientAndDiffuseColor.multLocal(0.5f);
332         ambientAndDiffuseColor.a = alpha;
333         mat.setBoolean("UseMaterialColors", true);
334         mat.setColor("Ambient", ambientAndDiffuseColor);
335         mat.setColor("Specular", new ColorRGBA(m.getMaterial().getSpecularColor().getRed(),
336                 m.getMaterial().getSpecularColor().getGreen(), m.getMaterial().getSpecularColor().getBlue(), alpha));
337         mat.setColor("Diffuse", ambientAndDiffuseColor);
338         mat.setFloat("Shininess", m.getMaterial().getPower());
339         if (m.getTextureFileName().length() > 0) {
340             StringTokenizer st = new StringTokenizer(m.getTextureFileName(), "*");
341             System.out.println("m.getTextureFileName() = " + m.getTextureFileName());
342             while (st.hasMoreElements()) {
343                 String fileName = st.nextToken();
344                 System.out.println("fileName = " + fileName);
345                 String s = fileName.substring(fileName.indexOf('.') + 1);
346                 Texture texture = assetManager.loadTexture(folderName + fileName /*
347                          * m.getTextureFileName()
348                          */);
349                 s = s.toLowerCase();
350                 if (s.equals("spa")) {
351                     texture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
352                     mat.setTexture("SphereMap_A", texture);
353                 } else if (s.equals("sph")) {
354                     texture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
355                     mat.setTexture("SphereMap_H", texture);
356                 } else {
357 //                    texture.setWrap(Texture.WrapMode.Repeat);
358                     mat.setTexture("DiffuseMap", texture);
359                 }
360             }
361         }
362         int toonIndex = m.getToonIndex();
363         Texture toonTexture = null;
364         if (toonIndex >= 0) {
365             String extToonName = model.getToonTextureList().getToonFileName()[toonIndex];
366             try {
367                 toonTexture = assetManager.loadTexture(folderName + extToonName);
368             } catch (AssetNotFoundException ex) {
369                 String toonname = null;
370                 switch (toonIndex) {
371                     case 0:
372                         toonname = "toon01.bmp";
373                         break;
374                     case 1:
375                         toonname = "toon02.bmp";
376                         break;
377                     case 2:
378                         toonname = "toon03.bmp";
379                         break;
380                     case 3:
381                         toonname = "toon04.bmp";
382                         break;
383                     case 4:
384                         toonname = "toon05.bmp";
385                         break;
386                     case 5:
387                         toonname = "toon06.bmp";
388                         break;
389                     case 6:
390                         toonname = "toon07.bmp";
391                         break;
392                     case 7:
393                         toonname = "toon08.bmp";
394                         break;
395                     case 8:
396                         toonname = "toon09.bmp";
397                         break;
398                     case 9:
399                         toonname = "toon10.bmp";
400                         break;
401                 }
402                 if (toonname != null) {
403                     toonTexture = assetManager.loadTexture("toon/" + toonname);
404                 }
405             }
406         }
407         if (toonTexture != null) {
408             toonTexture.setWrap(Texture.WrapAxis.S, Texture.WrapMode.EdgeClamp);
409             toonTexture.setWrap(Texture.WrapAxis.T, Texture.WrapMode.EdgeClamp);
410             toonTexture.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
411             mat.setTexture("ColorRamp", toonTexture);
412         }
413         if (m.getEdgeFlag() != 0 /*
414                  * && !(geom.getMesh() instanceof PMDSkinMesh)
415                  */) {
416 //            mat.setFloat("EdgeSize", 0.02f);
417             mat.setFloat("EdgeSize", 0.01f);
418         } else {
419             mat.setFloat("EdgeSize", 0f);
420         }
421 //        mat.setParam("VertexLighting", VarType.Int, new Integer(1));
422 //        geom.setMaterial(mat);
423 //        geom.setPmdMaterial(m);
424 //        mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
425 //        mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
426 //        mat.getAdditionalRenderState().setWireframe(true);
427         if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
428             mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
429             mat.getAdditionalRenderState().setAlphaTest(true);
430 //                    mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
431         } else {
432             mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
433 //                    mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
434 //                    mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
435             mat.getAdditionalRenderState().setAlphaTest(true);
436         }
437         return mat;
438     }
439
440     void createSkeleton() {
441         TempVars temp = TempVars.get();
442         Bone[] boneArray = new Bone[model.getBoneList().getBoneCount()];
443         int boneIndex = 0;
444         for (PMDBone pmdBone : model.getBoneList().getBones()) {
445             Bone bone = new Bone(pmdBone.getBoneName());
446             bone.setUserControl(true);
447             Vector3f translation = new Vector3f(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
448             Quaternion rotation = new Quaternion();
449             boneArray[boneIndex++] = bone;
450         }
451         boneIndex = 0;
452         for (PMDBone pmdBone : model.getBoneList().getBones()) {
453             Bone bone = boneArray[boneIndex];
454             if (pmdBone.getParentBoneIndex() < boneArray.length) {
455                 Bone parent = boneArray[pmdBone.getParentBoneIndex()];
456                 PMDBone parentPMDBone = model.getBoneList().getBones()[pmdBone.getParentBoneIndex()];
457                 parent.addChild(bone);
458                 Vector3f v1 = temp.vect1; // new Vector3f();
459                 Vector3f v2 = temp.vect2; //new Vector3f();
460                 v1.set(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
461                 v2.set(parentPMDBone.getBoneHeadPos().x, parentPMDBone.getBoneHeadPos().y, parentPMDBone.getBoneHeadPos().z);
462                 v1.subtractLocal(v2);
463
464                 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
465             } else {
466                 Vector3f v1 = temp.vect1; //new Vector3f();
467                 v1.set(pmdBone.getBoneHeadPos().x, pmdBone.getBoneHeadPos().y, pmdBone.getBoneHeadPos().z);
468                 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
469             }
470
471             boneIndex++;
472         }
473
474         Skeleton skeleton = new Skeleton(boneArray);
475         PMDMesh meshes[] = meshList.toArray(new PMDMesh[meshList.size()]);
476
477         Quaternion q = new Quaternion();
478         q = q.fromAngleNormalAxis((float) Math.PI / 8, new Vector3f(0, 0, 1));
479         node.skeleton = skeleton;
480         temp.release();
481     }
482
483     void createSkinArray() {
484         List<Skin> skinList = new ArrayList<Skin>();
485         for (int i = 0; i < model.getSkinCount(); i++) {
486             PMDSkinData pmdSkinData = model.getSkinData()[i];
487             if (pmdSkinData.getSkinType() != 0) {
488                 Skin skin = new Skin(node, pmdSkinData.getSkinName());
489                 skin.setSkinData(pmdSkinData);
490                 skinList.add(skin);
491             }
492         }
493         skinArray = skinList.toArray(new Skin[skinList.size()]);
494     }
495
496     public Node createBoneNode() {
497         Node boneNode = new Node("boneMarks");
498         Spatial boneMarkArray[] = new Spatial[model.getBoneList().getBoneCount()];
499         for (int i = 0; i < model.getBoneList().getBoneCount(); i++) {
500             PMDBone bone = model.getBoneList().getBones()[i];
501             PMDGeometry boneMark = new PMDGeometry(bone.getBoneName());
502             Node boneMarkNode = new Node();
503             boneMark.setMesh(new Box(4f, 4f, 0.1f));
504 //            boneMark.setLocalTranslation(bone.getBoneHeadPos().x,
505 //                    bone.getBoneHeadPos().y, bone.getBoneHeadPos().z);
506 //            boneMark.move(bone.getBoneHeadPos().x,
507 //                    bone.getBoneHeadPos().y, bone.getBoneHeadPos().z);
508             boneMarkArray[i] = boneMarkNode;
509             Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
510             mat.setColor("Color", ColorRGBA.Blue);
511             boneMark.setMaterial(mat);
512             boneMarkNode.attachChild(boneMark);
513 //            if (bone.getBoneName().contains("目")) {
514             boneNode.attachChild(boneMarkNode);
515 //            }
516         }
517         PMDBoneMarkControl bmc = new PMDBoneMarkControl(skeletonControl, boneMarkArray, model.getBoneList().getBones());
518         node.addControl(bmc);
519         PMDGeometry skeletonGeom = new PMDGeometry();
520         SkeletonPoints sp = new SkeletonPoints(skeletonControl.skeleton);
521         skeletonGeom.setMesh(sp);
522         Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
523         mat.setColor("Color", ColorRGBA.Green);
524         mat.getAdditionalRenderState().setDepthTest(false);
525         skeletonGeom.setMaterial(mat);
526         node.attachChild(skeletonGeom);
527
528         SkeletonWire sw = new SkeletonWire(skeletonControl.skeleton);
529         PMDGeometry skeletonWireGeom = new PMDGeometry("skeletonWire", sw);
530         node.attachChild(skeletonWireGeom);
531         skeletonWireGeom.setMaterial(mat);
532
533         sp.updateGeometry();
534         sw.updateGeometry();
535
536
537         return boneNode;
538     }
539
540     @Override
541     public Object load(AssetInfo ai) throws IOException {
542         boolean errFlag = false;
543         for(;;) {
544             try {
545                 this.assetManager = ai.getManager();
546                 model = new PMDModel(ai.openStream());
547                 folderName = ai.getKey().getFolder();
548                 meshConverter = new MeshConverter(model);
549                 PMDNode pmdNode = createNode(ai.getKey().getName());
550                 if (JmeSystem.getFullName().indexOf("Android") == -1) {
551                     try {
552                         String vendor = GL11.glGetString(GL11.GL_VENDOR);
553                         if (vendor != null && vendor.toLowerCase().contains("intel")) {
554                             pmdNode.setGlslSkinning(false);
555                         } else {
556                             pmdNode.setGlslSkinning(true);
557                         }
558                     } catch(Exception ex) {
559                         pmdNode.setGlslSkinning(false);
560                     }
561                 }
562                 return pmdNode;
563             }catch(OutOfMemoryError ex) {
564                 if (errFlag) {
565                     throw new RuntimeException(ex);
566                 }
567                 errFlag = true;
568                 System.gc();
569             }
570         }
571     }
572 }