TestLodGeneration.java 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Copyright (c) 2009-2012 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package jme3test.stress;
  33. import com.jme3.animation.AnimChannel;
  34. import com.jme3.animation.AnimControl;
  35. import com.jme3.animation.SkeletonControl;
  36. import com.jme3.app.SimpleApplication;
  37. import com.jme3.bounding.BoundingBox;
  38. import com.jme3.font.BitmapText;
  39. import com.jme3.input.ChaseCamera;
  40. import com.jme3.input.KeyInput;
  41. import com.jme3.input.controls.ActionListener;
  42. import com.jme3.input.controls.KeyTrigger;
  43. import com.jme3.light.AmbientLight;
  44. import com.jme3.light.DirectionalLight;
  45. import com.jme3.math.ColorRGBA;
  46. import com.jme3.math.FastMath;
  47. import com.jme3.math.Vector3f;
  48. import com.jme3.scene.Geometry;
  49. import com.jme3.scene.Node;
  50. import com.jme3.scene.Spatial;
  51. import com.jme3.scene.VertexBuffer;
  52. import java.util.ArrayList;
  53. import java.util.List;
  54. import java.util.concurrent.Callable;
  55. import java.util.concurrent.ScheduledThreadPoolExecutor;
  56. import jme3tools.optimize.LodGenerator;
  57. public class TestLodGeneration extends SimpleApplication {
  58. public static void main(String[] args) {
  59. TestLodGeneration app = new TestLodGeneration();
  60. app.start();
  61. }
  62. boolean wireFrame = false;
  63. float reductionvalue = 0.0f;
  64. private int lodLevel = 0;
  65. private Node model;
  66. private BitmapText hudText;
  67. private List<Geometry> listGeoms = new ArrayList<Geometry>();
  68. private ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(5);
  69. private AnimChannel ch;
  70. public void simpleInitApp() {
  71. DirectionalLight dl = new DirectionalLight();
  72. dl.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
  73. rootNode.addLight(dl);
  74. AmbientLight al = new AmbientLight();
  75. al.setColor(ColorRGBA.White.mult(0.6f));
  76. rootNode.addLight(al);
  77. // model = (Node) assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
  78. model = (Node) assetManager.loadModel("Models/Jaime/Jaime.j3o");
  79. BoundingBox b = ((BoundingBox) model.getWorldBound());
  80. model.setLocalScale(1.2f / (b.getYExtent() * 2));
  81. // model.setLocalTranslation(0,-(b.getCenter().y - b.getYExtent())* model.getLocalScale().y, 0);
  82. for (Spatial spatial : model.getChildren()) {
  83. if (spatial instanceof Geometry) {
  84. listGeoms.add((Geometry) spatial);
  85. }
  86. }
  87. ChaseCamera chaseCam = new ChaseCamera(cam, inputManager);
  88. model.addControl(chaseCam);
  89. chaseCam.setLookAtOffset(b.getCenter());
  90. chaseCam.setDefaultDistance(5);
  91. chaseCam.setMinVerticalRotation(-FastMath.HALF_PI + 0.01f);
  92. chaseCam.setZoomSensitivity(0.5f);
  93. // ch = model.getControl(AnimControl.class).createChannel();
  94. // ch.setAnim("Wave");
  95. SkeletonControl c = model.getControl(SkeletonControl.class);
  96. if (c != null) {
  97. c.setEnabled(false);
  98. }
  99. reductionvalue = 0.80f;
  100. lodLevel = 1;
  101. for (final Geometry geometry : listGeoms) {
  102. LodGenerator lodGenerator = new LodGenerator(geometry);
  103. lodGenerator.bakeLods(LodGenerator.TriangleReductionMethod.PROPORTIONAL, reductionvalue);
  104. geometry.setLodLevel(lodLevel);
  105. }
  106. rootNode.attachChild(model);
  107. flyCam.setEnabled(false);
  108. guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
  109. hudText = new BitmapText(guiFont, false);
  110. hudText.setSize(guiFont.getCharSet().getRenderedSize());
  111. hudText.setText(computeNbTri() + " tris");
  112. hudText.setLocalTranslation(cam.getWidth() / 2, hudText.getLineHeight(), 0);
  113. guiNode.attachChild(hudText);
  114. inputManager.addListener(new ActionListener() {
  115. public void onAction(String name, boolean isPressed, float tpf) {
  116. if (isPressed) {
  117. if (name.equals("plus")) {
  118. // lodLevel++;
  119. // for (Geometry geometry : listGeoms) {
  120. // if (geometry.getMesh().getNumLodLevels() <= lodLevel) {
  121. // lodLevel = 0;
  122. // }
  123. // geometry.setLodLevel(lodLevel);
  124. // }
  125. // jaimeText.setText(computeNbTri() + " tris");
  126. reductionvalue += 0.05f;
  127. updateLod();
  128. }
  129. if (name.equals("minus")) {
  130. // lodLevel--;
  131. // for (Geometry geometry : listGeoms) {
  132. // if (lodLevel < 0) {
  133. // lodLevel = geometry.getMesh().getNumLodLevels() - 1;
  134. // }
  135. // geometry.setLodLevel(lodLevel);
  136. // }
  137. // jaimeText.setText(computeNbTri() + " tris");
  138. reductionvalue -= 0.05f;
  139. updateLod();
  140. }
  141. if (name.equals("wireFrame")) {
  142. wireFrame = !wireFrame;
  143. for (Geometry geometry : listGeoms) {
  144. geometry.getMaterial().getAdditionalRenderState().setWireframe(wireFrame);
  145. }
  146. }
  147. }
  148. }
  149. private void updateLod() {
  150. reductionvalue = FastMath.clamp(reductionvalue, 0.0f, 1.0f);
  151. makeLod(LodGenerator.TriangleReductionMethod.PROPORTIONAL, reductionvalue, 1);
  152. }
  153. }, "plus", "minus", "wireFrame");
  154. inputManager.addMapping("plus", new KeyTrigger(KeyInput.KEY_ADD));
  155. inputManager.addMapping("minus", new KeyTrigger(KeyInput.KEY_SUBTRACT));
  156. inputManager.addMapping("wireFrame", new KeyTrigger(KeyInput.KEY_SPACE));
  157. }
  158. @Override
  159. public void simpleUpdate(float tpf) {
  160. // model.rotate(0, tpf, 0);
  161. }
  162. private int computeNbTri() {
  163. int nbTri = 0;
  164. for (Geometry geometry : listGeoms) {
  165. if (geometry.getMesh().getNumLodLevels() > 0) {
  166. nbTri += geometry.getMesh().getLodLevel(lodLevel).getNumElements();
  167. } else {
  168. nbTri += geometry.getMesh().getTriangleCount();
  169. }
  170. }
  171. return nbTri;
  172. }
  173. @Override
  174. public void destroy() {
  175. super.destroy();
  176. exec.shutdown();
  177. }
  178. private void makeLod(final LodGenerator.TriangleReductionMethod method, final float value, final int ll) {
  179. exec.execute(new Runnable() {
  180. public void run() {
  181. for (final Geometry geometry : listGeoms) {
  182. LodGenerator lODGenerator = new LodGenerator(geometry);
  183. final VertexBuffer[] lods = lODGenerator.computeLods(method, value);
  184. enqueue(new Callable<Void>() {
  185. public Void call() throws Exception {
  186. geometry.getMesh().setLodLevels(lods);
  187. lodLevel = 0;
  188. if (geometry.getMesh().getNumLodLevels() > ll) {
  189. lodLevel = ll;
  190. }
  191. geometry.setLodLevel(lodLevel);
  192. hudText.setText(computeNbTri() + " tris");
  193. return null;
  194. }
  195. });
  196. }
  197. }
  198. });
  199. }
  200. }