How to shoot bullets - javascript

I'm trying to create a browser VR game, I have set up the world, the VR controllers, I have created the fire event but each time I pull the trigger, the bullet that was fired before disappears. How do I make the bullets "stay" in the scene and keep moving, while I fire new ones?
I'm following this example https://threejs.org/examples/#webvr_ballshooter but it's not exactly what I need
var geometry_bullet = new THREE.IcosahedronBufferGeometry( radius, 2 );
var bullet1 = new THREE.Mesh( geometry_bullet, new THREE.MeshLambertMaterial( { color: 0x2661b9 } ) );
bullet1.userData.velocity = new THREE.Vector3();
bullet1.userData.velocity.x = 10;
bullet1.userData.velocity.y = 10;
bullet1.userData.velocity.z = 10;
var bullet2 = new THREE.Mesh( geometry_bullet, new THREE.MeshLambertMaterial( { color: 0xee2f2f } ) );
bullet2.userData.velocity = new THREE.Vector3();
bullet2.userData.velocity.x = 1;
bullet2.userData.velocity.y = 1;
bullet2.userData.velocity.z = 1;
...
function handleController( controller ) {
if ( controller1.userData.isSelecting ) {
bullet1.position.set(controller1.position.x , controller1.position.y + 0.018 , controller1.position.z );
bullet1.userData.velocity.x = 0;
bullet1.userData.velocity.y = 10;
bullet1.userData.velocity.z = 10;
bullet1.userData.velocity.applyQuaternion( controller1.quaternion );
}
if ( controller2.userData.isSelecting ) {
bullet2.position.set(controller2.position.x , controller2.position.y + 0.018 , controller2.position.z );
bullet2.userData.velocity.x = 0;
bullet2.userData.velocity.y = 10;
bullet2.userData.velocity.z = 10;
bullet2.userData.velocity.applyQuaternion( controller2.quaternion );
}
} ...
function render() { ...
handleController( controller1 );
handleController( controller2 ); ...
bullet1.position.x -= bullet1.userData.velocity.x * delta;
bullet1.position.y -= bullet1.userData.velocity.y * delta;
bullet1.position.z -= bullet1.userData.velocity.z * delta;
scene.add(bullet1);
bullet2.position.x -= bullet2.userData.velocity.x * delta;
bullet2.position.y -= bullet2.userData.velocity.y * delta;
bullet2.position.z -= bullet2.userData.velocity.z * delta;
scene.add(bullet2);
...
renderer.render( scene, camera );
}

Related

How to rotate gltf model while scrolling the page

I'm trying to make the gltf model rotate smoothly while scrolling.
I managed to create a function that converts pageYOffset from pixels to radians
let scroollPositionRad = 0;
window.addEventListener("scroll", onWindowScroll );
function onWindowScroll(){
let scroollPosition = Math.round(pageYOffset);
let limit = document.body.offsetHeight - window.innerHeight;
scroollPositionRad = (scroollPosition * 2* Math.PI) / limit;
}
and a function that rotates and centers the model
function centerObj(rad){
obj.rotation.y = rad;
let box = new THREE.Box3().setFromObject( obj );
let center = box.getCenter( new THREE.Vector3() );
obj.position.x += ( obj.position.x - center.x );
obj.position.y += ( obj.position.y - center.y );
obj.position.z += ( obj.position.z - center.z );
}
if i try to call centerObj(scrollPositionRad) as animation, gltf model disappears
renderer.setAnimationLoop(_ => {
centerObj(scroollPositionRad);
renderer.render(scene, camera);
})
model loading code after scene creation
let loader = new THREE.GLTFLoader();
let obj = null;
loader.load('https://raw.githubusercontent.com/aaadraniki/projects/web-pages/assets/models/fender_br/scene.gltf', function(gltf) {
obj = gltf.scene;
scene.add(obj);
function centerObj(rad){
obj.rotation.y = rad;
let box = new THREE.Box3().setFromObject( obj );
let center = box.getCenter( new THREE.Vector3() );
obj.position.x += ( obj.position.x - center.x );
obj.position.y += ( obj.position.y - center.y );
obj.position.z += ( obj.position.z - center.z );
}
centerObj(0.8);
let scroollPositionRad = 0;
window.addEventListener("scroll", onWindowScroll );
function onWindowScroll(){
let scroollPosition = Math.round(pageYOffset);
let limit = document.body.offsetHeight - window.innerHeight;
scroollPositionRad = (scroollPosition * 2* Math.PI) / limit;
}
renderer.setAnimationLoop(_ => {
centerObj(scroollPositionRad);
renderer.render(scene, camera);
})
});
window.onscroll = (e) => {
scene.rotation.y = this.scrollY / 700.0;
}

Camera position and device controls using the waves example

I have a website where i need to use threejs. I used the waves example in a landing page and it is working well on desktop/laptop.
However, I need to be able to move the waves (same behaviour as mouse in desktop) but with the device gyroscope/accelerometer and it is working using the devicecontrols that i found in another example. The problem is that it is my first time using three and working with 3d and i am lost. The dots are really small they only seem to move in a very small line and i dont know how or where the camera should look.
For example,
Desired behaviour (https://www.dropbox.com/s/d11srwqww8jtuda/PhoneWanted.png?dl=0)
Current on desktop (https://www.dropbox.com/s/x3rpcnovrfr2v1x/Desktop.png?dl=0)
Current on mobile (https://www.dropbox.com/s/c9c1mojgi5zt55y/IMG_2385.jpeg?dl=0)
On mobile should look the same as on desktop and move the waves but only horizontally...
Is this possible?
Mobile Script
<script>
if (screen && screen.width < 900) {
//alert("Mobile");
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var SEPARATION = 100, AMOUNTX = 50, AMOUNTY = 50;
var container;
var camera, scene, renderer, controls;
var particles, count = 0;
var mouseX = 0, mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
controls = new THREE.DeviceOrientationControls( camera );
camera.position.z = 1000;
scene = new THREE.Scene();
//
var numParticles = AMOUNTX * AMOUNTY;
var positions = new Float32Array( numParticles * 3 );
var scales = new Float32Array( numParticles );
var i = 0, j = 0;
for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
positions[ i ] = ix * SEPARATION - ( ( AMOUNTX * SEPARATION ) / 2 ); // x
positions[ i + 1 ] = 0; // y
positions[ i + 2 ] = iy * SEPARATION - ( ( AMOUNTY * SEPARATION ) / 2 ); // z
scales[ j ] = 1;
i += 3;
j ++;
}
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'scale', new THREE.BufferAttribute( scales, 1 ) );
var material = new THREE.ShaderMaterial( {
uniforms: {
color: { value: new THREE.Color( 0xffffff ) },
},
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent
} );
particles = new THREE.Points( geometry, material );
scene.add( particles );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function animate() {
window.requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
}
</script>
Solution
console.log("Desktop");
if (WEBGL.isWebGLAvailable() === false) {
document.body.appendChild(WEBGL.getWebGLErrorMessage());
}
var SEPARATION = 100,
AMOUNTX = 50,
AMOUNTY = 50;
var container;
var camera, scene, renderer, controls;
var particles, count = 0;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
// var isMobile = isOSMobile();
var isMobile = true;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(75, window.innerWidth /
window.innerHeight, 1, 10000);
if (isMobile) {
controls = new THREE.DeviceOrientationControls(camera);
}
camera.position.z = 1000;
scene = new THREE.Scene();
//
var numParticles = AMOUNTX * AMOUNTY;
var positions = new Float32Array(numParticles * 3);
var scales = new Float32Array(numParticles);
var i = 0,
j = 0;
for (var ix = 0; ix < AMOUNTX; ix++) {
for (var iy = 0; iy < AMOUNTY; iy++) {
positions[i] = ix * SEPARATION - ((AMOUNTX *
SEPARATION) / 2); // x
positions[i + 1] = 0; // y
positions[i + 2] = iy * SEPARATION - ((AMOUNTY *
SEPARATION) / 2); // z
scales[j] = 1;
i += 3;
j++;
}
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(
positions, 3));
geometry.addAttribute('scale', new THREE.BufferAttribute(scales,
1));
var material = new THREE.ShaderMaterial({
uniforms: {
color: {
value: new THREE.Color(isMobile ? 0xffffff : 0x8D8D8F)
},
},
vertexShader: document.getElementById(
'vertexshader').textContent,
fragmentShader: document.getElementById(
'fragmentshader').textContent
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener('mousemove', onDocumentMouseMove,
false);
window.addEventListener('resize', onWindowResize, false);
if (isMobile) {
window.addEventListener("deviceorientation", handleOrientation, true);
}
}
function handleOrientation(e) {
var absolute = e.absolute;
var alpha = e.alpha;// x -90 ... 90
var beta = e.beta;// y 180 ... 0
var gamma = e.gamma;// x -90 ... 90
mouseX = -5 * windowHalfX * (gamma / 90);
//mouseY = -windowHalfY * ((beta - 90) / 90);
// console.log(mouseX.toFixed(2), ' x ', mouseY.toFixed(2));
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
//
function animate() {
requestAnimationFrame(animate);
render();
if (isMobile) {
controls.update();
}
}
function render() {
camera.position.x += (mouseX - camera.position.x) * .05;
if(isMobile) {
camera.position.y = 550;
} else {
camera.position.y += (-mouseY - camera.position.y) * .05;
}
camera.lookAt(scene.position);
var positions = particles.geometry.attributes.position.array;
var scales = particles.geometry.attributes.scale.array;
var i = 0,
j = 0;
for (var ix = 0; ix < AMOUNTX; ix++) {
for (var iy = 0; iy < AMOUNTY; iy++) {
positions[i + 1] = (Math.sin((ix + count) * 0.3) * 50) +
(Math.sin((iy + count) * 0.5) * 50);
scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 8 +
(Math.sin((iy + count) * 0.5) + 1) * 8;
i += 3;
j++;
}
}
particles.geometry.attributes.position.needsUpdate = true;
particles.geometry.attributes.scale.needsUpdate = true;
renderer.render(scene, camera);
count += 0.1;
}
function isOSMobile() {
var userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/android/i.test(userAgent)) {
return true;
}
if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
return true;
}
return false;
}
Thank you!
Fixed it. Code works, Y axis movement is disabled.
console.log("Desktop");
if (WEBGL.isWebGLAvailable() === false) {
document.body.appendChild(WEBGL.getWebGLErrorMessage());
}
var SEPARATION = 100,
AMOUNTX = 50,
AMOUNTY = 50;
var container;
var camera, scene, renderer, controls;
var particles, count = 0;
var mouseX = 0,
mouseY = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
// var isMobile = isOSMobile();
var isMobile = true;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(75, window.innerWidth /
window.innerHeight, 1, 10000);
if (isMobile) {
controls = new THREE.DeviceOrientationControls(camera);
}
camera.position.z = 1000;
scene = new THREE.Scene();
//
var numParticles = AMOUNTX * AMOUNTY;
var positions = new Float32Array(numParticles * 3);
var scales = new Float32Array(numParticles);
var i = 0,
j = 0;
for (var ix = 0; ix < AMOUNTX; ix++) {
for (var iy = 0; iy < AMOUNTY; iy++) {
positions[i] = ix * SEPARATION - ((AMOUNTX *
SEPARATION) / 2); // x
positions[i + 1] = 0; // y
positions[i + 2] = iy * SEPARATION - ((AMOUNTY *
SEPARATION) / 2); // z
scales[j] = 1;
i += 3;
j++;
}
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(
positions, 3));
geometry.addAttribute('scale', new THREE.BufferAttribute(scales,
1));
var material = new THREE.ShaderMaterial({
uniforms: {
color: {
value: new THREE.Color(isMobile ? 0xffffff : 0x8D8D8F)
},
},
vertexShader: document.getElementById(
'vertexshader').textContent,
fragmentShader: document.getElementById(
'fragmentshader').textContent
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
document.addEventListener('mousemove', onDocumentMouseMove,
false);
window.addEventListener('resize', onWindowResize, false);
if (isMobile) {
window.addEventListener("deviceorientation", handleOrientation, true);
}
}
function handleOrientation(e) {
var absolute = e.absolute;
var alpha = e.alpha;// x -90 ... 90
var beta = e.beta;// y 180 ... 0
var gamma = e.gamma;// x -90 ... 90
mouseX = -5 * windowHalfX * (gamma / 90);
//mouseY = -windowHalfY * ((beta - 90) / 90);
// console.log(mouseX.toFixed(2), ' x ', mouseY.toFixed(2));
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
}
//
function animate() {
requestAnimationFrame(animate);
render();
if (isMobile) {
controls.update();
}
}
function render() {
camera.position.x += (mouseX - camera.position.x) * .05;
if(isMobile) {
camera.position.y = 550;
} else {
camera.position.y += (-mouseY - camera.position.y) * .05;
}
camera.lookAt(scene.position);
var positions = particles.geometry.attributes.position.array;
var scales = particles.geometry.attributes.scale.array;
var i = 0,
j = 0;
for (var ix = 0; ix < AMOUNTX; ix++) {
for (var iy = 0; iy < AMOUNTY; iy++) {
positions[i + 1] = (Math.sin((ix + count) * 0.3) * 50) +
(Math.sin((iy + count) * 0.5) * 50);
scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 8 +
(Math.sin((iy + count) * 0.5) + 1) * 8;
i += 3;
j++;
}
}
particles.geometry.attributes.position.needsUpdate = true;
particles.geometry.attributes.scale.needsUpdate = true;
renderer.render(scene, camera);
count += 0.1;
}
function isOSMobile() {
var userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/android/i.test(userAgent)) {
return true;
}
if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) {
return true;
}
return false;
}

Bullet collision detection in three.js

For my first years of studies, i have a Three.js project. I have to create a little fps. I have followed a tutorial, everything is fine except the bullet collision detection. I try some stuff i have found on internet, follow some tutorial trying to understand as much as i can, because i don't want to just copy and paste stuff.
But i have to confess i am a bit lost. Here is the code i have develop. What i want to do is to detect when a bullet touch another object. Like for example make disappear a box when a bullet touch it.
The bullet are defined like this :
var bullet = new THREE.Mesh(
new THREE.SphereGeometry(0.05,8,8),
new THREE.MeshBasicMaterial({color:0xffffff})
Here is also my code
var scene, camera, renderer, mesh, clock;
var meshFloor, ambientLight, light;
var crate, crateTexture, crateNormalMap, crateBumpMap;
var keyboard = {};
var player = { height:1.8, speed:0.2, turnSpeed:Math.PI*0.02, canShoot:0 };
var USE_WIREFRAME = false;
var loadingScreen = {
scene: new THREE.Scene(),
camera: new THREE.PerspectiveCamera(90, 1280/720, 0.1, 100),
box: new THREE.Mesh(
new THREE.BoxGeometry(0.5,0.5,0.5),
new THREE.MeshBasicMaterial({ color:0x4444ff })
)
};
var loadingManager = null;
var RESOURCES_LOADED = false;
// Models index
var models = {
tent: {
obj:"models/Tent_Poles_01.obj",
mtl:"models/Tent_Poles_01.mtl",
mesh: null
},
campfire: {
obj:"models/Campfire_01.obj",
mtl:"models/Campfire_01.mtl",
mesh: null
},
pirateship: {
obj:"models/Pirateship.obj",
mtl:"models/Pirateship.mtl",
mesh: null
},
uzi: {
obj:"models/uziGold.obj",
mtl:"models/uziGold.mtl",
mesh: null,
castShadow:false
}
};
// Meshes index
var meshes = {};
// Bullets array
var bullets = [];
function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(90, 1280/720, 0.1, 1000);
clock = new THREE.Clock();
loadingScreen.box.position.set(0,0,5);
loadingScreen.camera.lookAt(loadingScreen.box.position);
loadingScreen.scene.add(loadingScreen.box);
loadingManager = new THREE.LoadingManager();
loadingManager.onProgress = function(item, loaded, total){
console.log(item, loaded, total);
};
loadingManager.onLoad = function(){
console.log("loaded all resources");
RESOURCES_LOADED = true;
onResourcesLoaded();
};
mesh = new THREE.Mesh(
new THREE.BoxGeometry(1,1,1),
new THREE.MeshPhongMaterial({color:0xff4444, wireframe:USE_WIREFRAME})
);
mesh.position.y += 1;
mesh.receiveShadow = true;
mesh.castShadow = true;
//scene.add(mesh);
meshFloor = new THREE.Mesh(
new THREE.PlaneGeometry(20,20, 10,10),
new THREE.MeshPhongMaterial({color:0xffffff, wireframe:USE_WIREFRAME})
);
meshFloor.rotation.x -= Math.PI / 2;
meshFloor.receiveShadow = true;
scene.add(meshFloor);
ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambientLight);
light = new THREE.PointLight(0xffffff, 0.8, 18);
light.position.set(-3,6,-3);
light.castShadow = true;
light.shadow.camera.near = 0.1;
light.shadow.camera.far = 25;
scene.add(light);
var textureLoader = new THREE.TextureLoader(loadingManager);
crateTexture = textureLoader.load("crate0/crate0_diffuse.jpg");
crateBumpMap = textureLoader.load("crate0/crate0_bump.jpg");
crateNormalMap = textureLoader.load("crate0/crate0_normal.jpg");
crate = new THREE.Mesh(
new THREE.BoxGeometry(3,3,3),
new THREE.MeshPhongMaterial({
color:0xffffff,
map:crateTexture,
bumpMap:crateBumpMap,
normalMap:crateNormalMap
})
);
crate.position.set(2.5, 3/2, 2.5);
crate.receiveShadow = true;
crate.castShadow = true;
// Load models
// REMEMBER: Loading in Javascript is asynchronous, so you need
// to wrap the code in a function and pass it the index. If you
// don't, then the index '_key' can change while the model is being
// downloaded, and so the wrong model will be matched with the wrong
// index key.
for( var _key in models ){
(function(key){
var mtlLoader = new THREE.MTLLoader(loadingManager);
mtlLoader.load(models[key].mtl, function(materials){
materials.preload();
var objLoader = new THREE.OBJLoader(loadingManager);
objLoader.setMaterials(materials);
objLoader.load(models[key].obj, function(mesh){
mesh.traverse(function(node){
if( node instanceof THREE.Mesh ){
if('castShadow' in models[key])
node.castShadow = models[key].castShadow;
else
node.castShadow = true;
if('receiveShadow' in models[key])
node.receiveShadow = models[key].receiveShadow;
else
node.receiveShadow = true;
}
});
models[key].mesh = mesh;
});
});
})(_key);
}
camera.position.set(0, player.height, -5);
camera.lookAt(new THREE.Vector3(0,player.height,0));
renderer = new THREE.WebGLRenderer();
renderer.setSize(1280, 720);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.BasicShadowMap;
document.body.appendChild(renderer.domElement);
animate();
}
// Runs when all resources are loaded
function onResourcesLoaded(){
// Clone models into meshes.
meshes["tent1"] = models.tent.mesh.clone();
meshes["tent2"] = models.tent.mesh.clone();
meshes["campfire1"] = models.campfire.mesh.clone();
meshes["campfire2"] = models.campfire.mesh.clone();
// Reposition individual meshes, then add meshes to scene
meshes["tent1"].position.set(-5, 0, 4);
scene.add(meshes["tent1"]);
meshes["tent2"].position.set(-8, 0, 4);
scene.add(meshes["tent2"]);
meshes["campfire1"].position.set(-5, 0, 1);
meshes["campfire2"].position.set(-8, 0, 1);
scene.add(meshes["campfire1"]);
scene.add(meshes["campfire2"]);
// player weapon
meshes["playerweapon"] = models.uzi.mesh.clone();
meshes["playerweapon"].position.set(0,2,0);
meshes["playerweapon"].scale.set(10,10,10);
scene.add(meshes["playerweapon"]);
}
function animate(){
// Play the loading screen until resources are loaded.
if( RESOURCES_LOADED == false ){
requestAnimationFrame(animate);
loadingScreen.box.position.x -= 0.05;
if( loadingScreen.box.position.x < -10 ) loadingScreen.box.position.x = 10;
loadingScreen.box.position.y = Math.sin(loadingScreen.box.position.x);
renderer.render(loadingScreen.scene, loadingScreen.camera);
return;
}
requestAnimationFrame(animate);
var time = Date.now() * 0.0005;
var delta = clock.getDelta();
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
crate.rotation.y += 0.01;
// Uncomment for absurdity!
// meshes["pirateship"].rotation.z += 0.01;
// go through bullets array and update position
// remove bullets when appropriate
for(var index=0; index<bullets.length; index+=1){
if( bullets[index] === undefined ) continue;
if( bullets[index].alive == false ){
bullets.splice(index,1);
continue;
}
bullets[index].position.add(bullets[index].velocity);
}
if(keyboard[38]){ // UP button
camera.position.x -= Math.sin(camera.rotation.y) * player.speed;
camera.position.z -= -Math.cos(camera.rotation.y) * player.speed;
}
if(keyboard[40]){ // DOWN button
camera.position.x += Math.sin(camera.rotation.y) * player.speed;
camera.position.z += -Math.cos(camera.rotation.y) * player.speed;
}
if(keyboard[65]){ // A key
camera.position.x += Math.sin(camera.rotation.y + Math.PI/2) * player.speed;
camera.position.z += -Math.cos(camera.rotation.y + Math.PI/2) * player.speed;
}
if(keyboard[68]){ // D key
camera.position.x += Math.sin(camera.rotation.y - Math.PI/2) * player.speed;
camera.position.z += -Math.cos(camera.rotation.y - Math.PI/2) * player.speed;
}
if(keyboard[37]){ // left arrow key
camera.rotation.y -= player.turnSpeed;
}
if(keyboard[39]){ // right arrow key
camera.rotation.y += player.turnSpeed;
}
// shoot a bullet
if(keyboard[32] && player.canShoot <= 0){ // spacebar key
// creates a bullet as a Mesh object
var bullet = new THREE.Mesh(
new THREE.SphereGeometry(0.05,8,8),
new THREE.MeshBasicMaterial({color:0xffffff})
);
// this is silly.
// var bullet = models.pirateship.mesh.clone();
// position the bullet to come from the player's weapon
bullet.position.set(
meshes["playerweapon"].position.x + 0.0 ,
meshes["playerweapon"].position.y + 0.10,
meshes["playerweapon"].position.z + 0.1
);
// set the velocity of the bullet
bullet.velocity = new THREE.Vector3(
-Math.sin(camera.rotation.y),
0,
Math.cos(camera.rotation.y)
);
// after 1000ms, set alive to false and remove from scene
// setting alive to false flags our update code to remove
// the bullet from the bullets array
bullet.alive = true;
setTimeout(function(){
bullet.alive = false;
scene.remove(bullet);
}, 1000);
// add to scene, array, and set the delay to 10 frames
bullets.push(bullet);
scene.add(bullet);
player.canShoot = 10;
}
if(player.canShoot > 0) player.canShoot -= 1;
// position the gun in front of the camera
meshes["playerweapon"].position.set(
camera.position.x - Math.sin(camera.rotation.y + Math.PI/6) * 0.75,
camera.position.y - 0.5 + Math.sin(time*4 + camera.position.x + camera.position.z)*0.01,
camera.position.z + Math.cos(camera.rotation.y + Math.PI/6) * 0.75
);
meshes["playerweapon"].rotation.set(
camera.rotation.x,
camera.rotation.y - Math.PI,
camera.rotation.z
);
renderer.render(scene, camera);
}
function keyDown(event){
keyboard[event.keyCode] = true;
}
function keyUp(event){
keyboard[event.keyCode] = false;
}
window.addEventListener('keydown', keyDown);
window.addEventListener('keyup', keyUp);
window.onload = init;
Here is a fiddle with the code i have already developed:
https://jsfiddle.net/Mxfrd/bany0afg/
If someone have an idea how can i do that, it will be super ! i am very lost on that point.
Thanks

THREE.JS: objects that should not appear as visible appear as visible

I'm in the process of tinkering together a solar system simulator and it is all going well with the exception of one part: when a moon or a planet goes behind its parent body, you can still see it!
There are no transparent objects in the scene, and I have not made any modifications to the order in which objects are rendered, so I'm at a loss as to why objects appear when they are behind another object.
I'm using three.js r71 (problem still appears in r84, though).
To see where it goes wrong: check out http:mrhuffman.net/projects/gp and pick the Martian system; you will see how Phobos or Deimos are still visible even though they are behind Mars.
Here's the code for the scene. It's not as tidy as it could be as I just started working on it, so if you need clarifications or have questions, shoot!
import THREE from '../vendor/three';
import OrbitControls from '../vendor/OrbitControlsES6';
import ColladaLoader from '../vendor/ColladaLoaderES6';
import nBodyProblem from '../algorithms/nBodyProblem';
const scene = ( function () {
//Full screen action
let w = window.innerWidth;
let h = window.innerHeight;
let requestAnimationFrameId = null;
let scene = null;
let camera = null;
let controls = null;
let renderer = null;
let system = null;
let dae = null;
let cameraControlsWrapper = null;
let orbitButton = null;
let view3DButton = null;
let pathCanvas = document.createElement( 'canvas' );
pathCanvas.style.display = 'none';
pathCanvas.style.backgroundImage = 'url(misc/starfield.jpg)';
let ctxPath = pathCanvas.getContext( '2d' );
let massCanvas = document.createElement( 'canvas' );
massCanvas.style.display = 'none';
massCanvas.style.position = 'absolute';
massCanvas.style.zIndex = 2;
massCanvas.style.top = 0;
massCanvas.style.bottom = 0;
let ctxMass = massCanvas.getContext( '2d' );
pathCanvas.width = w;
pathCanvas.height = h;
massCanvas.width = w;
massCanvas.height = h;
ctxPath.translate( w / 2, h / 2 );
ctxMass.translate( w / 2, h / 2 );
function showOrbits() {
orbitButton.style.display = 'none';
cameraControlsWrapper.style.display = 'none';
pathCanvas.style.display = 'block';
massCanvas.style.display = 'block';
view3DButton.style.display = 'block';
}
function hideOrbits() {
view3DButton.style.display = 'none';
pathCanvas.style.display = 'none';
massCanvas.style.display = 'none';
orbitButton.style.display = 'block';
cameraControlsWrapper.style.display = 'block';
}
function createBody( radius, name, type ) {
let segments = type !== 'asteroid' ? 32 : 6;
let geometry = new THREE.SphereGeometry( radius, segments, segments );
let map;
let bumpMap;
switch( type ) {
case 'asteroid':
map = THREE.ImageUtils.loadTexture('textures/Phobos.jpg');
bumpMap = THREE.ImageUtils.loadTexture('textures/PhobosBump.jpg');
break;
case 'custom':
map = THREE.ImageUtils.loadTexture('textures/Acid.jpg');
break;
case 'star':
map = THREE.ImageUtils.loadTexture('textures/Sun.jpg');
break;
case 'spacecraft':
scene.add( dae );
return dae;
default:
map = THREE.ImageUtils.loadTexture('textures/' + name + '.jpg');
bumpMap = THREE.ImageUtils.loadTexture('textures/Phobos.jpg');
}
let material = new THREE.MeshPhongMaterial( { map: map, bumpMap: bumpMap, bumpScale: 0.02 } );
let mesh = new THREE.Mesh( geometry, material );
mesh.rotation.x = 1.5;
scene.add( mesh );
return mesh;
}
function sceneSetup( callback, scenario, container, camPos, camFocus, viewOrbits, view3D, cameraControls ) {
if ( scenario.model === undefined ) {
callback( scenario, container, camPos, camFocus, viewOrbits, view3D, cameraControls );
return;
}
let loader = new ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( './models/' + scenario.model + '/' + scenario.model + '.dae', ( collada ) => {
dae = collada.scene;
dae.scale.setScalar( 1 / 800 );
callback( scenario, container, camPos, camFocus, viewOrbits, view3D, cameraControls );
});
}
function initSimulation( scenario, container, camPos, camFocus, viewOrbits, view3D, cameraControls ) {
cameraControlsWrapper = cameraControls;
orbitButton = viewOrbits;
orbitButton.addEventListener( 'click', showOrbits, false );
view3DButton = view3D;
view3DButton.addEventListener( 'click', hideOrbits, false );
hideOrbits();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45, w / h, 0.000001, 1500 );
//Prevent rolling of the camera when you view a body from another
camera.up.set( 0, 0, 1 );
camera.position.set( 0, 90, 150 );
var light = new THREE.AmbientLight(0x404040);
scene.add(light);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(w, h);
renderer.setClearColor(0x000000);
container.appendChild( pathCanvas );
container.appendChild( massCanvas );
container.appendChild( renderer.domElement );
controls = new OrbitControls( camera, renderer.domElement );
//Create a new n-body problem from the selected scenario
system = new nBodyProblem( {
g: scenario.g,
law: scenario.law,
dt: scenario.dt,
masses: scenario.masses
});
//Create visual manifestations of the planets, asteroids and star(s)
for (let i = 0; i < system.masses.length; i++) {
let mass = system.masses[ i ];
mass.manifestation = createBody( mass.radius, mass.name, mass.type );
}
const render = function () {
requestAnimationFrameId = requestAnimationFrame( render );
//Update state vectors system.updatePositionVectors().updateVelocityVectors().updateBarycenter().calculateElapsedTime();
//Check if a rocket should be fired and if so check if it should be fired in this iteration; should that be the case, fire!
if ( scenario.rocketBurn === true ) {
if ( system.elapsedTime === scenario.rocketBurnTime ) {
for ( let i = 0; i < system.masses.length; i++ ) {
if ( system.masses[ i ].type === 'spacecraft' ) {
system.masses[ i ].vx = scenario.afterRocketBurnVelocity.vx;
system.masses[ i ].vy = scenario.afterRocketBurnVelocity.vy;
system.masses[ i ].vz = scenario.afterRocketBurnVelocity.vz;
}
}
}
}
ctxMass.clearRect( -0.5 * w, -0.5 * h, w, h );
//Put all the masses in their new positions and set camera position and focus
for (let i = 0; i < system.masses.length; i++) {
let mass = system.masses[ i ];
let x = mass.x * scenario.scale;
let y = mass.y * scenario.scale;
let z = mass.z * scenario.scale;
mass.manifestation.position.set( x, y, z );
let camR = camPos.value;
let name = mass.name;
if ( camR === name ) {
camera.position.set( x, y, z + ( mass.radius * 1.2 ) );
controls.enabled = false;
} else if ( camR === 'free' ) {
controls.enabled = true;
}
if ( camFocus.value === name ) {
camera.lookAt( new THREE.Vector3( x, y, z ) );
//If the camera mode is free, the user can pan, orbit and have fun
if ( camPos === 'free' ) controls.target = new THREE.Vector3( x, y, z );
}
ctxPath.fillStyle = mass.color;
ctxPath.fillRect( x, y, 1, 1 );
ctxMass.beginPath();
ctxMass.fillStyle = mass.color;
ctxMass.arc( x, y, 6, 0, 2 * Math.PI );
ctxMass.fill();
ctxMass.font = "14px Arial";
ctxMass.fillText( mass.name, x + 8, y );
}
//Put the barycenter of the system in its new position
let barycenterX = system.x * scenario.scale;
let barycenterY = system.y * scenario.scale;
ctxMass.strokeStyle = 'limegreen';
ctxMass.lineWidth = 2;
ctxMass.beginPath();
ctxMass.moveTo( barycenterX - 20, barycenterY );
ctxMass.lineTo( barycenterX + 20, barycenterY );
ctxMass.moveTo( barycenterX, barycenterY - 20 );
ctxMass.lineTo( barycenterX, barycenterY + 20 );
ctxMass.stroke();
ctxMass.fillStyle = 'limegreen';
ctxMass.font = "14px Arial";
ctxMass.fillText( 'Barycenter', barycenterX, barycenterY - 25 );
renderer.render( scene, camera );
};
//Makes the scene responsive
//Note that traces are cleared when the size of the viewport changes
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize() {
w = window.innerWidth;
h = window.innerHeight;
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.setSize( w, h );
pathCanvas.width = w;
pathCanvas.height = h;
massCanvas.width = w;
massCanvas.height = h;
ctxPath.clearRect( -0.5 * w, -0.5 * h, w, h );
ctxMass.clearRect( -0.5 * w, -0.5 * h, w, h );
ctxPath.translate( w / 2, h / 2 );
ctxMass.translate( w / 2, h / 2 );
}
render();
}
//Tidy up
function resetSimulation() {
orbitButton.removeEventListener( 'click', showOrbits );
view3DButton.removeEventListener( 'click', hideOrbits );
cancelAnimationFrame( requestAnimationFrameId );
ctxPath.clearRect( -0.5 * w, -0.5 * h, w, h );
renderer.domElement.parentNode.removeChild( renderer.domElement );
pathCanvas.parentNode.removeChild( pathCanvas );
massCanvas.parentNode.removeChild( massCanvas );
}
//API
return {
startSimulation: ( scenario, container, camPos, camFocus, viewOrbits, view3D, cameraControls ) => {
sceneSetup( initSimulation, scenario, container, camPos, camFocus, viewOrbits, view3D, cameraControls );
},
resetSimulation: resetSimulation
};
}());
export default scene;

Three.js: How to animate particles along a line

I'm trying to animate particles along a path similar to this chrome expriement: http://armsglobe.chromeexperiments.com/
I've tried digging into the source of this project, and what I've groked so far is that they are using a built in curve method .getPoitns() to generate about 30 points on their lines.
Is there a better example on what I'm trying to accomplish? Is there a method for getting points on the line than using the .lerp() method 30 times to get 30 points? Should I just use TWEEN animations?
Any help or direction would be appreciated.
I've figured out a solution, not sure if it's the best or not, but it works well.
You can find a demo on JsFiddle: https://jsfiddle.net/L4beLw26/
//First create the line that we want to animate the particles along
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-800, 0, -800));
geometry.vertices.push(new THREE.Vector3(800, 0, 0));
var line = new THREE.Line(geometry, material);
var startPoint = line.geometry.vertices[0];
var endPoint = line.geometry.vertices[1];
scene.add(line);
//next create a set of about 30 animation points along the line
var animationPoints = createLinePoints(startPoint, endPoint);
//add particles to scene
for ( i = 0; i < numParticles; i ++ ) {
var desiredIndex = i / numParticles * animationPoints.length;
var rIndex = constrain(Math.floor(desiredIndex),0,animationPoints.length-1);
var particle = new THREE.Vector3();
var particle = animationPoints[rIndex].clone();
particle.moveIndex = rIndex;
particle.nextIndex = rIndex+1;
if(particle.nextIndex >= animationPoints.length )
particle.nextIndex = 0;
particle.lerpN = 0;
particle.path = animationPoints;
particleGeometry.vertices.push( particle );
}
//set particle material
var pMaterial = new THREE.ParticleBasicMaterial({
color: 0x00FF00,
size: 50,
map: THREE.ImageUtils.loadTexture(
"assets/textures/map_mask.png"
),
blending: THREE.AdditiveBlending,
transparent: true
});
var particles = new THREE.ParticleSystem( particleGeometry, pMaterial );
particles.sortParticles = true;
particles.dynamic = true;
scene.add(particles);
//update function for each particle animation
particles.update = function(){
// var time = Date.now()
for( var i in this.geometry.vertices ){
var particle = this.geometry.vertices[i];
var path = particle.path;
particle.lerpN += 0.05;
if(particle.lerpN > 1){
particle.lerpN = 0;
particle.moveIndex = particle.nextIndex;
particle.nextIndex++;
if( particle.nextIndex >= path.length ){
particle.moveIndex = 0;
particle.nextIndex = 1;
}
}
var currentPoint = path[particle.moveIndex];
var nextPoint = path[particle.nextIndex];
particle.copy( currentPoint );
particle.lerp( nextPoint, particle.lerpN );
}
this.geometry.verticesNeedUpdate = true;
};
function createLinePoints(startPoint, endPoint){
var numPoints = 30;
var returnPoints = [];
for(i=0; i <= numPoints; i ++){
var thisPoint = startPoint.clone().lerp(endPoint, i/numPoints);
returnPoints.push(thisPoint);
}
return returnPoints;
}
function constrain(v, min, max){
if( v < min )
v = min;
else
if( v > max )
v = max;
return v;
}
and then in the animation loop:
particles.update();
I don't know if anyone else can't see the snippets working, but I took the answer that jigglebilly provided and put it into a full html page and is working. Just so that if you want to see a working version. `
Particle Test
<script src="../js/three.js"></script>
<script type="text/javascript">
var renderer = new THREE.WebGLRenderer( { antialias: true } );
var camera = new THREE.PerspectiveCamera( 45, (window.innerWidth) / (window.innerHeight), 100, 10000);
var container = document.getElementById("containerElement");
var numParticles = 40;
container.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var material = new THREE.LineBasicMaterial({color: 0x0000ff });
//First create the line that we want to animate the particles along
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-800, 0, -800));
geometry.vertices.push(new THREE.Vector3(800, 0, 0));
var line = new THREE.Line(geometry, material);
var startPoint = line.geometry.vertices[0];
var endPoint = line.geometry.vertices[1];
scene.add(line);
//next create a set of about 30 animation points along the line
var animationPoints = createLinePoints(startPoint, endPoint);
var particleGeometry = new THREE.Geometry();
//add particles to scene
for ( i = 0; i < numParticles; i ++ ) {
var desiredIndex = i / numParticles * animationPoints.length;
var rIndex = constrain(Math.floor(desiredIndex),0,animationPoints.length-1);
var particle = new THREE.Vector3();
var particle = animationPoints[rIndex].clone();
particle.moveIndex = rIndex;
particle.nextIndex = rIndex+1;
if(particle.nextIndex >= animationPoints.length )
particle.nextIndex = 0;
particle.lerpN = 0;
particle.path = animationPoints;
particleGeometry.vertices.push( particle );
}
//set particle material
var pMaterial = new THREE.ParticleBasicMaterial({
color: 0x00FF00,
size: 50,
blending: THREE.AdditiveBlending,
transparent: true
});
var particles = new THREE.ParticleSystem( particleGeometry, pMaterial );
particles.sortParticles = true;
particles.dynamic = true;
scene.add(particles);
function UpdateParticles(){
// var time = Date.now()
for( var i = 0; i < particles.geometry.vertices.length; i++ ){
var particle = particles.geometry.vertices[i];
var path = particle.path;
particle.lerpN += 0.05;
if(particle.lerpN > 1){
particle.lerpN = 0;
particle.moveIndex = particle.nextIndex;
particle.nextIndex++;
if( particle.nextIndex >= path.length ){
particle.moveIndex = 0;
particle.nextIndex = 1;
}
}
var currentPoint = path[particle.moveIndex];
var nextPoint = path[particle.nextIndex];
particle.copy( currentPoint );
particle.lerp( nextPoint, particle.lerpN );
}
particles.geometry.verticesNeedUpdate = true;
};
animate();
function createLinePoints(startPoint, endPoint){
var numPoints = 30;
var returnPoints = [];
for(i=0; i <= numPoints; i ++){
var thisPoint = startPoint.clone().lerp(endPoint, i/numPoints);
returnPoints.push(thisPoint);
}
return returnPoints;
}
function constrain(v, min, max){
if( v < min )
v = min;
else
if( v > max )
v = max;
return v;
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
UpdateParticles();
}
</script>
`
This uses three.js R67.

Categories

Resources