mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 03:04:33 +02:00
Merge branch 'master' of https://github.com/worklist/hifi
This commit is contained in:
commit
0932a8b382
9 changed files with 191 additions and 393 deletions
|
@ -126,7 +126,7 @@ void *sendBuffer(void *args)
|
|||
int16_t clientMix[BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 2] = {};
|
||||
|
||||
|
||||
for (AgentList::iterator otherAgent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
for (AgentList::iterator otherAgent = agentList->begin(); otherAgent != agentList->end(); otherAgent++) {
|
||||
if (otherAgent != agent || ( otherAgent == agent && agentWantsLoopback)) {
|
||||
AudioRingBuffer* otherAgentBuffer = (AudioRingBuffer*) otherAgent->getLinkedData();
|
||||
|
||||
|
|
|
@ -114,15 +114,12 @@ int audioCallback (const void *inputBuffer,
|
|||
AudioData *data = (AudioData *) userData;
|
||||
|
||||
int16_t *inputLeft = ((int16_t **) inputBuffer)[0];
|
||||
// int16_t *inputRight = ((int16_t **) inputBuffer)[1];
|
||||
|
||||
//printLog("Audio callback at %6.0f\n", usecTimestampNow()/1000);
|
||||
// printLog("Audio callback at %6.0f\n", usecTimestampNow()/1000);
|
||||
|
||||
if (inputLeft != NULL) {
|
||||
|
||||
//
|
||||
// Measure the loudness of the signal from the microphone and store in audio object
|
||||
//
|
||||
float loudness = 0;
|
||||
for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) {
|
||||
loudness += abs(inputLeft[i]);
|
||||
|
@ -130,10 +127,8 @@ int audioCallback (const void *inputBuffer,
|
|||
|
||||
loudness /= BUFFER_LENGTH_SAMPLES;
|
||||
data->lastInputLoudness = loudness;
|
||||
|
||||
//
|
||||
|
||||
// If scope is turned on, copy input buffer to scope
|
||||
//
|
||||
if (scope->getState()) {
|
||||
for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) {
|
||||
scope->addData((float)inputLeft[i]/32767.0, 1, i);
|
||||
|
@ -165,7 +160,7 @@ int audioCallback (const void *inputBuffer,
|
|||
*(currentPacketPtr++) = 255;
|
||||
|
||||
// memcpy the corrected render yaw
|
||||
float correctedYaw = fmodf(data->linkedAvatar->getRenderYaw(), 360);
|
||||
float correctedYaw = fmodf(data->linkedAvatar->getAbsoluteHeadYaw(), 360);
|
||||
|
||||
if (correctedYaw > 180) {
|
||||
correctedYaw -= 360;
|
||||
|
@ -174,42 +169,13 @@ int audioCallback (const void *inputBuffer,
|
|||
}
|
||||
|
||||
if (data->mixerLoopbackFlag) {
|
||||
correctedYaw = correctedYaw > 0 ? correctedYaw + AGENT_LOOPBACK_MODIFIER : correctedYaw - AGENT_LOOPBACK_MODIFIER;
|
||||
correctedYaw = correctedYaw > 0
|
||||
? correctedYaw + AGENT_LOOPBACK_MODIFIER
|
||||
: correctedYaw - AGENT_LOOPBACK_MODIFIER;
|
||||
}
|
||||
|
||||
memcpy(currentPacketPtr, &correctedYaw, sizeof(float));
|
||||
currentPacketPtr += sizeof(float);
|
||||
|
||||
// if (samplesLeftForWalk == 0) {
|
||||
// sampleWalkPointer = walkingSoundArray;
|
||||
// }
|
||||
//
|
||||
// if (data->playWalkSound) {
|
||||
// // if this boolean is true and we aren't currently playing the walk sound
|
||||
// // set the number of samples left for walk
|
||||
// samplesLeftForWalk = walkingSoundSamples;
|
||||
// data->playWalkSound = false;
|
||||
// }
|
||||
//
|
||||
// if (samplesLeftForWalk > 0) {
|
||||
// // we need to play part of the walking sound
|
||||
// // so add it in
|
||||
// int affectedSamples = std::min(samplesLeftForWalk, BUFFER_LENGTH_SAMPLES);
|
||||
// for (int i = 0; i < affectedSamples; i++) {
|
||||
// inputLeft[i] += *sampleWalkPointer;
|
||||
// inputLeft[i] = std::max(inputLeft[i], std::numeric_limits<int16_t>::min());
|
||||
// inputLeft[i] = std::min(inputLeft[i], std::numeric_limits<int16_t>::max());
|
||||
//
|
||||
// sampleWalkPointer++;
|
||||
// samplesLeftForWalk--;
|
||||
//
|
||||
// if (sampleWalkPointer - walkingSoundArray > walkingSoundSamples) {
|
||||
// sampleWalkPointer = walkingSoundArray;
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
currentPacketPtr += sizeof(float);
|
||||
|
||||
// copy the audio data to the last BUFFER_LENGTH_BYTES bytes of the data packet
|
||||
memcpy(currentPacketPtr, inputLeft, BUFFER_LENGTH_BYTES);
|
||||
|
@ -239,26 +205,21 @@ int audioCallback (const void *inputBuffer,
|
|||
starve_counter++;
|
||||
packetsReceivedThisPlayback = 0;
|
||||
|
||||
//printLog("Starved #%d\n", starve_counter);
|
||||
// printLog("Starved #%d\n", starve_counter);
|
||||
data->wasStarved = 10; // Frames to render the indication that the system was starved.
|
||||
} else {
|
||||
if (!ringBuffer->isStarted()) {
|
||||
ringBuffer->setStarted(true);
|
||||
//printLog("starting playback %3.1f msecs delayed \n", (usecTimestampNow() - usecTimestamp(&firstPlaybackTimer))/1000.0);
|
||||
// printLog("starting playback %3.1f msecs delayed \n", (usecTimestampNow() - usecTimestamp(&firstPlaybackTimer))/1000.0);
|
||||
} else {
|
||||
//printLog("pushing buffer\n");
|
||||
// printLog("pushing buffer\n");
|
||||
}
|
||||
// play whatever we have in the audio buffer
|
||||
|
||||
//
|
||||
// if we haven't fired off the flange effect, check if we should
|
||||
//
|
||||
|
||||
//
|
||||
// NOTE: PER - LastMeasuredHeadYaw is now relative to body position, represents the local
|
||||
// rotation of the head relative to body, this may effect flange effect!
|
||||
//
|
||||
//
|
||||
// if we haven't fired off the flange effect, check if we should
|
||||
// TODO: lastMeasuredHeadYaw is now relative to body - check if this still works.
|
||||
|
||||
int lastYawMeasured = fabsf(data->linkedAvatar->getLastMeasuredHeadYaw());
|
||||
|
||||
if (!samplesLeftForFlange && lastYawMeasured > MIN_FLANGE_EFFECT_THRESHOLD) {
|
||||
|
@ -277,21 +238,6 @@ int audioCallback (const void *inputBuffer,
|
|||
}
|
||||
}
|
||||
|
||||
// check if we have more than we need to play out
|
||||
// int thresholdFrames = ceilf((PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) / (float)PACKET_LENGTH_SAMPLES);
|
||||
// int thresholdSamples = thresholdFrames * PACKET_LENGTH_SAMPLES;
|
||||
//
|
||||
// if (ringBuffer->diffLastWriteNextOutput() > thresholdSamples) {
|
||||
// // we need to push the next output forwards
|
||||
// int samplesToPush = ringBuffer->diffLastWriteNextOutput() - thresholdSamples;
|
||||
//
|
||||
// if (ringBuffer->getNextOutput() + samplesToPush > ringBuffer->getBuffer()) {
|
||||
// ringBuffer->setNextOutput(ringBuffer->getBuffer() + (samplesToPush - (ringBuffer->getBuffer() + RING_BUFFER_SAMPLES - ringBuffer->getNextOutput())));
|
||||
// } else {
|
||||
// ringBuffer->setNextOutput(ringBuffer->getNextOutput() + samplesToPush);
|
||||
// }
|
||||
// }
|
||||
|
||||
for (int s = 0; s < PACKET_LENGTH_SAMPLES_PER_CHANNEL; s++) {
|
||||
|
||||
int leftSample = ringBuffer->getNextOutput()[s];
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
const bool BALLS_ON = false;
|
||||
|
||||
float skinColor[] = {1.0, 0.84, 0.66};
|
||||
float lightBlue[] = { 0.7, 0.8, 1.0 };
|
||||
float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
||||
|
@ -129,6 +131,9 @@ Avatar::Avatar(bool isMine) {
|
|||
printLog("error %u: %s\n", error, lodepng_error_text(error));
|
||||
}
|
||||
}
|
||||
|
||||
if (BALLS_ON) { _balls = new Balls(100); }
|
||||
else { _balls = NULL; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -270,13 +275,16 @@ void Avatar::UpdateGyros(float frametime, SerialInterface * serialInterface, glm
|
|||
addLean(-measured_lateral_accel * frametime * HEAD_LEAN_SCALE, -measured_fwd_accel*frametime * HEAD_LEAN_SCALE);
|
||||
}
|
||||
|
||||
float Avatar::getAbsoluteHeadYaw() const {
|
||||
return _bodyYaw + _headYaw;
|
||||
}
|
||||
|
||||
void Avatar::addLean(float x, float z) {
|
||||
// Add Body lean as impulse
|
||||
_head.leanSideways += x;
|
||||
_head.leanForward += z;
|
||||
}
|
||||
|
||||
|
||||
void Avatar::setLeanForward(float dist){
|
||||
_head.leanForward = dist;
|
||||
}
|
||||
|
@ -291,6 +299,9 @@ void Avatar::setMousePressed( bool d ) {
|
|||
|
||||
void Avatar::simulate(float deltaTime) {
|
||||
|
||||
// update balls
|
||||
if (_balls) { _balls->simulate(deltaTime); }
|
||||
|
||||
// update avatar skeleton
|
||||
updateSkeleton();
|
||||
|
||||
|
@ -635,6 +646,15 @@ void Avatar::render(bool lookingInMirror) {
|
|||
}
|
||||
}
|
||||
|
||||
// Render the balls
|
||||
|
||||
if (_balls) {
|
||||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
_balls->render();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
if (!_chatMessage.empty()) {
|
||||
float width = 0;
|
||||
float lastWidth;
|
||||
|
@ -675,7 +695,6 @@ void Avatar::render(bool lookingInMirror) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Avatar::renderHead(bool lookingInMirror) {
|
||||
int side = 0;
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <glm/gtx/quaternion.hpp> //looks like we might not need this
|
||||
|
||||
#include "Balls.h"
|
||||
|
||||
const bool AVATAR_GRAVITY = true;
|
||||
const float DECAY = 0.1;
|
||||
const float THRUST_MAG = 10.0;
|
||||
|
@ -165,18 +167,21 @@ public:
|
|||
|
||||
void reset();
|
||||
void UpdateGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
|
||||
|
||||
void setNoise (float mag) { _head.noise = mag; }
|
||||
void setScale(float s) {_head.scale = s; };
|
||||
void setRenderYaw(float y) {_renderYaw = y;}
|
||||
void setRenderPitch(float p) {_renderPitch = p;}
|
||||
float getRenderYaw() {return _renderYaw;}
|
||||
float getRenderPitch() {return _renderPitch;}
|
||||
void setLeanForward(float dist);
|
||||
void setLeanSideways(float dist);
|
||||
void addLean(float x, float z);
|
||||
float getLastMeasuredHeadYaw() const {return _head.yawRate;}
|
||||
float getBodyYaw() {return _bodyYaw;};
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
|
||||
float getAbsoluteHeadYaw() const;
|
||||
void setLeanForward(float dist);
|
||||
void setLeanSideways(float dist);
|
||||
void addLean(float x, float z);
|
||||
|
||||
const glm::vec3& getHeadLookatDirection() const { return _orientation.getFront(); };
|
||||
const glm::vec3& getHeadLookatDirectionUp() const { return _orientation.getUp(); };
|
||||
|
@ -253,7 +258,9 @@ private:
|
|||
bool _interactingOtherIsNearby;
|
||||
float _pelvisStandingHeight;
|
||||
|
||||
void initializeSkeleton();
|
||||
Balls* _balls;
|
||||
|
||||
void initializeSkeleton();
|
||||
void updateSkeleton();
|
||||
void initializeBodySprings();
|
||||
void updateBodySprings( float deltaTime );
|
||||
|
@ -265,6 +272,7 @@ private:
|
|||
float collisionHeight,
|
||||
glm::vec3 collisionUpVector,
|
||||
float deltaTime);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
106
interface/src/Balls.cpp
Normal file
106
interface/src/Balls.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// Balls.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Philip on 4/25/13.
|
||||
//
|
||||
// A cloud of spring-mass spheres to simulate the avatar body/skin. Each ball
|
||||
// connects to as many as 4 neighbors, and executes motion according to a damped
|
||||
// spring, while responding physically to other avatars.
|
||||
//
|
||||
|
||||
#include "Balls.h"
|
||||
|
||||
Balls::Balls(int numberOfBalls) {
|
||||
_numberOfBalls = numberOfBalls;
|
||||
_balls = new Ball[_numberOfBalls];
|
||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||
_balls[i].position = glm::vec3(1.0 + randFloat()*0.5,
|
||||
0.5 + randFloat()*0.5,
|
||||
1.0 + randFloat()*0.5);
|
||||
_balls[i].radius = 0.02 + randFloat()*0.06;
|
||||
for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) {
|
||||
_balls[i].links[j] = rand() % (numberOfBalls + 1);
|
||||
if (_balls[i].links[j]-1 == i) { _balls[i].links[j] = 0; }
|
||||
_balls[i].springLength[j] = 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool RENDER_SPRINGS = true;
|
||||
|
||||
void Balls::render() {
|
||||
|
||||
// Render Balls NOTE: This needs to become something other that GlutSpheres!
|
||||
glColor3f(0.62,0.74,0.91);
|
||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||
glPushMatrix();
|
||||
glTranslatef(_balls[i].position.x, _balls[i].position.y, _balls[i].position.z);
|
||||
glutSolidSphere(_balls[i].radius, 15, 15);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// Render springs
|
||||
if (RENDER_SPRINGS) {
|
||||
glColor3f(0.74,0.91,0.62);
|
||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||
glBegin(GL_LINES);
|
||||
for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) {
|
||||
if(_balls[i].links[j] > 0) {
|
||||
glVertex3f(_balls[i].position.x,
|
||||
_balls[i].position.y,
|
||||
_balls[i].position.z);
|
||||
glVertex3f(_balls[_balls[i].links[j]-1].position.x,
|
||||
_balls[_balls[i].links[j]-1].position.y,
|
||||
_balls[_balls[i].links[j]-1].position.z);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const float CONSTANT_VELOCITY_DAMPING = 1.0f;
|
||||
const float NOISE_SCALE = 0.00;
|
||||
const float SPRING_FORCE = 1.0;
|
||||
const float SPRING_DAMPING = 1.0;
|
||||
|
||||
void Balls::simulate(float deltaTime) {
|
||||
for (unsigned int i = 0; i < _numberOfBalls; ++i) {
|
||||
|
||||
// Move particles
|
||||
_balls[i].position += _balls[i].velocity * deltaTime;
|
||||
|
||||
// Drag: decay velocity
|
||||
_balls[i].velocity *= (1.f - CONSTANT_VELOCITY_DAMPING*deltaTime);
|
||||
|
||||
// Add noise
|
||||
_balls[i].velocity += glm::vec3((randFloat() - 0.5) * NOISE_SCALE,
|
||||
(randFloat() - 0.5) * NOISE_SCALE,
|
||||
(randFloat() - 0.5) * NOISE_SCALE);
|
||||
|
||||
// Spring Force
|
||||
|
||||
|
||||
for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) {
|
||||
if(_balls[i].links[j] > 0) {
|
||||
float separation = glm::distance(_balls[i].position,
|
||||
_balls[_balls[i].links[j]-1].position);
|
||||
_balls[i].velocity += glm::normalize(_balls[i].position -
|
||||
_balls[_balls[i].links[j]-1].position) *
|
||||
deltaTime *
|
||||
SPRING_FORCE *
|
||||
(_balls[i].springLength[j] - separation);
|
||||
|
||||
//_balls[i].velocity *= (1.f - SPRING_DAMPING*deltaTime);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
37
interface/src/Balls.h
Normal file
37
interface/src/Balls.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Balls.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Philip on 4/25/13.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef hifi_Balls_h
|
||||
#define hifi_Balls_h
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
|
||||
const int NUMBER_SPRINGS = 4;
|
||||
|
||||
class Balls {
|
||||
public:
|
||||
Balls(int numberOfBalls);
|
||||
|
||||
void simulate(float deltaTime);
|
||||
void render();
|
||||
|
||||
private:
|
||||
struct Ball {
|
||||
glm::vec3 position, velocity;
|
||||
int links[NUMBER_SPRINGS];
|
||||
float springLength[NUMBER_SPRINGS];
|
||||
float radius;
|
||||
} *_balls;
|
||||
int _numberOfBalls;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,244 +0,0 @@
|
|||
//
|
||||
// Particle.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Seiji Emery on 9/4/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Particle.h"
|
||||
|
||||
#define NUM_ELEMENTS 4
|
||||
|
||||
glm::vec3 color0(1,0,0); // Motionless particle
|
||||
glm::vec3 color1(0,1,0); // Spring force
|
||||
glm::vec3 color2(0,0,1);
|
||||
glm::vec3 color3(0,1,1);
|
||||
|
||||
float radii[NUM_ELEMENTS] = {0.3f, 0.5f, 0.2f, 0.4f};
|
||||
|
||||
ParticleSystem::ParticleSystem(int num,
|
||||
glm::vec3 box,
|
||||
int wrap,
|
||||
float noiselevel,
|
||||
float setscale,
|
||||
float setgravity) {
|
||||
// Create and initialize particles
|
||||
int element;
|
||||
bounds = box;
|
||||
count = num;
|
||||
wrapBounds = false;
|
||||
noise = noiselevel;
|
||||
gravity = setgravity;
|
||||
scale = setscale;
|
||||
particles = new Particle[count];
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
particles[i].position.x = randFloat()*box.x;
|
||||
particles[i].position.y = randFloat()*box.y;
|
||||
particles[i].position.z = randFloat()*box.z;
|
||||
|
||||
// Constrain to a small box in center
|
||||
//particles[i].position.x = randFloat()+box.x/2.0;
|
||||
//particles[i].position.y = randFloat()+box.y/2.0;
|
||||
//particles[i].position.z = randFloat()+box.z/2.0;
|
||||
|
||||
particles[i].velocity.x = 0;
|
||||
particles[i].velocity.y = 0;
|
||||
particles[i].velocity.z = 0;
|
||||
|
||||
particles[i].parent = 0;
|
||||
particles[i].link *= 0;
|
||||
|
||||
element = 1; //rand()%NUM_ELEMENTS;
|
||||
particles[i].element = element;
|
||||
|
||||
if (element == 0) particles[i].color = color0;
|
||||
else if (element == 1) particles[i].color = color1;
|
||||
else if (element == 2) particles[i].color = color2;
|
||||
else if (element == 3) particles[i].color = color3;
|
||||
|
||||
particles[i].radius = 0.10f; //radii[element]*scale;
|
||||
particles[i].isColliding = false;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool ParticleSystem::updateHand(glm::vec3 pos, glm::vec3 vel, float radius) {
|
||||
handPos = pos;
|
||||
handVel = vel;
|
||||
handRadius = radius;
|
||||
return handIsColliding;
|
||||
}
|
||||
|
||||
void ParticleSystem::resetHand() {
|
||||
handActive = false;
|
||||
handIsColliding = false;
|
||||
handPos = glm::vec3(0,0,0);
|
||||
handVel = glm::vec3(0,0,0);
|
||||
handRadius = 0;
|
||||
}
|
||||
|
||||
void ParticleSystem::render() {
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
glPushMatrix();
|
||||
glTranslatef(particles[i].position.x, particles[i].position.y, particles[i].position.z);
|
||||
if (particles[i].numSprung == 0) glColor3f(1,1,1);
|
||||
else if (particles[i].numSprung == 1) glColor3f(0,1,0);
|
||||
else if (particles[i].numSprung == 2) glColor3f(1,1,0);
|
||||
else if (particles[i].numSprung >= 3) glColor3f(1,0,0);
|
||||
glutSolidSphere(particles[i].radius, 15, 15);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleSystem::link(int child, int parent) {
|
||||
particles[child].parent = parent;
|
||||
particles[child].velocity *= 0.5;
|
||||
particles[parent].velocity += particles[child].velocity;
|
||||
particles[child].velocity *= 0.0;
|
||||
particles[child].color = glm::vec3(1,1,0);
|
||||
particles[child].link = particles[parent].position - particles[child].position;
|
||||
}
|
||||
|
||||
void ParticleSystem::simulate (float deltaTime) {
|
||||
unsigned int i, j;
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (particles[i].element != 0) {
|
||||
|
||||
if (particles[i].parent == 0) {
|
||||
// Move particles
|
||||
particles[i].position += particles[i].velocity * deltaTime;
|
||||
|
||||
// Add gravity
|
||||
particles[i].velocity.y -= gravity*deltaTime;
|
||||
|
||||
// Drag: decay velocity
|
||||
const float CONSTANT_DAMPING = 0.1f;
|
||||
particles[i].velocity *= (1.f - CONSTANT_DAMPING*deltaTime);
|
||||
|
||||
// Add velocity from field
|
||||
//Field::addTo(particles[i].velocity);
|
||||
//particles[i].velocity += Field::valueAt(particles[i].position);
|
||||
|
||||
// Add noise
|
||||
const float RAND_VEL = 0.05f;
|
||||
if (noise) {
|
||||
if (1) {
|
||||
particles[i].velocity += glm::vec3((randFloat() - 0.5)*RAND_VEL,
|
||||
(randFloat() - 0.5)*RAND_VEL,
|
||||
(randFloat() - 0.5)*RAND_VEL);
|
||||
}
|
||||
if (randFloat() < noise*deltaTime) {
|
||||
particles[i].velocity += glm::vec3((randFloat() - 0.5)*RAND_VEL*100,
|
||||
(randFloat() - 0.5)*RAND_VEL*100,
|
||||
(randFloat() - 0.5)*RAND_VEL*100);
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
particles[i].position = particles[particles[i].parent].position + particles[i].link;
|
||||
}
|
||||
|
||||
|
||||
// Check for collision with manipulator hand
|
||||
particles[i].isColliding = (glm::vec3(particles[i].position - handPos).length() <
|
||||
(radius + handRadius));
|
||||
|
||||
// Check for collision with other balls
|
||||
float separation;
|
||||
const float HARD_SPHERE_FORCE = 100.0;
|
||||
const float SPRING_FORCE = 10.0;
|
||||
const float SPRING_DAMPING = 0.5;
|
||||
float spring_length = 0.5; //2*radii[1];
|
||||
float spring_range = spring_length * 1.2f;
|
||||
float contact;
|
||||
|
||||
particles[i].isColliding = false;
|
||||
particles[i].numSprung = 0;
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
if ((j != i) &&
|
||||
(!particles[i].parent)) {
|
||||
separation = glm::distance(particles[i].position, particles[j].position);
|
||||
contact = particles[i].radius + particles[j].radius;
|
||||
|
||||
// Hard Sphere Scattering
|
||||
|
||||
if (separation < contact) {
|
||||
particles[i].velocity += glm::normalize(particles[i].position - particles[j].position)*deltaTime*HARD_SPHERE_FORCE*(contact - separation);
|
||||
particles[i].isColliding = true;
|
||||
}
|
||||
|
||||
// Spring Action
|
||||
if ((particles[i].element == 1) && (separation < spring_range)) {
|
||||
particles[i].velocity += glm::normalize(particles[i].position - particles[j].position)*deltaTime*SPRING_FORCE*(spring_length - separation);
|
||||
particles[i].velocity *= (1.f - SPRING_DAMPING*deltaTime);
|
||||
particles[i].numSprung++;
|
||||
}
|
||||
|
||||
// Link!
|
||||
if ((particles[i].parent == 0) &&
|
||||
(particles[j].parent != i) &&
|
||||
(separation > 0.9*(particles[j].radius + particles[i].radius)) &&
|
||||
(separation < 1.0*(particles[j].radius + particles[i].radius)) ) {
|
||||
// Link i to j!!
|
||||
//link(i, j);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!particles[i].parent) {
|
||||
if (wrapBounds) {
|
||||
// wrap around bounds
|
||||
if (particles[i].position.x > bounds.x)
|
||||
particles[i].position.x -= bounds.x;
|
||||
else if (particles[i].position.x < 0.0f)
|
||||
particles[i].position.x += bounds.x;
|
||||
|
||||
if (particles[i].position.y > bounds.y)
|
||||
particles[i].position.y -= bounds.y;
|
||||
else if (particles[i].position.y < 0.0f)
|
||||
particles[i].position.y += bounds.y;
|
||||
|
||||
if (particles[i].position.z > bounds.z)
|
||||
particles[i].position.z -= bounds.z;
|
||||
else if (particles[i].position.z < 0.0f)
|
||||
particles[i].position.z += bounds.z;
|
||||
} else {
|
||||
// Bounce at bounds
|
||||
if (particles[i].position.x > bounds.x
|
||||
|| particles[i].position.x < 0.f) {
|
||||
if (particles[i].position.x > bounds.x) particles[i].position.x = bounds.x;
|
||||
else particles[i].position.x = 0.f;
|
||||
particles[i].velocity.x *= -1;
|
||||
}
|
||||
if (particles[i].position.y > bounds.y
|
||||
|| particles[i].position.y < 0.f) {
|
||||
if (particles[i].position.y > bounds.y) particles[i].position.y = bounds.y;
|
||||
else particles[i].position.y = 0.f;
|
||||
particles[i].velocity.y *= -1;
|
||||
}
|
||||
if (particles[i].position.z > bounds.z
|
||||
|| particles[i].position.z < 0.f) {
|
||||
if (particles[i].position.z > bounds.z) particles[i].position.z = bounds.z;
|
||||
else particles[i].position.z = 0.f;
|
||||
particles[i].velocity.z *= -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// Particle.h
|
||||
// interface
|
||||
//
|
||||
// Created by Seiji Emery on 9/4/12.
|
||||
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__Particle__
|
||||
#define __interface__Particle__
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class ParticleSystem {
|
||||
public:
|
||||
ParticleSystem(int num,
|
||||
glm::vec3 box,
|
||||
int wrap,
|
||||
float noiselevel,
|
||||
float setscale,
|
||||
float setgravity);
|
||||
|
||||
void simulate(float deltaTime);
|
||||
void render();
|
||||
bool updateHand(glm::vec3 pos, glm::vec3 vel, float radius);
|
||||
|
||||
private:
|
||||
struct Particle {
|
||||
glm::vec3 position, velocity, color, link;
|
||||
int element;
|
||||
int parent;
|
||||
float radius;
|
||||
bool isColliding;
|
||||
int numSprung;
|
||||
} *particles;
|
||||
unsigned int count;
|
||||
|
||||
glm::vec3 bounds;
|
||||
|
||||
float radius;
|
||||
bool wrapBounds;
|
||||
float noise;
|
||||
float gravity;
|
||||
float scale;
|
||||
glm::vec3 color;
|
||||
|
||||
void link(int child, int parent);
|
||||
|
||||
// Manipulator from outside
|
||||
void resetHand();
|
||||
bool handActive;
|
||||
bool handIsColliding;
|
||||
glm::vec3 handPos;
|
||||
glm::vec3 handVel;
|
||||
float handRadius;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -64,7 +64,6 @@
|
|||
#include "Camera.h"
|
||||
#include "ChatEntry.h"
|
||||
#include "Avatar.h"
|
||||
#include "Particle.h"
|
||||
#include "Texture.h"
|
||||
#include "Cloud.h"
|
||||
#include <AgentList.h>
|
||||
|
@ -116,14 +115,6 @@ bool showingVoxels = true;
|
|||
|
||||
glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
||||
|
||||
ParticleSystem balls(0,
|
||||
box,
|
||||
false, // Wrap?
|
||||
0.02f, // Noise
|
||||
0.3f, // Size scale
|
||||
0.0 // Gravity
|
||||
);
|
||||
|
||||
Cloud cloud(0, // Particles
|
||||
box, // Bounding Box
|
||||
false // Wrap
|
||||
|
@ -941,9 +932,7 @@ void display(void)
|
|||
avatar->render(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !::lookingInMirror ) balls.render();
|
||||
|
||||
|
||||
// Render the world box
|
||||
if (!::lookingInMirror && ::statsOn) { render_world_box(); }
|
||||
|
||||
|
@ -1560,7 +1549,6 @@ void idle(void) {
|
|||
|
||||
field.simulate (deltaTime);
|
||||
myAvatar.simulate(deltaTime);
|
||||
balls.simulate (deltaTime);
|
||||
cloud.simulate (deltaTime);
|
||||
|
||||
glutPostRedisplay();
|
||||
|
|
Loading…
Reference in a new issue