Showing the changes to interface/src (8 of 13 files). Show all
Unified · Split
| @@ -71,11 +71,6 @@ float flangeIntensity = 0; · 70 unmodified lines | ||
| 71 | 71 | float flangeRate = 0; |
| 72 | 72 | float flangeWeight = 0; |
| 73 | 73 | |
| 74 | −int16_t *walkingSoundArray; | |
| 75 | −int walkingSoundSamples; | |
| 76 | −int samplesLeftForWalk = 0; | |
| 77 | −int16_t *sampleWalkPointer; | |
| 78 | − | |
| 79 | 74 | timeval firstPlaybackTimer; |
| 80 | 75 | int packetsReceivedThisPlayback = 0; |
| 81 | 76 | float usecsAtStartup = 0; |
| @@ -357,10 +352,6 @@ bool Audio::getMixerLoopbackFlag() { · 275 unmodified lines | ||
| 357 | 352 | return audioData->mixerLoopbackFlag; |
| 358 | 353 | } |
| 359 | 354 | |
| 360 | −void Audio::setWalkingState(bool newWalkState) { | |
| 361 | − audioData->playWalkSound = newWalkState; | |
| 362 | −} | |
| 363 | − | |
| 364 | 355 | /** |
| 365 | 356 | * Initialize portaudio and start an audio stream. |
| 366 | 357 | * Should be called at the beginning of program exection. |
| @@ -368,23 +359,7 @@ void Audio::setWalkingState(bool newWalkState) { · 1 unmodified line | ||
| 368 | 359 | * @return Returns true if successful or false if an error occurred. |
| 369 | 360 | Use Audio::getError() to retrieve the error code. |
| 370 | 361 | */ |
| 371 | −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 | − | |
| 362 | +Audio::Audio(Oscilloscope* s, Avatar* linkedAvatar) { | |
| 388 | 363 | paError = Pa_Initialize(); |
| 389 | 364 | if (paError != paNoError) goto error; |
| 390 | 365 | |
| @@ -28,8 +28,6 @@ public: · 27 unmodified lines | ||
| 28 | 28 | float getInputLoudness() const; |
| 29 | 29 | void updateMixerParams(in_addr_t mixerAddress, in_port_t mixerPort); |
| 30 | 30 | |
| 31 | − void setWalkingState(bool newWalkState); | |
| 32 | − | |
| 33 | 31 | void setLastAcceleration(glm::vec3 a) { audioData->setLastAcceleration(a); }; |
| 34 | 32 | void setLastVelocity(glm::vec3 v) { audioData->setLastVelocity(v); }; |
| 35 | 33 | |
| @@ -38,7 +38,6 @@ class AudioData { · 37 unmodified lines | ||
| 38 | 38 | float lastInputLoudness; |
| 39 | 39 | |
| 40 | 40 | bool mixerLoopbackFlag; |
| 41 | − bool playWalkSound; | |
| 42 | 41 | |
| 43 | 42 | // Added avatar acceleration and velocity for procedural effects sounds from client |
| 44 | 43 | void setLastVelocity(glm::vec3 v) { _lastVelocity = v; }; |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <lodepng.h> |
| 12 | 12 | #include <SharedUtil.h> |
| 13 | 13 | #include "Avatar.h" |
| 14 | +#include "Head.h" | |
| 14 | 15 | #include "Log.h" |
| 15 | 16 | #include "ui/TextRenderer.h" |
| 16 | 17 | #include <AgentList.h> |
| @@ -23,12 +24,11 @@ const bool BALLS_ON = false; · 6 unmodified lines | ||
| 23 | 24 | const bool USING_AVATAR_GRAVITY = true; |
| 24 | 25 | const float GRAVITY_SCALE = 10.0f; |
| 25 | 26 | const float BOUNCE = 0.3f; |
| 26 | −const float DECAY = 0.1; | |
| 27 | 27 | const float THRUST_MAG = 1200.0; |
| 28 | 28 | const float YAW_MAG = 500.0; |
| 29 | 29 | const float BODY_SPIN_FRICTION = 5.0; |
| 30 | 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 | 32 | const float BODY_ROLL_WHILE_TURNING = 0.1; |
| 33 | 33 | const float VELOCITY_DECAY = 5.0; |
| 34 | 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 | 53 | float skinColor [] = {1.0, 0.84, 0.66}; |
| 54 | 54 | float lightBlue [] = {0.7, 0.8, 1.0}; |
| 55 | + | |
| 56 | +/* | |
| 55 | 57 | float browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; |
| 56 | 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 | 66 | float browWidth = 0.8; |
| 65 | 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 | 74 | float chatMessageScale = 0.0015; |
| 72 | 75 | float chatMessageHeight = 0.45; |
| 73 | 76 | |
| 77 | +/* | |
| 74 | 78 | vector<unsigned char> iris_texture; |
| 75 | 79 | unsigned int iris_texture_width = 512; |
| 76 | 80 | unsigned int iris_texture_height = 256; |
| 81 | +*/ | |
| 77 | 82 | |
| 78 | 83 | Avatar::Avatar(bool isMine) { |
| 79 | 84 | |
| @@ -104,43 +109,8 @@ Avatar::Avatar(bool isMine) { · 24 unmodified lines | ||
| 104 | 109 | |
| 105 | 110 | for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false; |
| 106 | 111 | |
| 107 | − _head.pupilSize = 0.10; | |
| 108 | − _head.interPupilDistance = 0.6; | |
| 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; | |
| 112 | + _head.initialize(); | |
| 113 | + | |
| 144 | 114 | _movedHandOffset = glm::vec3(0.0f, 0.0f, 0.0f); |
| 145 | 115 | _renderYaw = 0.0; |
| 146 | 116 | _renderPitch = 0.0; |
| @@ -153,6 +123,7 @@ Avatar::Avatar(bool isMine) { · 6 unmodified lines | ||
| 153 | 123 | |
| 154 | 124 | _avatarTouch.setReachableRadius(0.6); |
| 155 | 125 | |
| 126 | + /* | |
| 156 | 127 | if (iris_texture.size() == 0) { |
| 157 | 128 | switchToResourcesParentIfRequired(); |
| 158 | 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 | 131 | printLog("error %u: %s\n", error, lodepng_error_text(error)); |
| 161 | 132 | } |
| 162 | 133 | } |
| 134 | +*/ | |
| 163 | 135 | |
| 164 | 136 | if (BALLS_ON) { _balls = new Balls(100); } |
| 165 | 137 | else { _balls = NULL; } |
| @@ -239,7 +211,8 @@ Avatar::Avatar(const Avatar &otherAvatar) { · 73 unmodified lines | ||
| 239 | 211 | _distanceToNearestAvatar = otherAvatar._distanceToNearestAvatar; |
| 240 | 212 | |
| 241 | 213 | initializeSkeleton(); |
| 242 | − | |
| 214 | + | |
| 215 | +/* | |
| 243 | 216 | if (iris_texture.size() == 0) { |
| 244 | 217 | switchToResourcesParentIfRequired(); |
| 245 | 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 | 220 | printLog("error %u: %s\n", error, lodepng_error_text(error)); |
| 248 | 221 | } |
| 249 | 222 | } |
| 223 | +*/ | |
| 250 | 224 | } |
| 251 | 225 | |
| 252 | 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 | 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 | 476 | // use speed and angular velocity to determine walking vs. standing |
| 459 | 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 | 484 | void Avatar::updateHandMovementAndTouching(float deltaTime) { |
| 468 | 485 | |
| 469 | 486 | // reset hand and arm positions according to hand movement |
| @@ -540,7 +557,6 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { · 70 unmodified lines | ||
| 540 | 557 | _avatarTouch.setHoldingHands(false); |
| 541 | 558 | } |
| 542 | 559 | |
| 543 | − | |
| 544 | 560 | //if holding hands, apply the appropriate forces |
| 545 | 561 | if (_avatarTouch.getHoldingHands()) { |
| 546 | 562 | _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position += |
| @@ -549,8 +565,8 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { · 2 unmodified lines | ||
| 549 | 565 | - _joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].position |
| 550 | 566 | ) * 0.5f; |
| 551 | 567 | |
| 552 | − if (distanceBetweenOurHands > 0.2) { | |
| 553 | − float force = 700.0f * deltaTime; | |
| 568 | + if (distanceBetweenOurHands > 0.3) { | |
| 569 | + float force = 10.0f * deltaTime; | |
| 554 | 570 | if (force > 1.0f) {force = 1.0f;} |
| 555 | 571 | _velocity += vectorFromMyHandToYourHand * force; |
| 556 | 572 | } |
| @@ -579,37 +595,7 @@ void Avatar::updateHandMovementAndTouching(float deltaTime) { · 22 unmodified lines | ||
| 579 | 595 | |
| 580 | 596 | void Avatar::updateHead(float deltaTime) { |
| 581 | 597 | |
| 582 | − // Get head position data from network for other people | |
| 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 | − | |
| 598 | +/* | |
| 613 | 599 | // Decay head back to center if turned on |
| 614 | 600 | if (_isMine && _returnHeadToCenter) { |
| 615 | 601 | // Decay back toward center |
| @@ -712,6 +698,7 @@ void Avatar::updateHead(float deltaTime) { · 96 unmodified lines | ||
| 712 | 698 | const float AUDIO_AVERAGING_SECS = 0.05; |
| 713 | 699 | _head.averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _head.averageLoudness + |
| 714 | 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 | 882 | // render head |
| 896 | 883 | if (_displayingHead) { |
| 897 | − renderHead(lookingInMirror); | |
| 884 | + _head.render(lookingInMirror, _bodyYaw); | |
| 898 | 885 | } |
| 899 | 886 | |
| 900 | 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 | 944 | void Avatar::renderHead(bool lookingInMirror) { |
| 945 | +/* | |
| 956 | 946 | int side = 0; |
| 957 | 947 | |
| 958 | 948 | glEnable(GL_DEPTH_TEST); |
| @@ -1075,7 +1065,7 @@ void Avatar::renderHead(bool lookingInMirror) { · 116 unmodified lines | ||
| 1075 | 1065 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 1076 | 1066 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 1077 | 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 | 1071 | glPushMatrix(); |
| @@ -1121,8 +1111,10 @@ void Avatar::renderHead(bool lookingInMirror) { · 39 unmodified lines | ||
| 1121 | 1111 | |
| 1122 | 1112 | |
| 1123 | 1113 | glPopMatrix(); |
| 1114 | + */ | |
| 1124 | 1115 | } |
| 1125 | 1116 | |
| 1117 | + | |
| 1126 | 1118 | void Avatar::setHandMovementValues(glm::vec3 handOffset) { |
| 1127 | 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 | 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 | 1509 | // If first packet received, note time, turn head spring return OFF, get start rotation |
| 1523 | 1510 | gettimeofday(&_transmitterTimer, NULL); |
| 1524 | 1511 | if (deviceType == DEVICE_GLASS) { |
| 1525 | − setHeadReturnToCenter(true); | |
| 1526 | − setHeadSpringScale(10.f); | |
| 1512 | + _head.setReturnToCenter(true); | |
| 1513 | + _head.setSpringScale(10.f); | |
| 1527 | 1514 | printLog("Using Google Glass to drive head, springs ON.\n"); |
| 1528 | 1515 | |
| 1529 | 1516 | } else { |
| 1530 | − setHeadReturnToCenter(false); | |
| 1517 | + _head.setReturnToCenter(false); | |
| 1531 | 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 | 1524 | _transmitterInitialReading = glm::vec3(rot3, rot2, rot1); |
| 1538 | 1525 | } |
| 1526 | + | |
| 1539 | 1527 | const int TRANSMITTER_COUNT = 100; |
| 1540 | 1528 | if (_transmitterPackets % TRANSMITTER_COUNT == 0) { |
| 1541 | 1529 | // Every 100 packets, record the observed Hz of the transmitter data |
| @@ -18,8 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "InterfaceConfig.h" |
| 19 | 19 | #include "SerialInterface.h" |
| 20 | 20 | #include "Balls.h" |
| 21 | − | |
| 22 | −enum eyeContactTargets {LEFT_EYE, RIGHT_EYE, MOUTH}; | |
| 21 | +#include "Head.h" | |
| 23 | 22 | |
| 24 | 23 | enum DriveKeys |
| 25 | 24 | { |
| @@ -82,10 +81,8 @@ public: · 56 unmodified lines | ||
| 82 | 81 | Avatar* clone() const; |
| 83 | 82 | |
| 84 | 83 | void reset(); |
| 85 | − | |
| 86 | 84 | void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity); |
| 87 | 85 | void setNoise (float mag) {_head.noise = mag;} |
| 88 | − void setScale(float s) {_head.scale = s; }; | |
| 89 | 86 | void setRenderYaw(float y) {_renderYaw = y;} |
| 90 | 87 | void setRenderPitch(float p) {_renderPitch = p;} |
| 91 | 88 | float getRenderYaw() {return _renderYaw;} |
| @@ -124,11 +121,6 @@ public: · 32 unmodified lines | ||
| 124 | 121 | void updateArmIKAndConstraints( float deltaTime ); |
| 125 | 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 | 124 | // Set what driving keys are being pressed to control thrust levels |
| 133 | 125 | void setDriveKeys(int key, bool val) { _driveKeys[key] = val; }; |
| 134 | 126 | bool getDriveKeys(int key) { return _driveKeys[key]; }; |
| @@ -165,48 +157,7 @@ private: · 30 unmodified lines | ||
| 165 | 157 | bool isCollidable; // when false, the joint position will not register a collision |
| 166 | 158 | }; |
| 167 | 159 | |
| 168 | − struct AvatarHead | |
| 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; | |
| 160 | + Head _head; | |
| 210 | 161 | bool _isMine; |
| 211 | 162 | glm::vec3 _TEST_bigSpherePosition; |
| 212 | 163 | float _TEST_bigSphereRadius; |
| @@ -239,7 +190,6 @@ private: · 26 unmodified lines | ||
| 239 | 190 | Balls* _balls; |
| 240 | 191 | AvatarTouch _avatarTouch; |
| 241 | 192 | bool _displayingHead; // should be false if in first-person view |
| 242 | − bool _returnHeadToCenter; | |
| 243 | 193 | float _distanceToNearestAvatar; // How close is the nearest avatar? |
| 244 | 194 | glm::vec3 _gravity; |
| 245 | 195 | |
| @@ -256,11 +206,6 @@ private: · 10 unmodified lines | ||
| 256 | 206 | void updateCollisionWithSphere( glm::vec3 position, float radius, float deltaTime ); |
| 257 | 207 | void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime ); |
| 258 | 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 | 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 | 102 | int fullscreen = 0; |
| 103 | 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 | 112 | //CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON; |
| 106 | 113 | CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON; |
| 107 | 114 | |
| @@ -206,7 +213,6 @@ double elapsedTime; · 98 unmodified lines | ||
| 206 | 213 | timeval applicationStartupTime; |
| 207 | 214 | bool justStarted = true; |
| 208 | 215 | |
| 209 | − | |
| 210 | 216 | // Every second, check the frame rates and other stuff |
| 211 | 217 | void Timer(int extra) { |
| 212 | 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 | 379 | // Using gyro data, update both view frustum and avatar head position |
| 375 | −// | |
| 376 | 380 | void updateAvatar(float deltaTime) { |
| 377 | 381 | |
| 378 | 382 | // Update my avatar's head position from gyros |
| @@ -409,7 +413,34 @@ void updateAvatar(float deltaTime) { · 30 unmodified lines | ||
| 409 | 413 | const float RENDER_PITCH_MULTIPLY = 4.f; |
| 410 | 414 | myAvatar.setRenderPitch((1.f - renderPitchSpring * deltaTime) * myAvatar.getRenderPitch() + |
| 411 | 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 | 446 | if (OculusManager::isConnected()) { |
| @@ -1032,7 +1063,7 @@ void display(void) · 616 unmodified lines | ||
| 1032 | 1063 | myCamera.setDistance (1.5f); |
| 1033 | 1064 | myCamera.setTightness (8.0f); |
| 1034 | 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 | 1069 | // important... |
| @@ -1540,9 +1571,6 @@ void specialkey(int k, int x, int y) { · 501 unmodified lines | ||
| 1540 | 1571 | if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) myAvatar.setDriveKeys(RIGHT, 1); |
| 1541 | 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 | 1828 | // walking triggers the handControl to stop |
| 1801 | 1829 | if (myAvatar.getMode() == AVATAR_MODE_WALKING) { |
| 1802 | 1830 | handControl.stop(); |
| 1831 | + mouseViewShiftYaw *= 0.9; | |
| 1832 | + mouseViewShiftPitch *= 0.9; | |
| 1803 | 1833 | } |
| 1804 | 1834 | |
| 1805 | 1835 | // Read serial port interface devices |
| @@ -1836,7 +1866,6 @@ void idle(void) { · 30 unmodified lines | ||
| 1836 | 1866 | glutPostRedisplay(); |
| 1837 | 1867 | lastTimeIdle = check; |
| 1838 | 1868 | } |
| 1839 | − | |
| 1840 | 1869 | } |
| 1841 | 1870 | |
| 1842 | 1871 | void reshape(int width, int height) { |