diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d8442060f4..2efcd5b121 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -121,6 +121,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _wantToKillLocalVoxels(false), _audioScope(256, 200, true), _avatarManager(), + _myAvatar(NULL), _profile(QString()), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _mouseX(0), @@ -157,6 +158,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _logger(new FileLogger()), _persistThread(NULL) { + _myAvatar = _avatarManager.getMyAvatar(); + _applicationStartupTime = startup_time; switchToResourcesParentIfRequired(); @@ -327,6 +330,9 @@ Application::~Application() { VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown Menu::getInstance()->deleteLater(); + _avatarManager.clear(); + _myAvatar = NULL; + delete _logger; delete _settings; delete _glWidget; @@ -441,25 +447,25 @@ void Application::paintGL() { _myCamera.setUpShift (0.0f); _myCamera.setDistance (0.0f); _myCamera.setTightness (0.0f); // Camera is directly connected to head without smoothing - _myCamera.setTargetPosition(_myAvatar.getHead().calculateAverageEyePosition()); - _myCamera.setTargetRotation(_myAvatar.getHead().getOrientation()); + _myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); + _myCamera.setTargetRotation(_myAvatar->getHead().getOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { _myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay - _myCamera.setTargetPosition(_myAvatar.getHead().calculateAverageEyePosition()); - _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation()); + _myCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); + _myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { _myCamera.setTightness (0.0f); // Camera is directly connected to head without smoothing - _myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition()); - _myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation()); + _myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition()); + _myCamera.setTargetRotation(_myAvatar->getHead().getCameraOrientation()); } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setTightness(0.0f); - float headHeight = _myAvatar.getHead().calculateAverageEyePosition().y - _myAvatar.getPosition().y; - _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar.getScale()); - _myCamera.setTargetPosition(_myAvatar.getPosition() + glm::vec3(0, headHeight, 0)); - _myCamera.setTargetRotation(_myAvatar.getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); + float headHeight = _myAvatar->getHead().calculateAverageEyePosition().y - _myAvatar->getPosition().y; + _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale()); + _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight, 0)); + _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); } // Update camera position @@ -516,22 +522,22 @@ void Application::paintGL() { bool eyeRelativeCamera = false; if (_rearMirrorTools->getZoomLevel() == BODY) { - _mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar.getScale()); - _mirrorCamera.setTargetPosition(_myAvatar.getChestPosition()); + _mirrorCamera.setDistance(MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale()); + _mirrorCamera.setTargetPosition(_myAvatar->getChestPosition()); } else { // HEAD zoom level - _mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar.getScale()); - if (_myAvatar.getSkeletonModel().isActive() && _myAvatar.getHead().getFaceModel().isActive()) { + _mirrorCamera.setDistance(MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale()); + if (_myAvatar->getSkeletonModel().isActive() && _myAvatar->getHead().getFaceModel().isActive()) { // as a hack until we have a better way of dealing with coordinate precision issues, reposition the // face/body so that the average eye position lies at the origin eyeRelativeCamera = true; _mirrorCamera.setTargetPosition(glm::vec3()); } else { - _mirrorCamera.setTargetPosition(_myAvatar.getHead().calculateAverageEyePosition()); + _mirrorCamera.setTargetPosition(_myAvatar->getHead().calculateAverageEyePosition()); } } - _mirrorCamera.setTargetRotation(_myAvatar.getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); + _mirrorCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); _mirrorCamera.update(1.0f/_fps); // set the bounds of rear mirror view @@ -548,27 +554,27 @@ void Application::paintGL() { glPushMatrix(); if (eyeRelativeCamera) { // save absolute translations - glm::vec3 absoluteSkeletonTranslation = _myAvatar.getSkeletonModel().getTranslation(); - glm::vec3 absoluteFaceTranslation = _myAvatar.getHead().getFaceModel().getTranslation(); + glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation(); + glm::vec3 absoluteFaceTranslation = _myAvatar->getHead().getFaceModel().getTranslation(); // get the eye positions relative to the neck and use them to set the face translation glm::vec3 leftEyePosition, rightEyePosition; - _myAvatar.getHead().getFaceModel().setTranslation(glm::vec3()); - _myAvatar.getHead().getFaceModel().getEyePositions(leftEyePosition, rightEyePosition); - _myAvatar.getHead().getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f); + _myAvatar->getHead().getFaceModel().setTranslation(glm::vec3()); + _myAvatar->getHead().getFaceModel().getEyePositions(leftEyePosition, rightEyePosition); + _myAvatar->getHead().getFaceModel().setTranslation((leftEyePosition + rightEyePosition) * -0.5f); // get the neck position relative to the body and use it to set the skeleton translation glm::vec3 neckPosition; - _myAvatar.getSkeletonModel().setTranslation(glm::vec3()); - _myAvatar.getSkeletonModel().getNeckPosition(neckPosition); - _myAvatar.getSkeletonModel().setTranslation(_myAvatar.getHead().getFaceModel().getTranslation() - + _myAvatar->getSkeletonModel().setTranslation(glm::vec3()); + _myAvatar->getSkeletonModel().getNeckPosition(neckPosition); + _myAvatar->getSkeletonModel().setTranslation(_myAvatar->getHead().getFaceModel().getTranslation() - neckPosition); displaySide(_mirrorCamera, true); // restore absolute translations - _myAvatar.getSkeletonModel().setTranslation(absoluteSkeletonTranslation); - _myAvatar.getHead().getFaceModel().setTranslation(absoluteFaceTranslation); + _myAvatar->getSkeletonModel().setTranslation(absoluteSkeletonTranslation); + _myAvatar->getHead().getFaceModel().setTranslation(absoluteFaceTranslation); } else { displaySide(_mirrorCamera, true); } @@ -689,12 +695,12 @@ void Application::keyPressEvent(QKeyEvent* event) { if (activeWindow() == _window) { if (_chatEntryOn) { if (_chatEntry.keyPressEvent(event)) { - _myAvatar.setKeyState(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ? + _myAvatar->setKeyState(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ? DELETE_KEY_DOWN : INSERT_KEY_DOWN); - _myAvatar.setChatMessage(string(_chatEntry.getContents().size(), SOLID_BLOCK_CHAR)); + _myAvatar->setChatMessage(string(_chatEntry.getContents().size(), SOLID_BLOCK_CHAR)); } else { - _myAvatar.setChatMessage(_chatEntry.getContents()); + _myAvatar->setChatMessage(_chatEntry.getContents()); _chatEntry.clear(); _chatEntryOn = false; setMenuShortcutsEnabled(true); @@ -738,10 +744,10 @@ void Application::keyPressEvent(QKeyEvent* event) { if (_nudgeStarted) { _nudgeGuidePosition.y += _mouseVoxel.s; } else { - if (!_myAvatar.getDriveKeys(UP)) { - _myAvatar.jump(); + if (!_myAvatar->getDriveKeys(UP)) { + _myAvatar->jump(); } - _myAvatar.setDriveKeys(UP, 1); + _myAvatar->setDriveKeys(UP, 1); } break; @@ -753,7 +759,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (_nudgeStarted) { _nudgeGuidePosition.y -= _mouseVoxel.s; } else { - _myAvatar.setDriveKeys(DOWN, 1); + _myAvatar->setDriveKeys(DOWN, 1); } break; @@ -773,7 +779,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } } } else { - _myAvatar.setDriveKeys(FWD, 1); + _myAvatar->setDriveKeys(FWD, 1); } break; @@ -799,7 +805,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } } } else { - _myAvatar.setDriveKeys(BACK, 1); + _myAvatar->setDriveKeys(BACK, 1); } break; @@ -833,7 +839,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } } } else { - _myAvatar.setDriveKeys(ROT_LEFT, 1); + _myAvatar->setDriveKeys(ROT_LEFT, 1); } break; @@ -853,7 +859,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } } } else { - _myAvatar.setDriveKeys(ROT_RIGHT, 1); + _myAvatar->setDriveKeys(ROT_RIGHT, 1); } break; @@ -863,8 +869,8 @@ void Application::keyPressEvent(QKeyEvent* event) { nudgeVoxels(); } else { _chatEntryOn = true; - _myAvatar.setKeyState(NO_KEY_DOWN); - _myAvatar.setChatMessage(string()); + _myAvatar->setKeyState(NO_KEY_DOWN); + _myAvatar->setChatMessage(string()); setMenuShortcutsEnabled(false); } break; @@ -887,7 +893,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else if (_nudgeStarted && isShifted) { _nudgeGuidePosition.y += _mouseVoxel.s; } else { - _myAvatar.setDriveKeys(isShifted ? UP : FWD, 1); + _myAvatar->setDriveKeys(isShifted ? UP : FWD, 1); } break; @@ -909,7 +915,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } else if (_nudgeStarted && isShifted) { _nudgeGuidePosition.y -= _mouseVoxel.s; } else { - _myAvatar.setDriveKeys(isShifted ? DOWN : BACK, 1); + _myAvatar->setDriveKeys(isShifted ? DOWN : BACK, 1); } break; @@ -929,7 +935,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } } } else { - _myAvatar.setDriveKeys(isShifted ? LEFT : ROT_LEFT, 1); + _myAvatar->setDriveKeys(isShifted ? LEFT : ROT_LEFT, 1); } break; @@ -949,7 +955,7 @@ void Application::keyPressEvent(QKeyEvent* event) { } } } else { - _myAvatar.setDriveKeys(isShifted ? RIGHT : ROT_RIGHT, 1); + _myAvatar->setDriveKeys(isShifted ? RIGHT : ROT_RIGHT, 1); } break; @@ -1067,13 +1073,13 @@ void Application::keyPressEvent(QKeyEvent* event) { } break; case Qt::Key_Plus: - _myAvatar.increaseSize(); + _myAvatar->increaseSize(); break; case Qt::Key_Minus: - _myAvatar.decreaseSize(); + _myAvatar->decreaseSize(); break; case Qt::Key_Equal: - _myAvatar.resetSize(); + _myAvatar->resetSize(); break; case Qt::Key_1: @@ -1108,7 +1114,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { if (activeWindow() == _window) { if (_chatEntryOn) { - _myAvatar.setKeyState(NO_KEY_DOWN); + _myAvatar->setKeyState(NO_KEY_DOWN); return; } @@ -1117,47 +1123,47 @@ void Application::keyReleaseEvent(QKeyEvent* event) { _pasteMode = false; break; case Qt::Key_E: - _myAvatar.setDriveKeys(UP, 0); + _myAvatar->setDriveKeys(UP, 0); break; case Qt::Key_C: - _myAvatar.setDriveKeys(DOWN, 0); + _myAvatar->setDriveKeys(DOWN, 0); break; case Qt::Key_W: - _myAvatar.setDriveKeys(FWD, 0); + _myAvatar->setDriveKeys(FWD, 0); break; case Qt::Key_S: - _myAvatar.setDriveKeys(BACK, 0); + _myAvatar->setDriveKeys(BACK, 0); break; case Qt::Key_A: - _myAvatar.setDriveKeys(ROT_LEFT, 0); + _myAvatar->setDriveKeys(ROT_LEFT, 0); break; case Qt::Key_D: - _myAvatar.setDriveKeys(ROT_RIGHT, 0); + _myAvatar->setDriveKeys(ROT_RIGHT, 0); break; case Qt::Key_Up: - _myAvatar.setDriveKeys(FWD, 0); - _myAvatar.setDriveKeys(UP, 0); + _myAvatar->setDriveKeys(FWD, 0); + _myAvatar->setDriveKeys(UP, 0); break; case Qt::Key_Down: - _myAvatar.setDriveKeys(BACK, 0); - _myAvatar.setDriveKeys(DOWN, 0); + _myAvatar->setDriveKeys(BACK, 0); + _myAvatar->setDriveKeys(DOWN, 0); break; case Qt::Key_Left: - _myAvatar.setDriveKeys(LEFT, 0); - _myAvatar.setDriveKeys(ROT_LEFT, 0); + _myAvatar->setDriveKeys(LEFT, 0); + _myAvatar->setDriveKeys(ROT_LEFT, 0); break; case Qt::Key_Right: - _myAvatar.setDriveKeys(RIGHT, 0); - _myAvatar.setDriveKeys(ROT_RIGHT, 0); + _myAvatar->setDriveKeys(RIGHT, 0); + _myAvatar->setDriveKeys(ROT_RIGHT, 0); break; default: @@ -1192,11 +1198,11 @@ void Application::mouseMoveEvent(QMouseEvent* event) { // orbit behavior if (_mousePressed && !Menu::getInstance()->isVoxelModeActionChecked()) { if (_avatarManager.getLookAtTargetAvatar()) { - _myAvatar.orbit(_avatarManager.getLookAtTargetAvatar()->getPosition(), deltaX, deltaY); + _myAvatar->orbit(_avatarManager.getLookAtTargetAvatar()->getPosition(), deltaX, deltaY); return; } if (_isHoverVoxel) { - _myAvatar.orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY); + _myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY); return; } } @@ -1279,14 +1285,14 @@ void Application::mousePressEvent(QMouseEvent* event) { const float PERCENTAGE_TO_MOVE_TOWARD = 0.90f; glm::vec3 newTarget = getMouseVoxelWorldCoordinates(_hoverVoxel); - glm::vec3 myPosition = _myAvatar.getPosition(); + glm::vec3 myPosition = _myAvatar->getPosition(); // If there is not an action tool set (add, delete, color), move to this voxel if (Menu::getInstance()->isOptionChecked(MenuOption::ClickToFly) && !(Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) || Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) || Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode))) { - _myAvatar.setMoveTarget(myPosition + (newTarget - myPosition) * PERCENTAGE_TO_MOVE_TOWARD); + _myAvatar->setMoveTarget(myPosition + (newTarget - myPosition) * PERCENTAGE_TO_MOVE_TOWARD); } } @@ -1438,8 +1444,8 @@ void Application::timer() { DataServerClient::resendUnmatchedPackets(); // give the MyAvatar object position, orientation to the Profile so it can propagate to the data-server - _profile.updatePosition(_myAvatar.getPosition()); - _profile.updateOrientation(_myAvatar.getOrientation()); + _profile.updatePosition(_myAvatar->getPosition()); + _profile.updateOrientation(_myAvatar->getOrientation()); } static glm::vec3 getFaceVector(BoxFace face) { @@ -1734,7 +1740,7 @@ void Application::pasteVoxels() { } void Application::findAxisAlignment() { - glm::vec3 direction = _myAvatar.getMouseRayDirection(); + glm::vec3 direction = _myAvatar->getMouseRayDirection(); if (fabs(direction.z) > fabs(direction.x)) { _lookingAlongX = false; if (direction.z < 0) { @@ -1820,12 +1826,10 @@ void Application::init() { _headMouseY = _mouseY = _glWidget->height() / 2; QCursor::setPos(_headMouseX, _headMouseY); - _myAvatar.init(); - _myAvatar.setPosition(START_LOCATION); + // TODO: move _myAvatar out of Application. Move relevant code to MyAvataar or AvatarManager + _avatarManager.init(); _myCamera.setMode(CAMERA_MODE_FIRST_PERSON); _myCamera.setModeShiftRate(1.0f); - _myAvatar.setDisplayingLookatVectors(false); - _avatarManager.setMyAvatar(&_myAvatar); _mirrorCamera.setMode(CAMERA_MODE_MIRROR); _mirrorCamera.setAspectRatio((float)MIRROR_VIEW_WIDTH / (float)MIRROR_VIEW_HEIGHT); @@ -1930,9 +1934,9 @@ const float HEAD_SPHERE_RADIUS = 0.07f; bool Application::isLookingAtMyAvatar(Avatar* avatar) { glm::vec3 theirLookat = avatar->getHead().getLookAtPosition(); - glm::vec3 myHeadPosition = _myAvatar.getHead().getPosition(); + glm::vec3 myHeadPosition = _myAvatar->getHead().getPosition(); - if (pointInSphere(theirLookat, myHeadPosition, HEAD_SPHERE_RADIUS * _myAvatar.getScale())) { + if (pointInSphere(theirLookat, myHeadPosition, HEAD_SPHERE_RADIUS * _myAvatar->getScale())) { return true; } return false; @@ -1970,10 +1974,10 @@ void Application::updateMouseRay() { } // tell my avatar if the mouse is being pressed... - _myAvatar.setMousePressed(_mousePressed); + _myAvatar->setMousePressed(_mousePressed); // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position - _myAvatar.setMouseRay(_mouseRayOrigin, _mouseRayDirection); + _myAvatar->setMouseRay(_mouseRayOrigin, _mouseRayDirection); } void Application::updateFaceshift() { @@ -1986,7 +1990,7 @@ void Application::updateFaceshift() { // Copy angular velocity if measured by faceshift, to the head if (_faceshift.isActive()) { - _myAvatar.getHead().setAngularVelocity(_faceshift.getHeadAngularVelocity()); + _myAvatar->getHead().setAngularVelocity(_faceshift.getHeadAngularVelocity()); } } @@ -2010,14 +2014,14 @@ void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot) { } if (_faceshift.isActive()) { // deflect using Faceshift gaze data - glm::vec3 origin = _myAvatar.getHead().calculateAverageEyePosition(); + glm::vec3 origin = _myAvatar->getHead().calculateAverageEyePosition(); float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f; float deflection = Menu::getInstance()->getFaceshiftEyeDeflection(); lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3( _faceshift.getEstimatedEyePitch() * pitchSign * deflection, _faceshift.getEstimatedEyeYaw() * deflection, 0.0f))) * glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin); } - _myAvatar.getHead().setLookAtPosition(lookAtSpot); + _myAvatar->getHead().setLookAtPosition(lookAtSpot); } void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& face) { @@ -2075,9 +2079,9 @@ void Application::updateMouseVoxels(float deltaTime, float& distance, BoxFace& f _mouseVoxel.s = 0.0f; bool wasInitialized = _mouseVoxelScaleInitialized; if (Menu::getInstance()->isVoxelModeActionChecked() && - (fabs(_myAvatar.getVelocity().x) + - fabs(_myAvatar.getVelocity().y) + - fabs(_myAvatar.getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) { + (fabs(_myAvatar->getVelocity().x) + + fabs(_myAvatar->getVelocity().y) + + fabs(_myAvatar->getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) { if (_voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _mouseVoxel, distance, face)) { if (distance < MAX_VOXEL_EDIT_DISTANCE) { @@ -2209,16 +2213,16 @@ void Application::updateMyAvatarSimulation(float deltaTime) { PerformanceWarning warn(showWarnings, "Application::updateMyAvatarSimulation()"); if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) { - _myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition())); + _myAvatar->setGravity(_environment.getGravity(_myAvatar->getPosition())); } else { - _myAvatar.setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); + _myAvatar->setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); } if (Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) { - _myAvatar.simulate(deltaTime, &_myTransmitter); + _myAvatar->simulate(deltaTime, &_myTransmitter); } else { - _myAvatar.simulate(deltaTime, NULL); + _myAvatar->simulate(deltaTime, NULL); } } @@ -2246,8 +2250,8 @@ void Application::updateTransmitter(float deltaTime) { // no transmitter drive implies transmitter pick if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) { - _transmitterPickStart = _myAvatar.getChestPosition(); - glm::vec3 direction = _myAvatar.getOrientation() * + _transmitterPickStart = _myAvatar->getChestPosition(); + glm::vec3 direction = _myAvatar->getOrientation() * glm::quat(glm::radians(_myTransmitter.getEstimatedRotation())) * IDENTITY_FRONT; // check against voxels, avatars @@ -2321,8 +2325,8 @@ void Application::updateAudio(float deltaTime) { PerformanceWarning warn(showWarnings, "Application::updateAudio()"); // Update audio stats for procedural sounds - _audio.setLastAcceleration(_myAvatar.getThrust()); - _audio.setLastVelocity(_myAvatar.getVelocity()); + _audio.setLastAcceleration(_myAvatar->getThrust()); + _audio.setLastVelocity(_myAvatar->getVelocity()); } void Application::updateCursor(float deltaTime) { @@ -2394,16 +2398,16 @@ void Application::updateAvatar(float deltaTime) { PerformanceWarning warn(showWarnings, "Application::updateAvatar()"); // rotate body yaw for yaw received from multitouch - _myAvatar.setOrientation(_myAvatar.getOrientation() + _myAvatar->setOrientation(_myAvatar->getOrientation() * glm::quat(glm::vec3(0, _yawFromTouch, 0))); _yawFromTouch = 0.f; // apply pitch from touch - _myAvatar.getHead().setPitch(_myAvatar.getHead().getPitch() + _pitchFromTouch); + _myAvatar->getHead().setPitch(_myAvatar->getHead().getPitch() + _pitchFromTouch); _pitchFromTouch = 0.0f; // Update my avatar's state from gyros - _myAvatar.updateFromGyros(Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)); + _myAvatar->updateFromGyros(Menu::getInstance()->isOptionChecked(MenuOption::TurnWithHead)); // Update head mouse from faceshift if active if (_faceshift.isActive()) { @@ -2424,17 +2428,17 @@ void Application::updateAvatar(float deltaTime) { float yaw, pitch, roll; OculusManager::getEulerAngles(yaw, pitch, roll); - _myAvatar.getHead().setYaw(yaw); - _myAvatar.getHead().setPitch(pitch); - _myAvatar.getHead().setRoll(roll); + _myAvatar->getHead().setYaw(yaw); + _myAvatar->getHead().setPitch(pitch); + _myAvatar->getHead().setRoll(roll); } // Get audio loudness data from audio input device - _myAvatar.getHead().setAudioLoudness(_audio.getLastInputLoudness()); + _myAvatar->getHead().setAudioLoudness(_audio.getLastInputLoudness()); // send head/hand data to the avatar mixer and voxel server QByteArray avatarData = byteArrayWithPopluatedHeader(PacketTypeAvatarData); - avatarData.append(_myAvatar.toByteArray()); + avatarData.append(_myAvatar->toByteArray()); controlledBroadcastToNodes(avatarData, NodeSet() << NodeType::AvatarMixer); @@ -3319,7 +3323,7 @@ void Application::displayStats() { horizontalOffset += 171; } - glm::vec3 avatarPos = _myAvatar.getPosition(); + glm::vec3 avatarPos = _myAvatar->getPosition(); lines = _statsExpanded ? 4 : 3; displayStatsBackground(backgroundColor, horizontalOffset, 0, _glWidget->width() - (mirrorEnabled ? 301 : 411) - horizontalOffset, lines * STATS_PELS_PER_LINE + 10); @@ -3334,9 +3338,9 @@ void Application::displayStats() { sprintf(avatarPosition, "Position: %.3f, %.3f, %.3f", avatarPos.x, avatarPos.y, avatarPos.z); } char avatarVelocity[30]; - sprintf(avatarVelocity, "Velocity: %.1f", glm::length(_myAvatar.getVelocity())); + sprintf(avatarVelocity, "Velocity: %.1f", glm::length(_myAvatar->getVelocity())); char avatarBodyYaw[30]; - sprintf(avatarBodyYaw, "Yaw: %.2f", _myAvatar.getBodyYaw()); + sprintf(avatarBodyYaw, "Yaw: %.2f", _myAvatar->getBodyYaw()); char avatarMixerStats[200]; verticalOffset += STATS_PELS_PER_LINE; @@ -3957,10 +3961,10 @@ void Application::resetSensors() { } QCursor::setPos(_headMouseX, _headMouseY); - _myAvatar.reset(); + _myAvatar->reset(); _myTransmitter.resetLevels(); - _myAvatar.setVelocity(glm::vec3(0,0,0)); - _myAvatar.setThrust(glm::vec3(0,0,0)); + _myAvatar->setVelocity(glm::vec3(0,0,0)); + _myAvatar->setThrust(glm::vec3(0,0,0)); QMetaObject::invokeMethod(&_audio, "reset", Qt::QueuedConnection); } @@ -4089,7 +4093,7 @@ void Application::nodeKilled(SharedNodePointer node) { } else if (node->getType() == NodeType::AvatarMixer) { // our avatar mixer has gone away - clear the hash of avatars - _avatarManager.clearHash(); + _avatarManager.clearMixedAvatars(); } } @@ -4204,7 +4208,7 @@ void Application::removeScriptName(const QString& fileNameString) _activeScripts.removeOne(fileNameString); } -void Application::loadScript(const QString& fileNameString){ +void Application::loadScript(const QString& fileNameString) { _activeScripts.append(fileNameString); QByteArray fileNameAscii = fileNameString.toLocal8Bit(); const char* fileName = fileNameAscii.data(); @@ -4242,7 +4246,7 @@ void Application::loadScript(const QString& fileNameString){ scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree()); // hook our avatar object into this script engine - scriptEngine->setAvatarData(&_myAvatar, "MyAvatar"); + scriptEngine->setAvatarData( static_cast(_myAvatar), "MyAvatar"); QThread* workerThread = new QThread(this); @@ -4409,6 +4413,6 @@ void Application::takeSnapshot() { player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); player->play(); - Snapshot::saveSnapshot(_glWidget, _profile.getUsername(), _myAvatar.getPosition()); + Snapshot::saveSnapshot(_glWidget, _profile.getUsername(), _myAvatar->getPosition()); } diff --git a/interface/src/Application.h b/interface/src/Application.h index d38c3675d7..a0b52365cf 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -142,7 +142,7 @@ public: glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); QGLWidget* getGLWidget() { return _glWidget; } - MyAvatar* getAvatar() { return &_myAvatar; } + MyAvatar* getAvatar() { return _myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } @@ -374,10 +374,10 @@ private: VoxelQuery _voxelQuery; // NodeData derived class for querying voxels from voxel server AvatarManager _avatarManager; - MyAvatar _myAvatar; // The rendered avatar of oneself - Profile _profile; // The data-server linked profile for this user + MyAvatar* _myAvatar; // TODO: move this and relevant code to AvatarManager (or MyAvatar as the case may be) + Profile _profile; // The data-server linked profile for this user - Transmitter _myTransmitter; // Gets UDP data from transmitter app used to animate the avatar + Transmitter _myTransmitter; // Gets UDP data from transmitter app used to animate the avatar Faceshift _faceshift; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 1c08af89eb..06b550b9d6 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -23,21 +23,24 @@ AvatarManager::AvatarManager(QObject* parent) : _lookAtTargetAvatar(), _lookAtOtherPosition(), _lookAtIndicatorScale(1.0f), - _avatarFades(), - _myAvatar(NULL) -{ + _avatarFades() { // register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar qRegisterMetaType >("NodeWeakPointer"); + _myAvatar = QSharedPointer(new MyAvatar()); } -void AvatarManager::setMyAvatar(MyAvatar* myAvatar) { - if (!_myAvatar) { - // can only ever set this once - _myAvatar = myAvatar; - // add _myAvatar to the list - AvatarSharedPointer myPointer = AvatarSharedPointer(_myAvatar); - _avatarHash.insert(MY_AVATAR_KEY, myPointer); - } +void AvatarManager::clear() { + _lookAtTargetAvatar.clear(); + _avatarFades.clear(); + _avatarHash.clear(); + _myAvatar.clear(); +} + +void AvatarManager::init() { + _myAvatar->init(); + _myAvatar->setPosition(START_LOCATION); + _myAvatar->setDisplayingLookatVectors(false); + _avatarHash.insert(MY_AVATAR_KEY, _myAvatar); } void AvatarManager::updateLookAtTargetAvatar(glm::vec3 &eyePosition) { @@ -52,7 +55,7 @@ void AvatarManager::updateLookAtTargetAvatar(glm::vec3 &eyePosition) { foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) { Avatar* avatar = static_cast(avatarPointer.data()); - if (avatar != static_cast(_myAvatar)) { + if (avatar != static_cast(_myAvatar.data())) { float distance; if (avatar->findRayIntersection(mouseOrigin, mouseDirection, distance)) { // rescale to compensate for head embiggening @@ -86,7 +89,7 @@ void AvatarManager::updateAvatars(float deltaTime) { AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { Avatar* avatar = static_cast(avatarIterator.value().data()); - if (avatar == static_cast(_myAvatar)) { + if (avatar == static_cast(_myAvatar.data())) { // for now skip updates to _myAvatar because it is done explicitly in Application // TODO: update _myAvatar in this context ++avatarIterator; @@ -122,7 +125,7 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { if (!avatar->isInitialized()) { avatar->init(); } - if (avatar == static_cast(_myAvatar)) { + if (avatar == static_cast(_myAvatar.data())) { avatar->render(forceRenderHead); } else { avatar->render(false); @@ -130,8 +133,8 @@ void AvatarManager::renderAvatars(bool forceRenderHead, bool selfAvatarOnly) { avatar->setDisplayingLookatVectors(renderLookAtVectors); } renderAvatarFades(); - } else if (_myAvatar) { - // Render my own Avatar + } else { + // just render myAvatar _myAvatar->render(forceRenderHead); _myAvatar->setDisplayingLookatVectors(renderLookAtVectors); } @@ -261,10 +264,11 @@ AvatarHash::iterator AvatarManager::erase(const AvatarHash::iterator& iterator) } } -void AvatarManager::clearHash() { - // clear the AvatarManager hash - typically happens on the removal of the avatar-mixer +void AvatarManager::clearMixedAvatars() { + // clear any avatars that came from an avatar-mixer AvatarHash::iterator removeAvatar = _avatarHash.begin(); while (removeAvatar != _avatarHash.end()) { removeAvatar = erase(removeAvatar); } + _lookAtTargetAvatar.clear(); } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 369444bcc7..ca436b324d 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -25,7 +25,11 @@ class AvatarManager : public QObject, public DataServerCallbackObject, public Av public: AvatarManager(QObject* parent = 0); - void setMyAvatar(MyAvatar* myAvatar); + void clear(); + + void init(); + + MyAvatar* getMyAvatar() { return _myAvatar.data(); } AvatarData* getLookAtTargetAvatar() const { return _lookAtTargetAvatar.data(); } @@ -34,8 +38,7 @@ public: void updateAvatars(float deltaTime); void renderAvatars(bool forceRenderHead, bool selfAvatarOnly = false); - // virtual override - void clearHash(); + void clearMixedAvatars(); public slots: void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList); @@ -57,7 +60,7 @@ private: float _lookAtIndicatorScale; QVector _avatarFades; - MyAvatar* _myAvatar; + QSharedPointer _myAvatar; }; #endif /* defined(__hifi__AvatarManager__) */ diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index b1bb42edbf..72ada7d421 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -17,13 +17,6 @@ void AvatarHashMap::insert(const QUuid& id, AvatarSharedPointer avatar) { _avatarHash.insert(id, avatar); } -void AvatarHashMap::clearHash() { - AvatarHash::iterator removeAvatar = _avatarHash.begin(); - while (removeAvatar != _avatarHash.end()) { - removeAvatar = erase(removeAvatar); - } -} - AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) { return _avatarHash.erase(iterator); } diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 37e9004d6f..19b6623402 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -26,7 +26,6 @@ public: int size() const { return _avatarHash.size(); } virtual void insert(const QUuid& id, AvatarSharedPointer avatar); - virtual void clearHash(); protected: virtual AvatarHash::iterator erase(const AvatarHash::iterator& iterator);