mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 03:17:08 +02:00
Merge pull request #1539 from AndrewMeadows/master
first pass particle-hand-paddle collisions
This commit is contained in:
commit
b11f9e5460
16 changed files with 226 additions and 77 deletions
|
@ -355,6 +355,55 @@ bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float pene
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) {
|
||||||
|
// TODO: provide an early exit using bounding sphere of entire avatar
|
||||||
|
|
||||||
|
const HandData* handData = getHandData();
|
||||||
|
if (handData) {
|
||||||
|
int jointIndices[2] = { _skeletonModel.getLeftHandJointIndex(), _skeletonModel.getRightHandJointIndex() };
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
const PalmData* palm = handData->getPalm(i);
|
||||||
|
if (palm) {
|
||||||
|
// create a disk collision proxy where the hand is
|
||||||
|
glm::vec3 fingerAxis(0.f);
|
||||||
|
for (size_t f = 0; f < palm->getNumFingers(); ++f) {
|
||||||
|
const FingerData& finger = (palm->getFingers())[f];
|
||||||
|
if (finger.isActive()) {
|
||||||
|
// compute finger axis
|
||||||
|
glm::vec3 fingerTip = finger.getTipPosition();
|
||||||
|
glm::vec3 fingerRoot = finger.getRootPosition();
|
||||||
|
fingerAxis = glm::normalize(fingerTip - fingerRoot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glm::vec3 handPosition;
|
||||||
|
if (i == 0) {
|
||||||
|
_skeletonModel.getLeftHandPosition(handPosition);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_skeletonModel.getRightHandPosition(handPosition);
|
||||||
|
}
|
||||||
|
glm::vec3 diskCenter = handPosition + HAND_PADDLE_OFFSET * fingerAxis;
|
||||||
|
glm::vec3 diskNormal = palm->getNormal();
|
||||||
|
|
||||||
|
// collide against the disk
|
||||||
|
if (findSphereDiskPenetration(sphereCenter, sphereRadius,
|
||||||
|
diskCenter, HAND_PADDLE_RADIUS, diskNormal, collision._penetration)) {
|
||||||
|
collision._addedVelocity = palm->getVelocity();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) {
|
||||||
|
collision._penetration /= (float)(TREE_SCALE);
|
||||||
|
collision._addedVelocity = getVelocity();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int Avatar::parseData(unsigned char* sourceBuffer, int numBytes) {
|
int Avatar::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
// change in position implies movement
|
// change in position implies movement
|
||||||
glm::vec3 oldPosition = _position;
|
glm::vec3 oldPosition = _position;
|
||||||
|
|
|
@ -167,6 +167,13 @@ public:
|
||||||
bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||||
glm::vec3& penetration, int skeletonSkipIndex = -1) const;
|
glm::vec3& penetration, int skeletonSkipIndex = -1) const;
|
||||||
|
|
||||||
|
/// Checks for collision between the a sphere and the avatar.
|
||||||
|
/// \param collisionCenter the center of the penetration test sphere
|
||||||
|
/// \param collisionRadius the radius of the penetration test sphere
|
||||||
|
/// \param collision[out] the details of the collision point
|
||||||
|
/// \return whether or not the sphere collided
|
||||||
|
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
|
||||||
|
|
||||||
virtual int parseData(unsigned char* sourceBuffer, int numBytes);
|
virtual int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||||
|
|
||||||
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||||
|
|
|
@ -616,23 +616,37 @@ void Hand::renderLeapHands(bool isMine) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the palms
|
// Draw the hand paddles
|
||||||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
int MAX_NUM_PADDLES = 2; // one for left and one for right
|
||||||
PalmData& palm = getPalms()[i];
|
glColor4f(handColor.r, handColor.g, handColor.b, 0.3f);
|
||||||
if (palm.isActive()) {
|
for (int i = 0; i < MAX_NUM_PADDLES; i++) {
|
||||||
const float palmThickness = 0.02f;
|
const PalmData* palm = getPalm(i);
|
||||||
if (palm.getIsCollidingWithPalm()) {
|
if (palm) {
|
||||||
glColor4f(1, 0, 0, 0.50);
|
// compute finger axis
|
||||||
} else {
|
glm::vec3 fingerAxis(0.f);
|
||||||
glColor4f(handColor.r, handColor.g, handColor.b, 0.25);
|
for (size_t f = 0; f < palm->getNumFingers(); ++f) {
|
||||||
|
const FingerData& finger = (palm->getFingers())[f];
|
||||||
|
if (finger.isActive()) {
|
||||||
|
glm::vec3 fingerTip = finger.getTipPosition();
|
||||||
|
glm::vec3 fingerRoot = finger.getRootPosition();
|
||||||
|
fingerAxis = glm::normalize(fingerTip - fingerRoot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
glm::vec3 tip = palm.getPosition();
|
// compute paddle position
|
||||||
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
|
glm::vec3 handPosition;
|
||||||
const float radiusA = 0.05f;
|
if (i == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
|
||||||
const float radiusB = 0.03f;
|
_owningAvatar->getSkeletonModel().getLeftHandPosition(handPosition);
|
||||||
Avatar::renderJointConnectingCone(root, tip, radiusA, radiusB);
|
} else if (i == SIXENSE_CONTROLLER_ID_RIGHT_HAND) {
|
||||||
|
_owningAvatar->getSkeletonModel().getRightHandPosition(handPosition);
|
||||||
|
}
|
||||||
|
glm::vec3 tip = handPosition + HAND_PADDLE_OFFSET * fingerAxis;
|
||||||
|
glm::vec3 root = tip + palm->getNormal() * HAND_PADDLE_THICKNESS;
|
||||||
|
// render a very shallow cone as the paddle
|
||||||
|
Avatar::renderJointConnectingCone(root, tip, HAND_PADDLE_RADIUS, 0.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
class Avatar;
|
class Avatar;
|
||||||
class ProgramObject;
|
class ProgramObject;
|
||||||
|
|
||||||
|
const float HAND_PADDLE_OFFSET = 0.1f;
|
||||||
|
const float HAND_PADDLE_THICKNESS = 0.05f;
|
||||||
|
const float HAND_PADDLE_RADIUS = 0.15f;
|
||||||
|
|
||||||
class Hand : public HandData {
|
class Hand : public HandData {
|
||||||
public:
|
public:
|
||||||
Hand(Avatar* owningAvatar);
|
Hand(Avatar* owningAvatar);
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
|
#include <HandData.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#ifndef __interface__SkeletonModel__
|
#ifndef __interface__SkeletonModel__
|
||||||
#define __interface__SkeletonModel__
|
#define __interface__SkeletonModel__
|
||||||
|
|
||||||
#include <HandData.h>
|
|
||||||
|
|
||||||
#include "renderer/Model.h"
|
#include "renderer/Model.h"
|
||||||
|
|
||||||
|
|
|
@ -488,6 +488,22 @@ bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePos
|
||||||
return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
|
return getJointPosition(geometry.leftEyeJointIndex, firstEyePosition) &&
|
||||||
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
|
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Model::getLeftHandPosition(glm::vec3& position) const {
|
||||||
|
return getJointPosition(getLeftHandJointIndex(), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Model::getLeftHandRotation(glm::quat& rotation) const {
|
||||||
|
return getJointRotation(getLeftHandJointIndex(), rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Model::getRightHandPosition(glm::vec3& position) const {
|
||||||
|
return getJointPosition(getRightHandJointIndex(), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Model::getRightHandRotation(glm::quat& rotation) const {
|
||||||
|
return getJointRotation(getRightHandJointIndex(), rotation);
|
||||||
|
}
|
||||||
|
|
||||||
bool Model::setLeftHandPosition(const glm::vec3& position) {
|
bool Model::setLeftHandPosition(const glm::vec3& position) {
|
||||||
return setJointPosition(getLeftHandJointIndex(), position);
|
return setJointPosition(getLeftHandJointIndex(), position);
|
||||||
|
|
|
@ -82,6 +82,22 @@ public:
|
||||||
/// \return whether or not both eye meshes were found
|
/// \return whether or not both eye meshes were found
|
||||||
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
||||||
|
|
||||||
|
/// Retrieve the position of the left hand
|
||||||
|
/// \return true whether or not the position was found
|
||||||
|
bool getLeftHandPosition(glm::vec3& position) const;
|
||||||
|
|
||||||
|
/// Retrieve the rotation of the left hand
|
||||||
|
/// \return true whether or not the rotation was found
|
||||||
|
bool getLeftHandRotation(glm::quat& rotation) const;
|
||||||
|
|
||||||
|
/// Retrieve the position of the right hand
|
||||||
|
/// \return true whether or not the position was found
|
||||||
|
bool getRightHandPosition(glm::vec3& position) const;
|
||||||
|
|
||||||
|
/// Retrieve the rotation of the right hand
|
||||||
|
/// \return true whether or not the rotation was found
|
||||||
|
bool getRightHandRotation(glm::quat& rotation) const;
|
||||||
|
|
||||||
/// Sets the position of the left hand using inverse kinematics.
|
/// Sets the position of the left hand using inverse kinematics.
|
||||||
/// \return whether or not the left hand joint was found
|
/// \return whether or not the left hand joint was found
|
||||||
bool setLeftHandPosition(const glm::vec3& position);
|
bool setLeftHandPosition(const glm::vec3& position);
|
||||||
|
|
|
@ -20,9 +20,10 @@
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
#include <QtCore/QVariantMap>
|
#include <QtCore/QVariantMap>
|
||||||
|
|
||||||
|
#include <CollisionInfo.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
#include <NodeData.h>
|
#include <NodeData.h>
|
||||||
|
|
||||||
#include "HeadData.h"
|
#include "HeadData.h"
|
||||||
#include "HandData.h"
|
#include "HandData.h"
|
||||||
|
|
||||||
|
@ -118,6 +119,10 @@ public:
|
||||||
/// \return whether or not the sphere penetrated
|
/// \return whether or not the sphere penetrated
|
||||||
virtual bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
virtual bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
|
||||||
glm::vec3& penetration, int skeletonSkipIndex = -1) const { return false; }
|
glm::vec3& penetration, int skeletonSkipIndex = -1) const { return false; }
|
||||||
|
|
||||||
|
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUuid _uuid;
|
QUuid _uuid;
|
||||||
|
|
|
@ -38,8 +38,17 @@ PalmData& HandData::addNewPalm() {
|
||||||
return _palms.back();
|
return _palms.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
|
const PalmData* HandData::getPalm(int sixSenseID) const {
|
||||||
const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1;
|
// the palms are not necessarily added in left-right order,
|
||||||
|
// so we have to search for the right SixSenseID
|
||||||
|
for (int i = 0; i < _palms.size(); i++) {
|
||||||
|
const PalmData* palm = &(_palms[i]);
|
||||||
|
if (palm->getSixenseID() == sixSenseID) {
|
||||||
|
return palm->isActive() ? palm : NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const {
|
void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const {
|
||||||
leftPalmIndex = -1;
|
leftPalmIndex = -1;
|
||||||
|
|
|
@ -35,6 +35,9 @@ const int BUTTON_FWD = 128;
|
||||||
|
|
||||||
const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters
|
const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters
|
||||||
|
|
||||||
|
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
|
||||||
|
const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1;
|
||||||
|
|
||||||
class HandData {
|
class HandData {
|
||||||
public:
|
public:
|
||||||
HandData(AvatarData* owningAvatar);
|
HandData(AvatarData* owningAvatar);
|
||||||
|
@ -55,6 +58,7 @@ public:
|
||||||
|
|
||||||
std::vector<PalmData>& getPalms() { return _palms; }
|
std::vector<PalmData>& getPalms() { return _palms; }
|
||||||
const std::vector<PalmData>& getPalms() const { return _palms; }
|
const std::vector<PalmData>& getPalms() const { return _palms; }
|
||||||
|
const PalmData* getPalm(int sixSenseID) const;
|
||||||
size_t getNumPalms() const { return _palms.size(); }
|
size_t getNumPalms() const { return _palms.size(); }
|
||||||
PalmData& addNewPalm();
|
PalmData& addNewPalm();
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <AbstractAudioInterface.h>
|
#include <AbstractAudioInterface.h>
|
||||||
#include <VoxelTree.h>
|
#include <VoxelTree.h>
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
|
#include <CollisionInfo.h>
|
||||||
#include <HeadData.h>
|
#include <HeadData.h>
|
||||||
#include <HandData.h>
|
#include <HandData.h>
|
||||||
|
|
||||||
|
@ -136,15 +137,14 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
|
|
||||||
// particles that are in hand, don't collide with other avatar parts
|
// particles that are in hand, don't collide with avatars
|
||||||
if (particle->getInHand()) {
|
if (particle->getInHand()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("updateCollisionWithAvatars()...\n");
|
|
||||||
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
|
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * (float)(TREE_SCALE);
|
float radius = particle->getRadius() * (float)(TREE_SCALE);
|
||||||
const float ELASTICITY = 0.4f;
|
const float ELASTICITY = 0.95f;
|
||||||
const float DAMPING = 0.0f;
|
const float DAMPING = 0.0f;
|
||||||
const float COLLISION_FREQUENCY = 0.5f;
|
const float COLLISION_FREQUENCY = 0.5f;
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
|
@ -153,77 +153,40 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
// first check the selfAvatar if set...
|
// first check the selfAvatar if set...
|
||||||
if (_selfAvatar) {
|
if (_selfAvatar) {
|
||||||
AvatarData* avatar = (AvatarData*)_selfAvatar;
|
AvatarData* avatar = (AvatarData*)_selfAvatar;
|
||||||
//printf("updateCollisionWithAvatars()..._selfAvatar=%p\n", avatar);
|
CollisionInfo collision;
|
||||||
|
if (avatar->findSphereCollision(center, radius, collision)) {
|
||||||
// check hands...
|
if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) {
|
||||||
const HandData* handData = avatar->getHandData();
|
// only collide when particle and collision point are moving toward each other
|
||||||
|
collision._penetration /= (float)(TREE_SCALE);
|
||||||
// TODO: combine hand and collision check into one. Note: would need to supply
|
collision._addedVelocity /= (float)(TREE_SCALE);
|
||||||
// CollisionInfo class rather than just vec3 (penetration) so we can get back
|
updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY);
|
||||||
// added velocity.
|
applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity);
|
||||||
|
|
||||||
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
|
||||||
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
|
|
||||||
// apply a hard collision when ball collides with hand
|
|
||||||
penetration /= (float)(TREE_SCALE);
|
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
|
||||||
|
|
||||||
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
|
||||||
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
|
||||||
if (collidingPalm) {
|
|
||||||
glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)(TREE_SCALE);
|
|
||||||
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
|
||||||
addedVelocity = palmVelocity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
|
||||||
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
|
||||||
// apply hard collision when particle collides with avatar
|
|
||||||
penetration /= (float)(TREE_SCALE);
|
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
|
||||||
glm::vec3 addedVelocity = avatar->getVelocity();
|
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop through all the other avatars for potential interactions...
|
// loop through all the other avatars for potential interactions...
|
||||||
|
|
||||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||||
//qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n";
|
//qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n";
|
||||||
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
|
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
|
||||||
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
|
|
||||||
AvatarData* avatar = static_cast<AvatarData*>(node->getLinkedData());
|
AvatarData* avatar = static_cast<AvatarData*>(node->getLinkedData());
|
||||||
//printf("updateCollisionWithAvatars()...avatar=%p\n", avatar);
|
|
||||||
|
CollisionInfo collision;
|
||||||
// check hands...
|
if (avatar->findSphereCollision(center, radius, collision)) {
|
||||||
const HandData* handData = avatar->getHandData();
|
if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) {
|
||||||
|
// only collide when particle and collision point are moving toward each other
|
||||||
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
collision._penetration /= (float)(TREE_SCALE);
|
||||||
// apply a hard collision when ball collides with hand
|
collision._addedVelocity /= (float)(TREE_SCALE);
|
||||||
penetration /= (float)(TREE_SCALE);
|
updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity);
|
||||||
|
|
||||||
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
|
||||||
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
|
||||||
if (collidingPalm) {
|
|
||||||
glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)(TREE_SCALE);
|
|
||||||
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
|
||||||
addedVelocity = palmVelocity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
|
||||||
|
|
||||||
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
|
||||||
penetration /= (float)(TREE_SCALE);
|
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
|
||||||
glm::vec3 addedVelocity = avatar->getVelocity();
|
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: convert applyHardCollision() to take a CollisionInfo& instead of penetration + addedVelocity
|
||||||
void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::vec3& penetration,
|
void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::vec3& penetration,
|
||||||
float elasticity, float damping, const glm::vec3& addedVelocity) {
|
float elasticity, float damping, const glm::vec3& addedVelocity) {
|
||||||
//
|
//
|
||||||
|
|
|
@ -61,4 +61,4 @@ private:
|
||||||
AvatarData* _selfAvatar;
|
AvatarData* _selfAvatar;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__ParticleCollisionSystem__) */
|
#endif /* defined(__hifi__ParticleCollisionSystem__) */
|
||||||
|
|
26
libraries/shared/src/CollisionInfo.h
Normal file
26
libraries/shared/src/CollisionInfo.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// CollisionInfo.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Andrew Meadows on 2014.01.13
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__CollisionInfo__
|
||||||
|
#define __hifi__CollisionInfo__
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
class CollisionInfo {
|
||||||
|
public:
|
||||||
|
CollisionInfo() : _penetration(0.f), _addedVelocity(0.f) { }
|
||||||
|
~CollisionInfo() {}
|
||||||
|
|
||||||
|
//glm::vec3 _point;
|
||||||
|
//glm::vec3 _normal;
|
||||||
|
glm::vec3 _penetration;
|
||||||
|
glm::vec3 _addedVelocity;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__CollisionInfo__) */
|
|
@ -114,6 +114,30 @@ bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadiu
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius,
|
||||||
|
const glm::vec3& diskCenter, float diskRadius, const glm::vec3& diskNormal,
|
||||||
|
glm::vec3& penetration) {
|
||||||
|
glm::vec3 localCenter = sphereCenter - diskCenter;
|
||||||
|
float verticalDistance = glm::dot(localCenter, diskNormal);
|
||||||
|
|
||||||
|
|
||||||
|
if (abs(verticalDistance) < sphereRadius) {
|
||||||
|
// sphere hit the plane, but does it hit the disk?
|
||||||
|
// Note: this algorithm ignores edge hits.
|
||||||
|
glm::vec3 verticalOffset = verticalDistance * diskNormal;
|
||||||
|
if (glm::length(localCenter - verticalOffset) < diskRadius) {
|
||||||
|
// yes, hit the disk
|
||||||
|
penetration = (sphereRadius - abs(verticalDistance)) * diskNormal;
|
||||||
|
if (verticalDistance < 0.f) {
|
||||||
|
// hit the backside of the disk, so negate penetration vector
|
||||||
|
penetration *= -1.f;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius,
|
bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius,
|
||||||
const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration) {
|
const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration) {
|
||||||
if (findSphereCapsulePenetration(sphereCenter, sphereRadius,
|
if (findSphereCapsulePenetration(sphereCenter, sphereRadius,
|
||||||
|
|
|
@ -47,6 +47,17 @@ bool findSphereCapsuleConePenetration(const glm::vec3& sphereCenter, float spher
|
||||||
bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadius,
|
bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadius,
|
||||||
const glm::vec4& plane, glm::vec3& penetration);
|
const glm::vec4& plane, glm::vec3& penetration);
|
||||||
|
|
||||||
|
/// Computes the penetration between a sphere and a disk.
|
||||||
|
/// \param sphereCenter center of sphere
|
||||||
|
/// \param sphereRadius radius of sphere
|
||||||
|
/// \param diskCenter center of disk
|
||||||
|
/// \param diskRadius radius of disk
|
||||||
|
/// \param diskNormal normal of disk plan
|
||||||
|
/// \return true if sphere touches disk (does not handle collisions with disk edge)
|
||||||
|
bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius,
|
||||||
|
const glm::vec3& diskCenter, float diskRadius, const glm::vec3& diskNormal,
|
||||||
|
glm::vec3& penetration);
|
||||||
|
|
||||||
bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius,
|
bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius,
|
||||||
const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration);
|
const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue