From d9f412406fac538191ec173ccf2369bf9612a1a7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Dec 2013 18:12:47 -0800 Subject: [PATCH 1/3] better implementation of particle palm collisions --- interface/src/Application.cpp | 2 +- interface/src/avatar/Hand.cpp | 20 +++-- interface/src/avatar/Hand.h | 2 +- interface/src/avatar/Head.cpp | 1 + libraries/avatars/src/AvatarData.h | 3 + libraries/avatars/src/HandData.cpp | 21 +++++ libraries/avatars/src/HandData.h | 10 +++ libraries/avatars/src/HeadData.cpp | 8 ++ libraries/avatars/src/HeadData.h | 7 ++ .../particles/src/ParticleCollisionSystem.cpp | 82 ++++++++++++++++++- .../particles/src/ParticleCollisionSystem.h | 13 ++- 11 files changed, 153 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4d964407ca..d26e3450fa 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1858,7 +1858,7 @@ void Application::init() { _particles.init(); _particles.setViewFrustum(getViewFrustum()); - _particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio); + _particleCollisionSystem.init(&_particleEditSender, _particles.getTree(), _voxels.getTree(), &_audio, &_myAvatar); _palette.init(_glWidget->width(), _glWidget->height()); _palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 115fd1985d..6b8dbdce49 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -85,7 +85,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f //printf("potentially caught... particle ID:%d\n", closestParticle->getID()); if (!_toyBallInHand[handID]) { - printf("particle ID:%d NOT IN HAND\n", closestParticle->getID()); + /*** + printf("particle ID:%d IN TARGET AND NOT IN HAND\n", closestParticle->getID()); // you can create a ParticleEditHandle by doing this... ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID()); @@ -93,22 +94,22 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f // reflect off the hand... printf("particle ID:%d old velocity=%f,%f,%f\n", closestParticle->getID(), closestParticle->getVelocity().x, closestParticle->getVelocity().y, closestParticle->getVelocity().z); - glm::vec3 newVelocity = glm::reflect(closestParticle->getVelocity(), palm.getNormal()); + + glm::vec3 reflectNormal = glm::vec3(0,1,0); // palm.getNormal() + glm::vec3 newVelocity = glm::reflect(closestParticle->getVelocity(), reflectNormal); printf("particle ID:%d REFLECT velocity=%f,%f,%f\n", closestParticle->getID(), newVelocity.x, newVelocity.y, newVelocity.z); - newVelocity += palm.getTipVelocity() / (float)TREE_SCALE; - - printf("particle ID:%d with TIP velocity=%f,%f,%f\n", closestParticle->getID(), - newVelocity.x, newVelocity.y, newVelocity.z); + //newVelocity += palm.getTipVelocity() / (float)TREE_SCALE; + //printf("particle ID:%d with TIP velocity=%f,%f,%f\n", closestParticle->getID(), newVelocity.x, newVelocity.y, newVelocity.z); printf("particle ID:%d OLD position=%f,%f,%f\n", closestParticle->getID(), closestParticle->getPosition().x, closestParticle->getPosition().y, closestParticle->getPosition().z); glm::vec3 newPosition = closestParticle->getPosition(); - newPosition += newVelocity; // move it as if it's already been moving in new direction + newPosition += newVelocity * 10.f; // move it as if it's already been moving in new direction printf("particle ID:%d NEW position=%f,%f,%f\n", closestParticle->getID(), newPosition.x, newPosition.y, newPosition.z); @@ -123,6 +124,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f // but make sure you clean it up, when you're done delete caughtParticle; + **/ } } @@ -496,6 +498,10 @@ void Hand::renderLeapHands() { } glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z); glutWireSphere(targetRadius, 20.0f, 20.0f); + + const float collisionRadius = 0.05f; + glColor4f(0.5f,0.5f,0.5f, alpha); + glutWireSphere(collisionRadius, 20.0f, 20.0f); glPopMatrix(); } } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 451da1b878..59be80ce20 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -64,7 +64,7 @@ public: // Get the drag distance to move glm::vec3 getAndResetGrabDelta(); glm::vec3 getAndResetGrabDeltaVelocity(); - + private: // disallow copies of the Hand, copy of owning Avatar is disallowed too Hand(const Hand&); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b593602e3f..b14baca3ef 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -765,3 +765,4 @@ void Head::updateHairPhysics(float deltaTime) { _hairTuft[t].update(deltaTime); } } + diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 13c9b1e049..7ebf12616d 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -98,6 +98,9 @@ public: const QUuid& getLeaderUUID() const { return _leaderUUID; } + const HeadData* getHeadData() const { return _headData; } + const HandData* getHandData() const { return _handData; } + void setHeadData(HeadData* headData) { _headData = headData; } void setHandData(HandData* handData) { _handData = handData; } diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 12af614de3..70dd74a158 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -9,6 +9,7 @@ #include "HandData.h" #include "AvatarData.h" #include +#include // When converting between fixed and float, use this as the radix. @@ -223,6 +224,25 @@ void HandData::updateFingerTrails() { } } +bool HandData::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, + const PalmData*& collidingPalm) const { + + for (size_t i = 0; i < _palms.size(); ++i) { + const PalmData& palm = _palms[i]; + if (!palm.isActive()) { + continue; + } + glm::vec3 palmPosition = palm.getPosition(); + const float PALM_RADIUS = 0.05f; // in world (not voxel) coordinates + if (findSphereSpherePenetration(penetratorCenter, penetratorRadius, palmPosition, PALM_RADIUS, penetration)) { + collidingPalm = &palm; + return true; + } + } + return false; +} + + void FingerData::setTrailLength(unsigned int length) { _tipTrailPositions.resize(length); _tipTrailCurrentStartIndex = 0; @@ -265,3 +285,4 @@ const glm::vec3& FingerData::getTrailPosition(int index) { + diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 0a72160e95..00797881fe 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -68,6 +68,15 @@ public: int encodeRemoteData(unsigned char* destinationBuffer); int decodeRemoteData(unsigned char* sourceBuffer); + /// Checks for penetration between the described sphere and the hand. + /// \param penetratorCenter the center of the penetration test sphere + /// \param penetratorRadius the radius of the penetration test sphere + /// \param penetration[out] the vector in which to store the penetration + /// \param collidingPalm[out] a const PalmData* to the palm that was collided with + /// \return whether or not the sphere penetrated + bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration, + const PalmData*& collidingPalm) const; + friend class AvatarData; protected: glm::vec3 _basePosition; // Hands are placed relative to this @@ -124,6 +133,7 @@ public: PalmData(HandData* owningHandData); glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); } glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); } + glm::vec3 getVelocity() const { return _owningHandData->leapDirectionToWorldDirection(_rawVelocity); } const glm::vec3& getRawPosition() const { return _rawPosition; } const glm::vec3& getRawNormal() const { return _rawNormal; } diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index 1ad0d32e2d..f863d6b592 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -44,3 +44,11 @@ void HeadData::addLean(float sideways, float forwards) { _leanSideways += sideways; _leanForward += forwards; } + +bool HeadData::findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration) const { + // we would like to update this to determine collisions/penetrations with the Avatar's head sphere... + // but right now it does not appear as if the HeadData has a position and radius. + // this is a placeholder for now. + return false; +} + diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 0f096059c0..fde684bbf1 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -58,6 +58,13 @@ public: void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; } friend class AvatarData; + + /// Checks for penetration between the described sphere and the hand. + /// \param penetratorCenter the center of the penetration test sphere + /// \param penetratorRadius the radius of the penetration test sphere + /// \param penetration[out] the vector in which to store the penetration + /// \return whether or not the sphere penetrated + bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius, glm::vec3& penetration) const; protected: float _yaw; diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 8928a3db8c..3d077cc209 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -9,6 +9,9 @@ #include #include +#include +#include +#include #include "Particle.h" #include "ParticleCollisionSystem.h" @@ -17,16 +20,17 @@ #include "ParticleTree.h" ParticleCollisionSystem::ParticleCollisionSystem(ParticleEditPacketSender* packetSender, - ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio) { - init(packetSender, particles, voxels, audio); + ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio, AvatarData* selfAvatar) { + init(packetSender, particles, voxels, audio, selfAvatar); } void ParticleCollisionSystem::init(ParticleEditPacketSender* packetSender, - ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio) { + ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio, AvatarData* selfAvatar) { _packetSender = packetSender; _particles = particles; _voxels = voxels; _audio = audio; + _selfAvatar = selfAvatar; } ParticleCollisionSystem::~ParticleCollisionSystem() { @@ -59,6 +63,7 @@ void ParticleCollisionSystem::update() { void ParticleCollisionSystem::checkParticle(Particle* particle) { updateCollisionWithVoxels(particle); updateCollisionWithParticles(particle); + updateCollisionWithAvatars(particle); } void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { @@ -91,8 +96,76 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { } } +void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { + + //printf("updateCollisionWithAvatars()...\n"); + glm::vec3 center = particle->getPosition() * (float)TREE_SCALE; + float radius = particle->getRadius() * (float)TREE_SCALE; + const float VOXEL_ELASTICITY = 1.4f; + const float VOXEL_DAMPING = 0.0; + const float VOXEL_COLLISION_FREQUENCY = 0.5f; + glm::vec3 penetration; + const PalmData* collidingPalm = NULL; + + // first check the selfAvatar if set... + if (_selfAvatar) { + AvatarData* avatar = (AvatarData*)_selfAvatar; + //printf("updateCollisionWithAvatars()..._selfAvatar=%p\n", avatar); + + // check hands... + const HandData* handData = avatar->getHandData(); + + // if the particle penetrates the hand, then apply a hard collision + if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { + penetration /= (float)TREE_SCALE; + updateCollisionSound(particle, penetration, VOXEL_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, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity); + } + } + + // loop through all the other avatars for potential interactions... + NodeList* nodeList = NodeList::getInstance(); + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + //qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n"; + if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) { + AvatarData* avatar = (AvatarData*)node->getLinkedData(); + //printf("updateCollisionWithAvatars()...avatar=%p\n", avatar); + + // check hands... + const HandData* handData = avatar->getHandData(); + + // if the particle penetrates the hand, then apply a hard collision + if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) { + penetration /= (float)TREE_SCALE; + updateCollisionSound(particle, penetration, VOXEL_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, VOXEL_ELASTICITY, VOXEL_DAMPING, addedVelocity); + + } + } + } +} + + void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::vec3& penetration, - float elasticity, float damping) { + float elasticity, float damping, const glm::vec3& addedVelocity) { // // Update the avatar in response to a hard collision. Position will be reset exactly // to outside the colliding surface. Velocity will be modified according to elasticity. @@ -112,6 +185,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: if (penetrationLength > EPSILON) { glm::vec3 direction = penetration / penetrationLength; velocity -= glm::dot(velocity, direction) * direction * elasticity; + velocity += addedVelocity; velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f); if (glm::length(velocity) < HALTING_VELOCITY) { // If moving really slowly after a collision, and not applying forces, stop altogether diff --git a/libraries/particles/src/ParticleCollisionSystem.h b/libraries/particles/src/ParticleCollisionSystem.h index 0daece8634..920b89c053 100644 --- a/libraries/particles/src/ParticleCollisionSystem.h +++ b/libraries/particles/src/ParticleCollisionSystem.h @@ -22,18 +22,22 @@ #include "Particle.h" class AbstractAudioInterface; +class AvatarData; class ParticleEditPacketSender; class ParticleTree; class VoxelTree; +const glm::vec3 NO_ADDED_VELOCITY = glm::vec3(0); + class ParticleCollisionSystem { public: ParticleCollisionSystem(ParticleEditPacketSender* packetSender = NULL, ParticleTree* particles = NULL, VoxelTree* voxels = NULL, - AbstractAudioInterface* audio = NULL); + AbstractAudioInterface* audio = NULL, + AvatarData* selfAvatar = NULL); void init(ParticleEditPacketSender* packetSender, ParticleTree* particles, VoxelTree* voxels, - AbstractAudioInterface* audio = NULL); + AbstractAudioInterface* audio = NULL, AvatarData* selfAvatar = NULL); ~ParticleCollisionSystem(); @@ -41,7 +45,9 @@ public: void checkParticle(Particle* particle); void updateCollisionWithVoxels(Particle* particle); void updateCollisionWithParticles(Particle* particle); - void applyHardCollision(Particle* particle, const glm::vec3& penetration, float elasticity, float damping); + void updateCollisionWithAvatars(Particle* particle); + void applyHardCollision(Particle* particle, const glm::vec3& penetration, float elasticity, float damping, + const glm::vec3& addedVelocity = NO_ADDED_VELOCITY); void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency); private: @@ -52,6 +58,7 @@ private: ParticleTree* _particles; VoxelTree* _voxels; AbstractAudioInterface* _audio; + AvatarData* _selfAvatar; }; #endif /* defined(__hifi__ParticleCollisionSystem__) */ \ No newline at end of file From 8f1fbec057d5e117a60b10ec1e2dc7830226be57 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Dec 2013 19:49:22 -0800 Subject: [PATCH 2/3] added versioning to SVO files and Particle inHand support --- interface/src/Application.cpp | 6 +- interface/src/Application.h | 2 +- interface/src/avatar/Hand.cpp | 19 ++--- libraries/octree/src/Octree.cpp | 48 +++++++++++-- libraries/octree/src/Octree.h | 2 + libraries/octree/src/OctreePacketData.cpp | 9 +++ libraries/octree/src/OctreePacketData.h | 3 + libraries/particles/src/Particle.cpp | 70 +++++++++++++------ libraries/particles/src/Particle.h | 13 +++- .../particles/src/ParticleCollisionSystem.cpp | 7 +- .../particles/src/ParticleEditHandle.cpp | 10 +-- libraries/particles/src/ParticleEditHandle.h | 4 +- .../src/ParticleScriptingInterface.cpp | 4 +- .../src/ParticleScriptingInterface.h | 2 +- libraries/particles/src/ParticleTree.h | 2 + libraries/shared/src/PacketHeaders.cpp | 5 +- libraries/voxels/src/VoxelTree.h | 1 + 17 files changed, 151 insertions(+), 56 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d26e3450fa..1d845674e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1523,7 +1523,7 @@ void Application::shootParticle() { QString updateScript(""); ParticleEditHandle* particleEditHandle = makeParticle(position / (float)TREE_SCALE, radius, color, - velocity / (float)TREE_SCALE, gravity, damping, updateScript); + velocity / (float)TREE_SCALE, gravity, damping, NOT_IN_HAND, updateScript); // If we wanted to be able to edit this particle after shooting, then we could store this value // and use it for editing later. But we don't care about that for "shooting" and therefore we just @@ -1540,10 +1540,10 @@ ParticleEditHandle* Application::newParticleEditHandle(uint32_t id) { // Caller is responsible for managing this EditableParticle ParticleEditHandle* Application::makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, - glm::vec3 gravity, float damping, QString updateScript) { + glm::vec3 gravity, float damping, bool inHand, QString updateScript) { ParticleEditHandle* particleEditHandle = newParticleEditHandle(); - particleEditHandle->createParticle(position, radius, color, velocity, gravity, damping, updateScript); + particleEditHandle->createParticle(position, radius, color, velocity, gravity, damping, inHand, updateScript); return particleEditHandle; } diff --git a/interface/src/Application.h b/interface/src/Application.h index d54f9e74d8..f9ffc33781 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -125,7 +125,7 @@ public: void shootParticle(); // shoots a particle in the direction you're looking ParticleEditHandle* newParticleEditHandle(uint32_t id = NEW_PARTICLE); ParticleEditHandle* makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, - glm::vec3 gravity, float damping, QString updateScript); + glm::vec3 gravity, float damping, bool inHand, QString updateScript); void makeVoxel(glm::vec3 position, float scale, diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 6b8dbdce49..f991074b94 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -23,11 +23,9 @@ const float FINGERTIP_VOXEL_SIZE = 0.05; const int TOY_BALL_HAND = 1; const float TOY_BALL_RADIUS = 0.05f; const float TOY_BALL_DAMPING = 0.99f; -const glm::vec3 NO_GRAVITY = glm::vec3(0,0,0); const glm::vec3 NO_VELOCITY = glm::vec3(0,0,0); const glm::vec3 TOY_BALL_GRAVITY = glm::vec3(0,-1,0); const QString TOY_BALL_UPDATE_SCRIPT(""); -const QString TOY_BALL_DONT_DIE_SCRIPT("Particle.setShouldDie(false);"); const float PALM_COLLISION_RADIUS = 0.03f; const xColor TOY_BALL_ON_SERVER_COLOR[] = { @@ -161,9 +159,10 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f TOY_BALL_RADIUS / (float) TREE_SCALE, TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], NO_VELOCITY / (float)TREE_SCALE, - NO_GRAVITY / (float) TREE_SCALE, - TOY_BALL_DAMPING, - TOY_BALL_DONT_DIE_SCRIPT); + TOY_BALL_GRAVITY / (float) TREE_SCALE, + TOY_BALL_DAMPING, + IN_HAND, + TOY_BALL_UPDATE_SCRIPT); } } else { // Ball is in hand @@ -172,9 +171,10 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f TOY_BALL_RADIUS / (float) TREE_SCALE, TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], NO_VELOCITY / (float)TREE_SCALE, - NO_GRAVITY / (float) TREE_SCALE, - TOY_BALL_DAMPING, - TOY_BALL_DONT_DIE_SCRIPT); + TOY_BALL_GRAVITY / (float) TREE_SCALE, + TOY_BALL_DAMPING, + IN_HAND, + TOY_BALL_UPDATE_SCRIPT); } } else { // If toy ball just released, add velocity to it! @@ -193,7 +193,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], toyBallVelocity / (float)TREE_SCALE, TOY_BALL_GRAVITY / (float) TREE_SCALE, - TOY_BALL_DAMPING, + TOY_BALL_DAMPING, + NOT_IN_HAND, TOY_BALL_UPDATE_SCRIPT); // after releasing the ball, we free our ParticleEditHandle so we can't edit it further diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 6e7193f397..5bd99ee308 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1299,6 +1299,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* node, } bool Octree::readFromSVOFile(const char* fileName) { + bool fileOk = false; std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate); if(file.is_open()) { emit importSize(1.0f, 1.0f, 1.0f); @@ -1314,16 +1315,44 @@ bool Octree::readFromSVOFile(const char* fileName) { unsigned char* entireFile = new unsigned char[fileLength]; file.read((char*)entireFile, fileLength); bool wantImportProgress = true; - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, wantImportProgress); - readBitstreamToTree(entireFile, fileLength, args); + + unsigned char* dataAt = entireFile; + unsigned long dataLength = fileLength; + + // before reading the file, check to see if this version of the Octree supports file versions + if (getWantSVOfileVersions()) { + // if so, read the first byte of the file and see if it matches the expected version code + PACKET_TYPE expectedType = expectedDataPacketType(); + PACKET_TYPE gotType = *dataAt; + if (gotType == expectedType) { + dataAt += sizeof(expectedType); + dataLength -= sizeof(expectedType); + PACKET_VERSION expectedVersion = versionForPacketType(expectedType); + PACKET_VERSION gotVersion = *dataAt; + if (gotVersion == expectedVersion) { + dataAt += sizeof(expectedVersion); + dataLength -= sizeof(expectedVersion); + fileOk = true; + } else { + qDebug("SVO file version mismatch. Expected: %d Got: %d\n", expectedVersion, gotVersion); + } + } else { + qDebug("SVO file type mismatch. Expected: %c Got: %c\n", expectedType, gotType); + } + } else { + fileOk = true; // assume the file is ok + } + if (fileOk) { + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, wantImportProgress); + readBitstreamToTree(dataAt, dataLength, args); + } delete[] entireFile; emit importProgress(100); file.close(); - return true; } - return false; + return fileOk; } void Octree::writeToSVOFile(const char* fileName, OctreeElement* node) { @@ -1332,7 +1361,16 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* node) { if(file.is_open()) { qDebug("saving to file %s...\n", fileName); - + + // before reading the file, check to see if this version of the Octree supports file versions + if (getWantSVOfileVersions()) { + // if so, read the first byte of the file and see if it matches the expected version code + PACKET_TYPE expectedType = expectedDataPacketType(); + PACKET_VERSION expectedVersion = versionForPacketType(expectedType); + file.write(&expectedType, sizeof(expectedType)); + file.write(&expectedVersion, sizeof(expectedType)); + } + OctreeElementBag nodeBag; // If we were given a specific node, start from there, otherwise start from root if (node) { diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 0954ef1813..de74476a30 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -183,6 +183,8 @@ public: // These methods will allow the OctreeServer to send your tree inbound edit packets of your // own definition. Implement these to allow your octree based server to support editing + virtual bool getWantSVOfileVersions() const { return false; } + virtual PACKET_TYPE expectedDataPacketType() const { return PACKET_TYPE_UNKNOWN; } virtual bool handlesEditPacketType(PACKET_TYPE packetType) const { return false; } virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, unsigned char* editData, int maxLength, Node* senderNode) { return 0; } diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 36c4d056d1..9e7d88416b 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -305,6 +305,15 @@ bool OctreePacketData::appendValue(const glm::vec3& value) { return success; } +bool OctreePacketData::appendValue(bool value) { + bool success = append((uint8_t)value); // used unsigned char version + if (success) { + _bytesOfValues++; + _totalBytesOfValues++; + } + return success; +} + bool OctreePacketData::appendPosition(const glm::vec3& value) { const unsigned char* data = (const unsigned char*)&value; int length = sizeof(value); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 2843790f68..87b55ace96 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -130,6 +130,9 @@ public: /// appends a non-position vector to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::vec3& value); + /// appends a bool value to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(bool value); + /// appends a position to the end of the stream, may fail if new data stream is too long to fit in packet bool appendPosition(const glm::vec3& value); diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index d23815da3a..e598904ded 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -18,22 +18,23 @@ uint32_t Particle::_nextID = 0; -Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, - float damping, glm::vec3 gravity, QString updateScript, uint32_t id) { +Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity, + float damping, bool inHand, QString updateScript, uint32_t id) { - init(position, radius, color, velocity, damping, gravity, updateScript, id); + init(position, radius, color, velocity, gravity, damping, inHand, updateScript, id); } Particle::Particle() { rgbColor noColor = { 0, 0, 0 }; - init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0), DEFAULT_DAMPING, DEFAULT_GRAVITY, DEFAULT_SCRIPT, NEW_PARTICLE); + init(glm::vec3(0,0,0), 0, noColor, glm::vec3(0,0,0), + DEFAULT_GRAVITY, DEFAULT_DAMPING, NOT_IN_HAND, DEFAULT_SCRIPT, NEW_PARTICLE); } Particle::~Particle() { } -void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, - float damping, glm::vec3 gravity, QString updateScript, uint32_t id) { +void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity, + float damping, bool inHand, QString updateScript, uint32_t id) { if (id == NEW_PARTICLE) { _created = usecTimestampNow(); _id = _nextID; @@ -50,6 +51,7 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _damping = damping; _gravity = gravity; _updateScript = updateScript; + _inHand = inHand; } @@ -83,6 +85,9 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { if (success) { success = packetData->appendValue(getDamping()); } + if (success) { + success = packetData->appendValue(getInHand()); + } if (success) { uint16_t scriptLength = _updateScript.size() + 1; // include NULL success = packetData->appendValue(scriptLength); @@ -96,7 +101,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { int Particle::expectedBytes() { int expectedBytes = sizeof(uint32_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(float) + sizeof(glm::vec3) + sizeof(rgbColor) + sizeof(glm::vec3) + - sizeof(glm::vec3) + sizeof(float); + sizeof(glm::vec3) + sizeof(float) + sizeof(bool); return expectedBytes; } @@ -150,6 +155,11 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(_damping); bytesRead += sizeof(_damping); + // inHand + memcpy(&_inHand, dataAt, sizeof(_inHand)); + dataAt += sizeof(_inHand); + bytesRead += sizeof(_inHand); + // script uint16_t scriptLength; memcpy(&scriptLength, dataAt, sizeof(scriptLength)); @@ -240,6 +250,11 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe dataAt += sizeof(newParticle._damping); processedBytes += sizeof(newParticle._damping); + // inHand + memcpy(&newParticle._inHand, dataAt, sizeof(newParticle._inHand)); + dataAt += sizeof(newParticle._inHand); + processedBytes += sizeof(newParticle._inHand); + // script uint16_t scriptLength; memcpy(&scriptLength, dataAt, sizeof(scriptLength)); @@ -352,6 +367,11 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, copyAt += sizeof(details[i].damping); sizeOut += sizeof(details[i].damping); + // inHand + memcpy(copyAt, &details[i].inHand, sizeof(details[i].inHand)); + copyAt += sizeof(details[i].inHand); + sizeOut += sizeof(details[i].inHand); + // script uint16_t scriptLength = details[i].updateScript.size() + 1; memcpy(copyAt, &scriptLength, sizeof(scriptLength)); @@ -389,27 +409,31 @@ void Particle::update() { bool isStillMoving = (velocityScalar > STILL_MOVING); const uint64_t REALLY_OLD = 30 * 1000 * 1000; bool isReallyOld = (getLifetime() > REALLY_OLD); - bool shouldDie = !isStillMoving && isReallyOld; + bool isInHand = getInHand(); + bool shouldDie = !isInHand && !isStillMoving && isReallyOld; setShouldDie(shouldDie); runScript(); // allow the javascript to alter our state - - _position += _velocity * timeElapsed; - // handle bounces off the ground... - if (_position.y <= 0) { - _velocity = _velocity * glm::vec3(1,-1,1); - _position.y = 0; + // If the ball is in hand, it doesn't move or have gravity effect it + if (!isInHand) { + _position += _velocity * timeElapsed; + + // handle bounces off the ground... + if (_position.y <= 0) { + _velocity = _velocity * glm::vec3(1,-1,1); + _position.y = 0; + } + + // handle gravity.... + _velocity += _gravity * timeElapsed; + + // handle damping + glm::vec3 dampingResistance = _velocity * _damping; + _velocity -= dampingResistance * timeElapsed; + //printf("applying damping to Particle timeElapsed=%f\n",timeElapsed); } - - // handle gravity.... - _velocity += _gravity * timeElapsed; - - // handle damping - glm::vec3 dampingResistance = _velocity * _damping; - _velocity -= dampingResistance * timeElapsed; - //printf("applying damping to Particle timeElapsed=%f\n",timeElapsed); - + _lastUpdated = now; } diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 1d80adabc6..d4791c566c 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -32,6 +32,7 @@ public: glm::vec3 velocity; glm::vec3 gravity; float damping; + bool inHand; QString updateScript; uint32_t creatorTokenID; }; @@ -39,21 +40,24 @@ public: const float DEFAULT_DAMPING = 0.99f; const glm::vec3 DEFAULT_GRAVITY(0, (-9.8f / TREE_SCALE), 0); const QString DEFAULT_SCRIPT(""); +const bool IN_HAND = true; // it's in a hand +const bool NOT_IN_HAND = !IN_HAND; // it's not in a hand class Particle { public: Particle(); Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, - float damping = DEFAULT_DAMPING, glm::vec3 gravity = DEFAULT_GRAVITY, QString updateScript = DEFAULT_SCRIPT, - uint32_t id = NEW_PARTICLE); + glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND, + QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE); /// creates an NEW particle from an PACKET_TYPE_PARTICLE_ADD_OR_EDIT edit data buffer static Particle fromEditPacket(unsigned char* data, int length, int& processedBytes); virtual ~Particle(); virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, - float damping, glm::vec3 gravity, QString updateScript, uint32_t id); + glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND, + QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE); const glm::vec3& getPosition() const { return _position; } const rgbColor& getColor() const { return _color; } @@ -61,6 +65,7 @@ public: float getRadius() const { return _radius; } const glm::vec3& getVelocity() const { return _velocity; } const glm::vec3& getGravity() const { return _gravity; } + bool getInHand() const { return _inHand; } float getDamping() const { return _damping; } uint64_t getCreated() const { return _created; } uint64_t getLifetime() const { return usecTimestampNow() - _created; } @@ -81,6 +86,7 @@ public: } void setRadius(float value) { _radius = value; } void setGravity(const glm::vec3& value) { _gravity = value; } + void setInHand(bool inHand) { _inHand = inHand; } void setDamping(float value) { _damping = value; } void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } void setUpdateScript(QString updateScript) { _updateScript = updateScript; } @@ -116,6 +122,7 @@ protected: glm::vec3 _gravity; float _damping; QString _updateScript; + bool _inHand; uint32_t _creatorTokenID; bool _newlyCreated; diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index 3d077cc209..1a21d1231e 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -98,6 +98,11 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) { + // particles that are in hand, don't collide with other avatar parts + if (particle->getInHand()) { + return; + } + //printf("updateCollisionWithAvatars()...\n"); glm::vec3 center = particle->getPosition() * (float)TREE_SCALE; float radius = particle->getRadius() * (float)TREE_SCALE; @@ -194,7 +199,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: } ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID()); particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity, - particle->getGravity(), particle->getDamping(), particle->getUpdateScript()); + particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getUpdateScript()); } diff --git a/libraries/particles/src/ParticleEditHandle.cpp b/libraries/particles/src/ParticleEditHandle.cpp index 24700fbcba..e9606dd3cd 100644 --- a/libraries/particles/src/ParticleEditHandle.cpp +++ b/libraries/particles/src/ParticleEditHandle.cpp @@ -41,12 +41,12 @@ ParticleEditHandle::~ParticleEditHandle() { } void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, - glm::vec3 gravity, float damping, QString updateScript) { + glm::vec3 gravity, float damping, bool inHand, QString updateScript) { // setup a ParticleDetail struct with the data ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(), position, radius, {color.red, color.green, color.blue }, - velocity, gravity, damping, updateScript, _creatorTokenID }; + velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; // queue the packet _packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &addParticleDetail); @@ -62,7 +62,7 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor } bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, - glm::vec3 gravity, float damping, QString updateScript) { + glm::vec3 gravity, float damping, bool inHand, QString updateScript) { if (!isKnownID()) { return false; // not allowed until we know the id @@ -71,7 +71,7 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor // setup a ParticleDetail struct with the data ParticleDetail newParticleDetail = { _id, usecTimestampNow(), position, radius, {color.red, color.green, color.blue }, - velocity, gravity, damping, updateScript, _creatorTokenID }; + velocity, gravity, damping, inHand, updateScript, _creatorTokenID }; // queue the packet _packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &newParticleDetail); @@ -82,7 +82,7 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor // if we have a local tree, also update it... if (_localTree) { rgbColor rcolor = {color.red, color.green, color.blue }; - Particle tempParticle(position, radius, rcolor, velocity, damping, gravity, updateScript, _id); + Particle tempParticle(position, radius, rcolor, velocity, gravity, damping, inHand, updateScript, _id); _localTree->storeParticle(tempParticle); } diff --git a/libraries/particles/src/ParticleEditHandle.h b/libraries/particles/src/ParticleEditHandle.h index bed8b29d14..186dc47944 100644 --- a/libraries/particles/src/ParticleEditHandle.h +++ b/libraries/particles/src/ParticleEditHandle.h @@ -35,10 +35,10 @@ public: bool isKnownID() const { return _isKnownID; } void createParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, - glm::vec3 gravity, float damping, QString updateScript); + glm::vec3 gravity, float damping, bool inHand, QString updateScript); bool updateParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, - glm::vec3 gravity, float damping, QString updateScript); + glm::vec3 gravity, float damping, bool inHand, QString updateScript); static void handleAddResponse(unsigned char* packetData , int packetLength); private: diff --git a/libraries/particles/src/ParticleScriptingInterface.cpp b/libraries/particles/src/ParticleScriptingInterface.cpp index cb534cc522..d4ae76e645 100644 --- a/libraries/particles/src/ParticleScriptingInterface.cpp +++ b/libraries/particles/src/ParticleScriptingInterface.cpp @@ -15,7 +15,7 @@ void ParticleScriptingInterface::queueParticleAdd(PACKET_TYPE addPacketType, Par } unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius, - xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, QString updateScript) { + xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString updateScript) { // The application will keep track of creatorTokenID uint32_t creatorTokenID = _nextCreatorTokenID; @@ -24,7 +24,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl // setup a ParticleDetail struct with the data ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(), position, radius, {color.red, color.green, color.blue }, velocity, - gravity, damping, updateScript, creatorTokenID }; + gravity, damping, inHand, updateScript, creatorTokenID }; // queue the packet queueParticleAdd(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail); diff --git a/libraries/particles/src/ParticleScriptingInterface.h b/libraries/particles/src/ParticleScriptingInterface.h index 85dd0c6caf..68b8318ebe 100644 --- a/libraries/particles/src/ParticleScriptingInterface.h +++ b/libraries/particles/src/ParticleScriptingInterface.h @@ -27,7 +27,7 @@ public slots: /// queues the creation of a Particle which will be sent by calling process on the PacketSender /// returns the creatorTokenID for the newly created particle unsigned int queueParticleAdd(glm::vec3 position, float radius, - xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, QString updateScript); + xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString updateScript); private: void queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails); diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index 9d7d4a98f8..0594b2f4b2 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -36,6 +36,8 @@ public: // These methods will allow the OctreeServer to send your tree inbound edit packets of your // own definition. Implement these to allow your octree based server to support editing + virtual bool getWantSVOfileVersions() const { return true; } + virtual PACKET_TYPE expectedDataPacketType() const { return PACKET_TYPE_PARTICLE_DATA; } virtual bool handlesEditPacketType(PACKET_TYPE packetType) const; virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, unsigned char* editData, int maxLength, Node* senderNode); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 9b5961b12f..6c6c402f39 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -51,7 +51,10 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_PARTICLE_ADD_OR_EDIT: - return 1; + return 2; + + case PACKET_TYPE_PARTICLE_DATA: + return 2; default: return 0; diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index ea841ebf90..0b93cd0dc7 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -53,6 +53,7 @@ public: void readCodeColorBufferToTree(const unsigned char* codeColorBuffer, bool destructive = false); + virtual PACKET_TYPE expectedDataPacketType() const { return PACKET_TYPE_VOXEL_DATA; } virtual bool handlesEditPacketType(PACKET_TYPE packetType) const; virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, unsigned char* editData, int maxLength, Node* senderNode); From e969331f5c675393ee364873a64dba0a0079616c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 16 Dec 2013 20:29:28 -0800 Subject: [PATCH 3/3] implement catching of particles --- interface/src/Application.cpp | 2 +- interface/src/avatar/Hand.cpp | 60 +++++++++++++++-------------------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1d845674e0..3cb806c7f8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1534,7 +1534,7 @@ void Application::shootParticle() { // Caller is responsible for managing this EditableParticle ParticleEditHandle* Application::newParticleEditHandle(uint32_t id) { - ParticleEditHandle* particleEditHandle = new ParticleEditHandle(&_particleEditSender, _particles.getTree()); + ParticleEditHandle* particleEditHandle = new ParticleEditHandle(&_particleEditSender, _particles.getTree(), id); return particleEditHandle; } diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index f991074b94..4762a5e5de 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -74,55 +74,45 @@ void Hand::reset() { void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) { bool ballFromHand = Menu::getInstance()->isOptionChecked(MenuOption::BallFromHand); int handID = palm.getSixenseID(); + + bool grabButtonPressed = (palm.getControllerButtons() & BUTTON_FWD); + bool ballAlreadyInHand = _toyBallInHand[handID]; + glm::vec3 targetPosition = palm.getPosition() / (float)TREE_SCALE; float targetRadius = (TOY_BALL_RADIUS * 4.0f) / (float)TREE_SCALE; const Particle* closestParticle = Application::getInstance()->getParticles() ->getTree()->findClosestParticle(targetPosition, targetRadius); + //printf("simulateToyBall() handID:%d grabButtonPressed:%s ballAlreadyInHand:%s\n", + // handID, debug::valueOf(grabButtonPressed), debug::valueOf(ballAlreadyInHand)); + if (closestParticle) { - //printf("potentially caught... particle ID:%d\n", closestParticle->getID()); - - if (!_toyBallInHand[handID]) { - /*** - printf("particle ID:%d IN TARGET AND NOT IN HAND\n", closestParticle->getID()); - - // you can create a ParticleEditHandle by doing this... - ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID()); - - // reflect off the hand... - printf("particle ID:%d old velocity=%f,%f,%f\n", closestParticle->getID(), - closestParticle->getVelocity().x, closestParticle->getVelocity().y, closestParticle->getVelocity().z); - - glm::vec3 reflectNormal = glm::vec3(0,1,0); // palm.getNormal() - glm::vec3 newVelocity = glm::reflect(closestParticle->getVelocity(), reflectNormal); - - printf("particle ID:%d REFLECT velocity=%f,%f,%f\n", closestParticle->getID(), - newVelocity.x, newVelocity.y, newVelocity.z); - - //newVelocity += palm.getTipVelocity() / (float)TREE_SCALE; - //printf("particle ID:%d with TIP velocity=%f,%f,%f\n", closestParticle->getID(), newVelocity.x, newVelocity.y, newVelocity.z); - + //printf("potentially caught... handID:%d particle ID:%d grabButtonPressed:%s ballAlreadyInHand:%s\n", + // handID, closestParticle->getID(), debug::valueOf(grabButtonPressed), debug::valueOf(ballAlreadyInHand)); - printf("particle ID:%d OLD position=%f,%f,%f\n", closestParticle->getID(), - closestParticle->getPosition().x, closestParticle->getPosition().y, closestParticle->getPosition().z); - glm::vec3 newPosition = closestParticle->getPosition(); - - newPosition += newVelocity * 10.f; // move it as if it's already been moving in new direction - - printf("particle ID:%d NEW position=%f,%f,%f\n", closestParticle->getID(), - newPosition.x, newPosition.y, newPosition.z); - + // If I don't currently have a ball in my hand, then I can catch this closest particle + if (!ballAlreadyInHand && grabButtonPressed) { + //printf("caught... handID:%d particle ID:%d\n", handID, closestParticle->getID()); + ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID()); + glm::vec3 newPosition = targetPosition; + glm::vec3 newVelocity = NO_VELOCITY; + + // update the particle with it's new state... caughtParticle->updateParticle(newPosition, closestParticle->getRadius(), closestParticle->getXColor(), newVelocity, closestParticle->getGravity(), closestParticle->getDamping(), + IN_HAND, // we just grabbed it! closestParticle->getUpdateScript()); - - // but make sure you clean it up, when you're done - delete caughtParticle; - **/ + + // now tell our hand about us having caught it... + _toyBallInHand[handID] = true; + + //printf(">>>>>>> caught... handID:%d particle ID:%d _toyBallInHand[handID] = true\n", handID, closestParticle->getID()); + _ballParticleEditHandles[handID] = caughtParticle; + caughtParticle = NULL; } }