I have just started learning three.js and I want to know if it is possible to move a 3d model to the right side of the screen instead of being centered in the middle.
Here is an image to help with the explanation of what I am trying to do.
(link to the image)
The three.js code looks like this:
<script>
let scene, carMesh, camera, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xFFFFFF);
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(25,window.innerWidth/window.innerHeight,1,5000);
camera.position.set(1500, 1200, 2000);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', renderer);
hlight = new THREE.AmbientLight (0x404040,100);
scene.add(hlight);
directionalLight = new THREE.DirectionalLight(0xffffff,100);
directionalLight.position.set(0,1,0);
directionalLight.castShadow = true;
scene.add(directionalLight);
light = new THREE.PointLight(0xc4c4c4,10);
light.position.set(0,300,500);
scene.add(light);
light2 = new THREE.PointLight(0xc4c4c4,10);
light2.position.set(500,100,0);
scene.add(light2);
light3 = new THREE.PointLight(0xc4c4c4,10);
light3.position.set(0,100,-500);
scene.add(light3);
light4 = new THREE.PointLight(0xc4c4c4,10);
light4.position.set(-500,300,500);
scene.add(light4);
let loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function(gltf){
scene.add(gltf.scene);
carMesh = gltf.scene.children[0];
carMesh.scale.set(0.5,0.5,0.5);
camera.lookAt(carMesh.position);
});
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene,camera);
controls.update(scene,);
}
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
</script>
Many thanks
Ollie
This has little to to with Three.js. Rather, it is a question of the page's layout, and the relative placement of the Three.js dom element in the dom tree.
In your code, the Three.js content is a child of the body element:
document.body.appendChild(renderer.domElement);
If you want to position it in a certain way, e.g. on the right side, you can position an element, typically a div, and use this as the parent element of the Three.js content.
A very simple solution is:
<div id="container" style="float: right"></div>
...
document.getElementById("container").appendChild(renderer.domElement);
Of course, to meet your needs, you may have to style/position other elements on your page as well, e.g. the element left of the Three.js div. This can be achieved by css, which you can define either inline in the elements via style, or in a separate section of your document (the preferred approach).
Related
I’m trying to make a piece using three js where the object tilts away from the mouse on mouseover, like the locations here (mouse over the VIST tab):
https://meowwolf.com/explore
I don’t know whether this utilized three js or another library, but I don’t know how to go about it. I can’t find any examples on three js.org with the same “tilt away” technology.
So far Im just working with the basic cube example, but ultimately want to be able to "tilt" other objects/particles.
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var texture = new THREE.TextureLoader().load( 'textures/crate.gif' );
var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { map: texture } );
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 );
How can I do this, starting with just a box?
FOR CLARITY:
The meow wolf site has the objects tilt toward the corner of the object where the mouse is, and lerp back to original rotation when mouse exits
I am trying to load my ply file using Three.js. It has worked but I almost don't see any colors. There are some glimpses here and there, but it's mostly black (the first image below). The image opens properly (with colors) in MeshLab (the second image below). I have tried vertexColors: THREE.VertexColors (as suggested in Three.js - ply files - why colorless?) and vertexColors: THREE.FaceColors but nothing seemed to help. I am a three.js newbie, so please tell me what am I doing wrong.
and my code:
<!doctype html>
<html lang="en">
<head>
<title>Icon 7</title>
<meta charset="utf-8">
</head>
<body style="margin: 0;">
<script src="js/three.min.js"></script>
<script src="js/PLYLoader.js"></script>
<script src="js/OrbitControls.js"></script>
<script>
// Set up the scene, camera, and renderer as global variables.
var scene, camera, renderer;
init();
animate();
// Sets up the scene.
function init() {
// Create the scene and set the scene size.
scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
// Create a renderer and add it to the DOM.
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
// Create a camera, zoom it out from the model a bit, and add it to the scene.
camera = new THREE.PerspectiveCamera(35, WIDTH / HEIGHT, 0.1, 100);
camera.position.set(0,0.15,3);
camera.lookAt(new THREE.Vector3(0,0,0));
scene.add(camera);
// Create an event listener that resizes the renderer with the browser window.
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
// Set the background color of the scene.
renderer.setClearColor(0xd3d3d3, 1);
// Create a light, set its position, and add it to the scene.
var light = new THREE.PointLight(0xffffff);
light.position.set(0,200,100);
scene.add(light);
// Load in the mesh and add it to the scene.
var loader = new THREE.PLYLoader();
loader.load( './models/foot.ply', function ( geometry ) {
geometry.computeVertexNormals();
geometry.center();
var material = new THREE.MeshStandardMaterial ({ shininess: 1000,vertexColors: THREE.FaceColors } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = 0;
mesh.castShadow = false;
mesh.receiveShadow = false;
scene.add( mesh );
} );
// Add OrbitControls so that we can pan around with the mouse.
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.userPanSpeed = 0.05;
}
// Renders the scene and updates the render as needed.
function animate() {
// Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimationFrame(animate);
// Render the scene.
renderer.render(scene, camera);
controls.update();
}
</script>
</body>
</html>
Edit: as I don't have separate textures, this is not a duplicate question.
Instead of using MeshStandardMaterial use MeshBasicMaterial
When using three.js, I found a conflict between dat.gui.js and trackballControl.js. For example, after changing values by dat.gui, I can't rotate the camera with mousemove because the mouse can not move out from the area of GUI. Why and how to deal with it?
The trackballControls constructor allows for a second argument of a dom element.
This dom element is what the mouse event listeners for the controls will be added to. If you don't supply this argument, the mouse event listeners will be added to the document (which I believe is your problem).
It is hard to give you an example which will work for you, because you have not posted your code.
You should be able to send the renderer dom element to the trackballControls to fix your problem.
eg.
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
// send dom element to trackballControlls.
controls = new THREE.TrackballControls( camera, renderer.domElement );
Run snippet below for working example.
var camera, scene, renderer, mesh, material, controls, gui, directionalLight;
init();
render();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Add TrackballControls, sending dom element to attach mouseevent listeners to.
controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.addEventListener( 'change', render );
// Create scene.
scene = new THREE.Scene();
// Create material
material = new THREE.MeshPhongMaterial();
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
// Create directional light and add to scene.
directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// Add GUI
var gui = new dat.GUI();
var lightFolder = gui.addFolder('Light');
lightFolder.add(directionalLight, 'intensity').onChange(function(){render()});
lightFolder.open();
}
function animate() {
requestAnimationFrame(animate);
controls.update();
}
// Only called by controls change or gui change.
function render() {
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
controls.handleResize();
}
body {
margin: 0px;
}
<script src="https://cdn.rawgit.com/dataarts/dat.gui/v0.6.2/build/dat.gui.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/TrackballControls.js"></script>
I'm an old COBOL programmer, teaching myself a bit of Javascript and Three.js for a little personal project, and I've got struck now with this doubt for almost two days.
I've read all the questions about OrbitControls here in StackOverflow, and couldn't find anything related to what I'm trying to do. So any help would be appreciated.
I have a scene that's like the image below:
And here's what my Script Looks like right Now:
var container, renderer, scene, camera, controls;
var Main = {
Init: function () {
document.getElementById("comprimento").innerHTML = "Comprimento: " + localStorage.storLength / 100;
document.getElementById("largura").innerHTML = "Largura: " + localStorage.storWidth / 100;
document.getElementById("altura").innerHTML = "Altura: " + localStorage.storHeight / 100;
document.getElementById("quadrado").innerHTML = "Metros²: " + localStorage.storSquare;
Main.Render();
Main.Camera();
Main.Draw();
Main.Update();
// events
window.addEventListener('resize', onWindowResize, false);
},
Render: function () {
renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffe6ff);
container = document.getElementById("building");
document.body.appendChild(container);
container.appendChild(renderer.domElement);
// Inicializacao da Cena
scene = new THREE.Scene();
},
Camera: function () {
//Inicializacao da Camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
//Posicao da Camera nos eixos X,Y,Z
camera.position.set(0, 100, 800);
camera.lookAt(scene.position);
//Controle de Camera
controls = new THREE.OrbitControls(camera, renderer.domElement);
//Controle de Iluminação
var light = new THREE.PointLight(0xffffff);
light.position.set(100, 250, 250);
scene.add(light);
},
Draw: function () {
var planeGeometry = new THREE.PlaneGeometry(localStorage.storWidth, localStorage.storLength, 10, 10);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0x888888,
side: THREE.DoubleSide
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
scene.add(plane);
},
Update: function () {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(Main.Update);
}
}
function onWindowResize(event) {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
}
Main.Init();
This works just fine for using the orbitControl, while the mouse is over the part where the rendered materials are.
What I'm trying to do is, limit the Orbit control functionality to only be usable while the mouse is over the little green div that is overlaying the render scene. I've tried messing up with the parameters of the OrbitControl, tried adding onMouseOver functions on the javascript, associated with the div in the html, but nothing seems to work.
What I'm trying to do is even possible? If so, what am I missing?
Thanks in advance.
If I got you correctly, let's suppose, that you have a little green div
<div style="position: absolute;" id="LittleGreenDiv"></div>
Then you can use it as the second parameter when you create the object of controls:
var controls = new THREE.OrbitControls(camera, document.getElementById("LittleGreenDiv"));
jsfiddle example.
I have a Website with WebGL content. For this I have a div-element for showing the WebGL.
Now I am trying to get this content in multiple divs on the same page. The content should be exactly the same. If it is possible the animation should be shown on all divs.
I have tried to create a second renderer and tried to add this to the second div but this seems not to work.
How can I get the same WebGL content in multiple divs on the same page?
This is my code for creating the WebGL content. renderer1 was my try to append to the second div but this didnt work.
<div id="WebGLCanvas"/>
<script>
var scene;
var camera;
var controls;
var geometryArray;
initializeScene();
animateScene();
function initializeScene(){
if(!Detector.webgl){
Detector.addGetWebGLMessage();
return;
}
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setClearColorHex(0x000000, 1);
renderer1 = new THREE.WebGLRenderer({antialias:true});
renderer1.setClearColorHex(0x000000, 1);
canvasWidth = window.innerWidth;
canvasHeight = window.innerHeight;
renderer.setSize(canvasWidth, canvasHeight);
renderer1.setSize(canvasWidth, canvasHeight);
document.getElementById("WebGLCanvas").appendChild(renderer.domElement);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 1, 100);
camera.position.set(0, 0, 6);
camera.lookAt(scene.position);
scene.add(camera);
controls = new THREE.TrackballControls(camera, renderer.domElement);
axisSystem = new AxisSystem(camera, controls);
geometryArray = new Object();
var loader = new THREE.JSONLoader();
for(var i = 0; i < jsonFileNames.length; i++){
var layerName = jsonFileNames[i].split("/")[2].split(".")[0];
loader.load(jsonFileNames[i], function(geometry, layerName){
mesh = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({vertexColors: THREE.FaceColors}));
mesh.scale.set(0.003, 0.003, 0.003);
mesh.doubleSided = true;
scene.add(mesh);
geometryArray[layerName] = mesh;
}, layerName);
}
var directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
directionalLight.position = camera.position;
scene.add(directionalLight);
}
function animateScene(){
controls.update();
axisSystem.animate();
requestAnimationFrame(animateScene);
renderScene();
}
function renderScene(){
renderer.render(scene, camera);
axisSystem.render();
}
</script>
EDIT:
I have tried to add the renderer to a second div element but the scene than only appears on the last added div element and not on both.
This is the code I have tried. A simple example of what I am trying is that I want a left div element and a right div element. On both I want the same content. That means if I move the 3D object on my left element it should also move on the right element.
container = document.getElementById("webglcanvas");
container2 = document.getElementById("webglcanvas2");
containerWidth = container.clientWidth;
containerHeight = container.clientHeight;
renderer = new THREE.WebGLRenderer({antialias:true, alpha:true});
renderer.setSize(containerWidth, containerHeight);
container.appendChild(renderer.domElement);
container2.appendChild(renderer.domElement);
It's possible, take a look at this example. You just have to set the same camera not four different:
http://stemkoski.github.io/Three.js/Viewports-Quad.html
Did you need something more?