Browse Source

Improve forceps pinching mechanism

master
C. J. Howard 7 years ago
parent
commit
d7b404720c
4 changed files with 138 additions and 17 deletions
  1. +2
    -2
      src/game/ant.cpp
  2. +1
    -1
      src/game/ant.hpp
  3. +128
    -14
      src/game/tool.cpp
  4. +7
    -0
      src/game/tool.hpp

+ 2
- 2
src/game/ant.cpp View File

@ -55,10 +55,10 @@ void Ant::animate()
animationTime = fwrap(animationTime + 2.0f, colony->getTripodGaitAnimation()->getEndTime()); animationTime = fwrap(animationTime + 2.0f, colony->getTripodGaitAnimation()->getEndTime());
} }
void Ant::suspend(const Vector3& suspensionPoint)
void Ant::suspend(const Vector3& suspensionPoint, const Quaternion& suspensionRotation)
{ {
transform.translation = suspensionPoint; transform.translation = suspensionPoint;
transform.rotation = getRotation();
transform.rotation = suspensionRotation;
modelInstance.setTransform(transform); modelInstance.setTransform(transform);
} }

+ 1
- 1
src/game/ant.hpp View File

@ -70,7 +70,7 @@ public:
void animate(); void animate();
void suspend(const Vector3& suspensionPoint);
void suspend(const Vector3& suspensionPoint, const Quaternion& suspensionRotation);
void move(const Vector3& velocity); void move(const Vector3& velocity);

+ 128
- 14
src/game/tool.cpp View File

@ -30,10 +30,18 @@ Forceps::Forceps(const Model* model)
std::cerr << "Forceps release animation not found" << std::endl; std::cerr << "Forceps release animation not found" << std::endl;
} }
hoverDistance = 1.0f;
// Setup timing
float descentDuration = 0.125f;
float ascentDuration = 0.125f;
float descentFrameCount = descentDuration / (1.0f / 60.0f);
animationTimeStep = pinchAnimation->getEndTime() / descentFrameCount;
// Allocate tweener and and setup tweens // Allocate tweener and and setup tweens
tweener = new Tweener(); tweener = new Tweener();
descentTween = new Tween<float>(EaseFunction::OUT_CUBIC, 0.0f, 0.0667f, 1.0f, -1.0f);
ascentTween = new Tween<float>(EaseFunction::IN_CUBIC, 0.0f, 0.0667f, 0.0f, 1.0f);
descentTween = new Tween<float>(EaseFunction::OUT_CUBIC, 0.0f, descentDuration, hoverDistance, -hoverDistance);
ascentTween = new Tween<float>(EaseFunction::IN_CUBIC, 0.0f, ascentDuration, 0.0f, hoverDistance);
descentTween->setEndCallback(std::bind(&TweenBase::start, ascentTween)); descentTween->setEndCallback(std::bind(&TweenBase::start, ascentTween));
tweener->addTween(descentTween); tweener->addTween(descentTween);
tweener->addTween(ascentTween); tweener->addTween(ascentTween);
@ -62,7 +70,7 @@ void Forceps::update(float dt)
tweener->update(dt); tweener->update(dt);
// Determine distance from pick point // Determine distance from pick point
float forcepsDistance = descentTween->getStartValue();
float forcepsDistance = hoverDistance;
if (!ascentTween->isStopped()) if (!ascentTween->isStopped())
{ {
forcepsDistance = ascentTween->getTweenValue(); forcepsDistance = ascentTween->getTweenValue();
@ -71,9 +79,10 @@ void Forceps::update(float dt)
{ {
forcepsDistance = descentTween->getTweenValue(); forcepsDistance = descentTween->getTweenValue();
} }
Quaternion rotation = glm::angleAxis(cameraController->getAzimuth(), Vector3(0, 1, 0)) *
glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
Quaternion alignment = glm::angleAxis(cameraController->getAzimuth(), Vector3(0, 1, 0));
Quaternion tilt = glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
Quaternion rotation = glm::normalize(alignment * tilt);
Vector3 translation = pick + rotation * Vector3(0, forcepsDistance, 0); Vector3 translation = pick + rotation * Vector3(0, forcepsDistance, 0);
// Set tool position // Set tool position
@ -99,10 +108,53 @@ void Forceps::update(float dt)
} }
else if (state == Forceps::State::PINCHED) else if (state == Forceps::State::PINCHED)
{ {
if (!ascentTween->isStopped())
{
// Calculate interpolation factor
float interpolationFactor = (ascentTween->getTweenValue() - ascentTween->getStartValue()) / ascentTween->getDeltaValue();
// Form tilt quaternion
//Quaternion tilt = glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
tilt = glm::angleAxis(glm::radians(15.0f), Vector3(0, 0, -1));
// Project camera forward onto XZ plane
Vector3 cameraForwardXZ = cameraController->getCamera()->getForward();
cameraForwardXZ.y = 0.0f;
cameraForwardXZ = glm::normalize(cameraForwardXZ);
// Form alignment quaternion
//Quaternion alignment = glm::rotation(Vector3(0, 0, -1), cameraForwardXZ);
alignment = glm::angleAxis(cameraController->getAzimuth(), Vector3(0, 1, 0));
// Calculate target rotation at the top of the ascentTween
rotationTop = glm::normalize(alignment * tilt);
// Interpolate between bottom and top rotations
Quaternion interpolatedRotation = glm::normalize(glm::slerp(rotationBottom, rotationTop, interpolationFactor));
// Set target translation at the top of the ascent
translationTop = pick + rotationTop * Vector3(0, hoverDistance, 0);
// Interpolate between bottom and top translations
Vector3 interpolatedTranslation = glm::lerp(translationBottom, translationTop, interpolationFactor);
// Update model instance transform
modelInstance.setTranslation(interpolatedTranslation);
modelInstance.setRotation(interpolatedRotation);
}
if (suspendedAnt != nullptr) if (suspendedAnt != nullptr)
{ {
// Project forceps forward vector onto XZ plane
Vector3 forward = glm::normalize(modelInstance.getRotation() * Vector3(0, 0, -1));
forward.y = 0.0f;
forward = glm::normalize(forward);
// Calculate suspension quaternion
Quaternion suspensionRotation = glm::normalize(glm::rotation(Vector3(0, 0, -1), ((flipRotation) ? -forward : forward)));
// Suspend ant // Suspend ant
suspendedAnt->suspend(modelInstance.getTranslation());
suspendedAnt->suspend(modelInstance.getTranslation(), suspensionRotation);
} }
} }
else if (state == Forceps::State::PINCHING) else if (state == Forceps::State::PINCHING)
@ -111,8 +163,47 @@ void Forceps::update(float dt)
pinchAnimation->animate(pose, animationTime); pinchAnimation->animate(pose, animationTime);
pose->concatenate(); pose->concatenate();
// Rotate to align forceps with ant
if (targetedAnt != nullptr)
{
// Calculate interpolation factor
float interpolationFactor = (descentTween->getTweenValue() - descentTween->getStartValue()) / descentTween->getDeltaValue();
// Set target translation at the bottom of the descent
translationBottom = targetedAnt->getPosition();
// Interpolate between top and bottom translations
Vector3 interpolatedTranslation = glm::lerp(translationTop, translationBottom, interpolationFactor);
// Project camera forward onto XZ plane
Vector3 cameraForwardXZ = cameraController->getCamera()->getForward();
cameraForwardXZ.y = 0.0f;
cameraForwardXZ = glm::normalize(cameraForwardXZ);
// Form tilt quaternion
tilt = glm::angleAxis(glm::radians(15.0f), -cameraForwardXZ);
// Project ant forward onto XZ plane
Vector3 antForwardXZ = targetedAnt->getForward();
antForwardXZ.y = 0.0f;
antForwardXZ = glm::normalize(antForwardXZ);
// Form alignment quaternion
alignment = glm::rotation(Vector3(0, 0, -1), (flipRotation) ? antForwardXZ : -antForwardXZ);
// Calculate target rotation at the bottom of the descent
rotationBottom = glm::normalize(tilt * alignment);
// Interpolate between top and bottom rotations
Quaternion interpolatedRotation = glm::normalize(glm::slerp(rotationTop, rotationBottom, interpolationFactor));
// Update model instance transform
modelInstance.setTranslation(interpolatedTranslation);
modelInstance.setRotation(interpolatedRotation);
}
// If pinch animation is finished // If pinch animation is finished
if (animationTime >= pinchAnimation->getEndTime())
if (animationTime >= pinchAnimation->getEndTime() && descentTween->isStopped())
{ {
// If an ant was targeted // If an ant was targeted
if (targetedAnt != nullptr) if (targetedAnt != nullptr)
@ -120,7 +211,7 @@ void Forceps::update(float dt)
// Suspend targeted ant // Suspend targeted ant
suspendedAnt = targetedAnt; suspendedAnt = targetedAnt;
suspendedAnt->setState(Ant::State::SUSPENDED); suspendedAnt->setState(Ant::State::SUSPENDED);
suspendedAnt->suspend(modelInstance.getTranslation());
//suspendedAnt->suspend(modelInstance.getTranslation());
targetedAnt = nullptr; targetedAnt = nullptr;
} }
@ -130,8 +221,7 @@ void Forceps::update(float dt)
} }
// Increment animation time // Increment animation time
//animationTime += dt;
animationTime += 2.5f;
animationTime += animationTimeStep;
} }
void Forceps::setColony(Colony* colony) void Forceps::setColony(Colony* colony)
@ -178,10 +268,33 @@ void Forceps::pinch()
targetedAnt = ant; targetedAnt = ant;
} }
} }
if (targetedAnt != nullptr)
{
// Start descent tweener
descentTween->start();
// Save translation & rotation
translationTop = modelInstance.getTranslation();
rotationTop = modelInstance.getRotation();
// Project ant forward onto XZ plane
Vector3 antForwardXZ = targetedAnt->getForward();
antForwardXZ.y = 0.0f;
antForwardXZ = glm::normalize(antForwardXZ);
// Project camera forward onto XZ plane
Vector3 cameraForwardXZ = cameraController->getCamera()->getForward();
cameraForwardXZ.y = 0.0f;
cameraForwardXZ = glm::normalize(cameraForwardXZ);
// Find angle between ant and camera on XZ plane
float angle = std::acos(glm::dot(cameraForwardXZ, antForwardXZ));
// Determine direction to rotate
flipRotation = (angle > glm::radians(90.0f));
}
} }
// Start descent tweener
descentTween->start();
} }
void Forceps::release() void Forceps::release()
@ -189,6 +302,7 @@ void Forceps::release()
// Change state to releasing // Change state to releasing
state = Forceps::State::RELEASING; state = Forceps::State::RELEASING;
animationTime = 0.0f; animationTime = 0.0f;
targetedAnt = nullptr;
if (suspendedAnt != nullptr) if (suspendedAnt != nullptr)
{ {

+ 7
- 0
src/game/tool.hpp View File

@ -124,9 +124,16 @@ private:
const Animation* pinchAnimation; const Animation* pinchAnimation;
const Animation* releaseAnimation; const Animation* releaseAnimation;
float animationTime; float animationTime;
float animationTimeStep;
float hoverDistance;
Tweener* tweener; Tweener* tweener;
Tween<float>* descentTween; Tween<float>* descentTween;
Tween<float>* ascentTween; Tween<float>* ascentTween;
Vector3 translationBottom;
Vector3 translationTop;
Quaternion rotationTop;
Quaternion rotationBottom;
bool flipRotation;
Colony* colony; Colony* colony;
Ant* targetedAnt; Ant* targetedAnt;
Ant* suspendedAnt; Ant* suspendedAnt;

Loading…
Cancel
Save