mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-13 04:15:56 +02:00
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:
commit
e579be82a2
7 changed files with 225 additions and 50 deletions
153
examples/clap.js
153
examples/clap.js
|
@ -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);
|
|
@ -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
35
interface/src/Hair.cpp
Normal 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
35
interface/src/Hair.h
Normal 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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue