Merge branch 'master' of https://github.com/highfidelity/hifi into stack-manager

This commit is contained in:
Leonardo Murillo 2015-11-23 14:22:05 -06:00
commit ec6be93938
20 changed files with 246 additions and 752 deletions

View file

@ -223,7 +223,6 @@ void Agent::executeScript() {
AvatarData::fromFrame(frame->data, *scriptedAvatar);
});
using namespace recording;
static const FrameType AUDIO_FRAME_TYPE = Frame::registerFrameType(AudioConstants::AUDIO_FRAME_NAME);
Frame::registerFrameHandler(AUDIO_FRAME_TYPE, [this, &scriptedAvatar](Frame::ConstPointer frame) {
@ -280,6 +279,11 @@ void Agent::executeScript() {
setFinished(true);
}
QUuid Agent::getSessionUUID() const {
return DependencyManager::get<NodeList>()->getSessionUUID();
}
void Agent::setIsAvatar(bool isAvatar) {
_isAvatar = isAvatar;

View file

@ -18,6 +18,7 @@
#include <QtScript/QScriptEngine>
#include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QUuid>
#include <EntityEditPacketSender.h>
#include <EntityTree.h>
@ -35,6 +36,8 @@ class Agent : public ThreadedAssignment {
Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound)
Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream)
Q_PROPERTY(float lastReceivedAudioLoudness READ getLastReceivedAudioLoudness)
Q_PROPERTY(QUuid sessionUUID READ getSessionUUID)
public:
Agent(NLPacket& packet);
@ -47,6 +50,7 @@ public:
void setIsListeningToAudioStream(bool isListeningToAudioStream) { _isListeningToAudioStream = isListeningToAudioStream; }
float getLastReceivedAudioLoudness() const { return _lastReceivedAudioLoudness; }
QUuid getSessionUUID() const;
virtual void aboutToFinish();

View file

@ -271,7 +271,7 @@ function loadBirds(howMany) {
dimensions: { x: BIRD_SIZE, y: BIRD_SIZE, z: BIRD_SIZE },
gravity: { x: 0, y: BIRD_GRAVITY, z: 0 },
velocity: { x: 0, y: -0.1, z: 0 },
linearDamping: LINEAR_DAMPING,
damping: LINEAR_DAMPING,
collisionsWillMove: true,
lifetime: STARTING_LIFETIME,
color: colors[whichBird]

View file

@ -1,673 +0,0 @@
//
// bot_procedural.js
// hifi
//
// Created by Ben Arnold on 7/29/2013
//
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
// This is an example script that demonstrates an NPC avatar.
//
//
//For procedural walk animation
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
Script.include(HIFI_PUBLIC_BUCKET + "scripts/acScripts/proceduralAnimationAPI.js");
var procAnimAPI = new ProcAnimAPI();
function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}
function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function printVector(string, vector) {
print(string + " " + vector.x + ", " + vector.y + ", " + vector.z);
}
var CHANCE_OF_MOVING = 0.005;
var CHANCE_OF_SOUND = 0.005;
var CHANCE_OF_HEAD_TURNING = 0.01;
var CHANCE_OF_BIG_MOVE = 1.0;
var isMoving = false;
var isTurningHead = false;
var isPlayingAudio = false;
var X_MIN = 0.50;
var X_MAX = 15.60;
var Z_MIN = 0.50;
var Z_MAX = 15.10;
var Y_FEET = 0.0;
var AVATAR_PELVIS_HEIGHT = 0.84;
var Y_PELVIS = Y_FEET + AVATAR_PELVIS_HEIGHT;
var MAX_PELVIS_DELTA = 2.5;
var MOVE_RANGE_SMALL = 3.0;
var MOVE_RANGE_BIG = 10.0;
var TURN_RANGE = 70.0;
var STOP_TOLERANCE = 0.05;
var MOVE_RATE = 0.05;
var TURN_RATE = 0.2;
var HEAD_TURN_RATE = 0.05;
var PITCH_RANGE = 15.0;
var YAW_RANGE = 35.0;
var firstPosition = { x: getRandomFloat(X_MIN, X_MAX), y: Y_PELVIS, z: getRandomFloat(Z_MIN, Z_MAX) };
var targetPosition = { x: 0, y: 0, z: 0 };
var targetOrientation = { x: 0, y: 0, z: 0, w: 0 };
var currentOrientation = { x: 0, y: 0, z: 0, w: 0 };
var targetHeadPitch = 0.0;
var targetHeadYaw = 0.0;
var basePelvisHeight = 0.0;
var pelvisOscillatorPosition = 0.0;
var pelvisOscillatorVelocity = 0.0;
function clamp(val, min, max){
return Math.max(min, Math.min(max, val))
}
//Array of all valid bot numbers
var validBotNumbers = [];
// right now we only use bot 63, since many other bots have messed up skeletons and LOD issues
var botNumber = 63;//getRandomInt(0, 99);
var newFaceFilePrefix = "ron";
var newBodyFilePrefix = "bot" + botNumber;
// set the face model fst using the bot number
// there is no need to change the body model - we're using the default
Avatar.faceModelURL = HIFI_PUBLIC_BUCKET + "meshes/" + newFaceFilePrefix + ".fst";
Avatar.skeletonModelURL = HIFI_PUBLIC_BUCKET + "meshes/" + newBodyFilePrefix + "_a.fst";
Avatar.billboardURL = HIFI_PUBLIC_BUCKET + "meshes/billboards/bot" + botNumber + ".png";
Agent.isAvatar = true;
Agent.isListeningToAudioStream = true;
// change the avatar's position to the random one
Avatar.position = firstPosition;
basePelvisHeight = firstPosition.y;
printVector("New dancer, position = ", Avatar.position);
function loadSounds() {
var sound_filenames = ["AB1.raw", "Anchorman2.raw", "B1.raw", "B1.raw", "Bale1.raw", "Bandcamp.raw",
"Big1.raw", "Big2.raw", "Brian1.raw", "Buster1.raw", "CES1.raw", "CES2.raw", "CES3.raw", "CES4.raw",
"Carrie1.raw", "Carrie3.raw", "Charlotte1.raw", "EN1.raw", "EN2.raw", "EN3.raw", "Eugene1.raw", "Francesco1.raw",
"Italian1.raw", "Japanese1.raw", "Leigh1.raw", "Lucille1.raw", "Lucille2.raw", "MeanGirls.raw", "Murray2.raw",
"Nigel1.raw", "PennyLane.raw", "Pitt1.raw", "Ricardo.raw", "SN.raw", "Sake1.raw", "Samantha1.raw", "Samantha2.raw",
"Spicoli1.raw", "Supernatural.raw", "Swearengen1.raw", "TheDude.raw", "Tony.raw", "Triumph1.raw", "Uma1.raw",
"Walken1.raw", "Walken2.raw", "Z1.raw", "Z2.raw"
];
var footstep_filenames = ["FootstepW2Left-12db.wav", "FootstepW2Right-12db.wav", "FootstepW3Left-12db.wav", "FootstepW3Right-12db.wav",
"FootstepW5Left-12db.wav", "FootstepW5Right-12db.wav"];
var SOUND_BASE_URL = HIFI_PUBLIC_BUCKET + "sounds/Cocktail+Party+Snippets/Raws/";
var FOOTSTEP_BASE_URL = HIFI_PUBLIC_BUCKET + "sounds/Footsteps/";
for (var i = 0; i < sound_filenames.length; i++) {
sounds.push(SoundCache.getSound(SOUND_BASE_URL + sound_filenames[i]));
}
for (var i = 0; i < footstep_filenames.length; i++) {
footstepSounds.push(SoundCache.getSound(FOOTSTEP_BASE_URL + footstep_filenames[i]));
}
}
var sounds = [];
var footstepSounds = [];
loadSounds();
function playRandomSound() {
if (!Agent.isPlayingAvatarSound) {
var whichSound = Math.floor((Math.random() * sounds.length));
Agent.playAvatarSound(sounds[whichSound]);
}
}
function playRandomFootstepSound() {
var whichSound = Math.floor((Math.random() * footstepSounds.length));
Audio.playSound(footstepSounds[whichSound], {
position: Avatar.position,
volume: 1.0
});
}
// ************************************ Facial Animation **********************************
var allBlendShapes = [];
var targetBlendCoefficient = [];
var currentBlendCoefficient = [];
//Blendshape constructor
function addBlendshapeToPose(pose, shapeIndex, val) {
var index = pose.blendShapes.length;
pose.blendShapes[index] = {shapeIndex: shapeIndex, val: val };
}
//The mood of the avatar, determines face. 0 = happy, 1 = angry, 2 = sad.
//Randomly pick avatar mood. 80% happy, 10% mad 10% sad
var randMood = Math.floor(Math.random() * 11);
var avatarMood;
if (randMood == 0) {
avatarMood = 1;
} else if (randMood == 2) {
avatarMood = 2;
} else {
avatarMood = 0;
}
var currentExpression = -1;
//Face pose constructor
var happyPoses = [];
happyPoses[0] = {blendShapes: []};
addBlendshapeToPose(happyPoses[0], 28, 0.7); //MouthSmile_L
addBlendshapeToPose(happyPoses[0], 29, 0.7); //MouthSmile_R
happyPoses[1] = {blendShapes: []};
addBlendshapeToPose(happyPoses[1], 28, 1.0); //MouthSmile_L
addBlendshapeToPose(happyPoses[1], 29, 1.0); //MouthSmile_R
addBlendshapeToPose(happyPoses[1], 21, 0.2); //JawOpen
happyPoses[2] = {blendShapes: []};
addBlendshapeToPose(happyPoses[2], 28, 1.0); //MouthSmile_L
addBlendshapeToPose(happyPoses[2], 29, 1.0); //MouthSmile_R
addBlendshapeToPose(happyPoses[2], 21, 0.5); //JawOpen
addBlendshapeToPose(happyPoses[2], 46, 1.0); //CheekSquint_L
addBlendshapeToPose(happyPoses[2], 47, 1.0); //CheekSquint_R
addBlendshapeToPose(happyPoses[2], 17, 1.0); //BrowsU_L
addBlendshapeToPose(happyPoses[2], 18, 1.0); //BrowsU_R
var angryPoses = [];
angryPoses[0] = {blendShapes: []};
addBlendshapeToPose(angryPoses[0], 26, 0.6); //MouthFrown_L
addBlendshapeToPose(angryPoses[0], 27, 0.6); //MouthFrown_R
addBlendshapeToPose(angryPoses[0], 14, 0.6); //BrowsD_L
addBlendshapeToPose(angryPoses[0], 15, 0.6); //BrowsD_R
angryPoses[1] = {blendShapes: []};
addBlendshapeToPose(angryPoses[1], 26, 0.9); //MouthFrown_L
addBlendshapeToPose(angryPoses[1], 27, 0.9); //MouthFrown_R
addBlendshapeToPose(angryPoses[1], 14, 0.9); //BrowsD_L
addBlendshapeToPose(angryPoses[1], 15, 0.9); //BrowsD_R
angryPoses[2] = {blendShapes: []};
addBlendshapeToPose(angryPoses[2], 26, 1.0); //MouthFrown_L
addBlendshapeToPose(angryPoses[2], 27, 1.0); //MouthFrown_R
addBlendshapeToPose(angryPoses[2], 14, 1.0); //BrowsD_L
addBlendshapeToPose(angryPoses[2], 15, 1.0); //BrowsD_R
addBlendshapeToPose(angryPoses[2], 21, 0.5); //JawOpen
addBlendshapeToPose(angryPoses[2], 46, 1.0); //CheekSquint_L
addBlendshapeToPose(angryPoses[2], 47, 1.0); //CheekSquint_R
var sadPoses = [];
sadPoses[0] = {blendShapes: []};
addBlendshapeToPose(sadPoses[0], 26, 0.6); //MouthFrown_L
addBlendshapeToPose(sadPoses[0], 27, 0.6); //MouthFrown_R
addBlendshapeToPose(sadPoses[0], 16, 0.2); //BrowsU_C
addBlendshapeToPose(sadPoses[0], 2, 0.6); //EyeSquint_L
addBlendshapeToPose(sadPoses[0], 3, 0.6); //EyeSquint_R
sadPoses[1] = {blendShapes: []};
addBlendshapeToPose(sadPoses[1], 26, 0.9); //MouthFrown_L
addBlendshapeToPose(sadPoses[1], 27, 0.9); //MouthFrown_R
addBlendshapeToPose(sadPoses[1], 16, 0.6); //BrowsU_C
addBlendshapeToPose(sadPoses[1], 2, 0.9); //EyeSquint_L
addBlendshapeToPose(sadPoses[1], 3, 0.9); //EyeSquint_R
sadPoses[2] = {blendShapes: []};
addBlendshapeToPose(sadPoses[2], 26, 1.0); //MouthFrown_L
addBlendshapeToPose(sadPoses[2], 27, 1.0); //MouthFrown_R
addBlendshapeToPose(sadPoses[2], 16, 0.1); //BrowsU_C
addBlendshapeToPose(sadPoses[2], 2, 1.0); //EyeSquint_L
addBlendshapeToPose(sadPoses[2], 3, 1.0); //EyeSquint_R
addBlendshapeToPose(sadPoses[2], 21, 0.3); //JawOpen
var facePoses = [];
facePoses[0] = happyPoses;
facePoses[1] = angryPoses;
facePoses[2] = sadPoses;
function addBlendShape(s) {
allBlendShapes[allBlendShapes.length] = s;
}
//It is imperative that the following blendshapes are all present and are in the correct order
addBlendShape("EyeBlink_L"); //0
addBlendShape("EyeBlink_R"); //1
addBlendShape("EyeSquint_L"); //2
addBlendShape("EyeSquint_R"); //3
addBlendShape("EyeDown_L"); //4
addBlendShape("EyeDown_R"); //5
addBlendShape("EyeIn_L"); //6
addBlendShape("EyeIn_R"); //7
addBlendShape("EyeOpen_L"); //8
addBlendShape("EyeOpen_R"); //9
addBlendShape("EyeOut_L"); //10
addBlendShape("EyeOut_R"); //11
addBlendShape("EyeUp_L"); //12
addBlendShape("EyeUp_R"); //13
addBlendShape("BrowsD_L"); //14
addBlendShape("BrowsD_R"); //15
addBlendShape("BrowsU_C"); //16
addBlendShape("BrowsU_L"); //17
addBlendShape("BrowsU_R"); //18
addBlendShape("JawFwd"); //19
addBlendShape("JawLeft"); //20
addBlendShape("JawOpen"); //21
addBlendShape("JawChew"); //22
addBlendShape("JawRight"); //23
addBlendShape("MouthLeft"); //24
addBlendShape("MouthRight"); //25
addBlendShape("MouthFrown_L"); //26
addBlendShape("MouthFrown_R"); //27
addBlendShape("MouthSmile_L"); //28
addBlendShape("MouthSmile_R"); //29
addBlendShape("MouthDimple_L"); //30
addBlendShape("MouthDimple_R"); //31
addBlendShape("LipsStretch_L"); //32
addBlendShape("LipsStretch_R"); //33
addBlendShape("LipsUpperClose"); //34
addBlendShape("LipsLowerClose"); //35
addBlendShape("LipsUpperUp"); //36
addBlendShape("LipsLowerDown"); //37
addBlendShape("LipsUpperOpen"); //38
addBlendShape("LipsLowerOpen"); //39
addBlendShape("LipsFunnel"); //40
addBlendShape("LipsPucker"); //41
addBlendShape("ChinLowerRaise"); //42
addBlendShape("ChinUpperRaise"); //43
addBlendShape("Sneer"); //44
addBlendShape("Puff"); //45
addBlendShape("CheekSquint_L"); //46
addBlendShape("CheekSquint_R"); //47
for (var i = 0; i < allBlendShapes.length; i++) {
targetBlendCoefficient[i] = 0;
currentBlendCoefficient[i] = 0;
}
function setRandomExpression() {
//Clear all expression data for current expression
if (currentExpression != -1) {
var expression = facePoses[avatarMood][currentExpression];
for (var i = 0; i < expression.blendShapes.length; i++) {
targetBlendCoefficient[expression.blendShapes[i].shapeIndex] = 0.0;
}
}
//Get a new current expression
currentExpression = Math.floor(Math.random() * facePoses[avatarMood].length);
var expression = facePoses[avatarMood][currentExpression];
for (var i = 0; i < expression.blendShapes.length; i++) {
targetBlendCoefficient[expression.blendShapes[i].shapeIndex] = expression.blendShapes[i].val;
}
}
var expressionChangeSpeed = 0.1;
function updateBlendShapes(deltaTime) {
for (var i = 0; i < allBlendShapes.length; i++) {
currentBlendCoefficient[i] += (targetBlendCoefficient[i] - currentBlendCoefficient[i]) * expressionChangeSpeed;
Avatar.setBlendshape(allBlendShapes[i], currentBlendCoefficient[i]);
}
}
var BLINK_SPEED = 0.15;
var CHANCE_TO_BLINK = 0.0025;
var MAX_BLINK = 0.85;
var blink = 0.0;
var isBlinking = false;
function updateBlinking(deltaTime) {
if (isBlinking == false) {
if (Math.random() < CHANCE_TO_BLINK) {
isBlinking = true;
} else {
blink -= BLINK_SPEED;
if (blink < 0.0) blink = 0.0;
}
} else {
blink += BLINK_SPEED;
if (blink > MAX_BLINK) {
blink = MAX_BLINK;
isBlinking = false;
}
}
currentBlendCoefficient[0] = blink;
currentBlendCoefficient[1] = blink;
targetBlendCoefficient[0] = blink;
targetBlendCoefficient[1] = blink;
}
// *************************************************************************************
//Procedural walk animation using two keyframes
//We use a separate array for front and back joints
//Pitch, yaw, and roll for the joints
var rightAngles = [];
var leftAngles = [];
//for non mirrored joints such as the spine
var middleAngles = [];
//Actual joint mappings
var SHOULDER_JOINT_NUMBER = 15;
var ELBOW_JOINT_NUMBER = 16;
var JOINT_R_HIP = 1;
var JOINT_R_KNEE = 2;
var JOINT_L_HIP = 6;
var JOINT_L_KNEE = 7;
var JOINT_R_ARM = 15;
var JOINT_R_FOREARM = 16;
var JOINT_L_ARM = 39;
var JOINT_L_FOREARM = 40;
var JOINT_SPINE = 11;
var JOINT_R_FOOT = 3;
var JOINT_L_FOOT = 8;
var JOINT_R_TOE = 4;
var JOINT_L_TOE = 9;
// ******************************* Animation Is Defined Below *************************************
var NUM_FRAMES = 2;
for (var i = 0; i < NUM_FRAMES; i++) {
rightAngles[i] = [];
leftAngles[i] = [];
middleAngles[i] = [];
}
//Joint order for actual joint mappings, should be interleaved R,L,R,L,...S,S,S for R = right, L = left, S = single
var JOINT_ORDER = [];
//*** right / left joints ***
var HIP = 0;
JOINT_ORDER.push(JOINT_R_HIP);
JOINT_ORDER.push(JOINT_L_HIP);
var KNEE = 1;
JOINT_ORDER.push(JOINT_R_KNEE);
JOINT_ORDER.push(JOINT_L_KNEE);
var ARM = 2;
JOINT_ORDER.push(JOINT_R_ARM);
JOINT_ORDER.push(JOINT_L_ARM);
var FOREARM = 3;
JOINT_ORDER.push(JOINT_R_FOREARM);
JOINT_ORDER.push(JOINT_L_FOREARM);
var FOOT = 4;
JOINT_ORDER.push(JOINT_R_FOOT);
JOINT_ORDER.push(JOINT_L_FOOT);
var TOE = 5;
JOINT_ORDER.push(JOINT_R_TOE);
JOINT_ORDER.push(JOINT_L_TOE);
//*** middle joints ***
var SPINE = 0;
JOINT_ORDER.push(JOINT_SPINE);
//We have to store the angles so we can invert yaw and roll when making the animation
//symmetrical
//Front refers to leg, not arm.
//Legs Extending
rightAngles[0][HIP] = [30.0, 0.0, 8.0];
rightAngles[0][KNEE] = [-15.0, 0.0, 0.0];
rightAngles[0][ARM] = [85.0, -25.0, 0.0];
rightAngles[0][FOREARM] = [0.0, 0.0, -15.0];
rightAngles[0][FOOT] = [0.0, 0.0, 0.0];
rightAngles[0][TOE] = [0.0, 0.0, 0.0];
leftAngles[0][HIP] = [-15, 0.0, 8.0];
leftAngles[0][KNEE] = [-26, 0.0, 0.0];
leftAngles[0][ARM] = [85.0, 20.0, 0.0];
leftAngles[0][FOREARM] = [10.0, 0.0, -25.0];
leftAngles[0][FOOT] = [-13.0, 0.0, 0.0];
leftAngles[0][TOE] = [34.0, 0.0, 0.0];
middleAngles[0][SPINE] = [0.0, -15.0, 5.0];
//Legs Passing
rightAngles[1][HIP] = [6.0, 0.0, 8.0];
rightAngles[1][KNEE] = [-12.0, 0.0, 0.0];
rightAngles[1][ARM] = [85.0, 0.0, 0.0];
rightAngles[1][FOREARM] = [0.0, 0.0, -15.0];
rightAngles[1][FOOT] = [6.0, -8.0, 0.0];
rightAngles[1][TOE] = [0.0, 0.0, 0.0];
leftAngles[1][HIP] = [10.0, 0.0, 8.0];
leftAngles[1][KNEE] = [-60.0, 0.0, 0.0];
leftAngles[1][ARM] = [85.0, 0.0, 0.0];
leftAngles[1][FOREARM] = [0.0, 0.0, -15.0];
leftAngles[1][FOOT] = [0.0, 0.0, 0.0];
leftAngles[1][TOE] = [0.0, 0.0, 0.0];
middleAngles[1][SPINE] = [0.0, 0.0, 0.0];
//Actual keyframes for the animation
var walkKeyFrames = procAnimAPI.generateKeyframes(rightAngles, leftAngles, middleAngles, NUM_FRAMES);
// ******************************* Animation Is Defined Above *************************************
// ********************************** Standing Key Frame ******************************************
//We don't have to do any mirroring or anything, since this is just a single pose.
var rightQuats = [];
var leftQuats = [];
var middleQuats = [];
rightQuats[HIP] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 7.0);
rightQuats[KNEE] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0);
rightQuats[ARM] = Quat.fromPitchYawRollDegrees(85.0, 0.0, 0.0);
rightQuats[FOREARM] = Quat.fromPitchYawRollDegrees(0.0, 0.0, -10.0);
rightQuats[FOOT] = Quat.fromPitchYawRollDegrees(0.0, -8.0, 0.0);
rightQuats[TOE] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0);
leftQuats[HIP] = Quat.fromPitchYawRollDegrees(0, 0.0, -7.0);
leftQuats[KNEE] = Quat.fromPitchYawRollDegrees(0, 0.0, 0.0);
leftQuats[ARM] = Quat.fromPitchYawRollDegrees(85.0, 0.0, 0.0);
leftQuats[FOREARM] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 10.0);
leftQuats[FOOT] = Quat.fromPitchYawRollDegrees(0.0, 8.0, 0.0);
leftQuats[TOE] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0);
middleQuats[SPINE] = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0);
var standingKeyFrame = new procAnimAPI.KeyFrame(rightQuats, leftQuats, middleQuats);
// ************************************************************************************************
var currentFrame = 0;
var walkTime = 0.0;
var walkWheelRadius = 0.5;
var walkWheelRate = 2.0 * 3.141592 * walkWheelRadius / 8.0;
var avatarAcceleration = 0.75;
var avatarVelocity = 0.0;
var avatarMaxVelocity = 1.4;
function handleAnimation(deltaTime) {
updateBlinking(deltaTime);
updateBlendShapes(deltaTime);
if (Math.random() < 0.01) {
setRandomExpression();
}
if (avatarVelocity == 0.0) {
walkTime = 0.0;
currentFrame = 0;
} else {
walkTime += avatarVelocity * deltaTime;
if (walkTime > walkWheelRate) {
walkTime = 0.0;
currentFrame++;
if (currentFrame % 2 == 1) {
playRandomFootstepSound();
}
if (currentFrame > 3) {
currentFrame = 0;
}
}
}
var frame = walkKeyFrames[currentFrame];
var walkInterp = walkTime / walkWheelRate;
var animInterp = avatarVelocity / (avatarMaxVelocity / 1.3);
if (animInterp > 1.0) animInterp = 1.0;
for (var i = 0; i < JOINT_ORDER.length; i++) {
var walkJoint = procAnimAPI.deCasteljau(frame.rotations[i], frame.nextFrame.rotations[i], frame.controlPoints[i][0], frame.controlPoints[i][1], walkInterp);
var standJoint = standingKeyFrame.rotations[i];
var finalJoint = Quat.mix(standJoint, walkJoint, animInterp);
Avatar.setJointData(JOINT_ORDER[i], finalJoint);
}
}
function jumpWithLoudness(deltaTime) {
// potentially change pelvis height depending on trailing average loudness
pelvisOscillatorVelocity += deltaTime * Agent.lastReceivedAudioLoudness * 700.0 ;
pelvisOscillatorVelocity -= pelvisOscillatorPosition * 0.75;
pelvisOscillatorVelocity *= 0.97;
pelvisOscillatorPosition += deltaTime * pelvisOscillatorVelocity;
Avatar.headPitch = pelvisOscillatorPosition * 60.0;
var pelvisPosition = Avatar.position;
pelvisPosition.y = (Y_PELVIS - 0.35) + pelvisOscillatorPosition;
if (pelvisPosition.y < Y_PELVIS) {
pelvisPosition.y = Y_PELVIS;
} else if (pelvisPosition.y > Y_PELVIS + 1.0) {
pelvisPosition.y = Y_PELVIS + 1.0;
}
Avatar.position = pelvisPosition;
}
var forcedMove = false;
var wasMovingLastFrame = false;
function handleHeadTurn() {
if (!isTurningHead && (Math.random() < CHANCE_OF_HEAD_TURNING)) {
targetHeadPitch = getRandomFloat(-PITCH_RANGE, PITCH_RANGE);
targetHeadYaw = getRandomFloat(-YAW_RANGE, YAW_RANGE);
isTurningHead = true;
} else {
Avatar.headPitch = Avatar.headPitch + (targetHeadPitch - Avatar.headPitch) * HEAD_TURN_RATE;
Avatar.headYaw = Avatar.headYaw + (targetHeadYaw - Avatar.headYaw) * HEAD_TURN_RATE;
if (Math.abs(Avatar.headPitch - targetHeadPitch) < STOP_TOLERANCE &&
Math.abs(Avatar.headYaw - targetHeadYaw) < STOP_TOLERANCE) {
isTurningHead = false;
}
}
}
function stopWalking() {
avatarVelocity = 0.0;
isMoving = false;
}
var MAX_ATTEMPTS = 40;
function handleWalking(deltaTime) {
if (forcedMove || (!isMoving && Math.random() < CHANCE_OF_MOVING)) {
// Set new target location
var moveRange;
if (Math.random() < CHANCE_OF_BIG_MOVE) {
moveRange = MOVE_RANGE_BIG;
} else {
moveRange = MOVE_RANGE_SMALL;
}
//Keep trying new orientations if the desired target location is out of bounds
var attempts = 0;
do {
targetOrientation = Quat.multiply(Avatar.orientation, Quat.angleAxis(getRandomFloat(-TURN_RANGE, TURN_RANGE), { x:0, y:1, z:0 }));
var front = Quat.getFront(targetOrientation);
targetPosition = Vec3.sum(Avatar.position, Vec3.multiply(front, getRandomFloat(0.0, moveRange)));
}
while ((targetPosition.x < X_MIN || targetPosition.x > X_MAX || targetPosition.z < Z_MIN || targetPosition.z > Z_MAX)
&& attempts < MAX_ATTEMPTS);
targetPosition.x = clamp(targetPosition.x, X_MIN, X_MAX);
targetPosition.z = clamp(targetPosition.z, Z_MIN, Z_MAX);
targetPosition.y = Y_PELVIS;
wasMovingLastFrame = true;
isMoving = true;
forcedMove = false;
} else if (isMoving) {
var targetVector = Vec3.subtract(targetPosition, Avatar.position);
var distance = Vec3.length(targetVector);
if (distance <= avatarVelocity * deltaTime) {
Avatar.position = targetPosition;
stopWalking();
} else {
var direction = Vec3.normalize(targetVector);
//Figure out if we should be slowing down
var t = avatarVelocity / avatarAcceleration;
var d = (avatarVelocity / 2.0) * t;
if (distance < d) {
avatarVelocity -= avatarAcceleration * deltaTime;
if (avatarVelocity <= 0) {
stopWalking();
}
} else {
avatarVelocity += avatarAcceleration * deltaTime;
if (avatarVelocity > avatarMaxVelocity) avatarVelocity = avatarMaxVelocity;
}
Avatar.position = Vec3.sum(Avatar.position, Vec3.multiply(direction, avatarVelocity * deltaTime));
Avatar.orientation = Quat.mix(Avatar.orientation, targetOrientation, TURN_RATE);
wasMovingLastFrame = true;
}
}
}
function handleTalking() {
if (Math.random() < CHANCE_OF_SOUND) {
playRandomSound();
}
}
function changePelvisHeight(newHeight) {
var newPosition = Avatar.position;
newPosition.y = newHeight;
Avatar.position = newPosition;
}
function updateBehavior(deltaTime) {
if (AvatarList.containsAvatarWithDisplayName("mrdj")) {
if (wasMovingLastFrame) {
isMoving = false;
}
// we have a DJ, shouldn't we be dancing?
jumpWithLoudness(deltaTime);
} else {
// no DJ, let's just chill on the dancefloor - randomly walking and talking
handleHeadTurn();
handleAnimation(deltaTime);
handleWalking(deltaTime);
handleTalking();
}
}
Script.update.connect(updateBehavior);

View file

@ -10,7 +10,7 @@
//
// Set the following variables to the values needed
var channel = "PlaybackChannel1";
var commandChannel = "com.highfidelity.PlaybackChannel1";
var clip_url = null;
var playFromCurrentLocation = true;
var useDisplayName = true;
@ -18,7 +18,9 @@ var useAttachments = true;
var useAvatarModel = true;
// ID of the agent. Two agents can't have the same ID.
var id = 0;
var announceIDChannel = "com.highfidelity.playbackAgent.announceID";
var UNKNOWN_AGENT_ID = -2;
var id = UNKNOWN_AGENT_ID; // unknown until aknowledged
// Set position/orientation/scale here if playFromCurrentLocation is true
Avatar.position = { x:0, y: 0, z: 0 };
@ -45,7 +47,6 @@ Recording.setPlayerUseHeadModel(false);
Recording.setPlayerUseSkeletonModel(useAvatarModel);
function getAction(channel, message, senderID) {
if(subscribed) {
var command = JSON.parse(message);
print("I'm the agent " + id + " and I received this: ID: " + command.id_key + " Action: " + command.action_key + " URL: " + command.clip_url_key);
@ -53,24 +54,8 @@ function getAction(channel, message, senderID) {
if (command.id_key == id || command.id_key == -1) {
if (command.action_key === 6) {
clip_url = command.clip_url_key;
// If the id is -1 (broadcast) and the action is 6, in the url should be the performance file
// with all the clips recorded in a session (not just the single clip url).
// It has to be computed here in order to retrieve the url for the single agent.
// Checking the id we can assign the correct url to the correct agent.
if (command.id_key == -1) {
Assets.downloadData(clip_url, function (data) {
var myJSONObject = JSON.parse(data);
var hash = myJSONObject.results[id].hashATP;
});
Assets.downloadData(hash, function (data) {
clip_url = JSON.parse(data);
});
}
}
action = command.action_key;
print("That command was for me!");
print("My clip is: " + clip_url);
@ -139,17 +124,41 @@ function getAction(channel, message, senderID) {
}
function update(deltaTime) {
function update(deltaTime) {
totalTime += deltaTime;
if (totalTime > WAIT_FOR_AUDIO_MIXER && !subscribed) {
Messages.subscribe(channel);
subscribed = true;
print("I'm the agent and I am ready to receive!")
if (totalTime > WAIT_FOR_AUDIO_MIXER) {
if (!subscribed) {
Messages.subscribe(commandChannel); // command channel
Messages.subscribe(announceIDChannel); // id announce channel
subscribed = true;
print("I'm the agent and I am ready to receive!");
}
if (subscribed && id == UNKNOWN_AGENT_ID) {
print("sending ready, id:" + id);
Messages.sendMessage(announceIDChannel, "ready");
}
}
}
Script.update.connect(update);
Messages.messageReceived.connect(getAction);
Messages.messageReceived.connect(function (channel, message, senderID) {
if (channel == announceIDChannel && message != "ready") {
// If I don't yet know if my ID has been recieved, then check to see if the master has acknowledged me
if (id == UNKNOWN_AGENT_ID) {
var parts = message.split(".");
var agentID = parts[0];
var agentIndex = parts[1];
if (agentID == Agent.sessionUUID) {
id = agentIndex;
Messages.unsubscribe(announceIDChannel); // id announce channel
}
}
}
if (channel == commandChannel) {
getAction(channel, message, senderID);
}
});
Script.update.connect(update);

View file

@ -14,11 +14,16 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var ac_number = 1; // This is the default number of ACs. Their ID need to be unique and between 0 (included) and ac_number (excluded)
var names = new Array(); // It is possible to specify the name of the ACs in this array. ACs names ordered by IDs (Default name is "ACx", x = ID + 1))
var channel = "PlaybackChannel1";
var channel = "com.highfidelity.PlaybackChannel1";
var subscribed = false;
var clip_url = null;
var input_text = null;
var knownAgents = new Array; // We will add our known agents here when we discover them
// available playbackAgents will announce their sessionID here.
var announceIDChannel = "com.highfidelity.playbackAgent.announceID";
// Script. DO NOT MODIFY BEYOND THIS LINE.
Script.include("../libraries/toolBars.js");
@ -51,8 +56,9 @@ setupPlayback();
function setupPlayback() {
ac_number = Window.prompt("Insert number of agents: ","1");
if (ac_number === "" || ac_number === null)
if (ac_number === "" || ac_number === null) {
ac_number = 1;
}
Messages.subscribe(channel);
subscribed = true;
setupToolBars();
@ -134,7 +140,6 @@ function setupToolBars() {
}
function sendCommand(id, action) {
if (action === SHOW) {
toolBars[id].selectTool(onOffIcon[id], false);
toolBars[id].setAlpha(ALPHA_ON, playIcon[id]);
@ -151,8 +156,9 @@ function sendCommand(id, action) {
return;
}
if (id == (toolBars.length - 1))
if (id == (toolBars.length - 1)) {
id = -1; // Master command becomes broadcast.
}
var message = {
id_key: id,
@ -249,12 +255,30 @@ function scriptEnding() {
Overlays.deleteOverlay(nameOverlays[i]);
}
if(subscribed)
if (subscribed) {
Messages.unsubscribe(channel);
}
Messages.unsubscribe(announceIDChannel);
}
Controller.mousePressEvent.connect(mousePressEvent);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);
Messages.subscribe(announceIDChannel);
Messages.messageReceived.connect(function (channel, message, senderID) {
if (channel == announceIDChannel && message == "ready") {
// check to see if we know about this agent
if (knownAgents.indexOf(senderID) < 0) {
var indexOfNewAgent = knownAgents.length;
knownAgents[indexOfNewAgent] = senderID;
var acknowledgeMessage = senderID + "." + indexOfNewAgent;
Messages.sendMessage(announceIDChannel, acknowledgeMessage);
}
}
});
moveUI();

View file

@ -16,24 +16,33 @@
var _this;
var isAvatarRecording = false;
var channel = "groupRecordingChannel";
var startMessage = "RECONDING STARTED";
var stopMessage = "RECONDING ENDED";
var MASTER_TO_CLIENTS_CHANNEL = "startStopChannel";
var CLIENTS_TO_MASTER_CHANNEL = "resultsChannel";
var START_MESSAGE = "recordingStarted";
var STOP_MESSAGE = "recordingEnded";
var PARTICIPATING_MESSAGE = "participatingToRecording";
function recordingEntity() {
_this = this;
return;
}
};
function receivingMessage(channel, message, senderID) {
print("message received on channel:" + channel + ", message:" + message + ", senderID:" + senderID);
if(message === startMessage) {
_this.startRecording();
} else if(message === stopMessage) {
_this.stopRecording();
if (channel === MASTER_TO_CLIENTS_CHANNEL) {
print("CLIENT received message:" + message);
if (message === START_MESSAGE) {
_this.startRecording();
} else if (message === STOP_MESSAGE) {
_this.stopRecording();
}
}
};
function getClipUrl(url) {
Messages.sendMessage(CLIENTS_TO_MASTER_CHANNEL, url); //send back the url to the master
print("clip uploaded and url sent to master");
};
recordingEntity.prototype = {
preload: function (entityID) {
@ -50,19 +59,19 @@
enterEntity: function (entityID) {
print("entering in the recording area");
Messages.subscribe(channel);
Messages.subscribe(MASTER_TO_CLIENTS_CHANNEL);
},
leaveEntity: function (entityID) {
print("leaving the recording area");
_this.stopRecording();
Messages.unsubscribe(channel);
Messages.unsubscribe(MASTER_TO_CLIENTS_CHANNEL);
},
startRecording: function (entityID) {
if (!isAvatarRecording) {
print("RECORDING STARTED");
Messages.sendMessage(CLIENTS_TO_MASTER_CHANNEL, PARTICIPATING_MESSAGE); //tell to master that I'm participating
Recording.startRecording();
isAvatarRecording = true;
}
@ -73,17 +82,19 @@
print("RECORDING ENDED");
Recording.stopRecording();
isAvatarRecording = false;
recordingFile = Window.save("Save recording to file", "./groupRecording", "Recordings (*.hfr)");
var recordingFile = Window.save("Save recording to file", "./groupRecording", "Recordings (*.hfr)");
if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) {
Recording.saveRecording(recordingFile);
Recording.saveRecording(recordingFile); //save the clip locally
}
Recording.saveRecordingToAsset(getClipUrl); //save the clip to the asset and link a callback to get its url
}
},
unload: function (entityID) {
print("RECORDING ENTITY UNLOAD");
_this.stopRecording();
Messages.unsubscribe(channel);
Messages.unsubscribe(MASTER_TO_CLIENTS_CHANNEL);
Messages.messageReceived.disconnect(receivingMessage);
}
}

View file

@ -22,11 +22,24 @@ var TOOL_ICON_URL = HIFI_PUBLIC_BUCKET + "images/tools/";
var ALPHA_ON = 1.0;
var ALPHA_OFF = 0.7;
var COLOR_TOOL_BAR = { red: 0, green: 0, blue: 0 };
var MASTER_TO_CLIENTS_CHANNEL = "startStopChannel";
var CLIENTS_TO_MASTER_CHANNEL = "resultsChannel";
var START_MESSAGE = "recordingStarted";
var STOP_MESSAGE = "recordingEnded";
var PARTICIPATING_MESSAGE = "participatingToRecording";
var TIMEOUT = 20;
var toolBar = null;
var recordIcon;
var isRecording = false;
var channel = "groupRecordingChannel";
var performanceJSON = { "avatarClips" : [] };
var responsesExpected = 0;
var waitingForPerformanceFile = true;
var totalWaitingTime = 0;
var extension = "txt";
Messages.subscribe(CLIENTS_TO_MASTER_CHANNEL);
setupToolBar();
function setupToolBar() {
@ -55,22 +68,72 @@ function mousePressEvent(event) {
if (recordIcon === toolBar.clicked(clickedOverlay, false)) {
if (!isRecording) {
print("I'm the master. I want to start recording");
var message = "RECONDING STARTED";
Messages.sendMessage(channel, message);
Messages.sendMessage(MASTER_TO_CLIENTS_CHANNEL, START_MESSAGE);
isRecording = true;
} else {
print("I want to stop recording");
var message = "RECONDING ENDED";
Messages.sendMessage(channel, message);
waitingForPerformanceFile = true;
Script.update.connect(update);
Messages.sendMessage(MASTER_TO_CLIENTS_CHANNEL, STOP_MESSAGE);
isRecording = false;
}
}
}
function masterReceivingMessage(channel, message, senderID) {
if (channel === CLIENTS_TO_MASTER_CHANNEL) {
print("MASTER received message:" + message );
if (message === PARTICIPATING_MESSAGE) {
//increment the counter of all the participants
responsesExpected++;
} else if (waitingForPerformanceFile) {
//I get an atp url from one participant
performanceJSON.avatarClips[performanceJSON.avatarClips.length] = message;
}
}
}
function update(deltaTime) {
if (waitingForPerformanceFile) {
totalWaitingTime += deltaTime;
if (totalWaitingTime > TIMEOUT || performanceJSON.avatarClips.length === responsesExpected) {
print("UPLOADING PERFORMANCE FILE");
if (performanceJSON.avatarClips.length !== 0) {
//I can upload the performance file on the asset
Assets.uploadData(JSON.stringify(performanceJSON), extension, uploadFinished);
}
//clean things after upload performance file to asset
waitingForPerformanceFile = false;
responsesExpected = 0;
totalWaitingTime = 0;
Script.update.disconnect(update);
performanceJSON = { "avatarClips" : [] };
}
}
}
function uploadFinished(url){
//need to print somehow the url here this way the master can copy the url
print("PERFORMANCE FILE URL: " + url);
Assets.downloadData(url, function (data) {
printPerformanceJSON(JSON.parse(data));
});
}
function printPerformanceJSON(obj) {
print("some info:");
print("downloaded performance file from asset and examinating its content...");
var avatarClips = obj.avatarClips;
avatarClips.forEach(function(param) {
print("clip url obtained: " + param);
});
}
function cleanup() {
toolBar.cleanup();
Messages.unsubscribe(channel);
Messages.unsubscribe(CLIENTS_TO_MASTER_CHANNEL);
}
Script.scriptEnding.connect(cleanup);
Controller.mousePressEvent.connect(mousePressEvent);
Messages.messageReceived.connect(masterReceivingMessage);

View file

@ -76,7 +76,7 @@ var playerSphere = Entities.addEntity({
z: 0
},
collisionsWillMove: true,
linearDamping: 0.2
damping: 0.2
});
Script.setInterval(function(){

View file

@ -41,7 +41,7 @@ var rack = Entities.addEntity({
y: -9.8,
z: 0
},
linearDamping: 1,
damping: 1,
dimensions: {
x: 0.4,
y: 1.37,
@ -83,7 +83,7 @@ function createBalls() {
z: DIAMETER
},
restitution: 1.0,
linearDamping: 0.00001,
damping: 0.00001,
gravity: {
x: 0,
y: -9.8,

View file

@ -46,7 +46,7 @@ function makeBasketball() {
collisionSoundURL: collisionSoundURL,
modelURL: basketballURL,
restitution: 1.0,
linearDamping: 0.00001,
damping: 0.00001,
shapeType: "sphere"
});
originalPosition = position;

View file

@ -88,7 +88,7 @@ var topBlock = Entities.addEntity({
dimensions: blockDimensions,
position: topBlock_position,
rotation: topBlock_rotation,
linearDamping: LINEAR_DAMPING,
damping: LINEAR_DAMPING,
gravity: BLOCK_GRAVITY,
collisionsWillMove: true,
velocity: {
@ -106,7 +106,7 @@ var sideBlock1 = Entities.addEntity({
dimensions: blockDimensions,
position: sideBlock1_position,
rotation: sideBlock1_rotation,
linearDamping: LINEAR_DAMPING,
damping: LINEAR_DAMPING,
gravity: BLOCK_GRAVITY,
collisionsWillMove: true
});
@ -120,7 +120,7 @@ var sideBlock2 = Entities.addEntity({
position: sideBlock2_position,
rotation: sideBlock2_rotation,
collsionsWillMove: true,
linearDamping: LINEAR_DAMPING,
damping: LINEAR_DAMPING,
gravity: BLOCK_GRAVITY,
collisionsWillMove: true
});

View file

@ -28,7 +28,7 @@
var BUBBLE_LIFETIME_MAX = 8;
var BUBBLE_SIZE_MIN = 0.02;
var BUBBLE_SIZE_MAX = 0.1;
var BUBBLE_LINEAR_DAMPING = 0.4;
var BUBBLE_LINEAR_DAMPING = 0.2;
var BUBBLE_GRAVITY_MIN = 0.1;
var BUBBLE_GRAVITY_MAX = 0.3;
var GROWTH_FACTOR = 0.005;
@ -163,7 +163,7 @@
dimensions: BUBBLE_INITIAL_DIMENSIONS,
collisionsWillMove: false,
ignoreForCollisions: true,
linearDamping: BUBBLE_LINEAR_DAMPING,
damping: BUBBLE_LINEAR_DAMPING,
shapeType: "sphere"
});

View file

@ -123,7 +123,7 @@
type:'Sphere',
color: BALL_COLOR,
dimensions: BALL_DIMENSIONS,
linearDamping: BALL_LINEAR_DAMPING,
damping: BALL_LINEAR_DAMPING,
gravity: BALL_GRAVITY,
restitution: BALL_RESTITUTION,
collisionsWillMove: true,

View file

@ -18,10 +18,18 @@
#include <recording/Frame.h>
#include <recording/ClipCache.h>
#include <QtScript/QScriptValue>
#include <AssetClient.h>
#include <AssetUpload.h>
#include <QtCore/QUrl>
#include <QtWidgets/QFileDialog>
#include "ScriptEngineLogging.h"
using namespace recording;
static const QString HFR_EXTENSION = "hfr";
RecordingScriptingInterface::RecordingScriptingInterface() {
_player = DependencyManager::get<Deck>();
@ -171,6 +179,47 @@ void RecordingScriptingInterface::saveRecording(const QString& filename) {
recording::Clip::toFile(filename, _lastClip);
}
bool RecordingScriptingInterface::saveRecordingToAsset(QScriptValue getClipAtpUrl) {
if (!getClipAtpUrl.isFunction()) {
qCWarning(scriptengine) << "The argument is not a function.";
return false;
}
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "saveRecordingToAsset", Qt::BlockingQueuedConnection,
Q_ARG(QScriptValue, getClipAtpUrl));
return false;
}
if (!_lastClip) {
qWarning() << "There is no recording to save";
return false;
}
if (auto upload = DependencyManager::get<AssetClient>()->createUpload(recording::Clip::toBuffer(_lastClip), HFR_EXTENSION)) {
QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable {
QString clip_atp_url = "";
if (upload->getError() == AssetUpload::NoError) {
clip_atp_url = QString("%1:%2.%3").arg(URL_SCHEME_ATP, hash, upload->getExtension());
upload->deleteLater();
} else {
qCWarning(scriptengine) << "Error during the Asset upload.";
}
QScriptValueList args;
args << clip_atp_url;
getClipAtpUrl.call(QScriptValue(), args);
});
upload->start();
return true;
}
qCWarning(scriptengine) << "Saving on asset failed.";
return false;
}
void RecordingScriptingInterface::loadLastRecording() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "loadLastRecording", Qt::BlockingQueuedConnection);

View file

@ -18,6 +18,8 @@
#include <recording/Forward.h>
#include <recording/Frame.h>
class QScriptValue;
class RecordingScriptingInterface : public QObject, public Dependency {
Q_OBJECT
@ -60,6 +62,7 @@ public slots:
float recorderElapsed() const;
void saveRecording(const QString& filename);
bool saveRecordingToAsset(QScriptValue getClipAtpUrl);
void loadLastRecording();
protected:

View file

@ -62,7 +62,7 @@ static QScriptValue debugPrint(QScriptContext* context, QScriptEngine* engine){
}
message += context->argument(i).toString();
}
qCDebug(scriptengine) << "script:print()<<" << message;
qCDebug(scriptengine).noquote() << "script:print()<<" << message; // noquote() so that \n is treated as newline
message = message.replace("\\", "\\\\")
.replace("\n", "\\n")

View file

@ -75,7 +75,7 @@ var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
z: DIAMETER
},
restitution: 1.0,
linearDamping: 0.00001,
damping: 0.00001,
gravity: {
x: 0,
y: -9.8,

View file

@ -253,7 +253,7 @@
y: -9.8,
z: 0
},
linearDamping: 1,
damping: 1,
dimensions: {
x: 0.4,
y: 1.37,
@ -301,7 +301,7 @@
z: DIAMETER
},
restitution: 1.0,
linearDamping: 0.00001,
damping: 0.00001,
gravity: {
x: 0,
y: -9.8,
@ -871,7 +871,7 @@
y: -100,
z: 0
},
linearDamping: 1,
damping: 1,
angularDamping: 10,
mass: 10,
userData: JSON.stringify({
@ -990,7 +990,7 @@
z: 0
},
restitution: 10,
linearDamping: 0.0,
damping: 0.0,
velocity: {
x: 0,
y: -0.01,
@ -1113,7 +1113,7 @@
y: 0,
z: 0
},
linearDamping: 0.4,
damping: 0.4,
userData: JSON.stringify({
resetMe: {
resetMe: true
@ -1156,7 +1156,7 @@
y: 0,
z: 0
},
linearDamping: 0.2,
damping: 0.2,
userData: JSON.stringify({
resetMe: {
resetMe: true

View file

@ -233,7 +233,7 @@ MasterReset = function() {
y: -9.8,
z: 0
},
linearDamping: 1,
damping: 1,
dimensions: {
x: 0.4,
y: 1.37,
@ -282,7 +282,7 @@ MasterReset = function() {
z: DIAMETER
},
restitution: 1.0,
linearDamping: 0.00001,
damping: 0.00001,
gravity: {
x: 0,
y: -9.8,
@ -853,7 +853,7 @@ MasterReset = function() {
y: -100,
z: 0
},
linearDamping: 1,
damping: 1,
angularDamping: 10,
mass: 10,
userData: JSON.stringify({
@ -973,7 +973,7 @@ MasterReset = function() {
z: 0
},
restitution: 10,
linearDamping: 0.0,
damping: 0.01,
velocity: {
x: 0,
y: -0.01,
@ -1096,7 +1096,7 @@ MasterReset = function() {
y: 0,
z: 0
},
linearDamping: 0.4,
damping: 0.4,
userData: JSON.stringify({
resetMe: {
resetMe: true
@ -1139,7 +1139,7 @@ MasterReset = function() {
y: 0,
z: 0
},
linearDamping: 0.2,
damping: 0.2,
userData: JSON.stringify({
resetMe: {
resetMe: true