OSDN Git Service

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