I want to add collision to my uni project, like in this example, however, to prevent passage through the object. Now in my project, collision work just on top. I used this. I want to create collision to object cube. How to add collision to sides? Which argument changes that? I tried change this
raycaster.ray.origin.y -= 10;
raycaster.ray.origin.x -= 0;
But as I noticed this changes the location of the upper collision. I have idea, that this one is what I need, but I don’t understand how it works…
raycaster = new THREE.Raycaster( new THREE.Vector3(), new THREE.Vector3( 0, -1, 0 ), 0, 10 );
UPDATE
Using Ivan idea, now I can stop player moving into boxes. But when I come closer to that box, I get stuck and and can’t go anywhere. Even if the camera can’t see the box. So basically velocity x ir z axis become 0, and I can’t move. How to fix that?
UPDATED CODE:
/*
My WebGL App
*/
let mainContainer = null;
let fpsContainer
let stats = null;
let camera = null;
let renderer = null;
let scene = null;
let controls = null;
let raycaster = null;
let objects = [];
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;
let canJump = false;
let prevTime = performance.now();
let velocity = new THREE.Vector3();
let direction = new THREE.Vector3();
// Global variables
function init() {
if (THREE.WEBGL.isWebGLAvailable() === false) container.appendChild(WEBGL.getWebGLErrorMessage());
fpsContainer = document.querySelector('#fps');
mainContainer = document.querySelector('#webgl-secne');
scene = new THREE.Scene();
scene.background = new THREE.Color(0xEEEEEE); // http://www.colorpicker.com/
scene.fog = new THREE.Fog(0xffffff, 0, 750);
createStats();
createCamera();
createControls();
createLights();
createMeshes();
createRenderer();
renderer.setAnimationLoop(() => {
update();
render();
animate();
});
}
// Animations
function update() {
}
function animate() {
requestAnimationFrame(animate);
if (controls.isLocked === true) {
//raycaster
raycaster.ray.origin.copy(controls.getObject().position);
const intersections = raycaster.intersectObjects(objects);
const onObject = intersections.length > 0;
//raycaster2
//raycaster2.ray.origin.copy( controls.getObject().position );
//const intersections2 = raycaster2.intersectObjects( objects );
//const saliaObject = intersections2.length > 0;
//console.log(intersections2.length);
const time = performance.now();
const delta = (time - prevTime) / 1000;
velocity.x -= velocity.x * 10.0 * delta;
velocity.z -= velocity.z * 10.0 * delta;
velocity.y -= 9.8 * 100.0 * delta; // 100.0 = mass
direction.z = Number(moveForward) - Number(moveBackward);
direction.x = Number(moveRight) - Number(moveLeft);
direction.normalize(); // this ensures consistent movements in all directions
if (moveForward || moveBackward) velocity.z -= direction.z * 400.0 * delta;
if (moveLeft || moveRight) velocity.x -= direction.x * 400.0 * delta;
if (onObject === true) {
velocity.y = Math.max(0, velocity.y);
canJump = true;
}
//if ( saliaObject === true ) {
//velocity.z = Math.max( 0, velocity.z );
//canJump = true;
//}
//UPDATE
let collisionRange = 10; //if the mesh gets too close, the camera clips though the object...
let tempVelocity = velocity.clone().multiplyScalar(delta) //get the delta velocity
let nextPosition = controls.getObject().position.clone().add(tempVelocity);
let tooClose = false;
let playerPosition = controls.getObject().position;
for (let i = 0; i < objects.length; i++) {
let object = objects[i];
let objectDirection = object.position.clone().sub(playerPosition).normalize();
raycaster.set(nextPosition, objectDirection) //set the position and direction
let directionIntersects = raycaster.intersectObject(object);
if (directionIntersects.length > 0 && directionIntersects[0].distance < collisionRange) {
//too close, stop player from moving in that direction...
tooClose = true;
break;
}
}
if (tooClose == false) {
controls.moveRight(-velocity.x * delta);
controls.moveForward(-velocity.z * delta);
controls.getObject().position.y += (velocity.y * delta); // new behavior
}
if (controls.getObject().position.y < 10) {
velocity.y = 0;
controls.getObject().position.y = 10;
canJump = true;
}
prevTime = time;
}
renderer.render(scene, camera);
}
// Statically rendered content
function render() {
stats.begin();
renderer.render(scene, camera);
stats.end();
}
// FPS counter
function createStats() {
stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
fpsContainer.appendChild(stats.dom);
}
// Camera object
function createCamera() {
const fov = 75;
const aspect = mainContainer.clientWidth / mainContainer.clientHeight;
const near = 0.1;
const far = 500; // meters
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 0);
}
// Interactive controls
function createControls() {
controls = new THREE.PointerLockControls(camera, document.body);
var blocker = document.getElementById('blocker');
var instructions = document.getElementById('instructions');
instructions.addEventListener('click', function() {
controls.lock();
}, false);
controls.addEventListener('lock', function() {
instructions.style.display = 'none';
blocker.style.display = 'none';
});
controls.addEventListener('unlock', function() {
blocker.style.display = 'block';
instructions.style.display = '';
});
scene.add(controls.getObject());
var onKeyDown = function(event) {
switch (event.keyCode) {
case 38: // up
case 87: // w
moveForward = true;
break;
case 37: // left
case 65: // a
moveLeft = true;
break;
case 40: // down
case 83: // s
moveBackward = true;
break;
case 39: // right
case 68: // d
moveRight = true;
break;
case 32: // space
if (canJump === true) velocity.y += 350;
canJump = false;
break;
}
};
var onKeyUp = function(event) {
switch (event.keyCode) {
case 38: // up
case 87: // w
moveForward = false;
break;
case 37: // left
case 65: // a
moveLeft = false;
break;
case 40: // down
case 83: // s
moveBackward = false;
break;
case 39: // right
case 68: // d
moveRight = false;
break;
}
};
document.addEventListener('keydown', onKeyDown, false);
document.addEventListener('keyup', onKeyUp, false);
raycaster = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3(0, -1, 0), 0, 5);
//raycaster2 = new THREE.Raycaster( new THREE.Vector3(), new THREE.Vector3( 0, 0 , -1 ),0,2);
//raycaster2 = new THREE.Raycaster( new THREE.Vector2(), camera );
}
// Light objects
function createLights() {
}
// Meshes and other visible objects
function createMeshes() {
const geo = new THREE.PlaneBufferGeometry(1000, 1000);
const mat = new THREE.MeshBasicMaterial({
color: 0x98FB98
});
const plane = new THREE.Mesh(geo, mat);
plane.rotateX(-Math.PI / 2);
plane.receiveShadow = true;
scene.add(plane);
const geometry = new THREE.BoxBufferGeometry(20, 20, 20);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide
});
const cube = new THREE.Mesh(geometry, material);
cube.position.x = 15;
cube.position.z = 10;
cube.position.y = 15;
cube.receiveShadow = true;
cube.castShadow = true;
scene.add(cube);
objects.push(cube);
}
// Renderer object and features
function createRenderer() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(mainContainer.clientWidth, mainContainer.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
//renderer.setClearColor(0xEEEEEE);
mainContainer.appendChild(renderer.domElement);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', onWindowResize, false);
init();
body {
background-color: #fff;
margin: 0px;
overflow: hidden;
}
#info {
color: #808080;
font-family: Monospace;
font-size: 1rem;
text-align: center;
position: absolute;
top: 0px;
width: 100%;
padding: 5px;
z-index: 1;
}
#webgl-secne {
position: absolute;
width: 100%;
height: 100%;
}
/* Pointerlock */
#instructions {
position: absolute;
font-family: arial;
width: 100%;
height: 100%;
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: horizontal;
-moz-box-orient: horizontal;
box-orient: horizontal;
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
-webkit-box-align: center;
-moz-box-align: center;
box-align: center;
color: #ffffff;
text-align: center;
cursor: pointer;
z-index: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Computer Graphics</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<!-- Libraries -->
<script src="https://github.com/mrdoob/three.js/blob/e9f31ad154d2cc314f37b5a8da4bdddd4f1bde7e/build/three.js"></script>
<!-- <script src="lib/three.min.js"></script> -->
<script src="https://github.com/mrdoob/three.js/blob/e9f31ad154d2cc314f37b5a8da4bdddd4f1bde7e/examples/js/WebGL.js"></script>
<script src="https://github.com/mrdoob/three.js/blob/e9f31ad154d2cc314f37b5a8da4bdddd4f1bde7e/examples/js/libs/stats.min.js"></script>
<!-- <script src="lib/controls/OrbitControls.js"></script> -->
<!-- <script src="lib/controls/TrackballControls.js"></script>
<script src="lib/controls/FlyControls.js"></script>
<script src="lib/controls/FirstPersonControls.js"></script>-->
<script src="https://github.com/mrdoob/three.js/blob/e9f31ad154d2cc314f37b5a8da4bdddd4f1bde7e/examples/js/controls/PointerLockControls.js"></script>
<!-- <script src="lib/water/Reflector.js"></script>
<script src="lib/water/Refractor.js"></script>
<script src="lib/water/Water2.js"></script>
<script src="lib/dat.gui.min.js"></script>
<script src="lib/loaders/OBJLoader.js"></script>
<script src="lib/loaders/MTLLoader.js"></script>
<script src="lib/loaders/STLLoader.js"></script>
<script src="lib/loaders/GLTFLoader.js"></script>
<script src="lib/SceneUtils.js"></script> -->
<script src="app.js" defer></script>
<link href="main.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="info">Computer Graphics</div>
<!-- Pointerlock -->
<div id="blocker">
<div id="instructions"><span style="font-size:40px">Click to play</span><br /> (W, A, S, D = Move, SPACE = Jump, MOUSE = Look around)
</div>
</div>
<div id="webgl-secne">
<!-- <canvas width="800" height="600"></canvas> -->
</div>
<div id="fps"></div>
</body>
</html>