merge of windows-build

Conflicts:
	domain-server/src/DomainServer.cpp
	interface/src/Application.cpp
	interface/src/Menu.cpp
	libraries/avatars/src/AvatarData.h
	libraries/shared/src/NodeList.h
This commit is contained in:
Andrew Meadows 2014-01-16 09:00:13 -08:00
commit 1266ffd0ca
23 changed files with 414 additions and 250 deletions

View file

@ -417,7 +417,7 @@ int DomainServer::civetwebRequestHandler(struct mg_connection *connection) {
mg_printf(connection, "%s", RESPONSE_200);
// we have a valid UUID and node - kill the node that has this assignment
NodeList::getInstance()->killNodeWithUUID(deleteUUID);
QMetaObject::invokeMethod(NodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID));
// successfully processed request
return 1;

View file

@ -1432,9 +1432,11 @@ void Application::terminate() {
_voxelHideShowThread.terminate();
_voxelEditSender.terminate();
_particleEditSender.terminate();
if (_persistThread) {
_persistThread->terminate();
_persistThread = NULL;
}
}
static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) {
// record the packet for stats-tracking
@ -2276,6 +2278,7 @@ void Application::updateMouseVoxels(float deltaTime, glm::vec3& mouseRayOrigin,
}
}
void Application::updateHandAndTouch(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateHandAndTouch()");
@ -2319,9 +2322,11 @@ void Application::updateThreads(float deltaTime) {
_voxelHideShowThread.threadRoutine();
_voxelEditSender.threadRoutine();
_particleEditSender.threadRoutine();
if (_persistThread) {
_persistThread->threadRoutine();
}
}
}
void Application::updateMyAvatarSimulation(float deltaTime) {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@ -4395,10 +4400,13 @@ void Application::updateLocalOctreeCache(bool firstTime) {
QString localVoxelCacheFileName = getLocalVoxelCacheFileName();
const int LOCAL_CACHE_PERSIST_INTERVAL = 1000 * 10; // every 10 seconds
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableLocalVoxelCache)) {
_persistThread = new OctreePersistThread(_voxels.getTree(),
localVoxelCacheFileName.toLocal8Bit().constData(),LOCAL_CACHE_PERSIST_INTERVAL);
qDebug() << "updateLocalOctreeCache()... localVoxelCacheFileName=" << localVoxelCacheFileName;
}
if (_persistThread) {
_voxels.beginLoadingLocalVoxelCache(); // while local voxels are importing, don't do individual node VBO updates

View file

@ -311,6 +311,7 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::AmbientOcclusion);
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DontFadeOnVoxelServerChanges);
addActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::LodTools, Qt::SHIFT | Qt::Key_L, this, SLOT(lodTools()));
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::DisableLocalVoxelCache);
QMenu* voxelProtoOptionsMenu = voxelOptionsMenu->addMenu("Voxel Server Protocol Options");
@ -402,7 +403,6 @@ Menu::Menu() :
SLOT(setLEDTrackingOn(bool)));
#endif //def HAVE_LIBVPX
addDisabledActionAndSeparator(developerMenu, "Testing");
QMenu* timingMenu = developerMenu->addMenu("Timing and Statistics Tools");

View file

@ -171,6 +171,7 @@ namespace MenuOption {
const QString DestructiveAddVoxel = "Create Voxel is Destructive";
const QString DisableColorVoxels = "Disable Colored Voxels";
const QString DisableDeltaSending = "Disable Delta Sending";
const QString DisableLocalVoxelCache = "Disable Local Voxel Cache";
const QString DisableLowRes = "Disable Lower Resolution While Moving";
const QString DisplayFrustum = "Display Frustum";
const QString DisplayLeapHands = "Display Leap Hands";

View file

@ -355,6 +355,55 @@ bool Avatar::findSpherePenetration(const glm::vec3& penetratorCenter, float pene
return false;
}
bool Avatar::findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) {
// TODO: provide an early exit using bounding sphere of entire avatar
const HandData* handData = getHandData();
if (handData) {
int jointIndices[2] = { _skeletonModel.getLeftHandJointIndex(), _skeletonModel.getRightHandJointIndex() };
for (int i = 0; i < 2; i++) {
const PalmData* palm = handData->getPalm(i);
if (palm) {
// create a disk collision proxy where the hand is
glm::vec3 fingerAxis(0.f);
for (size_t f = 0; f < palm->getNumFingers(); ++f) {
const FingerData& finger = (palm->getFingers())[f];
if (finger.isActive()) {
// compute finger axis
glm::vec3 fingerTip = finger.getTipPosition();
glm::vec3 fingerRoot = finger.getRootPosition();
fingerAxis = glm::normalize(fingerTip - fingerRoot);
break;
}
}
glm::vec3 handPosition;
if (i == 0) {
_skeletonModel.getLeftHandPosition(handPosition);
}
else {
_skeletonModel.getRightHandPosition(handPosition);
}
glm::vec3 diskCenter = handPosition + HAND_PADDLE_OFFSET * fingerAxis;
glm::vec3 diskNormal = palm->getNormal();
// collide against the disk
if (findSphereDiskPenetration(sphereCenter, sphereRadius,
diskCenter, HAND_PADDLE_RADIUS, diskNormal, collision._penetration)) {
collision._addedVelocity = palm->getVelocity();
return true;
}
}
}
}
if (_skeletonModel.findSpherePenetration(sphereCenter, sphereRadius, collision._penetration)) {
collision._penetration /= (float)(TREE_SCALE);
collision._addedVelocity = getVelocity();
return true;
}
return false;
}
int Avatar::parseData(unsigned char* sourceBuffer, int numBytes) {
// change in position implies movement
glm::vec3 oldPosition = _position;

View file

@ -167,6 +167,13 @@ public:
bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
glm::vec3& penetration, int skeletonSkipIndex = -1) const;
/// Checks for collision between the a sphere and the avatar.
/// \param collisionCenter the center of the penetration test sphere
/// \param collisionRadius the radius of the penetration test sphere
/// \param collision[out] the details of the collision point
/// \return whether or not the sphere collided
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
virtual int parseData(unsigned char* sourceBuffer, int numBytes);
static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);

View file

@ -616,23 +616,37 @@ void Hand::renderLeapHands(bool isMine) {
}
}
// Draw the palms
for (size_t i = 0; i < getNumPalms(); ++i) {
PalmData& palm = getPalms()[i];
if (palm.isActive()) {
const float palmThickness = 0.02f;
if (palm.getIsCollidingWithPalm()) {
glColor4f(1, 0, 0, 0.50);
} else {
glColor4f(handColor.r, handColor.g, handColor.b, 0.25);
}
glm::vec3 tip = palm.getPosition();
glm::vec3 root = palm.getPosition() + palm.getNormal() * palmThickness;
const float radiusA = 0.05f;
const float radiusB = 0.03f;
Avatar::renderJointConnectingCone(root, tip, radiusA, radiusB);
// Draw the hand paddles
int MAX_NUM_PADDLES = 2; // one for left and one for right
glColor4f(handColor.r, handColor.g, handColor.b, 0.3f);
for (int i = 0; i < MAX_NUM_PADDLES; i++) {
const PalmData* palm = getPalm(i);
if (palm) {
// compute finger axis
glm::vec3 fingerAxis(0.f);
for (size_t f = 0; f < palm->getNumFingers(); ++f) {
const FingerData& finger = (palm->getFingers())[f];
if (finger.isActive()) {
glm::vec3 fingerTip = finger.getTipPosition();
glm::vec3 fingerRoot = finger.getRootPosition();
fingerAxis = glm::normalize(fingerTip - fingerRoot);
break;
}
}
// compute paddle position
glm::vec3 handPosition;
if (i == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
_owningAvatar->getSkeletonModel().getLeftHandPosition(handPosition);
} else if (i == SIXENSE_CONTROLLER_ID_RIGHT_HAND) {
_owningAvatar->getSkeletonModel().getRightHandPosition(handPosition);
}
glm::vec3 tip = handPosition + HAND_PADDLE_OFFSET * fingerAxis;
glm::vec3 root = tip + palm->getNormal() * HAND_PADDLE_THICKNESS;
// render a very shallow cone as the paddle
Avatar::renderJointConnectingCone(root, tip, HAND_PADDLE_RADIUS, 0.f);
}
}
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);

View file

@ -30,6 +30,10 @@
class Avatar;
class ProgramObject;
const float HAND_PADDLE_OFFSET = 0.1f;
const float HAND_PADDLE_THICKNESS = 0.05f;
const float HAND_PADDLE_RADIUS = 0.15f;
class Hand : public HandData {
public:
Hand(Avatar* owningAvatar);

View file

@ -8,6 +8,8 @@
#include <glm/gtx/transform.hpp>
#include <HandData.h>
#include "Application.h"
#include "Avatar.h"
#include "Menu.h"

View file

@ -9,7 +9,6 @@
#ifndef __interface__SkeletonModel__
#define __interface__SkeletonModel__
#include <HandData.h>
#include "renderer/Model.h"

View file

@ -67,6 +67,9 @@ void OculusManager::connect() {
_scaleLocation = _program.uniformLocation("scale");
_scaleInLocation = _program.uniformLocation("scaleIn");
_hmdWarpParamLocation = _program.uniformLocation("hmdWarpParam");
} else {
_deviceManager.Clear();
System::Destroy();
}
#endif
}

View file

@ -489,6 +489,22 @@ bool Model::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePos
getJointPosition(geometry.rightEyeJointIndex, secondEyePosition);
}
bool Model::getLeftHandPosition(glm::vec3& position) const {
return getJointPosition(getLeftHandJointIndex(), position);
}
bool Model::getLeftHandRotation(glm::quat& rotation) const {
return getJointRotation(getLeftHandJointIndex(), rotation);
}
bool Model::getRightHandPosition(glm::vec3& position) const {
return getJointPosition(getRightHandJointIndex(), position);
}
bool Model::getRightHandRotation(glm::quat& rotation) const {
return getJointRotation(getRightHandJointIndex(), rotation);
}
bool Model::setLeftHandPosition(const glm::vec3& position) {
return setJointPosition(getLeftHandJointIndex(), position);
}

View file

@ -82,6 +82,22 @@ public:
/// \return whether or not both eye meshes were found
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
/// Retrieve the position of the left hand
/// \return true whether or not the position was found
bool getLeftHandPosition(glm::vec3& position) const;
/// Retrieve the rotation of the left hand
/// \return true whether or not the rotation was found
bool getLeftHandRotation(glm::quat& rotation) const;
/// Retrieve the position of the right hand
/// \return true whether or not the position was found
bool getRightHandPosition(glm::vec3& position) const;
/// Retrieve the rotation of the right hand
/// \return true whether or not the rotation was found
bool getRightHandRotation(glm::quat& rotation) const;
/// Sets the position of the left hand using inverse kinematics.
/// \return whether or not the left hand joint was found
bool setLeftHandPosition(const glm::vec3& position);

View file

@ -24,7 +24,8 @@ bool Controller::computeStars(unsigned numStars, unsigned seed) {
this->retile(numStars, _tileResolution);
qDebug() << "Total time to generate stars: " << ((usecTimestampNow() - usecTimestamp(&startTime)) / 1000) << "msec";
qDebug() << "Total time to retile and generate stars: "
<< ((usecTimestampNow() - usecTimestamp(&startTime)) / 1000) << "msec";
return true;
}

View file

@ -33,9 +33,10 @@ typedef unsigned long long uint64_t;
#include <QtCore/QUuid>
#include <QtCore/QVariantMap>
#include <CollisionInfo.h>
#include <RegisteredMetaTypes.h>
#include <NodeData.h>
#include "HeadData.h"
#include "HandData.h"
@ -131,6 +132,10 @@ public:
virtual bool findSpherePenetration(const glm::vec3& penetratorCenter, float penetratorRadius,
glm::vec3& penetration, int skeletonSkipIndex = -1) const { return false; }
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision) {
return false;
}
protected:
QUuid _uuid;

View file

@ -38,8 +38,17 @@ PalmData& HandData::addNewPalm() {
return _palms.back();
}
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1;
const PalmData* HandData::getPalm(int sixSenseID) const {
// the palms are not necessarily added in left-right order,
// so we have to search for the right SixSenseID
for (int i = 0; i < _palms.size(); i++) {
const PalmData* palm = &(_palms[i]);
if (palm->getSixenseID() == sixSenseID) {
return palm->isActive() ? palm : NULL;
}
}
return NULL;
}
void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const {
leftPalmIndex = -1;

View file

@ -35,6 +35,9 @@ const int BUTTON_FWD = 128;
const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1;
class HandData {
public:
HandData(AvatarData* owningAvatar);
@ -55,6 +58,7 @@ public:
std::vector<PalmData>& getPalms() { return _palms; }
const std::vector<PalmData>& getPalms() const { return _palms; }
const PalmData* getPalm(int sixSenseID) const;
size_t getNumPalms() const { return _palms.size(); }
PalmData& addNewPalm();

View file

@ -11,6 +11,7 @@
#include <AbstractAudioInterface.h>
#include <VoxelTree.h>
#include <AvatarData.h>
#include <CollisionInfo.h>
#include <HeadData.h>
#include <HandData.h>
@ -137,15 +138,14 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
// particles that are in hand, don't collide with other avatar parts
// particles that are in hand, don't collide with avatars
if (particle->getInHand()) {
return;
}
//printf("updateCollisionWithAvatars()...\n");
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
float radius = particle->getRadius() * (float)(TREE_SCALE);
const float ELASTICITY = 0.4f;
const float ELASTICITY = 0.95f;
const float DAMPING = 0.0f;
const float COLLISION_FREQUENCY = 0.5f;
glm::vec3 penetration;
@ -154,77 +154,40 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
// 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();
// TODO: combine hand and collision check into one. Note: would need to supply
// CollisionInfo class rather than just vec3 (penetration) so we can get back
// added velocity.
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
// apply a hard collision when ball collides with hand
penetration /= (float)(TREE_SCALE);
updateCollisionSound(particle, penetration, 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;
CollisionInfo collision;
if (avatar->findSphereCollision(center, radius, collision)) {
if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) {
// only collide when particle and collision point are moving toward each other
collision._penetration /= (float)(TREE_SCALE);
collision._addedVelocity /= (float)(TREE_SCALE);
updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY);
applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity);
}
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
// apply hard collision when particle collides with avatar
penetration /= (float)(TREE_SCALE);
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
glm::vec3 addedVelocity = avatar->getVelocity();
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
}
}
// loop through all the other avatars for potential interactions...
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
//qDebug() << "updateCollisionWithAvatars()... node:" << *node << "\n";
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
AvatarData* avatar = static_cast<AvatarData*>(node->getLinkedData());
//printf("updateCollisionWithAvatars()...avatar=%p\n", avatar);
// check hands...
const HandData* handData = avatar->getHandData();
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
// apply a hard collision when ball collides with hand
penetration /= (float)(TREE_SCALE);
updateCollisionSound(particle, penetration, 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;
CollisionInfo collision;
if (avatar->findSphereCollision(center, radius, collision)) {
if (glm::dot(particle->getVelocity(), collision._addedVelocity) < 0.f) {
// only collide when particle and collision point are moving toward each other
collision._penetration /= (float)(TREE_SCALE);
collision._addedVelocity /= (float)(TREE_SCALE);
updateCollisionSound(particle, collision._penetration, COLLISION_FREQUENCY);
applyHardCollision(particle, collision._penetration, ELASTICITY, DAMPING, collision._addedVelocity);
}
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
penetration /= (float)(TREE_SCALE);
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
glm::vec3 addedVelocity = avatar->getVelocity();
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
}
}
}
}
// TODO: convert applyHardCollision() to take a CollisionInfo& instead of penetration + addedVelocity
void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::vec3& penetration,
float elasticity, float damping, const glm::vec3& addedVelocity) {
//

View file

@ -0,0 +1,26 @@
//
// CollisionInfo.h
// hifi
//
// Created by Andrew Meadows on 2014.01.13
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__CollisionInfo__
#define __hifi__CollisionInfo__
#include <glm/glm.hpp>
class CollisionInfo {
public:
CollisionInfo() : _penetration(0.f), _addedVelocity(0.f) { }
~CollisionInfo() {}
//glm::vec3 _point;
//glm::vec3 _normal;
glm::vec3 _penetration;
glm::vec3 _addedVelocity;
};
#endif /* defined(__hifi__CollisionInfo__) */

View file

@ -114,6 +114,30 @@ bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadiu
return false;
}
bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius,
const glm::vec3& diskCenter, float diskRadius, const glm::vec3& diskNormal,
glm::vec3& penetration) {
glm::vec3 localCenter = sphereCenter - diskCenter;
float verticalDistance = glm::dot(localCenter, diskNormal);
if (abs(verticalDistance) < sphereRadius) {
// sphere hit the plane, but does it hit the disk?
// Note: this algorithm ignores edge hits.
glm::vec3 verticalOffset = verticalDistance * diskNormal;
if (glm::length(localCenter - verticalOffset) < diskRadius) {
// yes, hit the disk
penetration = (sphereRadius - abs(verticalDistance)) * diskNormal;
if (verticalDistance < 0.f) {
// hit the backside of the disk, so negate penetration vector
penetration *= -1.f;
}
return true;
}
}
return false;
}
bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius,
const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration) {
if (findSphereCapsulePenetration(sphereCenter, sphereRadius,

View file

@ -47,6 +47,17 @@ bool findSphereCapsuleConePenetration(const glm::vec3& sphereCenter, float spher
bool findSpherePlanePenetration(const glm::vec3& sphereCenter, float sphereRadius,
const glm::vec4& plane, glm::vec3& penetration);
/// Computes the penetration between a sphere and a disk.
/// \param sphereCenter center of sphere
/// \param sphereRadius radius of sphere
/// \param diskCenter center of disk
/// \param diskRadius radius of disk
/// \param diskNormal normal of disk plan
/// \return true if sphere touches disk (does not handle collisions with disk edge)
bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius,
const glm::vec3& diskCenter, float diskRadius, const glm::vec3& diskNormal,
glm::vec3& penetration);
bool findCapsuleSpherePenetration(const glm::vec3& capsuleStart, const glm::vec3& capsuleEnd, float capsuleRadius,
const glm::vec3& sphereCenter, float sphereRadius, glm::vec3& penetration);

View file

@ -99,7 +99,7 @@ public:
int fillPingPacket(unsigned char* buffer);
int fillPingReplyPacket(unsigned char* pingBuffer, unsigned char* replyBuffer);
void pingPublicAndLocalSocketsForInactiveNode(Node* node);
void killNodeWithUUID(const QUuid& nodeUUID);
void sendKillNode(const char* nodeTypes, int numNodeTypes);
SharedNodePointer nodeWithAddress(const HifiSockAddr& senderSockAddr);
@ -123,6 +123,8 @@ public slots:
void sendDomainServerCheckIn();
void pingInactiveNodes();
void removeSilentNodes();
void killNodeWithUUID(const QUuid& nodeUUID);
signals:
void domainChanged(const QString& domainHostname);
void nodeAdded(SharedNodePointer);