mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into agent_script_engine_refactor
This commit is contained in:
commit
5c946090db
25 changed files with 332 additions and 165 deletions
|
@ -164,7 +164,6 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
|||
if ((s / 2) < numSamplesDelay) {
|
||||
// pull the earlier sample for the delayed channel
|
||||
int earlierSample = (*bufferToAdd)[(s / 2) - numSamplesDelay] * attenuationCoefficient * weakChannelAmplitudeRatio;
|
||||
|
||||
_clientSamples[s + delayedChannelOffset] = glm::clamp(_clientSamples[s + delayedChannelOffset] + earlierSample,
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
}
|
||||
|
@ -175,11 +174,11 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
|
|||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
|
||||
if ((s / 2) + numSamplesDelay < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) {
|
||||
// place the curernt sample at the right spot in the delayed channel
|
||||
int16_t clampedSample = glm::clamp((int) (_clientSamples[s + numSamplesDelay + delayedChannelOffset]
|
||||
// place the current sample at the right spot in the delayed channel
|
||||
int16_t clampedSample = glm::clamp((int) (_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset]
|
||||
+ (currentSample * weakChannelAmplitudeRatio)),
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
_clientSamples[s + numSamplesDelay + delayedChannelOffset] = clampedSample;
|
||||
_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] = clampedSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3479,13 +3479,13 @@ void Application::displayStats() {
|
|||
|
||||
// iterate all the current voxel stats, and list their sending modes, and total voxel counts
|
||||
std::stringstream sendingMode("");
|
||||
sendingMode << "Voxel Sending Mode: [";
|
||||
sendingMode << "Octree Sending Mode: [";
|
||||
int serverCount = 0;
|
||||
int movingServerCount = 0;
|
||||
unsigned long totalNodes = 0;
|
||||
unsigned long totalInternal = 0;
|
||||
unsigned long totalLeaves = 0;
|
||||
for(NodeToVoxelSceneStatsIterator i = _voxelServerSceneStats.begin(); i != _voxelServerSceneStats.end(); i++) {
|
||||
for(NodeToVoxelSceneStatsIterator i = _octreeServerSceneStats.begin(); i != _octreeServerSceneStats.end(); i++) {
|
||||
//const QUuid& uuid = i->first;
|
||||
VoxelSceneStats& stats = i->second;
|
||||
serverCount++;
|
||||
|
@ -4133,7 +4133,7 @@ void Application::domainChanged(QString domain) {
|
|||
|
||||
// reset our node to stats and node to jurisdiction maps... since these must be changing...
|
||||
_voxelServerJurisdictions.clear();
|
||||
_voxelServerSceneStats.clear();
|
||||
_octreeServerSceneStats.clear();
|
||||
_particleServerJurisdictions.clear();
|
||||
}
|
||||
|
||||
|
@ -4168,8 +4168,8 @@ void Application::nodeKilled(Node* node) {
|
|||
|
||||
// also clean up scene stats for that server
|
||||
_voxelSceneStatsLock.lockForWrite();
|
||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||
_voxelServerSceneStats.erase(nodeUUID);
|
||||
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
|
||||
_octreeServerSceneStats.erase(nodeUUID);
|
||||
}
|
||||
_voxelSceneStatsLock.unlock();
|
||||
|
||||
|
@ -4199,8 +4199,8 @@ void Application::nodeKilled(Node* node) {
|
|||
|
||||
// also clean up scene stats for that server
|
||||
_voxelSceneStatsLock.lockForWrite();
|
||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||
_voxelServerSceneStats.erase(nodeUUID);
|
||||
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
|
||||
_octreeServerSceneStats.erase(nodeUUID);
|
||||
}
|
||||
_voxelSceneStatsLock.unlock();
|
||||
|
||||
|
@ -4227,8 +4227,8 @@ void Application::trackIncomingVoxelPacket(unsigned char* messageData, ssize_t m
|
|||
|
||||
// now that we know the node ID, let's add these stats to the stats for that node...
|
||||
_voxelSceneStatsLock.lockForWrite();
|
||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||
VoxelSceneStats& stats = _voxelServerSceneStats[nodeUUID];
|
||||
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
|
||||
VoxelSceneStats& stats = _octreeServerSceneStats[nodeUUID];
|
||||
stats.trackIncomingOctreePacket(messageData, messageLength, wasStatsPacket);
|
||||
}
|
||||
_voxelSceneStatsLock.unlock();
|
||||
|
@ -4251,10 +4251,10 @@ int Application::parseOctreeStats(unsigned char* messageData, ssize_t messageLen
|
|||
|
||||
// now that we know the node ID, let's add these stats to the stats for that node...
|
||||
_voxelSceneStatsLock.lockForWrite();
|
||||
if (_voxelServerSceneStats.find(nodeUUID) != _voxelServerSceneStats.end()) {
|
||||
_voxelServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
||||
if (_octreeServerSceneStats.find(nodeUUID) != _octreeServerSceneStats.end()) {
|
||||
_octreeServerSceneStats[nodeUUID].unpackFromMessage(messageData, messageLength);
|
||||
} else {
|
||||
_voxelServerSceneStats[nodeUUID] = temp;
|
||||
_octreeServerSceneStats[nodeUUID] = temp;
|
||||
}
|
||||
_voxelSceneStatsLock.unlock();
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ public:
|
|||
QSettings* getSettings() { return _settings; }
|
||||
Swatch* getSwatch() { return &_swatch; }
|
||||
QMainWindow* getWindow() { return _window; }
|
||||
NodeToVoxelSceneStats* getVoxelSceneStats() { return &_voxelServerSceneStats; }
|
||||
NodeToVoxelSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
||||
void lockVoxelSceneStats() { _voxelSceneStatsLock.lockForRead(); }
|
||||
void unlockVoxelSceneStats() { _voxelSceneStatsLock.unlock(); }
|
||||
|
||||
|
@ -199,6 +199,7 @@ public:
|
|||
|
||||
glm::vec2 getViewportDimensions() const{ return glm::vec2(_glWidget->width(),_glWidget->height()); }
|
||||
NodeToJurisdictionMap& getVoxelServerJurisdictions() { return _voxelServerJurisdictions; }
|
||||
NodeToJurisdictionMap& getParticleServerJurisdictions() { return _particleServerJurisdictions; }
|
||||
void pasteVoxelsToOctalCode(const unsigned char* octalCodeDestination);
|
||||
|
||||
/// set a voxel which is to be rendered with a highlight
|
||||
|
@ -493,7 +494,7 @@ private:
|
|||
|
||||
NodeToJurisdictionMap _voxelServerJurisdictions;
|
||||
NodeToJurisdictionMap _particleServerJurisdictions;
|
||||
NodeToVoxelSceneStats _voxelServerSceneStats;
|
||||
NodeToVoxelSceneStats _octreeServerSceneStats;
|
||||
QReadWriteLock _voxelSceneStatsLock;
|
||||
|
||||
std::vector<VoxelFade> _voxelFades;
|
||||
|
|
|
@ -52,6 +52,8 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
|
|||
_outputFormat(),
|
||||
_outputDevice(NULL),
|
||||
_numOutputCallbackBytes(0),
|
||||
_loopbackAudioOutput(NULL),
|
||||
_loopbackOutputDevice(NULL),
|
||||
_inputRingBuffer(0),
|
||||
_ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL),
|
||||
_scope(scope),
|
||||
|
@ -201,19 +203,20 @@ void linearResampling(int16_t* sourceSamples, int16_t* destinationSamples,
|
|||
// upsample from 24 to 48
|
||||
// for now this only supports a stereo to stereo conversion - this is our case for network audio to output
|
||||
int sourceIndex = 0;
|
||||
int destinationToSourceFactor = (1 / sourceToDestinationFactor);
|
||||
int destinationToSourceFactor = (1 / sourceToDestinationFactor);
|
||||
int dtsSampleRateFactor = (destinationAudioFormat.sampleRate() / sourceAudioFormat.sampleRate());
|
||||
|
||||
for (int i = 0; i < numDestinationSamples; i += destinationAudioFormat.channelCount() * destinationToSourceFactor) {
|
||||
for (int i = 0; i < numDestinationSamples; i += destinationAudioFormat.channelCount() * dtsSampleRateFactor) {
|
||||
sourceIndex = (i / destinationToSourceFactor);
|
||||
|
||||
// fill the L/R channels and make the rest silent
|
||||
for (int j = i; j < i + (destinationToSourceFactor * destinationAudioFormat.channelCount()); j++) {
|
||||
for (int j = i; j < i + (dtsSampleRateFactor * destinationAudioFormat.channelCount()); j++) {
|
||||
if (j % destinationAudioFormat.channelCount() == 0) {
|
||||
// left channel
|
||||
destinationSamples[j] = sourceSamples[sourceIndex];
|
||||
} else if (j % destinationAudioFormat.channelCount() == 1) {
|
||||
// right channel
|
||||
destinationSamples[j] = sourceSamples[sourceIndex + 1];
|
||||
destinationSamples[j] = sourceSamples[sourceIndex + (sourceAudioFormat.channelCount() > 1 ? 1 : 0)];
|
||||
} else {
|
||||
// channels above 2, fill with silence
|
||||
destinationSamples[j] = 0;
|
||||
|
@ -263,9 +266,13 @@ void Audio::start() {
|
|||
_inputDevice = _audioInput->start();
|
||||
connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleAudioInput()));
|
||||
|
||||
// setup our general output device for audio-mixer audio
|
||||
_audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
_outputDevice = _audioOutput->start();
|
||||
|
||||
// setup a loopback audio output device
|
||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||
|
||||
gettimeofday(&_lastReceiveTime, NULL);
|
||||
}
|
||||
|
||||
|
@ -290,6 +297,30 @@ void Audio::handleAudioInput() {
|
|||
|
||||
QByteArray inputByteArray = _inputDevice->readAll();
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio)) {
|
||||
// if this person wants local loopback add that to the locally injected audio
|
||||
|
||||
if (!_loopbackOutputDevice) {
|
||||
// we didn't have the loopback output device going so set that up now
|
||||
_loopbackOutputDevice = _loopbackAudioOutput->start();
|
||||
}
|
||||
|
||||
if (_inputFormat == _outputFormat) {
|
||||
_loopbackOutputDevice->write(inputByteArray);
|
||||
} else {
|
||||
static float loopbackOutputToInputRatio = (_outputFormat.sampleRate() / (float) _inputFormat.sampleRate())
|
||||
* (_outputFormat.channelCount() / _inputFormat.channelCount());
|
||||
|
||||
QByteArray loopBackByteArray(inputByteArray.size() * loopbackOutputToInputRatio, 0);
|
||||
|
||||
linearResampling((int16_t*) inputByteArray.data(), (int16_t*) loopBackByteArray.data(),
|
||||
inputByteArray.size() / sizeof(int16_t),
|
||||
loopBackByteArray.size() / sizeof(int16_t), _inputFormat, _outputFormat);
|
||||
|
||||
_loopbackOutputDevice->write(loopBackByteArray);
|
||||
}
|
||||
}
|
||||
|
||||
_inputRingBuffer.writeData(inputByteArray.data(), inputByteArray.size());
|
||||
|
||||
while (_inputRingBuffer.samplesAvailable() > inputSamplesRequired) {
|
||||
|
@ -324,11 +355,6 @@ void Audio::handleAudioInput() {
|
|||
Q_ARG(QByteArray, QByteArray((char*) monoAudioSamples,
|
||||
NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL)),
|
||||
Q_ARG(bool, false), Q_ARG(bool, true));
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio)) {
|
||||
// if this person wants local loopback add that to the locally injected audio
|
||||
memcpy(_localInjectedSamples, monoAudioSamples, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL);
|
||||
}
|
||||
} else {
|
||||
// our input loudness is 0, since we're muted
|
||||
_lastInputLoudness = 0;
|
||||
|
@ -438,8 +464,8 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) {
|
|||
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||
ringBufferSamples[i * 2] = glm::clamp(ringBufferSamples[i * 2] + _localInjectedSamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
ringBufferSamples[(i * 2) + 1] += glm::clamp(ringBufferSamples[(i * 2) + 1] + _localInjectedSamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
ringBufferSamples[(i * 2) + 1] = glm::clamp(ringBufferSamples[(i * 2) + 1] + _localInjectedSamples[i],
|
||||
MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE);
|
||||
}
|
||||
|
||||
// copy the packet from the RB to the output
|
||||
|
|
|
@ -78,8 +78,11 @@ private:
|
|||
QAudioFormat _outputFormat;
|
||||
QIODevice* _outputDevice;
|
||||
int _numOutputCallbackBytes;
|
||||
QAudioOutput* _loopbackAudioOutput;
|
||||
QIODevice* _loopbackOutputDevice;
|
||||
AudioRingBuffer _inputRingBuffer;
|
||||
AudioRingBuffer _ringBuffer;
|
||||
|
||||
Oscilloscope* _scope;
|
||||
StDev _stdev;
|
||||
timeval _lastReceiveTime;
|
||||
|
|
|
@ -373,7 +373,10 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayLeapHands, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::LeapDrive, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::BallFromHand, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::BallFromHand, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::VoxelDrumming, 0, false);
|
||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::PlaySlaps, 0, false);
|
||||
|
||||
|
||||
|
||||
QMenu* trackingOptionsMenu = developerMenu->addMenu("Tracking Options");
|
||||
|
@ -1045,7 +1048,7 @@ void Menu::bandwidthDetailsClosed() {
|
|||
void Menu::voxelStatsDetails() {
|
||||
if (!_voxelStatsDialog) {
|
||||
_voxelStatsDialog = new VoxelStatsDialog(Application::getInstance()->getGLWidget(),
|
||||
Application::getInstance()->getVoxelSceneStats());
|
||||
Application::getInstance()->getOcteeSceneStats());
|
||||
connect(_voxelStatsDialog, SIGNAL(closed()), SLOT(voxelStatsDetailsClosed()));
|
||||
_voxelStatsDialog->show();
|
||||
}
|
||||
|
|
|
@ -244,6 +244,8 @@ namespace MenuOption {
|
|||
const QString ShowAllLocalVoxels = "Show All Local Voxels";
|
||||
const QString ShowTrueColors = "Show TRUE Colors";
|
||||
const QString SimulateLeapHand = "Simulate Leap Hand";
|
||||
const QString VoxelDrumming = "Voxel Drumming";
|
||||
const QString PlaySlaps = "Play Slaps";
|
||||
const QString SkeletonTracking = "Skeleton Tracking";
|
||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||
const QString LEDTracking = "LED Tracking";
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "Util.h"
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
||||
//#define DEBUG_HAND
|
||||
|
||||
using namespace std;
|
||||
|
||||
const float FINGERTIP_VOXEL_SIZE = 0.05;
|
||||
|
@ -24,9 +26,12 @@ const int TOY_BALL_HAND = 1;
|
|||
const float TOY_BALL_RADIUS = 0.05f;
|
||||
const float TOY_BALL_DAMPING = 0.99f;
|
||||
const glm::vec3 NO_VELOCITY = glm::vec3(0,0,0);
|
||||
const glm::vec3 TOY_BALL_GRAVITY = glm::vec3(0,-1,0);
|
||||
const glm::vec3 NO_GRAVITY = glm::vec3(0,0,0);
|
||||
const float NO_DAMPING = 0.f;
|
||||
const glm::vec3 TOY_BALL_GRAVITY = glm::vec3(0,-0.5,0);
|
||||
const QString TOY_BALL_UPDATE_SCRIPT("");
|
||||
const float PALM_COLLISION_RADIUS = 0.03f;
|
||||
const float CATCH_RADIUS = 0.2f;
|
||||
const xColor TOY_BALL_ON_SERVER_COLOR[] =
|
||||
{
|
||||
{ 255, 0, 0 },
|
||||
|
@ -78,32 +83,29 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
bool grabButtonPressed = (palm.getControllerButtons() & BUTTON_FWD);
|
||||
bool ballAlreadyInHand = _toyBallInHand[handID];
|
||||
|
||||
glm::vec3 targetPosition = palm.getPosition() / (float)TREE_SCALE;
|
||||
float targetRadius = (TOY_BALL_RADIUS * 4.0f) / (float)TREE_SCALE;
|
||||
glm::vec3 targetPosition = (ballFromHand ? palm.getPosition() : fingerTipPosition) / (float)TREE_SCALE;
|
||||
float targetRadius = CATCH_RADIUS / (float)TREE_SCALE;
|
||||
const Particle* closestParticle = Application::getInstance()->getParticles()
|
||||
->getTree()->findClosestParticle(targetPosition, targetRadius);
|
||||
|
||||
//printf("simulateToyBall() handID:%d grabButtonPressed:%s ballAlreadyInHand:%s\n",
|
||||
// handID, debug::valueOf(grabButtonPressed), debug::valueOf(ballAlreadyInHand));
|
||||
|
||||
if (closestParticle) {
|
||||
//printf("potentially caught... handID:%d particle ID:%d grabButtonPressed:%s ballAlreadyInHand:%s\n",
|
||||
// handID, closestParticle->getID(), debug::valueOf(grabButtonPressed), debug::valueOf(ballAlreadyInHand));
|
||||
|
||||
// If I don't currently have a ball in my hand, then I can catch this closest particle
|
||||
if (!ballAlreadyInHand && grabButtonPressed) {
|
||||
//printf("caught... handID:%d particle ID:%d\n", handID, closestParticle->getID());
|
||||
ParticleEditHandle* caughtParticle = Application::getInstance()->newParticleEditHandle(closestParticle->getID());
|
||||
glm::vec3 newPosition = targetPosition;
|
||||
glm::vec3 newVelocity = NO_VELOCITY;
|
||||
|
||||
// update the particle with it's new state...
|
||||
#ifdef DEBUG_HAND
|
||||
qDebug("Update caught particle!\n");
|
||||
#endif
|
||||
caughtParticle->updateParticle(newPosition,
|
||||
closestParticle->getRadius(),
|
||||
closestParticle->getXColor(),
|
||||
newVelocity,
|
||||
closestParticle->getGravity(),
|
||||
closestParticle->getDamping(),
|
||||
NO_GRAVITY,
|
||||
NO_DAMPING,
|
||||
IN_HAND, // we just grabbed it!
|
||||
closestParticle->getUpdateScript());
|
||||
|
||||
|
@ -143,6 +145,9 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
// create the ball, call MakeParticle, and use the resulting ParticleEditHandle to
|
||||
// manage the newly created particle.
|
||||
// Create a particle on the particle server
|
||||
#ifdef DEBUG_HAND
|
||||
qDebug("Created New Ball\n");
|
||||
#endif
|
||||
glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition;
|
||||
_ballParticleEditHandles[handID] = Application::getInstance()->makeParticle(
|
||||
ballPosition / (float)TREE_SCALE,
|
||||
|
@ -156,6 +161,9 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
}
|
||||
} else {
|
||||
// Ball is in hand
|
||||
#ifdef DEBUG_HAND
|
||||
qDebug("Ball in hand\n");
|
||||
#endif
|
||||
glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition;
|
||||
_ballParticleEditHandles[handID]->updateParticle(ballPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
|
@ -172,16 +180,18 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f
|
|||
|
||||
_toyBallInHand[handID] = false;
|
||||
glm::vec3 ballPosition = ballFromHand ? palm.getPosition() : fingerTipPosition;
|
||||
glm::vec3 handVelocity = palm.getRawVelocity();
|
||||
glm::vec3 fingerTipVelocity = palm.getTipVelocity();
|
||||
glm::vec3 ballVelocity = ballFromHand ? palm.getRawVelocity() : palm.getTipVelocity();
|
||||
glm::quat avatarRotation = _owningAvatar->getOrientation();
|
||||
glm::vec3 toyBallVelocity = avatarRotation * fingerTipVelocity;
|
||||
ballVelocity = avatarRotation * ballVelocity;
|
||||
|
||||
// ball is no longer in hand...
|
||||
#ifdef DEBUG_HAND
|
||||
qDebug("Threw ball, v = %.3f\n", glm::length(ballVelocity));
|
||||
#endif
|
||||
_ballParticleEditHandles[handID]->updateParticle(ballPosition / (float)TREE_SCALE,
|
||||
TOY_BALL_RADIUS / (float) TREE_SCALE,
|
||||
TOY_BALL_ON_SERVER_COLOR[_whichBallColor[handID]],
|
||||
toyBallVelocity / (float)TREE_SCALE,
|
||||
ballVelocity / (float)TREE_SCALE,
|
||||
TOY_BALL_GRAVITY / (float) TREE_SCALE,
|
||||
TOY_BALL_DAMPING,
|
||||
NOT_IN_HAND,
|
||||
|
@ -272,32 +282,35 @@ void Hand::simulate(float deltaTime, bool isMine) {
|
|||
_lastFingerDeleteVoxel = fingerTipPosition;
|
||||
}
|
||||
}
|
||||
// Check if the finger is intersecting with a voxel in the client voxel tree
|
||||
VoxelTreeElement* fingerNode = Application::getInstance()->getVoxels()->getVoxelEnclosing(
|
||||
glm::vec3(fingerTipPosition / (float)TREE_SCALE));
|
||||
if (fingerNode) {
|
||||
if (!palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just started
|
||||
palm.setIsCollidingWithVoxel(true);
|
||||
handleVoxelCollision(&palm, fingerTipPosition, fingerNode, deltaTime);
|
||||
// Set highlight voxel
|
||||
VoxelDetail voxel;
|
||||
glm::vec3 pos = fingerNode->getCorner();
|
||||
voxel.x = pos.x;
|
||||
voxel.y = pos.y;
|
||||
voxel.z = pos.z;
|
||||
voxel.s = fingerNode->getScale();
|
||||
voxel.red = fingerNode->getColor()[0];
|
||||
voxel.green = fingerNode->getColor()[1];
|
||||
voxel.blue = fingerNode->getColor()[2];
|
||||
Application::getInstance()->setHighlightVoxel(voxel);
|
||||
Application::getInstance()->setIsHighlightVoxel(true);
|
||||
}
|
||||
} else {
|
||||
if (palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just ended
|
||||
palm.setIsCollidingWithVoxel(false);
|
||||
Application::getInstance()->setIsHighlightVoxel(false);
|
||||
|
||||
// Voxel Drumming with fingertips if enabled
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::VoxelDrumming)) {
|
||||
VoxelTreeElement* fingerNode = Application::getInstance()->getVoxels()->getVoxelEnclosing(
|
||||
glm::vec3(fingerTipPosition / (float)TREE_SCALE));
|
||||
if (fingerNode) {
|
||||
if (!palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just started
|
||||
palm.setIsCollidingWithVoxel(true);
|
||||
handleVoxelCollision(&palm, fingerTipPosition, fingerNode, deltaTime);
|
||||
// Set highlight voxel
|
||||
VoxelDetail voxel;
|
||||
glm::vec3 pos = fingerNode->getCorner();
|
||||
voxel.x = pos.x;
|
||||
voxel.y = pos.y;
|
||||
voxel.z = pos.z;
|
||||
voxel.s = fingerNode->getScale();
|
||||
voxel.red = fingerNode->getColor()[0];
|
||||
voxel.green = fingerNode->getColor()[1];
|
||||
voxel.blue = fingerNode->getColor()[2];
|
||||
Application::getInstance()->setHighlightVoxel(voxel);
|
||||
Application::getInstance()->setIsHighlightVoxel(true);
|
||||
}
|
||||
} else {
|
||||
if (palm.getIsCollidingWithVoxel()) {
|
||||
// Collision has just ended
|
||||
palm.setIsCollidingWithVoxel(false);
|
||||
Application::getInstance()->setIsHighlightVoxel(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -325,9 +338,37 @@ void Hand::updateCollisions() {
|
|||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||
if (node->getLinkedData() && node->getType() == NODE_TYPE_AGENT) {
|
||||
Avatar* otherAvatar = (Avatar*)node->getLinkedData();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PlaySlaps)) {
|
||||
// Check for palm collisions
|
||||
glm::vec3 myPalmPosition = palm.getPosition();
|
||||
float palmCollisionDistance = 0.1f;
|
||||
palm.setIsCollidingWithPalm(false);
|
||||
// If 'Play Slaps' is enabled, look for palm-to-palm collisions and make sound
|
||||
for (int j = 0; j < otherAvatar->getHand().getNumPalms(); j++) {
|
||||
PalmData& otherPalm = otherAvatar->getHand().getPalms()[j];
|
||||
if (!otherPalm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 otherPalmPosition = otherPalm.getPosition();
|
||||
if (glm::length(otherPalmPosition - myPalmPosition) < palmCollisionDistance) {
|
||||
palm.setIsCollidingWithPalm(true);
|
||||
const float PALM_COLLIDE_VOLUME = 1.f;
|
||||
const float PALM_COLLIDE_FREQUENCY = 150.f;
|
||||
const float PALM_COLLIDE_DURATION_MAX = 2.f;
|
||||
const float PALM_COLLIDE_DECAY_PER_SAMPLE = 0.005f;
|
||||
Application::getInstance()->getAudio()->startDrumSound(PALM_COLLIDE_VOLUME,
|
||||
PALM_COLLIDE_FREQUENCY,
|
||||
PALM_COLLIDE_DURATION_MAX,
|
||||
PALM_COLLIDE_DECAY_PER_SAMPLE);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
glm::vec3 avatarPenetration;
|
||||
if (otherAvatar->findSpherePenetration(palm.getPosition(), scaledPalmRadius, avatarPenetration)) {
|
||||
totalPenetration = addPenetrations(totalPenetration, avatarPenetration);
|
||||
// Check for collisions with the other avatar's leap palms
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,20 +458,23 @@ void Hand::render( bool isMine) {
|
|||
|
||||
_renderAlpha = 1.0;
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
|
||||
for (int i = 0; i < getNumPalms(); i++) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (!palm.isActive()) {
|
||||
continue;
|
||||
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollisionProxies)) {
|
||||
for (int i = 0; i < getNumPalms(); i++) {
|
||||
PalmData& palm = getPalms()[i];
|
||||
if (!palm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 position = palm.getPosition();
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
glutSolidSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10);
|
||||
glPopMatrix();
|
||||
}
|
||||
glm::vec3 position = palm.getPosition();
|
||||
glPushMatrix();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
glutSolidSphere(PALM_COLLISION_RADIUS * _owningAvatar->getScale(), 10, 10);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayLeapHands)) {
|
||||
renderLeapHands();
|
||||
|
@ -459,10 +503,11 @@ void Hand::render( bool isMine) {
|
|||
void Hand::renderLeapHands() {
|
||||
|
||||
const float alpha = 1.0f;
|
||||
const float TARGET_ALPHA = 0.5f;
|
||||
|
||||
//const glm::vec3 handColor = _ballColor;
|
||||
const glm::vec3 handColor(1.0, 0.84, 0.66); // use the skin color
|
||||
|
||||
|
||||
bool ballFromHand = Menu::getInstance()->isOptionChecked(MenuOption::BallFromHand);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
@ -473,26 +518,25 @@ void Hand::renderLeapHands() {
|
|||
if (!palm.isActive()) {
|
||||
continue;
|
||||
}
|
||||
glm::vec3 targetPosition = palm.getPosition();
|
||||
float targetRadius = (TOY_BALL_RADIUS * 4.0f);
|
||||
glm::vec3 targetPosition = ballFromHand ? palm.getPosition() : palm.getTipPosition();
|
||||
glPushMatrix();
|
||||
|
||||
const Particle* closestParticle = Application::getInstance()->getParticles()
|
||||
->getTree()->findClosestParticle(targetPosition / (float)TREE_SCALE,
|
||||
targetRadius / (float)TREE_SCALE);
|
||||
CATCH_RADIUS / (float)TREE_SCALE);
|
||||
|
||||
// If we are hitting a particle then draw the target green, otherwise yellow
|
||||
if (closestParticle) {
|
||||
glColor4f(0,1,0, alpha);
|
||||
glColor4f(0,1,0, TARGET_ALPHA);
|
||||
} else {
|
||||
glColor4f(1,1,0, alpha);
|
||||
glColor4f(1,1,0, TARGET_ALPHA);
|
||||
}
|
||||
glTranslatef(targetPosition.x, targetPosition.y, targetPosition.z);
|
||||
glutWireSphere(targetRadius, 20.0f, 20.0f);
|
||||
glutWireSphere(CATCH_RADIUS, 10.f, 10.f);
|
||||
|
||||
const float collisionRadius = 0.05f;
|
||||
glColor4f(0.5f,0.5f,0.5f, alpha);
|
||||
glutWireSphere(collisionRadius, 20.0f, 20.0f);
|
||||
glutWireSphere(collisionRadius, 10.f, 10.f);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -534,7 +578,11 @@ void Hand::renderLeapHands() {
|
|||
PalmData& palm = getPalms()[i];
|
||||
if (palm.isActive()) {
|
||||
const float palmThickness = 0.02f;
|
||||
glColor4f(handColor.r, handColor.g, handColor.b, 0.25);
|
||||
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;
|
||||
|
|
|
@ -79,7 +79,6 @@ private:
|
|||
std::vector<HandBall> _leapFingerRootBalls;
|
||||
|
||||
glm::vec3 _lastFingerAddVoxel, _lastFingerDeleteVoxel;
|
||||
bool _isCollidingWithVoxel;
|
||||
VoxelDetail _collidingVoxel;
|
||||
|
||||
glm::vec3 _collisionCenter;
|
||||
|
|
|
@ -426,6 +426,31 @@ static TextRenderer* textRenderer() {
|
|||
return renderer;
|
||||
}
|
||||
|
||||
void MyAvatar::renderDebugBodyPoints() {
|
||||
glm::vec3 torsoPosition(getPosition());
|
||||
glm::vec3 headPosition(getHead().getEyePosition());
|
||||
float torsoToHead = glm::length(headPosition - torsoPosition);
|
||||
glm::vec3 position;
|
||||
printf("head-above-torso %.2f, scale = %0.2f\n", torsoToHead, getScale());
|
||||
|
||||
// Torso Sphere
|
||||
position = torsoPosition;
|
||||
glPushMatrix();
|
||||
glColor4f(0, 1, 0, .5f);
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(0.2, 10, 10);
|
||||
glPopMatrix();
|
||||
|
||||
// Head Sphere
|
||||
position = headPosition;
|
||||
glPushMatrix();
|
||||
glColor4f(0, 1, 0, .5f);
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(0.15, 10, 10);
|
||||
glPopMatrix();
|
||||
|
||||
|
||||
}
|
||||
void MyAvatar::render(bool forceRenderHead) {
|
||||
|
||||
// render body
|
||||
|
@ -438,6 +463,9 @@ void MyAvatar::render(bool forceRenderHead) {
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
//renderDebugBodyPoints();
|
||||
|
||||
|
||||
if (!_chatMessage.empty()) {
|
||||
int width = 0;
|
||||
int lastWidth = 0;
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
void simulate(float deltaTime, Transmitter* transmitter);
|
||||
void updateFromGyrosAndOrWebcam(bool turnWithHead);
|
||||
void render(bool forceRenderHead);
|
||||
void renderDebugBodyPoints();
|
||||
|
||||
// setters
|
||||
void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; }
|
||||
|
|
|
@ -79,12 +79,6 @@ void SixenseManager::update(float deltaTime) {
|
|||
palm->setTrigger(data.trigger);
|
||||
palm->setJoystick(data.joystick_x, data.joystick_y);
|
||||
|
||||
// Vibrate if needed
|
||||
if (palm->getIsCollidingWithVoxel()) {
|
||||
//printf("vibrate!\n");
|
||||
//vibrate(data.controller_index, 100, 1);
|
||||
}
|
||||
|
||||
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
|
||||
// Adjust for distance between acquisition 'orb' and the user's torso
|
||||
// (distance to the right of body center, distance below torso, distance behind torso)
|
||||
|
@ -113,8 +107,8 @@ void SixenseManager::update(float deltaTime) {
|
|||
const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
|
||||
finger.setRawTipPosition(position + rotation * FINGER_VECTOR);
|
||||
|
||||
// temporary for toy ball - store first finger tip velocity
|
||||
glm::vec3 oldTipPosition = palm->getTipPosition();
|
||||
// Store the one fingertip in the palm structure so we can track velocity
|
||||
glm::vec3 oldTipPosition = palm->getTipRawPosition();
|
||||
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime / 1000.f);
|
||||
palm->setTipPosition(newTipPosition);
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ void VoxelStatsDialog::paintEvent(QPaintEvent* event) {
|
|||
unsigned long totalLeaves = 0;
|
||||
|
||||
Application::getInstance()->lockVoxelSceneStats();
|
||||
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getVoxelSceneStats();
|
||||
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getOcteeSceneStats();
|
||||
for(NodeToVoxelSceneStatsIterator i = sceneStats->begin(); i != sceneStats->end(); i++) {
|
||||
//const QUuid& uuid = i->first;
|
||||
VoxelSceneStats& stats = i->second;
|
||||
|
@ -215,26 +215,42 @@ void VoxelStatsDialog::paintEvent(QPaintEvent* event) {
|
|||
"Leaves: " << serversLeavesString.toLocal8Bit().constData() << "";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
showAllVoxelServers();
|
||||
showAllOctreeServers();
|
||||
|
||||
this->QDialog::paintEvent(event);
|
||||
}
|
||||
void VoxelStatsDialog::showAllOctreeServers() {
|
||||
int serverCount = 0;
|
||||
|
||||
void VoxelStatsDialog::showAllVoxelServers() {
|
||||
showOctreeServersOfType(serverCount, NODE_TYPE_VOXEL_SERVER, "Voxel",
|
||||
Application::getInstance()->getVoxelServerJurisdictions());
|
||||
showOctreeServersOfType(serverCount, NODE_TYPE_PARTICLE_SERVER, "Particle",
|
||||
Application::getInstance()->getParticleServerJurisdictions());
|
||||
|
||||
if (_voxelServerLabelsCount > serverCount) {
|
||||
for (int i = serverCount; i < _voxelServerLabelsCount; i++) {
|
||||
int serverLabel = _voxelServerLables[i];
|
||||
RemoveStatItem(serverLabel);
|
||||
_voxelServerLables[i] = 0;
|
||||
}
|
||||
_voxelServerLabelsCount = serverCount;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelStatsDialog::showOctreeServersOfType(int& serverCount, NODE_TYPE serverType, const char* serverTypeName,
|
||||
NodeToJurisdictionMap& serverJurisdictions) {
|
||||
|
||||
QLocale locale(QLocale::English);
|
||||
|
||||
int serverNumber = 0;
|
||||
int serverCount = 0;
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||
// only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER
|
||||
if (node->getType() == NODE_TYPE_VOXEL_SERVER) {
|
||||
serverNumber++;
|
||||
if (node->getType() == serverType) {
|
||||
serverCount++;
|
||||
|
||||
if (serverCount > _voxelServerLabelsCount) {
|
||||
char label[128] = { 0 };
|
||||
sprintf(label, "Voxel Server %d",serverCount);
|
||||
sprintf(label, "%s Server %d", serverTypeName, serverCount);
|
||||
int thisServerRow = _voxelServerLables[serverCount-1] = AddStatItem(label);
|
||||
_labels[thisServerRow]->setTextFormat(Qt::RichText);
|
||||
_labels[thisServerRow]->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
|
@ -254,14 +270,12 @@ void VoxelStatsDialog::showAllVoxelServers() {
|
|||
|
||||
QUuid nodeUUID = node->getUUID();
|
||||
|
||||
NodeToJurisdictionMap& voxelServerJurisdictions = Application::getInstance()->getVoxelServerJurisdictions();
|
||||
|
||||
// lookup our nodeUUID in the jurisdiction map, if it's missing then we're
|
||||
// missing at least one jurisdiction
|
||||
if (voxelServerJurisdictions.find(nodeUUID) == voxelServerJurisdictions.end()) {
|
||||
if (serverJurisdictions.find(nodeUUID) == serverJurisdictions.end()) {
|
||||
serverDetails << " unknown jurisdiction ";
|
||||
} else {
|
||||
const JurisdictionMap& map = voxelServerJurisdictions[nodeUUID];
|
||||
const JurisdictionMap& map = serverJurisdictions[nodeUUID];
|
||||
|
||||
unsigned char* rootCode = map.getRootOctalCode();
|
||||
|
||||
|
@ -285,13 +299,13 @@ void VoxelStatsDialog::showAllVoxelServers() {
|
|||
} // jurisdiction
|
||||
|
||||
// now lookup stats details for this server...
|
||||
if (_extraServerDetails[serverNumber-1] != LESS) {
|
||||
if (_extraServerDetails[serverCount-1] != LESS) {
|
||||
Application::getInstance()->lockVoxelSceneStats();
|
||||
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getVoxelSceneStats();
|
||||
NodeToVoxelSceneStats* sceneStats = Application::getInstance()->getOcteeSceneStats();
|
||||
if (sceneStats->find(nodeUUID) != sceneStats->end()) {
|
||||
VoxelSceneStats& stats = sceneStats->at(nodeUUID);
|
||||
|
||||
switch (_extraServerDetails[serverNumber-1]) {
|
||||
switch (_extraServerDetails[serverCount-1]) {
|
||||
case MOST: {
|
||||
extraDetails << "<br/>" ;
|
||||
|
||||
|
@ -345,12 +359,12 @@ void VoxelStatsDialog::showAllVoxelServers() {
|
|||
" Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData();
|
||||
|
||||
serverDetails << extraDetails.str();
|
||||
if (_extraServerDetails[serverNumber-1] == MORE) {
|
||||
linkDetails << " " << " [<a href='most-" << serverNumber << "'>most...</a>]";
|
||||
linkDetails << " " << " [<a href='less-" << serverNumber << "'>less...</a>]";
|
||||
if (_extraServerDetails[serverCount-1] == MORE) {
|
||||
linkDetails << " " << " [<a href='most-" << serverCount << "'>most...</a>]";
|
||||
linkDetails << " " << " [<a href='less-" << serverCount << "'>less...</a>]";
|
||||
} else {
|
||||
linkDetails << " " << " [<a href='more-" << serverNumber << "'>less...</a>]";
|
||||
linkDetails << " " << " [<a href='less-" << serverNumber << "'>least...</a>]";
|
||||
linkDetails << " " << " [<a href='more-" << serverCount << "'>less...</a>]";
|
||||
linkDetails << " " << " [<a href='less-" << serverCount << "'>least...</a>]";
|
||||
}
|
||||
|
||||
} break;
|
||||
|
@ -361,22 +375,13 @@ void VoxelStatsDialog::showAllVoxelServers() {
|
|||
}
|
||||
Application::getInstance()->unlockVoxelSceneStats();
|
||||
} else {
|
||||
linkDetails << " " << " [<a href='more-" << serverNumber << "'>more...</a>]";
|
||||
linkDetails << " " << " [<a href='most-" << serverNumber << "'>most...</a>]";
|
||||
linkDetails << " " << " [<a href='more-" << serverCount << "'>more...</a>]";
|
||||
linkDetails << " " << " [<a href='most-" << serverCount << "'>most...</a>]";
|
||||
}
|
||||
serverDetails << linkDetails.str();
|
||||
_labels[_voxelServerLables[serverCount - 1]]->setText(serverDetails.str().c_str());
|
||||
} // is VOXEL_SERVER
|
||||
} // Node Loop
|
||||
|
||||
if (_voxelServerLabelsCount > serverCount) {
|
||||
for (int i = serverCount; i < _voxelServerLabelsCount; i++) {
|
||||
int serverLabel = _voxelServerLables[i];
|
||||
RemoveStatItem(serverLabel);
|
||||
_voxelServerLables[i] = 0;
|
||||
}
|
||||
_voxelServerLabelsCount = serverCount;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelStatsDialog::reject() {
|
||||
|
|
|
@ -42,7 +42,10 @@ protected:
|
|||
|
||||
int AddStatItem(const char* caption, unsigned colorRGBA = DEFAULT_COLOR);
|
||||
void RemoveStatItem(int item);
|
||||
void showAllVoxelServers();
|
||||
void showAllOctreeServers();
|
||||
|
||||
void showOctreeServersOfType(int& serverNumber, NODE_TYPE serverType,
|
||||
const char* serverTypeName, NodeToJurisdictionMap& serverJurisdictions);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int
|
|||
return position + numSamplesShift - _sampleCapacity;
|
||||
} else if (numSamplesShift < 0 && position + numSamplesShift < _buffer) {
|
||||
// this shift will go around to the end of the ring
|
||||
return position + numSamplesShift - _sampleCapacity;
|
||||
return position + numSamplesShift + _sampleCapacity;
|
||||
} else {
|
||||
return position + numSamplesShift;
|
||||
}
|
||||
|
|
|
@ -38,22 +38,20 @@ PalmData& HandData::addNewPalm() {
|
|||
return _palms.back();
|
||||
}
|
||||
|
||||
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
|
||||
const int SIXENSE_CONTROLLER_ID_RIGHT_HAND = 1;
|
||||
|
||||
void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex) const {
|
||||
leftPalmIndex = -1;
|
||||
float leftPalmX = FLT_MAX;
|
||||
rightPalmIndex = -1;
|
||||
float rightPalmX = -FLT_MAX;
|
||||
rightPalmIndex = -1;
|
||||
for (int i = 0; i < _palms.size(); i++) {
|
||||
const PalmData& palm = _palms[i];
|
||||
if (palm.isActive()) {
|
||||
float x = palm.getRawPosition().x;
|
||||
if (x < leftPalmX) {
|
||||
if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_LEFT_HAND) {
|
||||
leftPalmIndex = i;
|
||||
leftPalmX = x;
|
||||
}
|
||||
if (x > rightPalmX) {
|
||||
if (palm.getSixenseID() == SIXENSE_CONTROLLER_ID_RIGHT_HAND) {
|
||||
rightPalmIndex = i;
|
||||
rightPalmX = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +69,8 @@ _leapID(LEAPID_INVALID),
|
|||
_sixenseID(SIXENSEID_INVALID),
|
||||
_numFramesWithoutData(0),
|
||||
_owningHandData(owningHandData),
|
||||
_isCollidingWithVoxel(false)
|
||||
_isCollidingWithVoxel(false),
|
||||
_isCollidingWithPalm(false)
|
||||
{
|
||||
for (int i = 0; i < NUM_FINGERS_PER_HAND; ++i) {
|
||||
_fingers.push_back(FingerData(this, owningHandData));
|
||||
|
|
|
@ -158,7 +158,9 @@ public:
|
|||
void addToPosition(const glm::vec3& delta);
|
||||
|
||||
void setTipPosition(const glm::vec3& position) { _tipPosition = position; }
|
||||
const glm::vec3 getTipPosition() const { return _tipPosition; }
|
||||
const glm::vec3 getTipPosition() const { return _owningHandData->leapPositionToWorldPosition(_tipPosition); }
|
||||
const glm::vec3 getTipRawPosition() const { return _tipPosition; }
|
||||
|
||||
const glm::vec3& getTipVelocity() const { return _tipVelocity; }
|
||||
void setTipVelocity(const glm::vec3& velocity) { _tipVelocity = velocity; }
|
||||
|
||||
|
@ -182,6 +184,9 @@ public:
|
|||
bool getIsCollidingWithVoxel() { return _isCollidingWithVoxel; }
|
||||
void setIsCollidingWithVoxel(bool isCollidingWithVoxel) { _isCollidingWithVoxel = isCollidingWithVoxel; }
|
||||
|
||||
bool getIsCollidingWithPalm() { return _isCollidingWithPalm; }
|
||||
void setIsCollidingWithPalm(bool isCollidingWithPalm) { _isCollidingWithPalm = isCollidingWithPalm; }
|
||||
|
||||
private:
|
||||
std::vector<FingerData> _fingers;
|
||||
glm::quat _rawRotation;
|
||||
|
@ -205,6 +210,7 @@ private:
|
|||
HandData* _owningHandData;
|
||||
|
||||
bool _isCollidingWithVoxel; /// Whether the finger of this palm is inside a leaf voxel
|
||||
bool _isCollidingWithPalm;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -17,14 +17,14 @@ OctreeScriptingInterface::OctreeScriptingInterface(OctreeEditPacketSender* packe
|
|||
|
||||
OctreeScriptingInterface::~OctreeScriptingInterface() {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface()\n");
|
||||
if (_managedJuridiciontListerner) {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJuridiciontListerner... _jurisdictionListener->terminate()\n");
|
||||
if (_managedJurisdictionListener) {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJurisdictionListener... _jurisdictionListener->terminate()\n");
|
||||
_jurisdictionListener->terminate();
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJuridiciontListerner... deleting _jurisdictionListener\n");
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJurisdictionListener... deleting _jurisdictionListener\n");
|
||||
delete _jurisdictionListener;
|
||||
}
|
||||
if (_managedPacketSender) {
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJuridiciontListerner... _packetSender->terminate()\n");
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedJurisdictionListener... _packetSender->terminate()\n");
|
||||
_packetSender->terminate();
|
||||
//printf("OctreeScriptingInterface::~OctreeScriptingInterface() _managedPacketSender... deleting _packetSender\n");
|
||||
delete _packetSender;
|
||||
|
@ -42,11 +42,11 @@ void OctreeScriptingInterface::setJurisdictionListener(JurisdictionListener* jur
|
|||
void OctreeScriptingInterface::init() {
|
||||
//printf("OctreeScriptingInterface::init()\n");
|
||||
if (_jurisdictionListener) {
|
||||
_managedJuridiciontListerner = false;
|
||||
_managedJurisdictionListener = false;
|
||||
} else {
|
||||
_managedJuridiciontListerner = true;
|
||||
_managedJurisdictionListener = true;
|
||||
_jurisdictionListener = new JurisdictionListener(getServerNodeType());
|
||||
//printf("OctreeScriptingInterface::init() _managedJuridiciontListerner=true, creating _jurisdictionListener=%p\n", _jurisdictionListener);
|
||||
//printf("OctreeScriptingInterface::init() _managedJurisdictionListener=true, creating _jurisdictionListener=%p\n", _jurisdictionListener);
|
||||
_jurisdictionListener->initialize(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ protected:
|
|||
OctreeEditPacketSender* _packetSender;
|
||||
JurisdictionListener* _jurisdictionListener;
|
||||
bool _managedPacketSender;
|
||||
bool _managedJuridiciontListerner;
|
||||
bool _managedJurisdictionListener;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__OctreeScriptingInterface__) */
|
||||
|
|
|
@ -43,6 +43,7 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3
|
|||
_id = id;
|
||||
}
|
||||
_lastUpdated = usecTimestampNow();
|
||||
_lastEdited = _lastUpdated;
|
||||
|
||||
_position = position;
|
||||
_radius = radius;
|
||||
|
@ -67,6 +68,9 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
|||
if (success) {
|
||||
success = packetData->appendValue(getLastUpdated());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getLastEdited());
|
||||
}
|
||||
if (success) {
|
||||
success = packetData->appendValue(getRadius());
|
||||
}
|
||||
|
@ -99,7 +103,7 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const {
|
|||
}
|
||||
|
||||
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(uint64_t) + sizeof(float) +
|
||||
sizeof(glm::vec3) + sizeof(rgbColor) + sizeof(glm::vec3) +
|
||||
sizeof(glm::vec3) + sizeof(float) + sizeof(bool);
|
||||
return expectedBytes;
|
||||
|
@ -125,6 +129,11 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
dataAt += sizeof(_lastUpdated);
|
||||
bytesRead += sizeof(_lastUpdated);
|
||||
|
||||
// _lastEdited
|
||||
memcpy(&_lastEdited, dataAt, sizeof(_lastEdited));
|
||||
dataAt += sizeof(_lastEdited);
|
||||
bytesRead += sizeof(_lastEdited);
|
||||
|
||||
// radius
|
||||
memcpy(&_radius, dataAt, sizeof(_radius));
|
||||
dataAt += sizeof(_radius);
|
||||
|
@ -219,6 +228,11 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe
|
|||
memcpy(&newParticle._lastUpdated, dataAt, sizeof(newParticle._lastUpdated));
|
||||
dataAt += sizeof(newParticle._lastUpdated);
|
||||
processedBytes += sizeof(newParticle._lastUpdated);
|
||||
|
||||
// lastEdited
|
||||
memcpy(&newParticle._lastEdited, dataAt, sizeof(newParticle._lastEdited));
|
||||
dataAt += sizeof(newParticle._lastEdited);
|
||||
processedBytes += sizeof(newParticle._lastEdited);
|
||||
|
||||
// radius
|
||||
memcpy(&newParticle._radius, dataAt, sizeof(newParticle._radius));
|
||||
|
@ -279,6 +293,7 @@ void Particle::debugDump() const {
|
|||
printf("Particle id :%u\n", _id);
|
||||
printf(" created:%llu\n", _created);
|
||||
printf(" last updated:%llu\n", _lastUpdated);
|
||||
printf(" last edited:%llu\n", _lastEdited);
|
||||
printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z);
|
||||
printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z);
|
||||
printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z);
|
||||
|
@ -337,6 +352,11 @@ bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count,
|
|||
copyAt += sizeof(details[i].lastUpdated);
|
||||
sizeOut += sizeof(details[i].lastUpdated);
|
||||
|
||||
// lastEdited
|
||||
memcpy(copyAt, &details[i].lastEdited, sizeof(details[i].lastEdited));
|
||||
copyAt += sizeof(details[i].lastEdited);
|
||||
sizeOut += sizeof(details[i].lastEdited);
|
||||
|
||||
// radius
|
||||
memcpy(copyAt, &details[i].radius, sizeof(details[i].radius));
|
||||
copyAt += sizeof(details[i].radius);
|
||||
|
|
|
@ -26,6 +26,7 @@ class ParticleDetail {
|
|||
public:
|
||||
uint32_t id;
|
||||
uint64_t lastUpdated;
|
||||
uint64_t lastEdited;
|
||||
glm::vec3 position;
|
||||
float radius;
|
||||
rgbColor color;
|
||||
|
@ -70,6 +71,7 @@ public:
|
|||
uint64_t getCreated() const { return _created; }
|
||||
uint64_t getLifetime() const { return usecTimestampNow() - _created; }
|
||||
uint64_t getLastUpdated() const { return _lastUpdated; }
|
||||
uint64_t getLastEdited() const { return _lastEdited; }
|
||||
uint32_t getID() const { return _id; }
|
||||
bool getShouldDie() const { return _shouldDie; }
|
||||
QString getUpdateScript() const { return _updateScript; }
|
||||
|
@ -92,7 +94,7 @@ public:
|
|||
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);
|
||||
static int expectedBytes();
|
||||
|
@ -116,6 +118,7 @@ protected:
|
|||
glm::vec3 _velocity;
|
||||
uint64_t _lastUpdated;
|
||||
uint64_t _created;
|
||||
uint64_t _lastEdited;
|
||||
uint32_t _id;
|
||||
static uint32_t _nextID;
|
||||
bool _shouldDie;
|
||||
|
|
|
@ -44,7 +44,8 @@ void ParticleEditHandle::createParticle(glm::vec3 position, float radius, xColor
|
|||
glm::vec3 gravity, float damping, bool inHand, QString updateScript) {
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now,
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||
|
||||
|
@ -69,7 +70,8 @@ bool ParticleEditHandle::updateParticle(glm::vec3 position, float radius, xColor
|
|||
}
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
ParticleDetail newParticleDetail = { _id, usecTimestampNow(),
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail newParticleDetail = { _id, now, now,
|
||||
position, radius, {color.red, color.green, color.blue },
|
||||
velocity, gravity, damping, inHand, updateScript, _creatorTokenID };
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl
|
|||
_nextCreatorTokenID++;
|
||||
|
||||
// setup a ParticleDetail struct with the data
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, usecTimestampNow(),
|
||||
uint64_t now = usecTimestampNow();
|
||||
ParticleDetail addParticleDetail = { NEW_PARTICLE, now, now,
|
||||
position, radius, {color.red, color.green, color.blue }, velocity,
|
||||
gravity, damping, inHand, updateScript, creatorTokenID };
|
||||
|
||||
|
|
|
@ -115,15 +115,39 @@ bool ParticleTreeElement::containsParticle(const Particle& particle) const {
|
|||
}
|
||||
|
||||
bool ParticleTreeElement::updateParticle(const Particle& particle) {
|
||||
bool wantDebug = false;
|
||||
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();
|
||||
int difference = _particles[i].getLastUpdated() - particle.getLastUpdated();
|
||||
|
||||
bool changedOnServer = _particles[i].getLastEdited() < particle.getLastEdited();
|
||||
bool localOlder = _particles[i].getLastUpdated() < particle.getLastUpdated();
|
||||
|
||||
if (changedOnServer || localOlder) {
|
||||
|
||||
if (wantDebug) {
|
||||
printf("local particle [id:%d] %s and %s than server particle by %d, particle.isNewlyCreated()=%s\n",
|
||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
||||
}
|
||||
|
||||
uint64_t actuallyCreated = particle.getCreated();
|
||||
if (!particle.isNewlyCreated()) {
|
||||
actuallyCreated = _particles[i].getCreated();
|
||||
}
|
||||
_particles[i] = particle;
|
||||
_particles[i].setCreated(actuallyCreated);
|
||||
} else {
|
||||
if (wantDebug) {
|
||||
printf(">>> NO CHANGE <<< -- local particle [id:%d] %s and %s than server particle by %d, "
|
||||
"particle.isNewlyCreated()=%s\n",
|
||||
particle.getID(), (changedOnServer ? "CHANGED" : "same"),
|
||||
(localOlder ? "OLDER" : "NEWER"),
|
||||
difference, debug::valueOf(particle.isNewlyCreated()) );
|
||||
}
|
||||
}
|
||||
_particles[i] = particle;
|
||||
_particles[i].setCreated(actuallyCreated);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
|
|||
return 2;
|
||||
|
||||
case PACKET_TYPE_PARTICLE_DATA:
|
||||
return 2;
|
||||
return 3;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue