This commit is contained in:
atlante45 2013-08-05 15:26:43 -07:00
commit 55e34558cb
11 changed files with 273 additions and 163 deletions

View file

@ -2254,7 +2254,7 @@ Avatar* Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3
if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) { if (node->getLinkedData() != NULL && node->getType() == NODE_TYPE_AGENT) {
Avatar* avatar = (Avatar *) node->getLinkedData(); Avatar* avatar = (Avatar *) node->getLinkedData();
glm::vec3 headPosition = avatar->getHead().getPosition(); glm::vec3 headPosition = avatar->getHead().getPosition();
if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS)) { if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition, HEAD_SPHERE_RADIUS * avatar->getScale())) {
eyePosition = avatar->getHead().getEyePosition(); eyePosition = avatar->getHead().getEyePosition();
_lookatIndicatorScale = avatar->getScale(); _lookatIndicatorScale = avatar->getScale();
_lookatOtherPosition = headPosition; _lookatOtherPosition = headPosition;
@ -2266,6 +2266,16 @@ Avatar* Application::isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3
return NULL; return NULL;
} }
bool Application::isLookingAtMyAvatar(Avatar* avatar) {
glm::vec3 theirLookat = avatar->getHead().getLookAtPosition();
glm::vec3 myHeadPosition = _myAvatar.getHead().getPosition();
if (pointInSphere(theirLookat, myHeadPosition, HEAD_SPHERE_RADIUS * _myAvatar.getScale())) {
return true;
}
return false;
}
void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) { void Application::renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera) {
const float DISTANCE_FROM_HEAD_SPHERE = 0.1f * _lookatIndicatorScale; const float DISTANCE_FROM_HEAD_SPHERE = 0.1f * _lookatIndicatorScale;
@ -3015,6 +3025,9 @@ void Application::displaySide(Camera& whichCamera) {
if (!avatar->isInitialized()) { if (!avatar->isInitialized()) {
avatar->init(); avatar->init();
} }
if (isLookingAtMyAvatar(avatar)) {
avatar->getHead().setLookAtPosition(_myCamera.getPosition());
}
avatar->render(false, _renderAvatarBalls->isChecked()); avatar->render(false, _renderAvatarBalls->isChecked());
avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked()); avatar->setDisplayingLookatVectors(_renderLookatOn->isChecked());
} }

View file

@ -213,6 +213,7 @@ private:
void update(float deltaTime); void update(float deltaTime);
Avatar* isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection, Avatar* isLookingAtOtherAvatar(glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
glm::vec3& eyePosition, uint16_t& nodeID); glm::vec3& eyePosition, uint16_t& nodeID);
bool isLookingAtMyAvatar(Avatar* avatar);
void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera); void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera);
void updateAvatar(float deltaTime); void updateAvatar(float deltaTime);

119
interface/src/BendyLine.cpp Normal file
View file

@ -0,0 +1,119 @@
//
// BendyLine.cpp
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
#include "BendyLine.h"
#include "Util.h"
#include "world.h"
const float DEFAULT_BENDY_LINE_SPRING_FORCE = 10.0f;
const float DEFAULT_BENDY_LINE_TORQUE_FORCE = 0.1f;
const float DEFAULT_BENDY_LINE_DRAG = 10.0f;
const float DEFAULT_BENDY_LINE_LENGTH = 0.09f;
const float DEFAULT_BENDY_LINE_THICKNESS = 0.03f;
BendyLine::BendyLine(){
_springForce = DEFAULT_BENDY_LINE_SPRING_FORCE;
_torqueForce = DEFAULT_BENDY_LINE_TORQUE_FORCE;
_drag = DEFAULT_BENDY_LINE_DRAG;
_length = DEFAULT_BENDY_LINE_LENGTH;
_thickness = DEFAULT_BENDY_LINE_THICKNESS;
_gravityForce = glm::vec3(0.0f, 0.0f, 0.0f);
_basePosition = glm::vec3(0.0f, 0.0f, 0.0f);
_baseDirection = glm::vec3(0.0f, 0.0f, 0.0f);
_midPosition = glm::vec3(0.0f, 0.0f, 0.0f);
_endPosition = glm::vec3(0.0f, 0.0f, 0.0f);
_midVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
_endVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
}
void BendyLine::reset() {
_midPosition = _basePosition + _baseDirection * _length * ONE_HALF;
_endPosition = _midPosition + _baseDirection * _length * ONE_HALF;
_midVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
_endVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
}
void BendyLine::update(float deltaTime) {
glm::vec3 midAxis = _midPosition - _basePosition;
glm::vec3 endAxis = _endPosition - _midPosition;
float midLength = glm::length(midAxis);
float endLength = glm::length(endAxis);
glm::vec3 midDirection;
glm::vec3 endDirection;
if (midLength > 0.0f) {
midDirection = midAxis / midLength;
} else {
midDirection = _baseDirection;
}
if (endLength > 0.0f) {
endDirection = endAxis / endLength;
} else {
endDirection = _baseDirection;
}
// add spring force
float midForce = midLength - _length * ONE_HALF;
float endForce = endLength - _length * ONE_HALF;
_midVelocity -= midDirection * midForce * _springForce * deltaTime;
_endVelocity -= endDirection * endForce * _springForce * deltaTime;
// add gravity force
_midVelocity += _gravityForce;
_endVelocity += _gravityForce;
// add torque force
_midVelocity += _baseDirection * _torqueForce * deltaTime;
_endVelocity += midDirection * _torqueForce * deltaTime;
// add drag force
float momentum = 1.0f - (_drag * deltaTime);
if (momentum < 0.0f) {
_midVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
_endVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
} else {
_midVelocity *= momentum;
_endVelocity *= momentum;
}
// update position by velocity
_midPosition += _midVelocity;
_endPosition += _endVelocity;
// clamp lengths
glm::vec3 newMidVector = _midPosition - _basePosition;
glm::vec3 newEndVector = _endPosition - _midPosition;
float newMidLength = glm::length(newMidVector);
float newEndLength = glm::length(newEndVector);
glm::vec3 newMidDirection;
glm::vec3 newEndDirection;
if (newMidLength > 0.0f) {
newMidDirection = newMidVector/newMidLength;
} else {
newMidDirection = _baseDirection;
}
if (newEndLength > 0.0f) {
newEndDirection = newEndVector/newEndLength;
} else {
newEndDirection = _baseDirection;
}
_endPosition = _midPosition + newEndDirection * _length * ONE_HALF;
_midPosition = _basePosition + newMidDirection * _length * ONE_HALF;
}

52
interface/src/BendyLine.h Normal file
View file

@ -0,0 +1,52 @@
//
// BendyLine.h
// interface
//
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef hifi_bendyLine_h
#define hifi_bendyLine_h
#include <SharedUtil.h>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
class BendyLine {
public:
BendyLine();
void update(float deltaTime);
void reset();
void setLength (float length ) { _length = length; }
void setThickness (float thickness ) { _thickness = thickness; }
void setSpringForce (float springForce ) { _springForce = springForce; }
void setTorqueForce (float torqueForce ) { _torqueForce = torqueForce; }
void setDrag (float drag ) { _drag = drag; }
void setBasePosition (glm::vec3 basePosition ) { _basePosition = basePosition; }
void setBaseDirection(glm::vec3 baseDirection) { _baseDirection = baseDirection;}
void setGravityForce (glm::vec3 gravityForce ) { _gravityForce = gravityForce; }
glm::vec3 getBasePosition() { return _basePosition; }
glm::vec3 getMidPosition () { return _midPosition; }
glm::vec3 getEndPosition () { return _endPosition; }
float getThickness () { return _thickness; }
private:
float _springForce;
float _torqueForce;
float _drag;
float _length;
float _thickness;
glm::vec3 _gravityForce;
glm::vec3 _basePosition;
glm::vec3 _baseDirection;
glm::vec3 _midPosition;
glm::vec3 _endPosition;
glm::vec3 _midVelocity;
glm::vec3 _endVelocity;
};
#endif

View file

@ -322,26 +322,47 @@ void ParticleSystem::updateParticle(int p, float deltaTime) {
// apply color modulation // apply color modulation
if (myEmitter.particleAttributes[lifeStage ].modulationAmplitude > 0.0f) { if (myEmitter.particleAttributes[lifeStage ].modulationAmplitude > 0.0f) {
float modulation = 0.0f; float redModulation = 0.0f;
float greenModulation = 0.0f;
float bueModulation = 0.0f;
float radian = _timer * myEmitter.particleAttributes[lifeStage ].modulationRate * PI_TIMES_TWO; float radian = _timer * myEmitter.particleAttributes[lifeStage ].modulationRate * PI_TIMES_TWO;
if (myEmitter.particleAttributes[lifeStage ].modulationStyle == COLOR_MODULATION_STYLE_LIGHNTESS_PULSE) { if (myEmitter.particleAttributes[lifeStage ].modulationStyle == COLOR_MODULATION_STYLE_LIGHNTESS_PULSE) {
if (sinf(radian) > 0.0f) { if (sinf(radian) > 0.0f) {
modulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude; redModulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
} greenModulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
} else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_LIGHTNESS_WAVE) { bueModulation = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
float a = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
modulation = a * ONE_HALF + sinf(radian) * a * ONE_HALF;
} }
_particle[p].color.r += modulation; } else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_LIGHTNESS_WAVE) {
_particle[p].color.g += modulation; float amp = myEmitter.particleAttributes[lifeStage].modulationAmplitude;
_particle[p].color.b += modulation; float brightness = amp * ONE_HALF + sinf(radian) * amp * ONE_HALF;
_particle[p].color.a += modulation; redModulation = brightness;
greenModulation = brightness;
bueModulation = brightness;
} else if (myEmitter.particleAttributes[lifeStage].modulationStyle == COLOR_MODULATION_STYLE_RAINBOW_CYCLE) {
float amp = myEmitter.particleAttributes[lifeStage].modulationAmplitude * ONE_HALF;
redModulation = sinf(radian * RAINBOW_CYCLE_RED_RATE ) * amp;
greenModulation = sinf(radian * RAINBOW_CYCLE_GREEN_RATE) * amp;
bueModulation = sinf(radian * RAINBOW_CYCLE_BLUE_RATE ) * amp;
}
_particle[p].color.r += redModulation;
_particle[p].color.g += greenModulation;
_particle[p].color.b += bueModulation;
_particle[p].color.a = 1.0f;
if (_particle[p].color.r > 1.0f) {_particle[p].color.r = 1.0f;} if (_particle[p].color.r > 1.0f) {_particle[p].color.r = 1.0f;}
if (_particle[p].color.g > 1.0f) {_particle[p].color.g = 1.0f;} if (_particle[p].color.g > 1.0f) {_particle[p].color.g = 1.0f;}
if (_particle[p].color.b > 1.0f) {_particle[p].color.b = 1.0f;} if (_particle[p].color.b > 1.0f) {_particle[p].color.b = 1.0f;}
if (_particle[p].color.a > 1.0f) {_particle[p].color.a = 1.0f;} if (_particle[p].color.a > 1.0f) {_particle[p].color.a = 1.0f;}
if (_particle[p].color.r < 0.0f) {_particle[p].color.r = 0.0f;}
if (_particle[p].color.g < 0.0f) {_particle[p].color.g = 0.0f;}
if (_particle[p].color.b < 0.0f) {_particle[p].color.b = 0.0f;}
if (_particle[p].color.a < 0.0f) {_particle[p].color.a = 0.0f;}
} }
// do this at the end... // do this at the end...

View file

@ -15,6 +15,10 @@ const int NULL_PARTICLE = -1;
const int MAX_EMITTERS = 100; const int MAX_EMITTERS = 100;
const int MAX_PARTICLES = 5000; const int MAX_PARTICLES = 5000;
const float RAINBOW_CYCLE_RED_RATE = 0.5f;
const float RAINBOW_CYCLE_GREEN_RATE = 0.7f;
const float RAINBOW_CYCLE_BLUE_RATE = 1.0f;
enum ParticleRenderStyle enum ParticleRenderStyle
{ {
PARTICLE_RENDER_STYLE_SPHERE = 0, PARTICLE_RENDER_STYLE_SPHERE = 0,
@ -28,6 +32,7 @@ enum ColorModulationStyle
COLOR_MODULATION_STYLE_NULL = -1, COLOR_MODULATION_STYLE_NULL = -1,
COLOR_MODULATION_STYLE_LIGHNTESS_PULSE, COLOR_MODULATION_STYLE_LIGHNTESS_PULSE,
COLOR_MODULATION_STYLE_LIGHTNESS_WAVE, COLOR_MODULATION_STYLE_LIGHTNESS_WAVE,
COLOR_MODULATION_STYLE_RAINBOW_CYCLE,
NUM_COLOR_MODULATION_STYLES NUM_COLOR_MODULATION_STYLES
}; };

View file

@ -607,3 +607,12 @@ bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirecti
} }
return false; return false;
} }
bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadius) {
glm::vec3 diff = point - sphereCenter;
double mag = sqrt(glm::dot(diff, diff));
if (mag <= sphereRadius) {
return true;
}
return false;
}

View file

@ -76,4 +76,6 @@ float loadSetting(QSettings* settings, const char* name, float defaultValue);
bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius); bool rayIntersectsSphere(glm::vec3& rayStarting, glm::vec3& rayNormalizedDirection, glm::vec3& sphereCenter, double sphereRadius);
bool pointInSphere(glm::vec3& point, glm::vec3& sphereCenter, double sphereRadius);
#endif #endif

View file

@ -343,29 +343,6 @@ void Hand::updateRaveGloveParticles(float deltaTime) {
_raveGloveParticleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f)); _raveGloveParticleSystem.setUpDirection(glm::vec3(0.0f, 1.0f, 0.0f));
_raveGloveInitialized = true; _raveGloveInitialized = true;
} else { } else {
_raveGloveClock += deltaTime;
// this rave glove effect oscillates though various colors and radii that are meant to show off some effects
if (_raveGloveMode == RAVE_GLOVE_EFFECTS_MODE_THROBBING_COLOR) {
ParticleSystem::ParticleAttributes attributes;
float red = 0.5f + 0.5f * sinf(_raveGloveClock * 2.4f);
float green = 0.5f + 0.5f * cosf(_raveGloveClock * 2.7f);
float blue = 0.5f + 0.5f * sinf(_raveGloveClock * 3.0f);
float alpha = 1.0f;
attributes.color = glm::vec4(red, green, blue, alpha);
attributes.radius = 0.01f + 0.003f * sinf(_raveGloveClock * 50.0f);
attributes.modulationAmplitude = 0.0f;
for ( int f = 0; f< NUM_FINGERS; f ++ ) {
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_0, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_1, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_2, attributes);
_raveGloveParticleSystem.setParticleAttributes(_raveGloveEmitter[f], PARTICLE_LIFESTAGE_3, attributes);
}
}
_raveGloveParticleSystem.simulate(deltaTime); _raveGloveParticleSystem.simulate(deltaTime);
} }
} }
@ -395,6 +372,10 @@ void Hand::setRaveGloveMode(int mode) {
_raveGloveParticleSystem.setParticleAttributesToDefault(&attributes); _raveGloveParticleSystem.setParticleAttributesToDefault(&attributes);
attributes.modulationAmplitude = 1.0;
attributes.modulationRate = 0.33;
attributes.modulationStyle = COLOR_MODULATION_STYLE_RAINBOW_CYCLE;
attributes.color = glm::vec4( 0.5f, 0.5f, 0.5f, 1.0f);
attributes.radius = 0.02f; attributes.radius = 0.02f;
attributes.gravity = 0.0f; attributes.gravity = 0.0f;
attributes.airFriction = 0.0f; attributes.airFriction = 0.0f;

View file

@ -30,9 +30,9 @@ const float MINIMUM_EYE_ROTATION_DOT = 0.5f; // based on a dot product: 1.0 is
const float EYEBALL_RADIUS = 0.017; const float EYEBALL_RADIUS = 0.017;
const float EYELID_RADIUS = 0.019; const float EYELID_RADIUS = 0.019;
const float EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f }; const float EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f };
const float HAIR_SPRING_FORCE = 10.0f; const float HAIR_SPRING_FORCE = 7.0f;
const float HAIR_TORQUE_FORCE = 0.1f; const float HAIR_TORQUE_FORCE = 0.1f;
const float HAIR_GRAVITY_FORCE = 0.05f; const float HAIR_GRAVITY_FORCE = 0.02f;
const float HAIR_DRAG = 10.0f; const float HAIR_DRAG = 10.0f;
const float HAIR_LENGTH = 0.09f; const float HAIR_LENGTH = 0.09f;
const float HAIR_THICKNESS = 0.03f; const float HAIR_THICKNESS = 0.03f;
@ -127,20 +127,20 @@ void Head::reset() {
} }
} }
void Head::resetHairPhysics() { void Head::resetHairPhysics() {
glm::vec3 up = getUpDirection(); //glm::vec3 up = getUpDirection();
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
_hairTuft[t].length = _scale * HAIR_LENGTH; _hairTuft[t].setSpringForce (HAIR_SPRING_FORCE);
_hairTuft[t].thickness = _scale * HAIR_THICKNESS; _hairTuft[t].setTorqueForce (HAIR_TORQUE_FORCE);
_hairTuft[t].basePosition = _position + up * _scale * BODY_BALL_RADIUS_HEAD_BASE * 0.9f; _hairTuft[t].setGravityForce (HAIR_GRAVITY_FORCE * _gravity);
_hairTuft[t].midPosition = _hairTuft[t].basePosition + up * _hairTuft[t].length * ONE_HALF; _hairTuft[t].setDrag (HAIR_DRAG);
_hairTuft[t].endPosition = _hairTuft[t].midPosition + up * _hairTuft[t].length * ONE_HALF; _hairTuft[t].setLength (_scale * HAIR_LENGTH );
_hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].setThickness (_scale * HAIR_THICKNESS);
_hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f); _hairTuft[t].setBaseDirection(getUpDirection());
_hairTuft[t].reset();
}
} }
} }
@ -223,6 +223,7 @@ void Head::simulate(float deltaTime, bool isMine) {
// based on the nature of the lookat position, determine if the eyes can look / are looking at it. // based on the nature of the lookat position, determine if the eyes can look / are looking at it.
if (USING_PHYSICAL_MOHAWK) { if (USING_PHYSICAL_MOHAWK) {
updateHairPhysics(deltaTime); updateHairPhysics(deltaTime);
} }
// Update camera pitch and yaw independently from motion of head (for gyro-based interface) // Update camera pitch and yaw independently from motion of head (for gyro-based interface)
@ -376,17 +377,17 @@ void Head::renderMohawk() {
if (USING_PHYSICAL_MOHAWK) { if (USING_PHYSICAL_MOHAWK) {
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
glm::vec3 baseAxis = _hairTuft[t].midPosition - _hairTuft[t].basePosition; glm::vec3 baseAxis = _hairTuft[t].getMidPosition() - _hairTuft[t].getBasePosition();
glm::vec3 midAxis = _hairTuft[t].endPosition - _hairTuft[t].midPosition; glm::vec3 midAxis = _hairTuft[t].getEndPosition() - _hairTuft[t].getMidPosition();
glm::vec3 viewVector = _hairTuft[t].basePosition - Application::getInstance()->getCamera()->getPosition(); glm::vec3 viewVector = _hairTuft[t].getBasePosition() - Application::getInstance()->getCamera()->getPosition();
glm::vec3 basePerpendicular = glm::normalize(glm::cross(baseAxis, viewVector)); glm::vec3 basePerpendicular = glm::normalize(glm::cross(baseAxis, viewVector));
glm::vec3 midPerpendicular = glm::normalize(glm::cross(midAxis, viewVector)); glm::vec3 midPerpendicular = glm::normalize(glm::cross(midAxis, viewVector));
glm::vec3 base1 = _hairTuft[t].basePosition - basePerpendicular * _hairTuft[t].thickness * ONE_HALF; glm::vec3 base1 = _hairTuft[t].getBasePosition() - basePerpendicular * _hairTuft[t].getThickness() * ONE_HALF;
glm::vec3 base2 = _hairTuft[t].basePosition + basePerpendicular * _hairTuft[t].thickness * ONE_HALF; glm::vec3 base2 = _hairTuft[t].getBasePosition() + basePerpendicular * _hairTuft[t].getThickness() * ONE_HALF;
glm::vec3 mid1 = _hairTuft[t].midPosition - midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; glm::vec3 mid1 = _hairTuft[t].getMidPosition() - midPerpendicular * _hairTuft[t].getThickness() * ONE_HALF * ONE_HALF;
glm::vec3 mid2 = _hairTuft[t].midPosition + midPerpendicular * _hairTuft[t].thickness * ONE_HALF * ONE_HALF; glm::vec3 mid2 = _hairTuft[t].getMidPosition() + midPerpendicular * _hairTuft[t].getThickness() * ONE_HALF * ONE_HALF;
glColor3f(_mohawkColors[t].x, _mohawkColors[t].y, _mohawkColors[t].z); glColor3f(_mohawkColors[t].x, _mohawkColors[t].y, _mohawkColors[t].z);
@ -399,7 +400,7 @@ void Head::renderMohawk() {
glVertex3f(mid2.x, mid2.y, mid2.z ); glVertex3f(mid2.x, mid2.y, mid2.z );
glVertex3f(mid1.x, mid1.y, mid1.z ); glVertex3f(mid1.x, mid1.y, mid1.z );
glVertex3f(mid2.x, mid2.y, mid2.z ); glVertex3f(mid2.x, mid2.y, mid2.z );
glVertex3f(_hairTuft[t].endPosition.x, _hairTuft[t].endPosition.y, _hairTuft[t].endPosition.z ); glVertex3f(_hairTuft[t].getEndPosition().x, _hairTuft[t].getEndPosition().y, _hairTuft[t].getEndPosition().z );
glEnd(); glEnd();
} }
} else { } else {
@ -735,100 +736,17 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
glEnd(); glEnd();
} }
void Head::updateHairPhysics(float deltaTime) { void Head::updateHairPhysics(float deltaTime) {
glm::quat orientation = getOrientation(); glm::quat orientation = getOrientation();
glm::vec3 up = orientation * IDENTITY_UP; glm::vec3 up = orientation * IDENTITY_UP;
glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 front = orientation * IDENTITY_FRONT;
for (int t = 0; t < NUM_HAIR_TUFTS; t ++) { for (int t = 0; t < NUM_HAIR_TUFTS; t ++) {
float fraction = (float)t / (float)(NUM_HAIR_TUFTS - 1); float fraction = (float)t / (float)(NUM_HAIR_TUFTS - 1);
float angle = -20.0f + 40.0f * fraction; float angle = -20.0f + 40.0f * fraction;
float radian = angle * PI_OVER_180; float radian = angle * PI_OVER_180;
glm::vec3 baseDirection glm::vec3 baseDirection = front * sinf(radian) + up * cosf(radian);
= front * sinf(radian) _hairTuft[t].setBasePosition (_position + _scale * BODY_BALL_RADIUS_HEAD_BASE * 0.9f * baseDirection);
+ up * cosf(radian); _hairTuft[t].setBaseDirection(baseDirection);
_hairTuft[t].update(deltaTime);
_hairTuft[t].basePosition = _position + _scale * BODY_BALL_RADIUS_HEAD_BASE * 0.9f * baseDirection;
glm::vec3 midAxis = _hairTuft[t].midPosition - _hairTuft[t].basePosition;
glm::vec3 endAxis = _hairTuft[t].endPosition - _hairTuft[t].midPosition;
float midLength = glm::length(midAxis);
float endLength = glm::length(endAxis);
glm::vec3 midDirection;
glm::vec3 endDirection;
if (midLength > 0.0f) {
midDirection = midAxis / midLength;
} else {
midDirection = up;
}
if (endLength > 0.0f) {
endDirection = endAxis / endLength;
} else {
endDirection = up;
}
// add spring force
float midForce = midLength - _hairTuft[t].length * ONE_HALF;
float endForce = endLength - _hairTuft[t].length * ONE_HALF;
_hairTuft[t].midVelocity -= midDirection * midForce * HAIR_SPRING_FORCE * deltaTime;
_hairTuft[t].endVelocity -= endDirection * endForce * HAIR_SPRING_FORCE * deltaTime;
// add gravity force
glm::vec3 gravityForce = _gravity * HAIR_GRAVITY_FORCE * deltaTime;
_hairTuft[t].midVelocity += gravityForce;
_hairTuft[t].endVelocity += gravityForce;
// add torque force
_hairTuft[t].midVelocity += baseDirection * HAIR_TORQUE_FORCE * deltaTime;
_hairTuft[t].endVelocity += midDirection * HAIR_TORQUE_FORCE * deltaTime;
// add drag force
float momentum = 1.0f - (HAIR_DRAG * deltaTime);
if (momentum < 0.0f) {
_hairTuft[t].midVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
_hairTuft[t].endVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
} else {
_hairTuft[t].midVelocity *= momentum;
_hairTuft[t].endVelocity *= momentum;
}
// update position by velocity
_hairTuft[t].midPosition += _hairTuft[t].midVelocity;
_hairTuft[t].endPosition += _hairTuft[t].endVelocity;
// clamp lengths
glm::vec3 newMidVector = _hairTuft[t].midPosition - _hairTuft[t].basePosition;
glm::vec3 newEndVector = _hairTuft[t].endPosition - _hairTuft[t].midPosition;
float newMidLength = glm::length(newMidVector);
float newEndLength = glm::length(newEndVector);
glm::vec3 newMidDirection;
glm::vec3 newEndDirection;
if (newMidLength > 0.0f) {
newMidDirection = newMidVector/newMidLength;
} else {
newMidDirection = up;
}
if (newEndLength > 0.0f) {
newEndDirection = newEndVector/newEndLength;
} else {
newEndDirection = up;
}
_hairTuft[t].endPosition = _hairTuft[t].midPosition + newEndDirection * _hairTuft[t].length * ONE_HALF;
_hairTuft[t].midPosition = _hairTuft[t].basePosition + newMidDirection * _hairTuft[t].length * ONE_HALF;
} }
} }

View file

@ -18,6 +18,7 @@
#include <VoxelConstants.h> #include <VoxelConstants.h>
#include "Face.h" #include "Face.h"
#include "BendyLine.h"
#include "InterfaceConfig.h" #include "InterfaceConfig.h"
#include "SerialInterface.h" #include "SerialInterface.h"
#include "world.h" #include "world.h"
@ -80,18 +81,6 @@ private:
Head(const Head&); Head(const Head&);
Head& operator= (const Head&); Head& operator= (const Head&);
struct HairTuft
{
float length;
float thickness;
glm::vec3 basePosition;
glm::vec3 midPosition;
glm::vec3 endPosition;
glm::vec3 midVelocity;
glm::vec3 endVelocity;
};
struct Nose struct Nose
{ {
glm::vec3 top; glm::vec3 top;
@ -123,7 +112,7 @@ private:
float _returnSpringScale; //strength of return springs float _returnSpringScale; //strength of return springs
glm::vec3 _bodyRotation; glm::vec3 _bodyRotation;
bool _renderLookatVectors; bool _renderLookatVectors;
HairTuft _hairTuft[NUM_HAIR_TUFTS]; BendyLine _hairTuft[NUM_HAIR_TUFTS];
glm::vec3* _mohawkTriangleFan; glm::vec3* _mohawkTriangleFan;
glm::vec3* _mohawkColors; glm::vec3* _mohawkColors;
glm::vec3 _saccade; glm::vec3 _saccade;