0

I am using the same general purpose code to load basic mesh objects (no textures) from OBJ files (obtained free from sites on the web).

Some objects render OK in that different faces reflect light with different intensities towards the camera. But other objects just render a uniform matt color and so their form cannot be seen.

I have looked inside the files and noticed various differences. For example one successful file contains records with the following initial characters v, vt, vn, f, s (vertex, vertext texture, vertex normal, face, smooth). An example of an unsuccessful file has these initial characters: v, vt, f.

Here is the code which I am using.

function F_Load_OBJ_Model ( givenFilespec, givenName, givenScene, givenHexColorStr, posX, posY, posZ,  rotX, rotY, rotZ, scaleX, scaleY, scaleZ )
{

var OBJLoader = new THREE.OBJLoader();

OBJLoader.load( givenFilespec, F_make_LoadedOBJ_Handler ( givenName, givenScene, givenHexColorStr, posX, posY, posZ,  rotX, rotY, rotZ, scaleX, scaleY, scaleZ ) );

}


function F_make_LoadedOBJ_Handler( givenName, givenScene,     givenHexColorStr, posX, posY, posZ, rotX, rotY, rotZ, scaleX, scaleY, scaleZ )
{
    //... See Tapio's answer (callback factory for use in loops) 
    //... at http://stackoverflow.com/questions/10920372/associate-loaded-json-files-with-a-name-for-later-access
    //... This is useful in case have a loop loading multiple objects asynchronously.

return function ( object )
{
    //... Note that <object> is a THREE Object3D which can have 1 or more child meshes.
    //... But I will assume that there is only one child mesh.

    //var material = new THREE.MeshBasicMaterial();
    //eval( givenName + " = new THREE.Mesh( geometry, material );" );
    //eval ( " var thisMeshOb =" + givenName );
    //eval( givenName + " = object.children[0];" ); //....OK alias

    eval( givenName + " = object.children[0].clone();" );//... also OK

    //object.delete(); //... not possible or neccy, javascript will delete any object which cannot be referred to again.

    eval ( " var thisMeshOb =" + givenName );//... alias used for following common local commands

    thisMeshOb.position.set( posX, posY, posZ );
    thisMeshOb.rotation.set( rotX, rotY, rotZ );
    thisMeshOb.name = givenName; 
    thisMeshOb.scale.set( scaleX, scaleY, scaleZ );
    givenScene.add( thisMeshOb );
    //xxx thisMeshOb.material.type = THREE.MeshLambertMaterial();

    thisMeshOb.material.color.setHex( givenHexColorStr ) ;//...("0xff0000");

    thisMeshOb.geometry.computeFaceNormals(); //...no effect
    thisMeshOb.geometry.normalsNeedUpdate = true; //... no effect

    //... for PHONG ... floorGeometry.computeVertexNormals();   

    thisMeshOb.updateMatrix(); //... without this the next is not effective!?
    xxx = SOW_F_grob_Add_to_Target_Set( thisMeshOb );
};

}//... EOF F_make_LoadedOBJ_Handler. 

I guessed that it might be something to do with missing vertex normals. But adding the code to update them had no effect on the end result.

So is there a problem with the files or can I do something in THREE.js to make them render properly?

steveOw
  • 879
  • 12
  • 41

1 Answers1

1

You've found correctly that the flat-looking files have no "vn" info.

"vn" means "vertex normal" -- that is, the direction that the (smoothed) normal is facing.

You can try calling something like thisMeshOb.geometry.computeFaceNormals(); and possibly follow it with thisMeshOb.geometry.computeVertexNormals(); -- then set thisMeshOb.geometry.normalsNeedUpdate = true; -- this will calculate a new set of normals directly inside THREE.

You only need to call this once per session, at read-in time, btw -- no need to recalculate every frame.

bjorke
  • 3,295
  • 1
  • 16
  • 20
  • Ah yes I had tried the .computeFaceNormals and .normalsNeedUpdate but I had omitted .computeVertexNormals() thinking it was only needed for Phong materials (assuming that THREE.OBJLoader assigns Lambert material by default). Many thanks :). – steveOw Sep 23 '15 at 07:24
  • Update:see the answer by SPACORUM here: http://stackoverflow.com/questions/35136282/how-to-smooth-mesh-triangles-in-stl-loaded-buffergeometry (which also applies to OBJ sources). Also see the answer by Zydnar. Sometimes (exactly when isn't clear to me) after loading from OBJ you need to convert from (loaded)BufferGeometry to Geometry to run .mergeVertices(), then (if desired for performance) convert back to BufferGeometry, then make a final mesh. – steveOw Dec 03 '16 at 19:27