diff --git a/src/js/Fire.js b/src/js/Fire.js index f605e6d..acc9c1f 100644 --- a/src/js/Fire.js +++ b/src/js/Fire.js @@ -40,6 +40,21 @@ export default class Fire { // THREE.Fire.prototype.constructor = THREE.Fire; } + create() { + const fireTex = globals.loader.load("assets/flame/FireOrig.png"); + volumetricFire = new THREE.Fire(fireTex); + volumetricFire.scale.set(6, 6.8, 6.0); //width, height, z + volumetricFire.position.set(globals.posBehindX + 30, 3.5, globals.posBehindZ); + var wireframeMat = new THREE.MeshBasicMaterial({ + color : new THREE.Color(0xffffff), + wireframe : true + }); + var wireframe = new THREE.Mesh(volumetricFire.geometry, wireframeMat.clone()); + volumetricFire.add(wireframe); + wireframe.visible = false; + globals.scene.add(volumetricFire); + } + // update = function ( time ) { // var invModelMatrix = this.material.uniforms.invModelMatrix.value; // this.updateMatrixWorld(); diff --git a/src/js/Flame.js b/src/js/Flame.js index 1498489..11fb5d5 100644 --- a/src/js/Flame.js +++ b/src/js/Flame.js @@ -12,20 +12,36 @@ import globals from './globals.js'; export default class Flame { - constructor(fireParam) { - this.triggerTime = fireParam; + // constructor(fireParam) { + constructor() { + // this.triggerTime = fireParam; } - initFire() { - globals.loader.crossOrigin = ''; - var fireTex = globals.loader.load("./assets/flame/FireOrig.png"); + create(pos) { + // console.log(pos); + console.log(globals); + // console.log(globals.flameArr); - // const volumetricFire = new THREE.Fire(fireTex); - const volumetricFire = new Fire(fireTex); - volumetricFire.position.set(globals.posBehindX + 22, 0, globals.posBehindZ); + const fireTex = globals.loader.load("assets/flame/FireOrig.png"); + const volumetricFire = new THREE.Fire(fireTex); volumetricFire.scale.set(6, 6.8, 6.0); //width, height, z + + // volumetricFire.position.set(globals.posBehindX + 30, 3.5, globals.posBehindZ); + // volumetricFire.position.set(pos.x, 3.5, globals.posBehindZ); + volumetricFire.position.set(pos.x, globals.posBehindY, globals.posBehindZ); + + var wireframeMat = new THREE.MeshBasicMaterial({ + color : new THREE.Color(0xffffff), + wireframe : true + }); + var wireframe = new THREE.Mesh(volumetricFire.geometry, wireframeMat.clone()); volumetricFire.add(wireframe); - globals.scene.add(volumetricFire); + wireframe.visible = false; + + // globals.flameArr.push(volumetricFire) + globals.flameArr = [volumetricFire]; + // globals.scene.add(volumetricFire); + globals.scene.add(globals.flameArr[0]); } addFire(posX = globals.posBehindX + 22, currentTime) { diff --git a/src/js/InstrumentMappings.js b/src/js/InstrumentMappings.js index d714cf6..ecf5b31 100644 --- a/src/js/InstrumentMappings.js +++ b/src/js/InstrumentMappings.js @@ -15,6 +15,12 @@ export default class InstrumentMappings { getInstrumentMappingTemplate(movement = 'physics') { //const instrumentMapping = { return { + flameCenter: { + type: 'animation', + triggerOn: 2, + timesTriggered: 0, + originalPosition: { x: 0, y: 0, z: -5 } + }, //TODO: originalPosition and offsetMultiplier should have an effect on where ball (or other shapes) are dropped hiHatClosed: { ballDesc: 'H', diff --git a/src/js/Trigger.js b/src/js/Trigger.js index 0686f4a..33fe217 100644 --- a/src/js/Trigger.js +++ b/src/js/Trigger.js @@ -7,6 +7,7 @@ import { Transport, Player, Players, Part, Time, Volume } from 'tone'; import globals from './globals.js'; import InstrumentMappings from './InstrumentMappings.js'; import Physics from './Physics.js'; +import Flame from './Flame.js'; //-----TONE------// Tone.Transport.bpm.value = 200; @@ -86,12 +87,15 @@ const playerTomHigh = new Player("./assets/sounds/drum-kits/electronic/tom-high. const playerTomMid = new Player("./assets/sounds/drum-kits/electronic/tom-mid.mp3").toMaster(); const playerTomLow = new Player("./assets/sounds/drum-kits/electronic/tom-low.mp3").toMaster(); +let flameFirst = new Flame(); + export default class Trigger { constructor() { // super(); } triggerNote(obj) { + // console.log({obj}); const physics = new Physics(); @@ -122,8 +126,8 @@ export default class Trigger { } else if (triggerObj.variation === 'ride') { playerRide.start(); } else if (triggerObj.variation === 'tom-high') { - playerTomHigh.start(); - // flameFirst.addFire(globals.ticks); + playerTomHigh.start(); // key: 7 + // flameFirst.create(obj.initPosition); } else { console.log('UNDEF variation - triggerNote() -> triggerObj (drum): ', triggerObj); playerHiHat.start(); diff --git a/src/js/app.js b/src/js/app.js index 8ed9cf0..43127bb 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -3,7 +3,7 @@ import globals from './globals.js'; import InstrumentMappings from './InstrumentMappings.js'; import { FlyControls } from 'three/examples/jsm/controls/FlyControls.js'; import Light from './Light.js'; -// import Flame from './Flame.js'; +import Flame from './Flame.js'; import Physics from './Physics.js'; import Helpers from './THREEx.js'; import Pool from './Pool.js'; @@ -103,6 +103,7 @@ const globalSkyboxTheme = 'mercury'; var geometry = new THREE.CubeGeometry(1200, 1200, 1200); //prev var cubeMaterials = [ + // new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(`assets/flame/FireOrig.png`), side: THREE.DoubleSide }), //front side new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(`assets/skybox/${globalSkyboxTheme}/ft.png`), side: THREE.DoubleSide }), //front side new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(`assets/skybox/${globalSkyboxTheme}/bk.png`), side: THREE.DoubleSide }), //back side new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(`assets/skybox/${globalSkyboxTheme}/up.png`), side: THREE.DoubleSide }), //up side @@ -288,19 +289,12 @@ function addThickStaffLines() { //-----Static Fire Example------// -let flameActive = false; -let volumetricFire; //TODO: remove after Flame class methods working -// let flameFirst = new Flame(globals.triggerAnimationTime); -// flameFirst.initFire(); - globals.loader.crossOrigin = ''; -const fireTex = globals.loader.load("./assets/flame/FireOrig.png"); -volumetricFire = new THREE.Fire(fireTex); -volumetricFire.position.set(globals.posBehindX + 22, 0, globals.posBehindZ); -volumetricFire.scale.set(6, 6.8, 6.0); //width, height, z -volumetricFire.position.set(globals.posBehindX + 20, 0, globals.posBehindZ); -console.log(volumetricFire); -globals.scene.add(volumetricFire); + +let flameActive = false; +// // let flameFirst = new Flame(globals.triggerAnimationTime); +// let flameFirst = new Flame(); +// // flameFirst.create(); //-----POOL BALLS (STATIC ROW)------// const poolBalls = {}; @@ -390,7 +384,7 @@ function moveObject(object, motionActive, positionUp, threshold) { // var toneClock = new Tone.Clock(function(time) { // console.log(time); // }, 1); -var clock = new THREE.Clock(); +// var clock = new THREE.Clock(); //-----ANIMATION------// let animate = () => { @@ -402,6 +396,7 @@ let animate = () => { // console.log('ticks: ', Tone.Transport.ticks); //ex. 10 // console.log('position: ', Tone.Transport.position); //ex: 0:0:0.124 // console.log('seconds: ', Tone.Transport.seconds); + // console.log(globals.ticks); if (globals.showStaticRows === true) { for (var key in poolBalls) { @@ -454,9 +449,12 @@ let animate = () => { } // TODO: readd after webpack setup - // var flameRate = clock.getElapsedTime() * 2.0; + var flameRate = globals.clock.getElapsedTime() * 2.0; // volumetricFire.update(flameRate); - + if (globals.flameArr.length > 0) { + globals.flameArr[0].update(flameRate); + } + physics.updateBodies(globals.world); globals.world.step(globals.fixedTimeStep); diff --git a/src/js/audio.js b/src/js/audio.js index 2390612..011616b 100644 --- a/src/js/audio.js +++ b/src/js/audio.js @@ -1,6 +1,10 @@ import globals from './globals.js'; import Tone from 'tone'; import Physics from './Physics.js'; +import Flame from './Flame.js'; + +let flameAudio = new Flame(); + /* *** AUDIO *** */ @@ -91,15 +95,15 @@ const boleroFireChords = [ ["0:7:0", globals.instr.sphereChordF], ["0:9:0", globals.instr.sphereChordA3], ["0:10:0", globals.instr.sphereChordF], + // ["0:11:0", globals.instr.flameCenter], ]; +let flameActive = false; const pianoChordsFirstPart = new Tone.Part(function(time, instr) { physics.addBody(true, time * globals.multiplierPosX, instr); - // addFire(globalTicks); //old - // flameFirst.addFire(globalTicks); - // flameActive = false; }, boleroFireChords); +// boleroFireChords.push(["0:11:0", globals.instr.flameCenter]); const pianoChordsSecondPart = new Tone.Part(function(time, instr) { physics.addBody(true, time * globals.multiplierPosX, instr); }, boleroFireChords); @@ -107,15 +111,40 @@ const pianoChordsSecondPart = new Tone.Part(function(time, instr) { pianoChordsFirstPart.loop = 2; // pianoChordsFirstPart.start("1:0:0"); // pianoChordsFirstPart.start("4:0:0"); -pianoChordsFirstPart.start(globals.triggerAnimationTime); +pianoChordsFirstPart.start(globals.triggerAnimationTime); //"4:0:0" pianoChordsSecondPart.loop = 2; // pianoChordsSecondPart.start("6:0:0"); pianoChordsSecondPart.start("9:0:0"); +var animationPart = new Tone.Part(function(time, instr) { + physics.addBody(true, time * globals.multiplierPosX, instr); +}, [ + // ["0:0:0", globals.instr.flameCenter], + ["0:0:0", globals.instr.flameCenter], +]); +animationPart.start("6:5:0"); + +var animationPart2 = new Tone.Part(function(time, instr) { + physics.addBody(true, time * globals.multiplierPosX, instr); +}, [ + ["0:0:0", globals.instr.flameCenter], +]); +// animationPart2.start("10:5:0"); //TODO: add second animation part for fire +animationPart2.start("11:5:0"); //TODO: add second animation part for fire + +// animationPart.start("5:10:0"); +// animationPart.start("6:0:0"); +// var animationEvent = new Tone.Event(function(time, instr){ +// physics.addBody(true, time * globals.multiplierPosX, instr); +// //}, ["0:0:0", globals.instr.flameCenter]); +// }, [["0:0:0", globals.instr.flameCenter]]); //err: TypeError: Failed to execute 'setValueAtTime' on 'AudioParam': The provided float value is non-finite. +// animationEvent.start("5:11:0"); + var pianoChordsFinalPart = new Tone.Part(function(time, instr) { physics.addBody(true, time * globals.multiplierPosX, instr); }, [ + // ["0:0:0", globals.instr.flameCenter], //too soon ["0:0:0", globals.instr.sphereChordE], ["0:2:0", globals.instr.sphereChordG], ["0:4:0", globals.instr.sphereChordA3], diff --git a/src/js/globals.js b/src/js/globals.js index dbc8717..c71094d 100644 --- a/src/js/globals.js +++ b/src/js/globals.js @@ -17,6 +17,8 @@ export default { damping: 0.01, dropPosX: 5.5, fixedTimeStep: 1.0 / 60.0, + flameArr: [], + flameCounter: 0, instr: {}, instrumentCounter: 0, lastColor: '#000000', @@ -32,6 +34,7 @@ export default { showStaticRows: false, ticks: 0, triggerAnimationTime: '4:0:0', + // Transport: Tone.Transport, //TODO: add Transport here for logging ticks and position world: new CANNON.World(), }; diff --git a/src/js/physics.js b/src/js/physics.js index f11780a..f9db5cc 100644 --- a/src/js/physics.js +++ b/src/js/physics.js @@ -4,6 +4,11 @@ import Helpers from './THREEx.js'; import Trigger from './Trigger.js'; import InstrumentMappings from './InstrumentMappings.js'; +import Flame from './Flame.js'; + +let flamePhysics = new Flame(); + + /* *** PHYSICS *** */ @@ -33,11 +38,8 @@ export default class Physics { const defaultInstr = instrument.getInstrumentMappingTemplate(); options = defaultInstr.hiHatClosed; } - + const trigger = new Trigger(); - // console.log('addBody -> options: ', options); - // console.log('addBody -> timeout: ', timeout); - // helpers = new Helpers(); const material = new CANNON.Material(); const body = new CANNON.Body({ mass: 5, material: material }); @@ -81,28 +83,32 @@ export default class Physics { // zPos = options.originalPosition.z; body.position.set((sphere) ? -xPos : xPos, yPos, zPos); - // body.position.set((sphere) ? -x : x, y, 0); - body.linearDamping = globals.damping; - // body.initVelocity.x = 5; // TODO: cause balls to spin and roll off - // body.angularVelocity.y = 9.5; //crazy spin - // body.angularVelocity.y = 1.5; //slow spin + body.linearDamping = globals.damping; - // body.angularVelocity.z = 15.5; //GREAT - // body.angularVelocity.z = 12; - // body.angularVelocity.z = 8; //PREV body.angularVelocity.z = 12; - // body.angularVelocity.z = 35.5; //too fast - - // body.angularVelocity.x = 0.9; //flips ball - // body.angularVelocity.x = 9.9; //WORKS - off to right - // body.angularVelocity.z = 0.9; //spins ball - // console.log({ body }); - setTimeout(function() { //TODO: remove setTimeout param if not needed anymore + if (options.type === 'animation') { + console.log('addBody -> animation: ', options); + + // if (globals.flameCounter % 2 === 0) { + // if (globals.flameCounter % 3 === 0) { + console.log(globals.flameCounter); + // if (globals.flameCounter === 4) { + // if (globals.flameCounter % 2 === 1) { //is flame is called odd num of times + // if (globals.flameCounter === 1) { + // flamePhysics.create({x: -xPos}); + // globals.flameCounter = 0; + // } + flamePhysics.create({x: -xPos}); + + globals.flameCounter++; + return; + } + + // setTimeout(function() { //TODO: remove setTimeout param if not needed anymore globals.world.add(body); - }, timeout); - // globals.world.add(body); + // }, timeout); // if (this.useVisuals) this.helper.this.addVisual(body, (sphere) ? 'sphere' : 'box', true, false); @@ -114,7 +120,7 @@ export default class Physics { let bodyCollideCount = 0; body.addEventListener('collide', function(ev) { // console.log('body collide event: ', ev.body); - // console.log('body collide INERTIA: ', ev.body.inertia); //right is NaN, wrong is 0.8333333333333333 + // console.log('body collide INERTIA: ', ev.body.inertia); // console.log('contact between two bodies: ', ev.contact); // console.log(bodyCollideCount); @@ -163,15 +169,6 @@ export default class Physics { // body.quaternion.z = 0.5; // console.log(body); //TODO: rotate adjust HERE!!! } - - // //TODO: can this be removed and moved to initPhysics()??? - // //http://schteppe.github.io/cannon.js/docs/classes/ContactMaterial.html - // const materialGround = new CANNON.ContactMaterial(this.groundMaterial, material, { friction: 0.0, restitution: (sphere) ? sphereRestitution : defaultRestitution }); - // // console.log({materialGround}); - - // globals.world.addContactMaterial(materialGround); - // console.log('addBody() -> globals.world.contactmaterials: ', globals.world.contactmaterials); - // this.initContactMaterial((sphere) ? sphereRestitution : defaultRestitution); //changes ground color but breaks performance } initPhysics() { @@ -199,13 +196,7 @@ export default class Physics { this.groundMaterial = groundMaterial; // this.animate(); - - //TODO: use this.initContactMaterial here and remove from addBody() - // this.initContactMaterial(0.8); //no effect - // this.initContactMaterial(0.1); //no effect - - this.initContactMaterial(0.3); //PREV - + this.initContactMaterial(0.3); } initContactMaterial(restitutionValue = 0.3) { @@ -214,8 +205,6 @@ export default class Physics { const groundShape = new CANNON.Plane(); const tempMaterial = new CANNON.Material(); //http://schteppe.github.io/cannon.js/docs/classes/Material.html const groundBody = new CANNON.Body({ mass: 0, material: tempMaterial }); - // console.log({tempMaterial}); // friction: -1, restitution: -1 - // console.log({groundBody}); groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2); @@ -229,22 +218,9 @@ export default class Physics { this.shapes.sphere = new CANNON.Sphere(0.5); this.shapes.box = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)); - - // console.log({material}); - // material.color.r = 0; - // material.color.g = 0; - // material.color.b = 0.3; - // const body = new CANNON.Body({ mass: 5, material: material }); - - // console.log(this.groundMaterial); - const material = new CANNON.Material(); //why both tempMaterial and material needed? - // const materialGround = new CANNON.ContactMaterial(this.groundMaterial, material, { friction: 0.0, restitution: restitutionValue}); //*** UNCOMMENT TO FIX PERFORMANCE ISSUES WITH TOO MANY groundBody's const materialGround = new CANNON.ContactMaterial(tempMaterial, material, { friction: 0.0, restitution: restitutionValue }); - - // console.log({materialGround}); globals.world.addContactMaterial(materialGround); - // console.log('addBody() -> globals.world.contactmaterials: ', globals.world.contactmaterials); } createCannonTrimesh(geometry) { @@ -327,11 +303,6 @@ export default class Physics { body.threemesh = mesh; mesh.castShadow = castShadow; mesh.receiveShadow = receiveShadow; - - // console.log({mesh}); - // mesh.rotation.x = 4.0; //no effect - // mesh.rotation.y = -2.0; //no effect - // mesh.rotation.z = 2.0; //no effect globals.scene.add(mesh); } } @@ -388,18 +359,9 @@ export default class Physics { // TODO: try changing mesh.name to fix no color update mesh.name = 'groundPlane'; // geometry.colorsNeedUpdate = true; //no effect - // console.log({mesh}); const submesh = new THREE.Object3D(); - // console.log({material}); - // material.color = '0xffff00'; //err - - //TODO: set color here or in this.initContactMaterial? - // material.color.r = 0; - // material.color.g = 0; - // material.color.b = 0.3; - // const randColor = (Math.random()*0xFFFFFF<<0).toString(16); // const tempColor = parseInt('0x' + randColor); //or options.color @@ -407,23 +369,16 @@ export default class Physics { // const tempColor = '#9F532A'; //red const defaultColor = new THREE.Color(tempColor); - // console.log({defaultColor}); - material.color = defaultColor; const ground = new THREE.Mesh(geometry, material); ground.scale.set(100, 100, 100); // TODO: make ground smaller ground.name = 'groundMesh'; - // console.log({ground}); //TODO: use correctly - https://threejs.org/docs/#manual/en/introduction/How-to-update-things // ground.colorsNeedUpdate = true; submesh.add(ground); - // console.log({ground}); - - // console.log({ground}); - // console.log({submesh}); mesh.add(submesh); break;