Add color to .obj in ThreeJS

user3229941 picture user3229941 · Jan 24, 2014 · Viewed 7.5k times · Source

I am new to ThreeJS and have a simple question. I have the following code that will work properly, but I cannot add color to my .obj. The short and narrow of it is that I designed a game controller in Solidworks 2012, then I exported the CAD file as a .stl. I then used MeshLab to export the .stl as a .obj. Now I use the .obj in ThreeJS and it works, but I cannot for the life of me get color added to the .obj. Here is the code

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - loaders - vtk 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="" target="_blank">three.js</a> -
        vtk format loader test -
        model from <a href="" target="_blank">The GeorgiaTech Lagre Geometric Model Archive</a>,
        </div>

        <script src="three.min.js"></script>

        <script src="TrackballControls.js"></script>

        <script src="OBJLoader.js"></script>
        <script src="BinaryLoader.js"></script>
        <script src="Detector.js"></script>
        <script src="stats.min.js"></script>

        <script>

            if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

            var container, stats;

            var camera, controls, scene, renderer;

            var cross;

            init();
            animate();

            function init() {

                camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
                camera.position.z = 200;
                camera.position.y = 200;

                controls = new THREE.TrackballControls( camera );

                controls.rotateSpeed = 5.0;
                controls.zoomSpeed = 5;
                controls.panSpeed = 2;

                controls.noZoom = false;
                controls.noPan = false;

                controls.staticMoving = true;
                controls.dynamicDampingFactor = 0.3;

                scene = new THREE.Scene();

                scene.add( camera );

                // light

                var dirLight = new THREE.DirectionalLight( 0xffffff );
                dirLight.position.set( 20, 20, 100 ).normalize();

                camera.add( dirLight );
                camera.add( dirLight.target );

                // texture

                var manager = new THREE.LoadingManager();
                manager.onProgress = function ( item, loaded, total ) {

                    console.log( item, loaded, total );

                };

                var texture = new THREE.Texture();

                var loader = new THREE.ImageLoader( manager );
                loader.load( 'bigthumbnail.jpg', function ( image ) {

                    texture.image = image;
                    texture.needsUpdate = true;

                } );

                var loader = new THREE.OBJLoader()
                loader.load( 'Gamepad.obj', function ( object ) {

                    object.position.y = 0;
                    scene.add( object );                

                } );
                // renderer

                renderer = new THREE.WebGLRenderer( { antialias: false } );
                renderer.setSize( window.innerWidth, window.innerHeight );

                container = document.createElement( 'div' );
                document.body.appendChild( container );
                container.appendChild( renderer.domElement );

                stats = new Stats();
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.top = '0px';
                container.appendChild( stats.domElement );

                //

                window.addEventListener( 'resize', onWindowResize, false );

            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

                controls.handleResize();

            }

            function animate() {

                requestAnimationFrame( animate );

                controls.update();
                renderer.render( scene, camera );

                stats.update();

            }

        </script>

    </body>
</html>

I have poured through the threejs.org website and looked at most of the examples. All of the examples that use complex colors use .bin files or .js files. So I downloaded Python 2.7.6, installed it and ran convert_obj_three.py. This generated a .js file, but I'm not sure it is correctly formatted. Unfortunately, The output that convert_obj_three.py gave me is too large to post. My Second question is which file format is best for complex coloring, like chrome blue? .bin, .js or can I use .obj? If using a .js is the best way to go then how can I reliably convert the .obj file to .js? By the way, I tried using the .js that was created by convert_obj_three.py, but the webpage is blank all the time. Seems I cannot load the .js using THREE.JSONLoader().

Thanks in advance.

Answer

Shiva picture Shiva · Jan 24, 2014

after loader.load function is executed you get a threejs Object3D object. which contains the meshes of your object .

so you need to traverse over them to change the color of the material. The code will be something like this.

var loader = new THREE.OBJLoader()
                loader.load( 'Gamepad.obj', function ( object ) {

                   object.traverse( function ( child ) {
                             if ( child instanceof THREE.Mesh ) {
                                  child.material.ambient.setHex(0xFF0000);
                                  child.material.color.setHex(0x00FF00);
                                 }
                             } );

                    object.position.y = 0;
                    scene.add( object );                
            } );

Now the object's material has two properties which decides its color as you may see in the code ambient and color .

So this is to say that if in the scene you have white AmbientLight the object will appear Red(because the ambient property is set to #FF0000)

If the object is luminated by some other type of light like pointlight or directionalLight (as in your above case) the objects will appear Green(as color is set to #00FF00).

Now the last case if you have say that you have one white AmbientLight and one DirectionalLight in the Scene, then the object will appear as yellow as both material.ambient and material.color both will come into play and Red+Green will render as Yellow. Hoping this helps.