Using the Three.js Editor, I exported a project with a simple scene (two boxes). Everything loads fine—I see the two boxes from my PerspectiveCamera that I added. I want to control my camera view with the mouse wheel. Here is the script in the index.html:
<script type="module">
import * as THREE from './js/three.module.js';
import { APP } from './js/app.js';
import {OrbitControls} from './js/OrbitControls.js'; // I added this part.
// OrbitControls here?
var loader = new THREE.FileLoader();
loader.load( 'app.json', function ( text ) {
var player = new APP.Player( THREE );
player.load( JSON.parse( text ) );
player.setSize( window.innerWidth, window.innerHeight );
player.play();
document.body.appendChild( player.dom );
window.addEventListener( 'resize', function () {
player.setSize( window.innerWidth, window.innerHeight );
} );
} );
</script>
How do I utilize OrbitControls for this? Everything I've attempted (based on similar threads) leads to errors of things being undefined (like "camera" or "controls" depending on where I put it).
Alternatively (and even more ideally), is there a way to define the camera behavior I want within the Three.js Editor itself? That would be extra awesome!
EDIT
Thanks to #Mugen87 's original answer (basically that this isn't possible without editing app.js) here is the status of the question now. I removed the OrbitControls import from my index.html (above) and added it to my app.js. So my app.js currently looks like this:
import {OrbitControls} from './OrbitControls.js';
var APP = {
Player: function ( THREE ) {
window.THREE = THREE; // FIX for editor scripts (they require THREE in global namespace)
var loader = new THREE.ObjectLoader();
var camera, scene, renderer;
var events = {};
var dom = document.createElement( 'div' );
dom.className = "threejs-app";
this.dom = dom;
this.width = 500;
this.height = 500;
this.load = function ( json ) {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.setClearColor( 0x000000 );
renderer.setPixelRatio( window.devicePixelRatio );
var project = json.project;
if ( project.shadows ) renderer.shadowMap.enabled = true;
if ( project.vr ) renderer.xr.enabled = true;
dom.appendChild( renderer.domElement );
this.setScene( loader.parse( json.scene ) );
this.setCamera( loader.parse( json.camera ) );
events = {
init: [],
start: [],
stop: [],
keydown: [],
keyup: [],
mousedown: [],
mouseup: [],
mousemove: [],
touchstart: [],
touchend: [],
touchmove: [],
update: []
};
var scriptWrapParams = 'player,renderer,scene,camera';
var scriptWrapResultObj = {};
for ( var eventKey in events ) {
scriptWrapParams += ',' + eventKey;
scriptWrapResultObj[ eventKey ] = eventKey;
}
var scriptWrapResult = JSON.stringify( scriptWrapResultObj ).replace( /\"/g, '' );
for ( var uuid in json.scripts ) {
var object = scene.getObjectByProperty( 'uuid', uuid, true );
if ( object === undefined ) {
console.warn( 'APP.Player: Script without object.', uuid );
continue;
}
var scripts = json.scripts[ uuid ];
for ( var i = 0; i < scripts.length; i ++ ) {
var script = scripts[ i ];
var functions = ( new Function( scriptWrapParams, script.source + '\nreturn ' + scriptWrapResult + ';' ).bind( object ) )( this, renderer, scene, camera );
for ( var name in functions ) {
if ( functions[ name ] === undefined ) continue;
if ( events[ name ] === undefined ) {
console.warn( 'APP.Player: Event type not supported (', name, ')' );
continue;
}
events[ name ].push( functions[ name ].bind( object ) );
}
}
}
dispatch( events.init, arguments );
};
this.setCamera = function ( value ) {
camera = value;
camera.aspect = this.width / this.height;
camera.updateProjectionMatrix();
};
this.setScene = function ( value ) {
scene = value;
};
this.setSize = function ( width, height ) {
this.width = width;
this.height = height;
if ( camera ) {
camera.aspect = this.width / this.height;
camera.updateProjectionMatrix();
}
if ( renderer ) {
renderer.setSize( width, height );
}
};
function dispatch( array, event ) {
for ( var i = 0, l = array.length; i < l; i ++ ) {
array[ i ]( event );
}
}
var time, prevTime;
function animate() {
time = performance.now();
try {
dispatch( events.update, { time: time, delta: time - prevTime } );
} catch ( e ) {
console.error( ( e.message || e ), ( e.stack || "" ) );
}
renderer.render( scene, camera );
prevTime = time;
}
this.play = function () {
prevTime = performance.now();
document.addEventListener( 'keydown', onDocumentKeyDown );
document.addEventListener( 'keyup', onDocumentKeyUp );
document.addEventListener( 'mousedown', onDocumentMouseDown );
document.addEventListener( 'mouseup', onDocumentMouseUp );
document.addEventListener( 'mousemove', onDocumentMouseMove );
document.addEventListener( 'touchstart', onDocumentTouchStart );
document.addEventListener( 'touchend', onDocumentTouchEnd );
document.addEventListener( 'touchmove', onDocumentTouchMove );
dispatch( events.start, arguments );
renderer.setAnimationLoop( animate );
};
this.stop = function () {
document.removeEventListener( 'keydown', onDocumentKeyDown );
document.removeEventListener( 'keyup', onDocumentKeyUp );
document.removeEventListener( 'mousedown', onDocumentMouseDown );
document.removeEventListener( 'mouseup', onDocumentMouseUp );
document.removeEventListener( 'mousemove', onDocumentMouseMove );
document.removeEventListener( 'touchstart', onDocumentTouchStart );
document.removeEventListener( 'touchend', onDocumentTouchEnd );
document.removeEventListener( 'touchmove', onDocumentTouchMove );
dispatch( events.stop, arguments );
renderer.setAnimationLoop( null );
};
this.dispose = function () {
while ( dom.children.length ) {
dom.removeChild( dom.firstChild );
}
renderer.dispose();
camera = undefined;
scene = undefined;
renderer = undefined;
};
//
function onDocumentKeyDown( event ) {
dispatch( events.keydown, event );
}
function onDocumentKeyUp( event ) {
dispatch( events.keyup, event );
}
function onDocumentMouseDown( event ) {
dispatch( events.mousedown, event );
}
function onDocumentMouseUp( event ) {
dispatch( events.mouseup, event );
}
function onDocumentMouseMove( event ) {
dispatch( events.mousemove, event );
}
function onDocumentTouchStart( event ) {
dispatch( events.touchstart, event );
}
function onDocumentTouchEnd( event ) {
dispatch( events.touchend, event );
}
function onDocumentTouchMove( event ) {
dispatch( events.touchmove, event );
}
}
};
export { APP };
Side note: I'm noticing there are already many event listeners that were already generated by the Three.js Editor. They currently don't seem to do anything, but maybe they're there to be called from outside the script, such as in my index.html???
Anyway, where and how in the app.js file do I need to put the OrbitControls, in order to control the Y-axis position of the PerspectiveCamera with the mousewheel?
Alternatively (and even more ideally), is there a way to define the camera behavior I want within the Three.js Editor itself?
Unfortunately no. You can only use the default controls which are defined by EditorControls, a class similar to OrbitControls but only used in the editor.
How do I utilize OrbitControls for this?
I'm afraid this is not possible without changing app.js. The camera and the renderer are created in within APP.Player and are not public accessible. Since you need both objects for creating OrbitControls, it's not possible to instantiate the controls in index.html.
If you decide to change app.js, use the following code to create the controls if you include OrbitControls via ES6 imports:
var controls = new OrbitControls( camera, renderer.domElement );
three.js R112
Related
I have implemented a three.js viewer for my panoramic pictures a couple of years ago and now that I'm moving my site to another location, I have an issue with Three.js not willing to load anymore.
Error message in the console:
DOMException: "The operation is insecure."
Here is the html part I'm using:
<div class="article-pano-gallery" style="display:table">
<img onclick="init('https://images.laurentwillen.be/sites/21/2017/05/photo-panoramique-360-Catane.jpg')" class="article-gallery-image pano-image" data-srcset="https://images.laurentwillen.be/sites/21/2017/05/photo-panoramique-360-Catane.jpg" src="https://images.laurentwillen.be/sites/21/2017/05/photo-panoramique-360-Catane-150x150.jpg" width="150" height="150">
</div>
And for the JS part:
<script async src="https://ajax.googleapis.com/ajax/libs/threejs/r84/three.min.js"></script>
<script>
var camera, scene, renderer;
var isUserInteracting = false,
onMouseDownMouseX = 0, onMouseDownMouseY = 0,
lon = 0, onMouseDownLon = 0,
lat = 0, onMouseDownLat = 0,
phi = 0, theta = 0;
function init(full_image)
{
var container, mesh;
container = document.getElementById( 'background-section' );
document.getElementById( 'background-section') .style.display='block';
document.getElementById( 'pano-loading-section') .style.display='block';
document.getElementById( 'close') .style.display='block';
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
var geometry = new THREE.SphereBufferGeometry( 500, 60, 40 );
// invert the geometry on the x-axis so that all of the faces point inward
geometry.scale( - 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {
map: new THREE.TextureLoader().load( full_image )
} );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth*0.95, window.innerHeight*0.95 );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousedown', onPointerStart, false );
document.addEventListener( 'mousemove', onPointerMove, false );
document.addEventListener( 'mouseup', onPointerUp, false );
document.addEventListener( 'wheel', onDocumentMouseWheel, false );
document.addEventListener( 'touchstart', onPointerStart, false );
document.addEventListener( 'touchmove', onPointerMove, false );
document.addEventListener( 'touchend', onPointerUp, false );
document.addEventListener( 'dragover', function ( event )
{
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}, false );
document.addEventListener( 'dragenter', function ()
{
document.body.style.opacity = 0.5;
}, false );
document.addEventListener( 'dragleave', function ()
{
document.body.style.opacity = 1;
}, false );
document.addEventListener( 'drop', function ( event )
{
event.preventDefault();
var reader = new FileReader();
reader.addEventListener( 'load', function ( event ) {
material.map.image.src = event.target.result;
material.map.needsUpdate = true;
}, false );
reader.readAsDataURL( event.dataTransfer.files[ 0 ] );
document.body.style.opacity = 1;
}, false );
//
window.addEventListener( 'resize', onWindowResize, false );
document.getElementById( 'pano-loading-section') .style.display='none';
animate();
}
function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth*0.95, window.innerHeight*0.95 );
}
function onPointerStart( event )
{
isUserInteracting = true;
var clientX = event.clientX || event.touches[ 0 ].clientX;
var clientY = event.clientY || event.touches[ 0 ].clientY;
onMouseDownMouseX = clientX;
onMouseDownMouseY = clientY;
onMouseDownLon = lon;
onMouseDownLat = lat;
}
function onPointerMove( event )
{
if ( isUserInteracting === true )
{
var clientX = event.clientX || event.touches[ 0 ].clientX;
var clientY = event.clientY || event.touches[ 0 ].clientY;
lon = ( onMouseDownMouseX - clientX ) * 0.1 + onMouseDownLon;
lat = ( clientY - onMouseDownMouseY ) * 0.1 + onMouseDownLat;
}
}
function onPointerUp()
{
isUserInteracting = false;
}
function onDocumentMouseWheel( event )
{
var fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.Math.clamp( fov, 10, 75 );
camera.updateProjectionMatrix();
}
function animate()
{
requestAnimationFrame( animate );
update();
}
function update()
{
if ( isUserInteracting === false )
{
lon += 0.1;
}
lat = Math.max( - 85, Math.min( 85, lat ) );
phi = THREE.Math.degToRad( 90 - lat );
theta = THREE.Math.degToRad( lon );
camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
camera.target.y = 500 * Math.cos( phi );
camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );
camera.lookAt( camera.target );
/*
// distortion
camera.position.copy( camera.target ).negate();
*/
renderer.render( scene, camera );
}
</script>
I was using the same script on another domain for images and it was working well but now that I have moved, it doesn't work anymore.
I suppose it has something to do with cross domain but I don't see where exactly. I have tried a local version of the JS file and it's the same issue.
The error in the JS occurs on line 121. Here is the full text as requested below:
DOMException: "The operation is insecure." three.js:121:396
texImage2D https://wp.laurentwillen.be/js/three.js:121
n https://wp.laurentwillen.be/js/three.js:97
setTexture2D https://wp.laurentwillen.be/js/three.js:181
hf https://wp.laurentwillen.be/js/three.js:7
upload https://wp.laurentwillen.be/js/three.js:343
G https://wp.laurentwillen.be/js/three.js:147
renderBufferDirect https://wp.laurentwillen.be/js/three.js:165
n https://wp.laurentwillen.be/js/three.js:134
render https://wp.laurentwillen.be/js/three.js:180
update https://wp.laurentwillen.be/circuits/circuit-italie/catane/?bb:1679
animate https://wp.laurentwillen.be/circuits/circuit-italie/catane/?bb:1659
Thanks
This is definitely a CORS issue. I recommend you get yourself acquainted with how modern browsers handle cross-domain requests.
My best guess is that your images.laurentwillen.be server isn't configured to allow delivering assets to other domains. This is a safety feature so other people don't steal your bandwidth (you probably wouldn't want 1000s of sites freeloading by using images hosted on your server).
There are 2 solutions to this problem:
Host the images in the same domain where they're being requested.
Figure out how to let your server allow delivery of images to the domain where you're using them. The way to achieve this depends on the type of server you're running and you'll have to do some digging to figure out how to configure it, so solution 1 would be easiest.
I'm using the https://threejs.org/editor/ to export a webgl animation and I'm trying to figure out how to convert it to have a transparent background.
I'm essentially trying to put a div with text behind my animating threejs render.
I tried adding
renderer = new THREE.WebGLRenderer( { alpha: true,} );
renderer.setClearColor( 0xffffff, 0 );
but it doesn't seem to be working
I'm new to this so any help would be greatly appreciated!
Attached is my code so far
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta name="generator" content="Three.js Editor">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: sans-serif;
font-size: 13px;
background-color: black;
margin: 0px;
overflow: hidden;
}
.text {
font-size: 30vw;
color: white;
font-family: helvetica;
position: absolute;
z-index: 0;
}
</style>
</head>
<body ontouchstart="">
<script src="js/three.min.js"></script>
<script src="js/app.js"></script>
<script>
var loader = new THREE.FileLoader();
loader.load( 'app.json', function ( text ) {
var player = new APP.Player();
player.load( JSON.parse( text ) );
player.setSize( window.innerWidth, window.innerHeight );
player.play();
document.body.appendChild( player.dom );
window.addEventListener( 'resize', function () {
player.setSize( window.innerWidth, window.innerHeight );
} );
} );
</script>
<div class="text">Text Here</div>
</body>
</html>
And .js file
var APP = {
Player: function () {
var loader = new THREE.ObjectLoader();
var camera, scene, renderer;
var events = {};
var dom = document.createElement( 'div' );
this.dom = dom;
this.width = 500;
this.height = 500;
this.load = function ( json ) {
renderer = new THREE.WebGLRenderer( { alpha: true,} );
renderer.setClearColor( 0xffffff, 0 );
renderer.gammaOutput = true;
renderer.setPixelRatio( window.devicePixelRatio );
var project = json.project;
if ( project.shadows ) renderer.shadowMap.enabled = true;
if ( project.vr ) renderer.vr.enabled = true;
dom.appendChild( renderer.domElement );
this.setScene( loader.parse( json.scene ) );
this.setCamera( loader.parse( json.camera ) );
events = {
init: [],
start: [],
stop: [],
keydown: [],
keyup: [],
mousedown: [],
mouseup: [],
mousemove: [],
touchstart: [],
touchend: [],
touchmove: [],
update: []
};
var scriptWrapParams = 'player,renderer,scene,camera';
var scriptWrapResultObj = {};
for ( var eventKey in events ) {
scriptWrapParams += ',' + eventKey;
scriptWrapResultObj[ eventKey ] = eventKey;
}
var scriptWrapResult = JSON.stringify( scriptWrapResultObj ).replace( /\"/g, '' );
for ( var uuid in json.scripts ) {
var object = scene.getObjectByProperty( 'uuid', uuid, true );
if ( object === undefined ) {
console.warn( 'APP.Player: Script without object.', uuid );
continue;
}
var scripts = json.scripts[ uuid ];
for ( var i = 0; i < scripts.length; i ++ ) {
var script = scripts[ i ];
var functions = ( new Function( scriptWrapParams, script.source + '\nreturn ' + scriptWrapResult + ';' ).bind( object ) )( this, renderer, scene, camera );
for ( var name in functions ) {
if ( functions[ name ] === undefined ) continue;
if ( events[ name ] === undefined ) {
console.warn( 'APP.Player: Event type not supported (', name, ')' );
continue;
}
events[ name ].push( functions[ name ].bind( object ) );
}
}
}
dispatch( events.init, arguments );
};
this.setCamera = function ( value ) {
camera = value;
camera.aspect = this.width / this.height;
camera.updateProjectionMatrix();
if ( renderer.vr.enabled ) {
dom.appendChild( THREE.WEBVR.createButton( renderer ) );
}
};
this.setScene = function ( value ) {
scene = value;
};
this.setSize = function ( width, height ) {
this.width = width;
this.height = height;
if ( camera ) {
camera.aspect = this.width / this.height;
camera.updateProjectionMatrix();
}
if ( renderer ) {
renderer.setSize( width, height );
}
};
function dispatch( array, event ) {
for ( var i = 0, l = array.length; i < l; i ++ ) {
array[ i ]( event );
}
}
var time, prevTime;
function animate() {
time = performance.now();
try {
dispatch( events.update, { time: time, delta: time - prevTime } );
} catch ( e ) {
console.error( ( e.message || e ), ( e.stack || "" ) );
}
renderer.render( scene, camera );
prevTime = time;
}
this.play = function () {
prevTime = performance.now();
document.addEventListener( 'keydown', onDocumentKeyDown );
document.addEventListener( 'keyup', onDocumentKeyUp );
document.addEventListener( 'mousedown', onDocumentMouseDown );
document.addEventListener( 'mouseup', onDocumentMouseUp );
document.addEventListener( 'mousemove', onDocumentMouseMove );
document.addEventListener( 'touchstart', onDocumentTouchStart );
document.addEventListener( 'touchend', onDocumentTouchEnd );
document.addEventListener( 'touchmove', onDocumentTouchMove );
dispatch( events.start, arguments );
renderer.setAnimationLoop( animate );
};
this.stop = function () {
document.removeEventListener( 'keydown', onDocumentKeyDown );
document.removeEventListener( 'keyup', onDocumentKeyUp );
document.removeEventListener( 'mousedown', onDocumentMouseDown );
document.removeEventListener( 'mouseup', onDocumentMouseUp );
document.removeEventListener( 'mousemove', onDocumentMouseMove );
document.removeEventListener( 'touchstart', onDocumentTouchStart );
document.removeEventListener( 'touchend', onDocumentTouchEnd );
document.removeEventListener( 'touchmove', onDocumentTouchMove );
dispatch( events.stop, arguments );
renderer.setAnimationLoop( null );
};
this.dispose = function () {
while ( dom.children.length ) {
dom.removeChild( dom.firstChild );
}
renderer.dispose();
camera = undefined;
scene = undefined;
renderer = undefined;
};
//
function onDocumentKeyDown( event ) {
dispatch( events.keydown, event );
}
function onDocumentKeyUp( event ) {
dispatch( events.keyup, event );
}
function onDocumentMouseDown( event ) {
dispatch( events.mousedown, event );
}
function onDocumentMouseUp( event ) {
dispatch( events.mouseup, event );
}
function onDocumentMouseMove( event ) {
dispatch( events.mousemove, event );
}
function onDocumentTouchStart( event ) {
dispatch( events.touchstart, event );
}
function onDocumentTouchEnd( event ) {
dispatch( events.touchend, event );
}
function onDocumentTouchMove( event ) {
dispatch( events.touchmove, event );
}
}
};
You might need to adjust the CSS z-index of the <canvas> that ThreeJS is creating.
Note that the WebGLRenderer constructor has an overload that lets you pass in a canvas, instead of letting ThreeJS create it. This might be a useful in your case, so that you can easily control where the element lives in your DOM.
Hi guys I am working with kfAnimation animation from a Collada model. I want to include a trackball controls but when I do I exceed the size stack I dont know why my code is the following
function init() {
initRender();
// Camera
initCamera();
// Scene
initScene();
//controlls
initControls();
initGrid();
loadObjectAnimatedFrames();
window.addEventListener( 'resize', onWindowResize, false );
}
function loadObjectAnimatedFrames(){
loader = loader.load( 'sources/crack-animated.dae', function ( collada ) {
model = collada.scene;
animations = collada.animations;
kfAnimationsLength = animations.length;
//model.scale.x = model.scale.y = model.scale.z = 0.125; // 1/8 scale, modeled in cm
for ( var i = 0; i < kfAnimationsLength; ++i ) {
var animation = animations[ i ];
var kfAnimation = new THREE.KeyFrameAnimation( animation );
kfAnimation.timeScale = 1;
kfAnimations.push( kfAnimation );
}
start();
animate( lastTimestamp );
scene.add( model );
});
}
function initControls(){
controls = new THREE.TrackballControls(camera);
controls.minDistance = 100;
controls.maxDistance = 1800;
controls.addEventListener('change',render);
}
function animate( timestamp ) {
var frameTime = ( timestamp - lastTimestamp ) * 0.001;
if ( progress >= 0 && progress < 48 ) {
for ( var i = 0; i < kfAnimationsLength; ++i ) {
kfAnimations[ i ].update( frameTime );
}
} else if ( progress >= 48 ) {
for ( var i = 0; i < kfAnimationsLength; ++i ) {
kfAnimations[ i ].stop();
}
progress = 0;
start();
}
//pointLight.position.copy( camera.position );
progress += frameTime;
lastTimestamp = timestamp;
render();
}
I tried to put controls update inside animate and start function but I think it consumed a lot of resources. Also I tried to put inside render but same results.
Thanks for your help I hope some more experimented can help me.
Finally I found the solution and it was an option enableDamping and dampingFactor
function initControls(){
controls = new THREE.TrackballControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
}
after this I just add controls.update();
renderer.render( scene, camera );
requestAnimationFrame( animate );
My code below.
When I uncomment
object.rotation.y += ( targetRotation - object.rotation.y ) * 0.05; from render() or animate() function I get "Uncaught ReferenceError: object is not defined " error.
I tried anything, my animate() function is even in loader callback, I tried changing three.js to older version (currently using r59), hoped var object = event.content; might solve it, no effect.
I want to add "click and move your mouse to rotate model" usability, I have no problems with that when its cube.
but it just won't work with my *obj.
Help? =)
var scene, camera, renderer, loader, ambient, directionalLight;
var windowHalfX = 300;
var windowHalfY = 145;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
init();
function init() {
container = document.createElement( 'div' );
document.getElementById("3dbox").appendChild(container);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, 600 / 290, 0.1, 1000 );
//camera.position.set( -15, 10, 15 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( 600, 290 );
container.appendChild( renderer.domElement );
// MODEL
var loader = new THREE.OBJMTLLoader();
loader.addEventListener( 'load', function ( event ) {
var object = event.content;
scene.add( object );
animate();
});
loader.load( '<?php bloginfo('template_directory'); ?>/obj/female02.obj', '<?php bloginfo('template_directory'); ?>/obj/female02.mtl' );
camera.position.z = 100;
camera.position.y = 10;
ambient = new THREE.AmbientLight( 0x101030 );
scene.add( ambient );
directionalLight = new THREE.DirectionalLight( 0xffeedd );
directionalLight.position.set( 0, 0, 1 );
scene.add( directionalLight );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
}
function render() {
//object.rotation.y += ( targetRotation - object.rotation.y ) * 0.05;
renderer.render(scene, camera);
}
function animate() {
//object.rotation.y += ( targetRotation - object.rotation.y ) * 0.05;
requestAnimationFrame( animate );
render();
}
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
}
}
It is because "object" is a local variable in your callback function. Decare it globally:
var object;
Then in your callback,
object = event.content;
three.js r.59
I am attempting to rotate an object I uploaded along its y axis. The object uploads and the material is applied. I have used the same code to rotate a sphere but it does not seem to work with a custom object. If I un-comment the line at the bottom that is supposed to handle the actual rotation, the image no longer shows up as if there is an error.
Web GL Test
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
<script src="js/three.min.js"></script>
<script src="js/OBJLoader.js"></script>
<script type="text/javascript">
var container, stats;
var camera, scene, renderer;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 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( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 200;
camera.position.z = 150;
scene = new THREE.Scene();
var loader = new THREE.OBJLoader();
loader.addEventListener( 'load', function ( event ) {
var object = event.content;
var geom = new THREE.SphereGeometry( 100, 50, 50 );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.map = texture;
}
} );
object.position.y = 150;
scene.add( object );
});
loader.load( 'Head.obj' );
var texture = THREE.ImageUtils.loadTexture('face.gif');
texture.needsUpdate = true;
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, 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 onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
}
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
//object.rotation.y += ( targetRotation - object.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
</script>
</body>
The problem is that you use the variable "object" in the animate function before it is initialized. Also the variable "object" has a scope limited to the callback function of the loader.
You might want to read something about javascript variable scope.
http://www.mredkj.com/tutorials/reference_js_intro_ex.html
To solve your problem you might to change a few things.
1) Make the variable "object" global
// Make object a global variable
var camera, scene, renderer, object;
2) Do not call the animate function before the object is initialized
init();
//animate();
3) Do not use "var" inside callback function of the loader
var loader = new THREE.OBJLoader();
loader.addEventListener( 'load', function ( event ) {
//var object = event.content;
object = event.content;
var geom = new THREE.SphereGeometry( 100, 50, 50 );
4) Call "animate" after "object" is initialized
object.position.y = 150;
scene.add( object );
// Call animate after object is loaded and added to the scene
animate();
5) Good luck ;)