History

Merge remote-tracking branch 'upstream/master'

Philip Rosedale committed 13 years ago

Commit dec7e592 parents a89b011 d7d435113 files · +642 −208Browse files

Unified · Split

13 files
  1. eve/src/main.cpp +35 −24
  2. interface/resources/audio/walking.raw +0 −0
  3. interface/resources/audio/walking4.raw +0 −0
  4. interface/src/Audio.cpp +1 −26
  5. interface/src/Audio.h +0 −2
  6. interface/src/AudioData.h +0 −1
  7. interface/src/Avatar.cpp +76 −88
  8. interface/src/Avatar.h +2 −57
  9. interface/src/Head.cpp +378 −0
  10. interface/src/Head.h +93 −0
  11. interface/src/main.cpp +38 −9
  12. libraries/voxels/src/VoxelNode.cpp +16 −3
  13. libraries/voxels/src/VoxelNode.h +5 −0
eve/src/main.cpp+35−24
@@ -31,6 +31,8 @@ const int HAND_TIMER_SLEEP_ITERATIONS = 50; · 30 unmodified lines
31 31
32const float EVE_PELVIS_HEIGHT = 0.565925f;32const float EVE_PELVIS_HEIGHT = 0.565925f;
33 33
34const float AUDIO_INJECT_PROXIMITY = 0.4f;
35
34bool stopReceiveAgentDataThread;36bool stopReceiveAgentDataThread;
35bool injectAudioThreadRunning = false;37bool injectAudioThreadRunning = false;
36 38
@@ -43,20 +45,14 @@ void *receiveAgentData(void *args) { · 6 unmodified lines
43 unsigned char incomingPacket[MAX_PACKET_SIZE];45 unsigned char incomingPacket[MAX_PACKET_SIZE];
44 46
45 AgentList* agentList = AgentList::getInstance();47 AgentList* agentList = AgentList::getInstance();
46 Agent* avatarMixer = NULL;
47 48
48 while (!::stopReceiveAgentDataThread) {49 while (!::stopReceiveAgentDataThread) {
49 if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) { 50 if (agentList->getAgentSocket().receive(&senderAddress, incomingPacket, &bytesReceived)) {
50 switch (incomingPacket[0]) {51 switch (incomingPacket[0]) {
51 case PACKET_HEADER_BULK_AVATAR_DATA:52 case PACKET_HEADER_BULK_AVATAR_DATA:
52 // this is the positional data for other agents53 // this is the positional data for other agents
53 // eve doesn't care about this for now, so let's just update the receive time for the54 // pass that off to the agentList processBulkAgentData method
54 // avatar mixer - this makes sure it won't be killed during silent agent removal55 agentList->processBulkAgentData(&senderAddress, incomingPacket, bytesReceived);
55 avatarMixer = agentList->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
56
57 if (avatarMixer) {
58 avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
59 }
60 56
61 break;57 break;
62 default:58 default:
@@ -94,6 +90,12 @@ void *injectAudio(void *args) { · 31 unmodified lines
94 return NULL;90 return NULL;
95}91}
96 92
93void createAvatarDataForAgent(Agent* agent) {
94 if (!agent->getLinkedData()) {
95 agent->setLinkedData(new AvatarData());
96 }
97}
98
97int main(int argc, const char* argv[]) {99int main(int argc, const char* argv[]) {
98 // new seed for random audio sleep times100 // new seed for random audio sleep times
99 srand(time(0));101 srand(time(0));
@@ -133,13 +135,18 @@ int main(int argc, const char* argv[]) { · 33 unmodified lines
133 // read eve's audio data135 // read eve's audio data
134 AudioInjector eveAudioInjector("/etc/highfidelity/eve/resources/eve.raw");136 AudioInjector eveAudioInjector("/etc/highfidelity/eve/resources/eve.raw");
135 137
138 // lower Eve's volume by setting the attentuation modifier (this is a value out of 255)
139 eveAudioInjector.setAttenuationModifier(190);
140
141 // register the callback for agent data creation
142 agentList->linkedDataCreateCallback = createAvatarDataForAgent;
143
136 unsigned char broadcastPacket[MAX_PACKET_SIZE];144 unsigned char broadcastPacket[MAX_PACKET_SIZE];
137 broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;145 broadcastPacket[0] = PACKET_HEADER_HEAD_DATA;
138 146
139 timeval thisSend;147 timeval thisSend;
140 double numMicrosecondsSleep = 0;148 double numMicrosecondsSleep = 0;
141 149
142 int numIterationsLeftBeforeAudioSend = 0;
143 pthread_t injectAudioThread;150 pthread_t injectAudioThread;
144 151
145 int handStateTimer = 0;152 int handStateTimer = 0;
@@ -162,24 +169,23 @@ int main(int argc, const char* argv[]) { · 16 unmodified lines
162 // use the UDPSocket instance attached to our agent list to send avatar data to mixer169 // use the UDPSocket instance attached to our agent list to send avatar data to mixer
163 agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, packetPosition - broadcastPacket);170 agentList->getAgentSocket().send(avatarMixer->getActiveSocket(), broadcastPacket, packetPosition - broadcastPacket);
164 } 171 }
165 172
166 // temporarily disable Eve's audio sending until the file is actually available on EC2 box173 if (!::injectAudioThreadRunning) {
167 if (numIterationsLeftBeforeAudioSend == 0) {174 // enumerate the other agents to decide if one is close enough that eve should talk
168 if (!::injectAudioThreadRunning) {175 for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
169 pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector);176 AvatarData* avatarData = (AvatarData*) agent->getLinkedData();
170 177
171 numIterationsLeftBeforeAudioSend = randIntInRange(MIN_ITERATIONS_BETWEEN_AUDIO_SENDS,178 if (avatarData) {
172 MAX_ITERATIONS_BETWEEN_AUDIO_SENDS);179 glm::vec3 tempVector = eve.getPosition() - avatarData->getPosition();
180 float squareDistance = glm::dot(tempVector, tempVector);
181
182 if (squareDistance <= AUDIO_INJECT_PROXIMITY) {
183 pthread_create(&injectAudioThread, NULL, injectAudio, (void*) &eveAudioInjector);
184 }
185 }
173 }186 }
174 } else {
175 numIterationsLeftBeforeAudioSend--;
176 }187 }
177 188
178 // sleep for the correct amount of time to have data send be consistently timed
179 if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
180 usleep(numMicrosecondsSleep);
181 }
182
183 // simulate the effect of pressing and un-pressing the mouse button/pad189 // simulate the effect of pressing and un-pressing the mouse button/pad
184 handStateTimer++;190 handStateTimer++;
185 191
@@ -189,6 +195,11 @@ int main(int argc, const char* argv[]) { · 3 unmodified lines
189 eve.setHandState(0);195 eve.setHandState(0);
190 } else if (handStateTimer >= ITERATIONS_BEFORE_HAND_GRAB + HAND_GRAB_DURATION_ITERATIONS + HAND_TIMER_SLEEP_ITERATIONS) {196 } else if (handStateTimer >= ITERATIONS_BEFORE_HAND_GRAB + HAND_GRAB_DURATION_ITERATIONS + HAND_TIMER_SLEEP_ITERATIONS) {
191 handStateTimer = 0;197 handStateTimer = 0;
198 }
199
200 // sleep for the correct amount of time to have data send be consistently timed
201 if ((numMicrosecondsSleep = (DATA_SEND_INTERVAL_MSECS * 1000) - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
202 usleep(numMicrosecondsSleep);
192 } 203 }
193 }204 }
194 205
interface/resources/audio/walking.raw+0−0

Binary file not shown.

interface/resources/audio/walking4.raw+0−0

Binary file not shown.

interface/src/Audio.cpp+1−26
@@ -71,11 +71,6 @@ float flangeIntensity = 0; · 70 unmodified lines
71float flangeRate = 0;71float flangeRate = 0;
72float flangeWeight = 0;72float flangeWeight = 0;
73 73
74int16_t *walkingSoundArray;
75int walkingSoundSamples;
76int samplesLeftForWalk = 0;
77int16_t *sampleWalkPointer;
78
79timeval firstPlaybackTimer;74timeval firstPlaybackTimer;
80int packetsReceivedThisPlayback = 0;75int packetsReceivedThisPlayback = 0;
81float usecsAtStartup = 0;76float usecsAtStartup = 0;
@@ -357,10 +352,6 @@ bool Audio::getMixerLoopbackFlag() { · 275 unmodified lines
357 return audioData->mixerLoopbackFlag;352 return audioData->mixerLoopbackFlag;
358}353}
359 354
360void Audio::setWalkingState(bool newWalkState) {
361 audioData->playWalkSound = newWalkState;
362}
363
364/**355/**
365 * Initialize portaudio and start an audio stream.356 * Initialize portaudio and start an audio stream.
366 * Should be called at the beginning of program exection.357 * Should be called at the beginning of program exection.
@@ -368,23 +359,7 @@ void Audio::setWalkingState(bool newWalkState) { · 1 unmodified line
368 * @return Returns true if successful or false if an error occurred.359 * @return Returns true if successful or false if an error occurred.
369Use Audio::getError() to retrieve the error code.360Use Audio::getError() to retrieve the error code.
370 */361 */
371Audio::Audio(Oscilloscope *s, Avatar *linkedAvatar)362Audio::Audio(Oscilloscope* s, Avatar* linkedAvatar) {
372{
373 // read the walking sound from the raw file and store it
374 // in the in memory array
375
376 switchToResourcesParentIfRequired();
377 FILE *soundFile = fopen("resources/audio/walking.raw", "r");
378
379 // get length of file:
380 std::fseek(soundFile, 0, SEEK_END);
381 walkingSoundSamples = std::ftell(soundFile) / sizeof(int16_t);
382 walkingSoundArray = new int16_t[walkingSoundSamples];
383 std::rewind(soundFile);
384
385 std::fread(walkingSoundArray, sizeof(int16_t), walkingSoundSamples, soundFile);
386 std::fclose(soundFile);
387
388 paError = Pa_Initialize();363 paError = Pa_Initialize();
389 if (paError != paNoError) goto error;364 if (paError != paNoError) goto error;
390 365
interface/src/Audio.h+0−2
@@ -28,8 +28,6 @@ public: · 27 unmodified lines
28 float getInputLoudness() const;28 float getInputLoudness() const;
29 void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort);29 void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort);
30 30
31 void setWalkingState(bool newWalkState);
32
33 void setLastAcceleration(glm::vec3 a) { audioData->setLastAcceleration(a); };31 void setLastAcceleration(glm::vec3 a) { audioData->setLastAcceleration(a); };
34 void setLastVelocity(glm::vec3 v) { audioData->setLastVelocity(v); };32 void setLastVelocity(glm::vec3 v) { audioData->setLastVelocity(v); };
35 33
interface/src/AudioData.h+0−1
@@ -38,7 +38,6 @@ class AudioData { · 37 unmodified lines
38 float lastInputLoudness;38 float lastInputLoudness;
39 39
40 bool mixerLoopbackFlag;40 bool mixerLoopbackFlag;
41 bool playWalkSound;
42 41
43 // Added avatar acceleration and velocity for procedural effects sounds from client42 // Added avatar acceleration and velocity for procedural effects sounds from client
44 void setLastVelocity(glm::vec3 v) { _lastVelocity = v; };43 void setLastVelocity(glm::vec3 v) { _lastVelocity = v; };
interface/src/Avatar.cpp+76−88
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#include <lodepng.h>11#include <lodepng.h>
12#include <SharedUtil.h>12#include <SharedUtil.h>
13#include "Avatar.h"13#include "Avatar.h"
14#include "Head.h"
14#include "Log.h"15#include "Log.h"
15#include "ui/TextRenderer.h"16#include "ui/TextRenderer.h"
16#include <AgentList.h>17#include <AgentList.h>
@@ -23,12 +24,11 @@ const bool BALLS_ON = false; · 6 unmodified lines
23const bool USING_AVATAR_GRAVITY = true;24const bool USING_AVATAR_GRAVITY = true;
24const float GRAVITY_SCALE = 10.0f;25const float GRAVITY_SCALE = 10.0f;
25const float BOUNCE = 0.3f;26const float BOUNCE = 0.3f;
26const float DECAY = 0.1;
27const float THRUST_MAG = 1200.0;27const float THRUST_MAG = 1200.0;
28const float YAW_MAG = 500.0;28const float YAW_MAG = 500.0;
29const float BODY_SPIN_FRICTION = 5.0;29const float BODY_SPIN_FRICTION = 5.0;
30const float BODY_UPRIGHT_FORCE = 10.0;30const float BODY_UPRIGHT_FORCE = 10.0;
31const float BODY_PITCH_WHILE_WALKING = 30.0;31const float BODY_PITCH_WHILE_WALKING = 40.0;
32const float BODY_ROLL_WHILE_TURNING = 0.1;32const float BODY_ROLL_WHILE_TURNING = 0.1;
33const float VELOCITY_DECAY = 5.0;33const float VELOCITY_DECAY = 5.0;
34const float MY_HAND_HOLDING_PULL = 0.2;34const float MY_HAND_HOLDING_PULL = 0.2;
@@ -52,6 +52,8 @@ const float AVATAR_BRAKING_STRENGTH = 30.0f; · 17 unmodified lines
52 52
53float skinColor [] = {1.0, 0.84, 0.66};53float skinColor [] = {1.0, 0.84, 0.66};
54float lightBlue [] = {0.7, 0.8, 1.0};54float lightBlue [] = {0.7, 0.8, 1.0};
55
56/*
55float browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};57float browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
56float mouthColor[] = {1, 0, 0};58float mouthColor[] = {1, 0, 0};
57 59
@@ -64,16 +66,19 @@ float MouthWidthChoices[3] = {0.5, 0.77, 0.3}; · 6 unmodified lines
64float browWidth = 0.8;66float browWidth = 0.8;
65float browThickness = 0.16;67float browThickness = 0.16;
66 68
67bool usingBigSphereCollisionTest = true;
68 69
69char iris_texture_file[] = "resources/images/green_eye.png";70//char iris_texture_file[] = "resources/images/green_eye.png";
71*/
72bool usingBigSphereCollisionTest = true;
70 73
71float chatMessageScale = 0.0015;74float chatMessageScale = 0.0015;
72float chatMessageHeight = 0.45;75float chatMessageHeight = 0.45;
73 76
77/*
74vector<unsigned char> iris_texture;78vector<unsigned char> iris_texture;
75unsigned int iris_texture_width = 512;79unsigned int iris_texture_width = 512;
76unsigned int iris_texture_height = 256;80unsigned int iris_texture_height = 256;
81*/
77 82
78Avatar::Avatar(bool isMine) {83Avatar::Avatar(bool isMine) {
79 84
@@ -104,43 +109,8 @@ Avatar::Avatar(bool isMine) { · 24 unmodified lines
104 109
105 for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false;110 for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false;
106 111
107 _head.pupilSize = 0.10;112 _head.initialize();
108 _head.interPupilDistance = 0.6;113
109 _head.interBrowDistance = 0.75;
110 _head.nominalPupilSize = 0.10;
111 _head.pitchRate = 0.0;
112 _head.yawRate = 0.0;
113 _head.rollRate = 0.0;
114 _head.eyebrowPitch[0] = -30;
115 _head.eyebrowPitch[1] = -30;
116 _head.eyebrowRoll [0] = 20;
117 _head.eyebrowRoll [1] = -20;
118 _head.mouthPitch = 0;
119 _head.mouthYaw = 0;
120 _head.mouthWidth = 1.0;
121 _head.mouthHeight = 0.2;
122 _head.eyeballPitch[0] = 0;
123 _head.eyeballPitch[1] = 0;
124 _head.eyeballScaleX = 1.2;
125 _head.eyeballScaleY = 1.5;
126 _head.eyeballScaleZ = 1.0;
127 _head.eyeballYaw[0] = 0;
128 _head.eyeballYaw[1] = 0;
129 _head.pitchTarget = 0;
130 _head.yawTarget = 0;
131 _head.noiseEnvelope = 1.0;
132 _head.pupilConverge = 10.0;
133 _head.leanForward = 0.0;
134 _head.leanSideways = 0.0;
135 _head.eyeContact = 1;
136 _head.eyeContactTarget = LEFT_EYE;
137 _head.scale = 1.0;
138 _head.audioAttack = 0.0;
139 _head.averageLoudness = 0.0;
140 _head.lastLoudness = 0.0;
141 _head.browAudioLift = 0.0;
142 _head.noise = 0;
143 _head.returnSpringScale = 1.0;
144 _movedHandOffset = glm::vec3(0.0f, 0.0f, 0.0f);114 _movedHandOffset = glm::vec3(0.0f, 0.0f, 0.0f);
145 _renderYaw = 0.0;115 _renderYaw = 0.0;
146 _renderPitch = 0.0;116 _renderPitch = 0.0;
@@ -153,6 +123,7 @@ Avatar::Avatar(bool isMine) { · 6 unmodified lines
153 123
154 _avatarTouch.setReachableRadius(0.6);124 _avatarTouch.setReachableRadius(0.6);
155 125
126 /*
156 if (iris_texture.size() == 0) {127 if (iris_texture.size() == 0) {
157 switchToResourcesParentIfRequired();128 switchToResourcesParentIfRequired();
158 unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);129 unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
@@ -160,6 +131,7 @@ Avatar::Avatar(bool isMine) { · 1 unmodified line
160 printLog("error %u: %s\n", error, lodepng_error_text(error));131 printLog("error %u: %s\n", error, lodepng_error_text(error));
161 }132 }
162 }133 }
134*/
163 135
164 if (BALLS_ON) { _balls = new Balls(100); }136 if (BALLS_ON) { _balls = new Balls(100); }
165 else { _balls = NULL; }137 else { _balls = NULL; }
@@ -239,7 +211,8 @@ Avatar::Avatar(const Avatar &otherAvatar) { · 73 unmodified lines
239 _distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar;211 _distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar;
240 212
241 initializeSkeleton();213 initializeSkeleton();
242 214
215/*
243 if (iris_texture.size() == 0) {216 if (iris_texture.size() == 0) {
244 switchToResourcesParentIfRequired();217 switchToResourcesParentIfRequired();
245 unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);218 unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
@@ -247,6 +220,7 @@ Avatar::Avatar(const Avatar &otherAvatar) { · 1 unmodified line
247 printLog("error %u: %s\n", error, lodepng_error_text(error));220 printLog("error %u: %s\n", error, lodepng_error_text(error));
248 }221 }
249 }222 }
223*/
250}224}
251 225
252Avatar::~Avatar() {226Avatar::~Avatar() {
@@ -452,8 +426,52 @@ void Avatar::simulate(float deltaTime) { · 199 unmodified lines
452 }426 }
453 }427 }
454 428
429
430
431
432
433 // Get head position data from network for other people
434 if (!_isMine) {
435 _head.leanSideways = getHeadLeanSideways();
436 _head.leanForward = getHeadLeanForward();
437 }
438
439 //apply the head lean values to the springy position...
440 if (fabs(_head.leanSideways + _head.leanForward) > 0.0f) {
441 glm::vec3 headLean =
442 _orientation.getRight() * _head.leanSideways +
443 _orientation.getFront() * _head.leanForward;
444
445 // this is not a long-term solution, but it works ok for initial purposes of making the avatar lean
446 _joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
447 _joint[ AVATAR_JOINT_CHEST ].springyPosition += headLean * 0.4f;
448 _joint[ AVATAR_JOINT_NECK_BASE ].springyPosition += headLean * 0.7f;
449 _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition += headLean * 1.0f;
450
451 _joint[ AVATAR_JOINT_LEFT_COLLAR ].springyPosition += headLean * 0.6f;
452 _joint[ AVATAR_JOINT_LEFT_SHOULDER ].springyPosition += headLean * 0.6f;
453 _joint[ AVATAR_JOINT_LEFT_ELBOW ].springyPosition += headLean * 0.2f;
454 _joint[ AVATAR_JOINT_LEFT_WRIST ].springyPosition += headLean * 0.1f;
455 _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springyPosition += headLean * 0.0f;
456
457 _joint[ AVATAR_JOINT_RIGHT_COLLAR ].springyPosition += headLean * 0.6f;
458 _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springyPosition += headLean * 0.6f;
459 _joint[ AVATAR_JOINT_RIGHT_ELBOW ].springyPosition += headLean * 0.2f;
460 _joint[ AVATAR_JOINT_RIGHT_WRIST ].springyPosition += headLean * 0.1f;
461 _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition += headLean * 0.0f;
462 }
463
464
455 // update head state465 // update head state
456 updateHead(deltaTime);466 _head.setPositionRotationAndScale(
467 _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition,
468 glm::vec3(_headYaw, _headPitch, _headRoll),
469 _joint[ AVATAR_JOINT_HEAD_BASE ].radius
470 );
471
472 _head.setAudioLoudness(_audioLoudness);
473 _head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
474 _head.simulate(deltaTime, _isMine);
457 475
458 // use speed and angular velocity to determine walking vs. standing 476 // use speed and angular velocity to determine walking vs. standing
459 if (_speed + fabs(_bodyYawDelta) > 0.2) {477 if (_speed + fabs(_bodyYawDelta) > 0.2) {
@@ -463,7 +481,6 @@ void Avatar::simulate(float deltaTime) { · 3 unmodified lines
463 }481 }
464}482}
465 483
466
467void Avatar::updateHandMovementAndTouching(float deltaTime) {484void Avatar::updateHandMovementAndTouching(float deltaTime) {
468 485
469 // reset hand and arm positions according to hand movement486 // reset hand and arm positions according to hand movement
@@ -540,7 +557,6 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { · 70 unmodified lines
540 _avatarTouch.setHoldingHands(false); 557 _avatarTouch.setHoldingHands(false);
541 }558 }
542 559
543
544 //if holding hands, apply the appropriate forces560 //if holding hands, apply the appropriate forces
545 if (_avatarTouch.getHoldingHands()) {561 if (_avatarTouch.getHoldingHands()) {
546 _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += 562 _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position +=
@@ -549,8 +565,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { · 2 unmodified lines
549 - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position565 - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position
550 ) * 0.5f; 566 ) * 0.5f;
551 567
552 if (distanceBetweenOurHands > 0.2) {568 if (distanceBetweenOurHands > 0.3) {
553 float force = 700.0f * deltaTime;569 float force = 10.0f * deltaTime;
554 if (force > 1.0f) {force = 1.0f;}570 if (force > 1.0f) {force = 1.0f;}
555 _velocity += vectorFromMyHandToYourHand * force;571 _velocity += vectorFromMyHandToYourHand * force;
556 }572 }
@@ -579,37 +595,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { · 22 unmodified lines
579 595
580void Avatar::updateHead(float deltaTime) {596void Avatar::updateHead(float deltaTime) {
581 597
582 // Get head position data from network for other people598/*
583 if (!_isMine) {
584 _head.leanSideways = getHeadLeanSideways();
585 _head.leanForward = getHeadLeanForward();
586 }
587
588 //apply the head lean values to the springy position...
589 if (fabs(_head.leanSideways + _head.leanForward) > 0.0f) {
590 glm::vec3 headLean =
591 _orientation.getRight() * _head.leanSideways +
592 _orientation.getFront() * _head.leanForward;
593
594 // this is not a long-term solution, but it works ok for initial purposes of making the avatar lean
595 _joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
596 _joint[ AVATAR_JOINT_CHEST ].springyPosition += headLean * 0.4f;
597 _joint[ AVATAR_JOINT_NECK_BASE ].springyPosition += headLean * 0.7f;
598 _joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition += headLean * 1.0f;
599
600 _joint[ AVATAR_JOINT_LEFT_COLLAR ].springyPosition += headLean * 0.6f;
601 _joint[ AVATAR_JOINT_LEFT_SHOULDER ].springyPosition += headLean * 0.6f;
602 _joint[ AVATAR_JOINT_LEFT_ELBOW ].springyPosition += headLean * 0.2f;
603 _joint[ AVATAR_JOINT_LEFT_WRIST ].springyPosition += headLean * 0.1f;
604 _joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].springyPosition += headLean * 0.0f;
605
606 _joint[ AVATAR_JOINT_RIGHT_COLLAR ].springyPosition += headLean * 0.6f;
607 _joint[ AVATAR_JOINT_RIGHT_SHOULDER ].springyPosition += headLean * 0.6f;
608 _joint[ AVATAR_JOINT_RIGHT_ELBOW ].springyPosition += headLean * 0.2f;
609 _joint[ AVATAR_JOINT_RIGHT_WRIST ].springyPosition += headLean * 0.1f;
610 _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].springyPosition += headLean * 0.0f;
611 }
612
613 // Decay head back to center if turned on599 // Decay head back to center if turned on
614 if (_isMine && _returnHeadToCenter) {600 if (_isMine && _returnHeadToCenter) {
615 // Decay back toward center601 // Decay back toward center
@@ -712,6 +698,7 @@ void Avatar::updateHead(float deltaTime) { · 96 unmodified lines
712 const float AUDIO_AVERAGING_SECS = 0.05;698 const float AUDIO_AVERAGING_SECS = 0.05;
713 _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness +699 _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness +
714 (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness;700 (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness;
701*/
715}702}
716 703
717 704
@@ -894,7 +881,7 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { · 176 unmodified lines
894 881
895 // render head882 // render head
896 if (_displayingHead) {883 if (_displayingHead) {
897 renderHead(lookingInMirror);884 _head.render(lookingInMirror, _bodyYaw);
898 }885 }
899 886
900 // if this is my avatar, then render my interactions with the other avatar887 // if this is my avatar, then render my interactions with the other avatar
@@ -952,7 +939,10 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) { · 51 unmodified lines
952 }939 }
953}940}
954 941
942
943
955void Avatar::renderHead(bool lookingInMirror) {944void Avatar::renderHead(bool lookingInMirror) {
945/*
956 int side = 0;946 int side = 0;
957 947
958 glEnable(GL_DEPTH_TEST);948 glEnable(GL_DEPTH_TEST);
@@ -1075,7 +1065,7 @@ void Avatar::renderHead(bool lookingInMirror) { · 116 unmodified lines
1075 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);1065 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1076 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);1066 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1077 gluQuadricOrientation(_sphere, GLU_OUTSIDE);1067 gluQuadricOrientation(_sphere, GLU_OUTSIDE);
1078 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]);1068//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]);
1079 }1069 }
1080 1070
1081 glPushMatrix();1071 glPushMatrix();
@@ -1121,8 +1111,10 @@ void Avatar::renderHead(bool lookingInMirror) { · 39 unmodified lines
1121 1111
1122 1112
1123 glPopMatrix();1113 glPopMatrix();
1114 */
1124 }1115 }
1125 1116
1117
1126void Avatar::setHandMovementValues(glm::vec3 handOffset) {1118void Avatar::setHandMovementValues(glm::vec3 handOffset) {
1127 _movedHandOffset = handOffset;1119 _movedHandOffset = handOffset;
1128}1120}
@@ -1479,11 +1471,6 @@ void Avatar::renderBody() { · 350 unmodified lines
1479 }1471 }
1480}1472}
1481 1473
1482void Avatar::SetNewHeadTarget(float pitch, float yaw) {
1483 _head.pitchTarget = pitch;
1484 _head.yawTarget = yaw;
1485}
1486
1487//1474//
1488// Process UDP interface data from Android transmitter or Google Glass1475// Process UDP interface data from Android transmitter or Google Glass
1489//1476//
@@ -1522,12 +1509,12 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { · 32 unmodified lines
1522 // If first packet received, note time, turn head spring return OFF, get start rotation1509 // If first packet received, note time, turn head spring return OFF, get start rotation
1523 gettimeofday(&_transmitterTimer, NULL);1510 gettimeofday(&_transmitterTimer, NULL);
1524 if (deviceType == DEVICE_GLASS) {1511 if (deviceType == DEVICE_GLASS) {
1525 setHeadReturnToCenter(true);1512 _head.setReturnToCenter(true);
1526 setHeadSpringScale(10.f);1513 _head.setSpringScale(10.f);
1527 printLog("Using Google Glass to drive head, springs ON.\n");1514 printLog("Using Google Glass to drive head, springs ON.\n");
1528 1515
1529 } else {1516 } else {
1530 setHeadReturnToCenter(false);1517 _head.setReturnToCenter(false);
1531 printLog("Using Transmitter %s to drive head, springs OFF.\n", device);1518 printLog("Using Transmitter %s to drive head, springs OFF.\n", device);
1532 1519
1533 }1520 }
@@ -1536,6 +1523,7 @@ void Avatar::processTransmitterData(unsigned char* packetData, int numBytes) { · 2 unmodified lines
1536 1523
1537 _transmitterInitialReading = glm::vec3(rot3, rot2, rot1);1524 _transmitterInitialReading = glm::vec3(rot3, rot2, rot1);
1538 }1525 }
1526
1539 const int TRANSMITTER_COUNT = 100;1527 const int TRANSMITTER_COUNT = 100;
1540 if (_transmitterPackets % TRANSMITTER_COUNT == 0) {1528 if (_transmitterPackets % TRANSMITTER_COUNT == 0) {
1541 // Every 100 packets, record the observed Hz of the transmitter data1529 // Every 100 packets, record the observed Hz of the transmitter data
interface/src/Avatar.h+2−57
@@ -18,8 +18,7 @@ · 17 unmodified lines
18#include "InterfaceConfig.h"18#include "InterfaceConfig.h"
19#include "SerialInterface.h"19#include "SerialInterface.h"
20#include "Balls.h"20#include "Balls.h"
21 21#include "Head.h"
22enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
23 22
24enum DriveKeys23enum DriveKeys
25{24{
@@ -82,10 +81,8 @@ public: · 56 unmodified lines
82 Avatar* clone() const;81 Avatar* clone() const;
83 82
84 void reset();83 void reset();
85
86 void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);84 void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
87 void setNoise (float mag) {_head.noise = mag;}85 void setNoise (float mag) {_head.noise = mag;}
88 void setScale(float s) {_head.scale = s; };
89 void setRenderYaw(float y) {_renderYaw = y;}86 void setRenderYaw(float y) {_renderYaw = y;}
90 void setRenderPitch(float p) {_renderPitch = p;}87 void setRenderPitch(float p) {_renderPitch = p;}
91 float getRenderYaw() {return _renderYaw;}88 float getRenderYaw() {return _renderYaw;}
@@ -124,11 +121,6 @@ public: · 32 unmodified lines
124 void updateArmIKAndConstraints( float deltaTime );121 void updateArmIKAndConstraints( float deltaTime );
125 void setDisplayingHead( bool displayingHead );122 void setDisplayingHead( bool displayingHead );
126 123
127 float getAverageLoudness() {return _head.averageLoudness;};
128 void setAverageLoudness(float al) {_head.averageLoudness = al;};
129
130 void SetNewHeadTarget(float, float);
131
132 // Set what driving keys are being pressed to control thrust levels124 // Set what driving keys are being pressed to control thrust levels
133 void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };125 void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
134 bool getDriveKeys(int key) { return _driveKeys[key]; };126 bool getDriveKeys(int key) { return _driveKeys[key]; };
@@ -165,48 +157,7 @@ private: · 30 unmodified lines
165 bool isCollidable; // when false, the joint position will not register a collision157 bool isCollidable; // when false, the joint position will not register a collision
166 };158 };
167 159
168 struct AvatarHead160 Head _head;
169 {
170 float pitchRate;
171 float yawRate;
172 float rollRate;
173 float noise;
174 float eyeballPitch[2];
175 float eyeballYaw [2];
176 float eyebrowPitch[2];
177 float eyebrowRoll [2];
178 float eyeballScaleX;
179 float eyeballScaleY;
180 float eyeballScaleZ;
181 float interPupilDistance;
182 float interBrowDistance;
183 float nominalPupilSize;
184 float pupilSize;
185 float mouthPitch;
186 float mouthYaw;
187 float mouthWidth;
188 float mouthHeight;
189 float leanForward;
190 float leanSideways;
191 float pitchTarget;
192 float yawTarget;
193 float noiseEnvelope;
194 float pupilConverge;
195 float scale;
196 int eyeContact;
197 float browAudioLift;
198 eyeContactTargets eyeContactTarget;
199
200 // Sound loudness information
201 float lastLoudness;
202 float averageLoudness;
203 float audioAttack;
204
205 // Strength of return springs
206 float returnSpringScale;
207 };
208
209 AvatarHead _head;
210 bool _isMine;161 bool _isMine;
211 glm::vec3 _TEST_bigSpherePosition;162 glm::vec3 _TEST_bigSpherePosition;
212 float _TEST_bigSphereRadius;163 float _TEST_bigSphereRadius;
@@ -239,7 +190,6 @@ private: · 26 unmodified lines
239 Balls* _balls;190 Balls* _balls;
240 AvatarTouch _avatarTouch;191 AvatarTouch _avatarTouch;
241 bool _displayingHead; // should be false if in first-person view192 bool _displayingHead; // should be false if in first-person view
242 bool _returnHeadToCenter;
243 float _distanceToNearestAvatar; // How close is the nearest avatar?193 float _distanceToNearestAvatar; // How close is the nearest avatar?
244 glm::vec3 _gravity;194 glm::vec3 _gravity;
245 195
@@ -256,11 +206,6 @@ private: · 10 unmodified lines
256 void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );206 void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime );
257 void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );207 void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
258 void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime);208 void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime);
259 void setHeadSpringScale(float s) { _head.returnSpringScale = s; }
260
261 // Do you want head to try to return to center (depends on interface detected)
262 void setHeadReturnToCenter(bool r) { _returnHeadToCenter = r; };
263 const bool getHeadReturnToCenter() const { return _returnHeadToCenter; };
264};209};
265 210
266#endif211#endif
interface/src/Head.cpp+378−0
@@ -0,0 +1,378 @@
1//
2// Head.cpp
3// hifi
4//
5// Created by Jeffrey on May, 10, 2013
6// Copyright (c) 2013 Physical, Inc.. All rights reserved.
7//
8
9#include "Head.h"
10#include <vector>
11#include <SharedUtil.h>
12#include <lodepng.h>
13
14using namespace std;
15
16const float HEAD_MOTION_DECAY = 0.1;
17
18
19float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
20float _mouthColor[] = {1, 0, 0};
21
22float _BrowRollAngle [5] = {0, 15, 30, -30, -15};
23float _BrowPitchAngle[3] = {-70, -60, -50};
24float _eyeColor [3] = {1,1,1};
25
26float _MouthWidthChoices[3] = {0.5, 0.77, 0.3};
27
28float _browWidth = 0.8;
29float _browThickness = 0.16;
30
31char iris_texture_file[] = "resources/images/green_eye.png";
32
33vector<unsigned char> iris_texture;
34unsigned int iris_texture_width = 512;
35unsigned int iris_texture_height = 256;
36
37Head::Head() {
38 if (iris_texture.size() == 0) {
39 switchToResourcesParentIfRequired();
40 unsigned error = lodepng::decode(iris_texture, iris_texture_width, iris_texture_height, iris_texture_file);
41 if (error != 0) {
42 printLog("error %u: %s\n", error, lodepng_error_text(error));
43 }
44 }
45}
46
47void Head::initialize() {
48
49 audioLoudness = 0.0;
50 skinColor = glm::vec3(0.0f, 0.0f, 0.0f);
51 position = glm::vec3(0.0f, 0.0f, 0.0f);
52 yaw = 0.0f;
53 pitch = 0.0f;
54 roll = 0.0f;
55 pupilSize = 0.10;
56 interPupilDistance = 0.6;
57 interBrowDistance = 0.75;
58 nominalPupilSize = 0.10;
59 pitchRate = 0.0;
60 yawRate = 0.0;
61 rollRate = 0.0;
62 eyebrowPitch[0] = -30;
63 eyebrowPitch[1] = -30;
64 eyebrowRoll [0] = 20;
65 eyebrowRoll [1] = -20;
66 mouthPitch = 0;
67 mouthYaw = 0;
68 mouthWidth = 1.0;
69 mouthHeight = 0.2;
70 eyeballPitch[0] = 0;
71 eyeballPitch[1] = 0;
72 eyeballScaleX = 1.2;
73 eyeballScaleY = 1.5;
74 eyeballScaleZ = 1.0;
75 eyeballYaw[0] = 0;
76 eyeballYaw[1] = 0;
77 pitchTarget = 0;
78 yawTarget = 0;
79 noiseEnvelope = 1.0;
80 pupilConverge = 10.0;
81 leanForward = 0.0;
82 leanSideways = 0.0;
83 eyeContact = 1;
84 eyeContactTarget = LEFT_EYE;
85 scale = 1.0;
86 audioAttack = 0.0;
87 averageLoudness = 0.0;
88 lastLoudness = 0.0;
89 browAudioLift = 0.0;
90 noise = 0;
91 returnSpringScale = 1.0;
92 sphere = NULL;
93}
94
95void Head::setPositionRotationAndScale(glm::vec3 p, glm::vec3 r, float s) {
96
97 position = p;
98 scale = s;
99 yaw = r.x;
100 pitch = r.y;
101 roll = r.z;
102}
103
104void Head::setSkinColor(glm::vec3 c) {
105 skinColor = c;
106}
107
108void Head::setAudioLoudness(float loudness) {
109 audioLoudness = loudness;
110}
111
112
113void Head::setNewTarget(float pitch, float yaw) {
114 pitchTarget = pitch;
115 yawTarget = yaw;
116}
117
118void Head::simulate(float deltaTime, bool isMine) {
119
120 // Decay head back to center if turned on
121 if (isMine && returnHeadToCenter) {
122 // Decay back toward center
123 pitch *= (1.0f - HEAD_MOTION_DECAY * returnSpringScale * 2 * deltaTime);
124 yaw *= (1.0f - HEAD_MOTION_DECAY * returnSpringScale * 2 * deltaTime);
125 roll *= (1.0f - HEAD_MOTION_DECAY * returnSpringScale * 2 * deltaTime);
126 }
127
128 // For invensense gyro, decay only slightly when roughly centered
129 if (isMine) {
130 const float RETURN_RANGE = 15.0;
131 const float RETURN_STRENGTH = 2.0;
132 if (fabs(pitch) < RETURN_RANGE) { pitch *= (1.0f - RETURN_STRENGTH * deltaTime); }
133 if (fabs(yaw) < RETURN_RANGE) { yaw *= (1.0f - RETURN_STRENGTH * deltaTime); }
134 if (fabs(roll) < RETURN_RANGE) { roll *= (1.0f - RETURN_STRENGTH * deltaTime); }
135 }
136
137 if (noise) {
138 // Move toward new target
139 pitch += (pitchTarget - pitch) * 10 * deltaTime; // (1.f - DECAY*deltaTime)*Pitch + ;
140 yaw += (yawTarget - yaw ) * 10 * deltaTime; // (1.f - DECAY*deltaTime);
141 roll *= 1.f - (HEAD_MOTION_DECAY * deltaTime);
142 }
143
144 leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
145 leanSideways *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
146
147 // Update where the avatar's eyes are
148 //
149 // First, decide if we are making eye contact or not
150 if (randFloat() < 0.005) {
151 eyeContact = !eyeContact;
152 eyeContact = 1;
153 if (!eyeContact) {
154 // If we just stopped making eye contact,move the eyes markedly away
155 eyeballPitch[0] = eyeballPitch[1] = eyeballPitch[0] + 5.0 + (randFloat() - 0.5) * 10;
156 eyeballYaw [0] = eyeballYaw [1] = eyeballYaw [0] + 5.0 + (randFloat() - 0.5) * 5;
157 } else {
158 // If now making eye contact, turn head to look right at viewer
159 setNewTarget(0,0);
160 }
161 }
162
163 const float DEGREES_BETWEEN_VIEWER_EYES = 3;
164 const float DEGREES_TO_VIEWER_MOUTH = 7;
165
166 if (eyeContact) {
167 // Should we pick a new eye contact target?
168 if (randFloat() < 0.01) {
169 // Choose where to look next
170 if (randFloat() < 0.1) {
171 eyeContactTarget = MOUTH;
172 } else {
173 if (randFloat() < 0.5) eyeContactTarget = LEFT_EYE; else eyeContactTarget = RIGHT_EYE;
174 }
175 }
176 // Set eyeball pitch and yaw to make contact
177 float eye_target_yaw_adjust = 0;
178 float eye_target_pitch_adjust = 0;
179 if (eyeContactTarget == LEFT_EYE) eye_target_yaw_adjust = DEGREES_BETWEEN_VIEWER_EYES;
180 if (eyeContactTarget == RIGHT_EYE) eye_target_yaw_adjust = -DEGREES_BETWEEN_VIEWER_EYES;
181 if (eyeContactTarget == MOUTH) eye_target_pitch_adjust = DEGREES_TO_VIEWER_MOUTH;
182
183 eyeballPitch[0] = eyeballPitch[1] = -pitch + eye_target_pitch_adjust;
184 eyeballYaw [0] = eyeballYaw [1] = yaw + eye_target_yaw_adjust;
185 }
186
187 if (noise)
188 {
189 pitch += (randFloat() - 0.5) * 0.2 * noiseEnvelope;
190 yaw += (randFloat() - 0.5) * 0.3 *noiseEnvelope;
191 //PupilSize += (randFloat() - 0.5) * 0.001*NoiseEnvelope;
192
193 if (randFloat() < 0.005) mouthWidth = _MouthWidthChoices[rand()%3];
194
195 if (!eyeContact) {
196 if (randFloat() < 0.01) eyeballPitch[0] = eyeballPitch[1] = (randFloat() - 0.5) * 20;
197 if (randFloat() < 0.01) eyeballYaw[0] = eyeballYaw[1] = (randFloat()- 0.5) * 10;
198 }
199
200 if ((randFloat() < 0.005) && (fabs(pitchTarget - pitch) < 1.0) && (fabs(yawTarget - yaw) < 1.0)) {
201 setNewTarget((randFloat()-0.5) * 20.0, (randFloat()-0.5) * 45.0);
202 }
203
204 if (0) {
205
206 // Pick new target
207 pitchTarget = (randFloat() - 0.5) * 45;
208 yawTarget = (randFloat() - 0.5) * 22;
209 }
210 if (randFloat() < 0.01)
211 {
212 eyebrowPitch[0] = eyebrowPitch[1] = _BrowPitchAngle[rand()%3];
213 eyebrowRoll [0] = eyebrowRoll[1] = _BrowRollAngle[rand()%5];
214 eyebrowRoll [1] *=-1;
215 }
216 }
217
218 // Update audio trailing average for rendering facial animations
219 const float AUDIO_AVERAGING_SECS = 0.05;
220 averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * averageLoudness +
221 (deltaTime / AUDIO_AVERAGING_SECS) * audioLoudness;
222}
223
224
225
226
227void Head::render(bool lookingInMirror, float bodyYaw) {
228
229 int side = 0;
230
231 glEnable(GL_DEPTH_TEST);
232 glEnable(GL_RESCALE_NORMAL);
233
234 glPushMatrix();
235
236 glTranslatef(position.x, position.y, position.z);
237
238 glScalef(scale, scale, scale);
239
240 if (lookingInMirror) {
241 glRotatef(bodyYaw - yaw, 0, 1, 0);
242 glRotatef(pitch, 1, 0, 0);
243 glRotatef(-roll, 0, 0, 1);
244 } else {
245 glRotatef(bodyYaw + yaw, 0, 1, 0);
246 glRotatef(pitch, 1, 0, 0);
247 glRotatef(roll, 0, 0, 1);
248 }
249
250 //glScalef(2.0, 2.0, 2.0);
251 glColor3f(skinColor.x, skinColor.y, skinColor.z);
252
253 glutSolidSphere(1, 30, 30);
254
255 // Ears
256 glPushMatrix();
257 glTranslatef(1.0, 0, 0);
258 for(side = 0; side < 2; side++) {
259 glPushMatrix();
260 glScalef(0.3, 0.65, .65);
261 glutSolidSphere(0.5, 30, 30);
262 glPopMatrix();
263 glTranslatef(-2.0, 0, 0);
264 }
265 glPopMatrix();
266
267 // Update audio attack data for facial animation (eyebrows and mouth)
268 audioAttack = 0.9 * audioAttack + 0.1 * fabs(audioLoudness - lastLoudness);
269 lastLoudness = audioLoudness;
270
271
272 const float BROW_LIFT_THRESHOLD = 100;
273 if (audioAttack > BROW_LIFT_THRESHOLD)
274 browAudioLift += sqrt(audioAttack) / 1000.0;
275
276 browAudioLift *= .90;
277
278 // Render Eyebrows
279 glPushMatrix();
280 glTranslatef(-interBrowDistance / 2.0,0.4,0.45);
281 for(side = 0; side < 2; side++) {
282 glColor3fv(_browColor);
283 glPushMatrix();
284 glTranslatef(0, 0.35 + browAudioLift, 0);
285 glRotatef(eyebrowPitch[side]/2.0, 1, 0, 0);
286 glRotatef(eyebrowRoll[side]/2.0, 0, 0, 1);
287 glScalef(_browWidth, _browThickness, 1);
288 glutSolidCube(0.5);
289 glPopMatrix();
290 glTranslatef(interBrowDistance, 0, 0);
291 }
292 glPopMatrix();
293
294 // Mouth
295 glPushMatrix();
296 glTranslatef(0,-0.35,0.75);
297 glColor3f(0,0,0);
298 glRotatef(mouthPitch, 1, 0, 0);
299 glRotatef(mouthYaw, 0, 0, 1);
300 if (averageLoudness > 1.f) {
301 glScalef(mouthWidth * (.7f + sqrt(averageLoudness) /60.f),
302 mouthHeight * (1.f + sqrt(averageLoudness) /30.f), 1);
303 } else {
304 glScalef(mouthWidth, mouthHeight, 1);
305 }
306
307 glutSolidCube(0.5);
308 glPopMatrix();
309
310 glTranslatef(0, 1.0, 0);
311
312 glTranslatef(-interPupilDistance/2.0,-0.68,0.7);
313 // Right Eye
314 glRotatef(-10, 1, 0, 0);
315 glColor3fv(_eyeColor);
316 glPushMatrix();
317 {
318 glTranslatef(interPupilDistance/10.0, 0, 0.05);
319 glRotatef(20, 0, 0, 1);
320 glScalef(eyeballScaleX, eyeballScaleY, eyeballScaleZ);
321 glutSolidSphere(0.25, 30, 30);
322 }
323 glPopMatrix();
324
325 // Right Pupil
326 if (sphere == NULL) {
327 sphere = gluNewQuadric();
328 gluQuadricTexture(sphere, GL_TRUE);
329 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
330 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
331 gluQuadricOrientation(sphere, GLU_OUTSIDE);
332 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iris_texture_width, iris_texture_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &iris_texture[0]);
333 }
334
335 glPushMatrix();
336 {
337 glRotatef(eyeballPitch[1], 1, 0, 0);
338 glRotatef(eyeballYaw[1] + yaw + pupilConverge, 0, 1, 0);
339 glTranslatef(0,0,.35);
340 glRotatef(-75,1,0,0);
341 glScalef(1.0, 0.4, 1.0);
342
343 glEnable(GL_TEXTURE_2D);
344 gluSphere(sphere, pupilSize, 15, 15);
345 glDisable(GL_TEXTURE_2D);
346 }
347
348 glPopMatrix();
349 // Left Eye
350 glColor3fv(_eyeColor);
351 glTranslatef(interPupilDistance, 0, 0);
352 glPushMatrix();
353 {
354 glTranslatef(-interPupilDistance/10.0, 0, .05);
355 glRotatef(-20, 0, 0, 1);
356 glScalef(eyeballScaleX, eyeballScaleY, eyeballScaleZ);
357 glutSolidSphere(0.25, 30, 30);
358 }
359 glPopMatrix();
360 // Left Pupil
361 glPushMatrix();
362 {
363 glRotatef(eyeballPitch[0], 1, 0, 0);
364 glRotatef(eyeballYaw[0] + yaw - pupilConverge, 0, 1, 0);
365 glTranslatef(0, 0, .35);
366 glRotatef(-75, 1, 0, 0);
367 glScalef(1.0, 0.4, 1.0);
368
369 glEnable(GL_TEXTURE_2D);
370 gluSphere(sphere, pupilSize, 15, 15);
371 glDisable(GL_TEXTURE_2D);
372 }
373 glPopMatrix();
374
375 glPopMatrix();
376
377}
378
interface/src/Head.h+93−0
@@ -0,0 +1,93 @@
1//
2// Head.h
3// hifi
4//
5// Created by Jeffrey on May, 10, 2013
6// Copyright (c) 2013 Physical, Inc.. All rights reserved.
7//
8
9#ifndef hifi_Head_h
10#define hifi_Head_h
11
12#include <glm/glm.hpp>
13#include <glm/gtc/quaternion.hpp>
14#include <AvatarData.h>
15#include "world.h"
16#include "InterfaceConfig.h"
17#include "SerialInterface.h"
18
19enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH};
20
21class Head {
22public:
23 Head();
24
25 void initialize();
26 void simulate(float deltaTime, bool isMine);
27 void setPositionRotationAndScale(glm::vec3 position, glm::vec3 rotation, float scale);
28 void setSkinColor(glm::vec3 color);
29 void setAudioLoudness(float loudness);
30 void render(bool lookingInMirror, float bodyYaw);
31 void setNewTarget(float, float);
32 void setSpringScale(float s) { returnSpringScale = s; }
33
34 // Do you want head to try to return to center (depends on interface detected)
35 void setReturnToCenter(bool r) { returnHeadToCenter = r; }
36 const bool getReturnToCenter() const { return returnHeadToCenter; }
37
38 float getAverageLoudness() {return averageLoudness;};
39 void setAverageLoudness(float al) { averageLoudness = al;};
40
41//private:
42// I am making these public for now - just to get the code moved over quickly!
43
44 bool returnHeadToCenter;
45 float audioLoudness;
46 glm::vec3 skinColor;
47 glm::vec3 position;
48 glm::vec3 rotation;
49 float yaw;
50 float pitch;
51 float roll;
52 float pitchRate;
53 float yawRate;
54 float rollRate;
55 float noise;
56 float eyeballPitch[2];
57 float eyeballYaw [2];
58 float eyebrowPitch[2];
59 float eyebrowRoll [2];
60 float eyeballScaleX;
61 float eyeballScaleY;
62 float eyeballScaleZ;
63 float interPupilDistance;
64 float interBrowDistance;
65 float nominalPupilSize;
66 float pupilSize;
67 float mouthPitch;
68 float mouthYaw;
69 float mouthWidth;
70 float mouthHeight;
71 float leanForward;
72 float leanSideways;
73 float pitchTarget;
74 float yawTarget;
75 float noiseEnvelope;
76 float pupilConverge;
77 float scale;
78 int eyeContact;
79 float browAudioLift;
80 eyeContactTargets eyeContactTarget;
81
82 // Sound loudness information
83 float lastLoudness;
84 float averageLoudness;
85 float audioAttack;
86
87 GLUquadric* sphere;
88
89 // Strength of return springs
90 float returnSpringScale;
91};
92
93#endif
interface/src/main.cpp+38−9
@@ -102,6 +102,13 @@ int screenHeight = 800; · 101 unmodified lines
102int fullscreen = 0;102int fullscreen = 0;
103float aspectRatio = 1.0f;103float aspectRatio = 1.0f;
104 104
105bool USING_MOUSE_VIEW_SHIFT = false;
106float MOUSE_VIEW_SHIFT_RATE = 40.0f;
107float MOUSE_VIEW_SHIFT_YAW_MARGIN = (float)(WIDTH * 0.2f);
108float MOUSE_VIEW_SHIFT_PITCH_MARGIN = (float)(HEIGHT * 0.2f);
109float MOUSE_VIEW_SHIFT_YAW_LIMIT = 45.0;
110float MOUSE_VIEW_SHIFT_PITCH_LIMIT = 30.0;
111
105//CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON;112//CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON;
106CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON;113CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON;
107 114
@@ -206,7 +213,6 @@ double elapsedTime; · 98 unmodified lines
206timeval applicationStartupTime;213timeval applicationStartupTime;
207bool justStarted = true;214bool justStarted = true;
208 215
209
210// Every second, check the frame rates and other stuff216// Every second, check the frame rates and other stuff
211void Timer(int extra) {217void Timer(int extra) {
212 gettimeofday(&timerEnd, NULL);218 gettimeofday(&timerEnd, NULL);
@@ -370,9 +376,7 @@ void sendVoxelEditMessage(PACKET_HEADER header, VoxelDetail& detail) { · 157 unmodified lines
370 }376 }
371}377}
372 378
373//
374// Using gyro data, update both view frustum and avatar head position379// Using gyro data, update both view frustum and avatar head position
375//
376void updateAvatar(float deltaTime) {380void updateAvatar(float deltaTime) {
377 381
378 // Update my avatar's head position from gyros382 // Update my avatar's head position from gyros
@@ -409,7 +413,34 @@ void updateAvatar(float deltaTime) { · 30 unmodified lines
409 const float RENDER_PITCH_MULTIPLY = 4.f;413 const float RENDER_PITCH_MULTIPLY = 4.f;
410 myAvatar.setRenderPitch((1.f - renderPitchSpring * deltaTime) * myAvatar.getRenderPitch() +414 myAvatar.setRenderPitch((1.f - renderPitchSpring * deltaTime) * myAvatar.getRenderPitch() +
411 renderPitchSpring * deltaTime * -myAvatar.getHeadPitch() * RENDER_PITCH_MULTIPLY);415 renderPitchSpring * deltaTime * -myAvatar.getHeadPitch() * RENDER_PITCH_MULTIPLY);
412 416 }
417
418
419 if (USING_MOUSE_VIEW_SHIFT)
420 {
421 //make it so that when your mouse hits the edge of the screen, the camera shifts
422 float rightBoundary = (float)WIDTH - MOUSE_VIEW_SHIFT_YAW_MARGIN;
423 float bottomBoundary = (float)HEIGHT - MOUSE_VIEW_SHIFT_PITCH_MARGIN;
424
425 if (mouseX > rightBoundary) {
426 float f = (mouseX - rightBoundary) / ( (float)WIDTH - rightBoundary);
427 mouseViewShiftYaw += MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
428 if (mouseViewShiftYaw > MOUSE_VIEW_SHIFT_YAW_LIMIT) { mouseViewShiftYaw = MOUSE_VIEW_SHIFT_YAW_LIMIT; }
429 } else if (mouseX < MOUSE_VIEW_SHIFT_YAW_MARGIN) {
430 float f = 1.0 - (mouseX / MOUSE_VIEW_SHIFT_YAW_MARGIN);
431 mouseViewShiftYaw -= MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
432 if (mouseViewShiftYaw < -MOUSE_VIEW_SHIFT_YAW_LIMIT) { mouseViewShiftYaw = -MOUSE_VIEW_SHIFT_YAW_LIMIT; }
433 }
434 if (mouseY < MOUSE_VIEW_SHIFT_PITCH_MARGIN) {
435 float f = 1.0 - (mouseY / MOUSE_VIEW_SHIFT_PITCH_MARGIN);
436 mouseViewShiftPitch += MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
437 if ( mouseViewShiftPitch > MOUSE_VIEW_SHIFT_PITCH_LIMIT ) { mouseViewShiftPitch = MOUSE_VIEW_SHIFT_PITCH_LIMIT; }
438 }
439 else if (mouseY > bottomBoundary) {
440 float f = (mouseY - bottomBoundary) / ((float)HEIGHT - bottomBoundary);
441 mouseViewShiftPitch -= MOUSE_VIEW_SHIFT_RATE * f * deltaTime;
442 if (mouseViewShiftPitch < -MOUSE_VIEW_SHIFT_PITCH_LIMIT) { mouseViewShiftPitch = -MOUSE_VIEW_SHIFT_PITCH_LIMIT; }
443 }
413 }444 }
414 445
415 if (OculusManager::isConnected()) {446 if (OculusManager::isConnected()) {
@@ -1032,7 +1063,7 @@ void display(void) · 616 unmodified lines
1032 myCamera.setDistance (1.5f);1063 myCamera.setDistance (1.5f);
1033 myCamera.setTightness (8.0f);1064 myCamera.setTightness (8.0f);
1034 myCamera.setTargetPosition(myAvatar.getHeadPosition());1065 myCamera.setTargetPosition(myAvatar.getHeadPosition());
1035 myCamera.setTargetRotation(myAvatar.getBodyYaw(), 0.0f, 0.0f);1066 myCamera.setTargetRotation(myAvatar.getBodyYaw() - mouseViewShiftYaw, mouseViewShiftPitch, 0.0f);
1036 }1067 }
1037 1068
1038 // important...1069 // important...
@@ -1540,9 +1571,6 @@ void specialkey(int k, int x, int y) { · 501 unmodified lines
1540 if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(RIGHT, 1);1571 if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(RIGHT, 1);
1541 else myAvatar.setDriveKeys(ROT_RIGHT, 1); 1572 else myAvatar.setDriveKeys(ROT_RIGHT, 1);
1542 }1573 }
1543#ifndef _WIN32
1544 audio.setWalkingState(true);
1545#endif
1546 } 1574 }
1547}1575}
1548 1576
@@ -1800,6 +1828,8 @@ void idle(void) { · 251 unmodified lines
1800 // walking triggers the handControl to stop1828 // walking triggers the handControl to stop
1801 if (myAvatar.getMode() == AVATAR_MODE_WALKING) {1829 if (myAvatar.getMode() == AVATAR_MODE_WALKING) {
1802 handControl.stop();1830 handControl.stop();
1831 mouseViewShiftYaw *= 0.9;
1832 mouseViewShiftPitch *= 0.9;
1803 }1833 }
1804 1834
1805 // Read serial port interface devices1835 // Read serial port interface devices
@@ -1836,7 +1866,6 @@ void idle(void) { · 30 unmodified lines
1836 glutPostRedisplay();1866 glutPostRedisplay();
1837 lastTimeIdle = check;1867 lastTimeIdle = check;
1838 }1868 }
1839
1840}1869}
1841 1870
1842void reshape(int width, int height) {1871void reshape(int width, int height) {
libraries/voxels/src/VoxelNode.cpp+16−3
@@ -262,8 +262,21 @@ ViewFrustum::location VoxelNode::inFrustum(const ViewFrustum& viewFrustum) const · 261 unmodified lines
262 262
263float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {263float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {
264 glm::vec3 center = _box.getCenter() * (float)TREE_SCALE;264 glm::vec3 center = _box.getCenter() * (float)TREE_SCALE;
265 float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - center.x, 2) +265 glm::vec3 temp = viewFrustum.getPosition() - center;
266 powf(viewFrustum.getPosition().y - center.y, 2) +266 float distanceSquared = glm::dot(temp, temp);
267 powf(viewFrustum.getPosition().z - center.z, 2));267 float distanceToVoxelCenter = sqrtf(distanceSquared);
268 return distanceToVoxelCenter;268 return distanceToVoxelCenter;
269}269}
270
271float VoxelNode::distanceSquareToPoint(const glm::vec3& point) const {
272 glm::vec3 temp = point - _box.getCenter();
273 float distanceSquare = glm::dot(temp, temp);
274 return distanceSquare;
275}
276
277float VoxelNode::distanceToPoint(const glm::vec3& point) const {
278 glm::vec3 temp = point - _box.getCenter();
279 float distanceSquare = glm::dot(temp, temp);
280 float distance = sqrtf(distanceSquare);
281 return distance;
282}
libraries/voxels/src/VoxelNode.h+5−0
@@ -61,6 +61,11 @@ public: · 60 unmodified lines
61 bool isInView(const ViewFrustum& viewFrustum) const; 61 bool isInView(const ViewFrustum& viewFrustum) const;
62 ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const;62 ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const;
63 float distanceToCamera(const ViewFrustum& viewFrustum) const; 63 float distanceToCamera(const ViewFrustum& viewFrustum) const;
64
65 // points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)
66 float distanceSquareToPoint(const glm::vec3& point) const; // when you don't need the actual distance, use this.
67 float distanceToPoint(const glm::vec3& point) const;
68
64 bool isLeaf() const { return _childCount == 0; }69 bool isLeaf() const { return _childCount == 0; }
65 void printDebugDetails(const char* label) const;70 void printDebugDetails(const char* label) const;
66 bool isDirty() const { return _isDirty; };71 bool isDirty() const { return _isDirty; };