问题
I'm trying establish why I can't smooth shade geometry loaded with OBJLoader.
var loader = new THREE.OBJLoader(manager);
loader.load('/manmodel/js/man.obj', function (object, materials) {
console.log(object);
console.log(materials);
man = object;
man.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.geometry.computeFaceNormals();
child.geometry.computeVertexNormals( true );
child.material = new THREE.MeshPhongMaterial({
color: 'white',
shading: THREE.SmoothShading // <----------- THIS IS THE PROBLEM
});
}
});
man.position.y = -10;
scene.add(man);
});
This is the result:
If I remove the line computeFaceNormals() the model renders the same. If I remove computeVertexNormals( true ) the object renders with no lighting (black) - so I know this is doing something.
If I change the color attribute of the MeshPhongMaterial in this code, the color changes, so I also know that this is working.
I have tried to use the vertex and normal helpers to establish what the problem is, but they fail because with BufferGeometry the faces and verticices are not stored as arrays.
I have also tried modifying the man.obj file to change the 's' values from 'off' to 1. This did nothing.
As I will be loading several .obj files for different human figures, generated in Blender, and each is currently around 2MB, I prefer to do the shading on the browser than to 'bake' it into the file if this would increase file size.
THE QUESTION(s): Am I missing something here? OR, Is there a way to load the .obj file as standard Geometry, compute the normals, apply the shading, and then save as BufferGeometry?
ps. I may also need the normals for ray tracing further down the line.
回答1:
The most recent version of ObjLoader parses the .obj to a BufferGeometry for performance reasons. If you look back through the history on GitHub you can find the previous version which parses to Geometry:
https://github.com/mrdoob/three.js/blob/a321ba05f02ae3a1586a4060a53f5ad63b90729b/examples/js/loaders/OBJLoader.js
Load your .obj using this and you can then manipulate the Geometry until you have it as you need it, then create a new BufferGeometry and load the Geometry into it using BufferGeometry.fromGeometry(geometry) in order to get the performance. I have this working nicely.
回答2:
If we want to use the most recent loader (r73), we can also convert the BufferGeometry
to a Geometry
, and then back!
The only caveat is that I had to merge the vertices before computing the vertex normals. I'm guessing that converting from the buffers messes with the triangles, so we gotta merge them before anything.
var geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
child.geometry = new THREE.BufferGeometry().fromGeometry( geometry );
来源:https://stackoverflow.com/questions/26607094/three-js-objloader-load-to-geometry-manipulate-then-save-to-buffergeometry