Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ cert.cer

!package.json
!package-lock.json
recording/
48 changes: 48 additions & 0 deletions js/scenes/campFire.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
This scene is an example of how to use procedural texture
to animate the shape of an object. In this case the object
is a waving flag. The noise function is used to animate
the position of each vertex of the flag geometry.
*/

import * as cg from "../render/core/cg.js";

export const init = async model => {
// Define a tall, thin grid for the flame
clay.defineMesh('flame', clay.createGrid(20, 30));

// fire layer holder
let fireLayers = [];
for (let i = 0; i < 6; i++){
let fire = model.add('flame').color(1, .4, 0); // Orange color
fire.angle = i * 30; // angle = 0, 60, 120.
fireLayers.push(fire);
}

// logs
model.txtrSrc(1, '../media/textures/log1.png');
let logs =[]
for (let i = 0; i < 6; i++){
let log =model.add('tubeX').color(0.4,0.3,0.3).txtr(1).scale(1.3,0.07,0.07).move(0,0,0);
log.angle = i * 30
//log.turnY(log.angle);
logs.push(log);
}

model.scale(0.3).move(0,4,0).animate(() => {
// Animate the flame by modifying its vertices
fireLayers.forEach(fire => {
fire.identity().turnY(fire.angle);
fire.setVertices((u,v) => {
return [0.8*(u-0.5)*(1-v),
2*v,
.3 * v * cg.noise(5*u,5*v-model.time*3,model.time)
];
});
});

// logs.forEach(log => {
// log.identity().turnY(log.angle);
// });
});
}
56 changes: 56 additions & 0 deletions js/scenes/car.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
Create and animate hierarchical joints.
*/
let speed = 0.8

export const init = async model => {

model.txtrSrc(1, '../media/textures/tire.png');

// CREATE NODES WITH NO SHAPES AS JOINTS FOR ANIMATION.
let carbody = model.add();

//wheel center joint
let wheelFLCenter = carbody.add();
let wheelFRCenter = carbody.add();
let wheelBLCenter = carbody.add();
let wheelBRCenter = carbody.add();

//wheel joint
let wheelFL = wheelFLCenter.add();
let wheelFR = wheelFRCenter.add();
let wheelBL = wheelBLCenter.add();
let wheelBR = wheelBRCenter.add();

// CREATE AND PLACE SHAPES THAT WILL MOVE WITH EACH JOINT.
// carboday
carbody.add('cube').scale(.8,.25,.4).move(0.8,1.5,-1).color(1,0,0);
//car cabin
carbody.add('cube').scale(.5,.2,.35).move(0.8,3.8,-1.2).color(1,1,1);;

// wheel centers
wheelFRCenter.move(1.2,0,0)
wheelBLCenter.move(0,0,-0.8)
wheelFLCenter.move(1.2,0,-0.8)

wheelBR.add('torusZ').scale(.18,.18,.2).txtr(1);;
wheelFR.add('torusZ').scale(.18,.18,.2).txtr(1);;
wheelBL.add('torusZ').scale(.18,.18,.2).txtr(1);;
wheelFL.add('torusZ').scale(.18,.18,.2).txtr(1);;

// ANIMATE THE JOINTS OVER TIME.
model.scale(0.8,0.8,0.8).move(-0.5,1.3,0).animate(() => {
carbody.identity()
.turnY(Math.sin(speed*model.time)*.7+.7);

wheelFL.identity()
.turnZ(Math.sin(speed*model.time)*.7+.7);
wheelFR.identity()
.turnZ(Math.sin(speed*model.time)*.7+.7);
wheelBL.identity()
.turnZ(Math.sin(speed*model.time)*.7+.7);
wheelBR.identity()
.turnZ(Math.sin(speed*model.time)*.7+.7);
});
}

83 changes: 83 additions & 0 deletions js/scenes/carDrive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
This is a very simple example of how to use the
inputEvents object.

When the scene is in XR mode, the x position of
the left controller controls the red component
of the cube's color, and the x position of the
right controller controls the blue component of
the cube's color.
*/
export const init = async model => {
// See what the inputEvents can do
// console.log(inputEvents);

model.txtrSrc(1, '../media/textures/tire.png');

let speed = 0;
let color = [1,0,0];
// CREATE NODES WITH NO SHAPES AS JOINTS FOR ANIMATION.
let carbody = model.add();

//wheel center joint
let wheelFLCenter = carbody.add();
let wheelFRCenter = carbody.add();
let wheelBLCenter = carbody.add();
let wheelBRCenter = carbody.add();

//wheel joint
let wheelFL = wheelFLCenter.add();
let wheelFR = wheelFRCenter.add();
let wheelBL = wheelBLCenter.add();
let wheelBR = wheelBRCenter.add();

// CREATE AND PLACE SHAPES THAT WILL MOVE WITH EACH JOINT.
// carboday
let chassis = carbody.add('cube').scale(.8,.25,.4).move(0.8,1.5,-1).color(color);
//car cabin
carbody.add('cube').scale(.5,.2,.35).move(0.8,3.8,-1.2).color(1,1,1);;

// wheel centers
wheelFRCenter.move(1.2,0,0)
wheelBLCenter.move(0,0,-0.8)
wheelFLCenter.move(1.2,0,-0.8)

wheelBR.add('torusZ').scale(.18,.18,.2).txtr(1);;
wheelFR.add('torusZ').scale(.18,.18,.2).txtr(1);;
wheelBL.add('torusZ').scale(.18,.18,.2).txtr(1);;
wheelFL.add('torusZ').scale(.18,.18,.2).txtr(1);;

// USING THE GLOBAL inputEvents OBJECT

inputEvents.onMove = hand => {
if (isXR()) {
if (hand == 'left'){
color[0] = inputEvents.pos(hand)[0] * .5 + .5;
color[1] = inputEvents.pos(hand)[2] * .5 + .5;
}
}
}

model.scale(0.3).move(-0.5,4.5,0).animate(() => {
if (inputEvents.isPressed('right')) {
speed += 0.005;
} else {
speed *= 0.95;
}

//.identity resets everything
carbody.identity().move(speed * 2, 0, 0);
chassis.color(color);

wheelFL.identity()
.turnZ(-speed*model.time*.7);
wheelFR.identity()
.turnZ(-speed*model.time*.7);
wheelBL.identity()
.turnZ(-speed*model.time*.7);
wheelBR.identity()
.turnZ(-speed*model.time*.7);

});
}

2 changes: 1 addition & 1 deletion js/scenes/joints.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

export const init = async model => {

// CREATE NODES WITH NO SHAPES AS JOINTS FOR ANIMATION.

let shoulder = model.add();
Expand Down
112 changes: 112 additions & 0 deletions js/scenes/master2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

// MASTER-OWNED MULTIPLAYER COMET:
// - CONTROL GOES TO THE MOST RECENT TRIGGER PRESS (master2 pattern).
// - COLOR FOLLOWS LEFT/RIGHT HAND INPUT (multiplayer1 pattern).
// - EVERYONE SEES THE SAME FADING TRAIL.

window.sharedState = {
time: 0,
pos: [0, 1.5, 0],
color: [1, 0.2, 0.2],
pulse: 0,
controller: {},
trail: [],
};

const TRAIL_COUNT = 16;

const colorForInput = (hand, id) => {
let hash = 0;
for (let i = 0; i < id.length; i++)
hash = (hash * 31 + id.charCodeAt(i)) % 997;
const n = (hash % 100) / 100;
return hand == 'left' ? [0.2 + 0.5 * n, 1, 0.2] : [0.2, 0.5 + 0.5 * n, 1];
};

export const init = async model => {
let comet = model.add('sphere');
let halo = model.add('ringY');
let trail = [];
for (let i = 0; i < TRAIL_COUNT; i++)
trail.push(model.add('sphere'));

inputEvents.onPress = hand => {
const id = hand + clientID;
sharedState.controller[id] = {
pos: [...inputEvents.pos(hand)],
time: sharedState.time,
color: colorForInput(hand, id),
};
server.broadcastGlobal('sharedState');
};

inputEvents.onDrag = hand => {
const id = hand + clientID;
if (sharedState.controller[id]) {
sharedState.controller[id].pos = [...inputEvents.pos(hand)];
server.broadcastGlobal('sharedState');
}
};

inputEvents.onRelease = hand => {
delete sharedState.controller[hand + clientID];
server.broadcastGlobal('sharedState');
};

model.animate(() => {
sharedState = server.synchronize('sharedState');

if (clientID == clients[0]) {
sharedState.time = model.time;

let newest = null;
let newestTime = -1;
for (let id in sharedState.controller)
if (sharedState.controller[id].time > newestTime) {
newestTime = sharedState.controller[id].time;
newest = sharedState.controller[id];
}

if (newest) {
sharedState.pos = [...newest.pos];
sharedState.color = [...newest.color];
sharedState.pulse = 1;
sharedState.trail.unshift({
pos: [...sharedState.pos],
color: [...sharedState.color],
time: sharedState.time,
});
} else {
sharedState.pos = [
sharedState.pos[0],
1.45 + 0.1 * Math.sin(2 * sharedState.time),
sharedState.pos[2],
];
sharedState.pulse *= 0.95;
}

while (sharedState.trail.length > TRAIL_COUNT)
sharedState.trail.pop();
sharedState.trail = sharedState.trail.filter(p => sharedState.time - p.time < 2.5);
server.broadcastGlobal('sharedState');
}

const pulse = 1 + 0.25 * sharedState.pulse * Math.abs(Math.sin(10 * sharedState.time));
comet.identity().move(sharedState.pos).scale(0.07 * pulse).color(...sharedState.color);
halo.identity().move(sharedState.pos).turnY(2 * sharedState.time).scale(0.11).color(...sharedState.color);

for (let i = 0; i < TRAIL_COUNT; i++) {
const p = sharedState.trail[i];
if (!p) {
trail[i].identity().scale(0);
continue;
}
const age = Math.max(0, sharedState.time - p.time);
const fade = Math.max(0, 1 - age / 2.5);
trail[i].identity()
.move(p.pos)
.scale(0.05 * fade)
.color(p.color[0] * fade, p.color[1] * fade, p.color[2] * fade);
}
});
};
10 changes: 10 additions & 0 deletions js/scenes/scenes.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ export default () => {
{ name: "headGaze" , path: "./headGaze.js" , public: true },
{ name: "reading" , path: "./reading.js" , public: true },
{ name: "parse2" , path: "./parse2.js" , public: true },
{ name: "car" , path: "./car.js" , public: true },
{ name: "carDrive" , path: "./carDrive.js" , public: true },
{ name: "campFire" , path: "./campFire.js" , public: true },
{ name: "textHW" , path: "./textHW.js" , public: true },
{ name: "master2" , path: "./master2.js" , public: true },
{ name: "car" , path: "./car.js" , public: true },
{ name: "carDrive" , path: "./carDrive.js" , public: true },
{ name: "campFire" , path: "./campFire.js" , public: true },
{ name: "textHW" , path: "./textHW.js" , public: true },
{ name: "master2" , path: "./master2.js" , public: true }
]
};
}
Expand Down
Loading