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.
Related
I currently have a New Jersey d3js map. A 3D map is created out of a topo.json.
I'm trying to find a way to make my map rotate on a fixed axis where I choose to make it appear, but instead, it decides to go over the scene. Scrolling makes it go around a globe instead of just rotating on itself. I've seen a lot of answers in SO and videos about examples that work perfectly out of the box like I'm expecting my model to do, but it just simply decides to scroll around like a globe.
It makes sense to set up a pivot and rotate around it, but I'm stuck figuring out how to make it work.
var pivot = new THREE.Object3D();
pivot.position.set(0,0,0);
pivot.rotation.set(0,0,0);
scene.add(pivot);
This is my current map.
Repository: https://github.com/max-benzait/d3js-new-jersey
Github Page: https://max-benzait.github.io/d3js-new-jersey/
It rotates as if it was going around a globe, and I'm looking to make it scroll like in this example.
var camera, scene, renderer, mesh;
var local = false;
init();
animate();
function init() {
// Camera setup
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.set( 1, 2, - 2 );
// Scene setup
scene = new THREE.Scene();
camera.lookAt( scene.position );
// Cube Setup
var geometry = new THREE.BoxBufferGeometry( 0.5, 0.5, 0.5 );
var material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh( geometry, material );
mesh.position.set(0.5,0.5,0.5);
// Note: Until the mesh is rotated, global and local rotation are the same
mesh.rotation.y = 0.5;
scene.add( mesh );
// Add grid and axes
scene.add( new THREE.GridHelper( 4, 10 ) );
scene.add( new THREE.AxesHelper() );
// Add renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// Create rotation toggle button
var button = document.createElement("button");
button.innerText = "Local Rotation Off";
button.onclick = () => {
local = !local
if (local) button.innerText = "Local Rotation On";
else button.innerText = "Local Rotation Off";
};
document.body.appendChild(button);
}
function animate() {
requestAnimationFrame( animate );
// This is GLOBAL
if (!local) mesh.rotation.x += 0.03;
// This is LOCAL
else mesh.rotateX(0.03);
renderer.render( scene, camera );
}
body {
margin: 0;
}
button {
position: absolute;
top: 10px;
left: 10px;
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
I am having trouble rotating my 3d man object model horizontally via three.js.
My main confusion is that I dont know if I should to be controlling the camera angle or the object angle in order to achieve this and based on my research, there seemes to be different methods to achieving what I need but I am not sure which method would work with what I implemented so far.
<script src="js/three.js"></script>
<script src="js/OBJLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script>
var scene, camera, renderer , controls, ambientLight, pointLight, textureLoader, map, material, loader;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var SPEED = 0.01;
function init() {
scene = new THREE.Scene();
initChris();
initCamera();
initRenderer();
initControl();
document.body.appendChild(renderer.domElement);
}
function initCamera() {
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 8000);
ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
pointLight = new THREE.PointLight( 0xffffff, 0.8 );
camera.position.set(0, 0, 4000);
camera.add( pointLight );
scene.add( camera );
scene.add( ambientLight );
camera.lookAt(scene.position);
}
function initRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(WIDTH, HEIGHT);
renderer.setClearColor( 0x000000, 0 );
}
function initControl(){
controls = new THREE.OrbitControls( camera );
controls.enableZoom = false;
controls.minPolarAngle = Math.PI * 0.5;
controls.maxPolarAngle = Math.PI * 0.5;
controls.update();
}
function initChris() {
textureLoader = new THREE.TextureLoader();
map = textureLoader.load('img/CHRIS.BMP');
material = new THREE.MeshPhongMaterial({map: map});
loader = new THREE.OBJLoader();
loader.load( 'obj/CHRIS.OBJ', function ( object ) {
object.traverse( function ( node ) {
if ( node.isMesh ){
node.material = material;
}
});
scene.add( object );
});
}
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
init();
render();
</script>
I also dont know if there is something wrong with my 3d man model because I tried using different models and each model gave me a different rotation angle. For example, the model I am currently working with is showing my 3d man model at birds-eye-view and the rotation pivot is occuring at his feet while if I change the 3d man model taken from three.js example, I get to see the 3d man model at front view and the rotation pivot is centered which is what I am tryin to achieve with the 3d man model that I am working with.
Any help or advise is greatly appreciated.
I am a beginner in THREE.js, I want to create a sphere which I will use to create globe with texture but I'm stuck when creating MeshPhongMaterial it appears nothing. Otherwise when I'm using MeshBasicMaterial it appears,
And this is my code
var mainScene, camera, aspect, renderer;
mainScene = new THREE.Scene();
aspect = window.innerWidth / window.innerHeight;
camera = new THREE.PerspectiveCamera(40, aspect, 0.1, 100);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
var canvasContainer = document.getElementById("canvasContainer");
canvasContainer.appendChild(renderer.domElement);
var mesh = new THREE.Mesh(
new THREE.SphereGeometry(0.5,32,32),
new THREE.MeshPhongMaterial({
color: 0x00ff00,
wireframe: true
})
);
mainScene.add( mesh );
camera.position.z = 5;
var render = function(){
requestAnimationFrame(render);
renderer.render(mainScene, camera);
}
render();
I don't know what's wrong with this code and should I use MeshPhongMaterial to do it?
Thank you
MeshPhongMaterial requires scene lights.
Here is one way, but look at the three.js examples.
// ambient
scene.add( new THREE.AmbientLight( 0xffffff, 0.1 ) );
// light
var light = new THREE.PointLight( 0xffffff, 1 );
camera.add( light );
scene.add( camera ); // required because the camera has a child
three.js r.84
I'm in the middle of following some beginning lessons on webgl on udacity. In the online snippets they used material.ambient for MeshLambertMaterial.
Below, I'm attempting to create a basic cube example from scratch, but when I try to replace MeshBasicMaterial with MeshLambertMaterial I'm running into problems trying to get the cube to display.
Why isn't ambient defined on material, the way it is in the udacity tutorials? The threejs docs aren't very helpful, they don't even mention an ambient method on material... did the API change?
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 geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
var kv = 0.4;
//this line gets error: app.js:36 Uncaught TypeError: Cannot read property 'setRGB' of undefined
material.ambient.setRGB(kv * material.color.r, kv * material.color.g, kv * material.color.b);
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
}
render();
three.js materials no longer have an ambient property.
The ambient reflectance of the material (how the material responds to indirect, or ambient, light) is now assumed to be the same as the diffuse reflectance of the material (how the material responds to direct light).
The diffuse reflectance of the material is also known as the material's color.
three.js r.80
Why's my shoe loading upside down?, how to get it to load the right way up? And how do I get rid of those crazy metallic highlights?
Here's the working code and
here's the json model file. (I tried to do a plunker, but couldn't get around CORS issue of needing to load an external 6mb json file :( )
Here's my JS:
var scene, camera, renderer, geometry, material, cube, group, textureUrl, texture;
init();
render();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 275, window.innerWidth / window.innerHeight, 0.1, 10000 );
camera.position.z = 20;
controls = new THREE.OrbitControls( camera);
//set background to have transparency - alpha: true
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("viewport").appendChild(renderer.domElement);
var loader = new THREE.ObjectLoader();
loader.load("models/shoe4.json", function (obj) {
scene.add (obj);
});
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 300, 300, 300 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -300, -300, -300 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
function render() {
requestAnimationFrame(render);
scene.rotation.y += 0.005;
renderer.render(scene, camera);
}
Sorry to disagree with the previous answer...
Your model is upside down because the field-of-view of your camera, camera.fov, is 275 degrees. A reasonable value is 50 degrees.
All your MeshPhongMaterials have a shininess of 50. That is a perfectly reasonable value, and fairly low. material.shininess can range from 1 to 1000 or more for MeshPhongMaterial.
The "crazy metal look" is because you have set the specular reflectance of the material -- the material.specular property -- too high. A reasonable value in your case is:
material.specular.setRGB( 0.05, 0.05, 0.05 );
three.js r.71
If your model is upside down in your scene then maybe its just exported on its head. Could be an error with Y-up, best to fix it in your 3d Software. If you want to fix it in code, you can just rotate the geometry by 180 degrees:
var rotation = new THREE.Matrix4().makeRotationZ(Math.PI/2);
obj.geometry.applyMatrix(transformation);
Or you can also just rotate your mesh (-group) if you dont want to hassle with the geometry by doing
obj.rotation.z = Math.PI/2;
The crazy metal look is the specular highlight of your MeshPhongMaterial. All your materials have a shininess of 50, which is higher than usual. Set this value lower and/or darken the specular color which is the color of the highlight.
Materials take some time tweaking to look good in three.js, you will have to play around with the values depending on your lighting also.