Merge pull request #3137 from PhilipRosedale/master

Better clapping and hand squeezing scripts, started new hair class to hold vertlet hair
This commit is contained in:
Andrzej Kapolka 2014-07-08 14:20:03 -07:00
commit e579be82a2
7 changed files with 225 additions and 50 deletions

View file

@ -10,27 +10,34 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
function length(v) {
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
var clapAnimation = "https://s3-us-west-1.amazonaws.com/highfidelity-public/animations/ClapAnimations/ClapHands_Standing.fbx";
var startEndFrames = [];
startEndFrames.push({ start: 0, end: 8});
startEndFrames.push({ start: 10, end: 20});
startEndFrames.push({ start: 20, end: 28});
startEndFrames.push({ start: 30, end: 37});
startEndFrames.push({ start: 41, end: 46});
startEndFrames.push({ start: 53, end: 58});
var lastClapFrame = 0;
var lastAnimFrame = 0;
function printVector(v) {
print(v.x + ", " + v.y + ", " + v.z + "\n");
}
var claps = [];
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap1Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap2Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap3Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap4Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap5Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap6Reverb.wav"));
var numberOfSounds = claps.length;
function vMinus(a, b) {
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
return rval;
}
var clappingNow = false;
var collectedClicks = 0;
// First, load the clap sound from a URL
var clap1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap1.raw");
var clap2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap2.raw");
var clap3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap3.raw");
var clap4 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap4.raw");
var clap5 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap5.raw");
var clap6 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap6.raw");
var clickClappingNow = false;
var CLAP_START_RATE = 15.0;
var clapRate = CLAP_START_RATE;
var startedTimer = false;
var clapping = new Array();
clapping[0] = false;
@ -38,36 +45,94 @@ clapping[1] = false;
function maybePlaySound(deltaTime) {
// Set the location and other info for the sound to play
var palm1Position = Controller.getSpatialControlPosition(0);
var palm2Position = Controller.getSpatialControlPosition(2);
var distanceBetween = length(vMinus(palm1Position, palm2Position));
for (var palm = 0; palm < 2; palm++) {
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2 + 1);
var speed = length(palmVelocity);
const CLAP_SPEED = 0.2;
const CLAP_DISTANCE = 0.2;
var animationDetails = MyAvatar.getAnimationDetails(clapAnimation);
if (!clapping[palm] && (distanceBetween < CLAP_DISTANCE) && (speed > CLAP_SPEED)) {
var options = new AudioInjectionOptions();
options.position = palm1Position;
options.volume = speed / 2.0;
if (options.volume > 1.0) options.volume = 1.0;
which = Math.floor((Math.random() * 6) + 1);
if (which == 1) { Audio.playSound(clap1, options); }
else if (which == 2) { Audio.playSound(clap2, options); }
else if (which == 3) { Audio.playSound(clap3, options); }
else if (which == 4) { Audio.playSound(clap4, options); }
else if (which == 5) { Audio.playSound(clap5, options); }
else { Audio.playSound(clap6, options); }
Audio.playSound(clap, options);
clapping[palm] = true;
} else if (clapping[palm] && (speed < (CLAP_SPEED / 4.0))) {
clapping[palm] = false;
}
var frame = Math.floor(animationDetails.frameIndex);
if (frame != lastAnimFrame) {
print("frame " + frame);
lastAnimFrame = frame;
}
for (var i = 0; i < startEndFrames.length; i++) {
if (frame == startEndFrames[i].start && (frame != lastClapFrame)) {
playClap(1.0, Camera.getPosition());
lastClapFrame = frame;
}
}
var palm1Position = MyAvatar.getLeftPalmPosition();
var palm2Position = MyAvatar.getRightPalmPosition();
var distanceBetween = Vec3.length(Vec3.subtract(palm1Position, palm2Position));
var palm1Velocity = Controller.getSpatialControlVelocity(1);
var palm2Velocity = Controller.getSpatialControlVelocity(3);
var closingVelocity = Vec3.length(Vec3.subtract(palm1Velocity, palm2Velocity));
const CLAP_SPEED = 0.7;
const CLAP_DISTANCE = 0.15;
if ((closingVelocity > CLAP_SPEED) && (distanceBetween < CLAP_DISTANCE) && !clappingNow) {
var volume = closingVelocity / 2.0;
if (volume > 1.0) volume = 1.0;
playClap(volume, palm1Position);
clappingNow = true;
} else if (clappingNow && (distanceBetween > CLAP_DISTANCE * 1.2)) {
clappingNow = false;
}
}
function playClap(volume, position) {
var options = new AudioInjectionOptions();
options.position = position;
options.volume = 1.0;
var clip = Math.floor(Math.random() * numberOfSounds);
Audio.playSound(claps[clip], options);
}
function keepClapping() {
playClap(1.0, Camera.getPosition());
}
Controller.keyPressEvent.connect(function(event) {
if(event.text == "SHIFT") {
if (!clickClappingNow) {
playClap(1.0, Camera.getPosition());
var whichClip = Math.floor(Math.random() * startEndFrames.length);
lastClapFrame = 0;
MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false);
clickClappingNow = true;
} else {
clapRate *= 1.25;
MyAvatar.stopAnimation(clapAnimation);
MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false);
collectedClicks = collectedClicks + 1;
}
}
});
var CLAP_END_WAIT_MSECS = 500;
Controller.keyReleaseEvent.connect(function(event) {
if (event.text == "SHIFT") {
if (!startedTimer) {
startedTimer = true;
collectedClicks = 0;
Script.setTimeout(stopClapping, CLAP_END_WAIT_MSECS);
}
}
});
function stopClapping() {
if (collectedClicks == 0) {
startedTimer = false;
MyAvatar.stopAnimation(clapAnimation);
clapRate = CLAP_START_RATE;
clickClappingNow = false;
} else {
startedTimer = false;
}
}
// Connect a call back that happens every frame
Script.update.connect(maybePlaySound);
Script.update.connect(maybePlaySound);
//Controller.keyPressEvent.connect(keyPressEvent);

View file

@ -18,13 +18,16 @@ var RIGHT = 1;
var lastLeftFrame = 0;
var lastRightFrame = 0;
var LAST_FRAME = 11.0; // What is the number of the last frame we want to use in the animation?
var SMOOTH_FACTOR = 0.80;
var leftDirection = true;
var rightDirection = true;
var LAST_FRAME = 15.0; // What is the number of the last frame we want to use in the animation?
var SMOOTH_FACTOR = 0.0;
var MAX_FRAMES = 30.0;
Script.update.connect(function(deltaTime) {
var leftTriggerValue = Math.sqrt(Controller.getTriggerValue(LEFT));
var rightTriggerValue = Math.sqrt(Controller.getTriggerValue(RIGHT));
var leftTriggerValue = Controller.getTriggerValue(LEFT);
var rightTriggerValue = Controller.getTriggerValue(RIGHT);
var leftFrame, rightFrame;
@ -32,10 +35,31 @@ Script.update.connect(function(deltaTime) {
leftFrame = (leftTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastLeftFrame * SMOOTH_FACTOR;
rightFrame = (rightTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastRightFrame * SMOOTH_FACTOR;
if (!leftDirection) {
leftFrame = MAX_FRAMES - leftFrame;
}
if (!rightDirection) {
rightFrame = MAX_FRAMES - rightFrame;
}
if ((leftTriggerValue == 1.0) && (leftDirection == true)) {
leftDirection = false;
lastLeftFrame = MAX_FRAMES - leftFrame;
} else if ((leftTriggerValue == 0.0) && (leftDirection == false)) {
leftDirection = true;
lastLeftFrame = leftFrame;
}
if ((rightTriggerValue == 1.0) && (rightDirection == true)) {
rightDirection = false;
lastRightFrame = MAX_FRAMES - rightFrame;
} else if ((rightTriggerValue == 0.0) && (rightDirection == false)) {
rightDirection = true;
lastRightFrame = rightFrame;
}
if ((leftFrame != lastLeftFrame) && leftHandAnimation.length){
MyAvatar.stopAnimation(leftHandAnimation);
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
}
if ((rightFrame != lastRightFrame) && rightHandAnimation.length) {
MyAvatar.stopAnimation(rightHandAnimation);

35
interface/src/Hair.cpp Normal file
View file

@ -0,0 +1,35 @@
//
// Hair.cpp
// interface/src
//
// Created by Philip on June 26, 2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Creates single flexible vertlet-integrated strands that can be used for hair/fur/grass
#include "Hair.h"
#include "Util.h"
#include "world.h"
Hair::Hair() {
qDebug() << "Creating Hair";
}
void Hair::simulate(float deltaTime) {
}
void Hair::render() {
//
// Before calling this function, translate/rotate to the origin of the owning object
glPushMatrix();
glColor3f(1.0f, 1.0f, 0.0f);
glutSolidSphere(1.0f, 15, 15);
glPopMatrix();
}

35
interface/src/Hair.h Normal file
View file

@ -0,0 +1,35 @@
//
// Hair.h
// interface/src
//
// Created by Philip on June 26, 2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Hair_h
#define hifi_Hair_h
#include <iostream>
#include <glm/glm.hpp>
#include <SharedUtil.h>
#include "GeometryUtil.h"
#include "InterfaceConfig.h"
#include "Util.h"
class Hair {
public:
Hair();
void simulate(float deltaTime);
void render();
private:
};
#endif // hifi_Hair_h

View file

@ -143,6 +143,11 @@ void Avatar::simulate(float deltaTime) {
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
simulateHair(deltaTime);
}
foreach (Hair* hair, _hairs) {
hair->simulate(deltaTime);
}
}
// update position by velocity, and subtract the change added earlier for gravity
@ -380,6 +385,9 @@ void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
getHead()->render(1.0f, modelRenderMode);
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
renderHair();
foreach (Hair* hair, _hairs) {
hair->render();
}
}
}

View file

@ -19,6 +19,7 @@
#include <AvatarData.h>
#include "Hair.h"
#include "Hand.h"
#include "Head.h"
#include "InterfaceConfig.h"
@ -159,6 +160,7 @@ signals:
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
protected:
QVector<Hair*> _hairs;
SkeletonModel _skeletonModel;
QVector<Model*> _attachmentModels;
float _bodyYawDelta;

View file

@ -199,6 +199,9 @@ void MyAvatar::simulate(float deltaTime) {
PerformanceTimer perfTimer("MyAvatar::simulate/hair Simulate");
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
simulateHair(deltaTime);
foreach (Hair* hair, _hairs) {
hair->simulate(deltaTime);
}
}
}
@ -896,6 +899,9 @@ void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
getHead()->render(1.0f, modelRenderMode);
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
renderHair();
foreach (Hair* hair, _hairs) {
hair->render();
}
}
}
getHand()->render(true, modelRenderMode);