I am trying to display an animation, in which an avatar moves her both arms. I created the animation on Blender (v2.75) and exported to JSON (r71). The result: the avatar appears on browser, but there is no animation (no movements of arms). Here is the code: jsfiddle and below is the complete code. Can someone help me please?
<html>
<head>
<title>My first Three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="models/three.js"></script>
<script>
var camera, light, renderer, objeto, animation, helpset, clock, animacao;
var loader;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
scene.add( new THREE.AmbientLight( 0x666666 ) );
light = new THREE.DirectionalLight( 0xdfebff, 1.75 );
light.position.set( 50, 200, 100 );
light.position.multiplyScalar( 1.3 );
light.castShadow = true;
//light.shadowCameraVisible = true;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
var d = 300;
light.shadowCameraLeft = -d;
light.shadowCameraRight = d;
light.shadowCameraTop = d;
light.shadowCameraBottom = -d;
light.shadowCameraFar = 1000;
light.shadowDarkness = 0.5;
scene.add( light );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera.position.z = 5;
clock = new THREE.Clock();
loader = new THREE.JSONLoader();
loader.load( 'models/SL-MD-avatar_erica95.json', addModel );
function addModel( geometry, materials ){
materials[0].skinning = true;
// materials[0].color = "0xb091cc";
var m = new THREE.MeshLambertMaterial(materials);
// console.log(materials[0]);
objeto= new THREE.SkinnedMesh( geometry, m);
objeto.castShadow = true;
objeto.receiveShadow = true;
helpset = new THREE.SkeletonHelper(objeto);
//scene.add(helpset);
// console.log(geometry.animations[0]);
animacao = objeto.geometry.animations[0];
var nome = objeto.geometry.animations[0]["name"];
console.log (nome);
var animation = new THREE.Animation (objeto, animacao);
console.log(animation);
animation.play();
console.log(animation.isPlaying);
scene.add(objeto);
// console.log(animation.data);
}
}
function render() {
delta = 0.75 * clock.getDelta();
scene.traverse(function(child) {
if (child instanceof THREE.SkinnedMesh){
child.rotation.y += .01;
}
});
THREE.AnimationHandler.update( delta );
}
function animate(){
requestAnimationFrame(animate);
render();
renderer.render(scene, camera);
}
init();
animate();
</script>
</body>
</html>
It looks like you have trouble using Blender. You just miss movements for the bones.
Look in the json :
"animations": [
{ // first object in the array (=animations[0])
"length": 2.36, // animation duration
"hierarchy": [{ // hierarchy : defines the keyframes for each bone
"keys": [{ // hierarchy[0] (first bone) : keys = keyframes
"pos": [0, 1.067, 0], // keys[0] at time 0 : defines pos, rot, scl
"rot": [0, 0, 0, 1],
"scl": [1, 1, 1],
"time": 0
}, { // keys[1] at 2.36 (=last keyframe)
"pos": [0, 1.067, 0],
"rot": [0, 0, 0, 1],
"scl": [1, 1, 1], // ! you can see values are identical to
"time": 2.36 // keys[0] ! so this bone won't move
}],
"parent": -1
}, {
.... // same for all hierarchy...
That means the animation is playing but nothing moves. Try to change any value (pos : [0,1.067,0] to pos:[3,5,20] for example) and you will see that the animation is really playing.
In blender you have to assign the movements to each keyframe.
It is almost complete ;)
Related
hey guys i am new to threejs and im trying to load a texture on top of my own gltf model and im trying to load it with gltf loader, imported using cdn scripts, however, i got this error saying gltf is not a constructor, any ideas how to fix it? thanks in advance. have a nice day. below attached is the code and errors involving this issue.
Uncaught TypeError: THREE.GLTFLoader is not a constructor
at init (index.html:90)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>3d model</title>
<style>
body {
margin: 0;
}
canvas {
position: fixed; top: 0; left: 0;
}
div#test2 {
height: 5000px;
}
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://cdn.jsdelivr.net/npm/three#0.114/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from 'https://cdn.jsdelivr.net/npm/three#0.114/examples/jsm/loaders/RGBELoader.js';
var container, controls;
var camera, scene, renderer, mixer, clock;
var obj , material , texture
init();
animate();
function init() {
container = document.getElementById( 'test' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.01, 1000 );
// camera.position.set(0, 5, 30);
camera.position.x = 0
camera.position.y = 5
camera.position.z = 10
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
var light = new THREE.HemisphereLight(0xffffff,0x000000,10);
scene.add(light);
clock = new THREE.Clock();
// model
// var loader = new GLTFLoader();
// loader.load( 'scene.gltf', function ( gltf ) {
// // var matcapTexture = new THREE.TextureLoader().load('purple.jpg')
// // var texture = new THREE.MeshMatcapMaterial( {matcap: matcapTexture})
// obj = scene.add( gltf.scene );
// // obj.material.map = texture
// // obj.material.needsUpdate = tru
// mixer = new THREE.AnimationMixer( gltf.scene );
// gltf.animations.forEach( ( clip ) => {
// mixer.clipAction( clip ).play();
// } );
// } );
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('purple.jpg');
texture.flipY = false;
var loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function(gltf) {
model = gltf.scene;
scene.add(model);
});
model.material.map = texture;
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 0.8;
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
function rotateFunction() {
obj.rotation.y += 0.02;
console.log(obj.rotation.y)
}
document.addEventListener('scroll', function(e) { rotateFunction() });
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
var delta = clock.getDelta();
if ( mixer ) mixer.update( delta );
renderer.render( scene, camera );
}
function adjustCamera() {
var t = scrollY / (5000 - innerHeight);
console.log(t)
// t is 0 to 1
camera.position.z = 10 + 5 * t;
}
document.addEventListener('scroll', function(e) { adjustCamera() });
function changeColor() {
obj.material = texture
console.log(obj)
}
document.addEventListener('scroll', function(e) { changeColor() });
</script>
</body>
<div id="test">
</div>
<div id="test2">
testing121
</div>
</html>
When you import GLTFLoader via ES6 imports, there is no need to use the THREE namespace. Just do this:
const loader = new GLTFLoader();
I wish to move a cube based on the movement of another cube to which TransformControls is attached by means of Matrix4() method only.
The attempts so far have failed to shift the follower cube.
I'm not sure why the follower doesn't seem to take the world co-ordinates of the directing cube.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - transform 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 {
margin: 0px;
background-color: #000000;
color: #fff;
font-family:Monospace;
text-align: center;
font-size: 15px;
line-height: 30px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
padding: 15px;
z-index:100;
}
</style>
</head>
<body>
<div id="info">
"W" translate | "E" rotate | "R" scale | "+" increase size | "-" decrease size<br />
Press "Q" to toggle world/local space, keep "Ctrl" down to snap to grid
</div>
<script src="build/three.js"></script>
<script src="js/controls/TransformControls.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script>
var camera, scene, renderer, control, mesh, mesh1;
init();
animate();
//render();
//update();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.sortObjects = false;
document.body.appendChild( renderer.domElement );
//
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
camera.position.set( 1000, 500, 1000 );
camera.lookAt( new THREE.Vector3( 0, 200, 0 ) );
scene = new THREE.Scene();
scene.add( new THREE.GridHelper( 1000, 10 ) );
var light = new THREE.DirectionalLight( 0xffffff, 2 );
light.position.set( 1, 1, 1 );
scene.add( light );
//var texture = new THREE.TextureLoader().load( 'textures/crate.gif', render );
//texture.mapping = THREE.UVMapping;
//texture.anisotropy = renderer.getMaxAnisotropy();
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
control = new THREE.TransformControls( camera, renderer.domElement );
control.addEventListener( 'change', render );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
control.attach( mesh );
scene.add( control );
var followerCube = new THREE.BoxGeometry( 200, 200, 200 );
var material1 = new THREE.MeshBasicMaterial( { color: 0xff9909 } );
mesh1 = new THREE.Mesh( followerCube, mesh1 );
scene.updateMatrixWorld();
mesh1.matrixAutoUpdate = false;
var relativeMeshOffset = new THREE.Vector3( 100, 100, 200 );
var offsetPosition = relativeMeshOffset.applyMatrix4( mesh.matrixWorld );
mesh1.position.x = offsetPosition.x;
mesh1.position.y = offsetPosition.y;
mesh1.position.z = offsetPosition.z;
scene.add( mesh1 );
console.log(mesh1.position);
var orbitControl = new THREE.OrbitControls( camera, renderer.domElement );
orbitControl.addEventListener( 'change', render );
window.addEventListener( 'resize', onWindowResize, false );
window.addEventListener( 'keydown', function ( event ) {
switch ( event.keyCode ) {
case 81: // Q
control.setSpace( control.space === "local" ? "world" : "local" );
break;
case 17: // Ctrl
control.setTranslationSnap( 100 );
control.setRotationSnap( THREE.Math.degToRad( 15 ) );
break;
case 87: // W
control.setMode( "translate" );
break;
case 69: // E
control.setMode( "rotate" );
break;
case 82: // R
control.setMode( "scale" );
break;
case 187:
case 107: // +, =, num+
control.setSize( control.size + 0.1 );
break;
case 189:
case 109: // -, _, num-
control.setSize( Math.max( control.size - 0.1, 0.1 ) );
break;
}
});
window.addEventListener( 'keyup', function ( event ) {
switch ( event.keyCode ) {
case 17: // Ctrl
control.setTranslationSnap( null );
control.setRotationSnap( null );
break;
}
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function animate() {
requestAnimationFrame( animate );
render();
update();
}
function update() {
var relativeMeshOffset = new THREE.Vector3( 100, 100, 200 );
var offsetPosition = relativeMeshOffset.applyMatrix4( mesh.matrixWorld );
mesh1.position.x = offsetPosition.x;
mesh1.position.y = offsetPosition.y;
mesh1.position.z = offsetPosition.z;
}
function render() {
control.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>
Cause you set mesh1.matrixAutoUpdate = false; in line 75. If you do that, the mesh1 wouldn't change its position.
I am trying to combine webgl and css3d scenes so that the objects in the two scenes properly blend together. I am following the pattern described here:
and have created a simple example by modifying the three.js example css3d_sandbox.html.
In my version I have added a cube to the webGl scene and expect it to properly blend with the existing planes whether the cube is in front of or behind those objects.
I notice two anomalies. The first is that once the cube is added the planes disappear in unexpected positions as you pan around as if the far and near plane values are not being honored correctly or the objects are being incorrectly determined to be behind something else.
The second issue is that the css3d objects do not render at all when running against three.js r67, but they do render when running against r61. I tried replacing the r67 version of CSS3DRenderer.js with r61, but still do not see any css3d objects.
In r67 when the line to add the webGl dom as a child of the css3d dom is commented out, the css3d objects do appear.
I would appreciate any suggestions on how to resolve these issues. Sample code is below and may be run by dropping into any version of the three.js examples folder (e.g. r61 or r67).
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #000000;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: center;
z-index: 1;
}
a {
color: #000000;
}
</style>
</head>
<body>
<div id="info">three.js - css3d sandbox</div>
<script src="../build/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<!--<script src="js/renderers/CSS3DRenderer-r61.js"></script>-->
<script src="js/renderers/CSS3DRenderer.js"></script>
<script>
var camera, sceneGl, rendererGl;
var sceneCss, rendererCss;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 200, 200, 200 );
controls = new THREE.TrackballControls( camera );
sceneGl = new THREE.Scene();
sceneCss = new THREE.Scene();
var material = new THREE.MeshBasicMaterial( { color: 0x000000, opacity : 0.0 } );
material.blending = THREE.NoBlending;
//
var xpos = [50, -10, 30, 70, 110];
var ypos = [60, -40, 0, 40, 80];
var zpos = [-30, -50, 0, 50, 100];
for ( var i = 0; i < 5; i ++ ) {
var element = document.createElement( 'div' );
element.style.width = '100px';
element.style.height = '100px';
element.style.opacity = 1.0;
element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();
var object = new THREE.CSS3DObject( element );
object.position.x = xpos[i];
object.position.y = ypos[i];
object.position.z = zpos[i];
object.rotation.x = Math.PI/(i + 5);
object.rotation.y = Math.PI/(21 - 2 * i);
object.rotation.z = Math.PI/(3 * i + 25);
object.scale.x = i/12 + 0.5;
object.scale.y = 1/ (12 - i) + 0.5;
sceneCss.add( object );
var geometry = new THREE.PlaneGeometry( 100, 100 );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.copy( object.position );
mesh.rotation.copy( object.rotation );
mesh.scale.copy( object.scale );
sceneGl.add( mesh );
}
//
var boxGeom = new THREE.CubeGeometry( 60, 60, 60 );
var cubeMaterial = new THREE.MeshBasicMaterial(
{ color: 0x05009A, shading : THREE.FlatShading, side: THREE.FrontSide } );
var cube = new THREE.Mesh( boxGeom, cubeMaterial );
cube.position.copy( new THREE.Vector3(100, 75, 50) );
cube.rotation.copy( Math.PI/ 6 );
sceneGl.add( cube );
rendererCss = new THREE.CSS3DRenderer();
rendererCss.setSize( window.innerWidth, window.innerHeight );
rendererCss.domElement.style.position = 'absolute';
rendererCss.domElement.style.top = 0;
rendererGl = new THREE.WebGLRenderer();
rendererGl.setClearColor( 0xf0f0f0 );
rendererGl.setSize( window.innerWidth, window.innerHeight );
rendererGl.domElement.style.position = 'absolute';
rendererGl.domElement.style.zIndex = 1;
rendererGl.domElement.style.top = 0;
rendererCss.domElement.appendChild( rendererGl.domElement );
document.body.appendChild( rendererCss.domElement );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
rendererGl.render( sceneGl, camera );
rendererCss.render( sceneCss, camera );
}
</script>
</body>
</html>
Here is a fiddle with the code.
The link in the comment was helpful. As that solution mentions, setting alpha to true solves the issue of getting the css3d objects to render using r67. Making the webGl background transparent solves the problem of the css3d objects disappearing when panning around.
The solution mentioned in the link however adds both the webgl and css3d dom as child elements of the document. This approach did not work in my case. I find it necessary to still have the webgl dom as a child of the css3d dom for the cube to blend correctly with the planes when it is both in front of and behind those objects.
Working code below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/three.min.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src="js/renderers/CSS3DRenderer.js"></script>
<script>
var camera, sceneGl, rendererGl;
var sceneCss, rendererCss;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(200, 200, 200);
controls = new THREE.TrackballControls(camera);
sceneGl = new THREE.Scene();
sceneCss = new THREE.Scene();
var material = new THREE.MeshBasicMaterial({
color: 0x000000,
opacity: 0.0,
side: THREE.DoubleSide
});
var xpos = [50, -10, 30, 70, 110];
var ypos = [60, -40, 0, 40, 80];
var zpos = [-30, -50, 0, 50, 100];
for (var i = 0; i < 5; i++) {
var element = document.createElement('div');
element.style.width = '100px';
element.style.height = '100px';
element.style.opacity = 1.0;
element.style.background = new THREE.Color(Math.random() * 0xff0000).getStyle();
var object = new THREE.CSS3DObject(element);
object.position.x = xpos[i];
object.position.y = ypos[i];
object.position.z = zpos[i];
object.rotation.x = Math.PI / (i + 5);
object.rotation.y = Math.PI / (21 - 2 * i);
object.rotation.z = Math.PI / (3 * i + 25);
object.scale.x = i / 12 + 0.5;
object.scale.y = 1 / (12 - i) + 0.5;
sceneCss.add(object);
var geometry = new THREE.PlaneGeometry(100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(object.position);
mesh.rotation.copy(object.rotation);
mesh.scale.copy(object.scale);
sceneGl.add(mesh);
}
var boxGeom = new THREE.CubeGeometry(60, 60, 60);
var cubeMaterial = new THREE.MeshBasicMaterial({
color: 0x05009A,
shading: THREE.FlatShading,
side: THREE.DoubleSide
});
var cube = new THREE.Mesh(boxGeom, cubeMaterial);
cube.position.copy(new THREE.Vector3(100, 75, 50));
cube.rotation.copy(Math.PI / 6);
sceneGl.add(cube);
rendererCss = new THREE.CSS3DRenderer();
rendererCss.setSize(window.innerWidth, window.innerHeight);
rendererCss.domElement.style.position = 'absolute';
rendererCss.domElement.style.top = 0;
rendererGl = new THREE.WebGLRenderer({alpha:true});
rendererGl.setClearColor(0x00ff00, 0.0);
rendererGl.setSize(window.innerWidth, window.innerHeight);
rendererGl.domElement.style.position = 'absolute';
rendererGl.domElement.style.zIndex = 1;
rendererGl.domElement.style.top = 0;
rendererCss.domElement.appendChild(rendererGl.domElement);
document.body.appendChild(rendererCss.domElement);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
rendererGl.render(sceneGl, camera);
rendererCss.render(sceneCss, camera);
}
</script>
</body>
</html>
I have a problem .
I want move the earth in 360° with the mouse but nothing happens .
However , I would like the world is fixed and does not move when I use the mouse to rotate 360 .
Waiting for a response .
<!DOCTYPE html>
<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: #808080;
font-family:Monospace;
font-size:13px;
text-align:center;
background-color: #000000;
margin: 0px;
overflow: hidden;
}
#info {
position: absolute;
top: 0px; width: 100%;
padding: 5px;
}
a {
color: #0080ff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">three.js - earth demo</div>
<script src="../build/three.min.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
var group;
var mouseX = 0, mouseY = 0;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 900;
scene = new THREE.Scene();
group = new THREE.Object3D();
scene.add( group );
// earth
var earthTexture = new THREE.Texture();
var loader = new THREE.ImageLoader();
loader.addEventListener( 'load', function ( event ) {
earthTexture.image = event.content;
earthTexture.needsUpdate = true;
} );
loader.load( 'textures/1.jpg');
var geometry = new THREE.SphereGeometry( 250, 55, 55 );
var material = new THREE.MeshBasicMaterial( { map: earthTexture, overdraw: true } );
var mesh = new THREE.Mesh( geometry, material );
group.add( mesh );
// shadow
var canvas = document.createElement( 'canvas' );
canvas.width = 128;
canvas.height = 128;
var context = canvas.getContext( '2d' );
var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
gradient.addColorStop( 0.1, 'rgba(210,210,210,1)' );
gradient.addColorStop( 1, 'rgba(255,255,255,1)' );
context.fillStyle = gradient;
context.fillRect( 0, 0, canvas.width, canvas.height );
var texture = new THREE.Texture( canvas );
texture.needsUpdate = true;
var geometry = new THREE.PlaneGeometry( 300, 300, 3, 3 );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.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 );
mouseY = ( event.clientY - windowHalfY );
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.50;
camera.position.y += ( - mouseY - camera.position.y ) * 0.50;
camera.lookAt( scene.position );
group.rotation.y -= 0.01;
renderer.render( scene, camera );
}
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0x555555);
scene.add(ambientLight);
</script>
</body>
the problem that you are having is that you are only moving the camera in the X and Y direction, when the camera is a 3D entity.
In order to do the rotation, you need to move convert the mouse coordinate from 3D spherical coordinates (like latitude, longitude, altitude, assuming a constant altitude, you can assign X to longitude and Y to latitude).
Then assign the 3D cartesian coordinates to your camera:
The formula is (replacing what you have in your render function):
(assume altitude is 960, which works with your model)
camera.position.x = 960 * Math.sin(mouseX) * Math.cos(mouseY);
camera.position.y = 960 * Math.sin(mouseX) * Math.sin(mouseY);
camera.position.z = 960 * Math.cos(mouseX);
The next caveat is that sin and cos take radians (range from -pi to pi (-3.14159 to 3.14159)...so you will need to adjust your onDocumentMouseMove event to something like
mouseX = -Math.PI + (event.clientX)/(windowHalfX*2)*Math.PI*2;
mouseY = -Math.PI + (event.clientY)/(windowHalfY*2)*Math.PI*2;
This will cause the mouse to act in lat/long coordinate (which can still be a little strange if you are looking at the top of the world. You could restrict mouseY=0, then the X rotation would always be on the equator.
The math is a little more complicated if you want moving the mouse to be on a moving frame vs. the earth centric frame I've shown. But this should at least be a start.
I test the material switch on three.js and I have seen material camaro ici :
http://mrdoob.github.com/three.js/examples/webgl_materials_cars_camaro.html
But if I think understand the code, I tried to reproduce it with a single object that has a single material
and clicking on the button changes the material.
But I have two problems:
- How to create a variation of material with a texture
- After 3 days of testing, my code does not work and I do not understand why
if you could tell me where it gets stuck and why:
/////////////////////// MATERIAL /////////////////////////////
var materials = {
Red: new THREE.MeshLambertMaterial( {
color: 0x660000,
envMap: textureCube,
combine: THREE.MixOperation,
reflectivity: 0.5
} ),
Black: new THREE.MeshLambertMaterial( {
color: 0x000000,
envMap: textureCube,
combine: THREE.MixOperation,
reflectivity: 0.5
} ),
White: new THREE.MeshLambertMaterial( {
color: 0xffffff,
envMap: textureCube,
combine: THREE.MixOperation,
reflectivity: 0.5
} ),
Gold: new THREE.MeshPhongMaterial( {
color: 0xaa9944,
specular: 0xbbaa99,
shininess: 50,
envMap: textureCube,
combine: THREE.MultiplyOperation
} ),
Chrome: new THREE.MeshPhongMaterial( {
color: 0xffffff,
specular:0xffffff,
envMap: textureCube,
combine: THREE.MultiplyOperation
} ),
// how to configure this material ?
/*LWood: new THREE.ImageUtils.loadTexture ( texture );
url = "models/macabann/chataigner.jpg";
imgTexture.repeat.set( 4, 4 );
imgTexture.wrapS = imgTexture.wrapT = THREE.RepeatWrapping;
imgTexture.anisotropy = 16;
shininess: 50;
specular: 0x333333;
envMap: textureCube;
combine: THREE.MixOperation;
reflectivity: 0.2;
bumpScale: 1;
shading: THREE.SmoothShading;*/
/*DWood: new THREE.ImageUtils.loadTexture ( texture );
url = "models/macabann/chataigner.jpg";
imgTexture.repeat.set( 4, 4 );
imgTexture.wrapS = imgTexture.wrapT = THREE.RepeatWrapping;
imgTexture.anisotropy = 16;
shininess: 50;
specular: 0x333333;
envMap: textureCube;
combine: THREE.MixOperation;
reflectivity: 0.2;
bumpScale: 0;
shading: THREE.SmoothShading;*/
};
/////////////////////// FIN MATERIAL /////////////////////////////
////////////////////////// OBJET ////////////////////////////
var loader = new THREE.JSONLoader();
loader.load('models/macabann/bielo.js', function ( geometry )
{ createScene( geometry, materials ) }
);
function createScene( geometry, materials ) {
var Bmaterial = new THREE.MeshLambertMaterial();
Bmaterial = materials [ "Orange" ];// default cette ligne merde
var mesh = new THREE.Mesh( geometry, Bmaterial );
mesh.scale.set(1, 1, 1);
mesh.position.y = 0;
mesh.position.x = 0;
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add( mesh );
createButtons( materials, Bmaterial );
}
///////////////////// FIN OBJET ///////////////////////
//////////////////// buttons //////////////////////////
function createButtons( materials, Bmaterial ) {
var buttons = document.getElementById( "buttons" );
for ( var key in materials ) {
var button = document.createElement( 'button' );
button.textContent = key;
button.addEventListener( 'click', function ( event ) {
Bmaterial = materials[ this.textContent ];///////problem ?
}, false
);
buttons.appendChild( button );
}
}
thanks to answers
This code is incorrect
function createScene( geometry, materials ) {
var m = new THREE.MeshLambertMaterial();
m.materials = Bmaterial [ "Orange" ];
var mesh = new THREE.Mesh( geometry, m );
It should be
function createScene( geometry, materials ) {
var m = Bmaterial [ "Orange" ];
var mesh = new THREE.Mesh( geometry, m );
Also, you can't change from a less complicated material to a more complicated one. For example, if one material has a texture, they all must. See https://github.com/mrdoob/three.js/wiki/Updates.
So make all your materials in you material array MeshPhongMaterial. If one material does not need a texture, then assign it a dummy white one.