Fixing The Invisible Data Problem In 3D Max

I write this as I run a script on about 60,000 objects in my max scene scene.  I wanted to discuss why I had to write the  script to begin with, as it may help you in the future.  It's an automated solution to fix a common problem I run into working with engineering data and models from other applications in within 3D Studio Max.  It is a little bit of a hidden problem to begin with, but is quite prevalent once you are aware of it.  

Let's diagnose a scene to explain the problems.

The Symptoms...
  • Have you ever had geometry that wouldn't smooth properly?
  • Your model looks smooth in the viewport but looks faceted in render?
  • Have you ever had a model that looked pretty clean but the file size was inexplicably larger than you thought it should be?
  • Have you had a model where the reflections just seem wrong for no reason?
  • Here is a good visual example of the smoothing problem.
The Cause...

From what I gather, these can all be due to how data is treated during import.  I have run into these most frequently when using any kind of imported data....  STP, IGS, OBJ, FBX, etc. I am taking an educated guess that the issue is how different programs treat edge and face building, a logical culprit.   Knowing Max and Maya very well, they both treat smoothing differently, Max uses face ID's and Maya uses hard soft edges.  They also both have normal's, which I believe can be face, edge, or vertex based.  I am not a programmer, but I believe this invisible data is where the problems start piling up.  Importing seems to lock the normals of objects.  If you notice any of the above symptoms on your model, you've probably been annoyed and tried countless things to correct it.  You may have noticed that converting objects types and auto smooth didn't do much.  Countless pages like this really aren't going to help much either.  I don't think the object is corrupt... it's probably just storing lots of useless, possibly conflicting, data.  So let's get rid of it.

The Solution...

It is likely all of these issues can be solved with the same solution.  Rebuilding the surface from scratch in Max.  I tried a bunch of methods and noticed that the easiest way to deal with this is to create a blank object, and attach the old one.  Think of it like a book, the pages are fine, but the index has lots of duplicate and referenced stuff you don't care about.  Recreating an object essentially discards the old data index and builds a fresh one with only whats needed to make it.  Also, resetting the normals that are kept after the rebuild can fix persistent smoothing issues.  I find this is a winning one-two punch to fix strange geometry issues from imports.

Here are the basic steps to fix:
  1. Create a new object
  2. Clear out it's vertices so it is a blank object.
  3. Align it to the original source object, so pivots match.
  4. Attach the original to new blank object.  (invisible data killer)
  5. Force reset the object normals with Edit Normals Modifier
  6. Select all modifier normals and hit reset. (persistent normal issue killer)
  7. Collapse modifier and pretend you never had issues.

This works on multiple object selections and is a good way to purge data right when you're getting started.  This converts everything to polys.  If you want to save even more space, convert it to EditableMesh, they are smaller to store than EditablePolys are.  Also note I haven't dealt with materials in this code yet.

Here's the Initial Maxscript code:
selObjs = selection as array;
for oldObj in selObjs do
 (
 newObj = sphere isSelected:On
 newObj.transform = oldObj.transform
 convertToPoly newObj
 RememberThisName = oldObj.name
 thisMany = polyop.getNumVerts newObj
 polyop.deleteVerts newObj #{1..thisMany}
 polyop.attach newObj oldObj
 thisMany = polyop.getNumVerts newObj
 myEditNormals = Edit_Normals()
 addmodifier newObj myEditNormals 
 addModifier newObj (Edit_Normals())
 newObj.modifiers[#Edit_Normals].EditNormalsMod.SetSelection #{1..thisMany}
 newObj.modifiers[#Edit_Normals].EditNormalsMod.Reset ()
 convertToPoly newObj
 newObj.name = RememberThisName
 )
 select selObjs

Example scene size difference (can't show you geometry.... NDA):

Before: 544MB

After: Script purge and converted to editable mesh 212MB.

No scene difference except smoothing works properly afterward.

You're welcome.

That's all for now.