Created
December 22, 2019 19:47
-
-
Save benursu/853f0634b12b0c5a1f993c3ad9de1ea0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
// Time Machine | |
// Ben Ursu | @afrosquared | |
// Frank Vitale | @creativefrv | 3D Models & Print | |
// Noland Chaliha | @alwayscodingsomething | Shaders | |
// Willow Ursu | Word Wielding | |
// Jon Ursu | Scout & Set Design | |
// Chris Price | @chrislprice | Photography | https://www.instagram.com/p/B6UZeVChgRI/ | |
// Spark AR Studio v76 | |
// Instagram | https://www.instagram.com/a/r/?effect_id=2589582634603145 | |
// Target | http://www.afrosquared.com/effects/assets/images/time-machine-target.jpg | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// require | |
const Scene = require('Scene'); | |
const Animation = require('Animation'); | |
const R = require('Reactive'); | |
const TouchGestures = require('TouchGestures') | |
const D = require('Diagnostics'); | |
const Time = require('Time'); | |
const Materials = require('Materials'); | |
const Textures = require('Textures'); | |
const Audio = require('Audio'); | |
const CameraInfo = require('CameraInfo'); | |
const Patches = require('Patches'); | |
const Instruction = require('Instruction'); | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// util | |
var vectorForward = R.vector(1, 0, 0); | |
var rotation90 = Math.PI / 2; | |
var rotation180 = Math.PI; | |
var rotation360 = Math.PI * 2; | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// scene | |
var canvasInstructions = Scene.root.find('canvasInstructions'); | |
var tracker0 = Scene.root.find('tracker0'); | |
var tracker0Location = tracker0.child('location'); | |
var portal = Scene.root.find('portal'); | |
var watch = portal.find('watch'); | |
var watchHourHand = watch.child('hourHand'); | |
var watchHourHandRotate = watchHourHand; | |
var watchMinuteHand = watch.child('minuteHand'); | |
var watchMinuteHandRotate = watchMinuteHand; | |
var watchSecondHand = watch.child('secondHand'); | |
var watchSecondHandRotate = watchSecondHand.child('secondHandRotate'); | |
var clock = portal.find('clock'); | |
var compassInscriptionParticle = portal.child('compassInscriptionParticle'); | |
var earth = portal.child('earth'); | |
var earthModel = earth.child('earthModel'); | |
var earthModelEarth = earthModel.find('Earth'); | |
var earthModelEarthMesh = earthModel.find('Earth_Surface.mat_0'); | |
var space = portal.child('space'); | |
var watchHandsMaterial = Materials.get('watchHands'); | |
var watchHandsHourShadowMaterial = Materials.get('watchHandsHourShadow'); | |
var watchHandsMinuteShadowMaterial = Materials.get('watchHandsMinuteShadow'); | |
var watchHandsSecondShadowMaterial = Materials.get('watchHandsSecondShadow'); | |
var compassRingMaterial = Materials.get('compassRing'); | |
var compassInscription0Material = Materials.get('compassInscription0'); | |
var compassInscriptionParticleMaterial = Materials.get('compassInscriptionParticle'); | |
var clockFaceMaterial = Materials.get('clockFace'); | |
var compassInscription0Value = R.val(0); | |
Patches.setScalarValue('compassInscription0Value', compassInscription0Value); | |
var watchHandsShadowHourOpacity = 0.3; | |
var watchHandsShadowMinuteOpacity = 0.2; | |
var watchHandsShadowSecondOpacity = 0.15; | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// audio | |
var introPlayback = Audio.getPlaybackController('intro'); | |
var watchPlayback = Audio.getPlaybackController('watch'); | |
var timeMinuteOclockPlayback = Audio.getPlaybackController('timeMinuteOclock'); | |
var timeHourPlaybacks = []; | |
for(var i = 1; i <= 12; i++){ | |
var playback = Audio.getPlaybackController('timeHour' + i); | |
timeHourPlaybacks.push(playback); | |
} | |
var timeMinutePlaybacks = []; | |
for(var i = 1; i <= 59; i++){ | |
var playback = Audio.getPlaybackController('timeMinute' + i); | |
timeMinutePlaybacks.push(playback); | |
} | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// tracker | |
var tracking0 = false; | |
var trackStarted = false; | |
tracker0.confidence.monitor().subscribe(function(e){ | |
if(e.newValue == 'NOT_TRACKING'){ | |
tracking0 = false; | |
introReset(); | |
}else{ | |
canvasInstructions.hidden = true; | |
tracking0 = true; | |
trackStarted = true; | |
introStart(); | |
} | |
}); | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////////////// intro | |
var clockStartZ = 0; | |
var clockEndZ = -0.2; | |
var watchMinuteHandRotateDriver; | |
var watchHourHandRotateDriver; | |
var watchSecondHandRotateDriver; | |
var watchLoopCount = 6; | |
var watchMinuteHandRotateDuration = 5000; | |
var watchHourHandRotateDuration = watchMinuteHandRotateDuration; | |
var watchSecondHandRotateDuration = watchMinuteHandRotateDuration; | |
var date = new Date(); | |
var hours = date.getHours(); | |
hours = hours % 12; | |
hours = hours ? hours : 12; | |
var minutes = date.getMinutes(); | |
var seconds = date.getSeconds(); | |
// hours = 10; | |
// minutes = 59; | |
var watchMinuteHandRotateOffset = rotation360 - ((minutes/60) * rotation360); | |
var watchHourHandRotateOffset = rotation360 - ((hours/12) * rotation360); | |
var watchSecondHandRotateOffset = rotation360 - ((seconds/60) * rotation360); | |
var watchSecondHandRotateOffsetOneSecEarlier = rotation360 - (((seconds-1)/60) * rotation360); | |
var watchSecondHandRotateOffsetTwoSecEarlier = rotation360 - (((seconds-2)/60) * rotation360); | |
var watchSecondHandRotateOffsetThreeSecEarlier = rotation360 - (((seconds-3)/60) * rotation360); | |
var compassInscriptionParticleStartZ = -0.013; | |
var compassInscriptionParticleEndZ = -0.2; | |
var compassInscriptionParticleMaterialOpacity = 0.3; | |
var introTimeouts = []; | |
var introDrivers = []; | |
function introReset(){ | |
Patches.setPulseValue('introReset', R.once()); | |
for(var i = 0; i < introTimeouts.length; i++){ | |
Time.clearInterval(introTimeouts[i]); | |
} | |
for(var i = 0; i < introDrivers.length; i++){ | |
introDrivers[i].stop(); | |
} | |
if(watchMinuteHandRotateDriver != null){ | |
watchMinuteHandRotateDriver.stop(); | |
} | |
if(watchHourHandRotateDriver != null){ | |
watchHourHandRotateDriver.stop(); | |
} | |
if(watchSecondHandRotateDriver != null){ | |
watchSecondHandRotateDriver.stop(); | |
} | |
compassRingMaterial.opacity = 0; | |
compassInscription0Material.opacity = 0; | |
watchHandsMaterial.opacity = 0; | |
watchHandsHourShadowMaterial.opacity = 0; | |
watchHandsMinuteShadowMaterial.opacity = 0; | |
watchHandsSecondShadowMaterial.opacity = 0; | |
clockFaceMaterial.opacity = 0; | |
earth.hidden = true; | |
space.hidden = true; | |
clock.transform.z = clockStartZ; | |
earth.transform.z = 0; | |
earthModel.transform.rotationY = 0; | |
earthModel.transform.scaleX = 0.002; | |
earthModel.transform.scaleY = 0.002; | |
earthModel.transform.scaleZ = 0.002; | |
earthModelEarth.transform.rotationX = 0; | |
earthModelEarth.transform.rotationZ = 0; | |
watchMinuteHandRotate.transform.rotationY = watchMinuteHandRotateOffset; | |
watchHourHandRotate.transform.rotationY = watchHourHandRotateOffset; | |
watchSecondHandRotate.transform.rotationY = watchSecondHandRotateOffsetThreeSecEarlier; | |
// watchSecondHandRotate.transform.rotationY = watchSecondHandRotateOffset; | |
compassInscription0Value = R.val(0); | |
Patches.setScalarValue('compassInscription0Value', compassInscription0Value); | |
compassInscriptionParticle.transform.z = compassInscriptionParticleStartZ; | |
} | |
function introStart(){ | |
introReset(); | |
Patches.setPulseValue('introStart', R.once()); | |
introPlayback.reset(); | |
introPlayback.setPlaying(true); | |
watchPlayback.reset(); | |
watchPlayback.setPlaying(true); | |
watchPlayback.setLooping(true); | |
var timeout = Time.setTimeout(function () { | |
timeHourPlaybacks[hours-1].reset(); | |
timeHourPlaybacks[hours-1].setPlaying(true); | |
}, 1000); | |
var timeout = Time.setTimeout(function () { | |
if(minutes == 0){ | |
timeMinuteOclockPlayback.reset(); | |
timeMinuteOclockPlayback.setPlaying(true); | |
}else{ | |
timeMinutePlaybacks[minutes-1].reset(); | |
timeMinutePlaybacks[minutes-1].setPlaying(true); | |
} | |
}, 1750); | |
//animation | |
var timerCounter = 0; | |
//timerCounter += 0; | |
var timeout = Time.setTimeout(function () { | |
var driver = Animation.timeDriver({ durationMilliseconds: 1000 }); | |
var sampler = Animation.samplers.linear(0, 1); | |
watchHandsMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1000 }); | |
var sampler = Animation.samplers.linear(0, watchHandsShadowHourOpacity); | |
watchHandsHourShadowMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1000 }); | |
var sampler = Animation.samplers.linear(0, watchHandsShadowMinuteOpacity); | |
watchHandsMinuteShadowMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1000 }); | |
var sampler = Animation.samplers.linear(0, watchHandsShadowSecondOpacity); | |
watchHandsSecondShadowMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
watchSecondHandRotateDriver = Animation.timeDriver({durationMilliseconds: 2000 }); | |
var sampler = Animation.samplers.linear(watchSecondHandRotateOffsetTwoSecEarlier, watchSecondHandRotateOffset); | |
watchSecondHandRotate.transform.rotationY = Animation.animate(watchSecondHandRotateDriver, sampler); | |
watchSecondHandRotateDriver.start(); | |
}, timerCounter); | |
introTimeouts.push(timeout); | |
// timerCounter += 1000; | |
// var timeout = Time.setTimeout(function () { | |
// watchSecondHandRotate.transform.rotationY = watchSecondHandRotateOffsetTwoSecEarlier; | |
// }, timerCounter); | |
// introTimeouts.push(timeout); | |
// timerCounter += 1000; | |
// var timeout = Time.setTimeout(function () { | |
// watchSecondHandRotate.transform.rotationY = watchSecondHandRotateOffsetOneSecEarlier; | |
// }, timerCounter); | |
// introTimeouts.push(timeout); | |
timerCounter += 2000; | |
var timeout = Time.setTimeout(function () { | |
watchMinuteHandRotateDriver = Animation.timeDriver({durationMilliseconds: watchMinuteHandRotateDuration }); | |
var sampler = Animation.samplers.easeInCubic(watchMinuteHandRotateOffset, watchMinuteHandRotateOffset + (rotation360 * -watchLoopCount * 12) ); | |
watchMinuteHandRotate.transform.rotationY = Animation.animate(watchMinuteHandRotateDriver, sampler); | |
watchMinuteHandRotateDriver.start(); | |
watchHourHandRotateDriver = Animation.timeDriver({durationMilliseconds: watchHourHandRotateDuration }); | |
var sampler = Animation.samplers.easeInCubic(watchHourHandRotateOffset, watchHourHandRotateOffset + (rotation360 * -watchLoopCount)); | |
watchHourHandRotate.transform.rotationY = Animation.animate(watchHourHandRotateDriver, sampler); | |
watchHourHandRotateDriver.start(); | |
watchSecondHandRotateDriver = Animation.timeDriver({durationMilliseconds: watchSecondHandRotateDuration }); | |
var sampler = Animation.samplers.easeInCubic(watchSecondHandRotateOffset, watchSecondHandRotateOffset + (rotation360 * -watchLoopCount * 60) ); | |
watchSecondHandRotate.transform.rotationY = Animation.animate(watchSecondHandRotateDriver, sampler); | |
watchSecondHandRotateDriver.start(); | |
}, timerCounter); | |
introTimeouts.push(timeout); | |
timerCounter += 500; | |
var timeout = Time.setTimeout(function () { | |
var driver = Animation.timeDriver({ durationMilliseconds: 500 }); | |
var sampler = Animation.samplers.linear(0, 1); | |
compassRingMaterial.opacity = Animation.animate(driver, sampler); | |
compassInscription0Material.opacity = Animation.animate(driver, sampler); | |
clockFaceMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
}, timerCounter); | |
introTimeouts.push(timeout); | |
timerCounter += 500; | |
var timeout = Time.setTimeout(function () { | |
earth.hidden = false; | |
space.hidden = false; | |
var driver = Animation.timeDriver({ durationMilliseconds: 3400 }); | |
var sampler = Animation.samplers.easeInCubic(clockStartZ, clockEndZ); | |
clock.transform.z = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 9000 }); | |
var sampler = Animation.samplers.easeInOutCubic(0, 4.25); | |
earth.transform.z = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({durationMilliseconds: 10000 }); | |
var sampler = Animation.samplers.easeOutCubic(0, rotation360*5); | |
earthModel.transform.rotationY = Animation.animate(driver, sampler); | |
driver.start(); | |
}, timerCounter); | |
introTimeouts.push(timeout); | |
//offset burn | |
var timeout = Time.setTimeout(function () { | |
var driver = Animation.timeDriver({durationMilliseconds: 3500 }); | |
var sampler = Animation.samplers.linear(0, 1); | |
compassInscription0Value = Animation.animate(driver, sampler); | |
driver.start(); | |
Patches.setScalarValue('compassInscription0Value', compassInscription0Value); | |
var driver = Animation.timeDriver({durationMilliseconds: 500 }); | |
var sampler = Animation.samplers.linear(0, compassInscriptionParticleMaterialOpacity); | |
compassInscriptionParticleMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
var driver = Animation.timeDriver({durationMilliseconds: 2000 }); | |
var sampler = Animation.samplers.linear(compassInscriptionParticleStartZ, compassInscriptionParticleEndZ); | |
compassInscriptionParticle.transform.z = Animation.animate(driver, sampler); | |
driver.start(); | |
}, timerCounter + 1500); | |
introTimeouts.push(timeout); | |
//offset burn out | |
var timeout = Time.setTimeout(function () { | |
var driver = Animation.timeDriver({durationMilliseconds: 2000 }); | |
var sampler = Animation.samplers.linear(compassInscriptionParticleMaterialOpacity, 0); | |
compassInscriptionParticleMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
}, timerCounter + 2500); | |
introTimeouts.push(timeout); | |
//offset earth | |
var timeout = Time.setTimeout(function () { | |
var driver = Animation.timeDriver({ durationMilliseconds: 6000 }); | |
// var sampler = Animation.samplers.polyline({ | |
// keyframes: [ | |
// 0.002,0.001,0.004 | |
// ], | |
// knots: [ | |
// 0,15,30 | |
// ] | |
// }); | |
var sampler = Animation.samplers.easeInOutCubic(0.002, 0.003); | |
earthModel.transform.scaleX = Animation.animate(driver, sampler); | |
earthModel.transform.scaleY = Animation.animate(driver, sampler); | |
earthModel.transform.scaleZ = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 5000 }); | |
var sampler = Animation.samplers.easeInOutCubic(0, -rotation90); | |
earthModelEarth.transform.rotationX = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 12000, loopCount: Infinity }); | |
var sampler = Animation.samplers.linear(0, rotation360); | |
earthModelEarth.transform.rotationZ = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
}, timerCounter + 5000); | |
introTimeouts.push(timeout); | |
timerCounter += 2000; | |
var timeout = Time.setTimeout(function () { | |
var driver = Animation.timeDriver({ durationMilliseconds: 1400 }); | |
var sampler = Animation.samplers.linear(1, 0); | |
clockFaceMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1100 }); | |
var sampler = Animation.samplers.linear(1, 0); | |
watchHandsMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1100 }); | |
var sampler = Animation.samplers.linear(watchHandsShadowHourOpacity, 0); | |
watchHandsHourShadowMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1100 }); | |
var sampler = Animation.samplers.linear(watchHandsShadowMinuteOpacity, 0); | |
watchHandsMinuteShadowMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
var driver = Animation.timeDriver({ durationMilliseconds: 1100 }); | |
var sampler = Animation.samplers.linear(watchHandsShadowSecondOpacity, 0); | |
watchHandsSecondShadowMaterial.opacity = Animation.animate(driver, sampler); | |
driver.start(); | |
introDrivers.push(driver); | |
}, timerCounter); | |
introTimeouts.push(timeout); | |
} | |
//debug | |
// TouchGestures.onTap().subscribe(function(gesture) { | |
// canvasInstructions.hidden = true; | |
// introStart(); | |
// }); | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// fade text | |
var textParticles = Scene.root.find('textParticles'); | |
var textParticlesAlphaSampler = Animation.samplers.HSVA([ | |
Animation.samplers.constant(1), | |
Animation.samplers.constant(1), | |
Animation.samplers.constant(1), | |
Animation.samplers.easeInCubic(1, 0) | |
]); | |
var textParticlesSizeSampler = Animation.samplers.easeInQuad(0.013, 0.017); | |
for(var i = 0; i <= 20; i++){ | |
var emitter = textParticles.find('turn' + i + 'Emitter'); | |
emitter.hsvaColorModulationModifier = textParticlesAlphaSampler; | |
emitter.sizeModifier = textParticlesSizeSampler; | |
} | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// instructions | |
CameraInfo.captureDevicePosition.monitor({fireOnInitialValue: true}).subscribe(function (e) { | |
if(e.newValue == 'FRONT'){ | |
Instruction.bind(true, 'flip_camera'); | |
canvasInstructions.hidden = true; | |
}else{ | |
Instruction.bind(false, 'flip_camera'); | |
if(!trackStarted){ | |
canvasInstructions.hidden = false; | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment