mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 17:24:31 +02:00
Merge remote-tracking branch 'upstream/master' into slaps
This commit is contained in:
commit
14d198f930
25 changed files with 321 additions and 99 deletions
|
@ -1523,7 +1523,7 @@ void Application::shootParticle() {
|
||||||
QString updateScript("");
|
QString updateScript("");
|
||||||
|
|
||||||
ParticleEditHandle* particleEditHandle = makeParticle(position / (float)TREE_SCALE, radius, color,
|
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
|
// 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
|
// and use it for editing later. But we don't care about that for "shooting" and therefore we just
|
||||||
|
@ -1534,16 +1534,16 @@ void Application::shootParticle() {
|
||||||
|
|
||||||
// Caller is responsible for managing this EditableParticle
|
// Caller is responsible for managing this EditableParticle
|
||||||
ParticleEditHandle* Application::newParticleEditHandle(uint32_t id) {
|
ParticleEditHandle* Application::newParticleEditHandle(uint32_t id) {
|
||||||
ParticleEditHandle* particleEditHandle = new ParticleEditHandle(&_particleEditSender, _particles.getTree());
|
ParticleEditHandle* particleEditHandle = new ParticleEditHandle(&_particleEditSender, _particles.getTree(), id);
|
||||||
return particleEditHandle;
|
return particleEditHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caller is responsible for managing this EditableParticle
|
// Caller is responsible for managing this EditableParticle
|
||||||
ParticleEditHandle* Application::makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
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* particleEditHandle = newParticleEditHandle();
|
||||||
particleEditHandle->createParticle(position, radius, color, velocity, gravity, damping, updateScript);
|
particleEditHandle->createParticle(position, radius, color, velocity, gravity, damping, inHand, updateScript);
|
||||||
return particleEditHandle;
|
return particleEditHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1858,7 +1858,7 @@ void Application::init() {
|
||||||
_particles.init();
|
_particles.init();
|
||||||
_particles.setViewFrustum(getViewFrustum());
|
_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.init(_glWidget->width(), _glWidget->height());
|
||||||
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0);
|
_palette.addAction(Menu::getInstance()->getActionForOption(MenuOption::VoxelAddMode), 0, 0);
|
||||||
|
|
|
@ -125,7 +125,7 @@ public:
|
||||||
void shootParticle(); // shoots a particle in the direction you're looking
|
void shootParticle(); // shoots a particle in the direction you're looking
|
||||||
ParticleEditHandle* newParticleEditHandle(uint32_t id = NEW_PARTICLE);
|
ParticleEditHandle* newParticleEditHandle(uint32_t id = NEW_PARTICLE);
|
||||||
ParticleEditHandle* makeParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
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,
|
void makeVoxel(glm::vec3 position,
|
||||||
float scale,
|
float scale,
|
||||||
|
|
|
@ -23,11 +23,9 @@ const float FINGERTIP_VOXEL_SIZE = 0.05;
|
||||||
const int TOY_BALL_HAND = 1;
|
const int TOY_BALL_HAND = 1;
|
||||||
const float TOY_BALL_RADIUS = 0.05f;
|
const float TOY_BALL_RADIUS = 0.05f;
|
||||||
const float TOY_BALL_DAMPING = 0.99f;
|
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 NO_VELOCITY = glm::vec3(0,0,0);
|
||||||
const glm::vec3 TOY_BALL_GRAVITY = glm::vec3(0,-1,0);
|
const glm::vec3 TOY_BALL_GRAVITY = glm::vec3(0,-1,0);
|
||||||
const QString TOY_BALL_UPDATE_SCRIPT("");
|
const QString TOY_BALL_UPDATE_SCRIPT("");
|
||||||
const QString TOY_BALL_DONT_DIE_SCRIPT("Particle.setShouldDie(false);");
|
|
||||||
const float PALM_COLLISION_RADIUS = 0.03f;
|
const float PALM_COLLISION_RADIUS = 0.03f;
|
||||||
const xColor TOY_BALL_ON_SERVER_COLOR[] =
|
const xColor TOY_BALL_ON_SERVER_COLOR[] =
|
||||||
{
|
{
|
||||||
|
@ -76,53 +74,45 @@ void Hand::reset() {
|
||||||
void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) {
|
void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) {
|
||||||
bool ballFromHand = Menu::getInstance()->isOptionChecked(MenuOption::BallFromHand);
|
bool ballFromHand = Menu::getInstance()->isOptionChecked(MenuOption::BallFromHand);
|
||||||
int handID = palm.getSixenseID();
|
int handID = palm.getSixenseID();
|
||||||
|
|
||||||
|
bool grabButtonPressed = (palm.getControllerButtons() & BUTTON_FWD);
|
||||||
|
bool ballAlreadyInHand = _toyBallInHand[handID];
|
||||||
|
|
||||||
glm::vec3 targetPosition = palm.getPosition() / (float)TREE_SCALE;
|
glm::vec3 targetPosition = palm.getPosition() / (float)TREE_SCALE;
|
||||||
float targetRadius = (TOY_BALL_RADIUS * 4.0f) / (float)TREE_SCALE;
|
float targetRadius = (TOY_BALL_RADIUS * 4.0f) / (float)TREE_SCALE;
|
||||||
const Particle* closestParticle = Application::getInstance()->getParticles()
|
const Particle* closestParticle = Application::getInstance()->getParticles()
|
||||||
->getTree()->findClosestParticle(targetPosition, targetRadius);
|
->getTree()->findClosestParticle(targetPosition, targetRadius);
|
||||||
|
|
||||||
|
//printf("simulateToyBall() handID:%d grabButtonPressed:%s ballAlreadyInHand:%s\n",
|
||||||
|
// handID, debug::valueOf(grabButtonPressed), debug::valueOf(ballAlreadyInHand));
|
||||||
|
|
||||||
if (closestParticle) {
|
if (closestParticle) {
|
||||||
//printf("potentially caught... particle ID:%d\n", closestParticle->getID());
|
//printf("potentially caught... handID:%d particle ID:%d grabButtonPressed:%s ballAlreadyInHand:%s\n",
|
||||||
|
// handID, closestParticle->getID(), debug::valueOf(grabButtonPressed), debug::valueOf(ballAlreadyInHand));
|
||||||
if (!_toyBallInHand[handID]) {
|
|
||||||
printf("particle ID:%d 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 newVelocity = glm::reflect(closestParticle->getVelocity(), palm.getNormal());
|
|
||||||
|
|
||||||
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("particle ID:%d OLD position=%f,%f,%f\n", closestParticle->getID(),
|
// If I don't currently have a ball in my hand, then I can catch this closest particle
|
||||||
closestParticle->getPosition().x, closestParticle->getPosition().y, closestParticle->getPosition().z);
|
if (!ballAlreadyInHand && grabButtonPressed) {
|
||||||
glm::vec3 newPosition = closestParticle->getPosition();
|
//printf("caught... handID:%d particle ID:%d\n", handID, closestParticle->getID());
|
||||||
|
ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID());
|
||||||
newPosition += newVelocity; // move it as if it's already been moving in new direction
|
glm::vec3 newPosition = targetPosition;
|
||||||
|
glm::vec3 newVelocity = NO_VELOCITY;
|
||||||
printf("particle ID:%d NEW position=%f,%f,%f\n", closestParticle->getID(),
|
|
||||||
newPosition.x, newPosition.y, newPosition.z);
|
// update the particle with it's new state...
|
||||||
|
|
||||||
caughtParticle->updateParticle(newPosition,
|
caughtParticle->updateParticle(newPosition,
|
||||||
closestParticle->getRadius(),
|
closestParticle->getRadius(),
|
||||||
closestParticle->getXColor(),
|
closestParticle->getXColor(),
|
||||||
newVelocity,
|
newVelocity,
|
||||||
closestParticle->getGravity(),
|
closestParticle->getGravity(),
|
||||||
closestParticle->getDamping(),
|
closestParticle->getDamping(),
|
||||||
|
IN_HAND, // we just grabbed it!
|
||||||
closestParticle->getUpdateScript());
|
closestParticle->getUpdateScript());
|
||||||
|
|
||||||
// but make sure you clean it up, when you're done
|
// now tell our hand about us having caught it...
|
||||||
delete caughtParticle;
|
_toyBallInHand[handID] = true;
|
||||||
|
|
||||||
|
//printf(">>>>>>> caught... handID:%d particle ID:%d _toyBallInHand[handID] = true\n", handID, closestParticle->getID());
|
||||||
|
_ballParticleEditHandles[handID] = caughtParticle;
|
||||||
|
caughtParticle = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,9 +149,10 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
||||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||||
NO_VELOCITY / (float)TREE_SCALE,
|
NO_VELOCITY / (float)TREE_SCALE,
|
||||||
NO_GRAVITY / (float) TREE_SCALE,
|
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||||
TOY_BALL_DAMPING,
|
TOY_BALL_DAMPING,
|
||||||
TOY_BALL_DONT_DIE_SCRIPT);
|
IN_HAND,
|
||||||
|
TOY_BALL_UPDATE_SCRIPT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Ball is in hand
|
// Ball is in hand
|
||||||
|
@ -170,9 +161,10 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
||||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||||
NO_VELOCITY / (float)TREE_SCALE,
|
NO_VELOCITY / (float)TREE_SCALE,
|
||||||
NO_GRAVITY / (float) TREE_SCALE,
|
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||||
TOY_BALL_DAMPING,
|
TOY_BALL_DAMPING,
|
||||||
TOY_BALL_DONT_DIE_SCRIPT);
|
IN_HAND,
|
||||||
|
TOY_BALL_UPDATE_SCRIPT);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If toy ball just released, add velocity to it!
|
// If toy ball just released, add velocity to it!
|
||||||
|
@ -191,7 +183,8 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
||||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||||
toyBallVelocity / (float)TREE_SCALE,
|
toyBallVelocity / (float)TREE_SCALE,
|
||||||
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||||
TOY_BALL_DAMPING,
|
TOY_BALL_DAMPING,
|
||||||
|
NOT_IN_HAND,
|
||||||
TOY_BALL_UPDATE_SCRIPT);
|
TOY_BALL_UPDATE_SCRIPT);
|
||||||
|
|
||||||
// after releasing the ball, we free our ParticleEditHandle so we can't edit it further
|
// after releasing the ball, we free our ParticleEditHandle so we can't edit it further
|
||||||
|
@ -521,6 +514,10 @@ void Hand::renderLeapHands() {
|
||||||
}
|
}
|
||||||
glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z);
|
glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z);
|
||||||
glutWireSphere(targetRadius, 20.0f, 20.0f);
|
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();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
// Get the drag distance to move
|
// Get the drag distance to move
|
||||||
glm::vec3 getAndResetGrabDelta();
|
glm::vec3 getAndResetGrabDelta();
|
||||||
glm::vec3 getAndResetGrabDeltaVelocity();
|
glm::vec3 getAndResetGrabDeltaVelocity();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
// disallow copies of the Hand, copy of owning Avatar is disallowed too
|
||||||
Hand(const Hand&);
|
Hand(const Hand&);
|
||||||
|
|
|
@ -765,3 +765,4 @@ void Head::updateHairPhysics(float deltaTime) {
|
||||||
_hairTuft[t].update(deltaTime);
|
_hairTuft[t].update(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,9 @@ public:
|
||||||
|
|
||||||
const QUuid& getLeaderUUID() const { return _leaderUUID; }
|
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 setHeadData(HeadData* headData) { _headData = headData; }
|
||||||
void setHandData(HandData* handData) { _handData = handData; }
|
void setHandData(HandData* handData) { _handData = handData; }
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "HandData.h"
|
#include "HandData.h"
|
||||||
#include "AvatarData.h"
|
#include "AvatarData.h"
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
#include <GeometryUtil.h>
|
||||||
|
|
||||||
|
|
||||||
// When converting between fixed and float, use this as the radix.
|
// When converting between fixed and float, use this as the radix.
|
||||||
|
@ -224,6 +225,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) {
|
void FingerData::setTrailLength(unsigned int length) {
|
||||||
_tipTrailPositions.resize(length);
|
_tipTrailPositions.resize(length);
|
||||||
_tipTrailCurrentStartIndex = 0;
|
_tipTrailCurrentStartIndex = 0;
|
||||||
|
@ -266,3 +286,4 @@ const glm::vec3& FingerData::getTrailPosition(int index) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,15 @@ public:
|
||||||
int encodeRemoteData(unsigned char* destinationBuffer);
|
int encodeRemoteData(unsigned char* destinationBuffer);
|
||||||
int decodeRemoteData(unsigned char* sourceBuffer);
|
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;
|
friend class AvatarData;
|
||||||
protected:
|
protected:
|
||||||
glm::vec3 _basePosition; // Hands are placed relative to this
|
glm::vec3 _basePosition; // Hands are placed relative to this
|
||||||
|
@ -124,6 +133,7 @@ public:
|
||||||
PalmData(HandData* owningHandData);
|
PalmData(HandData* owningHandData);
|
||||||
glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); }
|
glm::vec3 getPosition() const { return _owningHandData->leapPositionToWorldPosition(_rawPosition); }
|
||||||
glm::vec3 getNormal() const { return _owningHandData->leapDirectionToWorldDirection(_rawNormal); }
|
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& getRawPosition() const { return _rawPosition; }
|
||||||
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
const glm::vec3& getRawNormal() const { return _rawNormal; }
|
||||||
|
|
|
@ -44,3 +44,11 @@ void HeadData::addLean(float sideways, float forwards) {
|
||||||
_leanSideways += sideways;
|
_leanSideways += sideways;
|
||||||
_leanForward += forwards;
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,13 @@ public:
|
||||||
void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; }
|
void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; }
|
||||||
|
|
||||||
friend class AvatarData;
|
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:
|
protected:
|
||||||
float _yaw;
|
float _yaw;
|
||||||
|
|
|
@ -1299,6 +1299,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* node,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::readFromSVOFile(const char* fileName) {
|
bool Octree::readFromSVOFile(const char* fileName) {
|
||||||
|
bool fileOk = false;
|
||||||
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
|
std::ifstream file(fileName, std::ios::in|std::ios::binary|std::ios::ate);
|
||||||
if(file.is_open()) {
|
if(file.is_open()) {
|
||||||
emit importSize(1.0f, 1.0f, 1.0f);
|
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];
|
unsigned char* entireFile = new unsigned char[fileLength];
|
||||||
file.read((char*)entireFile, fileLength);
|
file.read((char*)entireFile, fileLength);
|
||||||
bool wantImportProgress = true;
|
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;
|
delete[] entireFile;
|
||||||
|
|
||||||
emit importProgress(100);
|
emit importProgress(100);
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return fileOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::writeToSVOFile(const char* fileName, OctreeElement* node) {
|
void Octree::writeToSVOFile(const char* fileName, OctreeElement* node) {
|
||||||
|
@ -1332,7 +1361,16 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* node) {
|
||||||
|
|
||||||
if(file.is_open()) {
|
if(file.is_open()) {
|
||||||
qDebug("saving to file %s...\n", fileName);
|
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;
|
OctreeElementBag nodeBag;
|
||||||
// If we were given a specific node, start from there, otherwise start from root
|
// If we were given a specific node, start from there, otherwise start from root
|
||||||
if (node) {
|
if (node) {
|
||||||
|
|
|
@ -183,6 +183,8 @@ public:
|
||||||
|
|
||||||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
// 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
|
// 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 bool handlesEditPacketType(PACKET_TYPE packetType) const { return false; }
|
||||||
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||||
unsigned char* editData, int maxLength, Node* senderNode) { return 0; }
|
unsigned char* editData, int maxLength, Node* senderNode) { return 0; }
|
||||||
|
|
|
@ -305,6 +305,15 @@ bool OctreePacketData::appendValue(const glm::vec3& value) {
|
||||||
return success;
|
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) {
|
bool OctreePacketData::appendPosition(const glm::vec3& value) {
|
||||||
const unsigned char* data = (const unsigned char*)&value;
|
const unsigned char* data = (const unsigned char*)&value;
|
||||||
int length = sizeof(value);
|
int length = sizeof(value);
|
||||||
|
|
|
@ -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
|
/// 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);
|
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
|
/// 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);
|
bool appendPosition(const glm::vec3& value);
|
||||||
|
|
||||||
|
|
|
@ -18,22 +18,23 @@
|
||||||
uint32_t Particle::_nextID = 0;
|
uint32_t Particle::_nextID = 0;
|
||||||
|
|
||||||
|
|
||||||
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||||
float damping, glm::vec3 gravity, QString updateScript, uint32_t id) {
|
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() {
|
Particle::Particle() {
|
||||||
rgbColor noColor = { 0, 0, 0 };
|
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() {
|
Particle::~Particle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity,
|
||||||
float damping, glm::vec3 gravity, QString updateScript, uint32_t id) {
|
float damping, bool inHand, QString updateScript, uint32_t id) {
|
||||||
if (id == NEW_PARTICLE) {
|
if (id == NEW_PARTICLE) {
|
||||||
_created = usecTimestampNow();
|
_created = usecTimestampNow();
|
||||||
_id = _nextID;
|
_id = _nextID;
|
||||||
|
@ -50,6 +51,7 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3
|
||||||
_damping = damping;
|
_damping = damping;
|
||||||
_gravity = gravity;
|
_gravity = gravity;
|
||||||
_updateScript = updateScript;
|
_updateScript = updateScript;
|
||||||
|
_inHand = inHand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,6 +85,9 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
||||||
if (success) {
|
if (success) {
|
||||||
success = packetData->appendValue(getDamping());
|
success = packetData->appendValue(getDamping());
|
||||||
}
|
}
|
||||||
|
if (success) {
|
||||||
|
success = packetData->appendValue(getInHand());
|
||||||
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
uint16_t scriptLength = _updateScript.size() + 1; // include NULL
|
uint16_t scriptLength = _updateScript.size() + 1; // include NULL
|
||||||
success = packetData->appendValue(scriptLength);
|
success = packetData->appendValue(scriptLength);
|
||||||
|
@ -96,7 +101,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
||||||
int Particle::expectedBytes() {
|
int Particle::expectedBytes() {
|
||||||
int expectedBytes = sizeof(uint32_t) + sizeof(uint64_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(rgbColor) + sizeof(glm::vec3) +
|
||||||
sizeof(glm::vec3) + sizeof(float);
|
sizeof(glm::vec3) + sizeof(float) + sizeof(bool);
|
||||||
return expectedBytes;
|
return expectedBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +155,11 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
dataAt += sizeof(_damping);
|
dataAt += sizeof(_damping);
|
||||||
bytesRead += sizeof(_damping);
|
bytesRead += sizeof(_damping);
|
||||||
|
|
||||||
|
// inHand
|
||||||
|
memcpy(&_inHand, dataAt, sizeof(_inHand));
|
||||||
|
dataAt += sizeof(_inHand);
|
||||||
|
bytesRead += sizeof(_inHand);
|
||||||
|
|
||||||
// script
|
// script
|
||||||
uint16_t scriptLength;
|
uint16_t scriptLength;
|
||||||
memcpy(&scriptLength, dataAt, sizeof(scriptLength));
|
memcpy(&scriptLength, dataAt, sizeof(scriptLength));
|
||||||
|
@ -240,6 +250,11 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
||||||
dataAt += sizeof(newParticle._damping);
|
dataAt += sizeof(newParticle._damping);
|
||||||
processedBytes += sizeof(newParticle._damping);
|
processedBytes += sizeof(newParticle._damping);
|
||||||
|
|
||||||
|
// inHand
|
||||||
|
memcpy(&newParticle._inHand, dataAt, sizeof(newParticle._inHand));
|
||||||
|
dataAt += sizeof(newParticle._inHand);
|
||||||
|
processedBytes += sizeof(newParticle._inHand);
|
||||||
|
|
||||||
// script
|
// script
|
||||||
uint16_t scriptLength;
|
uint16_t scriptLength;
|
||||||
memcpy(&scriptLength, dataAt, sizeof(scriptLength));
|
memcpy(&scriptLength, dataAt, sizeof(scriptLength));
|
||||||
|
@ -352,6 +367,11 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
||||||
copyAt += sizeof(details[i].damping);
|
copyAt += sizeof(details[i].damping);
|
||||||
sizeOut += 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
|
// script
|
||||||
uint16_t scriptLength = details[i].updateScript.size() + 1;
|
uint16_t scriptLength = details[i].updateScript.size() + 1;
|
||||||
memcpy(copyAt, &scriptLength, sizeof(scriptLength));
|
memcpy(copyAt, &scriptLength, sizeof(scriptLength));
|
||||||
|
@ -389,27 +409,31 @@ void Particle::update() {
|
||||||
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
bool isStillMoving = (velocityScalar > STILL_MOVING);
|
||||||
const uint64_t REALLY_OLD = 30 * 1000 * 1000;
|
const uint64_t REALLY_OLD = 30 * 1000 * 1000;
|
||||||
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
bool isReallyOld = (getLifetime() > REALLY_OLD);
|
||||||
bool shouldDie = !isStillMoving && isReallyOld;
|
bool isInHand = getInHand();
|
||||||
|
bool shouldDie = !isInHand && !isStillMoving && isReallyOld;
|
||||||
setShouldDie(shouldDie);
|
setShouldDie(shouldDie);
|
||||||
|
|
||||||
runScript(); // allow the javascript to alter our state
|
runScript(); // allow the javascript to alter our state
|
||||||
|
|
||||||
_position += _velocity * timeElapsed;
|
|
||||||
|
|
||||||
// handle bounces off the ground...
|
// If the ball is in hand, it doesn't move or have gravity effect it
|
||||||
if (_position.y <= 0) {
|
if (!isInHand) {
|
||||||
_velocity = _velocity * glm::vec3(1,-1,1);
|
_position += _velocity * timeElapsed;
|
||||||
_position.y = 0;
|
|
||||||
|
// 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;
|
_lastUpdated = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
glm::vec3 velocity;
|
glm::vec3 velocity;
|
||||||
glm::vec3 gravity;
|
glm::vec3 gravity;
|
||||||
float damping;
|
float damping;
|
||||||
|
bool inHand;
|
||||||
QString updateScript;
|
QString updateScript;
|
||||||
uint32_t creatorTokenID;
|
uint32_t creatorTokenID;
|
||||||
};
|
};
|
||||||
|
@ -39,21 +40,24 @@ public:
|
||||||
const float DEFAULT_DAMPING = 0.99f;
|
const float DEFAULT_DAMPING = 0.99f;
|
||||||
const glm::vec3 DEFAULT_GRAVITY(0, (-9.8f / TREE_SCALE), 0);
|
const glm::vec3 DEFAULT_GRAVITY(0, (-9.8f / TREE_SCALE), 0);
|
||||||
const QString DEFAULT_SCRIPT("");
|
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 {
|
class Particle {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Particle();
|
Particle();
|
||||||
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
||||||
float damping = DEFAULT_DAMPING, glm::vec3 gravity = DEFAULT_GRAVITY, QString updateScript = DEFAULT_SCRIPT,
|
glm::vec3 gravity = DEFAULT_GRAVITY, float damping = DEFAULT_DAMPING, bool inHand = NOT_IN_HAND,
|
||||||
uint32_t id = NEW_PARTICLE);
|
QString updateScript = DEFAULT_SCRIPT, uint32_t id = NEW_PARTICLE);
|
||||||
|
|
||||||
/// creates an NEW particle from an PACKET_TYPE_PARTICLE_ADD_OR_EDIT edit data buffer
|
/// 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);
|
static Particle fromEditPacket(unsigned char* data, int length, int& processedBytes);
|
||||||
|
|
||||||
virtual ~Particle();
|
virtual ~Particle();
|
||||||
virtual void init(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity,
|
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 glm::vec3& getPosition() const { return _position; }
|
||||||
const rgbColor& getColor() const { return _color; }
|
const rgbColor& getColor() const { return _color; }
|
||||||
|
@ -61,6 +65,7 @@ public:
|
||||||
float getRadius() const { return _radius; }
|
float getRadius() const { return _radius; }
|
||||||
const glm::vec3& getVelocity() const { return _velocity; }
|
const glm::vec3& getVelocity() const { return _velocity; }
|
||||||
const glm::vec3& getGravity() const { return _gravity; }
|
const glm::vec3& getGravity() const { return _gravity; }
|
||||||
|
bool getInHand() const { return _inHand; }
|
||||||
float getDamping() const { return _damping; }
|
float getDamping() const { return _damping; }
|
||||||
uint64_t getCreated() const { return _created; }
|
uint64_t getCreated() const { return _created; }
|
||||||
uint64_t getLifetime() const { return usecTimestampNow() - _created; }
|
uint64_t getLifetime() const { return usecTimestampNow() - _created; }
|
||||||
|
@ -81,6 +86,7 @@ public:
|
||||||
}
|
}
|
||||||
void setRadius(float value) { _radius = value; }
|
void setRadius(float value) { _radius = value; }
|
||||||
void setGravity(const glm::vec3& value) { _gravity = value; }
|
void setGravity(const glm::vec3& value) { _gravity = value; }
|
||||||
|
void setInHand(bool inHand) { _inHand = inHand; }
|
||||||
void setDamping(float value) { _damping = value; }
|
void setDamping(float value) { _damping = value; }
|
||||||
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
|
void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; }
|
||||||
void setUpdateScript(QString updateScript) { _updateScript = updateScript; }
|
void setUpdateScript(QString updateScript) { _updateScript = updateScript; }
|
||||||
|
@ -116,6 +122,7 @@ protected:
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
float _damping;
|
float _damping;
|
||||||
QString _updateScript;
|
QString _updateScript;
|
||||||
|
bool _inHand;
|
||||||
|
|
||||||
uint32_t _creatorTokenID;
|
uint32_t _creatorTokenID;
|
||||||
bool _newlyCreated;
|
bool _newlyCreated;
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
#include <AbstractAudioInterface.h>
|
#include <AbstractAudioInterface.h>
|
||||||
#include <VoxelTree.h>
|
#include <VoxelTree.h>
|
||||||
|
#include <AvatarData.h>
|
||||||
|
#include <HeadData.h>
|
||||||
|
#include <HandData.h>
|
||||||
|
|
||||||
#include "Particle.h"
|
#include "Particle.h"
|
||||||
#include "ParticleCollisionSystem.h"
|
#include "ParticleCollisionSystem.h"
|
||||||
|
@ -17,16 +20,17 @@
|
||||||
#include "ParticleTree.h"
|
#include "ParticleTree.h"
|
||||||
|
|
||||||
ParticleCollisionSystem::ParticleCollisionSystem(ParticleEditPacketSender* packetSender,
|
ParticleCollisionSystem::ParticleCollisionSystem(ParticleEditPacketSender* packetSender,
|
||||||
ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio) {
|
ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio, AvatarData* selfAvatar) {
|
||||||
init(packetSender, particles, voxels, audio);
|
init(packetSender, particles, voxels, audio, selfAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleCollisionSystem::init(ParticleEditPacketSender* packetSender,
|
void ParticleCollisionSystem::init(ParticleEditPacketSender* packetSender,
|
||||||
ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio) {
|
ParticleTree* particles, VoxelTree* voxels, AbstractAudioInterface* audio, AvatarData* selfAvatar) {
|
||||||
_packetSender = packetSender;
|
_packetSender = packetSender;
|
||||||
_particles = particles;
|
_particles = particles;
|
||||||
_voxels = voxels;
|
_voxels = voxels;
|
||||||
_audio = audio;
|
_audio = audio;
|
||||||
|
_selfAvatar = selfAvatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleCollisionSystem::~ParticleCollisionSystem() {
|
ParticleCollisionSystem::~ParticleCollisionSystem() {
|
||||||
|
@ -59,6 +63,7 @@ void ParticleCollisionSystem::update() {
|
||||||
void ParticleCollisionSystem::checkParticle(Particle* particle) {
|
void ParticleCollisionSystem::checkParticle(Particle* particle) {
|
||||||
updateCollisionWithVoxels(particle);
|
updateCollisionWithVoxels(particle);
|
||||||
updateCollisionWithParticles(particle);
|
updateCollisionWithParticles(particle);
|
||||||
|
updateCollisionWithAvatars(particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
|
@ -91,8 +96,81 @@ 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;
|
||||||
|
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,
|
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
|
// 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.
|
// to outside the colliding surface. Velocity will be modified according to elasticity.
|
||||||
|
@ -112,6 +190,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::
|
||||||
if (penetrationLength > EPSILON) {
|
if (penetrationLength > EPSILON) {
|
||||||
glm::vec3 direction = penetration / penetrationLength;
|
glm::vec3 direction = penetration / penetrationLength;
|
||||||
velocity -= glm::dot(velocity, direction) * direction * elasticity;
|
velocity -= glm::dot(velocity, direction) * direction * elasticity;
|
||||||
|
velocity += addedVelocity;
|
||||||
velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f);
|
velocity *= glm::clamp(1.f - damping, 0.0f, 1.0f);
|
||||||
if (glm::length(velocity) < HALTING_VELOCITY) {
|
if (glm::length(velocity) < HALTING_VELOCITY) {
|
||||||
// If moving really slowly after a collision, and not applying forces, stop altogether
|
// If moving really slowly after a collision, and not applying forces, stop altogether
|
||||||
|
@ -120,7 +199,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::
|
||||||
}
|
}
|
||||||
ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID());
|
ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID());
|
||||||
particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity,
|
particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity,
|
||||||
particle->getGravity(), particle->getDamping(), particle->getUpdateScript());
|
particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getUpdateScript());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,18 +22,22 @@
|
||||||
#include "Particle.h"
|
#include "Particle.h"
|
||||||
|
|
||||||
class AbstractAudioInterface;
|
class AbstractAudioInterface;
|
||||||
|
class AvatarData;
|
||||||
class ParticleEditPacketSender;
|
class ParticleEditPacketSender;
|
||||||
class ParticleTree;
|
class ParticleTree;
|
||||||
class VoxelTree;
|
class VoxelTree;
|
||||||
|
|
||||||
|
const glm::vec3 NO_ADDED_VELOCITY = glm::vec3(0);
|
||||||
|
|
||||||
class ParticleCollisionSystem {
|
class ParticleCollisionSystem {
|
||||||
public:
|
public:
|
||||||
ParticleCollisionSystem(ParticleEditPacketSender* packetSender = NULL, ParticleTree* particles = NULL,
|
ParticleCollisionSystem(ParticleEditPacketSender* packetSender = NULL, ParticleTree* particles = NULL,
|
||||||
VoxelTree* voxels = NULL,
|
VoxelTree* voxels = NULL,
|
||||||
AbstractAudioInterface* audio = NULL);
|
AbstractAudioInterface* audio = NULL,
|
||||||
|
AvatarData* selfAvatar = NULL);
|
||||||
|
|
||||||
void init(ParticleEditPacketSender* packetSender, ParticleTree* particles, VoxelTree* voxels,
|
void init(ParticleEditPacketSender* packetSender, ParticleTree* particles, VoxelTree* voxels,
|
||||||
AbstractAudioInterface* audio = NULL);
|
AbstractAudioInterface* audio = NULL, AvatarData* selfAvatar = NULL);
|
||||||
|
|
||||||
~ParticleCollisionSystem();
|
~ParticleCollisionSystem();
|
||||||
|
|
||||||
|
@ -41,7 +45,9 @@ public:
|
||||||
void checkParticle(Particle* particle);
|
void checkParticle(Particle* particle);
|
||||||
void updateCollisionWithVoxels(Particle* particle);
|
void updateCollisionWithVoxels(Particle* particle);
|
||||||
void updateCollisionWithParticles(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);
|
void updateCollisionSound(Particle* particle, const glm::vec3 &penetration, float frequency);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -52,6 +58,7 @@ private:
|
||||||
ParticleTree* _particles;
|
ParticleTree* _particles;
|
||||||
VoxelTree* _voxels;
|
VoxelTree* _voxels;
|
||||||
AbstractAudioInterface* _audio;
|
AbstractAudioInterface* _audio;
|
||||||
|
AvatarData* _selfAvatar;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__ParticleCollisionSystem__) */
|
#endif /* defined(__hifi__ParticleCollisionSystem__) */
|
|
@ -41,12 +41,12 @@ ParticleEditHandle::~ParticleEditHandle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
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
|
// setup a ParticleDetail struct with the data
|
||||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
||||||
position, radius, {color.red, color.green, color.blue },
|
position, radius, {color.red, color.green, color.blue },
|
||||||
velocity, gravity, damping, updateScript, _creatorTokenID };
|
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||||
|
|
||||||
// queue the packet
|
// queue the packet
|
||||||
_packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &addParticleDetail);
|
_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,
|
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()) {
|
if (!isKnownID()) {
|
||||||
return false; // not allowed until we know the id
|
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
|
// setup a ParticleDetail struct with the data
|
||||||
ParticleDetail newParticleDetail = { _id, usecTimestampNow(),
|
ParticleDetail newParticleDetail = { _id, usecTimestampNow(),
|
||||||
position, radius, {color.red, color.green, color.blue },
|
position, radius, {color.red, color.green, color.blue },
|
||||||
velocity, gravity, damping, updateScript, _creatorTokenID };
|
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||||
|
|
||||||
// queue the packet
|
// queue the packet
|
||||||
_packetSender->queueParticleEditMessages(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, 1, &newParticleDetail);
|
_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 we have a local tree, also update it...
|
||||||
if (_localTree) {
|
if (_localTree) {
|
||||||
rgbColor rcolor = {color.red, color.green, color.blue };
|
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);
|
_localTree->storeParticle(tempParticle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ public:
|
||||||
bool isKnownID() const { return _isKnownID; }
|
bool isKnownID() const { return _isKnownID; }
|
||||||
|
|
||||||
void createParticle(glm::vec3 position, float radius, xColor color, glm::vec3 velocity,
|
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,
|
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);
|
static void handleAddResponse(unsigned char* packetData , int packetLength);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -15,7 +15,7 @@ void ParticleScriptingInterface::queueParticleAdd(PACKET_TYPE addPacketType, Par
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius,
|
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
|
// The application will keep track of creatorTokenID
|
||||||
uint32_t creatorTokenID = _nextCreatorTokenID;
|
uint32_t creatorTokenID = _nextCreatorTokenID;
|
||||||
|
@ -24,7 +24,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl
|
||||||
// setup a ParticleDetail struct with the data
|
// setup a ParticleDetail struct with the data
|
||||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
||||||
position, radius, {color.red, color.green, color.blue }, velocity,
|
position, radius, {color.red, color.green, color.blue }, velocity,
|
||||||
gravity, damping, updateScript, creatorTokenID };
|
gravity, damping, inHand, updateScript, creatorTokenID };
|
||||||
|
|
||||||
// queue the packet
|
// queue the packet
|
||||||
queueParticleAdd(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail);
|
queueParticleAdd(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail);
|
||||||
|
|
|
@ -27,7 +27,7 @@ public slots:
|
||||||
/// queues the creation of a Particle which will be sent by calling process on the PacketSender
|
/// queues the creation of a Particle which will be sent by calling process on the PacketSender
|
||||||
/// returns the creatorTokenID for the newly created particle
|
/// returns the creatorTokenID for the newly created particle
|
||||||
unsigned int queueParticleAdd(glm::vec3 position, float radius,
|
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:
|
private:
|
||||||
void queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails);
|
void queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails);
|
||||||
|
|
|
@ -36,6 +36,8 @@ public:
|
||||||
|
|
||||||
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
|
// 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
|
// 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 bool handlesEditPacketType(PACKET_TYPE packetType) const;
|
||||||
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||||
unsigned char* editData, int maxLength, Node* senderNode);
|
unsigned char* editData, int maxLength, Node* senderNode);
|
||||||
|
|
|
@ -51,7 +51,10 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case PACKET_TYPE_PARTICLE_ADD_OR_EDIT:
|
case PACKET_TYPE_PARTICLE_ADD_OR_EDIT:
|
||||||
return 1;
|
return 2;
|
||||||
|
|
||||||
|
case PACKET_TYPE_PARTICLE_DATA:
|
||||||
|
return 2;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
|
|
||||||
void readCodeColorBufferToTree(const unsigned char* codeColorBuffer, bool destructive = false);
|
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 bool handlesEditPacketType(PACKET_TYPE packetType) const;
|
||||||
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||||
unsigned char* editData, int maxLength, Node* senderNode);
|
unsigned char* editData, int maxLength, Node* senderNode);
|
||||||
|
|
Loading…
Reference in a new issue