mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:44:01 +02:00
Added drum sounds and voxel collision detection
This commit is contained in:
parent
a84e97c54a
commit
8fdd78dc26
8 changed files with 154 additions and 86 deletions
|
@ -289,7 +289,7 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o
|
|||
// add output (@speakers) data just written to the scope
|
||||
_scope->addSamples(1, outputLeft, BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
_scope->addSamples(2, outputRight, BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||
|
||||
|
||||
gettimeofday(&_lastCallbackTime, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -1567,6 +1567,38 @@ void VoxelSystem::falseColorizeInView() {
|
|||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
||||
class NodeAndPoint {
|
||||
public:
|
||||
VoxelNode* node;
|
||||
glm::vec3 point;
|
||||
};
|
||||
|
||||
// Find the smallest colored voxel enclosing a point (if there is one)
|
||||
bool VoxelSystem::getVoxelEnclosingOperation(VoxelNode* node, void* extraData) {
|
||||
NodeAndPoint* nodeAndPoint = (NodeAndPoint*) extraData;
|
||||
AABox voxelBox = node->getAABox();
|
||||
if (voxelBox.contains(nodeAndPoint->point)) {
|
||||
if (node->isColored() && node->isLeaf()) {
|
||||
// we've reached a solid leaf containing the point, return the node.
|
||||
nodeAndPoint->node = node;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// The point is not inside this voxel, so stop recursing.
|
||||
return false;
|
||||
}
|
||||
return true; // keep looking
|
||||
}
|
||||
|
||||
VoxelNode* VoxelSystem::getVoxelEnclosing(const glm::vec3& point) {
|
||||
NodeAndPoint nodeAndPoint;
|
||||
nodeAndPoint.point = point;
|
||||
nodeAndPoint.node = NULL;
|
||||
_tree->recurseTreeWithOperation(getVoxelEnclosingOperation, (void*) &nodeAndPoint);
|
||||
return nodeAndPoint.node;
|
||||
}
|
||||
|
||||
|
||||
// helper classes and args for falseColorizeBySource
|
||||
class groupColor {
|
||||
public:
|
||||
|
|
|
@ -121,6 +121,8 @@ public:
|
|||
virtual void domainChanged(QString domain);
|
||||
|
||||
bool treeIsBusy() const { return _treeIsBusy; }
|
||||
|
||||
VoxelNode* getVoxelEnclosing(const glm::vec3& point);
|
||||
|
||||
signals:
|
||||
void importSize(float x, float y, float z);
|
||||
|
@ -200,6 +202,7 @@ private:
|
|||
static bool hideAllSubTreeOperation(VoxelNode* node, void* extraData);
|
||||
static bool showAllSubTreeOperation(VoxelNode* node, void* extraData);
|
||||
static bool showAllLocalVoxelsOperation(VoxelNode* node, void* extraData);
|
||||
static bool getVoxelEnclosingOperation(VoxelNode* node, void* extraData);
|
||||
|
||||
int updateNodeInArrays(VoxelNode* node, bool reuseIndex, bool forceDraw);
|
||||
int forceRemoveNodeFromArrays(VoxelNode* node);
|
||||
|
|
|
@ -24,7 +24,10 @@ Hand::Hand(Avatar* owningAvatar) :
|
|||
_raveGloveInitialized(false),
|
||||
_owningAvatar(owningAvatar),
|
||||
_renderAlpha(1.0),
|
||||
_ballColor(0.0, 0.0, 0.4)
|
||||
_ballColor(0.0, 0.0, 0.4),
|
||||
_collisionCenter(0,0,0),
|
||||
_collisionAge(0),
|
||||
_collisionDuration(0)
|
||||
{
|
||||
// initialize all finger particle emitters with an invalid id as default
|
||||
for (int f = 0; f< NUM_FINGERS; f ++ ) {
|
||||
|
@ -51,6 +54,10 @@ void Hand::reset() {
|
|||
|
||||
void Hand::simulate(float deltaTime, bool isMine) {
|
||||
|
||||
if (_collisionAge > 0.f) {
|
||||
_collisionAge += deltaTime;
|
||||
}
|
||||
|
||||
calculateGeometry();
|
||||
|
||||
if (_isRaveGloveActive) {
|
||||
|
@ -67,8 +74,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
for (size_t i = 0; i < getNumPalms(); ++i) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
glm::vec3 palmPosition = palm.getPosition();
|
||||
FingerData& finger = palm.getFingers()[0];
|
||||
FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger
|
||||
glm::vec3 fingerTipPosition = finger.getTipPosition();
|
||||
if (palm.getControllerButtons() & BUTTON_1) {
|
||||
if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
|
||||
|
@ -88,55 +94,43 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
}
|
||||
}
|
||||
// Check if the finger is intersecting with a voxel in the client voxel tree
|
||||
VoxelNode* fingerNode = Application::getInstance()->getVoxels()->getVoxelAt(fingerTipPosition.x / TREE_SCALE,
|
||||
fingerTipPosition.y / TREE_SCALE,
|
||||
fingerTipPosition.z / TREE_SCALE,
|
||||
FINGERTIP_VOXEL_SIZE / TREE_SCALE);
|
||||
VoxelNode* fingerNode = Application::getInstance()->getVoxels()->getVoxelEnclosing(glm::vec3(fingerTipPosition / (float)TREE_SCALE));
|
||||
if (fingerNode) {
|
||||
finger.setIsTouchingVoxel(true);
|
||||
glm::vec3 corner = fingerNode->getCorner();
|
||||
glm::vec3 storedCorner = finger.getFingerVoxelPosition();
|
||||
printf("corner: %.3f, %.3f, %.3f ", corner.x, corner.y, corner.z);
|
||||
printf("stored corner: %.3f, %.3f, %.3f\n", storedCorner.x, storedCorner.y, storedCorner.z);
|
||||
if (finger.getIsTouchingVoxel()) printf("Touching! %f.3", randFloat());
|
||||
if (glm::length(fingerNode->getCorner() - finger.getFingerVoxelPosition()) > EPSILON) {
|
||||
printf("diff = %.9f\n", glm::length(fingerNode->getCorner() - finger.getFingerVoxelPosition()));
|
||||
finger.setFingerVoxelPosition(fingerNode->getCorner());
|
||||
finger.setFingerVoxelScale(fingerNode->getScale());
|
||||
printf("touching voxel scale, %0.4f\n", fingerNode->getScale() * TREE_SCALE);
|
||||
printVector(glm::vec3(fingerNode->getCorner() * (float)TREE_SCALE));
|
||||
if (!palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just started
|
||||
palm.setIsCollidingWithVoxel(true);
|
||||
handleVoxelCollision(&palm, fingerTipPosition, fingerNode, deltaTime);
|
||||
}
|
||||
} else {
|
||||
if (palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just ended
|
||||
palm.setIsCollidingWithVoxel(false);
|
||||
}
|
||||
/*
|
||||
if ((currentFingerVoxel.x != _fingerVoxel.x) ||
|
||||
(currentFingerVoxel.y != _fingerVoxel.y) ||
|
||||
(currentFingerVoxel.z != _fingerVoxel.z) ||
|
||||
(currentFingerVoxel.s != _fingerVoxel.s) ||
|
||||
(currentFingerVoxel.red != _fingerVoxel.red) ||
|
||||
(currentFingerVoxel.green != _fingerVoxel.green) ||
|
||||
(currentFingerVoxel.blue != _fingerVoxel.blue)) {
|
||||
memcpy(&_fingerVoxel, ¤tFingerVoxel, sizeof(VoxelDetail));
|
||||
_fingerIsOnVoxel = true;
|
||||
Application::getInstance()->setHighlightVoxel(currentFingerVoxel);
|
||||
Application::getInstance()->setIsHighlightVoxel(true);
|
||||
printf("Moved onto a voxel %.2f, %.2f, %.2f s %.2f\n",
|
||||
currentFingerVoxel.x * TREE_SCALE,
|
||||
currentFingerVoxel.y * TREE_SCALE,
|
||||
currentFingerVoxel.z * TREE_SCALE,
|
||||
currentFingerVoxel.s * TREE_SCALE);
|
||||
// If desired, make a sound
|
||||
Application::getInstance()->getAudio()->startCollisionSound(1.0, 7040 * currentFingerVoxel.s * TREE_SCALE, 0.0, 0.999f, false);
|
||||
}
|
||||
*/
|
||||
} else if (finger.getIsTouchingVoxel()) {
|
||||
// Just moved off a voxel, change back it's color
|
||||
printf("Moved out of voxel!\n");
|
||||
finger.setIsTouchingVoxel(false);
|
||||
Application::getInstance()->setIsHighlightVoxel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Hand::handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelNode* voxel, float deltaTime) {
|
||||
//
|
||||
// Collision between finger and a voxel plays sound
|
||||
//
|
||||
float volume = glm::length(palm->getVelocity());
|
||||
float duration = volume;
|
||||
_collisionCenter = fingerTipPosition;
|
||||
_collisionAge = deltaTime;
|
||||
_collisionDuration = duration;
|
||||
int voxelBrightness = voxel->getColor()[0] + voxel->getColor()[1] + voxel->getColor()[2];
|
||||
float frequency = 100.f + (voxelBrightness * 2.f); // Hz
|
||||
// Play a sound
|
||||
Application::getInstance()->getAudio()->startCollisionSound(volume,
|
||||
frequency,
|
||||
0.25,
|
||||
0.995f,
|
||||
false);
|
||||
|
||||
}
|
||||
|
||||
void Hand::calculateGeometry() {
|
||||
const glm::vec3 leapHandsOffsetFromFace(0.0, -0.2, -0.3); // place the hand in front of the face where we can see it
|
||||
|
||||
|
@ -233,6 +227,21 @@ void Hand::render() {
|
|||
}
|
||||
}
|
||||
|
||||
// If hand/voxel collision has happened, render a little expanding sphere
|
||||
if (_collisionAge > 0.f) {
|
||||
float opacity = glm::clamp(1.f - (_collisionAge / _collisionDuration), 0.f, 1.f);
|
||||
glColor4f(1, 0, 0, 0.5 * opacity);
|
||||
glPushMatrix();
|
||||
glTranslatef(_collisionCenter.x, _collisionCenter.y, _collisionCenter.z);
|
||||
glutSolidSphere(_collisionAge * 0.25f, 20, 20);
|
||||
glPopMatrix();
|
||||
if (_collisionAge > _collisionDuration) {
|
||||
_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) {
|
||||
|
@ -353,7 +362,6 @@ void Hand::renderLeapHands() {
|
|||
} else {
|
||||
glColor4f(handColor.r, handColor.g, handColor.b, alpha);
|
||||
}
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(_leapFingerTipBalls[i].position.x, _leapFingerTipBalls[i].position.y, _leapFingerTipBalls[i].position.z);
|
||||
glutSolidSphere(_leapFingerTipBalls[i].radius, 20.0f, 20.0f);
|
||||
|
|
|
@ -84,6 +84,12 @@ private:
|
|||
std::vector<HandBall> _leapFingerRootBalls;
|
||||
|
||||
glm::vec3 _lastFingerAddVoxel, _lastFingerDeleteVoxel;
|
||||
bool _isCollidingWithVoxel;
|
||||
VoxelDetail _collidingVoxel;
|
||||
|
||||
glm::vec3 _collisionCenter;
|
||||
float _collisionAge;
|
||||
float _collisionDuration;
|
||||
|
||||
// private methods
|
||||
void setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||
|
@ -94,6 +100,8 @@ private:
|
|||
void renderLeapHands();
|
||||
void renderLeapFingerTrails();
|
||||
void calculateGeometry();
|
||||
|
||||
void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelNode* voxel, float deltaTime);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,6 @@ void SixenseManager::update(float deltaTime) {
|
|||
}
|
||||
MyAvatar* avatar = Application::getInstance()->getAvatar();
|
||||
Hand& hand = avatar->getHand();
|
||||
hand.getPalms().clear();
|
||||
|
||||
int maxControllers = sixenseGetMaxControllers();
|
||||
for (int i = 0; i < maxControllers; i++) {
|
||||
|
@ -42,45 +41,63 @@ void SixenseManager::update(float deltaTime) {
|
|||
sixenseControllerData data;
|
||||
sixenseGetNewestData(i, &data);
|
||||
|
||||
// Set palm position and normal based on Hydra position/orientation
|
||||
PalmData palm(&hand);
|
||||
palm.setActive(true);
|
||||
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
|
||||
//printf("si: %i\n", data.controller_index);
|
||||
|
||||
// Compute current velocity from position change
|
||||
palm.setVelocity((position - palm.getPosition()) / deltaTime);
|
||||
// Set palm position and normal based on Hydra position/orientation
|
||||
|
||||
// Either find a palm matching the sixense controller, or make a new one
|
||||
PalmData* palm;
|
||||
bool foundHand = false;
|
||||
for (int j = 0; j < hand.getNumPalms(); j++) {
|
||||
if (hand.getPalms()[j].getSixenseID() == data.controller_index) {
|
||||
palm = &hand.getPalms()[j];
|
||||
foundHand = true;
|
||||
}
|
||||
}
|
||||
if (!foundHand) {
|
||||
PalmData newPalm(&hand);
|
||||
hand.getPalms().push_back(newPalm);
|
||||
palm = &hand.getPalms()[hand.getNumPalms() - 1];
|
||||
palm->setSixenseID(data.controller_index);
|
||||
printf("Found new Sixense controller, ID %i\n", data.controller_index);
|
||||
}
|
||||
|
||||
palm->setActive(true);
|
||||
|
||||
// Read controller buttons and joystick into the hand
|
||||
palm.setControllerButtons(data.buttons);
|
||||
palm.setTrigger(data.trigger);
|
||||
palm.setJoystick(data.joystick_x, data.joystick_y);
|
||||
|
||||
palm->setControllerButtons(data.buttons);
|
||||
palm->setTrigger(data.trigger);
|
||||
palm->setJoystick(data.joystick_x, data.joystick_y);
|
||||
|
||||
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
|
||||
// Adjust for distance between acquisition 'orb' and the user's torso
|
||||
// (distance to the right of body center, distance below torso, distance behind torso)
|
||||
const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f);
|
||||
position = SPHERE_TO_TORSO + position;
|
||||
palm.setRawPosition(position);
|
||||
glm::quat rotation(data.rot_quat[3], -data.rot_quat[0], data.rot_quat[1], -data.rot_quat[2]);
|
||||
|
||||
// Rotate about controller
|
||||
// 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);
|
||||
palm->setRawNormal(rotation * PALM_VECTOR);
|
||||
|
||||
// initialize the "finger" based on the direction
|
||||
FingerData finger(&palm, &hand);
|
||||
FingerData finger(palm, &hand);
|
||||
finger.setActive(true);
|
||||
finger.setRawRootPosition(position);
|
||||
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, 100.0f);
|
||||
const float FINGER_LENGTH = 100.0f; // Millimeters
|
||||
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
|
||||
finger.setRawTipPosition(position + rotation * FINGER_VECTOR);
|
||||
|
||||
// three fingers indicates to the skeleton that we have enough data to determine direction
|
||||
palm.getFingers().clear();
|
||||
palm.getFingers().push_back(finger);
|
||||
palm.getFingers().push_back(finger);
|
||||
palm.getFingers().push_back(finger);
|
||||
|
||||
hand.getPalms().push_back(palm);
|
||||
palm->getFingers().clear();
|
||||
palm->getFingers().push_back(finger);
|
||||
palm->getFingers().push_back(finger);
|
||||
palm->getFingers().push_back(finger);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -41,8 +41,10 @@ _velocity(0, 0, 0),
|
|||
_controllerButtons(0),
|
||||
_isActive(false),
|
||||
_leapID(LEAPID_INVALID),
|
||||
_sixenseID(SIXENSEID_INVALID),
|
||||
_numFramesWithoutData(0),
|
||||
_owningHandData(owningHandData)
|
||||
_owningHandData(owningHandData),
|
||||
_isCollidingWithVoxel(false)
|
||||
{
|
||||
for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) {
|
||||
_fingers.push_back(FingerData(this, owningHandData));
|
||||
|
@ -56,10 +58,7 @@ _isActive(false),
|
|||
_leapID(LEAPID_INVALID),
|
||||
_numFramesWithoutData(0),
|
||||
_owningPalmData(owningPalmData),
|
||||
_owningHandData(owningHandData),
|
||||
_isTouchingVoxel(false),
|
||||
_fingerVoxelPosition(),
|
||||
_fingerVoxelScale(0)
|
||||
_owningHandData(owningHandData)
|
||||
{
|
||||
const int standardTrailLength = 10;
|
||||
setTrailLength(standardTrailLength);
|
||||
|
|
|
@ -24,6 +24,7 @@ const int NUM_FINGERS_PER_HAND = 5;
|
|||
const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND;
|
||||
|
||||
const int LEAPID_INVALID = -1;
|
||||
const int SIXENSEID_INVALID = -1;
|
||||
|
||||
enum RaveGloveEffectsMode
|
||||
{
|
||||
|
@ -120,13 +121,6 @@ public:
|
|||
void resetFramesWithoutData() { _numFramesWithoutData = 0; }
|
||||
int getFramesWithoutData() const { return _numFramesWithoutData; }
|
||||
|
||||
void setIsTouchingVoxel(bool isTouchingVoxel) { _isTouchingVoxel = isTouchingVoxel; }
|
||||
bool getIsTouchingVoxel() { return _isTouchingVoxel; }
|
||||
void setFingerVoxelPosition(const glm::vec3& fingerVoxelPosition) { _fingerVoxelPosition = fingerVoxelPosition; }
|
||||
const glm::vec3& getFingerVoxelPosition() const { return _fingerVoxelPosition; }
|
||||
void setFingerVoxelScale(float fingerVoxelScale) { _fingerVoxelScale = fingerVoxelScale; }
|
||||
float getFingerVoxelScale() { return _fingerVoxelScale; }
|
||||
|
||||
private:
|
||||
glm::vec3 _tipRawPosition;
|
||||
glm::vec3 _rootRawPosition;
|
||||
|
@ -138,10 +132,6 @@ private:
|
|||
int _tipTrailCurrentValidLength;
|
||||
PalmData* _owningPalmData;
|
||||
HandData* _owningHandData;
|
||||
|
||||
bool _isTouchingVoxel;
|
||||
glm::vec3 _fingerVoxelPosition;
|
||||
float _fingerVoxelScale;
|
||||
};
|
||||
|
||||
class PalmData {
|
||||
|
@ -153,12 +143,16 @@ public:
|
|||
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
||||
bool isActive() const { return _isActive; }
|
||||
int getLeapID() const { return _leapID; }
|
||||
int getSixenseID() const { return _sixenseID; }
|
||||
|
||||
|
||||
std::vector<FingerData>& getFingers() { return _fingers; }
|
||||
size_t getNumFingers() { return _fingers.size(); }
|
||||
|
||||
void setActive(bool active) { _isActive = active; }
|
||||
void setLeapID(int id) { _leapID = id; }
|
||||
void setSixenseID(int id) { _sixenseID = id; }
|
||||
|
||||
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
|
||||
void setRawNormal(const glm::vec3& normal) { _rawNormal = normal; }
|
||||
void setVelocity(const glm::vec3& velocity) { _velocity = velocity; }
|
||||
|
@ -177,6 +171,9 @@ public:
|
|||
void setJoystick(float joystickX, float joystickY) { _joystickX = joystickX; _joystickY = joystickY; }
|
||||
float getJoystickX() { return _joystickX; }
|
||||
float getJoystickY() { return _joystickY; }
|
||||
|
||||
bool getIsCollidingWithVoxel() { return _isCollidingWithVoxel; }
|
||||
void setIsCollidingWithVoxel(bool isCollidingWithVoxel) { _isCollidingWithVoxel = isCollidingWithVoxel; }
|
||||
|
||||
private:
|
||||
std::vector<FingerData> _fingers;
|
||||
|
@ -189,8 +186,12 @@ private:
|
|||
|
||||
bool _isActive; // This has current valid data
|
||||
int _leapID; // the Leap's serial id for this tracked object
|
||||
int _sixenseID; // Sixense controller ID for this palm
|
||||
int _numFramesWithoutData; // after too many frames without data, this tracked object assumed lost.
|
||||
HandData* _owningHandData;
|
||||
|
||||
bool _isCollidingWithVoxel; /// Whether the finger of this palm is inside a leaf voxel
|
||||
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__HandData__) */
|
||||
|
|
Loading…
Reference in a new issue