mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-26 03:55:08 +02:00
Merge pull request #2970 from Barnold1953/master
Mirror mode fix, particleBirds.js
This commit is contained in:
commit
6f5d2ba233
3 changed files with 209 additions and 209 deletions
|
@ -1,202 +0,0 @@
|
||||||
//
|
|
||||||
// particleBird.js
|
|
||||||
// examples
|
|
||||||
//
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// This sample script moves a voxel around like a bird and sometimes makes tweeting noises
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
function vLength(v) {
|
|
||||||
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
|
||||||
}
|
|
||||||
function printVector(v) {
|
|
||||||
print(v.x + ", " + v.y + ", " + v.z + "\n");
|
|
||||||
}
|
|
||||||
// Create a random vector with individual lengths between a,b
|
|
||||||
function randVector(a, b) {
|
|
||||||
var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) };
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vMinus(a, b) {
|
|
||||||
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vPlus(a, b) {
|
|
||||||
var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vCopy(a, b) {
|
|
||||||
a.x = b.x;
|
|
||||||
a.y = b.y;
|
|
||||||
a.z = b.z;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a vector which is fraction of the way between a and b
|
|
||||||
function vInterpolate(a, b, fraction) {
|
|
||||||
var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction };
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decide what kind of bird we are
|
|
||||||
var tweet;
|
|
||||||
var color;
|
|
||||||
var size;
|
|
||||||
var which = Math.random();
|
|
||||||
if (which < 0.2) {
|
|
||||||
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw");
|
|
||||||
color = { r: 100, g: 50, b: 120 };
|
|
||||||
size = 0.08;
|
|
||||||
} else if (which < 0.4) {
|
|
||||||
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/rosyfacedlovebird.raw");
|
|
||||||
color = { r: 100, g: 150, b: 75 };
|
|
||||||
size = 0.09;
|
|
||||||
} else if (which < 0.6) {
|
|
||||||
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/saysphoebe.raw");
|
|
||||||
color = { r: 84, g: 121, b: 36 };
|
|
||||||
size = 0.05;
|
|
||||||
} else if (which < 0.8) {
|
|
||||||
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/mexicanWhipoorwill.raw");
|
|
||||||
color = { r: 23, g: 197, b: 230 };
|
|
||||||
size = 0.12;
|
|
||||||
} else {
|
|
||||||
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/westernscreechowl.raw");
|
|
||||||
color = { r: 50, g: 67, b: 144 };
|
|
||||||
size = 0.15;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var startTimeInSeconds = new Date().getTime() / 1000;
|
|
||||||
|
|
||||||
var birdLifetime = 20; // lifetime of the bird in seconds!
|
|
||||||
var position = { x: 0, y: 0, z: 0 };
|
|
||||||
var targetPosition = { x: 0, y: 0, z: 0 };
|
|
||||||
var range = 1.0; // Over what distance in meters do you want your bird to fly around
|
|
||||||
var frame = 0;
|
|
||||||
var moving = false;
|
|
||||||
var tweeting = 0;
|
|
||||||
var moved = false;
|
|
||||||
|
|
||||||
var CHANCE_OF_MOVING = 0.00;
|
|
||||||
var CHANCE_OF_FLAPPING = 0.05;
|
|
||||||
var CHANCE_OF_TWEETING = 0.05;
|
|
||||||
var START_HEIGHT_ABOVE_ME = 1.5;
|
|
||||||
var BIRD_GRAVITY = -0.1;
|
|
||||||
var BIRD_FLAP = 1.0;
|
|
||||||
var myPosition = MyAvatar.position;
|
|
||||||
var properties = {
|
|
||||||
lifetime: birdLifetime,
|
|
||||||
position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z },
|
|
||||||
velocity: { x: 0, y: Math.random() * BIRD_FLAP, z: 0 },
|
|
||||||
gravity: { x: 0, y: BIRD_GRAVITY, z: 0 },
|
|
||||||
radius : 0.1,
|
|
||||||
color: { red: 0,
|
|
||||||
green: 255,
|
|
||||||
blue: 0 }
|
|
||||||
};
|
|
||||||
var range = 1.0; // Distance around avatar where I can move
|
|
||||||
// Create the actual bird
|
|
||||||
var particleID = Particles.addParticle(properties);
|
|
||||||
function moveBird(deltaTime) {
|
|
||||||
|
|
||||||
// check to see if we've been running long enough that our bird is dead
|
|
||||||
var nowTimeInSeconds = new Date().getTime() / 1000;
|
|
||||||
if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) {
|
|
||||||
|
|
||||||
print("our bird is dying, stop our script");
|
|
||||||
Script.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
myPosition = MyAvatar.position;
|
|
||||||
frame++;
|
|
||||||
if (frame % 3 == 0) {
|
|
||||||
// Tweeting behavior
|
|
||||||
if (tweeting == 0) {
|
|
||||||
if (Math.random() < CHANCE_OF_TWEETING) {
|
|
||||||
//print("tweet!" + "\n");
|
|
||||||
var options = new AudioInjectionOptions();
|
|
||||||
options.position = position;
|
|
||||||
options.volume = 0.75;
|
|
||||||
Audio.playSound(tweet, options);
|
|
||||||
tweeting = 10;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tweeting -= 1;
|
|
||||||
}
|
|
||||||
if (Math.random() < CHANCE_OF_FLAPPING) {
|
|
||||||
// Add a little upward impulse to our bird
|
|
||||||
// TODO: Get velocity
|
|
||||||
//
|
|
||||||
var newProperties = {
|
|
||||||
velocity: { x:0.0, y: Math.random() * BIRD_FLAP, z: 0.0 }
|
|
||||||
};
|
|
||||||
Particles.editParticle(particleID, newProperties);
|
|
||||||
print("flap!");
|
|
||||||
}
|
|
||||||
// Moving behavior
|
|
||||||
if (moving == false) {
|
|
||||||
if (Math.random() < CHANCE_OF_MOVING) {
|
|
||||||
targetPosition = randVector(-range, range);
|
|
||||||
targetPosition = vPlus(targetPosition, myPosition);
|
|
||||||
|
|
||||||
if (targetPosition.x < 0) {
|
|
||||||
targetPosition.x = 0;
|
|
||||||
}
|
|
||||||
if (targetPosition.y < 0) {
|
|
||||||
targetPosition.y = 0;
|
|
||||||
}
|
|
||||||
if (targetPosition.z < 0) {
|
|
||||||
targetPosition.z = 0;
|
|
||||||
}
|
|
||||||
if (targetPosition.x > TREE_SCALE) {
|
|
||||||
targetPosition.x = TREE_SCALE;
|
|
||||||
}
|
|
||||||
if (targetPosition.y > TREE_SCALE) {
|
|
||||||
targetPosition.y = TREE_SCALE;
|
|
||||||
}
|
|
||||||
if (targetPosition.z > TREE_SCALE) {
|
|
||||||
targetPosition.z = TREE_SCALE;
|
|
||||||
}
|
|
||||||
//printVector(position);
|
|
||||||
moving = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (moving) {
|
|
||||||
position = vInterpolate(position, targetPosition, 0.5);
|
|
||||||
if (vLength(vMinus(position, targetPosition)) < (size / 5.0)) {
|
|
||||||
moved = false;
|
|
||||||
moving = false;
|
|
||||||
} else {
|
|
||||||
moved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (moved || (tweeting > 0)) {
|
|
||||||
if (tweeting > 0) {
|
|
||||||
var newProperties = {
|
|
||||||
position: position,
|
|
||||||
radius : size * 1.5,
|
|
||||||
color: { red: Math.random() * 255, green: 0, blue: 0 }
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
var newProperties = {
|
|
||||||
position: position,
|
|
||||||
radius : size,
|
|
||||||
color: { red: color.r, green: color.g, blue: color.b }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Particles.editParticle(particleID, newProperties);
|
|
||||||
moved = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// register the call back so it fires before each data send
|
|
||||||
Script.update.connect(moveBird);
|
|
199
examples/particleBirds.js
Normal file
199
examples/particleBirds.js
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
//
|
||||||
|
// particleBirds.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Benjamin Arnold on May 29, 2014
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This sample script creates a swarm of tweeting bird particles that fly around the avatar.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// Multiply vector by scalar
|
||||||
|
function vScalarMult(v, s) {
|
||||||
|
var rval = { x: v.x * s, y: v.y * s, z: v.z * s };
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printVector(v) {
|
||||||
|
print(v.x + ", " + v.y + ", " + v.z + "\n");
|
||||||
|
}
|
||||||
|
// Create a random vector with individual lengths between a,b
|
||||||
|
function randVector(a, b) {
|
||||||
|
var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) };
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a vector which is fraction of the way between a and b
|
||||||
|
function vInterpolate(a, b, fraction) {
|
||||||
|
var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction };
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTimeInSeconds = new Date().getTime() / 1000;
|
||||||
|
|
||||||
|
var birdLifetime = 20; // lifetime of the birds in seconds!
|
||||||
|
var range = 1.0; // Over what distance in meters do you want the flock to fly around
|
||||||
|
var frame = 0;
|
||||||
|
|
||||||
|
var CHANCE_OF_MOVING = 0.1;
|
||||||
|
var CHANCE_OF_TWEETING = 0.05;
|
||||||
|
var BIRD_GRAVITY = -0.1;
|
||||||
|
var BIRD_FLAP_SPEED = 10.0;
|
||||||
|
var BIRD_VELOCITY = 0.5;
|
||||||
|
var myPosition = MyAvatar.position;
|
||||||
|
|
||||||
|
var range = 1.0; // Distance around avatar where I can move
|
||||||
|
|
||||||
|
// This is our Bird object
|
||||||
|
function Bird (particleID, tweetSound, targetPosition) {
|
||||||
|
this.particleID = particleID;
|
||||||
|
this.tweetSound = tweetSound;
|
||||||
|
this.previousFlapOffset = 0;
|
||||||
|
this.targetPosition = targetPosition;
|
||||||
|
this.moving = false;
|
||||||
|
this.tweeting = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Array of birds
|
||||||
|
var birds = [];
|
||||||
|
|
||||||
|
function addBird()
|
||||||
|
{
|
||||||
|
// Decide what kind of bird we are
|
||||||
|
var tweet;
|
||||||
|
var color;
|
||||||
|
var size;
|
||||||
|
var which = Math.random();
|
||||||
|
if (which < 0.2) {
|
||||||
|
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw");
|
||||||
|
color = { red: 100, green: 50, blue: 120 };
|
||||||
|
size = 0.08;
|
||||||
|
} else if (which < 0.4) {
|
||||||
|
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/rosyfacedlovebird.raw");
|
||||||
|
color = { red: 100, green: 150, blue: 75 };
|
||||||
|
size = 0.09;
|
||||||
|
} else if (which < 0.6) {
|
||||||
|
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/saysphoebe.raw");
|
||||||
|
color = { red: 84, green: 121, blue: 36 };
|
||||||
|
size = 0.05;
|
||||||
|
} else if (which < 0.8) {
|
||||||
|
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/mexicanWhipoorwill.raw");
|
||||||
|
color = { red: 23, green: 197, blue: 230 };
|
||||||
|
size = 0.12;
|
||||||
|
} else {
|
||||||
|
tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/westernscreechowl.raw");
|
||||||
|
color = { red: 50, green: 67, blue: 144 };
|
||||||
|
size = 0.15;
|
||||||
|
}
|
||||||
|
var properties = {
|
||||||
|
lifetime: birdLifetime,
|
||||||
|
position: Vec3.sum(randVector(-range, range), myPosition),
|
||||||
|
velocity: { x: 0, y: 0, z: 0 },
|
||||||
|
gravity: { x: 0, y: BIRD_GRAVITY, z: 0 },
|
||||||
|
radius : size,
|
||||||
|
color: color
|
||||||
|
};
|
||||||
|
|
||||||
|
birds.push(new Bird(Particles.addParticle(properties), tweet, properties.position));
|
||||||
|
}
|
||||||
|
|
||||||
|
var numBirds = 30;
|
||||||
|
|
||||||
|
// Generate the birds
|
||||||
|
for (var i = 0; i < numBirds; i++) {
|
||||||
|
addBird();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main update function
|
||||||
|
function updateBirds(deltaTime) {
|
||||||
|
|
||||||
|
// Check to see if we've been running long enough that our birds are dead
|
||||||
|
var nowTimeInSeconds = new Date().getTime() / 1000;
|
||||||
|
if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) {
|
||||||
|
|
||||||
|
print("our birds are dying, stop our script");
|
||||||
|
Script.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame++;
|
||||||
|
// Only update every third frame
|
||||||
|
if ((frame % 3) == 0) {
|
||||||
|
myPosition = MyAvatar.position;
|
||||||
|
|
||||||
|
// Update all the birds
|
||||||
|
for (var i = 0; i < numBirds; i++) {
|
||||||
|
particleID = birds[i].particleID;
|
||||||
|
var properties = Particles.getParticleProperties(particleID);
|
||||||
|
|
||||||
|
// Tweeting behavior
|
||||||
|
if (birds[i].tweeting == 0) {
|
||||||
|
if (Math.random() < CHANCE_OF_TWEETING) {
|
||||||
|
var options = new AudioInjectionOptions();
|
||||||
|
options.position = properties.position;
|
||||||
|
options.volume = 0.75;
|
||||||
|
Audio.playSound(birds[i].tweetSound, options);
|
||||||
|
birds[i].tweeting = 10;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
birds[i].tweeting -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin movement by getting a target
|
||||||
|
if (birds[i].moving == false) {
|
||||||
|
if (Math.random() < CHANCE_OF_MOVING) {
|
||||||
|
var targetPosition = Vec3.sum(randVector(-range, range), myPosition);
|
||||||
|
|
||||||
|
if (targetPosition.x < 0) {
|
||||||
|
targetPosition.x = 0;
|
||||||
|
}
|
||||||
|
if (targetPosition.y < 0) {
|
||||||
|
targetPosition.y = 0;
|
||||||
|
}
|
||||||
|
if (targetPosition.z < 0) {
|
||||||
|
targetPosition.z = 0;
|
||||||
|
}
|
||||||
|
if (targetPosition.x > TREE_SCALE) {
|
||||||
|
targetPosition.x = TREE_SCALE;
|
||||||
|
}
|
||||||
|
if (targetPosition.y > TREE_SCALE) {
|
||||||
|
targetPosition.y = TREE_SCALE;
|
||||||
|
}
|
||||||
|
if (targetPosition.z > TREE_SCALE) {
|
||||||
|
targetPosition.z = TREE_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
birds[i].targetPosition = targetPosition;
|
||||||
|
|
||||||
|
birds[i].moving = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we are moving, move towards the target
|
||||||
|
if (birds[i].moving) {
|
||||||
|
var desiredVelocity = Vec3.subtract(birds[i].targetPosition, properties.position);
|
||||||
|
desiredVelocity = vScalarMult(Vec3.normalize(desiredVelocity), BIRD_VELOCITY);
|
||||||
|
|
||||||
|
properties.velocity = vInterpolate(properties.velocity, desiredVelocity, 0.2);
|
||||||
|
// If we are near the target, we should get a new target
|
||||||
|
if (Vec3.length(Vec3.subtract(properties.position, birds[i].targetPosition)) < (properties.radius / 5.0)) {
|
||||||
|
birds[i].moving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a cosine wave offset to make it look like its flapping.
|
||||||
|
var offset = Math.cos(nowTimeInSeconds * BIRD_FLAP_SPEED) * properties.radius;
|
||||||
|
properties.position.y = properties.position.y + (offset - birds[i].previousFlapOffset);
|
||||||
|
// Change position relative to previous offset.
|
||||||
|
birds[i].previousFlapOffset = offset;
|
||||||
|
|
||||||
|
// Update the particle
|
||||||
|
Particles.editParticle(particleID, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the call back so it fires before each data send
|
||||||
|
Script.update.connect(updateBirds);
|
|
@ -2789,16 +2789,19 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
||||||
glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation();
|
glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation();
|
||||||
glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation();
|
glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation();
|
||||||
|
|
||||||
// get the eye positions relative to the neck and use them to set the face translation
|
// get the neck position so we can translate the face relative to it
|
||||||
glm::vec3 leftEyePosition, rightEyePosition;
|
|
||||||
_myAvatar->getHead()->getFaceModel().setTranslation(glm::vec3());
|
|
||||||
_myAvatar->getHead()->getFaceModel().getEyePositions(leftEyePosition, rightEyePosition);
|
|
||||||
_myAvatar->getHead()->getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f);
|
|
||||||
|
|
||||||
// get the neck position relative to the body and use it to set the skeleton translation
|
|
||||||
glm::vec3 neckPosition;
|
glm::vec3 neckPosition;
|
||||||
_myAvatar->getSkeletonModel().setTranslation(glm::vec3());
|
_myAvatar->getSkeletonModel().setTranslation(glm::vec3());
|
||||||
_myAvatar->getSkeletonModel().getNeckPosition(neckPosition);
|
_myAvatar->getSkeletonModel().getNeckPosition(neckPosition);
|
||||||
|
|
||||||
|
// get the eye position relative to the body
|
||||||
|
glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
|
||||||
|
float eyeHeight = eyePosition.y - _myAvatar->getPosition().y;
|
||||||
|
|
||||||
|
// set the translation of the face relative to the neck position
|
||||||
|
_myAvatar->getHead()->getFaceModel().setTranslation(neckPosition - glm::vec3(0, eyeHeight, 0));
|
||||||
|
|
||||||
|
// translate the neck relative to the face
|
||||||
_myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() -
|
_myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead()->getFaceModel().getTranslation() -
|
||||||
neckPosition);
|
neckPosition);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue