Trying to work with PointerLockControls, WASD keys and Three.js - javascript

I hope I'm not asking an obviously noob question, but I noticed on the three.js official examples, PointerLockControls.js allows for mouse pointer lock AND WASD keys navigation.
I've managed to get the mouse pointer to lock, but I am struggling to get the WASD keys to do anything.
Perhaps this is not the .js script I need to begin with?
I'm still very new to this, but I feel my file is so close! Any help would be appreciated.
this is my code
import * as THREE from './three.js-master/build/three.module.js'
import {GLTFLoader} from './three.js-master/examples/jsm/loaders/GLTFLoader.js'
import {PointerLockControls} from './three.js-master/examples/jsm/controls/PointerLockControls.js'
if (typeof window !== 'undefined' && typeof window.THREE === 'object') {
window.THREE.SimpleFPControls = SimpleFPControls;
}
const canvas = document.querySelector('.webgl')
const scene = new THREE.Scene()
const loader = new GLTFLoader
loader.load('assets/untitled.glb', function(glb){
console.log(glb)
const root = glb.scene;
root.scale.set(0.01,0.01,0.01)
scene.add(root);
}, function(xhr){
console.log((xhr.loaded/xhr.total * 100) + "% loaded")
}, function(error){
console.log('An error occured')
})
const light = new THREE.DirectionalLight(0xffffff, 1)
light.position.set(0,0,2)
scene.add(light)
// const geometry = new THREE.BoxGeometry(1,1,1)
//const material = new THREE.MeshBasicMaterial({
// color: 0x00ff00
//})
//const boxMesh = new THREE.Mesh(geometry,material)
//scene.add(boxMesh)
//BOILER PLATE CODE
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
const camera = new THREE.PerspectiveCamera(75, sizes.width/sizes.height, 0.1, 100)
camera.position.set(0,1,10)
camera.lookAt(0, 0, 0);
scene.add(camera)
//add document.body to PointerLockControls constructor
let fpsControls = new PointerLockControls( camera , document.body );
//add event listener to your document.body
document.body.addEventListener( 'click', function () {
//lock mouse on screen
fpsControls.lock();
}, false );
const renderer = new THREE.WebGLRenderer({
canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.shadowMap.enabled = true
renderer.outputEncoding = true
document.body.appendChild(renderer.domElement)
function animate(){
requestAnimationFrame(animate)
renderer.render(scene,camera)
}
const controls = new PointerLockControls(camera, document.bodybody);
animate()

PointerLockControls only adds event listeners to pointerlockchange, pointerlockerror and mousemove. So it handles the mouse capturing and applies the mouse movements to the camera in order to rotate it.
However, the class adds not key event listeners. If you closely study the source code of official example, you will see that these event listeners are implemented on application level.

Related

[Violation]Added non-passive event listener to a scroll-blocking 'touchstart' event

I just started working with Three.js & everytime I try to use the onchange event, I keep getting this non-passive event listener violation for my onchange event. please help.
ERROR : [Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952
CODE :
"use strict";
import * as THREE from "https://unpkg.com/three#0.141.0/build/three.module";
import * as dat from "https://cdn.skypack.dev/dat.gui";
// Adding the gui //
const gui = new dat.GUI();
const world = {
plane: {
width: 10
}
}
gui.add(world.plane, 'width', 1, 20).
onchange = function() {
console.log(planeMesh.geometry);
// planeMesh.geometry.dispose();
// planeMesh.geometry = new THREE.planeGeometry(world.plane.width, 10, 10, 10);
}
// Instantiating scene, camera & renderer //
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
// Building the geometry & material //
const planeGeometry = new THREE.PlaneGeometry(10, 10, 10, 10);
const planeMaterial = new THREE.MeshPhongMaterial({
color: 0xff0000,
side: THREE.DoubleSide,
flatShading: THREE.FlatShading
});
// Binding the geometry and material //
const planeMesh = new THREE.Mesh(planeGeometry,planeMaterial);
// Adding the planeMesh to the scene //
scene.add( planeMesh );
const {array} = planeMesh.geometry.attributes.position;
for(let i=0; i<array.length; i += 3){
const x = array[i];
const y = array[i+1];
const z = array[i+2];
array[i+2] = z + Math.random();
}
// Adding light //
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0,0,1);
scene.add(light);
// Animating & rendering the design //
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();

Three.js Using Raycaster to detect line and cone children of ArrowHelper

I have a functioning Raycaster for a simple painting app. I use it for a "bucket tool" in which the user can click on an object and change its color. It works for geometry objects such as BoxGeometry and CircleGeometry, but I'm struggling to apply it to the children of an ArrowHelper object. Because ArrowHelper isn't a shape and does not possess a geometry attribute, Raycaster does not detect collision with its position when checking scene.children for intersections. However, the children of ArrowHelper objects are always two things: a line and a cone, both of which have geometry, material, and position attributes.
I HAVE TRIED:
Toggling the recursive boolean of the function .intersectObjects(objects: Array, recursive: Boolean, optionalTarget: Array ) to true, so that it includes the children of the objects in the array.
Circumventing the ArrowHelper parent by iterating through scene.children for ArrowHelper objects and adding their lines and cones into a separate array of objects. From there I attempted to check for intersections with only the list of lines and cones, but no intersections were detected.
Raycaster setup:
const runRaycaster = (mouseEvent) => {
... // sets mouse and canvas bounds here
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
for (let i = 0; i < intersects.length; i++) {
// works for GEOMETRY ONLY
// needs modifications for checking ArrowHelpers
intersects[i].object.material.color.set(currentColor);
}
}
};
Here's my attempt to check the lines and cones individually, without the ArrowHelper parent:
let arrowObjectsList = [];
for (let i = 0; i < scene.children.length; i++) {
if (scene.children[i].type === 'ArrowHelper') {
arrowObjectsList.push(scene.children[i].line);
arrowObjectsList.push(scene.children[i].cone);
} else {
console.log(scene.children[i].type);
}
}
console.log(arrowObjectsList); // returns 2 objects per arrow on the canvas
// intersectsArrows always returns empty
const intersectsArrows = raycaster.intersectObjects(arrowObjectsList, true);
SOME NOTES:
Every ArrowHelper, its line, and its cone have uniquely identifiable names so they can be recolored/repositioned/deleted later.
The Raycaster runs with every onMouseDown and onMouseMove event.
Notably, the line and cone children of ArrowHelpers are BufferGeometry and CylinderBufferGeometry, respectively, rather than variations of Geometry. I'm wondering if this has anything to do with it. According to this example from the Three.JS documentation website, BufferGeometry can be detected by Raycaster in a similar fashion.
Setting recursion = true worked for me. Run the simple code below, and click on the arrow head. You will see the intersection information printed to the console. (three.js r125)
let W = window.innerWidth;
let H = window.innerHeight;
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(28, 1, 1, 1000);
camera.position.set(5, 5, 5);
camera.lookAt(scene.position);
scene.add(camera);
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, -1);
camera.add(light);
const mesh = new THREE.ArrowHelper(
new THREE.Vector3(0, 0, 1),
new THREE.Vector3(0, 0, 0),
2,
0xff0000,
1,
1
);
scene.add(mesh);
function render() {
renderer.render(scene, camera);
}
function resize() {
W = window.innerWidth;
H = window.innerHeight;
renderer.setSize(W, H);
camera.aspect = W / H;
camera.updateProjectionMatrix();
render();
}
window.addEventListener("resize", resize);
resize();
render();
// RAYCASTER STUFF
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
renderer.domElement.addEventListener('mousedown', function(e) {
mouse.set(
(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1
);
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
console.log(intersects);
});
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
background: skyblue;
}
<script src="https://threejs.org/build/three.min.js"></script>
After a closer inspection, it was a matter of the set position, not necessarily the arrow. The position of the arrow varied based on user mouse click to specify the start point. However, it still presented several problems: It was very difficult to select the line because the lineWidth value of LineBasicMaterial cannot have any other value besides 1, despite being editable. This is due to a limitation in the OpenGL Core Profile, as addressed in the docs and in this question. Similarly, the cone would not respond to setLength. This limits the customization of the ArrowHelper tool pretty badly.
Because of this, I decided to entirely replace ArrowHelper with two objects coupled together: tubeGeometry and coneGeometry, both assigned a MeshBasicMaterial, in a way which can be accessed by Raycasters out of the box.
... // the pos Float32Array is set according to user mouse coordinates.
const v1 = new THREE.Vector3(pos[0], pos[1], pos[2]);
const v2 = new THREE.Vector3(pos[3], pos[4], pos[5]);
const material = new THREE.MeshBasicMaterial({
color: color,
side: THREE.DoubleSide,
});
// Because there are only two vectors, no actual curve occurs.
// Therefore, it's our straight line.
const tubeGeometry = new THREE.TubeBufferGeometry(
new THREE.CatmullRomCurve3([v1, v2]), 1, 3, 3, false);
const coneGeometry = new THREE.ConeGeometry(10, 10, 3, 1, false);
arrowLine = new THREE.Mesh(tubeGeometry, material);
arrowTip = new THREE.Mesh(coneGeometry, material);
// needs names to be updated later.
arrowLine.name = 'arrowLineName';
arrowTip.name = 'arrowTipName';
When placing the arrow, the user will click and drag to specify the start and end point of the arrow, so the arrow and its tip have to be updated with onMouseMove. We have to use Math.atan2 to get the angle in degrees between v1 and v2, with v1 as the center. Subtracting 90 orients the rotation to the default position.
... // on the onMouseMove event, pos is updated with new coords.
const setDirection = () => {
const v1 = new THREE.Vector3(pos[0], pos[1], pos[2]);
const v2 = new THREE.Vector3(pos[3], pos[4], pos[5]);
// copying the v2 pos ensures that the arrow tip is always at the end.
arrowTip.position.copy(v2);
// rotating the arrow tip according to the angle between start and end
// points, v1 and v2.
let angleDegrees = 180 - (Math.atan2(pos[1] - pos[4], pos[3] - pos[0]) * 180 / Math.PI - 90);
const angleRadians = angleDegrees * Math.PI / 180;
arrowTip.rotation.set(0, 0, angleRadians);
// NOT VERY EFFICIENT, but it does the job to "update" the curve.
arrowLine.geometry.copy( new THREE.TubeBufferGeometry(new THREE.CatmullRomCurve3([v1, v2]),1,3,3,false));
scene.add(arrowLine);
scene.add(arrowTip);
};
Out of the box, this "arrow" allows me to select and edit it with Raycaster without a problem. No worrying about line positioning, line thickness, or line length.

THREE.PointerLockControls doesn't lock my pointer

Uncaught TypeError: THREE.PointerLockControls is not a constructor
I can't use firstperson controls for whatever reason, I am really lost for reason with this one. It's got me really stumped.
const THREE = require('THREE');
var FirstPersonControls = require('first-person-controls');
const CANNON = require('cannon');
var keyboard = new THREEx.KeyboardState();
var lights = [];
var camSpeed = 1;
var world, mass, body, body2, shape, shape2, timeStep=1/60,
camera, scene, renderer, geometry, material, mesh, textureCube;
initThree();
initCannon();
animate();
function initCannon() {
world = new CANNON.World();
world.gravity.set(0,-9.8,0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
shape = new CANNON.Box(new CANNON.Vec3(1,1,1));
shape2 = new CANNON.Box(new CANNON.Vec3(50,1,50));
mass = 1;
body = new CANNON.Body({
mass: 1
});
body2 = new CANNON.Body({
mass: 0
});
body.position.set(1,10,1);
body.addShape(shape);
body2.addShape(shape2);
body.angularDamping = 0.5;
world.addBody(body);
world.addBody(body2);
}
function initThree() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 10000 );
var controls = new THREE.FirstPersonControls(camera);
controls.lookSpeed = 0.1;
controls.movementSpeed = 10;
var clock = new THREE.Clock(true);
var prefix = ".png"
var r = __dirname + "/skyboxes/mp_cliffside/";
var urls = [
r + "px" + prefix, r + "nx" + prefix,
r + "py" + prefix, r + "ny" + prefix,
r + "pz" + prefix, r + "nz" + prefix
];
textureCube = new THREE.CubeTextureLoader().load( urls );
var dottedAlphaMap = new THREE.TextureLoader().load( __dirname + "/textures/brickmap.png" );
var dottedAlphaMap2 = new THREE.TextureLoader().load( __dirname + "/textures/stonemap-wet-texture.jpg" );
scene.background = textureCube;
lights[0] = new THREE.PointLight( '#ffffff', 3, 100 );
lights[0].position.set( 0, 5, 0 );
scene.add( lights[0] );
scene.add( camera );
renderer = new THREE.WebGLRenderer({ alpha:false });
renderer.setSize( window.innerWidth, window.innerHeight );
camera.position.y = 40;
camera.rotation.x = -90 * Math.PI / 180;
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
updatePhysics();
render();
}
var controllee = camera;
function updatePhysics() {
// Step the physics world
world.step(timeStep);
// Copy coordinates from Cannon.js to Three.js
lights[0].position.copy(camera.position)
}
function render() {
requestAnimationFrame(render);
controls.update(clock.getDelta());
if(keyboard.pressed("F")){
camera.fov += 0.1;
camera.updateProjectionMatrix();
}
if(keyboard.pressed("G")){
camera.fov -= 0.1;
camera.updateProjectionMatrix();
}
if(keyboard.pressed("space")){
controllee.translateY(camSpeed/10);
}
if(keyboard.pressed("shift")){
controllee.translateY(-camSpeed/10);
}
if(keyboard.pressed("W")){
controllee.translateZ(-camSpeed/10);
}
if(keyboard.pressed("S")){
controllee.translateZ(camSpeed/10);
}
if(keyboard.pressed("A")){
controllee.translateX(-camSpeed/10);
}
if(keyboard.pressed("D")){
controllee.translateX(camSpeed/10);
}
if(keyboard.pressed("I")){
controllee.rotateX(camSpeed/100);
}
if(keyboard.pressed("K")){
controllee.rotateX(-camSpeed/100);
}
if(keyboard.pressed("J")){
controllee.rotateY(camSpeed/100);
}
if(keyboard.pressed("L")){
controllee.rotateY(-camSpeed/100);
}
if(keyboard.pressed("U")){
controllee.rotateZ(camSpeed/100);
}
if(keyboard.pressed("O")){
controllee.rotateZ(-camSpeed/100);
}
renderer.render( scene, camera );
}
I am using imported three.js and cannon.js, from node package manager.
I am trying to get the controls to be like an fps, but stuff like this keeps getting in my way!
Any help is appreciated, the only thing i can think of is that its not included in the NPM version of three, in which case, I'm SOL
Update: I have changed my code to include three via a tag. Same goes with the PointerLockControls, but now the problem is that I dont know how the heck to lock the pointer.
UNDERSTAND that you have to use "controls.lock()" to effectively lock your mouse to the screen (your pointer will disappear and you will be able to look around like a FPS game).
Unfortunately, you CAN NOT lock the mouse pointer from code. Instead, a user interaction WITH A DOM ELEMENT is required.
The simplest Dom element you can use is the "body", by using document.body.. see:
//add document.body to PointerLockControls constructor
let fpsControls = new PointerLockControls( camera , document.body );
//add event listener to your document.body
document.body.addEventListener( 'click', function () {
//lock mouse on screen
fpsControls.lock();
}, false );
NOTE 1: no need to call fpsControls.update() in animation function;
NOTE 2: make sure your body section is IN FRONT of the canvas and covering the entire screen, setting z-index: -1 on the canvas' CSS if necessary (or setting z-index: 10, in body's CSS ). Example:
body{
z-index: 10
margin: 0;
padding: 0;
height: 100vh;
width: 100vh;
overflow: hidden;
}
This way, you can click anywhere in the screen to experience the expected behavior. ESC will make you unlock the controller
Keep Calm and Happy Coding
but now the problem is that I don't know how the heck to lock the pointer.
You can do it like in the following example:
Create splash screen that says "Click to Play"
Register an click event listener to the respective DOM element
In the listener code call document.body.requestPointerLock() in order to asynchronously ask the browser for the pointer lock

THREE.JS Mesh position smooth animation

I have a pretty easy question for you with three.js about x position translation of an imported .obj mesh.
I'm fairly new to three.js and was wandering if someone could give me some lead on what to do or solve this problem.
So... I have this mesh on (0,-200,0) and i just wanted to move it to (50,-200,0) with a smooth translation through a button back and forth to the two positions.
objLoader = new THREE.OBJLoader();
objLoader.load('models/map_real.obj', function (obj) {
var blackMat = new THREE.MeshStandardMaterial({color:0xfaf9c9});
obj.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material = blackMat;
}
});
obj.castShadow = true;
obj.receiveShadow = true;
obj.position.set(0,-200,0)
obj.rotation.y = getDeg(-20);
scene.add(obj);
objWrap = obj;
});
I have in my main.js an init() which contains all the functions such as camera(), animate(), render() etc... and from the variable objWrap.position.x it logs the correct position.
I've tried to capture the click (as the snippet below shows) on my #test button and only increment the position by 0.5 - - i get this, is not in the animate loop so it cant keep add 0.5.
$('#test').click(function(){
if (objWrap.position.x <= 50) {
objWrap.position += 0.5}
});
So the final result that i want is a button that toggle back and forth a smooth animation that goes from objWrap.position.x = 0 to objWrap.position.x = 50
I hope to have been clear, feel free to ask if you need to know more, i'll respond in seconds... All the help is truly appreciate!
Just an example of how you can do it with Tween.js:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.setScalar(50);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.add(new THREE.GridHelper(200, 100));
var box = new THREE.Mesh(new THREE.BoxGeometry(2, 2, 2), new THREE.MeshBasicMaterial({
color: "aqua"
}));
scene.add(box);
btnMove.addEventListener("click", onClick, false);
var forth = true;
function onClick() {
new TWEEN.Tween(box.position)
.to(box.position.clone().setX(forth ? 50 : 0), 1000)
.onStart(function() {
btnMove.disabled = true;
})
.onComplete(function() {
btnMove.disabled = false;
forth = !forth;
})
.start();
}
render();
function render() {
requestAnimationFrame(render);
TWEEN.update();
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
<button id="btnMove" style="position:absolute;">Move</button>
This works with ReactJS,
import TWEEN.
import {TWEEN} from "three/examples/jsm/libs/tween.module.min";
Enable drag controller and tween animation.
const { gl, camera } = useThree();
const objects = []; // objects.push(ref.current)
useEffect(() => {
const controls = new DragControls( objects, camera, gl.domElement );
controls.addEventListener( 'dragend', (e) => {
new TWEEN.Tween(e.object.position)
.to(new Vector3(x, y, z), 1000)
.easing(TWEEN.Easing.Back.InOut)
.start();
});
})
UseFrame to show the animation.
useFrame(() => {
TWEEN.update();
});
Hope to help someone.

Eye separation using WebVR

I'm trying to make a WebVR environment using Three.js. I exported some scenes from Cinema4D and loaded them in with the Colladaloader of Three.js. Now I wanted to try this environment in my Google Cardboard but I needed to have the split screen for both my eyes, of course.
I used the npm module three-stereo-effect to achieve the VR effect, but it's overlapping when using it in a cardboard. I looked it up and saw that a lot of WebVR examples had a rounded rectangle for each eye (example of what I mean), not a straight rectangle, I thought I needed to find matrices to fix that (When looking at the examples of this repository). But then I downloaded a VR tunnel racing game and saw that they used straight rectangles and the vision was fine.
Now I'm thinking the eyeSeparation of my stereo effect is incorrect, I saw someone use the property eyeSeparation on the StereoEffect module and tried that out, but I think I shouldn't just be guessing a value...
Am I on the right track here to find a solution? Or am I looking in the total wrong direction why my 3D scene does not give a good vision when using a Cardboard?
This is the code I'm experimenting with.
import {sets} from './data/';
import * as THREE from 'three';
import threeOrbitControls from 'three-orbit-controls';
import ColladaLoader from 'three-collada-loader';
import threeStereoEffect from 'three-stereo-effect';
import {BufferLoader} from './modules/sound';
import {SpawnObject} from './modules/render';
const OrbitControls = threeOrbitControls(THREE);
const StereoEffect = threeStereoEffect(THREE);
let scene, camera, renderer;
let audioCtx, bufferLoader;
const notes = [];
let stereoEffect = null;
const init = () => {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
audioCtx = new AudioContext();
bufferLoader = new BufferLoader(audioCtx);
bufferLoader.load(sets.drums)
.then(data => spawnObject(data));
initEnvironment();
};
const spawnObject = data => {
for (let i = 0;i < 5;i ++) {
const bol = new SpawnObject(`object.dae`, audioCtx, data[0], scene, false);
notes.push(bol);
}
// console.log(notes);
};
const initEnvironment = () => {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight,
1, 10000
);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
stereoEffect = new StereoEffect(renderer);
// stereoEffect.eyeSeparation = 1;
stereoEffect.setSize(window.innerWidth, window.innerHeight);
console.log(stereoEffect);
document.querySelector(`main`).appendChild(renderer.domElement);
camera.position.set(0, 0, 2);
camera.lookAt(scene.position);
new OrbitControls(camera);
//LIGHTS
const light = new THREE.PointLight(0xFFFFFF);
light.position.set(0, 0, 9);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
light.shadow.camera.near = 10;
light.shadow.camera.far = 100;
scene.add(light);
// const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
// hemiLight.color.setHSL(0.6, 1, 0.6);
// hemiLight.groundColor.setHSL(0.095, 1, 0.75);
// hemiLight.position.set(0, 500, 0);
// scene.add(hemiLight);
//
// const dirLight = new THREE.DirectionalLight(0xffffff, 1);
// dirLight.color.setHSL(0.1, 1, 0.95);
// dirLight.position.set(- 1, 1.75, 1);
// dirLight.position.multiplyScalar(50);
// scene.add(dirLight);
// dirLight.castShadow = true;
//FLOOR
const matFloor = new THREE.MeshPhongMaterial();
const geoFloor = new THREE.BoxGeometry(2000, 1, 2000);
const mshFloor = new THREE.Mesh(geoFloor, matFloor);
matFloor.color.set(0x212E39);
mshFloor.receiveShadow = true;
mshFloor.position.set(0, - 1, 0);
scene.add(mshFloor);
//ENVIRONMENT
const loader = new ColladaLoader();
loader.load(`../assets/environment.dae`, collada => {
collada.scene.traverse(child => {
child.castShadow = true;
child.receiveShadow = true;
});
scene.add(collada.scene);
render();
});
};
const render = () => {
// stereoEffect.render(scene, camera);
// effect.render(scene, camera);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setClearColor(0xdddddd, 1);
stereoEffect.render(scene, camera);
requestAnimationFrame(render);
};
init();
From the PDF "Scalable Multi-view Stereo Camera Array for Real World Real-Time Image Capture and Three-Dimensional Displays":
2.1.1 Binocular Disparity
Binocular disparity is the positional difference between the two retinal projections of a given point in space. This positional difference results from the fact that the two eyes are laterally separated and therefore see the world from the two slightly different vantage points. For the average person the mean lateral separation also known as the interocular is 65mm. Most of the population has an eye separation within ±10mm of the average interocular.
It would seem, with a little testing with friends with a variety of face shapes you will find a happy average for the eyeSeparation value for the device and the people using it. I would then also provide some settings panel which allows a few different settings of the eyeSeparation for users to choose from if they find disparity or overlap in their stereo experience. Normally I think this would be done with a keyboard connected to the same system to dial in the stereo alignment, but you're in cardboard, so the user may need trial and error to get it right.

Categories

Resources