Unified · Split
| @@ -31,6 +31,8 @@ const int HAND_TIMER_SLEEP_ITERATIONS = 50; · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | const float EVE_PELVIS_HEIGHT = 0.565925f; | 32 | const float EVE_PELVIS_HEIGHT = 0.565925f; |
| 33 | 33 | ||
| 34 | const float AUDIO_INJECT_PROXIMITY = 0.4f; | ||
| 35 | |||
| 34 | bool stopReceiveAgentDataThread; | 36 | bool stopReceiveAgentDataThread; |
| 35 | bool injectAudioThreadRunning = false; | 37 | bool 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 agents | 53 | // 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 the | 54 | // pass that off to the agentList processBulkAgentData method |
| 54 | // avatar mixer - this makes sure it won't be killed during silent agent removal | 55 | 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 | ||
| 93 | void createAvatarDataForAgent(Agent* agent) { | ||
| 94 | if (!agent->getLinkedData()) { | ||
| 95 | agent->setLinkedData(new AvatarData()); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 97 | int main(int argc, const char* argv[]) { | 99 | int main(int argc, const char* argv[]) { |
| 98 | // new seed for random audio sleep times | 100 | // 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 data | 135 | // 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 mixer | 169 | // 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 box | 173 | 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/pad | 189 | // 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 | ||
Binary file not shown.
Binary file not shown.
| @@ -71,11 +71,6 @@ float flangeIntensity = 0; · 70 unmodified lines | |||
| 71 | float flangeRate = 0; | 71 | float flangeRate = 0; |
| 72 | float flangeWeight = 0; | 72 | float flangeWeight = 0; |
| 73 | 73 | ||
| 74 | int16_t *walkingSoundArray; | ||
| 75 | int walkingSoundSamples; | ||
| 76 | int samplesLeftForWalk = 0; | ||
| 77 | int16_t *sampleWalkPointer; | ||
| 78 | |||
| 79 | timeval firstPlaybackTimer; | 74 | timeval firstPlaybackTimer; |
| 80 | int packetsReceivedThisPlayback = 0; | 75 | int packetsReceivedThisPlayback = 0; |
| 81 | float usecsAtStartup = 0; | 76 | float usecsAtStartup = 0; |
| @@ -357,10 +352,6 @@ bool Audio::getMixerLoopbackFlag() { · 275 unmodified lines | |||
| 357 | return audioData->mixerLoopbackFlag; | 352 | return audioData->mixerLoopbackFlag; |
| 358 | } | 353 | } |
| 359 | 354 | ||
| 360 | void 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. |
| 369 | Use Audio::getError() to retrieve the error code. | 360 | Use Audio::getError() to retrieve the error code. |
| 370 | */ | 361 | */ |
| 371 | Audio::Audio(Oscilloscope *s, Avatar *linkedAvatar) | 362 | Audio::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 | ||
| @@ -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 | ||
| @@ -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 client | 42 | // 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; }; |
| @@ -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 | |||
| 23 | const bool USING_AVATAR_GRAVITY = true; | 24 | const bool USING_AVATAR_GRAVITY = true; |
| 24 | const float GRAVITY_SCALE = 10.0f; | 25 | const float GRAVITY_SCALE = 10.0f; |
| 25 | const float BOUNCE = 0.3f; | 26 | const float BOUNCE = 0.3f; |
| 26 | const float DECAY = 0.1; | ||
| 27 | const float THRUST_MAG = 1200.0; | 27 | const float THRUST_MAG = 1200.0; |
| 28 | const float YAW_MAG = 500.0; | 28 | const float YAW_MAG = 500.0; |
| 29 | const float BODY_SPIN_FRICTION = 5.0; | 29 | const float BODY_SPIN_FRICTION = 5.0; |
| 30 | const float BODY_UPRIGHT_FORCE = 10.0; | 30 | const float BODY_UPRIGHT_FORCE = 10.0; |
| 31 | const float BODY_PITCH_WHILE_WALKING = 30.0; | 31 | const float BODY_PITCH_WHILE_WALKING = 40.0; |
| 32 | const float BODY_ROLL_WHILE_TURNING = 0.1; | 32 | const float BODY_ROLL_WHILE_TURNING = 0.1; |
| 33 | const float VELOCITY_DECAY = 5.0; | 33 | const float VELOCITY_DECAY = 5.0; |
| 34 | const float MY_HAND_HOLDING_PULL = 0.2; | 34 | const float MY_HAND_HOLDING_PULL = 0.2; |
| @@ -52,6 +52,8 @@ const float AVATAR_BRAKING_STRENGTH = 30.0f; · 17 unmodified lines | |||
| 52 | 52 | ||
| 53 | float skinColor [] = {1.0, 0.84, 0.66}; | 53 | float skinColor [] = {1.0, 0.84, 0.66}; |
| 54 | float lightBlue [] = {0.7, 0.8, 1.0}; | 54 | float lightBlue [] = {0.7, 0.8, 1.0}; |
| 55 | |||
| 56 | /* | ||
| 55 | float browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; | 57 | float browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; |
| 56 | float mouthColor[] = {1, 0, 0}; | 58 | float mouthColor[] = {1, 0, 0}; |
| 57 | 59 | ||
| @@ -64,16 +66,19 @@ float MouthWidthChoices[3] = {0.5, 0.77, 0.3}; · 6 unmodified lines | |||
| 64 | float browWidth = 0.8; | 66 | float browWidth = 0.8; |
| 65 | float browThickness = 0.16; | 67 | float browThickness = 0.16; |
| 66 | 68 | ||
| 67 | bool usingBigSphereCollisionTest = true; | ||
| 68 | 69 | ||
| 69 | char iris_texture_file[] = "resources/images/green_eye.png"; | 70 | //char iris_texture_file[] = "resources/images/green_eye.png"; |
| 71 | */ | ||
| 72 | bool usingBigSphereCollisionTest = true; | ||
| 70 | 73 | ||
| 71 | float chatMessageScale = 0.0015; | 74 | float chatMessageScale = 0.0015; |
| 72 | float chatMessageHeight = 0.45; | 75 | float chatMessageHeight = 0.45; |
| 73 | 76 | ||
| 77 | /* | ||
| 74 | vector<unsigned char> iris_texture; | 78 | vector<unsigned char> iris_texture; |
| 75 | unsigned int iris_texture_width = 512; | 79 | unsigned int iris_texture_width = 512; |
| 76 | unsigned int iris_texture_height = 256; | 80 | unsigned int iris_texture_height = 256; |
| 81 | */ | ||
| 77 | 82 | ||
| 78 | Avatar::Avatar(bool isMine) { | 83 | Avatar::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 | ||
| 252 | Avatar::~Avatar() { | 226 | Avatar::~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 state | 465 | // 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 | |||
| 467 | void Avatar::updateHandMovementAndTouching(float deltaTime) { | 484 | void Avatar::updateHandMovementAndTouching(float deltaTime) { |
| 468 | 485 | ||
| 469 | // reset hand and arm positions according to hand movement | 486 | // 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 forces | 560 | //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 ].position | 565 | - _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 | ||
| 580 | void Avatar::updateHead(float deltaTime) { | 596 | void Avatar::updateHead(float deltaTime) { |
| 581 | 597 | ||
| 582 | // Get head position data from network for other people | 598 | /* |
| 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 on | 599 | // Decay head back to center if turned on |
| 614 | if (_isMine && _returnHeadToCenter) { | 600 | if (_isMine && _returnHeadToCenter) { |
| 615 | // Decay back toward center | 601 | // 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 head | 882 | // 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 avatar | 887 | // 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 | |||
| 955 | void Avatar::renderHead(bool lookingInMirror) { | 944 | void 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 | |||
| 1126 | void Avatar::setHandMovementValues(glm::vec3 handOffset) { | 1118 | void 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 | ||
| 1482 | void 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 Glass | 1475 | // 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 rotation | 1509 | // 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 data | 1529 | // Every 100 packets, record the observed Hz of the transmitter data |
| @@ -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" | |
| 22 | enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; | ||
| 23 | 22 | ||
| 24 | enum DriveKeys | 23 | enum 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 levels | 124 | // 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 collision | 157 | bool isCollidable; // when false, the joint position will not register a collision |
| 166 | }; | 158 | }; |
| 167 | 159 | ||
| 168 | struct AvatarHead | 160 | 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 view | 192 | 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 | #endif | 211 | #endif |
| @@ -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 | |||
| 14 | using namespace std; | ||
| 15 | |||
| 16 | const float HEAD_MOTION_DECAY = 0.1; | ||
| 17 | |||
| 18 | |||
| 19 | float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; | ||
| 20 | float _mouthColor[] = {1, 0, 0}; | ||
| 21 | |||
| 22 | float _BrowRollAngle [5] = {0, 15, 30, -30, -15}; | ||
| 23 | float _BrowPitchAngle[3] = {-70, -60, -50}; | ||
| 24 | float _eyeColor [3] = {1,1,1}; | ||
| 25 | |||
| 26 | float _MouthWidthChoices[3] = {0.5, 0.77, 0.3}; | ||
| 27 | |||
| 28 | float _browWidth = 0.8; | ||
| 29 | float _browThickness = 0.16; | ||
| 30 | |||
| 31 | char iris_texture_file[] = "resources/images/green_eye.png"; | ||
| 32 | |||
| 33 | vector<unsigned char> iris_texture; | ||
| 34 | unsigned int iris_texture_width = 512; | ||
| 35 | unsigned int iris_texture_height = 256; | ||
| 36 | |||
| 37 | Head::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 | |||
| 47 | void 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 | |||
| 95 | void 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 | |||
| 104 | void Head::setSkinColor(glm::vec3 c) { | ||
| 105 | skinColor = c; | ||
| 106 | } | ||
| 107 | |||
| 108 | void Head::setAudioLoudness(float loudness) { | ||
| 109 | audioLoudness = loudness; | ||
| 110 | } | ||
| 111 | |||
| 112 | |||
| 113 | void Head::setNewTarget(float pitch, float yaw) { | ||
| 114 | pitchTarget = pitch; | ||
| 115 | yawTarget = yaw; | ||
| 116 | } | ||
| 117 | |||
| 118 | void 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 | |||
| 227 | void 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 | |||
| @@ -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 | |||
| 19 | enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; | ||
| 20 | |||
| 21 | class Head { | ||
| 22 | public: | ||
| 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 | ||
| @@ -102,6 +102,13 @@ int screenHeight = 800; · 101 unmodified lines | |||
| 102 | int fullscreen = 0; | 102 | int fullscreen = 0; |
| 103 | float aspectRatio = 1.0f; | 103 | float aspectRatio = 1.0f; |
| 104 | 104 | ||
| 105 | bool USING_MOUSE_VIEW_SHIFT = false; | ||
| 106 | float MOUSE_VIEW_SHIFT_RATE = 40.0f; | ||
| 107 | float MOUSE_VIEW_SHIFT_YAW_MARGIN = (float)(WIDTH * 0.2f); | ||
| 108 | float MOUSE_VIEW_SHIFT_PITCH_MARGIN = (float)(HEIGHT * 0.2f); | ||
| 109 | float MOUSE_VIEW_SHIFT_YAW_LIMIT = 45.0; | ||
| 110 | float MOUSE_VIEW_SHIFT_PITCH_LIMIT = 30.0; | ||
| 111 | |||
| 105 | //CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON; | 112 | //CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON; |
| 106 | CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON; | 113 | CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON; |
| 107 | 114 | ||
| @@ -206,7 +213,6 @@ double elapsedTime; · 98 unmodified lines | |||
| 206 | timeval applicationStartupTime; | 213 | timeval applicationStartupTime; |
| 207 | bool justStarted = true; | 214 | bool justStarted = true; |
| 208 | 215 | ||
| 209 | |||
| 210 | // Every second, check the frame rates and other stuff | 216 | // Every second, check the frame rates and other stuff |
| 211 | void Timer(int extra) { | 217 | void 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 position | 379 | // Using gyro data, update both view frustum and avatar head position |
| 375 | // | ||
| 376 | void updateAvatar(float deltaTime) { | 380 | void updateAvatar(float deltaTime) { |
| 377 | 381 | ||
| 378 | // Update my avatar's head position from gyros | 382 | // 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 stop | 1828 | // 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 devices | 1835 | // 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 | ||
| 1842 | void reshape(int width, int height) { | 1871 | void reshape(int width, int height) { |
| @@ -262,8 +262,21 @@ ViewFrustum::location VoxelNode::inFrustum(const ViewFrustum& viewFrustum) const · 261 unmodified lines | |||
| 262 | 262 | ||
| 263 | float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const { | 263 | float 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 | |||
| 271 | float 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 | |||
| 277 | float 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 | } | ||
| @@ -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; }; |