GLTFLoader global variable undefined - three.js

i'm learning three js and try to animate an gltf object rotation in three.js r98. But I get a Console Error: Variable obj undefined, but the variable is declared on top before the init script, so it should be global right. I don't see why this shouldn't work. If I use scene.rotation.y += 0.01; it works. But this is not usefull if there are other object which should not rotate^^. the variable model has the same error. With MLTD Loader this works: Loop Rotation on any axis for a 3D obj Three js. Instead of gltf.scene i tried gltf.asset but with same error.
Many Thanks for help.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script src="js/GLTFLoader.js"></script>
<script src="js/WebGL.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/dat.gui.min.js"></script>
<script>
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var stats, clock, mixer;
var camera, scene, renderer, model;
var obj;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 100 );
camera.position.set( 0, 3, 10);
camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0f );
scene.fog = new THREE.Fog( 0xe0e0e0, 20, 100 );
clock = new THREE.Clock();
// lights
var light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 20, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 20, 10 );
scene.add( light );
// model
var loader = new THREE.GLTFLoader();
loader.load( 'logo1.gltf', function( gltf ) {
model = gltf.scene;
model.scale.set(1,1,1);
obj = model;
scene.add( model );
//createGUI( model, gltf.animations );
}, undefined, function( e ) {
console.error( e );
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.gammaOutput = true;
renderer.gammaFactor = 2.2;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// stats
// stats = new Stats();
//container.appendChild( stats.dom );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
obj.rotation.y += 0.01;
requestAnimationFrame( animate );
renderer.render( scene, camera );
//stats.update();
}
</script>
</body>
</html>

The problem is that obj is only set when the onLoad() callback of GLTFLoader.load() fires. Since this happens in an asynchronous way, you should put the following line of code in your animate() function in order to solve the problem.
if ( obj ) obj.rotation.y += 0.01;

Related

one OrbitControls with two scenes

I want to sync the mouse control of two .dae files (in two scenes side-by-side) with OrbitControls. I can control any one object individually with any one of my scenes but any attempt to control both objects in sync fails.
It seems like I can only have one OrbitControls instance. Any one of the following 'controls#' lines works on its own but as soon as I have both, only the first one is operative:
controls1 = new OrbitControls( camera1, renderer1.domElement );
controls2 = new OrbitControls( camera2, renderer2.domElement );
I am a chemistry prof, not a programmer.Any help is gratefully appreciated. Thanks!
<html lang="en">
<head>
<title>GD - 2 mols</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<h3> VB orbital visualizer: 2 molecules</h3>
<div id="molcontainer1"></div>
<div id="molcontainer2"></div>
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims#1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "../three/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { ColladaLoader } from '../three/examples/jsm/loaders/ColladaLoader.js';
import { OrbitControls } from '../three/examples/jsm/controls/OrbitControls.js';
let molcontainer1, molcontainer2, camera1, camera2, scene1, scene2, renderer1, renderer2, mol1, mol2;
init();
//animate();
function init() {
molcontainer1 = document.getElementById( 'molcontainer1' );
molcontainer2 = document.getElementById( 'molcontainer2' );
//scene, camera, lighting, etc
scene1 = new THREE.Scene();
scene1.background = new THREE.Color( 0xbbffff );
scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0xffcccc );
camera1 = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera1.position.set( 0.4, 0.4, 0.4 );
camera1.lookAt( 0, 0, 0 );
camera2 = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera2.position.set( 0.4, 0.4, 0.4 );
camera2.lookAt( 0, 0, 0 );
const ambientLight1 = new THREE.AmbientLight( 0xffffff, 1 ); // was 0xcccccc
scene1.add( ambientLight1 );
const ambientLight2 = new THREE.AmbientLight( 0xffffff, 1 ); // was 0xcccccc
scene2.add( ambientLight2 );
const directionalLight1 = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight1.position.set( 1, 1, 1 ).normalize();
scene1.add( directionalLight1 );
const directionalLight2 = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight2.position.set( 1, 1, 1 ).normalize();
scene2.add( directionalLight2 );
renderer1 = new THREE.WebGLRenderer();
renderer1.outputEncoding = THREE.sRGBEncoding;
renderer1.setPixelRatio( window.devicePixelRatio );
renderer1.setSize( window.innerWidth/2, window.innerHeight/2 );
molcontainer1.appendChild( renderer1.domElement );
renderer2 = new THREE.WebGLRenderer();
renderer2.outputEncoding = THREE.sRGBEncoding;
renderer2.setPixelRatio( window.devicePixelRatio );
renderer2.setSize( window.innerWidth/2, window.innerHeight/2 );
molcontainer2.appendChild( renderer2.domElement );
// loading manager
const loadingManager = new THREE.LoadingManager( function () {
scene1.add( mol1 );
scene2.add( mol2 );
} );
// assign collada .dae file
const loader1 = new ColladaLoader( loadingManager );
loader1.load( './models/molecule.dae', function ( collada ) {
mol1 = collada.scene;
animate();
render();
} );
const loader2 = new ColladaLoader( loadingManager );
loader2.load( './models/CH2CHO.dae', function ( collada ) {
mol2 = collada.scene;
animate();
render();
} );
// 3d mouse controls
controls1 = new OrbitControls( camera1, renderer1.domElement );
controls2 = new OrbitControls( camera2, renderer2.domElement );
controls1.addEventListener( 'change', render );
controls2.addEventListener( 'change', render );
controls1.target.set( 0, 0, 0 );
controls2.target.set( 0, 0, 0 );
//controls.update();
window.addEventListener( 'resize', onWindowResize );
}
function animate() {
requestAnimationFrame( animate);
window.addEventListener( 'resize', onWindowResize ); // just added this
render();
}
function onWindowResize() {
camera1.aspect = window.innerWidth / window.innerHeight;
camera1.updateProjectionMatrix();
renderer1.setSize( window.innerWidth/2, window.innerHeight/2 );
camera2.aspect = window.innerWidth / window.innerHeight;
camera2.updateProjectionMatrix();
renderer2.setSize( window.innerWidth/2, window.innerHeight/2 );
render();
}
function render() {
renderer1.render( scene1, camera1 );
renderer2.render( scene2, camera2 );
//controls.update();
}
</script>
</body>
</html>```
You actually only need one camera and one OrbitControls to drive the two renderers and Scenes. The reason for this is that neither is intrinsically tied to the renderer or the Scene; the camera basically just tracks a group of variables that, on each frame, allow the renderer to compute its projection, and the OrbitControls only cares about the user's interaction with (a defined portion of) the page and the camera whose values it needs to mutate. (Note, as well, that neither a camera nor an OrbitControls takes any reference to a renderer or Scene when you initialize it, and most examples you see don't use Scene.Add() to add the camera to the scene graph.)
So, your code needs the following modifications.
First, wrap your molcontainer* divs inside of another div, and give it an ID of, say, molwrapper. This wrapper div will define the area on the page (comprising the two scenes) that will receive the user interaction for the OrbitControls. Use document.getElementById() to store a reference to molwrapper.
Next, remove all references to camera2 and rename camera1 to camera, and do the same with controls2 and controls1.
Finally, initialize controls (which used to be controls1) by passing it references to camera (which used to be camera1) and molwrapper.
I've posted a working example on CodePen.

Why is my camera so far from rendered model?

I am trying to create my first glTF model in Three.js rendered from Blender and I can not get the camera to display close to the rendered model.
No matter what I do to the Blender camera nothing fixes the problem so it must be the code that has been written in Three.js. Please help! Thx
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webglTF - 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 {
color: #046;
font-weight: bold;
}
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/libs/inflate.min.js"></script>
<script src="js/loaders/GLTFLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/WebGL.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var container, stats, controls;
var camera, scene, renderer, light;
var clock = new THREE.Clock();
var mixers = [];
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.set( -400, 0, 200 );
controls = new THREE.OrbitControls( camera );
controls.target.set( 0, 0, 0 );
controls.update();
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
light.position.set( 0, 200, 0 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 200, 100 );
light.castShadow = true;
light.shadow.camera.top = 180;
light.shadow.camera.bottom = -100;
light.shadow.camera.left = -120;
light.shadow.camera.right = 120;
scene.add( light );
// scene.add( new THREE.CameraHelper( light.shadow.camera )
);
// ground
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry(
2000, 2000 ), new THREE.MeshPhongMaterial( { material:
0x999999, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000
);
grid.material.opacity = 0.2;
grid.material.transparent = true;
scene.add( grid );
// model
var loader = new THREE.GLTFLoader();
loader.load( '../The-Raisin/TREE_GLTF.gltf', function ( gltf)
{
scene.add( gltf.scene );
}, undefined, function ( error ) {
console.error( error );
} );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// stats
stats = new Stats();
container.appendChild( stats.dom );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
if ( mixers.length > 0 ) {
for ( var i = 0; i < mixers.length; i ++ ) {
mixers[ i ].update( clock.getDelta() );
}
}
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
Camera is displayed outside of scene.
No matter what I do to the Blender camera nothing fixes the problem
Changing the camera properties in Blender has not effect if you define an own camera object in your application. You have two options:
Access gltf.cameras in your onLoad() callback which represents an array of cameras defined in the glTF asset. If the camera from Blender is exported, you should find it right there.
Improve the parameters of the camera defined in your application with an approach similar to 3D viewers. You usually center your object first and then derive optimal camera parameters from the object's AABB. Try to use the following code from this three.js based glTF viewer:
https://github.com/donmccurdy/three-gltf-viewer/blob/18f43073bbfdbd3c220e2059e548e74c507522d2/src/viewer.js#L218-L246
three.js R104

Collada load in THREE.js

I want to load collada file using three.js. I tried but the file is not showing. No error is also showing. I tried some other dae file but this dae file is not working. What's the issue i could not find. Is there problem with file or code ?
<script src="build/three.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/renderers/CSS3DRenderer.js"></script>
<script src="js/loaders/ColladaLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats, clock;
var camera, scene, renderer, elf;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.1, 10000 );
camera.position.set( 0, 0, 3000 );
//camera.position.z = 3000;
//camera.position.y = 150;
camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );
scene = new THREE.Scene();
clock = new THREE.Clock();
// loading manager
var loadingManager = new THREE.LoadingManager( function() {
scene.add( elf );
} );
// collada
var loader = new THREE.ColladaLoader( loadingManager );
loader.load( 'textures/sketup/pack.dae', function ( collada ) {
elf = collada.scene;
} );
//
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.8 );
directionalLight.position.set( 1, 1, 0 ).normalize();
scene.add( directionalLight );
//
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//
stats = new Stats();
container.appendChild( stats.dom );
//
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 );
render();
stats.update();
}
function render() {
var delta = clock.getDelta();
if ( elf !== undefined ) {
elf.rotation.y += delta * 0.5;
}
renderer.render( scene, camera );
}
</script>
I tried this code. But this code is not showing the collada file. What's the issue?
here is the file link
https://drive.google.com/file/d/0BxtPLq6DiFBkajVjRWJGaVBFSzNkbkdlQWdhMTkzQ0hQY0hR/view

Rotate a moving model to be parallel on a plane geometry

I am trying to rotate a model on a plane geometry that represents a hill. I use the following code. My problem is that though the model see to have the correct rotation when start animating and is parallel to the face it is moving when getting near and overcoming the point(0,0,0) it is rotating weirdly. Maybe the problem that I have set the up of the model to be the vector(0,0,1) (you can copy paste to an editor and view the example on your browser):
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - trackball controls</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 {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - trackball controls example</br>
MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
</div>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,mesh,animation,morph;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
// world
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(100,100,2,2);
var material = new THREE.MeshPhongMaterial({color: 0xff0000,side:THREE.DoubleSide,
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1});
var vertices = geometry.attributes.position.array;
vertices[ 14 ] =10;
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
// wireframe
var helper1 = new THREE.WireframeHelper( mesh, 0x000000 ); // or THREE.WireframeHelper
helper1.material.linewidth = 2;
scene.add( helper1 );
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
//
render();
}
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( 0, 0, -20 ),
new THREE.Vector3( 0, 0, 20 )
);
var helper = new THREE.Line( geometry, material );
scene.add( helper );
//////////
var loader = new THREE.JSONLoader( true );
loader.load( "http://threejs.org/examples/models/animated/horse.js", function( geometry ) {
morph = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x606060, morphTargets: true } ) );
morph.scale.set( 0.02, 0.02, 0.02 );
//morph.rotation.set(Math.PI/2,Math.PI/2+Math.PI/4,0);//rotate to look at the direction moving.
morph.position.set(-50,-50,0);
scene.add( morph );
animation = new THREE.MorphAnimation( morph );
animation.play();
} );
/////////
//raycaster function
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove( event ) {
mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
// See if the ray from the camera into the world hits one of our meshes
var intersects = raycaster.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersects.length > 0 ) {
helper.position.set( 0, 0, 0 );
helper.lookAt( intersects[ 0 ].face.normal );
document.body.style.cursor = "crosshair";
helper.position.copy( intersects[ 0 ].point );
render();
}
else{document.body.style.cursor = "auto";}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
var prevTime = Date.now();
function render() {
if ( animation ) {
var time = Date.now();
animation.update( time - prevTime );
prevTime = time;
}
if(morph){
if(morph.position.x>50){morph.position.x=-50;morph.position.y = -50;}
morph.position.x+=0.3;
morph.position.y+=0.3;
var help = helper.clone();
help.position.set(morph.position.x,morph.position.y,-10);
var ray= new THREE.Raycaster();
ray.set(help.position,new THREE.Vector3(0,0,1).normalize());
var intersect = ray.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersect.length > 0 ) {
morph.up.set(0,0,1);
morph.position.copy( intersect[ 0 ].point );
morph.lookAt( intersect[ 0 ].face.normal );
}
}
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
Any ideas to keep the models rotation parallel to the face it is on?
Similar question with this one that has no answer.
i have take the code above and after playing with it for a while was able to get the effect you were going for but maybe not the way that answers your question... here is what i have found anyway... and another note i think i was working with the code that was first posted..
so it's been a long time scene i have dealt with 3d code (2001-2002 time frame) so my knowledge may be both rusty and out of date with newer trends. plus i am new to this frame work.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - trackball controls</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 {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js - trackball controls example</br>
MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
</div>
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/Detector.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,mesh,animation,morph;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
// world
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(100,100,2,2);
var material = new THREE.MeshPhongMaterial({color: 0xff0000,side:THREE.DoubleSide,
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1});
var vertices = geometry.attributes.position.array;
vertices[ 14 ] =10;
mesh = new THREE.Mesh(geometry,material);
scene.add(mesh);
// wireframe
var helper1 = new THREE.WireframeHelper( mesh, 0x000000 ); // or THREE.WireframeHelper
helper1.material.linewidth = 2;
scene.add( helper1 );
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
container.addEventListener( 'mousemove', onMouseMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
//
render();
}
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( 0, 0, -20 ),
new THREE.Vector3( 0, 0, 20 )
);
var helper = new THREE.Line( geometry, material );
scene.add( helper );
//////////
var loader = new THREE.JSONLoader( true );
loader.load( "http://threejs.org/examples/models/animated/horse.js", function( geometry ) {
morph = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0x606060, morphTargets: true } ) );
morph.scale.set( 0.02, 0.02, 0.02 );
//morph.rotation.set(Math.PI/2,Math.PI/2+Math.PI/4,0);//rotate to look at the direction moving.
morph.position.set(-50,-50,0);
scene.add( morph );
animation = new THREE.MorphAnimation( morph );
animation.play();
} );
/////////
//raycaster function
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove( event ) {
mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
// See if the ray from the camera into the world hits one of our meshes
var intersects = raycaster.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersects.length > 0 ) {
helper.position.set( 0, 0, 0 );
helper.lookAt( intersects[ 0 ].face.normal );
document.body.style.cursor = "crosshair";
helper.position.copy( intersects[ 0 ].point );
render();
}
else{document.body.style.cursor = "auto";}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame( animate );
render();
controls.update();
}
var prevTime = Date.now();
function render() {
var DelX,DelY,DelZ,LastZ;
DelX=0.3;DelY=0.3;
if ( animation ) {
var time = Date.now();
animation.update( time - prevTime );
prevTime = time;
}
if(morph){
LastZ=morph.position.z;
if(morph.position.x>50){morph.position.x=-50;morph.position.y = -50.1;}
morph.position.x+=DelX;
morph.position.y+=DelY;
var help = helper.clone();
help.position.set(morph.position.x,morph.position.y,-10);
var ray= new THREE.Raycaster();
ray.set(help.position,new THREE.Vector3(0,0,1).normalize());
var intersect = ray.intersectObject( mesh );
// Toggle rotation bool for meshes that we clicked
if ( intersect.length > 0 ) {
morph.up.set(0,0,1);
morph.position.copy( intersect[ 0 ].point );
DelZ=morph.position.z-LastZ;
var PointToLookat = new THREE.Vector3(morph.position.x+DelX,morph.position.y+DelY,morph.position.z+DelZ);
morph.lookAt( PointToLookat );
// old morph.lookAt( intersect[ 0 ].face.normal );
}
}
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
so basically your LookAt is "pointing" the horse at some point in 3d space at first i assumed it was a vector direction and maybe that what you were assuming too, i at least was wrong, so you have to put your point "in front" of the current position of the object. i added some delta vars and kept track of the lastZ position value (as i write this i realized i could have used a vector for that) so i found the "next spot" the object will be at and used that as the PointToLookat.

three.js set background image

How to create a static background image?
For default background:
scene = new THREE.Scene();
// ...
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );
How to set a image for scene.fog, or set opacity for clearcolor?
If you are trying to set a static background image (even if you rotate your main camera, the background doesn't change), you have to create 2 scenes and 2 cameras.
The first scene will be composed of a basic plane on which a texture is applied.
The second scene will have all your objects.
Here is a code that would do it :
<html>
<body>
<script src="Three.js"></script>
<script>
var color = 0x000000;
// Create your main scene
var scene = new THREE.Scene();
// Create your main camera
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// Create lights
var light = new THREE.PointLight(0xEEEEEE);
light.position.set(20, 0, 20);
scene.add(light);
var lightAmb = new THREE.AmbientLight(0x777777);
scene.add(lightAmb);
// Create your renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a cube
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({
color: 0xff00ff,
ambient: 0x121212,
emissive: 0x121212
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// Set up the main camera
camera.position.z = 5;
// Load the background texture
var texture = THREE.ImageUtils.loadTexture( '1.jpg' );
var backgroundMesh = new THREE.Mesh(
new THREE.PlaneGeometry(2, 2, 0),
new THREE.MeshBasicMaterial({
map: texture
}));
backgroundMesh .material.depthTest = false;
backgroundMesh .material.depthWrite = false;
// Create your background scene
var backgroundScene = new THREE.Scene();
var backgroundCamera = new THREE.Camera();
backgroundScene .add(backgroundCamera );
backgroundScene .add(backgroundMesh );
// Rendering function
var render = function () {
requestAnimationFrame(render);
// Update the color to set
if (color < 0xdddddd) color += 0x0000ff;
// Update the cube color
cube.material.color.setHex(color);
// Update the cube rotations
cube.rotation.x += 0.05;
cube.rotation.y += 0.02;
renderer.autoClear = false;
renderer.clear();
renderer.render(backgroundScene , backgroundCamera );
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
**Demo right here **
Hope this helps.
NOTE (2014/06/28): This code works with the latest release of Three.js: R67
Use Texture loader to load a any image as texture and then apply that to scene like this:
//Load background texture
const loader = new THREE.TextureLoader();
loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' , function(texture)
{
scene.background = texture;
});
Result:
Demo:
See the Pen Flat Earth Three.JS by Hitesh Sahu (#hiteshsahu) on CodePen.
this run:
renderer = new THREE.WebGLRenderer({ antialias: false,alpha:true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor(0x000000, 0);
An background image can be set by setting the scene.background attribute of the THREE.Scene:
scene = new THREE.Scene();
bgTexture = loader.load("https://i.stack.imgur.com/vDUZz.jpg",
function ( texture ) {
var img = texture.image;
bgWidth= img.width;
bgHeight = img.height;
resize();
} );
scene.background = bgTexture;
bgTexture.wrapS = THREE.MirroredRepeatWrapping;
bgTexture.wrapT = THREE.MirroredRepeatWrapping;
The aspect ratio of the image can be adjusted to the aspect ratio of the canvas like this:
var aspect = window.innerWidth / window.innerHeight;
var texAspect = bgWidth / bgHeight;
var relAspect = aspect / texAspect;
bgTexture.repeat = new THREE.Vector2(
Math.max(relAspect, 1),
Math.max(1/relAspect,1) );
bgTexture.offset = new THREE.Vector2(
-Math.max(relAspect-1, 0)/2,
-Math.max(1/relAspect-1, 0)/2 );
See the code snippet:
(function onLoad() {
var container, loader, camera, scene, renderer, controls, bgTexture, bgWidth, bgHeight;
init();
animate();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, -4, -1.5);
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
bgTexture = loader.load("https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/background.jpg",
function ( texture ) {
var img = texture.image;
bgWidth= img.width;
bgHeight = img.height;
resize();
}
);
scene.background = bgTexture;
bgTexture.wrapS = THREE.MirroredRepeatWrapping;
bgTexture.wrapT = THREE.MirroredRepeatWrapping;
scene.add(camera);
window.onresize = resize;
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.x = -0.75;
directionalLight.position.y = -0.5;
directionalLight.position.z = -1;
scene.add( directionalLight );
controls = new THREE.OrbitControls(camera, renderer.domElement);
createModel();
}
function createModel() {
var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
var texAspect = bgWidth / bgHeight;
var relAspect = aspect / texAspect;
bgTexture.repeat = new THREE.Vector2( Math.max(relAspect, 1), Math.max(1/relAspect,1) );
bgTexture.offset = new THREE.Vector2( -Math.max(relAspect-1, 0)/2, -Math.max(1/relAspect-1, 0)/2 );
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://threejs.org/build/three.min.js"></script>
<!--script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script-->
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
thank you ))
I found yet another solution:
<!DOCTYPE html>
<head>
<title>three.js webgl - orbit controls</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 {
color: #000;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
background-image:url(./foto.jpg);
margin: 0px;
overflow: hidden;
}
#info {
color:#000;
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: red;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
three.js
</div>
<script src="./three.min.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<!--используем для вывода информации fps-->
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var cross;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera.position.z = 100;
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
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( './kos.jpg', function ( image ) {
texture.image = image;
texture.needsUpdate = true;
} );
// model
var loader = new THREE.OBJLoader( manager );
loader.load( './skull.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.map = texture;
}
} );
object.position.y = 10;
scene.add( object );
} );
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0xffffff );
scene.add( light );
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
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 );
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
It seems rather late in the day to be adding any contribution to this thread but here is my 'hap'orth':
<head>
<meta charset=utf-8>
<title>Temple7</title>
<style>
body { margin: 0;
}
canvas { width: 100%; height: 100%;
background-image:url(Clouds.jpg);
}
</style>
</head>
This rather simplistic approach has its limitations. The .jpg image retains its pixel dimensions so that, for different sizes of the browser window one sees different amounts of the image. If the canvas size exceeds the size of the .jpg, then tiling occurs.

Resources