3dsmax.adoc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. = 3ds Max Bone Animation to JME3 using OgreMax plugin
  2. :revnumber: 2.1
  3. :revdate: 2020/07/24
  4. == Asset Management
  5. For the managing of assets in general, be sure to read the xref:tutorials:concepts/multi-media_asset_pipeline.adoc[Asset Pipeline Documentation]. It contains vital information on how to manage your asset files.
  6. == Creating models in 3dsMax
  7. For this tutorial I used 3D Studio Max 2012 and OgreMax 2.4.3 free edition
  8. === Create Model and Bones
  9. * Create a new file
  10. * Select the "`Create`" tab > "`Geometry`" > "`Cylinder`"
  11. image:how-to/modeling/3dsmax/3dsmax-0.png[3dsmax-0.png,width="",height=""]
  12. * Draw a cylinder, lets say with 8 height segments (must be enough for a smooth deformation)
  13. * Also check "`Generate Mapping Coords`".
  14. image:how-to/modeling/3dsmax/3dsmax-1.png[3dsmax-1.png,width="",height=""]
  15. * Click "`Create`" tab > "`Systems`" > "`Bones`"
  16. image:how-to/modeling/3dsmax/3dsmax-2.png[3dsmax-2.png,width="",height=""]
  17. * Add some bones in the center of the cylinder
  18. image:how-to/modeling/3dsmax/3dsmax-3.png[3dsmax-3.png,width="",height=""]
  19. * Select the cylinder, right click it and click "`Convert To`": > "`Convert to Editable Mesh`" to prevent issues with OgreMax
  20. * Click the "`Modify`" tab > "`Modifier List`" and add the "`Skin`" modifier
  21. image:how-to/modeling/3dsmax/3dsmax-4.png[3dsmax-4.png,width="",height=""]
  22. * Beneath "`Bones:`" click "`Add`" and select all of your bones
  23. image:how-to/modeling/3dsmax/3dsmax-5.png[3dsmax-5.png,width="",height=""]
  24. * You may also edit the envelopes, but for a small test the default settings are ok
  25. === Create the animation
  26. * Select the cylinder, and click "`Display`" tab > "`Freeze Selected`" so it is easier to select the bones during animation
  27. * Select the two top bones and enable the "`Auto Key`" mode
  28. image:how-to/modeling/3dsmax/3dsmax-6.png[3dsmax-6.png,width="",height=""]
  29. * The first key frame will be created automatically. Move the animation track slider to frame 5
  30. * Move the selected bones a bit. The cylinder mesh will be deformed. Because you are in the "`Auto Key`" mode, a key frame will be created
  31. image:how-to/modeling/3dsmax/3dsmax-7.png[3dsmax-7.png,width="",height=""]
  32. * Create some additional key frames. You may also select more bones and move or rotate them. I’ve created 25 frames and the last key frame equals the first, so the animation is loopable
  33. * After creating the animation, disable the "`Auto Key`" mode
  34. === OgreMax settings
  35. * Open the "`OgreMax Scene Settings`" dialog from the menu
  36. * In the "`Meshes`" tab, enable "`Export XML Files`" and disable "`Export Binary Files`" as well as "`Export Vertex Colors`"
  37. image:how-to/modeling/3dsmax/3dsmax-8.png[3dsmax-8.png,width="",height=""]
  38. * Click the "`Environment`" tab and uncheck "`Export Environment Settings`". Otherwise the JME importer will throw a NullPointerException
  39. image:how-to/modeling/3dsmax/3dsmax-9.png[3dsmax-9.png,width="",height=""]
  40. * If you have textured your model, you may also check "`Copy Bitmaps to Export Directory`" in the "`Bitmaps`" tab
  41. * Unfreeze the cylinder by clicking "`Display`" tab > "`Unfreeze All`" and select it
  42. * While having the cylinder selected, open the "`OgreMax Object Settings`" dialog from the menu
  43. * Open the "`Mesh Animations`" tab and select type "`Skeleton`", "`Export Skeleton`" : "`Yes`"
  44. * Below "`Mesh Animations`" hit the "`Add…`" button
  45. * Assign a name to the track, maybe "`wobble`". The track type must be "`Skin`". Set the right "`Start/End Frames`" for your animation
  46. image:how-to/modeling/3dsmax/3dsmax-10.png[3dsmax-10.png,width="",height=""]
  47. * Hit ok and you will see the animation in the table. You may add additional animations by selecting other frame ranges, if desired
  48. image:how-to/modeling/3dsmax/3dsmax-11.png[3dsmax-11.png,width="",height=""]
  49. === Export and Import
  50. * When all animations are in the list, select "`OgreMax`" > "`Export`" > "`Export Scene`" and name the file "`worm.scene`"
  51. * Create a JME test class that imports the file, get the animation controller and start the "`wobble`" animation
  52. [source,java]
  53. ----
  54. import com.jme3.animation.AnimChannel;
  55. import com.jme3.animation.AnimControl;
  56. import com.jme3.animation.Skeleton;
  57. import com.jme3.app.SimpleApplication;
  58. import com.jme3.asset.plugins.FileLocator;
  59. import com.jme3.light.AmbientLight;
  60. import com.jme3.light.PointLight;
  61. import com.jme3.material.Material;
  62. import com.jme3.math.ColorRGBA;
  63. import com.jme3.scene.Geometry;
  64. import com.jme3.scene.Node;
  65. import com.jme3.scene.Spatial;
  66. import com.jme3.scene.control.LodControl;
  67. import com.jme3.scene.debug.SkeletonDebugger;
  68. /**
  69. * This is a test class for loading a Ogre XML scene exported by OgreMax.
  70. *
  71. * @author Stephan Dreyer
  72. *
  73. */
  74. public class TestOgreMaxImport extends SimpleApplication {
  75. @Override
  76. public void simpleInitApp() {
  77. assetManager.registerLocator("Assets/model/ogre/test/", FileLocator.class);
  78. // create the geometry and attach it
  79. final Node model = (Node) assetManager.loadModel("worm.scene");
  80. // resize it, because of the large 3dsmax scales
  81. model.setLocalScale(.001f);
  82. // attach to root node
  83. rootNode.attachChild(model);
  84. addLodControl(model);
  85. final AnimControl ac = findAnimControl(model);
  86. try {
  87. // add a skeleton debugger to make bones visible
  88. final Skeleton skel = ac.getSkeleton();
  89. final SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton",
  90. skel);
  91. final Material mat = new Material(assetManager,
  92. "Common/MatDefs/Misc/Unshaded.j3md");
  93. mat.setColor("Color", ColorRGBA.Green);
  94. mat.getAdditionalRenderState().setDepthTest(false);
  95. skeletonDebug.setMaterial(mat);
  96. ((Node) ac.getSpatial()).attachChild(skeletonDebug);
  97. // create a channel and start the wobble animation
  98. final AnimChannel channel = ac.createChannel();
  99. channel.setAnim("wobble");
  100. } catch (final Exception e) {
  101. e.printStackTrace();
  102. }
  103. // add some lights
  104. rootNode.addLight(new AmbientLight());
  105. rootNode.addLight(new PointLight());
  106. }
  107. public void addLodControl(final Spatial parent) {
  108. if (parent instanceof Node) {
  109. for (final Spatial s : ((Node) parent).getChildren()) {
  110. addLodControl(s);
  111. }
  112. } else if (parent instanceof Geometry) {
  113. final LodControl lc = new LodControl();
  114. lc.setDistTolerance(1f);
  115. parent.addControl(lc);
  116. }
  117. }
  118. /**
  119. * Method to find the animation control, because it is not on the models root
  120. * node.
  121. *
  122. * @param parent
  123. * The spatial to search.
  124. * @return The {@link AnimControl} or null if it does not exist.
  125. */
  126. public AnimControl findAnimControl(final Spatial parent) {
  127. final AnimControl animControl = parent.getControl(AnimControl.class);
  128. if (animControl != null) {
  129. return animControl;
  130. }
  131. if (parent instanceof Node) {
  132. for (final Spatial s : ((Node) parent).getChildren()) {
  133. final AnimControl animControl2 = findAnimControl(s);
  134. if (animControl2 != null) {
  135. return animControl2;
  136. }
  137. }
  138. }
  139. return null;
  140. }
  141. public static void main(final String[] args) {
  142. new TestOgreMaxImport().start();
  143. }
  144. }
  145. ----
  146. You will see your worms strange movements. Have fun!
  147. image:how-to/modeling/3dsmax/3dsmax-12.png[3dsmax-12.png,width="",height=""]
  148. ==== 3ds Max Biped Animation to JME3
  149. You can also use the biped operator to animate models, but you have to consider a lot of things.
  150. === Creating a character in 3dsMax
  151. I will not tell you in detail how to model a character. There I many good tutorials on the web, I used link:http://majoh.deviantart.com/art/Mandi-s-3dsmax-Biped-Tutorial-26515784[that one].
  152. * You may create a biped before you start modeling, so it is quite easier to fit the proportions of the biped.
  153. * After creating a model and a biped I got something like that:
  154. image:how-to/modeling/3dsmax/1.png[1.png,width="",height=""]
  155. * I added the "`Meshsmooth`" modifier with 2 iterations and got this result:
  156. image:how-to/modeling/3dsmax/3dsmax_biped_2.png[3dsmax_biped_2.png,width="",height=""]
  157. * After smoothing your mesh you could correct vertices with the "`Edit Mesh`" modifier. Finally you add the "`Physique`" modifier.
  158. * Now you can edit your envelopes to fit your model.
  159. === Creating a simple walk animation
  160. * Select the chest of your biped, choose "`Motion`" (1) tab > "`Foot Step Mode`" (2) > "`Create Multiple Footsteps`" (3)
  161. * You need to select the "`In Place Mode`" (4), so the character moves in place without changing its location.
  162. image:how-to/modeling/3dsmax/3dsmax_biped_3_1.png[3dsmax_biped_3_1.png,width="",height=""]
  163. * You can now play a bit with the settings, I adjusted "`Actual Stride Length`" and "`Actual Stride Height`".
  164. * For the "`Number`" of Footsteps 6 will be sufficient because the animation is cycled later.
  165. * *Note:* You can also create or edit footsteps by hand and move or rotate them.
  166. * After all footsteps are created, hit the "`Create Keys`" for Inactive Footsteps button in the "`Footstep Operations`" panel
  167. * You can now check your animation by pressing the "`Play`" button in the timeline.
  168. === Preparing the export and setting up OgreMax
  169. * The "`OgreMax`" Scene Settings should be the same as shown above.
  170. * Because you want your animation to be looped, you've got to find two key frames where the legs are nearly in the same position. For my settings I've chosen the frames 48-78 for the walk animation.
  171. * Select the character mesh and open the "`OgreMax Scene Settings`" dialog.
  172. * Open the "`Mesh Animations`" tab and select type "`Skeleton`", "`Export Skeleton`" : "`Yes`"
  173. * Below "`Mesh Animations`" hit the "`Add…`" button
  174. image:how-to/modeling/3dsmax/3dsmax_biped_4.png[3dsmax_biped_4.png,width="",height=""]
  175. * Enter a name for the track, e.g. "`walk`".
  176. * Assure the track type is set to "`Physique`".
  177. * Set the start and end frames, for me it is 48-78.
  178. * Close the dialog by pushing "`Ok`".
  179. * *Note:* It could be useful to create also a track "`start_run`", that blends between the stand and walk animation. I would use frame 0-47 for that.
  180. * Because you have a smooth model with a lot of polygons, it may be useful to create xref:core:scene/mesh.adoc[levels of detail (LOD)]. When the camera is farther away, a low-poly mesh of your character will be rendered.
  181. image:how-to/modeling/3dsmax/3dsmax_biped_5.png[3dsmax_biped_5.png,width="",height=""]
  182. * Open the "`Mesh LOD`" tab in object settings.
  183. * It will suffice to select the "`Automatic`" setting, but if your animation starts to look weird, you can create them by hand.
  184. * I used 4 levels of LOD with a distance of 1. Don't worry about the distance setting, you can change it later in JME.
  185. * For the level reduction, I used 20 percent, which produce good results. You may adjust all the settings depending on your needs.
  186. * Close the dialog by clicking "`Ok`".
  187. === Fixing the location
  188. * Before you export you need to do a little fix, because your model is not really located where you see it. JME will get into a lot of trouble, if you don't change that.
  189. * Assure to save the max file. Sometimes OgreMax crashes the whole application during export. If you want to change the animation after export, you should reload this file because fixing the location changes something I can't really figure out.
  190. image:how-to/modeling/3dsmax/3dsmax_biped_6.png[3dsmax_biped_6.png,width="",height=""]
  191. * Right click the "`Select`" and Move tool in the upper toolbar. A dialog will pop up.
  192. * Set the X and Y location to 0 and close the dialog.
  193. * There is another way to achieve this. If you have scaled, moved or rotated your model, just open the "`Hierarchy`" tab and click "`Transform`" and "`Scale`" on the "`Reset`" panel.
  194. === Export and Import
  195. * Now you can export your scene. Select only the mesh and use "`Export`" selected objects. You will not need the whole scene including the biped object, but the bones are created automatically during export.
  196. * Create a JME test class for the scene import.
  197. For that, I extended the first class:
  198. [source,java]
  199. ----
  200. import com.jme3.animation.AnimChannel;
  201. import com.jme3.animation.AnimControl;
  202. import com.jme3.animation.Skeleton;
  203. import com.jme3.app.SimpleApplication;
  204. import com.jme3.asset.plugins.FileLocator;
  205. import com.jme3.light.AmbientLight;
  206. import com.jme3.light.PointLight;
  207. import com.jme3.material.Material;
  208. import com.jme3.math.ColorRGBA;
  209. import com.jme3.math.Vector3f;
  210. import com.jme3.scene.Geometry;
  211. import com.jme3.scene.Node;
  212. import com.jme3.scene.Spatial;
  213. import com.jme3.scene.control.LodControl;
  214. import com.jme3.scene.debug.SkeletonDebugger;
  215. import com.jme3.scene.shape.Box;
  216. /**
  217. * This is a test class for loading a Ogre XML scene exported by OgreMax.
  218. *
  219. * @author Stephan Dreyer
  220. *
  221. */
  222. public class TestOgreMaxImport extends SimpleApplication {
  223. @Override
  224. public void simpleInitApp() {
  225. assetManager.registerLocator("Assets/model/ogre/test/", FileLocator.class);
  226. // create the geometry and attach it
  227. final Node model = (Node) assetManager.loadModel("guy.scene");
  228. // resize it, because of the large 3dsmax scales
  229. model.setLocalScale(.02f);
  230. // attach to root node
  231. rootNode.attachChild(model);
  232. addLodControl(model);
  233. final AnimControl ac = findAnimControl(model);
  234. try {
  235. // add a skeleton debugger to make bones visible
  236. final Skeleton skel = ac.getSkeleton();
  237. final SkeletonDebugger skeletonDebug = new SkeletonDebugger("skeleton",
  238. skel);
  239. final Material mat = new Material(assetManager,
  240. "Common/MatDefs/Misc/Unshaded.j3md");
  241. mat.setColor("Color", ColorRGBA.Green);
  242. mat.getAdditionalRenderState().setDepthTest(false);
  243. skeletonDebug.setMaterial(mat);
  244. ((Node) ac.getSpatial()).attachChild(skeletonDebug);
  245. // create a channel and start the walk animation
  246. final AnimChannel channel = ac.createChannel();
  247. channel.setAnim("walk");
  248. } catch (final Exception e) {
  249. e.printStackTrace();
  250. }
  251. flyCam.setMoveSpeed(40f);
  252. cam.setLocation(new Vector3f(15, 10, 15));
  253. cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
  254. cam.setFrustumNear(1f);
  255. // add some lights
  256. rootNode.addLight(new AmbientLight());
  257. final PointLight pl = new PointLight();
  258. pl.setPosition(new Vector3f(-3f, 3f, 1f));
  259. rootNode.addLight(pl);
  260. // add a box as floor
  261. final Box b = new Box(100f, 0.1f, 100f);
  262. final Geometry geo = new Geometry("floor", b);
  263. final Material mat = new Material(assetManager,
  264. "Common/MatDefs/Misc/Unshaded.j3md");
  265. mat.setColor("Color", ColorRGBA.LightGray);
  266. geo.setMaterial(mat);
  267. rootNode.attachChild(geo);
  268. }
  269. /**
  270. * Method to traverse through the scene graph and add a {@link LodControl} to
  271. * the mesh.
  272. *
  273. * @param parent
  274. * The Node to add the control to.
  275. */
  276. public void addLodControl(final Spatial parent) {
  277. if (parent instanceof Node) {
  278. for (final Spatial s : ((Node) parent).getChildren()) {
  279. addLodControl(s);
  280. }
  281. } else if (parent instanceof Geometry) {
  282. final LodControl lc = new LodControl();
  283. // the distance for LOD changes is set here, you may adjust this
  284. lc.setDistTolerance(1f);
  285. parent.addControl(lc);
  286. }
  287. }
  288. /**
  289. * Method to find the animation control, because it is not on the models root
  290. * node.
  291. *
  292. * @param parent
  293. * The spatial to search.
  294. * @return The {@link AnimControl} or null if it does not exist.
  295. */
  296. public AnimControl findAnimControl(final Spatial parent) {
  297. final AnimControl animControl = parent.getControl(AnimControl.class);
  298. if (animControl != null) {
  299. return animControl;
  300. }
  301. if (parent instanceof Node) {
  302. for (final Spatial s : ((Node) parent).getChildren()) {
  303. final AnimControl animControl2 = findAnimControl(s);
  304. if (animControl2 != null) {
  305. return animControl2;
  306. }
  307. }
  308. }
  309. return null;
  310. }
  311. public static void main(final String[] args) {
  312. new TestOgreMaxImport().start();
  313. }
  314. }
  315. ----
  316. After starting the class, you can see a nice smooth walk animation (if it's not smooth, you need to adjust your track frames):
  317. image:how-to/modeling/3dsmax/3dsmax_biped_7.png[3dsmax_biped_7.png,width="",height=""]
  318. As you can see, the LOD is working:
  319. image:how-to/modeling/3dsmax/3dsmax_biped_8.png[3dsmax_biped_8.png,width="",height=""]