I am using GridHelper to make a grid and I would like to place a cube directly on top of a grid's tile. Here is my current implementation, which puts a cube on a grid, but it not directly aligned with a tile.
// cubes
cubeGeo = new THREE.BoxGeometry( 50, 50, 50 );
cubeMaterial = new THREE.MeshLambertMaterial( {color: 0xfeb74c } );
var voxel1 = new THREE.Mesh( cubeGeo, cubeMaterial );
scene.add(voxel1);
// grid
var gridHelper = new THREE.GridHelper( 1000, 20 );
console.log(gridHelper);
scene.add( gridHelper );
Grid with Box not align
How would i go about making the box align with the grid ?
You can translate your geometry after it is created, like so:
cubeGeo = new THREE.BoxBufferGeometry( 50, 50, 50 );
cubeGeo.translate( 25, 0, 25 );
If you add additional cubes, you can reuse the same geometry, and set the mesh's position:
voxel.position.set( x, y, z );
three.js r.87
Related
When I change position about the axis(x, y), my figure change shape like in picture below. How can I fix it? I'm using Three.js.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 2000 );
camera.position.set(0,0,20);
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth/2, window.innerHeight/2 );
document.getElementById('gameWindow').appendChild( renderer.domElement );
const canvas = renderer.domElement;
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( new THREE.SphereGeometry( 2, 20, 20 ), material );
const cube1 = new THREE.Mesh( new THREE.SphereGeometry( 2, 20, 20 ), material );
scene.add(cube, cube1);
cube.position.x=20;
renderer.render(scene, camera);
If you want to maintain the shape of your figure when you change the position, you'll need to switch to an orthographic projection.
To do so in three.js you'll need to replace your PerspectiveCamera with an OrthographicCamera.
Here's a link to the docs that'll help you.
I am trying to create an opening door when the user clicks on a sphere in three.js. I tried doing it with a model but I managed to get it to just appear in the correct position rather than rota to it through animation.
I decided to try to focus on an easier scenario and just use a rectangle I would make in three.js. After hours of trying to get it to work I managed to get it to spin and stop when at 90 degrees. However it was rotating around its y axis which was found in the center of the rectangle.
I found this tutorial : https://jsfiddle.net/uxzmsLfr/1/
var camera, scene, renderer;
var mesh, pivot;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
scene = new THREE.Scene();
var geometry = new THREE.PlaneGeometry( 0.2, 0.5, 0.2 );
var material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0, -.25, 0);
scene.add( mesh );
var geo2 = geometry.clone();
geo2.rotateZ(THREE.Math.degToRad(90)); // ROTATE GEOMETRY SO IT'S IN THE CORRECT ORIENTATION
var mesh2 = new THREE.Mesh( geo2, material );
mesh2.position.set( 0, .25, 0 ); // MOVE THE GEOMOETRY UP BY HALF SO PIVOT IS AT THE BOTTOM OF THE GEO
mesh2.rotation.set(0, 0, Math.PI / 2);
mesh.add(mesh2);
pivot = new THREE.Group();
pivot.position.set( 0.0, 0.25, 0 ); // MOVE THE PIVOT BACK TO WORLD ORIGN
mesh.add( pivot ); // THIS ADDS THE PIVOT TO THE CENTRE OF THE GEOMOETRY, WHICH WAS THEN ADDING MESH2 IN THE WRONG PLACE
pivot.add( mesh2 );
// VISUALISE PIVOT
var pivotSphereGeo = new THREE.SphereGeometry( 0.01 );
var pivotSphere = new THREE.Mesh(pivotSphereGeo);
pivotSphere.position.set( 0,0,0 );
pivotSphere.position.z = 0.1;
scene.add( pivotSphere );
scene.add( new THREE.AxesHelper() );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
pivot.rotation.z += 0.01;
renderer.render( scene, camera );
}
And so far I managed to do the same with my code. The only thing that I'm struggling with now is how to remove the stationary rectangle?
I would appreciate any help you can give me.
The example uses the mesh plane to offset the position of the second mesh. You can always use a group for these purposes if you don't want to render anything.
So, replace the line:
mesh = new THREE.Mesh( geometry, material );
with:
mesh = new THREE.Group();
And rename the variable accordingly to not have a confusing code.
There are two plane meshes in the code above. The first one is defined by:
mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0, -.25, 0);
scene.add( mesh );
The second one (the "door") is defined by:
var mesh2 = new THREE.Mesh( geo2, material );
mesh2.position.set( 0, .25, 0 ); // MOVE THE GEOMOETRY UP BY HALF SO PIVOT IS AT THE BOTTOM OF THE GEO
mesh2.rotation.set(0, 0, Math.PI / 2);
mesh.add(mesh2);
Removing the code that defines the first one will remove the non-door rectangle. But you can't simply remove that code can call it a day, because notice the last line of the mesh2 definition:
mesh.add(mesh2);
This means mesh2 was added as a child of mesh. The pivot group is also a child of mesh. In both cases, replace mesh with scene, and you should be good to go.
I'm just starting to learn three.js and have been trying to set up a simple textured cube box in an isometric view. When I add edge lines to my cube it turns out to be quite grainy on a few of the edges.
I've tried moving the camera and aspect ratio a bit but to no avail.
var aspect = 100/100
var scene = new THREE.Scene();
var d = 100;
camera = new THREE.OrthographicCamera( - d * aspect, d * aspect, d, - d, 1, 500 );
camera.position.set( 80, 80, 80 ); // all components equal
camera.lookAt( scene.position ); // or the origin
var renderer = new THREE.WebGLRenderer( {alpha: true });
renderer.setSize( 100, 80 );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 65, 65, 65 );
var edges = new THREE.EdgesGeometry( geometry )
var line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( {color: 0x000000} ) );
var material = new THREE.MeshBasicMaterial( { color: 0xf0f0f5 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
scene.add( line );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
The above gives me a nice grey cube with black edges but the edges appear grainy in my browser.
Picture below:
This is a Z-fighting issue, which can be solved by a polgon offset .polygonOffset.
The issue is caused because the lines and the surface have to same coordinates and depth.
Set the .polygonOffset, .polygonOffsetFactor and .polygonOffsetUnits property of that THREE.Material, which is set to the solid geometry.
This causes that the surfaces are slightly pushed to the back and the lines cover the surfaces:
e.g.
var material = new THREE.MeshBasicMaterial({
color: 0xf0f0f5,
polygonOffset: true,
polygonOffsetFactor: 1.0,
polygonOffsetUnits: -4.0
} );
var aspect = 100/100
var scene = new THREE.Scene();
var d = 100;
camera = new THREE.OrthographicCamera( - d * aspect, d * aspect, d, - d, 1, 500 );
camera.position.set( 80, 80, 80 ); // all components equal
camera.lookAt( scene.position ); // or the origin
var renderer = new THREE.WebGLRenderer( {alpha: true });
renderer.setSize( 100, 80 );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 65, 65, 65 );
var edges = new THREE.EdgesGeometry( geometry )
var line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( {color: 0x000000} ) );
var material = new THREE.MeshBasicMaterial({
color: 0xf0f0f5,
polygonOffset: true,
polygonOffsetFactor: 1.0,
polygonOffsetUnits: -4.0
} );
var cube = new THREE.Mesh( geometry, material );
scene.add( line );
scene.add( cube );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
I'm working on a tutorial for Three.js and in an example, it presents the concepts of shadows that can be utilized through methods such as: castShadow, receiveShadow and by setting shadowMapenabled to true.
However the example code is for Three.js r69. As of the date of this question, Three.js is at r75 and this code for casting shadows does not work.
Additionally the current Three.js documentation has no information on shadowMapenabled nor shadowMap.enabled or the other methods mentioned.
Suggestions on how to resolve this?
Some of the shadow map properties have been renamed in the recent versions, but they basically work the same.
Setting up the renderer for shadow maps (and choosing the more computational expensive shadow map type):
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
Setting up the light (notice how it also works with THREE.PointLight):
var light = new THREE.PointLight( 0xffffff, 1, 100 );
light.position.set( 0, 12, 0 );
light.castShadow = true; // default false
light.shadow.mapSize.width = 1024; // default 512
light.shadow.mapSize.height = 1024; // default 512
light.shadow.camera.near = 2; // default 0.5
light.shadow.camera.far = 100; // default 500
//light.shadow.camera.left = 500 // Not sure about this one +
// right, top and bottom, Do they still do anything?
scene.add( light );
You get notified of all these API changes if you check your console when trying to use the properties specified in the current documention.
Creating you objects that casts and receives shadows is same as before:
//Creating box
var boxGeometry = new THREE.BoxGeometry( 1, 1, 1 );
var boxMaterial = new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x999999, shininess: 15, shading: THREE.FlatShading } );
var box = new THREE.Mesh( boxGeometry, boxMaterial );
box.castShadow = true;
scene.add( box );
creating plane
var planeGeometry = new THREE.PlaneGeometry( 20, 20, 32, 32 );
var planeMaterial = new THREE.MeshPhongMaterial( { color: 0x00dddd, specular: 0x009900, shininess: 10, shading: THREE.FlatShading } )
var plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.receiveShadow = true;
scene.add( plane );
Placing the plane under the box and it will receive a shadow.
Here is a working codepen example
EDIT
In the current version of THREE.js, the scene needs to be rendered at least twice for the shadows to show.
THREE.js r75.
Here is a the simple code for shadow in three.js .Also included the shadow camera helper
var light = new THREE.SpotLight( 0xFFAA55 );
light.castShadow = true;
light.position.set( 1, 3, 5 );
light.shadowCameraNear = 0.5;
scene.add( light );
helper = new THREE.CameraHelper( light.shadow.camera );
scene.add( helper );
code
I'm creating a skydome in three.js like this:
var geometry = new THREE.SphereGeometry( 40, 32, 15, 1*Math.PI/2, 2*Math.PI, Math.PI, Math.PI);
var material = new THREE.MeshBasicMaterial( { color: 0xddddff } );
mesh = new THREE.Mesh( geometry, material );
mesh.material.side = THREE.DoubleSide;
scene.add( mesh );
This does draw half of a sphere but it also colors the part that I expected to be open (it colors the surface of my mesh that I need the skydome for). How do I solve this problem?
The thing is that even if you draw half a sphere, I doubt it will put UVs correctly, so I very recommend you to make your own skydome using custom mesh.
For skydome you can use mesh.material.side = THREE.BackSide instead of .DoubleSide, btw, unless you stay on the surface all the time.
I wasn't drawing the sphere correctly:
var geometry = new THREE.SphereGeometry( 50, 60, 60, Math.PI, Math.PI, 3*Math.PI/2);
var material = new THREE.MeshBasicMaterial( { color: 0xddddff } );
mesh = new THREE.Mesh( geometry, material );
mesh.material.side = THREE.DoubleSide;
scene.add( mesh );