While testing the import/export between Rhino and Three, I have encountered some problems while visualising a fairly complicated obj file. I exported the obj from Rhino after triangulating the Mesh.
The problem shows indipendently from the material: with no material, with a material or/and with a texture applied within Three.
Jpeg of the geometry I try to import from Rhino vs the result on Three.js:
As you can see, there are some weird depth problems, especially depending on the camera position. I made a long research on the topic without finding a solution. I'll append some other topics on StackOverflow that I already have followed.
On my own, I tried also to check and flip the normals within Rhino, with no success.
My script (updated with Gaitat advice):
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loaders - OBJ loader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
z-index: 100;
display:block;
}
#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
</style>
</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank">three.js</a> - OBJLoader test
</div>
<script src="../build/three.min.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script>
var container;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 1, 2500 );
camera.position.z = 50;
// scene
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0x101030 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 );
scene.add( directionalLight );
// texture
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
var texture = new THREE.Texture();
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round(percentComplete, 2) + '% downloaded' );
}
};
var onError = function ( xhr ) {
};
var loader = new THREE.ImageLoader( manager );
loader.load( 'textures/UV_Grid_Sm.jpg', function ( image ) {
texture.image = image;
texture.needsUpdate = true;
} );
// model
loader = new THREE.OBJLoader( manager );
loader.load( 'obj/RU_obj/testTriangulated_again.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.map = texture;
}
} );
object.position.y = - 30;
object.scale.x = 0.5;
object.scale.y = 0.5;
object.scale.z = 0.5;
scene.add( object );
}, onProgress, onError );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
mouseX = ( event.clientX - windowHalfX ) / 2;
mouseY = ( event.clientY - windowHalfY ) / 2;
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * .05;
camera.position.y += ( - mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
And here it is my obj file: https://www.dropbox.com/s/di157kddzw5tasr/testTriangulated.obj?dl=0.
Thanks in advance.
Replace this code:
loader.load('obj/RU_obj/testTriangulated.obj', function(geometry) {
var material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
geometry.position.y = 0;
geometry.material = material;
scene.add(geometry);
});
with
var material = new THREE.MeshPhongMaterial( { color: 0x00ff00 } );
loader.load('obj/RU_obj/testTriangulated.obj', function(object) {
scene.add( new THREE.Mesh (object.geometry, material) );
});
You cannot assign the material as you did. What I am doing is using the geometry of the loaded object and creating a new mesh which I then add to the scene.
Update
Your object is actually inside out so what you are seeing is the inside of it. So in Rhino you have to change the normals or change the orientation of your polygons. The fix here is to use double sided material. This code has the fix:
<body>
<div id="info">
<a href="http://threejs.org" target="_blank">three.js</a> - OBJLoader test
</div>
<script src="../build/three.min.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script>
var container;
var camera, scene, renderer, controls;
var mouseX = 0, mouseY = 0;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 100;
// scene
scene = new THREE.Scene();
// lights
var ambient = new THREE.AmbientLight( 0x101030 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 );
scene.add( directionalLight );
// texture
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) { };
var texture = new THREE.Texture();
var loader = new THREE.ImageLoader( manager );
loader.load( 'textures/UV_Grid_Sm.jpg', function ( image )
{
texture.image = image;
texture.needsUpdate = true;
} );
// model
var loader = new THREE.OBJLoader( manager );
loader.load( 'testTriangulated.obj', function ( object )
{
object.traverse( function ( child )
{
if ( child instanceof THREE.Mesh )
{
child.material.map = texture;
child.material.side = THREE.DoubleSide;
}
} );
scene.add( object );
} );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// controls
controls = new THREE.TrackballControls (camera, renderer.domElement);
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate()
{
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
</script>
</body>