From 38d928fa4e0c7dfbee677ce8aa348cc03302fb99 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 13 Dec 2013 11:58:12 -0800 Subject: [PATCH 1/3] make balls for both hands, allow you to change color, remove red wire simulation --- interface/src/avatar/Hand.cpp | 112 +++++++++++++++---------------- interface/src/avatar/Hand.h | 10 +-- libraries/avatars/src/HandData.h | 1 + 3 files changed, 60 insertions(+), 63 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 69a339ef06..2c7b24b5c6 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -24,11 +24,20 @@ 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 = { 255, 255, 0 }; +const xColor TOY_BALL_ON_SERVER_COLOR[] = + { + { 255, 0, 0 }, + { 0, 255, 0 }, + { 0, 0, 255 }, + { 255, 255, 0 }, + { 0, 255, 255 }, + { 255, 0, 255 }, + }; Hand::Hand(Avatar* owningAvatar) : HandData((AvatarData*)owningAvatar), @@ -39,13 +48,14 @@ Hand::Hand(Avatar* owningAvatar) : _collisionCenter(0,0,0), _collisionAge(0), _collisionDuration(0), - _toyBallPosition(0), - _toyBallVelocity(0), - _toyBallInHand(false), - _hasToyBall(false), - _ballParticleEditHandle(NULL), _pitchUpdate(0) { + for (int i = 0; i < MAX_HANDS; i++) { + _toyBallInHand[i] = false; + _ballParticleEditHandles[i] = NULL; + _whichBallColor[i] = 0; + } + _lastControllerButtons = 0; } void Hand::init() { @@ -77,13 +87,25 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f // but make sure you clean it up, when you're done delete caughtParticle; } + int handID = palm.getSixenseID(); + + // If there's a ball in hand, and the user presses the skinny button, then change the color of the ball + int currentControllerButtons = palm.getControllerButtons(); + printf("currentControllerButtons=%d\n",currentControllerButtons); + + if (currentControllerButtons != _lastControllerButtons && (currentControllerButtons & BUTTON_0)) { + _whichBallColor[handID]++; + if (_whichBallColor[handID] >= sizeof(TOY_BALL_ON_SERVER_COLOR)/sizeof(TOY_BALL_ON_SERVER_COLOR[0])) { + _whichBallColor[handID] = 0; + } + } // Is the controller button being held down.... if (palm.getControllerButtons() & BUTTON_FWD) { // If grabbing toy ball, add forces to it. // If we don't currently have a ball in hand, then create it... - if (!_toyBallInHand) { + if (!_toyBallInHand[handID]) { // Test for whether close enough to catch and catch.... // isCaught is also used as "creating" a new ball... for now, this section is the @@ -92,75 +114,60 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f // If we didn't catch something, then create a new ball.... if (!isCaught) { - _toyBallInHand = true; - _hasToyBall = true; + _toyBallInHand[handID] = true; // create the ball, call MakeParticle, and use the resulting ParticleEditHandle to // manage the newly created particle. // Create a particle on the particle server - _ballParticleEditHandle = Application::getInstance()->makeParticle(fingerTipPosition / (float)TREE_SCALE, - TOY_BALL_RADIUS / (float) TREE_SCALE, - TOY_BALL_ON_SERVER_COLOR, - _toyBallVelocity / (float)TREE_SCALE, - NO_GRAVITY / (float) TREE_SCALE, - TOY_BALL_DAMPING, - TOY_BALL_DONT_DIE_SCRIPT); + _ballParticleEditHandles[handID] = Application::getInstance()->makeParticle( + fingerTipPosition / (float)TREE_SCALE, + 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); } - } - if (_toyBallInHand) { + } else { // Ball is in hand - _toyBallPosition = fingerTipPosition; - _toyBallVelocity = glm::vec3(0); - - _ballParticleEditHandle->updateParticle(fingerTipPosition / (float)TREE_SCALE, + _ballParticleEditHandles[handID]->updateParticle(fingerTipPosition / (float)TREE_SCALE, TOY_BALL_RADIUS / (float) TREE_SCALE, - TOY_BALL_ON_SERVER_COLOR, - _toyBallVelocity / (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); } } else { // If toy ball just released, add velocity to it! - if (_toyBallInHand) { + if (_toyBallInHand[handID]) { - _toyBallInHand = false; + _toyBallInHand[handID] = false; glm::vec3 handVelocity = palm.getRawVelocity(); glm::vec3 fingerTipVelocity = palm.getTipVelocity(); glm::quat avatarRotation = _owningAvatar->getOrientation(); - //printVector(avatarRotation * handVelocity); - _toyBallVelocity += avatarRotation * fingerTipVelocity; + glm::vec3 toyBallVelocity = avatarRotation * fingerTipVelocity; // ball is no longer in hand... - _ballParticleEditHandle->updateParticle(fingerTipPosition / (float)TREE_SCALE, + _ballParticleEditHandles[handID]->updateParticle(fingerTipPosition / (float)TREE_SCALE, TOY_BALL_RADIUS / (float) TREE_SCALE, - TOY_BALL_ON_SERVER_COLOR, - _toyBallVelocity / (float)TREE_SCALE, + TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]], + toyBallVelocity / (float)TREE_SCALE, TOY_BALL_GRAVITY / (float) TREE_SCALE, TOY_BALL_DAMPING, TOY_BALL_UPDATE_SCRIPT); // after releasing the ball, we free our ParticleEditHandle so we can't edit it further // note: deleting the edit handle doesn't effect the actual particle - delete _ballParticleEditHandle; - _ballParticleEditHandle = NULL; + delete _ballParticleEditHandles[handID]; + _ballParticleEditHandles[handID] = NULL; } } - // Simulate toy ball - _toyBallPosition += _toyBallVelocity * deltaTime; - if (!_toyBallInHand) { - _toyBallVelocity += TOY_BALL_GRAVITY * deltaTime; - } - if (_toyBallPosition.y < 0.f) { - _toyBallPosition.y = 0.f; - _toyBallVelocity.y *= -1.f; - } - - if (_hasToyBall) { - _toyBallVelocity -= (_toyBallVelocity * TOY_BALL_DAMPING) * deltaTime; - //printf("applying damping to TOY_BALL deltaTime=%f\n",deltaTime); + // remember the last pressed button state + if (currentControllerButtons != 0) { + _lastControllerButtons = currentControllerButtons; } } @@ -192,9 +199,7 @@ void Hand::simulate(float deltaTime, bool isMine) { FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger glm::vec3 fingerTipPosition = finger.getTipPosition(); - if (palm.getSixenseID() == TOY_BALL_HAND) { - simulateToyBall(palm, fingerTipPosition, deltaTime); - } + simulateToyBall(palm, fingerTipPosition, deltaTime); if (palm.getControllerButtons() & BUTTON_1) { if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) { @@ -376,15 +381,6 @@ void Hand::render( bool isMine) { renderLeapHands(); } - // Render toy ball - if (isMine && _hasToyBall) { - glPushMatrix(); - glColor3f(1, 0, 0); - glTranslatef(_toyBallPosition.x, _toyBallPosition.y, _toyBallPosition.z); - glutWireSphere(TOY_BALL_RADIUS, 10, 10); - glPopMatrix(); - } - if (isMine) { // If hand/voxel collision has happened, render a little expanding sphere if (_collisionAge > 0.f) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 1d3dc7b724..a6f3014797 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -96,11 +96,11 @@ private: void simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime); - glm::vec3 _toyBallPosition; - glm::vec3 _toyBallVelocity; - bool _toyBallInHand; - bool _hasToyBall; - ParticleEditHandle* _ballParticleEditHandle; + #define MAX_HANDS 2 + bool _toyBallInHand[MAX_HANDS]; + int _whichBallColor[MAX_HANDS]; + ParticleEditHandle* _ballParticleEditHandles[MAX_HANDS]; + int _lastControllerButtons; float _pitchUpdate; diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index 2677ffdba8..6fba4d5e2c 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -26,6 +26,7 @@ const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND; const int LEAPID_INVALID = -1; const int SIXENSEID_INVALID = -1; +const int BUTTON_0 = 1; // the skinny button between 1 and 2 const int BUTTON_1 = 32; const int BUTTON_2 = 64; const int BUTTON_3 = 8; From aaf4ff7dfcc7f9a19658e02510b55da3b55eec04 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 13 Dec 2013 14:30:29 -0800 Subject: [PATCH 2/3] added lifetime to particles --- interface/src/avatar/Hand.cpp | 3 +- libraries/particles/src/Particle.cpp | 35 ++++++++++++++++--- libraries/particles/src/Particle.h | 11 ++++-- libraries/particles/src/ParticleTree.cpp | 2 ++ .../particles/src/ParticleTreeElement.cpp | 5 +++ libraries/shared/src/SharedUtil.h | 1 + 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 2c7b24b5c6..b718729fcb 100755 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -79,7 +79,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f ->getTree()->findClosestParticle(targetPosition, targetRadius); if (closestParticle) { - printf("potentially caught... particle ID:%d\n", closestParticle->getID()); + //printf("potentially caught... particle ID:%d\n", closestParticle->getID()); // you can create a ParticleEditHandle by doing this... ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID()); @@ -91,7 +91,6 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f // If there's a ball in hand, and the user presses the skinny button, then change the color of the ball int currentControllerButtons = palm.getControllerButtons(); - printf("currentControllerButtons=%d\n",currentControllerButtons); if (currentControllerButtons != _lastControllerButtons && (currentControllerButtons & BUTTON_0)) { _whichBallColor[handID]++; diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 9f945999b6..25695c5f81 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -35,6 +35,7 @@ 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) { if (id == NEW_PARTICLE) { + _created = usecTimestampNow(); _id = _nextID; _nextID++; } else { @@ -58,6 +59,9 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { //printf("Particle::appendParticleData()... getID()=%d\n", getID()); + if (success) { + success = packetData->appendValue(getCreated()); + } if (success) { success = packetData->appendValue(getLastUpdated()); } @@ -90,7 +94,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { } int Particle::expectedBytes() { - int expectedBytes = sizeof(uint32_t) + sizeof(uint64_t) + sizeof(float) + + 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); return expectedBytes; @@ -106,6 +110,11 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(_id); bytesRead += sizeof(_id); + // created + memcpy(&_created, dataAt, sizeof(_created)); + dataAt += sizeof(_created); + bytesRead += sizeof(_created); + // lastupdated memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated)); dataAt += sizeof(_lastUpdated); @@ -191,6 +200,11 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe newParticle._newlyCreated = false; } + // created + memcpy(&newParticle._created, dataAt, sizeof(newParticle._created)); + dataAt += sizeof(newParticle._created); + processedBytes += sizeof(newParticle._created); + // lastUpdated memcpy(&newParticle._lastUpdated, dataAt, sizeof(newParticle._lastUpdated)); dataAt += sizeof(newParticle._lastUpdated); @@ -248,6 +262,7 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe void Particle::debugDump() const { printf("Particle id :%u\n", _id); + printf(" created:%llu\n", _created); printf(" last updated:%llu\n", _lastUpdated); printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z); printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z); @@ -280,7 +295,8 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, sizeOut += lengthOfOctcode; // Now add our edit content details... - + uint64_t created = usecTimestampNow(); + // id memcpy(copyAt, &details[i].id, sizeof(details[i].id)); copyAt += sizeof(details[i].id); @@ -292,8 +308,15 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, memcpy(copyAt, &details[i].creatorTokenID, sizeof(details[i].creatorTokenID)); copyAt += sizeof(details[i].creatorTokenID); sizeOut += sizeof(details[i].creatorTokenID); - } + } else { + created = 0; + } + // created + memcpy(copyAt, &created, sizeof(created)); + copyAt += sizeof(created); + sizeOut += sizeof(created); + // lastUpdated memcpy(copyAt, &details[i].lastUpdated, sizeof(details[i].lastUpdated)); copyAt += sizeof(details[i].lastUpdated); @@ -363,7 +386,11 @@ void Particle::update() { // calculate our default shouldDie state... then allow script to change it if it wants... float velocityScalar = glm::length(getVelocity()); const float STILL_MOVING = 0.05 / TREE_SCALE; - setShouldDie(velocityScalar < STILL_MOVING); + bool isStillMoving = (velocityScalar > STILL_MOVING); + const uint64_t REALLY_OLD = 30 * 1000 * 1000; + bool isReallyOld = (getLifetime() > REALLY_OLD); + bool shouldDie = !isStillMoving && isReallyOld; + setShouldDie(shouldDie); runScript(); // allow the javascript to alter our state diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 0fed2c80f0..8e754fee39 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -62,6 +62,8 @@ public: const glm::vec3& getVelocity() const { return _velocity; } const glm::vec3& getGravity() const { return _gravity; } float getDamping() const { return _damping; } + uint64_t getCreated() const { return _created; } + uint64_t getLifetime() const { return usecTimestampNow() - _created; } uint64_t getLastUpdated() const { return _lastUpdated; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } @@ -83,6 +85,7 @@ public: void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } void setUpdateScript(QString updateScript) { _updateScript = updateScript; } void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } + void setCreated(uint64_t created) { _created = created; } bool appendParticleData(OctreePacketData* packetData) const; int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); @@ -106,6 +109,7 @@ protected: float _radius; glm::vec3 _velocity; uint64_t _lastUpdated; + uint64_t _created; uint32_t _id; static uint32_t _nextID; bool _shouldDie; @@ -129,8 +133,11 @@ public slots: glm::vec3 getGravity() const { return _particle->getGravity(); } float getDamping() const { return _particle->getDamping(); } float getRadius() const { return _particle->getRadius(); } - bool setShouldDie() { return _particle->getShouldDie(); } - + bool getShouldDie() { return _particle->getShouldDie(); } + float getCreated() const { return ((float)_particle->getCreated() / (float)USECS_PER_SECOND); } + float getLifetime() const { return ((float)_particle->getLifetime() / (float)USECS_PER_SECOND); } + + void setPosition(glm::vec3 value) { _particle->setPosition(value); } void setVelocity(glm::vec3 value) { _particle->setVelocity(value); } void setGravity(glm::vec3 value) { _particle->setGravity(value); } diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index c1fd6d8bbb..2a0b261bef 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -110,7 +110,9 @@ bool ParticleTree::findNearPointOperation(OctreeElement* element, void* extraDat const Particle* ParticleTree::findClosestParticle(glm::vec3 position, float targetRadius) { // First, look for the existing particle in the tree.. FindNearPointArgs args = { position, targetRadius, false, NULL, FLT_MAX }; + lockForRead(); recurseTreeWithOperation(findNearPointOperation, &args); + unlock(); return args.closestParticle; } diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index df234269d1..6e45f7b62b 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -118,7 +118,12 @@ bool ParticleTreeElement::updateParticle(const Particle& particle) { uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { if (_particles[i].getID() == particle.getID()) { + uint64_t actuallyCreated = particle.getCreated(); + if (!particle.isNewlyCreated()) { + actuallyCreated = _particles[i].getCreated(); + } _particles[i] = particle; + _particles[i].setCreated(actuallyCreated); return true; } } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 8124822b46..cd6444624f 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -52,6 +52,7 @@ static const float METER = 1.0f; static const float DECIMETER = 0.1f; static const float CENTIMETER = 0.01f; static const float MILLIIMETER = 0.001f; +static const uint64_t USECS_PER_SECOND = 1000 * 1000; uint64_t usecTimestamp(const timeval *time); uint64_t usecTimestampNow(); From 41fdbcb30f9ce19a52b80f26a3d4f8e73e472af2 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 13 Dec 2013 15:25:03 -0800 Subject: [PATCH 3/3] Fix for crash that Philip was seeing. --- interface/src/avatar/SkeletonModel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b8c500d3bd..b7af35c632 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -127,6 +127,9 @@ bool operator<(const IndexValue& firstIndex, const IndexValue& secondIndex) { void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJointIndices, const QVector& fingertipJointIndices, PalmData& palm) { + if (jointIndex == -1) { + return; + } const FBXGeometry& geometry = _geometry->getFBXGeometry(); setJointPosition(jointIndex, palm.getPosition()); float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;