diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a4271afdc7..270fe3f5c5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1499,14 +1499,14 @@ void Application::shootParticle() { glm::vec3 position = _viewFrustum.getPosition(); glm::vec3 direction = _viewFrustum.getDirection(); - const float LINEAR_VELOCITY = 30.0f; + const float LINEAR_VELOCITY = 5.f; glm::vec3 lookingAt = position + (direction * LINEAR_VELOCITY); - const float radius = 0.5 / TREE_SCALE; - xColor color = { 255, 0, 0}; + const float radius = 0.125 / TREE_SCALE; + xColor color = { 0, 255, 255}; glm::vec3 velocity = lookingAt - position; - glm::vec3 gravity = DEFAULT_GRAVITY; - float damping = DEFAULT_DAMPING; + glm::vec3 gravity = DEFAULT_GRAVITY * 0.f; + float damping = DEFAULT_DAMPING * 0.01f; QString updateScript(""); ParticleEditHandle* particleEditHandle = makeParticle(position / (float)TREE_SCALE, radius, color, @@ -1551,18 +1551,7 @@ void Application::makeVoxel(glm::vec3 position, _voxels.createVoxel(voxel.x, voxel.y, voxel.z, voxel.s, voxel.red, voxel.green, voxel.blue, isDestructive); - - // Implement voxel fade effect - VoxelFade fade(VoxelFade::FADE_OUT, 1.0f, 1.0f, 1.0f); - const float VOXEL_BOUNDS_ADJUST = 0.01f; - float slightlyBigger = voxel.s * VOXEL_BOUNDS_ADJUST; - fade.voxelDetails.x = voxel.x - slightlyBigger; - fade.voxelDetails.y = voxel.y - slightlyBigger; - fade.voxelDetails.z = voxel.z - slightlyBigger; - fade.voxelDetails.s = voxel.s + slightlyBigger + slightlyBigger; - _voxelFades.push_back(fade); - -} + } const glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel) { return glm::vec3((_mouseVoxel.x + _mouseVoxel.s / 2.f) * TREE_SCALE, @@ -2530,7 +2519,10 @@ void Application::updateAvatar(float deltaTime) { _yawFromTouch = 0.f; // apply pitch from touch - _myAvatar.getHead().setMousePitch(_myAvatar.getHead().getMousePitch() + _pitchFromTouch); + _myAvatar.getHead().setMousePitch(_myAvatar.getHead().getMousePitch() + + _myAvatar.getHand().getPitchUpdate() + + _pitchFromTouch); + _myAvatar.getHand().setPitchUpdate(0.f); _pitchFromTouch = 0.0f; // Update my avatar's state from gyros and/or webcam diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 7d735a5ced..e3a45d8711 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -19,15 +19,26 @@ using namespace std; +const float FINGERTIP_VOXEL_SIZE = 0.05; +const int TOY_BALL_HAND = 1; +const float TOY_BALL_RADIUS = 0.05f; +const glm::vec3 TOYBALL_GRAVITY (0, -1, 0); +float TOYBALL_DAMPING = 1.f; +const float PALM_COLLISION_RADIUS = 0.03f; + Hand::Hand(Avatar* owningAvatar) : HandData((AvatarData*)owningAvatar), - + _owningAvatar(owningAvatar), _renderAlpha(1.0), _ballColor(0.0, 0.0, 0.4), _collisionCenter(0,0,0), _collisionAge(0), - _collisionDuration(0) + _collisionDuration(0), + _toyBallPosition(0), + _toyBallVelocity(0), + _toyBallInHand(false), + _pitchUpdate(0) { } @@ -44,6 +55,57 @@ void Hand::init() { void Hand::reset() { } +void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) { + if (palm.getControllerButtons() & BUTTON_FWD) { + // If grabbing toy ball, add forces to it + if (!_toyBallInHand) { + // Test for whether close enough to catch and catch + bool isCaught = true; + if (isCaught) { + _toyBallInHand = true; + } + } + if (_toyBallInHand) { + // Ball is in hand + _toyBallPosition = fingerTipPosition; + _toyBallVelocity = glm::vec3(0); + + } + } else { + // If toy ball just released, add velocity to it! + if (_toyBallInHand) { + _toyBallInHand = false; + glm::vec3 handVelocity = palm.getRawVelocity(); + glm::vec3 fingerTipVelocity = palm.getTipVelocity(); + glm::quat avatarRotation = _owningAvatar->getOrientation(); + //printVector(avatarRotation * handVelocity); + _toyBallVelocity += avatarRotation * fingerTipVelocity; + + // Create a particle on the particle server + xColor color = { 255, 255, 0}; // Slightly different color on server + glm::vec3 gravity = glm::vec3(0, -1, 0); + float damping = 0.99f; + QString updateScript(""); + Application::getInstance()->makeParticle(fingerTipPosition / (float)TREE_SCALE, + TOY_BALL_RADIUS / (float) TREE_SCALE, + color, + _toyBallVelocity / (float)TREE_SCALE, + gravity / (float) TREE_SCALE, damping, updateScript); + } + } + // Simulate toy ball + _toyBallPosition += _toyBallVelocity * deltaTime; + + if (!_toyBallInHand) { + _toyBallVelocity += TOYBALL_GRAVITY * deltaTime; + } + if (_toyBallPosition.y < 0.f) { + _toyBallPosition.y = 0.f; + _toyBallVelocity.y *= -1.f; + } + _toyBallVelocity -= (_toyBallVelocity * TOYBALL_DAMPING) * deltaTime; + +} void Hand::simulate(float deltaTime, bool isMine) { @@ -64,13 +126,19 @@ void Hand::simulate(float deltaTime, bool isMine) { calculateGeometry(); if (isMine) { - // Create a voxel at fingertip if controller button is pressed - const float FINGERTIP_VOXEL_SIZE = 0.0125; + + // Iterate hand controllers, take actions as needed + for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; if (palm.isActive()) { FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger glm::vec3 fingerTipPosition = finger.getTipPosition(); + + if (palm.getSixenseID() == TOY_BALL_HAND) { + simulateToyBall(palm, fingerTipPosition, deltaTime); + } + if (palm.getControllerButtons() & BUTTON_1) { if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) { QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value(); @@ -121,8 +189,6 @@ void Hand::simulate(float deltaTime, bool isMine) { } } -const float PALM_COLLISION_RADIUS = 0.03f; - void Hand::updateCollisions() { // use position to obtain the left and right palm indices int leftPalmIndex, rightPalmIndex; @@ -171,7 +237,7 @@ void Hand::handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPositi const float DECAY_PER_SAMPLE = 0.0005f; const float DURATION_MAX = 2.0f; const float MIN_VOLUME = 0.1f; - float volume = MIN_VOLUME + glm::clamp(glm::length(palm->getVelocity()), 0.f, (1.f - MIN_VOLUME)); + float volume = MIN_VOLUME + glm::clamp(glm::length(palm->getRawVelocity()), 0.f, (1.f - MIN_VOLUME)); float duration = volume; _collisionCenter = fingerTipPosition; _collisionAge = deltaTime; @@ -253,6 +319,14 @@ void Hand::render( bool isMine) { renderLeapHands(); } + // Render toy ball + if (isMine) { + glPushMatrix(); + glColor3f(1, 0, 0); + glTranslatef(_toyBallPosition.x, _toyBallPosition.y, _toyBallPosition.z); + glutSolidSphere(TOY_BALL_RADIUS, 10, 10); + glPopMatrix(); + } if (isMine) { // If hand/voxel collision has happened, render a little expanding sphere @@ -267,47 +341,8 @@ void Hand::render( bool isMine) { _collisionAge = 0.f; } } - - // If hand controller buttons pressed, render stuff as needed - if (getPalms().size() > 0) { - for (size_t i = 0; i < getPalms().size(); ++i) { - PalmData& palm = getPalms()[i]; - // If trigger pulled, thrust in that direction and draw beam - const float MAX_THRUSTER_BEAM_LENGTH = 5.f; - const float THRUSTER_MARKER_SIZE = 0.0125f; - if (palm.getJoystickY() != 0.f) { - FingerData& finger = palm.getFingers()[0]; - if (finger.isActive()) { - if (palm.getJoystickY() > 0.f) { - glColor3f(0, 1, 0); - } else { - glColor3f(1, 0, 0); - } - glm::vec3 palmPosition = palm.getPosition(); - glm::vec3 pointerPosition = palmPosition + - glm::normalize(finger.getTipPosition() - palmPosition) * - MAX_THRUSTER_BEAM_LENGTH; - glPushMatrix(); - glm::vec3 markerPosition = palmPosition + - glm::normalize(finger.getTipPosition() - palmPosition) * - MAX_THRUSTER_BEAM_LENGTH * - (0.5f + palm.getJoystickY() / 2.f); - - glTranslatef(markerPosition.x, markerPosition.y, markerPosition.z); - glutSolidSphere(THRUSTER_MARKER_SIZE, 10, 10); - glPopMatrix(); - glLineWidth(2.0); - glBegin(GL_LINES); - glVertex3f(palmPosition.x, palmPosition.y, palmPosition.z); - glVertex3f(pointerPosition.x, pointerPosition.y, pointerPosition.z); - glEnd(); - } - } - } - } } - - + glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 12d6d0d8da..a8a6b6106e 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -54,6 +54,10 @@ public: const glm::vec3& getLeapFingerTipBallPosition (int ball) const { return _leapFingerTipBalls [ball].position;} const glm::vec3& getLeapFingerRootBallPosition(int ball) const { return _leapFingerRootBalls[ball].position;} + // Pitch from controller input to view + const float getPitchUpdate() const { return _pitchUpdate; } + void setPitchUpdate(float pitchUpdate) { _pitchUpdate = pitchUpdate; } + private: // disallow copies of the Hand, copy of owning Avatar is disallowed too Hand(const Hand&); @@ -86,6 +90,15 @@ private: void calculateGeometry(); void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime); + + void simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime); + + glm::vec3 _toyBallPosition; + glm::vec3 _toyBallVelocity; + bool _toyBallInHand; + + float _pitchUpdate; + }; #endif diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c65c6d50a3..7518d639c3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -667,20 +667,31 @@ void MyAvatar::updateThrust(float deltaTime, Transmitter * transmitter) { // Add thrust and rotation from hand controllers const float THRUST_MAG_HAND_JETS = THRUST_MAG_FWD; const float JOYSTICK_YAW_MAG = YAW_MAG; + const float JOYSTICK_PITCH_MAG = PITCH_MAG * 0.5f; + const int THRUST_CONTROLLER = 0; + const int VIEW_CONTROLLER = 1; for (size_t i = 0; i < getHand().getPalms().size(); ++i) { PalmData& palm = getHand().getPalms()[i]; - if (palm.isActive()) { + if (palm.isActive() && (palm.getSixenseID() == THRUST_CONTROLLER)) { if (palm.getJoystickY() != 0.f) { FingerData& finger = palm.getFingers()[0]; if (finger.isActive()) { } - glm::vec3 thrustDirection = glm::normalize(finger.getTipPosition() - palm.getPosition()); - _thrust += thrustDirection * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickY() * _thrustMultiplier * deltaTime; + _thrust += front * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickY() * _thrustMultiplier * deltaTime; } + if (palm.getJoystickX() != 0.f) { + _thrust += right * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickX() * _thrustMultiplier * deltaTime; + } + } else if (palm.isActive() && (palm.getSixenseID() == VIEW_CONTROLLER)) { if (palm.getJoystickX() != 0.f) { _bodyYawDelta -= palm.getJoystickX() * JOYSTICK_YAW_MAG * deltaTime; } + if (palm.getJoystickY() != 0.f) { + getHand().setPitchUpdate(getHand().getPitchUpdate() + + (palm.getJoystickY() * JOYSTICK_PITCH_MAG * deltaTime)); + } } + } // Update speed brake status diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index e7414895e3..a76bed3ac9 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -16,7 +16,7 @@ SixenseManager::SixenseManager() { #ifdef HAVE_SIXENSE sixenseInit(); - sixenseSetFilterEnabled(0); + sixenseSetFilterEnabled(1); #endif } @@ -42,8 +42,6 @@ void SixenseManager::update(float deltaTime) { sixenseControllerData data; sixenseGetNewestData(i, &data); - //printf("si: %i\n", data.controller_index); - // Set palm position and normal based on Hydra position/orientation // Either find a palm matching the sixense controller, or make a new one @@ -82,15 +80,18 @@ void SixenseManager::update(float deltaTime) { const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f); position = SPHERE_TO_TORSO + position; - // Compute current velocity from position change - palm->setVelocity((position - palm->getRawPosition()) / deltaTime / 1000.f); // meters/sec - palm->setRawPosition(position); - // Rotation of Palm glm::quat rotation(data.rot_quat[3], -data.rot_quat[0], data.rot_quat[1], -data.rot_quat[2]); rotation = glm::angleAxis(180.0f, 0.f, 1.f, 0.f) * rotation; const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f); - palm->setRawNormal(rotation * PALM_VECTOR); + glm::vec3 newNormal = rotation * PALM_VECTOR; + palm->setRawNormal(newNormal); + palm->setRawRotation(rotation); + + // Compute current velocity from position change + glm::vec3 rawVelocity = (position - palm->getRawPosition()) / deltaTime / 1000.f; + palm->setRawVelocity(rawVelocity); // meters/sec + palm->setRawPosition(position); // initialize the "finger" based on the direction FingerData finger(palm, &hand); @@ -98,8 +99,14 @@ void SixenseManager::update(float deltaTime) { finger.setRawRootPosition(position); const float FINGER_LENGTH = 300.0f; // Millimeters const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); + const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; finger.setRawTipPosition(position + rotation * FINGER_VECTOR); + // temporary for toy ball - store first finger tip velocity + glm::vec3 oldTipPosition = palm->getTipPosition(); + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f); + palm->setTipPosition(newTipPosition); + // three fingers indicates to the skeleton that we have enough data to determine direction palm->getFingers().clear(); palm->getFingers().push_back(finger); diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index d525bbd7df..12af614de3 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -59,9 +59,11 @@ void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) } PalmData::PalmData(HandData* owningHandData) : +_rawRotation(0, 0, 0, 1), _rawPosition(0, 0, 0), _rawNormal(0, 1, 0), -_velocity(0, 0, 0), +_rawVelocity(0, 0, 0), +_rotationalVelocity(0, 0, 0), _controllerButtons(0), _isActive(false), _leapID(LEAPID_INVALID), diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index fb5cbff763..2677ffdba8 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -94,6 +94,7 @@ public: void setLeapID(int id) { _leapID = id; } void setRawTipPosition(const glm::vec3& pos) { _tipRawPosition = pos; } void setRawRootPosition(const glm::vec3& pos) { _rootRawPosition = pos; } + void setTrailLength(unsigned int length); void updateTrail(); @@ -122,6 +123,7 @@ public: PalmData(HandData* owningHandData); glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); } glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); } + const glm::vec3& getRawPosition() const { return _rawPosition; } const glm::vec3& getRawNormal() const { return _rawNormal; } bool isActive() const { return _isActive; } @@ -136,13 +138,19 @@ public: void setLeapID(int id) { _leapID = id; } void setSixenseID(int id) { _sixenseID = id; } + void setRawRotation(const glm::quat rawRotation) { _rawRotation = rawRotation; }; + const glm::quat getRawRotation() const { return _rawRotation; } void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; } - void setVelocity(const glm::vec3& velocity) { _velocity = velocity; } - const glm::vec3& getVelocity() const { return _velocity; } - + void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } + const glm::vec3& getRawVelocity() const { return _rawVelocity; } void addToPosition(const glm::vec3& delta); - + + void setTipPosition(const glm::vec3& position) { _tipPosition = position; } + const glm::vec3 getTipPosition() const { return _tipPosition; } + const glm::vec3& getTipVelocity() const { return _tipVelocity; } + void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; } + void incrementFramesWithoutData() { _numFramesWithoutData++; } void resetFramesWithoutData() { _numFramesWithoutData = 0; } int getFramesWithoutData() const { return _numFramesWithoutData; } @@ -162,9 +170,15 @@ public: private: std::vector _fingers; + glm::quat _rawRotation; glm::vec3 _rawPosition; glm::vec3 _rawNormal; - glm::vec3 _velocity; + glm::vec3 _rawVelocity; + glm::vec3 _rotationalVelocity; + glm::quat _lastRotation; + + glm::vec3 _tipPosition; + glm::vec3 _tipVelocity; int _controllerButtons; float _trigger; float _joystickX, _joystickY;