THREE.js 加载 .OBJ 文件 - 为什么有些文件呈现扁平化?
THREE.js loading .OBJ files - why do some render flat?
我正在使用相同的通用代码从 OBJ 文件(从 Web 站点免费获得)加载基本网格对象(无纹理)。
有些物体呈现良好,因为不同的面向相机反射不同强度的光。但其他物体只是呈现出统一的哑光颜色,因此看不到它们的形状。
我查看了这些文件并注意到了各种差异。例如,一个成功的文件包含具有以下初始字符 v、vt、vn、f、s(vertex、vertext texture、vertex normal、face、smooth)的记录。不成功文件的示例具有以下初始字符:v、vt、f。
这是我正在使用的代码。
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
//... 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.
我猜想可能是顶点法线缺失的问题。但是添加代码更新它们对最终结果没有影响。
文件是否有问题,或者我可以在 THREE.js 中做些什么来使它们正确呈现?
您正确地发现了平面文件没有 "vn" 信息。
"vn" 表示 "vertex normal" -- 即(平滑的)法线所面对的方向。
您可以尝试调用类似 thisMeshOb.geometry.computeFaceNormals();
的方法,并可能在其后调用 thisMeshOb.geometry.computeVertexNormals();
-- 然后设置 thisMeshOb.geometry.normalsNeedUpdate = true;
-- 这将直接在三内计算一组新的法线。
你只需要在每个会话中调用一次,在读入时,顺便说一句——不需要重新计算每一帧。
我正在使用相同的通用代码从 OBJ 文件(从 Web 站点免费获得)加载基本网格对象(无纹理)。
有些物体呈现良好,因为不同的面向相机反射不同强度的光。但其他物体只是呈现出统一的哑光颜色,因此看不到它们的形状。
我查看了这些文件并注意到了各种差异。例如,一个成功的文件包含具有以下初始字符 v、vt、vn、f、s(vertex、vertext texture、vertex normal、face、smooth)的记录。不成功文件的示例具有以下初始字符:v、vt、f。
这是我正在使用的代码。
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
//... 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.
我猜想可能是顶点法线缺失的问题。但是添加代码更新它们对最终结果没有影响。
文件是否有问题,或者我可以在 THREE.js 中做些什么来使它们正确呈现?
您正确地发现了平面文件没有 "vn" 信息。
"vn" 表示 "vertex normal" -- 即(平滑的)法线所面对的方向。
您可以尝试调用类似 thisMeshOb.geometry.computeFaceNormals();
的方法,并可能在其后调用 thisMeshOb.geometry.computeVertexNormals();
-- 然后设置 thisMeshOb.geometry.normalsNeedUpdate = true;
-- 这将直接在三内计算一组新的法线。
你只需要在每个会话中调用一次,在读入时,顺便说一句——不需要重新计算每一帧。