This commit is contained in:
Philip Rosedale 2014-03-27 15:16:11 -07:00
commit c8cacf75f3
18 changed files with 169 additions and 58 deletions

View file

@ -138,7 +138,11 @@ void Agent::run() {
ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent);
NodeList* nodeList = NodeList::getInstance(); NodeList* nodeList = NodeList::getInstance();
nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet()
<< NodeType::AudioMixer
<< NodeType::AvatarMixer
<< NodeType::VoxelServer
<< NodeType::ParticleServer);
// figure out the URL for the script for this agent assignment // figure out the URL for the script for this agent assignment
QString scriptURLString("http://%1:8080/assignment/%2"); QString scriptURLString("http://%1:8080/assignment/%2");

View file

@ -21,8 +21,9 @@ quint64 endSceneSleepTime = 0;
OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer node) : OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer node) :
_myServer(myServer), _myServer(myServer),
_node(node), _nodeUUID(node->getUUID()),
_packetData(), _packetData(),
_nodeMissingCount(0),
_processLock(), _processLock(),
_isShuttingDown(false) _isShuttingDown(false)
{ {
@ -43,46 +44,68 @@ OctreeSendThread::~OctreeSendThread() {
} }
qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected " qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected "
"- ending sending thread [" << this << "]"; "- ending sending thread [" << this << "]";
_node.clear();
OctreeServer::clientDisconnected(); OctreeServer::clientDisconnected();
} }
void OctreeSendThread::setIsShuttingDown() { void OctreeSendThread::setIsShuttingDown() {
QMutexLocker locker(&_processLock); // this will cause us to wait till the process loop is complete
_isShuttingDown = true; _isShuttingDown = true;
OctreeServer::stopTrackingThread(this); OctreeServer::stopTrackingThread(this);
// this will cause us to wait till the process loop is complete, we do this after we change _isShuttingDown
QMutexLocker locker(&_processLock);
} }
bool OctreeSendThread::process() { bool OctreeSendThread::process() {
if (_isShuttingDown) {
return false; // exit early if we're shutting down
}
OctreeServer::didProcess(this); OctreeServer::didProcess(this);
float lockWaitElapsedUsec = OctreeServer::SKIP_TIME; float lockWaitElapsedUsec = OctreeServer::SKIP_TIME;
quint64 lockWaitStart = usecTimestampNow(); quint64 lockWaitStart = usecTimestampNow();
QMutexLocker locker(&_processLock); _processLock.lock();
quint64 lockWaitEnd = usecTimestampNow(); quint64 lockWaitEnd = usecTimestampNow();
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart); lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
OctreeServer::trackProcessWaitTime(lockWaitElapsedUsec); OctreeServer::trackProcessWaitTime(lockWaitElapsedUsec);
if (_isShuttingDown) {
return false; // exit early if we're shutting down
}
quint64 start = usecTimestampNow(); quint64 start = usecTimestampNow();
// don't do any send processing until the initial load of the octree is complete... // don't do any send processing until the initial load of the octree is complete...
if (_myServer->isInitialLoadComplete()) { if (_myServer->isInitialLoadComplete()) {
if (!_node.isNull()) { SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID, false);
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(_node->getLinkedData()); if (node) {
_nodeMissingCount = 0;
OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(node->getLinkedData());
// Sometimes the node data has not yet been linked, in which case we can't really do anything // Sometimes the node data has not yet been linked, in which case we can't really do anything
if (nodeData && !nodeData->isShuttingDown()) { if (nodeData && !nodeData->isShuttingDown()) {
bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
packetDistributor(_node, nodeData, viewFrustumChanged); packetDistributor(node, nodeData, viewFrustumChanged);
}
} else {
_nodeMissingCount++;
const int MANY_FAILED_LOCKS = 1;
if (_nodeMissingCount >= MANY_FAILED_LOCKS) {
QString safeServerName("Octree");
if (_myServer) {
safeServerName = _myServer->getMyServerName();
}
qDebug() << qPrintable(safeServerName) << "server: sending thread [" << this << "]"
<< "failed to get nodeWithUUID() " << _nodeUUID <<". Failed:" << _nodeMissingCount << "times";
} }
} }
} }
_processLock.unlock();
if (_isShuttingDown) {
return false; // exit early if we're shutting down
}
// Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap // Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap
if (isStillRunning()) { if (isStillRunning()) {
// dynamically sleep until we need to fire off the next set of octree elements // dynamically sleep until we need to fire off the next set of octree elements

View file

@ -38,14 +38,15 @@ protected:
virtual bool process(); virtual bool process();
private: private:
SharedNodePointer _node;
OctreeServer* _myServer; OctreeServer* _myServer;
QUuid _nodeUUID;
int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent);
int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged); int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged);
OctreePacketData _packetData; OctreePacketData _packetData;
int _nodeMissingCount;
QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing
bool _isShuttingDown; bool _isShuttingDown;
}; };

View file

@ -1160,7 +1160,6 @@ QString OctreeServer::getStatusLink() {
} }
void OctreeServer::sendStatsPacket() { void OctreeServer::sendStatsPacket() {
// TODO: we have too many stats to fit in a single MTU... so for now, we break it into multiple JSON objects and // TODO: we have too many stats to fit in a single MTU... so for now, we break it into multiple JSON objects and
// send them separately. What we really should do is change the NodeList::sendStatsToDomainServer() to handle the // send them separately. What we really should do is change the NodeList::sendStatsToDomainServer() to handle the
// the following features: // the following features:
@ -1241,59 +1240,78 @@ QMap<OctreeSendThread*, quint64> OctreeServer::_threadsDidPacketDistributor;
QMap<OctreeSendThread*, quint64> OctreeServer::_threadsDidHandlePacketSend; QMap<OctreeSendThread*, quint64> OctreeServer::_threadsDidHandlePacketSend;
QMap<OctreeSendThread*, quint64> OctreeServer::_threadsDidCallWriteDatagram; QMap<OctreeSendThread*, quint64> OctreeServer::_threadsDidCallWriteDatagram;
QMutex OctreeServer::_threadsDidProcessMutex;
QMutex OctreeServer::_threadsDidPacketDistributorMutex;
QMutex OctreeServer::_threadsDidHandlePacketSendMutex;
QMutex OctreeServer::_threadsDidCallWriteDatagramMutex;
void OctreeServer::didProcess(OctreeSendThread* thread) { void OctreeServer::didProcess(OctreeSendThread* thread) {
QMutexLocker locker(&_threadsDidProcessMutex);
_threadsDidProcess[thread] = usecTimestampNow(); _threadsDidProcess[thread] = usecTimestampNow();
} }
void OctreeServer::didPacketDistributor(OctreeSendThread* thread) { void OctreeServer::didPacketDistributor(OctreeSendThread* thread) {
QMutexLocker locker(&_threadsDidPacketDistributorMutex);
_threadsDidPacketDistributor[thread] = usecTimestampNow(); _threadsDidPacketDistributor[thread] = usecTimestampNow();
} }
void OctreeServer::didHandlePacketSend(OctreeSendThread* thread) { void OctreeServer::didHandlePacketSend(OctreeSendThread* thread) {
QMutexLocker locker(&_threadsDidHandlePacketSendMutex);
_threadsDidHandlePacketSend[thread] = usecTimestampNow(); _threadsDidHandlePacketSend[thread] = usecTimestampNow();
} }
void OctreeServer::didCallWriteDatagram(OctreeSendThread* thread) { void OctreeServer::didCallWriteDatagram(OctreeSendThread* thread) {
QMutexLocker locker(&_threadsDidCallWriteDatagramMutex);
_threadsDidCallWriteDatagram[thread] = usecTimestampNow(); _threadsDidCallWriteDatagram[thread] = usecTimestampNow();
} }
void OctreeServer::stopTrackingThread(OctreeSendThread* thread) { void OctreeServer::stopTrackingThread(OctreeSendThread* thread) {
QMutexLocker lockerA(&_threadsDidProcessMutex);
QMutexLocker lockerB(&_threadsDidPacketDistributorMutex);
QMutexLocker lockerC(&_threadsDidHandlePacketSendMutex);
QMutexLocker lockerD(&_threadsDidCallWriteDatagramMutex);
_threadsDidProcess.remove(thread); _threadsDidProcess.remove(thread);
_threadsDidPacketDistributor.remove(thread); _threadsDidPacketDistributor.remove(thread);
_threadsDidHandlePacketSend.remove(thread); _threadsDidHandlePacketSend.remove(thread);
_threadsDidCallWriteDatagram.remove(thread);
} }
int howManyThreadsDidSomething(QMap<OctreeSendThread*, quint64>& something, quint64 since) { int howManyThreadsDidSomething(QMutex& mutex, QMap<OctreeSendThread*, quint64>& something, quint64 since) {
if (since == 0) {
return something.size();
}
int count = 0; int count = 0;
QMap<OctreeSendThread*, quint64>::const_iterator i = something.constBegin(); if (mutex.tryLock()) {
while (i != something.constEnd()) { if (since == 0) {
if (i.value() > since) { count = something.size();
count++; } else {
QMap<OctreeSendThread*, quint64>::const_iterator i = something.constBegin();
while (i != something.constEnd()) {
if (i.value() > since) {
count++;
}
++i;
}
} }
++i; mutex.unlock();
} }
return count; return count;
} }
int OctreeServer::howManyThreadsDidProcess(quint64 since) { int OctreeServer::howManyThreadsDidProcess(quint64 since) {
return howManyThreadsDidSomething(_threadsDidProcess, since); return howManyThreadsDidSomething(_threadsDidProcessMutex, _threadsDidProcess, since);
} }
int OctreeServer::howManyThreadsDidPacketDistributor(quint64 since) { int OctreeServer::howManyThreadsDidPacketDistributor(quint64 since) {
return howManyThreadsDidSomething(_threadsDidPacketDistributor, since); return howManyThreadsDidSomething(_threadsDidPacketDistributorMutex, _threadsDidPacketDistributor, since);
} }
int OctreeServer::howManyThreadsDidHandlePacketSend(quint64 since) { int OctreeServer::howManyThreadsDidHandlePacketSend(quint64 since) {
return howManyThreadsDidSomething(_threadsDidHandlePacketSend, since); return howManyThreadsDidSomething(_threadsDidHandlePacketSendMutex, _threadsDidHandlePacketSend, since);
} }
int OctreeServer::howManyThreadsDidCallWriteDatagram(quint64 since) { int OctreeServer::howManyThreadsDidCallWriteDatagram(quint64 since) {
return howManyThreadsDidSomething(_threadsDidCallWriteDatagram, since); return howManyThreadsDidSomething(_threadsDidCallWriteDatagramMutex, _threadsDidCallWriteDatagram, since);
} }

View file

@ -211,6 +211,10 @@ protected:
static QMap<OctreeSendThread*, quint64> _threadsDidHandlePacketSend; static QMap<OctreeSendThread*, quint64> _threadsDidHandlePacketSend;
static QMap<OctreeSendThread*, quint64> _threadsDidCallWriteDatagram; static QMap<OctreeSendThread*, quint64> _threadsDidCallWriteDatagram;
static QMutex _threadsDidProcessMutex;
static QMutex _threadsDidPacketDistributorMutex;
static QMutex _threadsDidHandlePacketSendMutex;
static QMutex _threadsDidCallWriteDatagramMutex;
}; };
#endif // __octree_server__OctreeServer__ #endif // __octree_server__OctreeServer__

View file

@ -14,12 +14,12 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="src/Application.cpp" line="3608"/> <location filename="src/Application.cpp" line="3610"/>
<source>Open Script</source> <source>Open Script</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="src/Application.cpp" line="3609"/> <location filename="src/Application.cpp" line="3611"/>
<source>JavaScript Files (*.js)</source> <source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -113,18 +113,18 @@
<context> <context>
<name>Menu</name> <name>Menu</name>
<message> <message>
<location filename="src/Menu.cpp" line="459"/> <location filename="src/Menu.cpp" line="456"/>
<source>Open .ini config file</source> <source>Open .ini config file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="src/Menu.cpp" line="461"/> <location filename="src/Menu.cpp" line="458"/>
<location filename="src/Menu.cpp" line="473"/> <location filename="src/Menu.cpp" line="470"/>
<source>Text files (*.ini)</source> <source>Text files (*.ini)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="src/Menu.cpp" line="471"/> <location filename="src/Menu.cpp" line="468"/>
<source>Save .ini config file</source> <source>Save .ini config file</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View file

@ -10,7 +10,8 @@
uniform sampler2DShadow shadowMap; uniform sampler2DShadow shadowMap;
varying vec4 shadowColor;
void main(void) { void main(void) {
gl_FragColor = gl_Color * mix(vec4(0.8, 0.8, 0.8, 1.0), vec4(1.0, 1.0, 1.0, 1.0), gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, gl_TexCoord[0].stp));
shadow2D(shadowMap, gl_TexCoord[0].stp));
} }

View file

@ -0,0 +1,28 @@
#version 120
//
// shadow_map.vert
// vertex shader
//
// Created by Andrzej Kapolka on 3/27/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
varying vec4 shadowColor;
void main(void) {
// the shadow color includes only the ambient terms
shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient);
// the normal color includes diffuse
vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position)));
// generate the shadow texture coordinate using the eye position
vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = vec4(dot(gl_EyePlaneS[0], eyePosition), dot(gl_EyePlaneT[0], eyePosition),
dot(gl_EyePlaneR[0], eyePosition), 1.0);
// use the fixed function transform
gl_Position = ftransform();
}

View file

@ -1636,6 +1636,8 @@ void Application::updateLOD() {
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) { if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
Menu::getInstance()->autoAdjustLOD(_fps); Menu::getInstance()->autoAdjustLOD(_fps);
} else {
Menu::getInstance()->resetLODAdjust();
} }
} }

View file

@ -393,8 +393,6 @@ void Menu::loadSettings(QSettings* settings) {
_maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM);
_maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS); _maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS);
_voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE); _voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE);
_avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier",
DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER);
_boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0);
settings->beginGroup("View Frustum Offset Camera"); settings->beginGroup("View Frustum Offset Camera");
@ -434,7 +432,6 @@ void Menu::saveSettings(QSettings* settings) {
settings->setValue("maxVoxels", _maxVoxels); settings->setValue("maxVoxels", _maxVoxels);
settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond); settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond);
settings->setValue("voxelSizeScale", _voxelSizeScale); settings->setValue("voxelSizeScale", _voxelSizeScale);
settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier);
settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust);
settings->beginGroup("View Frustum Offset Camera"); settings->beginGroup("View Frustum Offset Camera");
settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw);
@ -1203,7 +1200,10 @@ void Menu::autoAdjustLOD(float currentFPS) {
if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) { if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) {
// attempt to lower the detail in proportion to the fps difference // attempt to lower the detail in proportion to the fps difference
float targetFps = (ADJUST_LOD_DOWN_FPS + ADJUST_LOD_UP_FPS) * 0.5f; float targetFps = (ADJUST_LOD_DOWN_FPS + ADJUST_LOD_UP_FPS) * 0.5f;
_avatarLODDistanceMultiplier *= (targetFps / _fastFPSAverage.getAverage()); float averageFps = _fastFPSAverage.getAverage();
const float MAXIMUM_MULTIPLIER_SCALE = 2.0f;
_avatarLODDistanceMultiplier *= (averageFps < EPSILON) ? MAXIMUM_MULTIPLIER_SCALE :
qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps);
_lastAvatarDetailDrop = now; _lastAvatarDetailDrop = now;
} }
} else if (_fastFPSAverage.getAverage() > ADJUST_LOD_UP_FPS) { } else if (_fastFPSAverage.getAverage() > ADJUST_LOD_UP_FPS) {
@ -1249,6 +1249,12 @@ void Menu::autoAdjustLOD(float currentFPS) {
} }
} }
void Menu::resetLODAdjust() {
_fpsAverage.reset();
_fastFPSAverage.reset();
_lastAvatarDetailDrop = _lastAdjust = usecTimestampNow();
}
void Menu::setVoxelSizeScale(float sizeScale) { void Menu::setVoxelSizeScale(float sizeScale) {
_voxelSizeScale = sizeScale; _voxelSizeScale = sizeScale;
} }

View file

@ -85,6 +85,7 @@ public:
// User Tweakable LOD Items // User Tweakable LOD Items
QString getLODFeedbackText(); QString getLODFeedbackText();
void autoAdjustLOD(float currentFPS); void autoAdjustLOD(float currentFPS);
void resetLODAdjust();
void setVoxelSizeScale(float sizeScale); void setVoxelSizeScale(float sizeScale);
float getVoxelSizeScale() const { return _voxelSizeScale; } float getVoxelSizeScale() const { return _voxelSizeScale; }
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; } float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }

View file

@ -397,9 +397,13 @@ void Avatar::renderDisplayName() {
glPushMatrix(); glPushMatrix();
glm::vec3 textPosition; glm::vec3 textPosition;
getSkeletonModel().getNeckPosition(textPosition); if (getSkeletonModel().getNeckPosition(textPosition)) {
textPosition += getBodyUpDirection() * getHeadHeight() * 1.1f; textPosition += getBodyUpDirection() * getHeadHeight() * 1.1f;
} else {
const float HEAD_PROPORTION = 0.75f;
textPosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION);
}
glTranslatef(textPosition.x, textPosition.y, textPosition.z); glTranslatef(textPosition.x, textPosition.y, textPosition.z);
// we need "always facing camera": we must remove the camera rotation from the stack // we need "always facing camera": we must remove the camera rotation from the stack

View file

@ -79,6 +79,7 @@ void MyAvatar::reset() {
// TODO? resurrect headMouse stuff? // TODO? resurrect headMouse stuff?
//_headMouseX = _glWidget->width() / 2; //_headMouseX = _glWidget->width() / 2;
//_headMouseY = _glWidget->height() / 2; //_headMouseY = _glWidget->height() / 2;
_skeletonModel.reset();
getHead()->reset(); getHead()->reset();
getHand()->reset(); getHand()->reset();

View file

@ -1259,7 +1259,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
remainingModels.insert(model.key()); remainingModels.insert(model.key());
} }
while (!remainingModels.isEmpty()) { while (!remainingModels.isEmpty()) {
QString topID = getTopModelID(parentMap, models, *remainingModels.constBegin()); QString first = *remainingModels.constBegin();
foreach (const QString& id, remainingModels) {
if (id < first) {
first = id;
}
}
QString topID = getTopModelID(parentMap, models, first);
appendModelIDs(parentMap.value(topID), childMap, models, remainingModels, modelIDs); appendModelIDs(parentMap.value(topID), childMap, models, remainingModels, modelIDs);
} }

View file

@ -130,9 +130,16 @@ void Model::init() {
} }
void Model::reset() { void Model::reset() {
if (_jointStates.isEmpty()) {
return;
}
foreach (Model* attachment, _attachments) { foreach (Model* attachment, _attachments) {
attachment->reset(); attachment->reset();
} }
const FBXGeometry& geometry = _geometry->getFBXGeometry();
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].rotation = geometry.joints.at(i).rotation;
}
} }
void Model::clearShapes() { void Model::clearShapes() {

View file

@ -506,8 +506,10 @@ void VoxelSystem::initVoxelMemory() {
_perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0);
_perlinModulateProgram.release(); _perlinModulateProgram.release();
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() _shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
+ "shaders/shadow_map.frag"); Application::resourcesPath() + "shaders/shadow_map.vert");
_shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
Application::resourcesPath() + "shaders/shadow_map.frag");
_shadowMapProgram.link(); _shadowMapProgram.link();
_shadowMapProgram.bind(); _shadowMapProgram.bind();
@ -1471,10 +1473,6 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) {
_shadowMapProgram.bind(); _shadowMapProgram.bind();
glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID());
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_2D);
glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]);
glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]);
@ -1496,10 +1494,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) {
_shadowMapProgram.release(); _shadowMapProgram.release();
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_2D);
} else if (texture) { } else if (texture) {
_perlinModulateProgram.release(); _perlinModulateProgram.release();

View file

@ -357,10 +357,20 @@ int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) {
return 0; return 0;
} }
SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) {
QMutexLocker locker(&_nodeHashMutex); const int WAIT_TIME = 10; // wait up to 10ms in the try lock case
return _nodeHash.value(nodeUUID); SharedNodePointer node;
} // if caller wants us to block and guarantee the correct answer, then honor that request
if (blockingLock) {
// this will block till we can get access
QMutexLocker locker(&_nodeHashMutex);
node = _nodeHash.value(nodeUUID);
} else if (_nodeHashMutex.tryLock(WAIT_TIME)) { // some callers are willing to get wrong answers but not block
node = _nodeHash.value(nodeUUID);
_nodeHashMutex.unlock();
}
return node;
}
SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) { SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) {
QUuid nodeUUID = uuidFromPacketHeader(packet); QUuid nodeUUID = uuidFromPacketHeader(packet);

View file

@ -103,7 +103,7 @@ public:
QByteArray constructPingReplyPacket(const QByteArray& pingPacket); QByteArray constructPingReplyPacket(const QByteArray& pingPacket);
void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node);
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true);
SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer sendingNodeForPacket(const QByteArray& packet);
SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType,