2 * Copyright (c) 2011 Kazuhiko Kobayashi All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
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.
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.
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.
30 package projectkyoto.jme3.mmd;
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;
77 public class PMDLoaderGLSLSkinning2 implements AssetLoader{
81 MeshConverter meshConverter;
83 AssetManager assetManager;
85 List<PMDMesh> meshList = new ArrayList<PMDMesh>();
86 List<PMDSkinMesh> skinMeshList = new ArrayList<PMDSkinMesh>();
96 SkeletonControl skeletonControl;
97 HashMap<String, Texture> textureMap = new HashMap<String, Texture>();
98 public PMDLoaderGLSLSkinning2() {
100 public PMDLoaderGLSLSkinning2(AssetManager assetManager, PMDModel model) {
101 this.assetManager = assetManager;
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");
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");
120 if (meshConverter == null) {
121 meshConverter = new MeshConverter(model);
122 meshConverter.convertMesh();
125 // assetManager = null;
126 // folderName = null;
128 skinMeshList.clear();
134 skeletonControl = null;
138 public PMDNode createNode(String name) {
140 node = new PMDNode(name, model, assetManager);
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++);
151 PMDMaterial pmdMaterial = md.getMaterial();
152 setupMaterial(pmdMaterial, geom);
153 node.attachChild(geom);
155 node.pmdGeometryArray[pmdGeometryIndex++] = geom;
156 meshConverter.getMeshDataList().set(i, null);
158 mesh.setInterleaved();
161 createSkinCommonVertData();
162 for (PMDMaterial pmdMaterial : meshConverter.getSkinMeshData().getIndexMap().keySet()) {
163 PMDSkinMesh mesh = createSkinMesh(pmdMaterial);
164 PMDGeometry geom = new PMDGeometry("geom" + meshCount++);
166 setupMaterial(pmdMaterial, geom);
167 node.attachChild(geom);
168 skinMeshList.add(mesh);
170 // System.out.println("child size = "+node.getChildren().size()+" "+meshList.size()+" "+skinMeshList.size());
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);
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);
182 node.calcOffsetMatrices();
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);
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);
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);
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);
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);
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);
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);
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);
228 skinvfb2.position(0);
229 skinvfb2.put(skinvfb);
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();
238 skinIndexArray[i] = 0;
243 PMDSkinMesh createSkinMesh(PMDMaterial pmdMaterial) {
244 boolean textureFlag = true;
245 if (pmdMaterial.getTextureFileName().length() == 0) {
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);
256 mesh.setBuffer(skintb);
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());
265 ib.setupData(VertexBuffer.Usage.Static, 1, VertexBuffer.Format.UnsignedShort, isb);
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();
276 PMDMesh createMesh_old(MeshData md) {
277 boolean textureFlag = true;
278 if (md.getMaterial().getTextureFileName().length() == 0) {
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);
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);
293 VertexBuffer tb = new VertexBuffer(VertexBuffer.Type.TexCoord);
295 FloatBuffer tfb = null;
297 tfb = BufferUtils.createFloatBuffer(md.getVertIndexList().size() * 2);
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);
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);
314 tfb.put(v.getUv().getU()).put(1f - v.getUv().getV());
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()));
320 for (Integer index : md.getIndexList()) {
321 isb.put(index.shortValue());
322 // System.out.println("index = "+index);
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);
329 // bvb.setupData(VertexBuffer.Usage.CpuOnly, 3, VertexBuffer.Format.Float, bvfb);
330 // bnb.setupData(VertexBuffer.Usage.CpuOnly, 3, VertexBuffer.Format.Float, bnfb);
332 tb.setupData(VertexBuffer.Usage.Static, 2, VertexBuffer.Format.Float, tfb);
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);
340 mesh.setVbBackup(vb);
341 mesh.setNbBackup(nb);
343 // mesh.setBuffer(bvb);
344 // mesh.setBuffer(bnb);
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();
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();
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);
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);
384 PMDVertex v = new PMDVertex();
387 mesh.setVertCount(md.getVertIndexList().size());
389 mesh.setVbBackup(vb);
390 mesh.setNbBackup(nb);
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();
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();
413 void setupMaterial(PMDMaterial m, PMDGeometry geom) {
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);
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);
431 geom.setPmdMaterial(m);
432 if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
433 geom.setQueueBucket(Bucket.Transparent);
435 geom.setQueueBucket(Bucket.Inherit);
439 Material createMaterial(PMDMaterial m, boolean skinning) {
441 if (m.getMaterial().getFaceColor().getAlpha() < 1f) {
443 mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning_alpha.j3md");
445 mat = new Material(assetManager, "MatDefs/pmd/pmd_alpha.j3md");
449 mat = new Material(assetManager, "MatDefs/pmd/pmd_no_skinning.j3md");
451 mat = new Material(assetManager, "MatDefs/pmd/pmd.j3md");
455 mat.setInt("NumBones", meshConverter.getMaxBoneSize());
457 float alpha = m.getMaterial().getFaceColor().getAlpha();
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()
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);
492 // texture.setWrap(Texture.WrapMode.Repeat);
493 mat.setTexture("DiffuseMap", texture);
497 int toonIndex = m.getToonIndex();
498 Texture toonTexture = null;
499 if (toonIndex >= 0) {
500 String extToonName = model.getToonTextureList().getToonFileName()[toonIndex];
502 toonTexture = loadTexture(folderName + extToonName);
503 } catch (Exception ex) {
504 String toonname = null;
507 toonname = "toon01.bmp";
510 toonname = "toon02.bmp";
513 toonname = "toon03.bmp";
516 toonname = "toon04.bmp";
519 toonname = "toon05.bmp";
522 toonname = "toon06.bmp";
525 toonname = "toon07.bmp";
528 toonname = "toon08.bmp";
531 toonname = "toon09.bmp";
534 toonname = "toon10.bmp";
537 if (toonname != null) {
538 toonTexture = loadTexture("toon/" + toonname);
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);
548 if (m.getEdgeFlag() != 0 /*
549 * && !(geom.getMesh() instanceof PMDSkinMesh)
551 // mat.setFloat("EdgeSize", 0.02f);
552 mat.setFloat("EdgeSize", 0.01f);
554 mat.setFloat("EdgeSize", 0f);
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);
567 // mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
568 // mat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Back);
569 // mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
570 // mat.getAdditionalRenderState().setAlphaTest(true);
575 void createSkeleton() {
576 TempVars temp = TempVars.get();
577 Bone[] boneArray = new Bone[model.getBoneList().getBoneCount()];
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;
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);
599 bone.setBindTransforms(v1, Quaternion.IDENTITY, new Vector3f(1, 1, 1));
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));
609 Skeleton skeleton = new Skeleton(boneArray);
610 PMDMesh meshes[] = meshList.toArray(new PMDMesh[meshList.size()]);
612 Quaternion q = new Quaternion();
613 q = q.fromAngleNormalAxis((float) Math.PI / 8, new Vector3f(0, 0, 1));
614 node.skeleton = skeleton;
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());
629 skinArray = skinList.toArray(new Skin[skinList.size()]);
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);
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);
664 SkeletonWire sw = new SkeletonWire(skeletonControl.skeleton);
665 PMDGeometry skeletonWireGeom = new PMDGeometry("skeletonWire", sw);
666 node.attachChild(skeletonWireGeom);
667 skeletonWireGeom.setMaterial(mat);
677 public Object load(AssetInfo ai) throws IOException {
678 boolean errFlag = false;
681 PMDLoaderGLSLSkinning2 loader = new PMDLoaderGLSLSkinning2();
682 return loader.load2(ai);
683 }catch(OutOfMemoryError ex) {
685 throw new RuntimeException(ex);
688 if (ai.getManager() instanceof DesktopAssetManager) {
689 ((DesktopAssetManager)ai.getManager()).clearCache();
692 System.runFinalization();
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) {
707 String vendor = GL11.glGetString(GL11.GL_VENDOR);
708 if (vendor != null && vendor.toLowerCase().contains("intel")) {
709 pmdNode.setGlslSkinning(false);
711 pmdNode.setGlslSkinning(true);
713 } catch(Exception ex) {
714 pmdNode.setGlslSkinning(false);
720 public void setFolderName(String folderName) {
721 this.folderName = folderName;
724 public String getFolderName() {
727 Texture loadTexture(String name) {
728 Texture tex = textureMap.get(name);
730 tex = assetManager.loadTexture(name);
731 textureMap.put(name, tex);