bucky balls!

This commit is contained in:
Philip Rosedale 2014-01-01 10:45:06 -08:00
parent e3a77ef139
commit d1e9c25d00
3 changed files with 168 additions and 2 deletions

View file

@ -19,6 +19,13 @@
using namespace std;
const float RANGE_BBALLS = 0.5f;
const float SIZE_BBALLS = 0.02f;
const float CORNER_BBALLS = 2.f;
const float GRAVITY_BBALLS = -0.25f;
const float BBALLS_ATTRACTION_DISTANCE = SIZE_BBALLS / 2.f;
const float FINGERTIP_COLLISION_RADIUS = SIZE_BBALLS / 2.f;
const float FINGERTIP_VOXEL_SIZE = 0.05;
const int TOY_BALL_HAND = 1;
const float TOY_BALL_RADIUS = 0.05f;
@ -40,6 +47,7 @@ const xColor TOY_BALL_ON_SERVER_COLOR[] =
{ 255, 0, 255 },
};
Hand::Hand(Avatar* owningAvatar) :
HandData((AvatarData*)owningAvatar),
@ -67,6 +75,35 @@ Hand::Hand(Avatar* owningAvatar) :
// the throw and catch sounds should not loopback, we'll play them locally
_throwInjector.setShouldLoopback(false);
_catchInjector.setShouldLoopback(false);
// Make some bucky balls for the avatar
_bballIsGrabbed[0] = 0;
_bballIsGrabbed[1] = 0;
if (_owningAvatar && _owningAvatar->getOwningNode() == NULL) {
printf("Creating buckyballs...\n");
for (int i = 0; i < NUM_BBALLS; i++) {
_bballPosition[i] = CORNER_BBALLS + randVector() * RANGE_BBALLS;
int element = (rand() % 3);
if (element == 0) {
_bballRadius[i] = SIZE_BBALLS;
_bballColor[i] = glm::vec3(0.13f, 0.55f, 0.13f);
} else if (element == 1) {
_bballRadius[i] = SIZE_BBALLS / 2.f;
_bballColor[i] = glm::vec3(0.64f, 0.16f, 0.16f);
} else {
_bballRadius[i] = SIZE_BBALLS * 2.f;
_bballColor[i] = glm::vec3(0.31f, 0.58f, 0.80f);
}
_bballColliding[i] = 0.f;
_bballElement[i] = element;
if (_bballElement[i] != 1) {
_bballVelocity[i] = randVector() * 0.3f;
} else {
_bballVelocity[i] = glm::vec3(0);
}
}
}
}
void Hand::init() {
@ -82,6 +119,111 @@ void Hand::init() {
void Hand::reset() {
}
void Hand::grabBuckyBalls(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) {
float penetration;
glm::vec3 diff;
if (palm.getControllerButtons() & BUTTON_FWD) {
if (!_bballIsGrabbed[palm.getSixenseID()]) {
// Look for a ball to grab
for (int i = 0; i < NUM_BBALLS; i++) {
diff = _bballPosition[i] - fingerTipPosition;
penetration = glm::length(diff) - (_bballRadius[i] + FINGERTIP_COLLISION_RADIUS);
if (penetration < 0.f) {
_bballIsGrabbed[palm.getSixenseID()] = i;
}
}
}
if (_bballIsGrabbed[palm.getSixenseID()]) {
// If ball being grabbed, move with finger
diff = _bballPosition[_bballIsGrabbed[palm.getSixenseID()]] - fingerTipPosition;
penetration = glm::length(diff) - (_bballRadius[_bballIsGrabbed[palm.getSixenseID()]] + FINGERTIP_COLLISION_RADIUS);
_bballPosition[_bballIsGrabbed[palm.getSixenseID()]] -= glm::normalize(diff) * penetration;
glm::vec3 fingerTipVelocity = _owningAvatar->getOrientation() * palm.getTipVelocity();
if (_bballElement[_bballIsGrabbed[palm.getSixenseID()]] != 1) {
_bballVelocity[_bballIsGrabbed[palm.getSixenseID()]] = fingerTipVelocity;
}
_bballPosition[_bballIsGrabbed[palm.getSixenseID()]] = fingerTipPosition;
_bballColliding[_bballIsGrabbed[palm.getSixenseID()]] = 1.f;
}
} else {
_bballIsGrabbed[palm.getSixenseID()] = 0;
}
}
const float COLLISION_BLEND_RATE = 0.5f;
const float ATTRACTION_BLEND_RATE = 0.9f;
const float ATTRACTION_VELOCITY_BLEND_RATE = 0.10f;
void Hand::simulateBuckyBalls(float deltaTime) {
// Look for collisions
for (int i = 0; i < NUM_BBALLS; i++) {
if (_bballElement[i] != 1) {
// For 'interacting' elements, look for other balls to interact with
for (int j = 0; j < NUM_BBALLS; j++) {
if (i != j) {
glm::vec3 diff = _bballPosition[i] - _bballPosition[j];
float penetration = glm::length(diff) - (_bballRadius[i] + _bballRadius[j]);
if (penetration < 0.f) {
// Colliding - move away and transfer velocity
_bballPosition[i] -= glm::normalize(diff) * penetration * COLLISION_BLEND_RATE;
if (glm::dot(_bballVelocity[i], diff) < 0.f) {
_bballVelocity[i] = _bballVelocity[i] * (1.f - COLLISION_BLEND_RATE) +
glm::reflect(_bballVelocity[i], glm::normalize(diff)) * COLLISION_BLEND_RATE;
}
}
else if ((penetration > EPSILON) && (penetration < BBALLS_ATTRACTION_DISTANCE)) {
// If they get close to each other, bring them together with magnetic force
_bballPosition[i] -= glm::normalize(diff) * penetration * ATTRACTION_BLEND_RATE;
// Also make their velocities more similar
_bballVelocity[i] = _bballVelocity[i] * (1.f - ATTRACTION_VELOCITY_BLEND_RATE) + _bballVelocity[j] * ATTRACTION_VELOCITY_BLEND_RATE;
}
}
}
}
}
// Update position and bounce on walls
const float BBALL_CONTINUOUS_DAMPING = 0.00f;
const float BBALL_WALL_COLLISION_DAMPING = 0.2f;
for (int i = 0; i < NUM_BBALLS; i++) {
_bballPosition[i] += _bballVelocity[i] * deltaTime;
if (_bballElement[i] != 1) {
_bballVelocity[i].y += GRAVITY_BBALLS * deltaTime;
}
_bballVelocity[i] -= _bballVelocity[i] * BBALL_CONTINUOUS_DAMPING * deltaTime;
for (int j = 0; j < 3; j++) {
if ((_bballPosition[i][j] + _bballRadius[i]) > (CORNER_BBALLS + RANGE_BBALLS)) {
_bballPosition[i][j] = (CORNER_BBALLS + RANGE_BBALLS) - _bballRadius[i];
_bballVelocity[i][j] *= -(1.f - BBALL_WALL_COLLISION_DAMPING);
}
if ((_bballPosition[i][j] - _bballRadius[i]) < (CORNER_BBALLS -RANGE_BBALLS)) {
_bballPosition[i][j] = (CORNER_BBALLS -RANGE_BBALLS) + _bballRadius[i];
_bballVelocity[i][j] *= -(1.f - BBALL_WALL_COLLISION_DAMPING);
}
}
_bballColliding[i] *= 0.8f;
if (_bballColliding[i] < 0.1f) {
_bballColliding[i] = 0.f;
}
}
}
void Hand::renderBuckyBalls() {
for (int i = 0; i < NUM_BBALLS; i++) {
if (_bballColliding[i] > 0.f) {
glColor3f(_bballColor[i].x * 1.15f, _bballColor[i].y * 1.15f, _bballColor[i].z * 1.15f);
} else {
glColor3f(_bballColor[i].x, _bballColor[i].y, _bballColor[i].z);
}
glPushMatrix();
glTranslatef(_bballPosition[i].x, _bballPosition[i].y, _bballPosition[i].z);
glutSolidSphere(_bballRadius[i], 15, 15);
//glutSolidCube(_bballRadius[i] * 2.f);
glPopMatrix();
}
}
void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime) {
Application* app = Application::getInstance();
ParticleTree* particles = app->getParticles()->getTree();
@ -256,6 +398,10 @@ void Hand::simulate(float deltaTime, bool isMine) {
_collisionAge += deltaTime;
}
if (isMine) {
simulateBuckyBalls(deltaTime);
}
const glm::vec3 leapHandsOffsetFromFace(0.0, -0.2, -0.3); // place the hand in front of the face where we can see it
Head& head = _owningAvatar->getHead();
@ -279,6 +425,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
glm::vec3 fingerTipPosition = finger.getTipPosition();
simulateToyBall(palm, fingerTipPosition, deltaTime);
grabBuckyBalls(palm, fingerTipPosition, deltaTime);
if (palm.getControllerButtons() & BUTTON_4) {
_grabDelta += palm.getRawVelocity() * deltaTime;
@ -453,7 +600,7 @@ void Hand::calculateGeometry() {
for (size_t f = 0; f < palm.getNumFingers(); ++f) {
FingerData& finger = palm.getFingers()[f];
if (finger.isActive()) {
const float standardBallRadius = 0.010f;
const float standardBallRadius = FINGERTIP_COLLISION_RADIUS;
_leapFingerTipBalls.resize(_leapFingerTipBalls.size() + 1);
HandBall& ball = _leapFingerTipBalls.back();
ball.rotation = _baseOrientation;
@ -493,6 +640,11 @@ void Hand::calculateGeometry() {
void Hand::render(bool isMine) {
_renderAlpha = 1.0;
if (isMine) {
renderBuckyBalls();
}
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
for (int i = 0; i < getNumPalms(); i++) {
PalmData& palm = getPalms()[i];

View file

@ -31,6 +31,8 @@
class Avatar;
class ProgramObject;
const int NUM_BBALLS = 200;
class Hand : public HandData {
public:
@ -99,7 +101,10 @@ private:
void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime);
void simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime);
void grabBuckyBalls(PalmData& palm, const glm::vec3& fingerTipPosition, float deltaTime);
void simulateBuckyBalls(float deltaTime);
void renderBuckyBalls();
#define MAX_HANDS 2
bool _toyBallInHand[MAX_HANDS];
@ -116,6 +121,15 @@ private:
AudioInjector _throwInjector;
AudioInjector _catchInjector;
glm::vec3 _bballPosition[NUM_BBALLS];
glm::vec3 _bballVelocity[NUM_BBALLS];
glm::vec3 _bballColor[NUM_BBALLS];
float _bballRadius[NUM_BBALLS];
float _bballColliding[NUM_BBALLS];
int _bballElement[NUM_BBALLS];
int _bballIsGrabbed[2];
};
#endif

View file

@ -102,7 +102,7 @@ void SixenseManager::update(float deltaTime) {
FingerData finger(palm, &hand);
finger.setActive(true);
finger.setRawRootPosition(position);
const float FINGER_LENGTH = 300.0f; // Millimeters
const float FINGER_LENGTH = 150.0f; // Millimeters
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
finger.setRawTipPosition(position + rotation * FINGER_VECTOR);