javascriptthree.js.objobjloader

Three.js: Load proper model scale/size


I am working on a three.js project where users are able to upload .obj models into a scene. The problem is I have two different sized models (one scaled to mm, other has an arbitrary scale). They are very clearly different in size when loaded in 3D model programs such as MeshLab and Blender, but they appear in the scene with the exact same size!

Q: What could be causing these two models that are clearly different in size, to load into three.js with the exact same size?

Here is proof the objects are loaded and saved with different scale

Here is the three.js project in question: https://pcforge.tech/3d-viewer/

Disclaimer - This is not an attempt at self-promotion so please do not see it as one. I am just asking for help as I cannot figure out the cause of the problem.

Edit: After some research, it is apparent .OBJ files do not preserve the unit/scale data across software platforms, so I am planning on allowing users to set their own unit dimensions (mm) when uploading models, and convert those units to the SI units when uploaded.


Solution

  • The Wavefront OBJ format unfortunately doesn't contain a unit parameter which means any vertices and scale could be relative to any unit, allowing us only to guess.

    Even if the model has the exact same vertices and scale they could have been made at different units which was proper for each object, but will be imported and shown at the same size. The modeler software may use its native unit as base for scale or the custom unit, or ignore it completely. it may contain original vertices or it may be normalized on export. No standard here.

    Some software solve this on import by trying to identify which software produced the model. The only place you can find this information, if at all, is in the non-standardized comment section found in the file header.

    An example of a file header:

    ####
    #
    #   OBJ File Generated by LightWave3D
    #   LightWave3D OBJ Export v2.3
    #
    ####
    ...
    

    (a non-standardized header but you could scan for "Lightwave3D .." in this case and used a fixed scale for that.)

    However, you would have to know how to parse each comment flavor and in some cases the model has been converted by a third-party software and the original source lost:

    #
    # Wavefront OBJ file: X:\somemodel.obj
    #
    # Converted by the PolyTrans geometry converter from Okino Computer Graphics, Inc.
    # Date/time of export: 02/02/2017 10:02:41
    #
    # Bounding box of geometry = (-163.899,-822.297,-1250.76) to (178.462,123.762,141.221).
    
    ...
    

    (which software produced the original?).

    Some will provide an import dialog letting you chose source and scale based on that, but also this comes with it's own challenges such as the ones mentioned above.

    The latter or something in spirit of it is also what you would need to implement if you want to import OBJ files and scale them to proper units. My suggestion would be to first normalize the geometry, setup a orthographic camera, use the object outline/cartoon render and use a background showing scale as a ruler; then have the user change the background scale until it's correct, or something of that sort (as you can imagine this can go in many different directions at various complexities).

    An alternative is to support a format which do embed units. Such a format in this case could Collada ("dae" files). It has a much wider scope and is more complex than OBJ, but stores units and has generally good support. THREE.js has an importer for collada (I haven't tested myself yet so I don't know how much of the scope of collada it covers or how well it imports).