Pages

Saturday 5 January 2013

Importing 3DS Max Models into Unity 3D for iPhone/Android Games

I have started delving into the realm of 3D modeling for a Vuforia augmented reality based game I am developing. To that end I've been spending the past 2 weeks learning 3ds Max and some more Unity 3D (the game engine I am using to create the Vuforia AR based game). This article covers importing a 3D scene from 3ds Max into Unity with steps to optimize your scene for low spec devices by reducing the number of polygons, textures and draw calls.

I purchased a 3D model of a complex scene off of Turbo Squid. I'm a bit of a novice when it comes to 3D modeling so I decided to purchase an already made scene and modify it to suit my needs. As my game's intended platforms are Android and iOS devices I knew optimization would be key to good game experience. Following the standard Unity instructions on how to import a model from 3ds Max yielded me a few problems:
  • Importing the .max file directly into my Unity project's assets timed out after Unity gave up 3 minutes later trying to internally convert the .max file to an .fbx file.
  • Manually exporting the scene from 3ds to an .fbx file and then importing that into Unity gave me the scene, and despite the textures being imported into Unity no textures were being applied (everything was just gray).
  • Importing the .fbx into Unity took a very long time.
  • Deploying Unity app to my Android with just the gray scene crashed the app (more precisely, as soon as a Vuforia target was found in the camera frame).
  • A bunch of the Vray materials and lights were not exportable to .fbx.
The conclusion? My 90 MB max project with 70 MB of textures was too much for my 4 core laptop to achieve a workflow with any kind of acceptable speed, let alone the idea of trying to get the model to load on Android/iPhones ;-) What's more, Vray materials aren't compatible for exporting to .fbx so it would've been better if I'd got a 3D model using the standard renderer with standard materials. But as I had paid a nice sum for the Vray rendered version and liked the model, I pushed on.

The answer? Merge a bunch of objects all with their own materials/textures into a single mesh object and bake a rendered view of that mesh into a single texture (containing all the other textures/lighting/shadows) that then need be the only texture applied to the mesh as a material. In other words, we merge a bunch of multiple objects with different images attached to their surfaces into a single object with a single image file (texture).

Importing a multi-textured 3ds Max scene into Unity

I wrote the instructions below aimed at complete newbies who want to optimize their complex 3D scene suitable for a low spec handheld device like Android or iPhone. This is achieved by combining several objects into one mesh and baking a single texture image to apply to the mesh as the only material. The baked texture image will come from a rendered output of the object complete with its standard or Vray materials, any multisub object materials, shadows, lighting etc. The scene I happened to buy used the Vray renderer but the same instructions should be applicable to models that use the standard renderer as well.

NB. There is a plugin for 3ds Max called Flatiron that be used to bake entire scenes into one image texture. The full version costs a bit but if you have luck with the trial version you may wish to purchase it. I didn't have much luck so I decided to go the manual route, as detailed below.
  1. Open your 3D model scene in 3DS Max. I use 3ds Max 2010 with the trial version of Vray 1.5 SP4.
  2. Select the objects that have their own standard (and/or multi/sub) materials that you want to turn into a single mesh object with a single material.
    * To select objects, make sure the Select Object icon is the highlighted icon on the top horizontal toolbar (just below the row of main menus you should see a drop down list of All, Geometry, Shapes, Cameras, Lights etc. and beside that the Select Object icon which is a cube with a mouse pointer - in Max 2010 at least).
    Press Ctrl+left mouse click to select multiple objects within your scene. You also can click on the Select by Name icon and choose the objects from their names.
    Ctrl+A
    (or Edit -> Select All) will select all objects currently displayed in the viewport.
  3. Optional: press Alt+Q or Tools -> Isolate Selection to display only the selected objects in the current viewport.
  4. Select Group -> Ungroup as many times until all the selected objects are ungrouped. The Ungrouped menu item will become grayed out. This is to make sure you can Attach all items (covered below).
  5. Select one object, right click it and choose Convert To -> Convert to Editable Mesh.
  6. With the same object still selected, on the right hand panel of Max, select the Modify icon (2nd icon from the left on the top of the right-hand panel in 2010) and directly below that is the object's name, Modifier List (a drop down menu) and then the stack list (think layers of operations done on the object). Currently the only layer in the stack list should be Editable Mesh. After clicking Editable Mesh in the stack list you will see a few Editable Mesh related configuration sections appear below it.
  7. In the Edit Geometry section, click Attach List and the Attach List dialog window will popup. Assuming you're in isolated mode (Alt+Q a few steps back) then you can happily select all objects in that list and click the Attach button in the dialog window. This operation will effectively make all your objects into one single mesh object. Alternatively, click the Attach button next to Attach List and select objects individually if you're not in isolated mode. With the newly created Editable Mesh object selected, select Unwrap UVW from the Modifier List. You should now see in order from bottom to top, Editable Mesh and Unwrap UVW in your object's stack list.
  8. In the Unwrap UVW's Parameters panel, look for the section called Channel and change Map Channel to 2. If you get a warning about changing channels with the options to Move or Abandon, go with Move. I noticed this started appearing after I upgraded to 3ds Max 2013 and after trial and error Move seemed to be the best option.
  9. Click the small + icon next to Unwrap UVW in the stack list, select Face and press Ctrl+A (or Edit -> Select All) to select all faces.
  10. Click the Edit... button in the same Parameters panel and the UVW Editor window will open.
  11. Open Mapping -> Flatten Mapping and with the default values press OK.
  12. Depending on how many faces your object has, a while later you should see a bunch of green/white wireframe like figures neatly laid out in a square region representing the unwrapped version of all faces of your object. This so-called UV map will be the map of coordinates that tell how the 2D texture image is to be wrapped around the 3D mesh object.
  13. Close the UVW Editor.
  14. Select Unwrap UVW in the stack list.
  15. Making sure the object is still selected, press 0 or Rendering -> Render To Texture to open the Render To Texture dialog window. Here is where we generate the texture image by rendering the 3D model in Max and following the unwrapped UV map coordinates, the object's faces' materials will be baked onto that area of the texture image file.
  16. Under the General Settings section, Output set Path to a folder where you want the output image file saved.
  17. Under the Objects to Bake section, you should see the mesh object's name in the list.
  18. Under the Mapping Coordinates section, select Use Existing Channel next to Object.
  19. Select 2 from the drop down list next to Channel. If there is no 2, then it means the UV map was not unwrapped properly to channel 2.
  20. Under the Output section, click the Add button. If you are using the Vray renderer, select VRayCompleteMap. If you are using the standard renderer you can probably use CompleteMap but I haven't tried with that one. Using the complete map will ensure not only materials, but also lighting and shadows etc are baked in.
  21. Under the Selected Element Common Settings section, you should see something like:
    • Name: VRayCompleteMap
    • File Name and Type: <object name>VRayCompleteMap.xxx
    • Target Map Slot: Diffuse Map (select Diffuse map if its in the list)
    • Element Type: VRayCompleteMap
    • Width/height dimensions: the resolution of the output texture image.

      A few notes about this section:
      • If you select multiple mesh objects to render to texture at the same time (which is completely possible, just select them all before opening the Render To Texture dialog and they will all be listed under Objects to Bake), then the file name and type cannot be changed from the UI.
      • You can change the default type by:
        1. Open C:\Program Files\Autodesk\3ds Max 2010\ui\macroscripts\Macro_BakeTextures.mcr in a text editor.
        2. Change local    defaultFileType = ".tga" to local    defaultFileType = ".png"
          TGA seems to be the Max default, I prefer PNG but you can use JPG or TIF too.
        3. Restart Max.
      • Choosing the right resolution is a bit of an experiment and I'm still experimenting and discovering. It all comes down to the specs of the target devices that your game will run on, how many objects you have in total, how many faces in one mesh object, the actual content of the object (is it a far away stone in the background or a closeup thing requiring more detail?). So far I've been playing around with 512x512 to 1024x1024 resolutions with 10-30 objects and the scene has been rendering on my Android okay. This is a static environment though and those numbers still feel too high. You'll just have to experiment here. My approach is bake all your textures to high resolution and then scale them down as you test the level of detail of actual content rendered on a device until you're happy with the lowest image size vs content detail.
      • When selecting multiple objects to bake at the same time you may not be able to select Diffuse map in the Target Map Slot setting and may get some warnings about it not being set for some objects. So far I've been fine just ignoring these warnings or just having the Target Map Slot for multiple objects set to "varies".
  22. Down the very bottom, I set both Views and Render to Original. Then click the Render button.
  23. The render process may take some time. When it's finished it's not obvious with a "Render finished" message or anything. You should just see the preview window of the rendered texture image appear to be finished (and the fact your computer is no longer slowed down to a snail's pace and you can actually open the menus in Max etc!)
  24. Back on the stack list with Unwrap UVW selected, change the Map Channel that you set to 2 back to 1.
  25. Right-click Unwrap UVW and select Collapse All. This collapses all the layers in your stack into one layer.
  26. Open the Material Editor (4th icon from right on top toolbar in 2010 - the icon with a chequered circle with a small square bottom right).
  27. In one of the free slots (the spheres), drag/drop the texture image that was created from Windows Explorer. You will now have a new standard material with the image file attached as a bitmap texture on the diffuse channel.
  28. Now drag/drop that material slot (the sphere) onto the actual mesh object in your scene. And presto! You now have a single mesh object with a single rendered-to-texture image material.
  29. Things may look a bit fuzzy in 3ds Max viewport more than they actually do in Unity, I'm not sure why.
  30. Next I simply export the selected object(s) as an FBX (ensuring Insert Media is selected in the FBX settings window) and then import that FBX file into Unity and I have the same textured object to play with in Unity!
It's a long process, and quite manual. Same may prefer using Flatiron but I had more control over the individual objects here. If anyone with more experience than me finds an error in an article, please contact me or leave a comment and I'll amend it.

4 comments:

  1. What about a youtube tutorial please?

    ReplyDelete
  2. Good tutorial. Thank you~
    But it a bit hard to understand...
    You'd better take some screenshots whit the procedures(^^♪

    ReplyDelete
  3. Why do you collapse the Unwrap UVW modifier? You can export your mesh with the Unwrap UVW modifier applied and it works in Unity. I was just wondering what the reasoning is behind collapsing the modifiers, I can't see the difference.

    Oh, about the fuzziness in the Max Viewport you can use the Nitrous Texture Size Limit over at Scriptspot to increase the resolution of your textures. Cheers!

    ReplyDelete
  4. Hey!

    Trying my hands on Unity2d Development I was implementing to import 3DS Max Models into Unity 3D. This post is quite helpful. Thanks a lot for sharing.

    ReplyDelete