Skip to content

Instantly share code, notes, and snippets.

@benursu
Created December 22, 2019 19:47
Show Gist options
  • Save benursu/853f0634b12b0c5a1f993c3ad9de1ea0 to your computer and use it in GitHub Desktop.
Save benursu/853f0634b12b0c5a1f993c3ad9de1ea0 to your computer and use it in GitHub Desktop.
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// 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