I'm new to three js and webgl. I have a complicated solar system I'm building and it all works great until I want to animate anything. Here is a very stripped down version to show the problem (with sun in low res). If I add the line sun.rotate.y += 1; it wont load or run anything at all. I have looked around a lot and can't figure out why. I'm sure it is something stupid I'm missing. Thanks for any help.
<script>
// SETUP SCENE
var camera, controls, scene, renderer;
var container
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 90000 );
camera.position.z = 100;
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = .2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = true;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
// ADD THE SUN PHYSICAL LOCATION
var geometry = new THREE.SphereGeometry(5, 3, 3, 0, Math.PI * 2, 0, Math.PI * 2);
var material = new THREE.MeshBasicMaterial({color: "Yellow"});
var sun = new THREE.Mesh(geometry, material);
scene.add(sun);
//RENDER
renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
render();
animate();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
render();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
function render() {
sun.rotate.y +=1; // Problem animating?
renderer.render( scene, camera );
}
</script>
You need to define sun as a global variable because currently it is not visible in the render() scope.
Also, I think to rotate a mesh you call "rotateX(), rotateY() or rotateZ()" so it is sun.rotateY(0.01)
Edit: I realized you can rotate the mesh by modifying its rotation rather than its rotate property.
You have a scope issue ( well it's complicated depending on what you are using es6 or es5), these are the offending bits:
Declare your global(or not Js will add it) to the global space :
var container, sun;
And refer to it inside the init function:
this.sun = new THREE.Mesh(geometry, material);
Working Pen:
Scope Issue in Three.js
Also, TrackballControls is not part of Three.js, you have to import it, check the pen.
Also, Also,for the rotation you might want to use:
sun.rotation.y += 0.003;
Related
Im having troubles with Orbitcontrols. I have my threee js model and i want it to autorotate when the page is loaded for the first time but for some reason it does not work properly. The 3d model stand still as if the command line was not considered.
Here is the code where i initialize the function:
the init() function where i declare my model and add them to the scene:
controls.autoRotate=true
controls.addEventListener('change', render);
render();
the render function:
function render() {
renderer.render(scene, camera);
}
Please note that i can move my model as i wish in my page but the automatic rotation does not seem to be triggered.
Using OrbitControls.autoRotate only works if you call controls.update() in your animation loop. You can't use automatic rotation in combination with on-demand rendering (meaning by utilizing the change event listener of the controls).
let camera, scene, renderer, controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.autoRotate = true;
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.124/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.124/examples/js/controls/OrbitControls.js"></script>
I've been working on a mini project recently for a visuals I want to develop and I'm having issues being able to limit the camera rotation based on the Y axis rotation, and I don't quite know why or how I'm having this issue.
I've looked around and all I can find is people wanting to remove the angle clamp, and they always seem to refer to minAzimuthAngle or maxAzimuthAngle, but I can't seem to get it to do anything.
// controls.minAzimuthAngle = -Math.PI, controls.maxAzimuthAngle = Math.PI
I'm just asking here as I can't find much elsewhere to explain my problem. I'm thinking it's just the specifically the way I'm using or rendering the camera but it's hard to find any reference to clamping the angles other than unclamping them.
var renderer, scene, camera; // scene render var creation
var orbitalControl = new THREE.OrbitControls(camera, renderer); //orbitcontrol setup
var controls = new THREE.OrbitControls( camera, renderer); // camera to renderer
controls.addEventListener( 'change', render ); //control listening
scene = new THREE.Scene(), camera; // scene creation
var W = window.innerWidth, H = window.innerHeight; // scene size
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 400); // camera assignment
camera.up = new THREE.Vector3(0,500,0);
controls = new THREE.OrbitControls(camera); // centeralising the camera
controls.target = new THREE.Vector3(500, 200, 500); // controls
controls.addEventListener('change', render); // renderer based on controls
scene.add(camera); // camera to scene
controls.addEventListener( 'change', render ); // control adjustments
controls.screenSpacePanning = false;
controls.enableDamping = true, controls.dampingFactor = 0.25;
controls.enableZoom = false, controls.autoRotate = false;
controls.minPolarAngle = Math.PI / 2 ; // radians
controls.maxPolarAngle = Math.PI / 2 // radians
controls.minAzimuthAngle = -Math.PI * 0.5;
controls.maxAzimuthAngle = Math.PI * 0.5;
controls.addEventListener("change", () => {
if (this.renderer) this.renderer.render(this.scene, camera)});
regardless of whatever I change the min or max AzimuthAngle, it doesn't do anything, but it's the only thing I'm referred to from any other posts.
is there something conflicting with the way I'm trying to render this?
I genuinelly have no clue what the issue is.
Thanks in advance for anyone who responds
github link to the entire project; https://github.com/Thealonic/GENESIS
I'm having issues being able to limit the camera rotation based on the Y axis rotation,
In this case, you have to configure minAzimuthAngle and maxAzimuthAngle. Keep in mind that you can only use values in the range [ - Math.PI, Math.PI ]. Check out how the following example restricts how far you can orbit horizontally.
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 20, 20, 20 );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.minAzimuthAngle = 0;
controls.maxAzimuthAngle = Math.PI * 0.5;
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 20,20, 0 );
scene.add( light );
// axes
scene.add( new THREE.AxesHelper( 20 ) );
// geometry
var geometry = new THREE.SphereGeometry( 5, 12, 8 );
// material
var material = new THREE.MeshPhongMaterial( {
color: 0x00ffff,
flatShading: true,
transparent: true,
opacity: 0.7,
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
body {
margin: 0;
}
canvas {
display: block;
}
<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>
I have been trying various options for all day to solve my problem. I was also trying various examples posted here in previous years. Although my problem is still unsolved and my objects are not appearing.
I was trying 3 different formats: .json, .js and now .mtl with.obj. My current code looks like this:
function addModels() {
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load("../models/lampa.mtl", function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load("../models/lampa.obj", function (mesh) {
mesh.scale.set(1,1,1);
mesh.position.set(0,0,0);
scene.add(mesh);
})
})
And this is html file with the script running canvas.
var camera;
var scene;
var renderer = new THREE.WebGLRenderer();
var controls;
//Simple functions to initialise scene and render it.
initialise();
render();
//animate();
//add models
addModels();
function initialise() {
// Create a scene
scene = new THREE.Scene();
// Add the camera
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 100, 250);
// Add scene elements
addWalls();
addKerbs();
// Add lights
addLights();
// Create the WebGL Renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
//add Grass
createGrass();
addGrass();
// Append the renderer to the body
document.body.appendChild( renderer.domElement );
// Add a resize event listener
window.addEventListener( 'resize', Resize, false );
// Add the orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(0, 100, 0);
}
//rendering function
function render() {
renderer.render( scene, camera );
requestAnimationFrame( render );
controls.update();
}
//Window resize.
function Resize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame(animate);
render();
status.update();
renderer.render(scene,camera);
}
When addModels() is in initialise function, but it throws an error like this:
Every answer is appreciated. Thank you.
I am really sorry for every trouble. It appears that everything is fine here, just three.js was out of date...
I've encountered one strange problem with displaying collada model in three.js
I suspect that something wrong with the logic of the script but I can't figure out.
The problem is that the Collada model is displayed black till a user moves a mouse (orbit controls). Only after this the model gets lighted.
So, initially, when the page loads, the model is black and this is confusing a user.
What's wrong with the code? Where could be the error?
The code of the script is the following:
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer;
var pointLight;
init();
render();
function animate()
{
pointLight.position.copy( camera.position );
requestAnimationFrame(animate);
controls.update();
}
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( -40, 70, 70 );
controls = new THREE.OrbitControls( camera );
controls.damping = 0.2;
controls.addEventListener( 'change', render );
scene = new THREE.Scene();
// world
var mesh;
var loader = new THREE.ColladaLoader();
loader.load('./models/collada/test.dae', function (result) {
mesh = result.scene;
mesh.scale.set(0.3, 0.3, 0.3);
scene.add(mesh);
render();
});
// lights
var hemLight = new THREE.HemisphereLight(0x000000, 0x303030, 0.8);
scene.add(hemLight);
pointLight = new THREE.PointLight( 0xffffff, 1.1 );
pointLight.position.copy( camera.position );
scene.add( pointLight );
// renderer
renderer = new THREE.WebGLRenderer({antialias:true, alpha:true});
renderer.setClearColor(0xEEEEEE, 1);
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
animate();
}
function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function render()
{
renderer.render( scene, camera );
}
</script>
You're not calling render() from your animate() function, so the scene is only rendered through the OrbitControls onChange event. Add render() at the end of animate() and it will work. You can also then remove the onChange callback, since you'll be rendering steadily.
I'm trying to animate an exported model(from 3dsmax -> dae file -> json) with animations using three.js. I am not getting any console errors but rather just a blank screen. Anyone have any ideas on why this is happening? I'm happy to also include json, png's, max file, dae file or any other resource that may be of help. Any help would be much appreciated. I'm stuck...here is the javascript:
<script>
var camera, scene, renderer, animmesh;
var clock = new THREE.Clock();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 5;
scene = new THREE.Scene();
scene.add(camera);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var loader = new THREE.JSONLoader();
loader.load("../../assets/model-threejs.json", function (model, material) {
createScene(model, material);
});
}
function createScene(model, material) {
material[0].skinning = true;
animmesh = new THREE.SkinnedMesh(model, material[0]);
scene.add(animmesh);
}
function render() {
renderer.render(scene, camera);
}
init();
render();
</script>
You had several problems. 1) Your elephant was so big it was off the screen. 2) You need to tell the camera to look at the origin. 3) When you simplified the code you made it too simple, you still need the animate loop.
This code works (since I didn't have your PNG files, I used a MeshNormalMaterial):
var camera, scene, renderer, animmesh, controls;
var clock = new THREE.Clock();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.x = -900;
scene.add(camera);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth*.9, window.innerHeight*.9 );
document.body.appendChild( renderer.domElement );
var loader = new THREE.JSONLoader();
loader.load("model-threejs.json", function (model, material) {
animmesh = new THREE.Mesh(model, new THREE.MeshNormalMaterial());
scene.add(animmesh);
animate();
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render(scene, camera);
camera.lookAt(new THREE.Vector3(0,0,0));
}
init();