Skip to content

Instantly share code, notes, and snippets.

@benursu
Last active April 25, 2021 17:32
Show Gist options
  • Save benursu/40e7456e114f669af9d249b845c83dda to your computer and use it in GitHub Desktop.
Save benursu/40e7456e114f669af9d249b845c83dda to your computer and use it in GitHub Desktop.
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Chain
// @afrosquared | Ben Ursu
// Instagram | Spark AR Studio | SDK v111
// https://www.instagram.com/a/r/?effect_id=296042214483846
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//require
const Scene = require('Scene');
const Animation = require('Animation');
const R = require('Reactive');
const D = require('Diagnostics');
const Time = require('Time');
const Materials = require('Materials');
const Textures = require('Textures');
const TouchGestures = require('TouchGestures');
const FT = require('FaceTracking');
import { AssetsLoader } from './AssetsLoader';
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//vars
var rotation180 = Math.PI;
var rotation360 = Math.PI * 2;
var vectorForward = R.vector(1, 0, 0);
var facePosition = FT.face(0).forehead.top;
var facetracker0;
var connection0;
var connection1;
var segmentStreakTotal = 1;
var segmentSegmentTotal = 30;
var segment0Connect;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//scene
var objects = {};
var materials = {};
var textures = {};
var PROJECT_OBJECTS = [
'facetracker0',
'connection0',
'connection1',
'segment0_connect'
];
for(var i = 0; i < segmentStreakTotal; i++){
for(var k = 0; k < segmentSegmentTotal; k++){
var segmentName = '**/segment' + i + '_' + k;
var segmentLineName = segmentName + '/line';
var segmentLineCubeName = segmentLineName + '/cube';
var segmentLineCubeNodeName = segmentLineCubeName + '/node-0'
PROJECT_OBJECTS.push(segmentName);
PROJECT_OBJECTS.push(segmentLineName);
PROJECT_OBJECTS.push(segmentLineCubeName);
PROJECT_OBJECTS.push(segmentLineCubeNodeName);
}
for(var k = 0; k <= segmentSegmentTotal; k++){
PROJECT_OBJECTS.push('**/position' + i + '_' + k);
}
}
const PROJECT_MATERIALS = [
];
const PROJECT_TEXTURES = [
];
// Load assets
AssetsLoader({
objects: PROJECT_OBJECTS,
materials: PROJECT_MATERIALS,
textures: PROJECT_TEXTURES
}).then(assets => {
objects = assets.objects;
materials = assets.materials;
textures = assets.textures;
facetracker0 = objects['facetracker0'];
connection0 = objects['connection0'];
connection1 = objects['connection1'];
segment0Connect = objects['segment0_connect'];
segmentsInit();
segmentsLookAt();
segmentsPositions();
}).catch(err => {
D.log(err);
});
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//segments
var positions = [];
var segments = [];
var segmentLines = [];
var segmentLineCubes = [];
var segmentPositionRatios = [];
var segmentScaleRatios = [];
for(var i = 0; i <= segmentStreakTotal; i++){
positions.push([]);
segments.push([]);
segmentLines.push([]);
segmentLineCubes.push([]);
segmentPositionRatios.push([]);
segmentScaleRatios.push([]);
}
function segmentsInit(){
for(var i = 0; i < segmentStreakTotal; i++){
for(var k = 0; k < segmentSegmentTotal; k++){
var segmentName = '**/segment' + i + '_' + k;
var segmentLineName = segmentName + '/line';
var segmentLineCubeName = segmentLineName + '/cube';
var segmentLineCubeNodeName = segmentLineCubeName + '/node-0'
var segment = objects[segmentName][0];
segment.hidden = false;
var segmentLine = objects[segmentLineName][0];
var segmentLineCube = objects[segmentLineCubeName][0];
var segmentLineCubeNode = objects[segmentLineCubeNodeName][0];
segmentLineCubeNode.transform.scaleX = 0.0014;
segmentLineCubeNode.transform.scaleZ = 0.0014;
var segmentPositionRatio = R.val(1);
var segmentScaleRatio = R.val(1);
segments[i].push(segment);
segmentLines[i].push(segmentLine);
segmentLineCubes[i].push(segmentLineCube);
segmentPositionRatios[i].push(segmentPositionRatio);
segmentScaleRatios[i].push(segmentScaleRatio);
}
for(var k = 0; k <= segmentSegmentTotal; k++){
var position = objects['**/position' + i + '_' + k][0];
positions[i].push(position);
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//segments lookat
function segmentsLookAt(){
for(var i = 0; i < segmentStreakTotal; i++){
for(var k = 0; k < segmentSegmentTotal; k++){
segments[i][k].transform.position = positions[i][k].transform.position.mul(segmentPositionRatios[i][k]);
segmentLineCubes[i][k].transform.scaleX = positions[i][k].transform.position.distance(positions[i][k+1].transform.position).mul(segmentScaleRatios[i][k]);
var position0_forwardVector = R.normalize(positions[i][k+1].transform.position.sub(positions[i][k].transform.position));
var position0_rotationAxis = position0_forwardVector.cross(vectorForward);
var position0_dot = position0_forwardVector.dot(vectorForward).add(1);
var position0_w0 = position0_dot.mul(-1);
var position0_x0 = position0_rotationAxis.x;
var position0_y0 = position0_rotationAxis.y;
var position0_z0 = position0_rotationAxis.z;
var position0QuatL = R.sqrt((position0_x0.mul(position0_x0)).add(position0_y0.mul(position0_y0)).add(position0_z0.mul(position0_z0)).add(position0_w0.mul(position0_w0)));
var position0QuatLL = R.val(1).div(position0QuatL);
var position0_w = position0_w0.mul(position0QuatLL);
var position0_x = position0_x0.mul(position0QuatLL);
var position0_y = position0_y0.mul(position0QuatLL);
var position0_z = position0_z0.mul(position0QuatLL);
//quaternion to euler using zyx
var position0_r11 = R.val(2).mul((position0_x.mul(position0_y).add(position0_w.mul(position0_z))));
var position0_r12 = (position0_w.mul(position0_w)).add(position0_x.mul(position0_x)).sub(position0_y.mul(position0_y)).sub(position0_z.mul(position0_z));
var position0_r21 = R.val(-2).mul((position0_x.mul(position0_z)).sub(position0_w.mul(position0_y)));
var position0_r31 = R.val(2).mul((position0_y.mul(position0_z)).add(position0_w.mul(position0_x)));
var position0_r32 = (position0_w.mul(position0_w)).sub(position0_x.mul(position0_x)).sub(position0_y.mul(position0_y)).add(position0_z.mul(position0_z));
var position0_heading = R.atan2(position0_r31, position0_r32);
var position0_asin_attitude = R.asin(position0_r21);
var position0_bank = R.atan2(position0_r11, position0_r12);
segments[i][k].transform.rotationX = position0_heading;
segments[i][k].transform.rotationY = position0_asin_attitude;
segments[i][k].transform.rotationZ = position0_bank;
if(i == 0 && k == 0){
segment0Connect.transform.position = segments[i][k].transform.position;
segment0Connect.transform.rotationX = segments[i][k].transform.rotationX;
segment0Connect.transform.rotationY = segments[i][k].transform.rotationY;
segment0Connect.transform.rotationZ = segments[i][k].transform.rotationZ;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//segments start/end positions
function segmentsPositions(){
var faceZOffset = 53.5;
var segmentXDirection = 0.025;
var segmentXOffset = 0;
var segmentYLength = 0.1;
var segmentZLength = 0.1;
for(var i = 0; i < segmentStreakTotal; i++){
for(var k = 0; k <= segmentSegmentTotal; k++){
var percentage = k/segmentSegmentTotal;
var bridgeToConnection0AttractionPerc = percentage;
var bridgeToConnection1AttractionPerc = R.vector(bridgeToConnection0AttractionPerc * bridgeToConnection0AttractionPerc, 0, bridgeToConnection0AttractionPerc * bridgeToConnection0AttractionPerc);
if(k == segmentSegmentTotal){
bridgeToConnection1AttractionPerc = 0;
}
var bridge = FT.face(0).cameraTransform.applyToPoint(facePosition.add(R.vector(segmentXOffset + (segmentXDirection * (k*k)), (Math.sin(Math.PI * percentage))*segmentYLength, k*segmentZLength))).add(R.vector(0,0,faceZOffset));
var bridgeToConnection0 = connection0.transform.position.sub(bridge);
var bridgeToConnection0Weight = bridge.add(bridgeToConnection0.mul(bridgeToConnection0AttractionPerc));
var bridgeToConnection1 = connection1.transform.position.sub(bridgeToConnection0Weight);
var bridgeToConnection1Weight = bridgeToConnection0Weight.add(bridgeToConnection1.mul(bridgeToConnection1AttractionPerc));
positions[i][k].transform.position = bridgeToConnection1Weight;
}
}
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// helplers
function getRandom(min, max) {
return Math.random() * (max - min) + min;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment