Three.js GLB Skeletal Animation not playing in Chrome - javascript

I'm trying to play basic embedded skeletal animation in .glb model using Three.js
The solution i'm using comes from this forum : https://discourse.threejs.org/t/easiest-way-to-play-skeletal-animation-from-gltf/7792
I'm using the very basic code. The animation is found (i can log it into console). But the animation doesn't play.
let file, scale, backgroundColor;
window.onload = loader;
function loader (){
file = "Fox.glb";
scale = 1;
backgroundColor = 0x000000;
init();
}
function init(){
//RENDERER
myCanvas = document.getElementById('myCanvas');
renderer = new THREE.WebGLRenderer({
canvas: myCanvas,
antialias: true
});
renderer.setClearColor(backgroundColor);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
//CAMERA
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 1000 );
//SCENE
scene = new THREE.Scene();
let controls = new THREE.OrbitControls(camera, renderer.domElement);
camera.position.set( 0, 20, 100 );
controls.update();
//LIGHTS
let light = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(light);
let light2 = new THREE.PointLight(0xffffff, 0.5);
scene.add(light2);
let loader = new THREE.GLTFLoader();
loader.load(file, handle_load);
let mesh;
function handle_load(gltf) {
mesh = gltf.scene;
//ANIMATION
let mixer = new THREE.AnimationMixer( gltf.scene );
let action = mixer.clipAction( gltf.animations[ 0 ] );
action.play();
//PREPARING DISPLAY
mesh.children[0].material = new THREE.MeshLambertMaterial();
mesh.children[0].scale.set(1,1,1,)
scene.add( mesh );
mesh.position.z = -10;
}
render();
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
What am i missing?

You are not updating the animation mixer in your animation loop. Write your render() function like so:
function render() {
renderer.render(scene, camera);
const delta = clock.getDelta();
if (mixer) mixer.update(delta);
requestAnimationFrame(render);
}
The clock variable is an instance of THREE.Clock. You have to define it (and your animation mixer) in the same scope like your renderer, camera and scene.

Related

THREE.JS Uncaught ReferenceError: OrbitControls is not defined

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const controls = new OrbitControls(camera);
camera.position.set(200, 0, 0);
controls.update();
const geometry = new THREE.SphereGeometry(50, 32, 32);
const material = new THREE.MeshBasicMaterial({
color: 0xffff00
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
<script src="https://cdn.jsdelivr.net/npm/three#0.129.0/build/three.min.js"></script>
When I run my javascript code. I get the following error "Uncaught ReferenceError: OrbitControls is not defined".
I saw this post about it, but it doesn't seem to help.
Any ideas?
My OrbitControls.js is in the same file under the three.js file
I got your code running without errors by importing OrbitControls and defining your renderer at the top and passing it into OrbitControls.
Edit, I added a second snippet that was adapted from a three.js example on their site that I think adds the yellow sphere you're looking for.
let camera, controls, scene, renderer;
init();
//render(); // remove when using next line for animation loop (requestAnimationFrame)
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xcccccc);
scene.fog = new THREE.FogExp2(0xcccccc, 0.002);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(400, 200, 0);
// controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 100;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI / 2;
// world
const geometry = new THREE.SphereGeometry(50, 32, 32);
const material = new THREE.MeshBasicMaterial({
color: 0xffff00
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
//
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
render();
}
function render() {
renderer.render(scene, camera);
}
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/examples/js/controls/OrbitControls.min.js"></script>
let camera, controls, scene, renderer;
init();
//render(); // remove when using next line for animation loop (requestAnimationFrame)
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xcccccc);
scene.fog = new THREE.FogExp2(0xcccccc, 0.002);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(400, 200, 0);
// controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 100;
controls.maxDistance = 500;
controls.maxPolarAngle = Math.PI / 2;
// world
const geometry = new THREE.SphereGeometry(50, 32, 32);
const material = new THREE.MeshBasicMaterial({
color: 0xffff00
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
//
window.addEventListener('resize', onWindowResize);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
render();
}
function render() {
renderer.render(scene, camera);
}
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.122.0/examples/js/controls/OrbitControls.min.js"></script>

Rotate cubetexture in Three.js

I got this cubetexture in Three.js. Say I want to rotate the cubeTexture itself 180 degrees. I know I can do this by rotating the camera but I want to rotate the texture itself and not the camera. How can I achieve this?
I want to rotate the x axis of the cubeTexture causing it to display the opposite side. Something like texture.flipX = true; would be handy.
https://codepen.io/haangglide/pen/GRZPqaw
var camera, scene, box, renderer;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
scene = new THREE.Scene();
const texture = new THREE.CubeTextureLoader()
.setCrossOrigin('') .setPath('https://alca.tv/static/codepen/pens/common/SwedishRoyalCastle/').load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
scene.background = texture;
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: new THREE.Color('skyblue') });
box = new THREE.Mesh(geometry, material);
scene.add(box);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
scene.add(camera);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Edit:
According to the following discussions it does not seem easy or even possible to do what you ask with ThreeJS, but in the first link it does mention that it may be possible with BabylonJS.
https://discourse.threejs.org/t/rotate-a-scenes-background-skybox-texture/12199
https://discourse.threejs.o9rg/t/rotate-a-scenes-background/3928/15
Original answer:
You didn't say which axis so I will just use the Y axis. I am also using 45 degrees instead of 180 so you can see it is working.
var camera, scene, box, renderer;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
scene = new THREE.Scene();
const texture = new THREE.CubeTextureLoader()
.setCrossOrigin('') .setPath('https://alca.tv/static/codepen/pens/common/SwedishRoyalCastle/').load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg']);
scene.background = texture;
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: new THREE.Color('skyblue') });
box = new THREE.Mesh(geometry, material);
///
///
///
///////////////////////////////
//since threejs uses radians, you will need a function to get radians from degrees
function getRadians(degrees) {
return Math.PI / 180 * degrees;
}
//using rotation.set(x, y, z)
box.rotation.set(0, getRadians(45), 0);
//directly setting the rotations
box.rotation.y = getRadians(45);
///////////////////////////////
///
///
///
scene.add(box);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
scene.add(camera);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
<script src="https://threejs.org/build/three.js"></script>

How to rotate object with offset by orbit control in three.js?

I want to control object like this:
Now camera is move around Y coordinate, but need to be move around NEW Y. Code is here:
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var controls = new THREE.OrbitControls(camera);
cube.position.x = 300;
// controls.target = THREE.Vector3(300, 0, 0);
I found that target option can set the focus point of the controls, but if I add this code: controls.target = THREE.Vector3(300, 0, 0); the object back to the center of the screen, but it should be at the right edge.
More over, when I set new THREE.OrbitControls(camera); to new THREE.OrbitControls(cube); and add controls.target = THREE.Vector3(300, 0, 0); control doesn't work, but when I set controls.target = THREE.Vector3(301, 0, 0); it is managed but not like a camera
OrbitControls.target set the focus point of the controls and the .object orbits around this. But it is a manually manipulation. As mentioned in the documentation OrbitControls.update() must be called after any manual changes to the camera's transform.
e.g.
controls.target = new THREE.Vector3(1, 0, 0)
controls.update();
See the example:
(function onLoad() {
var container, camera, scene, renderer, controls;
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, 1.0, -4);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
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.set(1,2,1.5);
scene.add( directionalLight );
controls = new THREE.OrbitControls(camera, container);
controls.target = new THREE.Vector3(3, 0, 0)
controls.update();
controls.autoRotate = true;
controls.autoRotateSpeed = 5.0
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
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;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.115/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>

three.js JsonLoader is not showing JSON object converted from .obj

i have this code:
var camera, scene, controls, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.z = 10;
//lights
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(10, 10, 10);
scene.add(light);
controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setClearColor(0x000000, 0); // the default
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var jsonLoader = new THREE.JSONLoader();
var mesh;
jsonLoader.load('corona.js',
function (geometry, materials) {
console.log(JSON.stringify(materials));
console.log(JSON.stringify(geometry));
var material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
Like you can see i am using JSONLoader to show a Corona beer, but for some reason it is not showing anything. You can take a look at the live code here http://xsportfit.com/corona/index.html
These is a list of the files i used for this example:
- http://xsportfit.com/corona/corona.obj
- http://xsportfit.com/corona/corona.mtl
- http://xsportfit.com/corona/corona.js
I have used convert_obj_three.py script to convert corona.obj into corona.js file
Something is wrong in the JSON. You can have it displayed by directly writing your material. For example
new THREE.MeshLambertMaterial({
color:0xffffff,
map:THREE.ImageUtils.loadTexture('BotellaText.jpg')
});

Three.js throws error for scene object and float32array in IE9

When trying to use CanvasRenderer to draw 3D object to make it compatible in IE9 I am getting error float32array error, scene error.
My code is here -
var renderer = new THREE.CanvasRenderer(); // Fallback to canvas renderer, if necessary.
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var geometry = new THREE.CubeGeometry(20, 20, 20);
var material = new THREE.MeshBasicMaterial({ color: 0x0000FF });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 50;
var render = function () {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
};
render(); // Start the rendering of the animation frames.
Any suggestion?

Categories

Resources