How to rotate a 3d model horizontally with three.js - javascript

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.

Related

Why wont my threejs model rotate on its own?

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>

Orbit controls; Angle clamping

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>

MeshPhongMaterial doesn't appear

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

Three JS Animation Screen Blank

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;

Three.js add a rotating camera

jsfiddle: http://jsfiddle.net/VsWb9/2151/
After a reading a few articles i am at a loss.
Rotate camera around object with Three.js
Below is simple code for a cube rotating with a floor. This should hopefully be a simple example to follow.
I am trying to add a camera so on click and drag it rotates around the scene. Similar to this http://threejs.org/examples/#misc_controls_trackball
For anyone with the same quesiton lets get you to my point below:
Download three.js here:
http://threejs.org/
You need to have something call orbit controls in your js folder. You will find a link to orbitcontrols to download here:
https://dl.dropboxusercontent.com/u/3587259/Code/Threejs/OrbitControls.js
Copy this and put it in your site folder.
You then need to link to orbit control and three.js it in your html. Like the below:
<script src="js/OrbitControls.js"></script>
<script src="js/three.min.js"></script>
Then see below for a simple wireframe cube with a floor.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 0.1, 1000);
var axisHelper = new THREE.AxisHelper( 5 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//This breaks it?
//controls = new THREE.OrbitControls( camera, renderer.domElement );
var geometry = new THREE.CubeGeometry(2,1,1);
var material = new THREE.MeshBasicMaterial({wireframe: true});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var floorMaterial = new THREE.MeshBasicMaterial( {wireframe: true} );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -50.0;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
camera.position.z = 3;
var render = function () {
requestAnimationFrame(render);
cube.rotation.z += 0.005;
cube.rotation.x += 0.005;
renderer.render(scene, camera);
};
render();

Categories