1

I'm trying to put a basic shader with animated displacement on an OBJ object. The shader works fine on a CubeBufferGeometry, but I can't get it to work with OBJLoader.

            // OBJ Loader
            var loader = new THREE.OBJLoader();
            loader.load( "obj/statue.obj", function ( group ) {
                geometry = group.children[ 0 ].geometry;
                geometry.attributes.uv2 = geometry.attributes.uv;
                geometry.center();

                mesh = new THREE.Mesh( geometry, material );
                mesh.scale.multiplyScalar( 15 );
                mesh.position.y = -700;

                mesh.traverse( function( node ) {
                    if( node.material ) {
                    node.material.side = THREE.DoubleSide;
                    }
                }); 
                mesh.traverse(function (child) {
                    if (child instanceof THREE.Mesh) {
                    child.geometry.computeFaceNormals();
                    }
                });

                scene.add( mesh );

                // Vertex Displacement
                vertexDisplacement = new Float32Array(geometry.attributes.position.count);
                    for (var i = 0; i < vertexDisplacement.length; i += 1){
                        vertexDisplacement[i] = Math.sin(i);
                }

                geometry.addAttribute('vertexDisplacement', new THREE.BufferAttribute(vertexDisplacement, 1));


            } );

However, in my render/animate function, my mesh variable is undefined (I already have var mesh as a global variable). I think this is because my mesh is also being defined in the OBJLoader function?

I get: 'TypeError: mesh is undefined'

Here's my render/animate function:

        var delta = 0;
        function animate() {

            requestAnimationFrame( animate );

            mesh.rotation.x += 0.005;
            mesh.rotation.y += 0.01;

            delta +=0.1;

            mesh.material.uniforms.delta.value = 0.5 + Math.sin(delta) * 0.5;

            for (var i = 0; i < vertexDisplacement.length; i += 1) {
                vertexDisplacement[i] = 0.5 + Math.sin(i * delta) * 0.25;
            }
            mesh.geometry.attributes.vertexDisplacement.needsUpdate = true;


            renderer.render( scene, camera );

        }
gman
  • 100,619
  • 31
  • 269
  • 393
qbuffer
  • 383
  • 4
  • 14
  • Not shown in the Q, so: you're handling the async aspect of loading the obj right? (starting the anim loop as the last step inside the load handler, or at least after the processing has finished). –  Jul 20 '17 at 22:35
  • I can load the obj fine, but when I call it in the anim loop it gives me the error (mesh is undefined). – qbuffer Jul 20 '17 at 22:39
  • 1
    I think what K3N is trying to say is that you should be waiting for your OBJ to load before calling your anim loop for the first time – 2pha Jul 21 '17 at 04:44

1 Answers1

1

You need to set your mesh variable.

Trying to access a declare global variable that has not been set will result in undefined

var mesh;
console.log(mesh);
// undefined
mesh = function(){};
console.log(mesh);
// function(){}
Alexander Higgins
  • 6,765
  • 1
  • 23
  • 41
  • Not exactly sure how to set my mesh variable for OBJLoader outside of its function. Could you be more specific in what I should do? – qbuffer Jul 20 '17 at 22:56
  • I am not familiar with the library but you can always set a global variable to an instance the private variable that you set inside of a function. – Alexander Higgins Jul 20 '17 at 23:16