Colliding with ground, voxels makes interesting sounds and flashes your display

This commit is contained in:
Philip Rosedale 2013-07-16 16:40:50 -07:00
parent be30a27a4f
commit 192ae63789
8 changed files with 97 additions and 58 deletions

View file

@ -188,6 +188,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
_isTouchPressed(false), _isTouchPressed(false),
_yawFromTouch(0.0f), _yawFromTouch(0.0f),
_pitchFromTouch(0.0f), _pitchFromTouch(0.0f),
_groundPlaneImpact(0.0f),
_mousePressed(false), _mousePressed(false),
_mouseVoxelScale(1.0f / 1024.0f), _mouseVoxelScale(1.0f / 1024.0f),
_justEditedVoxel(false), _justEditedVoxel(false),
@ -2516,7 +2517,7 @@ void Application::displaySide(Camera& whichCamera) {
//draw a grid ground plane.... //draw a grid ground plane....
if (_renderGroundPlaneOn->isChecked()) { if (_renderGroundPlaneOn->isChecked()) {
drawGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE); renderGroundPlaneGrid(EDGE_SIZE_GROUND_PLANE, _audio.getCollisionSoundMagnitude());
} }
// Draw voxels // Draw voxels
if (_renderVoxels->isChecked()) { if (_renderVoxels->isChecked()) {
@ -2592,6 +2593,9 @@ void Application::displayOverlay() {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
// Display a single screen-size quad to
renderCollisionOverlay(_glWidget->width(), _glWidget->height(), _audio.getCollisionSoundMagnitude());
#ifndef _WIN32 #ifndef _WIN32
_audio.render(_glWidget->width(), _glWidget->height()); _audio.render(_glWidget->width(), _glWidget->height());
if (_oscilloscopeOn->isChecked()) { if (_oscilloscopeOn->isChecked()) {

View file

@ -101,6 +101,9 @@ public:
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; } QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
GeometryCache* getGeometryCache() { return &_geometryCache; } GeometryCache* getGeometryCache() { return &_geometryCache; }
void setGroundPlaneImpact(float groundPlaneImpact) { _groundPlaneImpact = groundPlaneImpact; }
private slots: private slots:
void timer(); void timer();
@ -206,7 +209,7 @@ private:
void deleteVoxelUnderCursor(); void deleteVoxelUnderCursor();
void eyedropperVoxelUnderCursor(); void eyedropperVoxelUnderCursor();
void resetSensors(); void resetSensors();
void setMenuShortcutsEnabled(bool enabled); void setMenuShortcutsEnabled(bool enabled);
void updateCursor(); void updateCursor();
@ -344,6 +347,8 @@ private:
float _yawFromTouch; float _yawFromTouch;
float _pitchFromTouch; float _pitchFromTouch;
float _groundPlaneImpact;
VoxelDetail _mouseVoxelDragging; VoxelDetail _mouseVoxelDragging;
glm::vec3 _voxelThrust; glm::vec3 _voxelThrust;
bool _mousePressed; // true if mouse has been pressed (clear when finished) bool _mousePressed; // true if mouse has been pressed (clear when finished)

View file

@ -605,11 +605,7 @@ void Audio::addProceduralSounds(int16_t* inputBuffer,
float speed = glm::length(_lastVelocity); float speed = glm::length(_lastVelocity);
float volume = VOLUME_BASELINE * (1.f - speed / MAX_AUDIBLE_VELOCITY); float volume = VOLUME_BASELINE * (1.f - speed / MAX_AUDIBLE_VELOCITY);
// Test tone (should be continuous!) int sample;
/*
for (int i = 0; i < numSamples; i++) {
inputBuffer[i] += (int16_t) (_proceduralEffectSample + i)%16 * 10;
}*/
// //
// Travelling noise // Travelling noise
@ -617,32 +613,32 @@ void Audio::addProceduralSounds(int16_t* inputBuffer,
// Add a noise-modulated sinewave with volume that tapers off with speed increasing // Add a noise-modulated sinewave with volume that tapers off with speed increasing
if ((speed > MIN_AUDIBLE_VELOCITY) && (speed < MAX_AUDIBLE_VELOCITY)) { if ((speed > MIN_AUDIBLE_VELOCITY) && (speed < MAX_AUDIBLE_VELOCITY)) {
for (int i = 0; i < numSamples; i++) { for (int i = 0; i < numSamples; i++) {
//inputBuffer[i] += (int16_t)((sinf((float) (_proceduralEffectSample + i) / SOUND_PITCH * speed) * (1.f + randFloat() * 0.0f)) * volume * speed);
inputBuffer[i] += (int16_t)(sinf((float) (_proceduralEffectSample + i) / SOUND_PITCH ) * volume * (1.f + randFloat() * 0.25f) * speed); inputBuffer[i] += (int16_t)(sinf((float) (_proceduralEffectSample + i) / SOUND_PITCH ) * volume * (1.f + randFloat() * 0.25f) * speed);
} }
} }
const float COLLISION_SOUND_CUTOFF_LEVEL = 5.0f; const float COLLISION_SOUND_CUTOFF_LEVEL = 0.01f;
int sample; const float COLLISION_SOUND_MAX_VOLUME = 1000.f;
const float UP_MAJOR_FIFTH = powf(1.5f, 4.0f);
float t;
if (_collisionSoundMagnitude > COLLISION_SOUND_CUTOFF_LEVEL) { if (_collisionSoundMagnitude > COLLISION_SOUND_CUTOFF_LEVEL) {
for (int i = 0; i < numSamples; i++) { for (int i = 0; i < numSamples; i++) {
sample = (int16_t) (((sinf(((float)_proceduralEffectSample + (float)i) * _collisionSoundFrequency) * (1.f - _collisionSoundNoise) t = (float) _proceduralEffectSample + (float) i;
+ ((randFloat() * 2.f - 1.0f) * _collisionSoundNoise)) sample = sinf(t * _collisionSoundFrequency) +
* _collisionSoundMagnitude)); sinf(t * _collisionSoundFrequency / 4.f) +
sinf(t * _collisionSoundFrequency / 16.f * UP_MAJOR_FIFTH);
sample *= _collisionSoundMagnitude * COLLISION_SOUND_MAX_VOLUME;
inputBuffer[i] += sample; inputBuffer[i] += sample;
outputLeft[i] += sample; outputLeft[i] += sample;
outputRight[i] += sample; outputRight[i] += sample;
_collisionSoundMagnitude *= _collisionSoundDuration; _collisionSoundMagnitude *= _collisionSoundDuration;
} }
} }
//if (_heartbeatMagnitude > 0.0f) {
//
//}
_proceduralEffectSample += numSamples; _proceduralEffectSample += numSamples;
} }
//
// Starts a collision sound. magnitude is 0-1, with 1 the loudest possible sound.
//
void Audio::startCollisionSound(float magnitude, float frequency, float noise, float duration) { void Audio::startCollisionSound(float magnitude, float frequency, float noise, float duration) {
_collisionSoundMagnitude = magnitude; _collisionSoundMagnitude = magnitude;
_collisionSoundFrequency = frequency; _collisionSoundFrequency = frequency;

View file

@ -43,10 +43,10 @@ public:
int getJitterBufferSamples() { return _jitterBufferSamples; }; int getJitterBufferSamples() { return _jitterBufferSamples; };
void lowPassFilter(int16_t* inputBuffer); void lowPassFilter(int16_t* inputBuffer);
void setCollisionSoundMagnitude(float collisionSoundMagnitude) { _collisionSoundMagnitude = collisionSoundMagnitude; }
void startCollisionSound(float magnitude, float frequency, float noise, float duration); void startCollisionSound(float magnitude, float frequency, float noise, float duration);
float getCollisionSoundMagnitude() { return _collisionSoundMagnitude; };
void ping(); void ping();

View file

@ -545,8 +545,8 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) {
_position += _scale * _gravity * (GRAVITY_EARTH * deltaTime) * deltaTime; _position += _scale * _gravity * (GRAVITY_EARTH * deltaTime) * deltaTime;
} }
updateCollisionWithEnvironment(); updateCollisionWithEnvironment(deltaTime);
updateCollisionWithVoxels(); updateCollisionWithVoxels(deltaTime);
updateAvatarCollisions(deltaTime); updateAvatarCollisions(deltaTime);
} }
@ -867,7 +867,7 @@ void Avatar::updateCollisionWithSphere(glm::vec3 position, float radius, float d
} }
} }
void Avatar::updateCollisionWithEnvironment() { void Avatar::updateCollisionWithEnvironment(float deltaTime) {
glm::vec3 up = getBodyUpDirection(); glm::vec3 up = getBodyUpDirection();
float radius = _height * 0.125f; float radius = _height * 0.125f;
@ -878,7 +878,12 @@ void Avatar::updateCollisionWithEnvironment() {
if (Application::getInstance()->getEnvironment()->findCapsulePenetration( if (Application::getInstance()->getEnvironment()->findCapsulePenetration(
_position - up * (_pelvisFloatingHeight - radius), _position - up * (_pelvisFloatingHeight - radius),
_position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) { _position + up * (_height - _pelvisFloatingHeight - radius), radius, penetration)) {
createCollisionSound(penetration, ENVIRONMENT_COLLISION_FREQUENCY); float velocityTowardCollision = glm::dot(_velocity, glm::normalize(penetration));
if (velocityTowardCollision > 0.2) {
Application::getInstance()->setGroundPlaneImpact(1.0f);
}
updateCollisionSound(penetration, deltaTime, ENVIRONMENT_COLLISION_FREQUENCY);
applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING); applyHardCollision(penetration, ENVIRONMENT_SURFACE_ELASTICITY, ENVIRONMENT_SURFACE_DAMPING);
@ -886,7 +891,7 @@ void Avatar::updateCollisionWithEnvironment() {
} }
void Avatar::updateCollisionWithVoxels() { void Avatar::updateCollisionWithVoxels(float deltaTime) {
float radius = _height * 0.125f; float radius = _height * 0.125f;
const float VOXEL_ELASTICITY = 1.4f; const float VOXEL_ELASTICITY = 1.4f;
const float VOXEL_DAMPING = 0.0; const float VOXEL_DAMPING = 0.0;
@ -895,7 +900,7 @@ void Avatar::updateCollisionWithVoxels() {
if (Application::getInstance()->getVoxels()->findCapsulePenetration( if (Application::getInstance()->getVoxels()->findCapsulePenetration(
_position - glm::vec3(0.0f, _pelvisFloatingHeight - radius, 0.0f), _position - glm::vec3(0.0f, _pelvisFloatingHeight - radius, 0.0f),
_position + glm::vec3(0.0f, _height - _pelvisFloatingHeight - radius, 0.0f), radius, penetration)) { _position + glm::vec3(0.0f, _height - _pelvisFloatingHeight - radius, 0.0f), radius, penetration)) {
createCollisionSound(penetration, VOXEL_COLLISION_FREQUENCY); updateCollisionSound(penetration, deltaTime, VOXEL_COLLISION_FREQUENCY);
applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING);
} }
} }
@ -924,26 +929,34 @@ void Avatar::applyHardCollision(const glm::vec3& penetration, float elasticity,
} }
} }
void Avatar::createCollisionSound(const glm::vec3 &penetration, float frequency) { void Avatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTime, float frequency) {
// Push the collision into the audio system for procedural effects // consider whether to have the collision make a sound
const float AUDIBLE_COLLISION_THRESHOLD = 0.2f; const float AUDIBLE_COLLISION_THRESHOLD = 0.02f;
const float COLLISION_VOLUME = 1000.f; const float COLLISION_LOUDNESS = 1.f;
const float MAX_COLLISION_VOLUME = 15000.f;
const float DURATION_SCALING = 0.004f; const float DURATION_SCALING = 0.004f;
float velocityTowardCollision = glm::dot(_velocity, glm::normalize(penetration)); const float NOISE_SCALING = 0.1f;
float velocityTangentToCollision = glm::length(_velocity) - velocityTowardCollision; glm::vec3 velocity = _velocity;
if (velocityTowardCollision > AUDIBLE_COLLISION_THRESHOLD) { glm::vec3 gravity = getGravity();
Application::getInstance()->getAudio()->startCollisionSound(
fmax(COLLISION_VOLUME * velocityTowardCollision, MAX_COLLISION_VOLUME), if (glm::length(gravity) > EPSILON) {
frequency, // If gravity is on, remove the effect of gravity on velocity for this
fmin(velocityTangentToCollision / velocityTowardCollision, 1.f), // frame, so that we are not constantly colliding with the surface
1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision); velocity -= _scale * glm::length(gravity) * GRAVITY_EARTH * deltaTime * glm::normalize(gravity);
}
float velocityTowardCollision = glm::dot(velocity, glm::normalize(penetration));
float velocityTangentToCollision = glm::length(velocity) - velocityTowardCollision;
if (velocityTowardCollision > AUDIBLE_COLLISION_THRESHOLD) {
// Volume is proportional to collision velocity
// Base frequency is modified upward by the angle of the collision
// Noise is a function of the angle of collision
// Duration of the sound is a function of both base frequency and velocity of impact
Application::getInstance()->getAudio()->startCollisionSound(
fmin(COLLISION_LOUDNESS * velocityTowardCollision, 1.f),
frequency * (1.f + velocityTangentToCollision / velocityTowardCollision),
fmin(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.f),
1.f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision);
} }
//float collisionSoundLevel = penetrationLength * COLLISION_VOLUME;
//if (collisionSoundLevel > AUDIBLE_COLLISION_THRESHOLD) {
// Application::getInstance()->getAudio()->setCollisionSoundMagnitude(collisionSoundLevel);
//}
} }
void Avatar::updateAvatarCollisions(float deltaTime) { void Avatar::updateAvatarCollisions(float deltaTime) {

View file

@ -159,6 +159,8 @@ public:
glm::quat getOrientation () const; glm::quat getOrientation () const;
glm::quat getWorldAlignedOrientation() const; glm::quat getWorldAlignedOrientation() const;
glm::vec3 getGravity () const { return _gravity; }
glm::vec3 getUprightHeadPosition() const; glm::vec3 getUprightHeadPosition() const;
AvatarVoxelSystem* getVoxels() { return &_voxels; } AvatarVoxelSystem* getVoxels() { return &_voxels; }
@ -259,10 +261,10 @@ private:
void updateAvatarCollisions(float deltaTime); void updateAvatarCollisions(float deltaTime);
void updateArmIKAndConstraints( float deltaTime ); void updateArmIKAndConstraints( float deltaTime );
void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
void updateCollisionWithEnvironment(); void updateCollisionWithEnvironment(float deltaTime);
void updateCollisionWithVoxels(); void updateCollisionWithVoxels(float deltaTime);
void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping); void applyHardCollision(const glm::vec3& penetration, float elasticity, float damping);
void createCollisionSound(const glm::vec3& penetration, float frequency); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency);
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
void checkForMouseRayTouching(); void checkForMouseRayTouching();
}; };

View file

@ -326,22 +326,38 @@ void drawvec3(int x, int y, float scale, float rotate, float thick, int mono, gl
glPopMatrix(); glPopMatrix();
} }
void renderCollisionOverlay(int width, int height, float magnitude) {
const float MIN_VISIBLE_COLLISION = 0.01f;
if (magnitude > MIN_VISIBLE_COLLISION) {
glColor4f(0, 0, 0, magnitude);
glBegin(GL_QUADS);
glVertex2f(0, 0);
glVertex2d(width, 0);
glVertex2d(width, height);
glVertex2d(0, height);
glEnd();
}
}
void drawGroundPlaneGrid(float size) { void renderGroundPlaneGrid(float size, float impact) {
glColor3f(0.4f, 0.5f, 0.3f);
glLineWidth(2.0); glLineWidth(2.0);
glm::vec4 impactColor(1, 0, 0, 1);
glm::vec3 lineColor(0.4, 0.5, 0.3);
glm::vec4 surfaceColor(0.5, 0.5, 0.5, 0.4);
glColor3fv(&lineColor.x);
for (float x = 0; x <= size; x++) { for (float x = 0; x <= size; x++) {
glBegin(GL_LINES); glBegin(GL_LINES);
glVertex3f(x, 0.0f, 0); glVertex3f(x, 0, 0);
glVertex3f(x, 0.0f, size); glVertex3f(x, 0, size);
glVertex3f(0, 0.0f, x); glVertex3f(0, 0, x);
glVertex3f(size, 0.0f, x); glVertex3f(size, 0, x);
glEnd(); glEnd();
} }
// Draw a translucent quad just underneath the grid. // Draw the floor, colored for recent impact
glColor4f(0.5, 0.5, 0.5, 0.4); glm::vec4 floorColor = impact * impactColor + (1.f - impact) * surfaceColor;
glColor4fv(&floorColor.x);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glVertex3f(0, 0, 0); glVertex3f(0, 0, 0);
glVertex3f(size, 0, 0); glVertex3f(size, 0, 0);

View file

@ -57,7 +57,10 @@ glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha);
double diffclock(timeval *clock1,timeval *clock2); double diffclock(timeval *clock1,timeval *clock2);
void drawGroundPlaneGrid(float size); void renderGroundPlaneGrid(float size, float impact);
void renderCollisionOverlay(int width, int height, float magnitude);
void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness); void renderDiskShadow(glm::vec3 position, glm::vec3 upDirection, float radius, float darkness);