How does position in Threejs work exactly? - javascript

I'm trying to make something responsive in Threejs which will be full screen.
I am having a hard time understanding the concept of positioning of objects due to this.
I will also want to add animations so need the positions to be dynamic.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var materialRed = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var materialBlue = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
var circle = new THREE.Mesh( new THREE.CircleGeometry( 12, 128 ), materialRed );
scene.add(circle);
var square = [];
square.push( new THREE.Mesh( new THREE.PlaneGeometry( 10, 10, 1), materialBlue ) );
square.push( new THREE.Mesh( new THREE.PlaneGeometry( 10, 10, 1), materialBlue ) );
scene.add(square[0]);
scene.add(square[1]);
square[0].position.x = 100;
square[1].position.x = -100;
camera.position.z = 100;
var render = function() {
requestAnimationFrame(render);
circle.position.x += 0.1;
circle.position.y += 0.05;
renderer.render( scene, camera );
};
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>
var circle = new THREE.Mesh( new THREE.CircleGeometry( 12, 128 ), materialRed );
scene.add(circle);
circle.position.x = 100;
I need to understand how positioning will change with change in aspect ration and camera frustums.
EDIT
For eg-
I need to move the sphere in an elliptical orbit around the screen. I need to calculate the equation of the orbit which will get me position of the sphere at every instance. I don't want the sphere to move out of frame and for that I'm ready to change the length of axes or size of sphere.

Related

How to calculate the position of objects in Three.js

I am new to 3D Graphics programming. I'm using Three.js to design a software that uses 3D visualisation for 3D bin packaging. Right now I'm using the below code to create and position two elements.
var camera, scene, renderer;
var mesh, mesh2;
init();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 800;
scene = new THREE.Scene();
var texture = new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/crate.gif' );
var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
var geometry2 = new THREE.BoxBufferGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( {map:texture} );
mesh = new THREE.Mesh( geometry, material );
mesh2 = new THREE.Mesh( geometry2, material );
mesh2.position.x = 170
mesh2.position.y = -48
mesh2.position.z = 100
mesh.rotation.x = 0.45;
mesh.rotation.y = 1;
mesh2.rotation.x = 0.45;
mesh2.rotation.y = 1;
scene.add( mesh2 );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
Right now I'm using (170, -48, 100) as the coordinates to align the second cube. I've arrived to these numbers by tweaking the numbers and constantly checking. But there should be some formula to get these x,y,z since I'm rotating them to a certain angle (x=0.45, y=1). I'm not sure how to start the calculation for this.
The problem statement is, given a set of cubes dimensions' (l1, w1, h1), (h2, w2, h2) and so on and cubes positions (x1, y1, z1) (x2, y2, z2) how to calculate and place them near and/or stack them?
Make mesh2 a child of mesh: mesh.add( mesh2 )
mesh2 will inherit rotation of mesh and you will define relative offsets to shift it in coordinate space of parent.
Fixed example:
mesh = new THREE.Mesh( geometry, material );
mesh2 = new THREE.Mesh( geometry2, material );
mesh2.position.x = 170
//mesh2.position.y = -48
//mesh2.position.z = 100
mesh.rotation.x = 0.45;
mesh.rotation.y = 1;
//mesh2.rotation.x = 0.45;
//mesh2.rotation.y = 1;
scene.add( mesh );
mesh.add( mesh2 ); // << ---- solution
Updated: Also possible without parent-child hierarchy.
let mesh = new THREE.Mesh( geometry, material );
let mesh2 = new THREE.Mesh( geometry2, material );
// mesh2.position.x = 170
// mesh2.position.y = -48
// mesh2.position.z = 100
mesh.rotation.x = 0.45;
mesh.rotation.y = 1;
mesh.updateMatrix(); // <<-- this is essential, to write .position and .rotation values into object transformation matrix.
// mesh2.rotation.x = 0.45;
// mesh2.rotation.y = 1;
scene.add( mesh );
// apply local transforms
mesh2.applyMatrix(new THREE.Matrix4().makeTranslation(210, 0, 0));
// apply transforms of mesh on top
mesh2.applyMatrix(mesh.matrix);
scene.add( mesh2 ); // << ---- add directly to Scene

Plane always black

I want to add a texture to my plane that repeats horizontal and vertical. The thing is, when I try to apply the texture, it is always black. I don't get any errors, and i already tried to add some lights, but the problem is still there; I don't know how to solve it... Here is what I did:
window.onload = function init()
{
scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
var light = new THREE.AmbientLight( 0x404040 ); // soft white light
scene.add( light );
var spotlight = new THREE.SpotLight( 0xffffff);
spotlight.position.set( -50, 40, 0 );
scene.add( spotlight );
var axes = new THREE.AxisHelper( 20 ); scene.add(axes);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE);
renderer.setSize(window.innerWidth, window.innerHeight);
desenhaMapa();
document.body.appendChild( renderer.domElement );
renderer.render(scene, camera);
}
function desenhaMapa()
{
labirinto = new THREE.Object3D();
var texturaPlano = new THREE.TextureLoader().load("texturaPac.jpg");
geometryPlano = new THREE.PlaneGeometry(50,50);
materialPlano = new THREE.MeshPhongMaterial( {map: texturaPlano} );
var planoPacMan = new THREE.Mesh(geometryPlano,materialPlano);
planoPacMan.rotation.x = -0.5 * Math.PI;
scene.add(planoPacMan);
}
Any suggestions?
TextureLoader.load() is an asynchronous method. That is why it has an onload argument.
You are calling render() before the texture loads. One solution is to call render() in the loader callback.
var loader = new THREE.TextureLoader();
var texture = loader.load( 'myTexture.jpg', function ( texture ) {
renderer.render( scene, camera );
} );
Another solution is to have an animation loop. But that is not required for static scenes.
three.js r.78

Rotate a face in a Three.js geometry

Hi I'm trying to make a torsional distortion using threejs. What I have is a cylinder where I want to rotate one of its end and let the other fixed, so I can recreate this effect.
What I have: Current shape
What I want: Desired shape
What I want to know is if there is a function that I can use to make the desired modification over the geometry, I have tried and I didn't find any.
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 100;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.CylinderGeometry(50, 50, 1000, 20);
var material = new THREE.MeshBasicMaterial({wireframe: true});
var cylinder = new THREE.Mesh( geometry, material );
cylinder.rotation.z = Math.PI/2;
scene.add( cylinder );

Can't animate wireframe rotation in Three.js

I tried to make the wireframe rotate in the scene.
The animation works when I removed the BoxHelper, but I want to animate the cube wireframe without diagonal line instead of a solid object.
Codepen demo :
Demo
Code :
var w = window.innerWidth, h = window.innerHeight,
scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000),
renderer = new THREE.WebGLRenderer(),
geometry = new THREE.BoxGeometry( 1, 1, 1 ),
material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ),
mesh = new THREE.Mesh( geometry, material ),
cube = new THREE.BoxHelper(mesh);
cube.material.color.setRGB(25,25,25);
scene.add(cube);
camera.position.z = 2;
renderer.setSize(w,h);
document.body.appendChild(renderer.domElement);
function render(){
requestAnimationFrame( render );
cube.rotation.x += 1;
renderer.render(scene, camera );
}
render();
The position of your THREE.BoxHelper instance is tied to the position of the THREE.Mesh. For your code to work you will have to add the mesh to the scene and rotate the mesh. Your box helper will follow.
If you don't want to show the mesh you can simply set mesh.visible = false;
This code works:
var w = window.innerWidth, h = window.innerHeight,
scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000),
renderer = new THREE.WebGLRenderer(),
geometry = new THREE.BoxGeometry( 1, 1, 1 ),
mesh = new THREE.Mesh( geometry );
camera.position.z = 2;
renderer.setSize(w,h);
document.body.appendChild(renderer.domElement);
mesh.visible = false; //<-- hide mesh
scene.add(mesh); //<-- add mesh to scene
cube = new THREE.BoxHelper(mesh);
cube.material.color.setRGB(25,25,25);
scene.add(cube);
function render(){
mesh.rotation.y += 0.01; //<-- rotate the mesh
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();

Create a unique sphere geometry from a sphere and a cylinder Three.js

I'm trying to create a bead like object in Three.js, essentially a sphere with a cylinder through it. I can create the two independently, but I'm wondering how to match the height of the sphere and the cylinder and how to merge / intersect them, so that the result will be one geometry.
Any ideas?
Thanks!
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//material
var material = new THREE.MeshNormalMaterial( {
wireframe: true
} );
//sphere
var sphere = new THREE.SphereGeometry(2,20,20);
var sphereMesh = new THREE.Mesh( sphere, material );
scene.add( sphereMesh );
//cyl
var cylinder = new THREE.CylinderGeometry(0.5, 0.5, 2, 32 );
var cylinderMesh = new THREE.Mesh( cylinder, material );
scene.add( cylinderMesh );
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 5;
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
http://jsfiddle.net/RqU2v/
#gaitat, totally awesome, thanks.
here's the solution with ThreeCSG:
//sphere
var sphere = new THREE.SphereGeometry(2,20,20);
var sphereMesh = new THREE.Mesh( sphere, material );
var sphereBSP = new ThreeBSP( sphereMesh );
//cyl
var cylinder = new THREE.CylinderGeometry(0.5, 0.5, 5, 32 );
var cylinderMesh = new THREE.Mesh( cylinder, material );
var cylinderBSP = new ThreeBSP( cylinderMesh );
//result
var subtract_bsp = sphereBSP.subtract( cylinderBSP );
var result = subtract_bsp.toMesh( material );
result.geometry.computeVertexNormals();
scene.add( result );

Categories

Resources