mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-25 20:16:09 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into fixery
This commit is contained in:
commit
355321c8b5
12 changed files with 589 additions and 480 deletions
|
@ -85,7 +85,6 @@ const float MIRROR_FULLSCREEN_DISTANCE = 0.35f;
|
||||||
const float MIRROR_REARVIEW_DISTANCE = 0.65f;
|
const float MIRROR_REARVIEW_DISTANCE = 0.65f;
|
||||||
const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
|
const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f;
|
||||||
|
|
||||||
|
|
||||||
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) {
|
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString &message) {
|
||||||
fprintf(stdout, "%s", message.toLocal8Bit().constData());
|
fprintf(stdout, "%s", message.toLocal8Bit().constData());
|
||||||
Application::getInstance()->getLogger()->addMessage(message.toLocal8Bit().constData());
|
Application::getInstance()->getLogger()->addMessage(message.toLocal8Bit().constData());
|
||||||
|
@ -142,7 +141,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
_resetRecentMaxPacketsSoon(true),
|
_resetRecentMaxPacketsSoon(true),
|
||||||
_swatch(NULL),
|
_swatch(NULL),
|
||||||
_pasteMode(false),
|
_pasteMode(false),
|
||||||
_logger(new FileLogger())
|
_logger(new FileLogger()),
|
||||||
|
_persistThread(NULL)
|
||||||
{
|
{
|
||||||
_applicationStartupTime = startup_time;
|
_applicationStartupTime = startup_time;
|
||||||
|
|
||||||
|
@ -177,7 +177,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
nodeList->addHook(&_voxels);
|
nodeList->addHook(&_voxels);
|
||||||
nodeList->addHook(this);
|
nodeList->addHook(this);
|
||||||
nodeList->addDomainListener(this);
|
nodeList->addDomainListener(this);
|
||||||
nodeList->addDomainListener(&_voxels);
|
|
||||||
|
|
||||||
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
|
// network receive thread and voxel parsing thread are both controlled by the --nonblocking command line
|
||||||
_enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking");
|
_enableProcessVoxelsThread = _enableNetworkThread = !cmdOptionExists(argc, constArgv, "--nonblocking");
|
||||||
|
@ -249,6 +248,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
||||||
|
|
||||||
// Set the sixense filtering
|
// Set the sixense filtering
|
||||||
_sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
_sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
|
@ -1434,6 +1434,8 @@ void Application::terminate() {
|
||||||
_voxelHideShowThread.terminate();
|
_voxelHideShowThread.terminate();
|
||||||
_voxelEditSender.terminate();
|
_voxelEditSender.terminate();
|
||||||
_particleEditSender.terminate();
|
_particleEditSender.terminate();
|
||||||
|
_persistThread->terminate();
|
||||||
|
_persistThread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) {
|
static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& dataBytes) {
|
||||||
|
@ -1933,6 +1935,9 @@ void Application::init() {
|
||||||
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
|
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
|
||||||
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
|
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
|
||||||
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
|
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
|
||||||
|
|
||||||
|
|
||||||
|
updateLocalOctreeCache(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::closeMirrorView() {
|
void Application::closeMirrorView() {
|
||||||
|
@ -2393,6 +2398,7 @@ void Application::updateThreads(float deltaTime) {
|
||||||
_voxelHideShowThread.threadRoutine();
|
_voxelHideShowThread.threadRoutine();
|
||||||
_voxelEditSender.threadRoutine();
|
_voxelEditSender.threadRoutine();
|
||||||
_particleEditSender.threadRoutine();
|
_particleEditSender.threadRoutine();
|
||||||
|
_persistThread->threadRoutine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4188,6 +4194,10 @@ void Application::domainChanged(QString domain) {
|
||||||
_voxelServerJurisdictions.clear();
|
_voxelServerJurisdictions.clear();
|
||||||
_octreeServerSceneStats.clear();
|
_octreeServerSceneStats.clear();
|
||||||
_particleServerJurisdictions.clear();
|
_particleServerJurisdictions.clear();
|
||||||
|
|
||||||
|
// reset our persist thread
|
||||||
|
qDebug() << "domainChanged()... domain=" << domain << " swapping persist cache\n";
|
||||||
|
updateLocalOctreeCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::nodeAdded(Node* node) {
|
void Application::nodeAdded(Node* node) {
|
||||||
|
@ -4523,3 +4533,47 @@ void Application::toggleLogDialog() {
|
||||||
_logDialog->close();
|
_logDialog->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Application::initAvatarAndViewFrustum() {
|
||||||
|
updateAvatar(0.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Application::getLocalVoxelCacheFileName() {
|
||||||
|
QString fileName = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||||
|
QDir logDir(fileName);
|
||||||
|
if (!logDir.exists(fileName)) {
|
||||||
|
logDir.mkdir(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileName.append(QString("/hifi.voxelscache."));
|
||||||
|
fileName.append(_profile.getLastDomain());
|
||||||
|
fileName.append(QString(".svo"));
|
||||||
|
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Application::updateLocalOctreeCache(bool firstTime) {
|
||||||
|
// only do this if we've already got a persistThread or we're told this is the first time
|
||||||
|
if (firstTime || _persistThread) {
|
||||||
|
|
||||||
|
if (_persistThread) {
|
||||||
|
_persistThread->terminate();
|
||||||
|
_persistThread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString localVoxelCacheFileName = getLocalVoxelCacheFileName();
|
||||||
|
const int LOCAL_CACHE_PERSIST_INTERVAL = 1000 * 10; // every 10 seconds
|
||||||
|
_persistThread = new OctreePersistThread(_voxels.getTree(),
|
||||||
|
localVoxelCacheFileName.toLocal8Bit().constData(),LOCAL_CACHE_PERSIST_INTERVAL);
|
||||||
|
|
||||||
|
qDebug() << "updateLocalOctreeCache()... localVoxelCacheFileName=" << localVoxelCacheFileName << "\n";
|
||||||
|
|
||||||
|
if (_persistThread) {
|
||||||
|
_voxels.beginLoadingLocalVoxelCache(); // while local voxels are importing, don't do individual node VBO updates
|
||||||
|
connect(_persistThread, SIGNAL(loadCompleted()), &_voxels, SLOT(localVoxelCacheLoaded()));
|
||||||
|
_persistThread->initialize(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -229,6 +229,7 @@ public slots:
|
||||||
void increaseVoxelSize();
|
void increaseVoxelSize();
|
||||||
void loadScript();
|
void loadScript();
|
||||||
void toggleLogDialog();
|
void toggleLogDialog();
|
||||||
|
void initAvatarAndViewFrustum();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -512,6 +513,11 @@ private:
|
||||||
QPointer<LogDialog> _logDialog;
|
QPointer<LogDialog> _logDialog;
|
||||||
|
|
||||||
FileLogger* _logger;
|
FileLogger* _logger;
|
||||||
|
|
||||||
|
OctreePersistThread* _persistThread;
|
||||||
|
|
||||||
|
QString getLocalVoxelCacheFileName();
|
||||||
|
void updateLocalOctreeCache(bool firstTime = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__interface__Application__) */
|
#endif /* defined(__interface__Application__) */
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
|
|
||||||
const bool VoxelSystem::DONT_BAIL_EARLY = false;
|
const bool VoxelSystem::DONT_BAIL_EARLY = false;
|
||||||
|
|
||||||
|
|
||||||
float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
|
float identityVerticesGlobalNormals[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 };
|
||||||
|
|
||||||
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7
|
float identityVertices[] = { 0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1, //0-7
|
||||||
|
@ -111,6 +110,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
||||||
_culledOnce = false;
|
_culledOnce = false;
|
||||||
_inhideOutOfView = false;
|
_inhideOutOfView = false;
|
||||||
_treeIsBusy = false;
|
_treeIsBusy = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::elementDeleted(OctreeElement* element) {
|
void VoxelSystem::elementDeleted(OctreeElement* element) {
|
||||||
|
@ -642,8 +642,6 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::setupNewVoxelsForDrawing() {
|
void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
|
|
||||||
|
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"setupNewVoxelsForDrawing()");
|
"setupNewVoxelsForDrawing()");
|
||||||
|
|
||||||
|
@ -703,6 +701,12 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
_setupNewVoxelsForDrawingLastFinished = end;
|
_setupNewVoxelsForDrawingLastFinished = end;
|
||||||
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
|
||||||
_inSetupNewVoxelsForDrawing = false;
|
_inSetupNewVoxelsForDrawing = false;
|
||||||
|
|
||||||
|
bool extraDebugging = Application::getInstance()->getLogger()->extraDebugging();
|
||||||
|
if (extraDebugging) {
|
||||||
|
qDebug("setupNewVoxelsForDrawing()... _voxelsUpdated=%lu...\n",_voxelsUpdated);
|
||||||
|
_viewFrustum->printDebugDetails();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) {
|
void VoxelSystem::setupNewVoxelsForDrawingSingleNode(bool allowBailEarly) {
|
||||||
|
@ -746,14 +750,12 @@ void VoxelSystem::checkForCulling() {
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()");
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "checkForCulling()");
|
||||||
uint64_t start = usecTimestampNow();
|
uint64_t start = usecTimestampNow();
|
||||||
|
|
||||||
|
|
||||||
// track how long its been since we were last moving. If we have recently moved then only use delta frustums, if
|
// track how long its been since we were last moving. If we have recently moved then only use delta frustums, if
|
||||||
// it's been a long time since we last moved, then go ahead and do a full frustum cull.
|
// it's been a long time since we last moved, then go ahead and do a full frustum cull.
|
||||||
if (isViewChanging()) {
|
if (isViewChanging()) {
|
||||||
_lastViewIsChanging = start;
|
_lastViewIsChanging = start;
|
||||||
}
|
}
|
||||||
uint64_t sinceLastMoving = (start - _lastViewIsChanging) / 1000;
|
uint64_t sinceLastMoving = (start - _lastViewIsChanging) / 1000;
|
||||||
|
|
||||||
bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS));
|
bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS));
|
||||||
|
|
||||||
// These has changed events will occur before we stop. So we need to remember this for when we finally have stopped
|
// These has changed events will occur before we stop. So we need to remember this for when we finally have stopped
|
||||||
|
@ -930,6 +932,11 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) {
|
||||||
voxel->calculateAverageFromChildren();
|
voxel->calculateAverageFromChildren();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for either voxels that should not render, or those that should render and are in view
|
||||||
|
// update their geometry in the array.if the voxel "should render" but is not in view, then
|
||||||
|
// it actually doesn't need to be rendered
|
||||||
|
if (!shouldRender || voxel->isInView(*_viewFrustum)) {
|
||||||
if (_writeRenderFullVBO) {
|
if (_writeRenderFullVBO) {
|
||||||
const bool DONT_REUSE_INDEX = false;
|
const bool DONT_REUSE_INDEX = false;
|
||||||
const bool FORCE_REDRAW = true;
|
const bool FORCE_REDRAW = true;
|
||||||
|
@ -939,6 +946,7 @@ int VoxelSystem::newTreeToArrays(VoxelTreeElement* voxel) {
|
||||||
const bool DONT_FORCE_REDRAW = false;
|
const bool DONT_FORCE_REDRAW = false;
|
||||||
voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
|
voxelsUpdated += updateNodeInArrays(voxel, REUSE_INDEX, DONT_FORCE_REDRAW);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
|
voxel->clearDirtyBit(); // clear the dirty bit, do this before we potentially delete things.
|
||||||
|
|
||||||
return voxelsUpdated;
|
return voxelsUpdated;
|
||||||
|
@ -959,7 +967,7 @@ int VoxelSystem::forceRemoveNodeFromArrays(VoxelTreeElement* node) {
|
||||||
// If this node has not yet been written to the array, then add it to the end of the array.
|
// If this node has not yet been written to the array, then add it to the end of the array.
|
||||||
glBufferIndex nodeIndex = node->getBufferIndex();
|
glBufferIndex nodeIndex = node->getBufferIndex();
|
||||||
node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
|
node->setBufferIndex(GLBUFFER_INDEX_UNKNOWN);
|
||||||
freeBufferIndex(nodeIndex); // NOTE: This is make the node invisible!
|
freeBufferIndex(nodeIndex); // NOTE: This will make the node invisible!
|
||||||
return 1; // updated!
|
return 1; // updated!
|
||||||
}
|
}
|
||||||
return 0; // not-updated
|
return 0; // not-updated
|
||||||
|
@ -1016,7 +1024,7 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo
|
||||||
void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||||
float voxelScale, const nodeColor& color) {
|
float voxelScale, const nodeColor& color) {
|
||||||
|
|
||||||
if (_initialized) {
|
if (_initialized && nodeIndex <= _maxVoxels) {
|
||||||
_writeVoxelDirtyArray[nodeIndex] = true;
|
_writeVoxelDirtyArray[nodeIndex] = true;
|
||||||
|
|
||||||
if (_useVoxelShader) {
|
if (_useVoxelShader) {
|
||||||
|
@ -1074,12 +1082,14 @@ void VoxelSystem::init() {
|
||||||
|
|
||||||
// our own _removedVoxels doesn't need to be notified of voxel deletes
|
// our own _removedVoxels doesn't need to be notified of voxel deletes
|
||||||
VoxelTreeElement::removeDeleteHook(&_removedVoxels);
|
VoxelTreeElement::removeDeleteHook(&_removedVoxels);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::changeTree(VoxelTree* newTree) {
|
void VoxelSystem::changeTree(VoxelTree* newTree) {
|
||||||
disconnect(_tree, 0, this, 0);
|
disconnect(_tree, 0, this, 0);
|
||||||
|
|
||||||
_tree = newTree;
|
_tree = newTree;
|
||||||
|
|
||||||
_tree->setDirtyBit();
|
_tree->setDirtyBit();
|
||||||
_tree->getRoot()->setVoxelSystem(this);
|
_tree->getRoot()->setVoxelSystem(this);
|
||||||
|
|
||||||
|
@ -1880,6 +1890,7 @@ public:
|
||||||
unsigned long nodesOutsideInside;
|
unsigned long nodesOutsideInside;
|
||||||
unsigned long nodesInsideOutside;
|
unsigned long nodesInsideOutside;
|
||||||
unsigned long nodesOutsideOutside;
|
unsigned long nodesOutsideOutside;
|
||||||
|
unsigned long nodesShown;
|
||||||
|
|
||||||
hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree,
|
hideOutOfViewArgs(VoxelSystem* voxelSystem, VoxelTree* tree,
|
||||||
bool culledOnce, bool widenViewFrustum, bool wantDeltaFrustums) :
|
bool culledOnce, bool widenViewFrustum, bool wantDeltaFrustums) :
|
||||||
|
@ -1898,7 +1909,8 @@ public:
|
||||||
nodesIntersectInside(0),
|
nodesIntersectInside(0),
|
||||||
nodesOutsideInside(0),
|
nodesOutsideInside(0),
|
||||||
nodesInsideOutside(0),
|
nodesInsideOutside(0),
|
||||||
nodesOutsideOutside(0)
|
nodesOutsideOutside(0),
|
||||||
|
nodesShown(0)
|
||||||
{
|
{
|
||||||
// Widen the FOV for trimming
|
// Widen the FOV for trimming
|
||||||
if (widenViewFrustum) {
|
if (widenViewFrustum) {
|
||||||
|
@ -1923,6 +1935,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
||||||
PerformanceWarning warn(showDebugDetails, "hideOutOfView()");
|
PerformanceWarning warn(showDebugDetails, "hideOutOfView()");
|
||||||
bool widenFrustum = true;
|
bool widenFrustum = true;
|
||||||
|
|
||||||
|
|
||||||
// When using "delta" view frustums and only hide/show items that are in the difference
|
// When using "delta" view frustums and only hide/show items that are in the difference
|
||||||
// between the two view frustums. There are some potential problems with this mode.
|
// between the two view frustums. There are some potential problems with this mode.
|
||||||
//
|
//
|
||||||
|
@ -1964,15 +1977,18 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
||||||
setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
|
setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extraDebugDetails = Application::getInstance()->getLogger()->extraDebugging();
|
bool extraDebugDetails = false; // Application::getInstance()->getLogger()->extraDebugging();
|
||||||
if (extraDebugDetails) {
|
if (extraDebugDetails) {
|
||||||
qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n",
|
qDebug("hideOutOfView() scanned=%ld removed=%ld show=%ld inside=%ld intersect=%ld outside=%ld\n",
|
||||||
args.nodesScanned, args.nodesRemoved, args.nodesInside,
|
args.nodesScanned, args.nodesRemoved, args.nodesShown, args.nodesInside,
|
||||||
args.nodesIntersect, args.nodesOutside
|
args.nodesIntersect, args.nodesOutside
|
||||||
);
|
);
|
||||||
qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n",
|
qDebug(" inside/inside=%ld intersect/inside=%ld outside/outside=%ld\n",
|
||||||
args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside
|
args.nodesInsideInside, args.nodesIntersectInside, args.nodesOutsideOutside
|
||||||
);
|
);
|
||||||
|
|
||||||
|
qDebug() << "args.thisViewFrustum....\n";
|
||||||
|
args.thisViewFrustum.printDebugDetails();
|
||||||
}
|
}
|
||||||
_inhideOutOfView = false;
|
_inhideOutOfView = false;
|
||||||
}
|
}
|
||||||
|
@ -2047,6 +2063,7 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat
|
||||||
// These are both needed to force redraw...
|
// These are both needed to force redraw...
|
||||||
voxel->setDirtyBit();
|
voxel->setDirtyBit();
|
||||||
voxel->markWithChangedTime();
|
voxel->markWithChangedTime();
|
||||||
|
args->nodesShown++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // keep recursing!
|
return true; // keep recursing!
|
||||||
|
@ -2129,6 +2146,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData
|
||||||
// here because we know will block any children anyway
|
// here because we know will block any children anyway
|
||||||
if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) {
|
if (voxel->getShouldRender() && !voxel->isKnownBufferIndex()) {
|
||||||
voxel->setDirtyBit(); // will this make it draw?
|
voxel->setDirtyBit(); // will this make it draw?
|
||||||
|
args->nodesShown++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2694,11 +2712,6 @@ void VoxelSystem::nodeKilled(Node* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelSystem::domainChanged(QString domain) {
|
|
||||||
killLocalVoxels();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long VoxelSystem::getFreeMemoryGPU() {
|
unsigned long VoxelSystem::getFreeMemoryGPU() {
|
||||||
// We can't ask all GPUs how much memory they have in use, but we can ask them about how much is free.
|
// We can't ask all GPUs how much memory they have in use, but we can ask them about how much is free.
|
||||||
// So, we can record the free memory before we create our VBOs and the free memory after, and get a basic
|
// So, we can record the free memory before we create our VBOs and the free memory after, and get a basic
|
||||||
|
@ -2763,4 +2776,26 @@ void VoxelSystem::unlockTree() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VoxelSystem::localVoxelCacheLoaded() {
|
||||||
|
qDebug() << "localVoxelCacheLoaded()\n";
|
||||||
|
|
||||||
|
// Make sure that the application has properly set up the view frustum for our loaded state
|
||||||
|
Application::getInstance()->initAvatarAndViewFrustum();
|
||||||
|
|
||||||
|
_tree->setDirtyBit(); // make sure the tree thinks it's dirty
|
||||||
|
_setupNewVoxelsForDrawingLastFinished = 0; // don't allow the setupNewVoxelsForDrawing() shortcuts
|
||||||
|
_writeRenderFullVBO = true; // this will disable individual node updates, was reset by killLocalVoxels()
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
_inhideOutOfView = false; // reenable hideOutOfView behavior
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::beginLoadingLocalVoxelCache() {
|
||||||
|
qDebug() << "beginLoadingLocalVoxelCache()\n";
|
||||||
|
_writeRenderFullVBO = true; // this will disable individual node updates
|
||||||
|
_inhideOutOfView = true; // this will disable hidOutOfView which we want to do until local cache is loaded
|
||||||
|
killLocalVoxels();
|
||||||
|
qDebug() << "DONE beginLoadingLocalVoxelCache()\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <NodeData.h>
|
#include <NodeData.h>
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
#include <VoxelTree.h>
|
#include <VoxelTree.h>
|
||||||
|
#include <OctreePersistThread.h>
|
||||||
|
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
@ -37,7 +38,7 @@ struct VoxelShaderVBOData
|
||||||
|
|
||||||
|
|
||||||
class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook,
|
class VoxelSystem : public NodeData, public OctreeElementDeleteHook, public OctreeElementUpdateHook,
|
||||||
public NodeListHook, public DomainChangeListener {
|
public NodeListHook {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
friend class VoxelHideShowThread;
|
friend class VoxelHideShowThread;
|
||||||
|
@ -113,7 +114,6 @@ public:
|
||||||
virtual void elementUpdated(OctreeElement* element);
|
virtual void elementUpdated(OctreeElement* element);
|
||||||
virtual void nodeAdded(Node* node);
|
virtual void nodeAdded(Node* node);
|
||||||
virtual void nodeKilled(Node* node);
|
virtual void nodeKilled(Node* node);
|
||||||
virtual void domainChanged(QString domain);
|
|
||||||
|
|
||||||
bool treeIsBusy() const { return _treeIsBusy; }
|
bool treeIsBusy() const { return _treeIsBusy; }
|
||||||
|
|
||||||
|
@ -146,6 +146,9 @@ public slots:
|
||||||
void setUseVoxelShader(bool useVoxelShader);
|
void setUseVoxelShader(bool useVoxelShader);
|
||||||
void setVoxelsAsPoints(bool voxelsAsPoints);
|
void setVoxelsAsPoints(bool voxelsAsPoints);
|
||||||
|
|
||||||
|
void localVoxelCacheLoaded();
|
||||||
|
void beginLoadingLocalVoxelCache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float _treeScale;
|
float _treeScale;
|
||||||
int _maxVoxels;
|
int _maxVoxels;
|
||||||
|
@ -269,7 +272,7 @@ private:
|
||||||
|
|
||||||
void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]);
|
void setupFaceIndices(GLuint& faceVBOID, GLubyte faceIdentityIndices[]);
|
||||||
|
|
||||||
int newTreeToArrays(VoxelTreeElement *currentNode);
|
int newTreeToArrays(VoxelTreeElement* currentNode);
|
||||||
void cleanupRemovedVoxels();
|
void cleanupRemovedVoxels();
|
||||||
|
|
||||||
void copyWrittenDataToReadArrays(bool fullVBOs);
|
void copyWrittenDataToReadArrays(bool fullVBOs);
|
||||||
|
|
|
@ -49,8 +49,10 @@ bool OctreeQueryNode::packetIsDuplicate() const {
|
||||||
// since our packets now include header information, like sequence number, and createTime, we can't just do a memcmp
|
// since our packets now include header information, like sequence number, and createTime, we can't just do a memcmp
|
||||||
// of the entire packet, we need to compare only the packet content...
|
// of the entire packet, we need to compare only the packet content...
|
||||||
if (_lastOctreePacketLength == getPacketLength()) {
|
if (_lastOctreePacketLength == getPacketLength()) {
|
||||||
return memcmp(_lastOctreePacket + OCTREE_PACKET_HEADER_SIZE,
|
if (memcmp(_lastOctreePacket + OCTREE_PACKET_HEADER_SIZE,
|
||||||
_octreePacket+OCTREE_PACKET_HEADER_SIZE , getPacketLength() - OCTREE_PACKET_HEADER_SIZE == 0);
|
_octreePacket + OCTREE_PACKET_HEADER_SIZE , getPacketLength() - OCTREE_PACKET_HEADER_SIZE) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -572,7 +572,7 @@ bool findRayIntersectionOp(OctreeElement* node, void* extraData) {
|
||||||
|
|
||||||
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
bool Octree::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||||
OctreeElement*& node, float& distance, BoxFace& face) {
|
OctreeElement*& node, float& distance, BoxFace& face) {
|
||||||
RayArgs args = { origin / static_cast<float>(TREE_SCALE), direction, node, distance, face };
|
RayArgs args = { origin / (float)(TREE_SCALE), direction, node, distance, face };
|
||||||
recurseTreeWithOperation(findRayIntersectionOp, &args);
|
recurseTreeWithOperation(findRayIntersectionOp, &args);
|
||||||
return args.found;
|
return args.found;
|
||||||
}
|
}
|
||||||
|
@ -600,7 +600,7 @@ bool findSpherePenetrationOp(OctreeElement* element, void* extraData) {
|
||||||
if (element->hasContent()) {
|
if (element->hasContent()) {
|
||||||
glm::vec3 elementPenetration;
|
glm::vec3 elementPenetration;
|
||||||
if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) {
|
if (element->findSpherePenetration(args->center, args->radius, elementPenetration, &args->penetratedObject)) {
|
||||||
args->penetration = addPenetrations(args->penetration, elementPenetration * static_cast<float>(TREE_SCALE));
|
args->penetration = addPenetrations(args->penetration, elementPenetration * (float)(TREE_SCALE));
|
||||||
args->found = true;
|
args->found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,8 +611,8 @@ bool Octree::findSpherePenetration(const glm::vec3& center, float radius, glm::v
|
||||||
void** penetratedObject) {
|
void** penetratedObject) {
|
||||||
|
|
||||||
SphereArgs args = {
|
SphereArgs args = {
|
||||||
center / static_cast<float>(TREE_SCALE),
|
center / (float)(TREE_SCALE),
|
||||||
radius / static_cast<float>(TREE_SCALE),
|
radius / (float)(TREE_SCALE),
|
||||||
penetration,
|
penetration,
|
||||||
false,
|
false,
|
||||||
NULL };
|
NULL };
|
||||||
|
@ -647,7 +647,7 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) {
|
||||||
if (node->hasContent()) {
|
if (node->hasContent()) {
|
||||||
glm::vec3 nodePenetration;
|
glm::vec3 nodePenetration;
|
||||||
if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) {
|
if (box.findCapsulePenetration(args->start, args->end, args->radius, nodePenetration)) {
|
||||||
args->penetration = addPenetrations(args->penetration, nodePenetration * static_cast<float>(TREE_SCALE));
|
args->penetration = addPenetrations(args->penetration, nodePenetration * (float)(TREE_SCALE));
|
||||||
args->found = true;
|
args->found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,9 +656,9 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) {
|
||||||
|
|
||||||
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) {
|
bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) {
|
||||||
CapsuleArgs args = {
|
CapsuleArgs args = {
|
||||||
start / static_cast<float>(TREE_SCALE),
|
start / (float)(TREE_SCALE),
|
||||||
end / static_cast<float>(TREE_SCALE),
|
end / (float)(TREE_SCALE),
|
||||||
radius / static_cast<float>(TREE_SCALE),
|
radius / (float)(TREE_SCALE),
|
||||||
penetration };
|
penetration };
|
||||||
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
penetration = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
|
recurseTreeWithOperation(findCapsulePenetrationOp, &args);
|
||||||
|
|
|
@ -13,9 +13,8 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "OctreePersistThread.h"
|
#include "OctreePersistThread.h"
|
||||||
#include "OctreeServer.h"
|
|
||||||
|
|
||||||
OctreePersistThread::OctreePersistThread(Octree* tree, const char* filename, int persistInterval) :
|
OctreePersistThread::OctreePersistThread(Octree* tree, const QString& filename, int persistInterval) :
|
||||||
_tree(tree),
|
_tree(tree),
|
||||||
_filename(filename),
|
_filename(filename),
|
||||||
_persistInterval(persistInterval),
|
_persistInterval(persistInterval),
|
||||||
|
@ -27,14 +26,14 @@ bool OctreePersistThread::process() {
|
||||||
|
|
||||||
if (!_initialLoadComplete) {
|
if (!_initialLoadComplete) {
|
||||||
uint64_t loadStarted = usecTimestampNow();
|
uint64_t loadStarted = usecTimestampNow();
|
||||||
qDebug("loading Octrees from file: %s...\n", _filename);
|
qDebug() << "loading Octrees from file: " << _filename << "...\n";
|
||||||
|
|
||||||
bool persistantFileRead;
|
bool persistantFileRead;
|
||||||
|
|
||||||
_tree->lockForWrite();
|
_tree->lockForWrite();
|
||||||
{
|
{
|
||||||
PerformanceWarning warn(true, "Loading Octree File", true);
|
PerformanceWarning warn(true, "Loading Octree File", true);
|
||||||
persistantFileRead = _tree->readFromSVOFile(_filename);
|
persistantFileRead = _tree->readFromSVOFile(_filename.toLocal8Bit().constData());
|
||||||
}
|
}
|
||||||
_tree->unlock();
|
_tree->unlock();
|
||||||
|
|
||||||
|
@ -60,6 +59,8 @@ bool OctreePersistThread::process() {
|
||||||
|
|
||||||
_initialLoadComplete = true;
|
_initialLoadComplete = true;
|
||||||
_lastCheck = usecTimestampNow(); // we just loaded, no need to save again
|
_lastCheck = usecTimestampNow(); // we just loaded, no need to save again
|
||||||
|
|
||||||
|
emit loadCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStillRunning()) {
|
if (isStillRunning()) {
|
||||||
|
@ -80,8 +81,8 @@ bool OctreePersistThread::process() {
|
||||||
// check the dirty bit and persist here...
|
// check the dirty bit and persist here...
|
||||||
_lastCheck = usecTimestampNow();
|
_lastCheck = usecTimestampNow();
|
||||||
if (_tree->isDirty()) {
|
if (_tree->isDirty()) {
|
||||||
qDebug("saving Octrees to file %s...\n",_filename);
|
qDebug() << "saving Octrees to file " << _filename << "...\n";
|
||||||
_tree->writeToSVOFile(_filename);
|
_tree->writeToSVOFile(_filename.toLocal8Bit().constData());
|
||||||
_tree->clearDirtyBit(); // tree is clean after saving
|
_tree->clearDirtyBit(); // tree is clean after saving
|
||||||
qDebug("DONE saving Octrees to file...\n");
|
qDebug("DONE saving Octrees to file...\n");
|
||||||
}
|
}
|
|
@ -11,27 +11,32 @@
|
||||||
#ifndef __Octree_server__OctreePersistThread__
|
#ifndef __Octree_server__OctreePersistThread__
|
||||||
#define __Octree_server__OctreePersistThread__
|
#define __Octree_server__OctreePersistThread__
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
#include <GenericThread.h>
|
#include <GenericThread.h>
|
||||||
#include <Octree.h>
|
#include "Octree.h"
|
||||||
|
|
||||||
/// Generalized threaded processor for handling received inbound packets.
|
/// Generalized threaded processor for handling received inbound packets.
|
||||||
class OctreePersistThread : public virtual GenericThread {
|
class OctreePersistThread : public GenericThread {
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static const int DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
static const int DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
|
||||||
|
|
||||||
OctreePersistThread(Octree* tree, const char* filename, int persistInterval = DEFAULT_PERSIST_INTERVAL);
|
OctreePersistThread(Octree* tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL);
|
||||||
|
|
||||||
bool isInitialLoadComplete() const { return _initialLoadComplete; }
|
bool isInitialLoadComplete() const { return _initialLoadComplete; }
|
||||||
|
|
||||||
time_t* getLoadCompleted() { return &_loadCompleted; }
|
time_t* getLoadCompleted() { return &_loadCompleted; }
|
||||||
uint64_t getLoadElapsedTime() const { return _loadTimeUSecs; }
|
uint64_t getLoadElapsedTime() const { return _loadTimeUSecs; }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void loadCompleted();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Implements generic processing behavior for this thread.
|
/// Implements generic processing behavior for this thread.
|
||||||
virtual bool process();
|
virtual bool process();
|
||||||
private:
|
private:
|
||||||
Octree* _tree;
|
Octree* _tree;
|
||||||
const char* _filename;
|
QString _filename;
|
||||||
int _persistInterval;
|
int _persistInterval;
|
||||||
bool _initialLoadComplete;
|
bool _initialLoadComplete;
|
||||||
|
|
|
@ -67,8 +67,8 @@ void ParticleCollisionSystem::checkParticle(Particle* particle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE);
|
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE);
|
float radius = particle->getRadius() * (float)(TREE_SCALE);
|
||||||
const float ELASTICITY = 0.4f;
|
const float ELASTICITY = 0.4f;
|
||||||
const float DAMPING = 0.0f;
|
const float DAMPING = 0.0f;
|
||||||
const float COLLISION_FREQUENCY = 0.5f;
|
const float COLLISION_FREQUENCY = 0.5f;
|
||||||
|
@ -79,7 +79,7 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
// let the particles run their collision scripts if they have them
|
// let the particles run their collision scripts if they have them
|
||||||
particle->collisionWithVoxel(voxelDetails);
|
particle->collisionWithVoxel(voxelDetails);
|
||||||
|
|
||||||
penetration /= static_cast<float>(TREE_SCALE);
|
penetration /= (float)(TREE_SCALE);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING);
|
applyHardCollision(particle, penetration, ELASTICITY, DAMPING);
|
||||||
|
|
||||||
|
@ -88,8 +88,8 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) {
|
void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) {
|
||||||
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE);
|
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE);
|
float radius = particle->getRadius() * (float)(TREE_SCALE);
|
||||||
const float ELASTICITY = 1.4f;
|
const float ELASTICITY = 1.4f;
|
||||||
const float DAMPING = 0.0f;
|
const float DAMPING = 0.0f;
|
||||||
const float COLLISION_FREQUENCY = 0.5f;
|
const float COLLISION_FREQUENCY = 0.5f;
|
||||||
|
@ -101,7 +101,7 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) {
|
||||||
particle->collisionWithParticle(penetratedParticle);
|
particle->collisionWithParticle(penetratedParticle);
|
||||||
penetratedParticle->collisionWithParticle(particle);
|
penetratedParticle->collisionWithParticle(particle);
|
||||||
|
|
||||||
penetration /= static_cast<float>(TREE_SCALE);
|
penetration /= (float)(TREE_SCALE);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
||||||
|
|
||||||
// apply a hard collision to both particles of half the penetration each
|
// apply a hard collision to both particles of half the penetration each
|
||||||
|
@ -133,8 +133,8 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("updateCollisionWithAvatars()...\n");
|
//printf("updateCollisionWithAvatars()...\n");
|
||||||
glm::vec3 center = particle->getPosition() * static_cast<float>(TREE_SCALE);
|
glm::vec3 center = particle->getPosition() * (float)(TREE_SCALE);
|
||||||
float radius = particle->getRadius() * static_cast<float>(TREE_SCALE);
|
float radius = particle->getRadius() * (float)(TREE_SCALE);
|
||||||
const float ELASTICITY = 0.4f;
|
const float ELASTICITY = 0.4f;
|
||||||
const float DAMPING = 0.0f;
|
const float DAMPING = 0.0f;
|
||||||
const float COLLISION_FREQUENCY = 0.5f;
|
const float COLLISION_FREQUENCY = 0.5f;
|
||||||
|
@ -156,13 +156,13 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
||||||
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
|
// TODO: dot collidingPalm and hand velocities and skip collision when they are moving apart.
|
||||||
// apply a hard collision when ball collides with hand
|
// apply a hard collision when ball collides with hand
|
||||||
penetration /= static_cast<float>(TREE_SCALE);
|
penetration /= (float)(TREE_SCALE);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
||||||
|
|
||||||
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
||||||
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
||||||
if (collidingPalm) {
|
if (collidingPalm) {
|
||||||
glm::vec3 palmVelocity = collidingPalm->getVelocity() / static_cast<float>(TREE_SCALE);
|
glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)(TREE_SCALE);
|
||||||
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
||||||
addedVelocity = palmVelocity;
|
addedVelocity = palmVelocity;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
||||||
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
||||||
// apply hard collision when particle collides with avatar
|
// apply hard collision when particle collides with avatar
|
||||||
penetration /= static_cast<float>(TREE_SCALE);
|
penetration /= (float)(TREE_SCALE);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
||||||
glm::vec3 addedVelocity = avatar->getVelocity();
|
glm::vec3 addedVelocity = avatar->getVelocity();
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
||||||
|
@ -191,13 +191,13 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
|
|
||||||
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
if (handData->findSpherePenetration(center, radius, penetration, collidingPalm)) {
|
||||||
// apply a hard collision when ball collides with hand
|
// apply a hard collision when ball collides with hand
|
||||||
penetration /= static_cast<float>(TREE_SCALE);
|
penetration /= (float)(TREE_SCALE);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
||||||
|
|
||||||
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
// determine if the palm that collided was moving, if so, then we add that palm velocity as well...
|
||||||
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
glm::vec3 addedVelocity = NO_ADDED_VELOCITY;
|
||||||
if (collidingPalm) {
|
if (collidingPalm) {
|
||||||
glm::vec3 palmVelocity = collidingPalm->getVelocity() / static_cast<float>(TREE_SCALE);
|
glm::vec3 palmVelocity = collidingPalm->getVelocity() / (float)(TREE_SCALE);
|
||||||
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
//printf("collidingPalm Velocity=%f,%f,%f\n", palmVelocity.x, palmVelocity.y, palmVelocity.z);
|
||||||
addedVelocity = palmVelocity;
|
addedVelocity = palmVelocity;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
||||||
|
|
||||||
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
} else if (avatar->findSpherePenetration(center, radius, penetration)) {
|
||||||
penetration /= static_cast<float>(TREE_SCALE);
|
penetration /= (float)(TREE_SCALE);
|
||||||
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
updateCollisionSound(particle, penetration, COLLISION_FREQUENCY);
|
||||||
glm::vec3 addedVelocity = avatar->getVelocity();
|
glm::vec3 addedVelocity = avatar->getVelocity();
|
||||||
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
applyHardCollision(particle, penetration, ELASTICITY, DAMPING, addedVelocity);
|
||||||
|
@ -231,7 +231,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm::
|
||||||
float velocityDotPenetration = glm::dot(velocity, penetration);
|
float velocityDotPenetration = glm::dot(velocity, penetration);
|
||||||
if (velocityDotPenetration > EPSILON) {
|
if (velocityDotPenetration > EPSILON) {
|
||||||
position -= penetration;
|
position -= penetration;
|
||||||
static float HALTING_VELOCITY = 0.2f / static_cast<float>(TREE_SCALE);
|
static float HALTING_VELOCITY = 0.2f / (float)(TREE_SCALE);
|
||||||
// cancel out the velocity component in the direction of penetration
|
// cancel out the velocity component in the direction of penetration
|
||||||
|
|
||||||
float penetrationLength = glm::length(penetration);
|
float penetrationLength = glm::length(penetration);
|
||||||
|
@ -263,12 +263,12 @@ void ParticleCollisionSystem::updateCollisionSound(Particle* particle, const glm
|
||||||
const float COLLISION_LOUDNESS = 1.f;
|
const float COLLISION_LOUDNESS = 1.f;
|
||||||
const float DURATION_SCALING = 0.004f;
|
const float DURATION_SCALING = 0.004f;
|
||||||
const float NOISE_SCALING = 0.1f;
|
const float NOISE_SCALING = 0.1f;
|
||||||
glm::vec3 velocity = particle->getVelocity() * static_cast<float>(TREE_SCALE);
|
glm::vec3 velocity = particle->getVelocity() * (float)(TREE_SCALE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// how do we want to handle this??
|
// how do we want to handle this??
|
||||||
//
|
//
|
||||||
glm::vec3 gravity = particle->getGravity() * static_cast<float>(TREE_SCALE);
|
glm::vec3 gravity = particle->getGravity() * (float)(TREE_SCALE);
|
||||||
|
|
||||||
if (glm::length(gravity) > EPSILON) {
|
if (glm::length(gravity) > EPSILON) {
|
||||||
// If gravity is on, remove the effect of gravity on velocity for this
|
// If gravity is on, remove the effect of gravity on velocity for this
|
||||||
|
|
|
@ -11,11 +11,14 @@
|
||||||
#ifndef __shared__GenericThread__
|
#ifndef __shared__GenericThread__
|
||||||
#define __shared__GenericThread__
|
#define __shared__GenericThread__
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
/// A basic generic "thread" class. Handles a single thread of control within the application. Can operate in non-threaded
|
/// A basic generic "thread" class. Handles a single thread of control within the application. Can operate in non-threaded
|
||||||
/// mode but caller must regularly call threadRoutine() method.
|
/// mode but caller must regularly call threadRoutine() method.
|
||||||
class GenericThread {
|
class GenericThread : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
GenericThread();
|
GenericThread();
|
||||||
virtual ~GenericThread();
|
virtual ~GenericThread();
|
||||||
|
|
Loading…
Reference in a new issue