Hello!
I’m having trouble setting the camera in my project to the right rotation.
I tried with the ThreeJS editor and copy/paste the values in my project’s code but the result is totally different. So I forked the example code from threejsfundamentals.org, trying to set up a live editor with a GUI but the camera’s rotation goes bananas with the code I have by now:
<!DOCTYPE html>
<canvas id="c"></canvas>
<div class="split">
<div id="view1" tabindex="1"></div>
<div id="view2" tabindex="2"></div>
</div>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<title>Camera Live Positioner</title>
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';
import { OrbitControls } from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/controls/OrbitControls.js';
import { GUI } from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
function main() {
const canvas = document.querySelector('#c');
const view1Elem = document.querySelector('#view1');
const view2Elem = document.querySelector('#view2');
const renderer = new THREE.WebGLRenderer({ canvas });
const fov = 45;
const aspect = 2; // the canvas default
const near = 5;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 20);
const cameraHelper = new THREE.CameraHelper(camera);
var gui = new GUI();
var cameraController = {
rotationX: 0
};
function cameraChanger() {
//console.log(cameraController['rotationX']);
camera.rotateX(cameraController['rotationX']);
}
gui.add(cameraController, 'rotationX', 0, 90, 1).onChange(cameraChanger);
const controls = new OrbitControls(camera, view1Elem);
controls.target.set(0, 5, 0);
controls.update();
const camera2 = new THREE.PerspectiveCamera(
60, // fov
2, // aspect
0.1, // near
500, // far
);
camera2.position.set(40, 10, 30);
camera2.lookAt(0, 5, 0);
const controls2 = new OrbitControls(camera2, view2Elem);
controls2.target.set(0, 5, 0);
controls2.update();
const scene = new THREE.Scene();
scene.background = new THREE.Color('black');
scene.add(cameraHelper);
{
const planeSize = 40;
const loader = new THREE.TextureLoader();
const texture = loader.load('https://threejsfundamentals.org/threejs/resources/images/checker.png');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.magFilter = THREE.NearestFilter;
const repeats = planeSize / 2;
texture.repeat.set(repeats, repeats);
const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
const planeMat = new THREE.MeshPhongMaterial({
map: texture,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(planeGeo, planeMat);
mesh.rotation.x = Math.PI * -.5;
scene.add(mesh);
}
{
const cubeSize = 4;
const cubeGeo = new THREE.BoxBufferGeometry(cubeSize, cubeSize, cubeSize);
const cubeMat = new THREE.MeshPhongMaterial({ color: '#8AC' });
const mesh = new THREE.Mesh(cubeGeo, cubeMat);
mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
scene.add(mesh);
}
{
const sphereRadius = 3;
const sphereWidthDivisions = 32;
const sphereHeightDivisions = 16;
const sphereGeo = new THREE.SphereBufferGeometry(sphereRadius, sphereWidthDivisions, sphereHeightDivisions);
const sphereMat = new THREE.MeshPhongMaterial({ color: '#CA8' });
const mesh = new THREE.Mesh(sphereGeo, sphereMat);
mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
scene.add(mesh);
}
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(0, 10, 0);
light.target.position.set(-5, 0, 0);
scene.add(light);
scene.add(light.target);
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function setScissorForElement(elem) {
const canvasRect = canvas.getBoundingClientRect();
const elemRect = elem.getBoundingClientRect();
// compute a canvas relative rectangle
const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
const left = Math.max(0, elemRect.left - canvasRect.left);
const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
const top = Math.max(0, elemRect.top - canvasRect.top);
const width = Math.min(canvasRect.width, right - left);
const height = Math.min(canvasRect.height, bottom - top);
// setup the scissor to only render to that part of the canvas
const positiveYUpBottom = canvasRect.height - bottom;
renderer.setScissor(left, positiveYUpBottom, width, height);
renderer.setViewport(left, positiveYUpBottom, width, height);
// return the aspect
return width / height;
}
function render() {
resizeRendererToDisplaySize(renderer);
// turn on the scissor
renderer.setScissorTest(true);
// render the original view
{
const aspect = setScissorForElement(view1Elem);
// adjust the camera for this aspect
camera.aspect = aspect;
camera.updateProjectionMatrix();
cameraHelper.update();
// don't draw the camera helper in the original view
cameraHelper.visible = false;
scene.background.set(0x000000);
// render
renderer.render(scene, camera);
}
// render from the 2nd camera
{
const aspect = setScissorForElement(view2Elem);
// adjust the camera for this aspect
camera2.aspect = aspect;
camera2.updateProjectionMatrix();
// draw the camera helper in the 2nd view
cameraHelper.visible = true;
scene.background.set(0x000040);
renderer.render(scene, camera2);
}
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
</body>
</html>
CSS looks like this:
html, body {
margin: 0;
height: 100%;
}
#c {
width: 100%;
height: 100%;
display: block;
}
.split {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
}
.split > div {
width: 100%;
height: 100%;
}
Hope somebody can help!