mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 16:13:28 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into new_voxel_scene_stats
Conflicts: interface/src/Application.cpp
This commit is contained in:
commit
581e0adecf
19 changed files with 448 additions and 199 deletions
|
@ -144,6 +144,8 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_packetsPerSecond(0),
|
||||
_bytesPerSecond(0),
|
||||
_bytesCount(0),
|
||||
_recentMaxPackets(0),
|
||||
_resetRecentMaxPacketsSoon(true),
|
||||
_swatch(NULL),
|
||||
_pasteMode(false)
|
||||
{
|
||||
|
@ -1304,7 +1306,10 @@ static glm::vec3 getFaceVector(BoxFace face) {
|
|||
}
|
||||
|
||||
void Application::idle() {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
// Normally we check PipelineWarnings, but since idle will often take more than 10ms we only show these idle timing
|
||||
// details if we're in ExtraDebugging mode. However, the ::update() and it's subcomponents will show their timing
|
||||
// details normally.
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging);
|
||||
PerformanceWarning warn(showWarnings, "Application::idle()");
|
||||
|
||||
timeval check;
|
||||
|
@ -1314,22 +1319,30 @@ void Application::idle() {
|
|||
|
||||
double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check);
|
||||
if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
|
||||
|
||||
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
||||
_glWidget->updateGL();
|
||||
_lastTimeUpdated = check;
|
||||
_idleLoopStdev.addValue(timeSinceLastUpdate);
|
||||
|
||||
// Record standard deviation and reset counter if needed
|
||||
const int STDEV_SAMPLES = 500;
|
||||
if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) {
|
||||
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
|
||||
_idleLoopStdev.reset();
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::idle()... update()");
|
||||
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
||||
}
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()");
|
||||
_glWidget->updateGL();
|
||||
}
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");
|
||||
_lastTimeUpdated = check;
|
||||
_idleLoopStdev.addValue(timeSinceLastUpdate);
|
||||
|
||||
// Record standard deviation and reset counter if needed
|
||||
const int STDEV_SAMPLES = 500;
|
||||
if (_idleLoopStdev.getSamples() > STDEV_SAMPLES) {
|
||||
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
|
||||
_idleLoopStdev.reset();
|
||||
}
|
||||
|
||||
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
|
||||
idleTimer->start(2);
|
||||
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
|
||||
idleTimer->start(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Application::terminate() {
|
||||
|
@ -1776,6 +1789,8 @@ static QUuid DEFAULT_NODE_ID_REF;
|
|||
|
||||
void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection,
|
||||
glm::vec3& eyePosition) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateLookatTargetAvatar()");
|
||||
|
||||
_lookatTargetAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePosition, DEFAULT_NODE_ID_REF);
|
||||
}
|
||||
|
@ -1791,7 +1806,10 @@ Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, con
|
|||
float distance;
|
||||
if (rayIntersectsSphere(mouseRayOrigin, mouseRayDirection, headPosition,
|
||||
HEAD_SPHERE_RADIUS * avatar->getHead().getScale(), distance)) {
|
||||
eyePosition = avatar->getHead().calculateAverageEyePosition();
|
||||
// rescale to compensate for head embiggening
|
||||
eyePosition = (avatar->getHead().calculateAverageEyePosition() - avatar->getHead().getScalePivot()) *
|
||||
(avatar->getScale() / avatar->getHead().getScale()) + avatar->getHead().getScalePivot();
|
||||
|
||||
_lookatIndicatorScale = avatar->getHead().getScale();
|
||||
_lookatOtherPosition = headPosition;
|
||||
nodeUUID = avatar->getOwningNode()->getUUID();
|
||||
|
@ -1907,17 +1925,13 @@ void Application::updateAvatars(float deltaTime, glm::vec3 mouseRayOrigin, glm::
|
|||
}
|
||||
}
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
void Application::updateMouseRay(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection) {
|
||||
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::update()");
|
||||
|
||||
// tell my avatar if the mouse is being pressed...
|
||||
_myAvatar.setMousePressed(_mousePressed);
|
||||
|
||||
// check what's under the mouse and update the mouse voxel
|
||||
glm::vec3 mouseRayOrigin, mouseRayDirection;
|
||||
_viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(),
|
||||
_mouseY / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateMouseRay()");
|
||||
|
||||
_viewFrustum.computePickRay(_mouseX / (float)_glWidget->width(), _mouseY / (float)_glWidget->height(),
|
||||
mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// adjust for mirroring
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
|
@ -1928,12 +1942,18 @@ void Application::update(float deltaTime) {
|
|||
_viewFrustum.getRight() * glm::dot(_viewFrustum.getRight(), mouseRayDirection));
|
||||
}
|
||||
|
||||
// tell my avatar if the mouse is being pressed...
|
||||
_myAvatar.setMousePressed(_mousePressed);
|
||||
|
||||
// tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position
|
||||
_myAvatar.setMouseRay(mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// Set where I am looking based on my mouse ray (so that other people can see)
|
||||
glm::vec3 lookAtSpot;
|
||||
}
|
||||
|
||||
void Application::updateFaceshift() {
|
||||
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");
|
||||
|
||||
// Update faceshift
|
||||
_faceshift.update();
|
||||
|
||||
|
@ -1941,39 +1961,47 @@ void Application::update(float deltaTime) {
|
|||
if (_faceshift.isActive()) {
|
||||
_myAvatar.getHead().setAngularVelocity(_faceshift.getHeadAngularVelocity());
|
||||
}
|
||||
}
|
||||
|
||||
// if we have faceshift, use that to compute the lookat direction
|
||||
glm::vec3 lookAtRayOrigin = mouseRayOrigin, lookAtRayDirection = mouseRayDirection;
|
||||
if (_faceshift.isActive()) {
|
||||
lookAtRayOrigin = _myAvatar.getHead().calculateAverageEyePosition();
|
||||
lookAtRayDirection = _myAvatar.getHead().getOrientation() * glm::quat(glm::radians(glm::vec3(
|
||||
_faceshift.getEstimatedEyePitch(), _faceshift.getEstimatedEyeYaw(), 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
}
|
||||
void Application::updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot, glm::vec3& lookAtRayOrigin,
|
||||
glm::vec3& lookAtRayDirection) {
|
||||
|
||||
updateLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, lookAtSpot);
|
||||
if (_lookatTargetAvatar && !_faceshift.isActive()) {
|
||||
// If the mouse is over another avatar's head...
|
||||
_myAvatar.getHead().setLookAtPosition(lookAtSpot);
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
|
||||
|
||||
} else if (_isHoverVoxel && !_faceshift.isActive()) {
|
||||
// Look at the hovered voxel
|
||||
lookAtSpot = getMouseVoxelWorldCoordinates(_hoverVoxel);
|
||||
_myAvatar.getHead().setLookAtPosition(lookAtSpot);
|
||||
if (!_lookatTargetAvatar) {
|
||||
if (_isHoverVoxel) {
|
||||
// Look at the hovered voxel
|
||||
lookAtSpot = getMouseVoxelWorldCoordinates(_hoverVoxel);
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
lookAtSpot = _myCamera.getPosition();
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR && !_faceshift.isActive()) {
|
||||
_myAvatar.getHead().setLookAtPosition(_myCamera.getPosition());
|
||||
|
||||
} else {
|
||||
// Just look in direction of the mouse ray
|
||||
const float FAR_AWAY_STARE = TREE_SCALE;
|
||||
lookAtSpot = lookAtRayOrigin + lookAtRayDirection * FAR_AWAY_STARE;
|
||||
_myAvatar.getHead().setLookAtPosition(lookAtSpot);
|
||||
} else {
|
||||
// Just look in direction of the mouse ray
|
||||
const float FAR_AWAY_STARE = TREE_SCALE;
|
||||
lookAtSpot = lookAtRayOrigin + lookAtRayDirection * FAR_AWAY_STARE;
|
||||
}
|
||||
}
|
||||
if (_faceshift.isActive()) {
|
||||
// deflect using Faceshift gaze data
|
||||
glm::vec3 origin = _myAvatar.getHead().calculateAverageEyePosition();
|
||||
float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f;
|
||||
const float PITCH_SCALE = 0.5f;
|
||||
const float YAW_SCALE = 0.5f;
|
||||
lookAtSpot = origin + _myCamera.getRotation() * glm::quat(glm::radians(glm::vec3(
|
||||
_faceshift.getEstimatedEyePitch() * pitchSign * PITCH_SCALE, _faceshift.getEstimatedEyeYaw() * YAW_SCALE, 0.0f))) *
|
||||
glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin);
|
||||
}
|
||||
_myAvatar.getHead().setLookAtPosition(lookAtSpot);
|
||||
}
|
||||
|
||||
void Application::updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
|
||||
float& distance, BoxFace& face) {
|
||||
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels()");
|
||||
|
||||
// Find the voxel we are hovering over, and respond if clicked
|
||||
float distance;
|
||||
BoxFace face;
|
||||
|
||||
// If we have clicked on a voxel, update it's color
|
||||
if (_isHoverVoxelSounding) {
|
||||
VoxelNode* hoveredNode = _voxels.getVoxelAt(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
||||
|
@ -1995,23 +2023,38 @@ void Application::update(float deltaTime) {
|
|||
} else {
|
||||
// Check for a new hover voxel
|
||||
glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
||||
_isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face);
|
||||
if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) {
|
||||
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
|
||||
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
|
||||
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
|
||||
_hoverVoxelOriginalColor[3] = 1;
|
||||
_audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY);
|
||||
_isHoverVoxelSounding = true;
|
||||
// only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled,
|
||||
// and make sure the tree is not already busy... because otherwise you'll have to wait.
|
||||
if (!_voxels.treeIsBusy()) {
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
||||
_isHoverVoxel = _voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _hoverVoxel, distance, face);
|
||||
}
|
||||
if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel &&
|
||||
glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) {
|
||||
|
||||
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
|
||||
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
|
||||
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
|
||||
_hoverVoxelOriginalColor[3] = 1;
|
||||
_audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY);
|
||||
_isHoverVoxelSounding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::updateMouseVoxels(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
|
||||
float& distance, BoxFace& face) {
|
||||
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateMouseVoxels()");
|
||||
|
||||
_mouseVoxel.s = 0.0f;
|
||||
if (Menu::getInstance()->isVoxelModeActionChecked() &&
|
||||
(fabs(_myAvatar.getVelocity().x) +
|
||||
fabs(_myAvatar.getVelocity().y) +
|
||||
fabs(_myAvatar.getVelocity().z)) / 3 < MAX_AVATAR_EDIT_VELOCITY) {
|
||||
PerformanceWarning warn(showWarnings, "Application::update()... findRayIntersection()");
|
||||
|
||||
if (_voxels.findRayIntersection(mouseRayOrigin, mouseRayDirection, _mouseVoxel, distance, face)) {
|
||||
if (distance < MAX_VOXEL_EDIT_DISTANCE) {
|
||||
|
@ -2080,12 +2123,17 @@ void Application::update(float deltaTime) {
|
|||
_justEditedVoxel = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::updateHandAndTouch(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHandAndTouch()");
|
||||
|
||||
// walking triggers the handControl to stop
|
||||
if (_myAvatar.getMode() == AVATAR_MODE_WALKING) {
|
||||
_handControl.stop();
|
||||
}
|
||||
|
||||
|
||||
// Update from Touch
|
||||
if (_isTouchPressed) {
|
||||
float TOUCH_YAW_SCALE = -0.25f;
|
||||
|
@ -2096,19 +2144,29 @@ void Application::update(float deltaTime) {
|
|||
_lastTouchAvgX = _touchAvgX;
|
||||
_lastTouchAvgY = _touchAvgY;
|
||||
}
|
||||
|
||||
// Leap finger-sensing device
|
||||
}
|
||||
|
||||
void Application::updateLeap(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateLeap()");
|
||||
|
||||
LeapManager::enableFakeFingers(Menu::getInstance()->isOptionChecked(MenuOption::SimulateLeapHand));
|
||||
_myAvatar.getHand().setRaveGloveActive(Menu::getInstance()->isOptionChecked(MenuOption::TestRaveGlove));
|
||||
LeapManager::nextFrame(_myAvatar);
|
||||
|
||||
// Read serial port interface devices
|
||||
}
|
||||
|
||||
void Application::updateSerialDevices(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateSerialDevices()");
|
||||
|
||||
if (_serialHeadSensor.isActive()) {
|
||||
_serialHeadSensor.readData(deltaTime);
|
||||
}
|
||||
|
||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
updateAvatar(deltaTime);
|
||||
}
|
||||
|
||||
void Application::updateThreads(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateThreads()");
|
||||
|
||||
// read incoming packets from network
|
||||
if (!_enableNetworkThread) {
|
||||
|
@ -2120,12 +2178,12 @@ void Application::update(float deltaTime) {
|
|||
_voxelProcessor.threadRoutine();
|
||||
_voxelEditSender.threadRoutine();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateMyAvatarSimulation(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarSimulation()");
|
||||
|
||||
|
||||
//loop through all the other avatars and simulate them...
|
||||
updateAvatars(deltaTime, mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// Simulate myself
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) {
|
||||
_myAvatar.setGravity(_environment.getGravity(_myAvatar.getPosition()));
|
||||
}
|
||||
|
@ -2138,12 +2196,21 @@ void Application::update(float deltaTime) {
|
|||
} else {
|
||||
_myAvatar.simulate(deltaTime, NULL);
|
||||
}
|
||||
|
||||
// Simulate particle cloud movements
|
||||
}
|
||||
|
||||
void Application::updateParticles(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateParticles()");
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ParticleCloud)) {
|
||||
_cloud.simulate(deltaTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::updateTransmitter(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateTransmitter()");
|
||||
|
||||
// no transmitter drive implies transmitter pick
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::TransmitterDrive) && _myTransmitter.isConnected()) {
|
||||
_transmitterPickStart = _myAvatar.getSkeleton().joint[AVATAR_JOINT_CHEST].position;
|
||||
|
@ -2178,7 +2245,12 @@ void Application::update(float deltaTime) {
|
|||
} else {
|
||||
_transmitterPickStart = _transmitterPickEnd = glm::vec3();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::updateCamera(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
|
||||
|
||||
if (!OculusManager::isConnected()) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
|
||||
if (_myCamera.getMode() != CAMERA_MODE_MIRROR) {
|
||||
|
@ -2213,7 +2285,12 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::updateDialogs(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
|
||||
|
||||
// Update bandwidth dialog, if any
|
||||
BandwidthDialog* bandwidthDialog = Menu::getInstance()->getBandwidthDialog();
|
||||
if (bandwidthDialog) {
|
||||
|
@ -2224,6 +2301,11 @@ void Application::update(float deltaTime) {
|
|||
if (voxelStatsDialog) {
|
||||
voxelStatsDialog->update();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::updateAudio(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateAudio()");
|
||||
|
||||
// Update audio stats for procedural sounds
|
||||
#ifndef _WIN32
|
||||
|
@ -2231,7 +2313,12 @@ void Application::update(float deltaTime) {
|
|||
_audio.setLastVelocity(_myAvatar.getVelocity());
|
||||
_audio.eventuallyAnalyzePing();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void Application::updateCursor(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateCursor()");
|
||||
|
||||
// watch mouse position, if it hasn't moved, hide the cursor
|
||||
bool underMouse = _glWidget->underMouse();
|
||||
if (!_mouseHidden) {
|
||||
|
@ -2252,6 +2339,42 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::update()");
|
||||
|
||||
// check what's under the mouse and update the mouse voxel
|
||||
glm::vec3 mouseRayOrigin, mouseRayDirection;
|
||||
updateMouseRay(deltaTime, mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// Set where I am looking based on my mouse ray (so that other people can see)
|
||||
glm::vec3 lookAtSpot;
|
||||
|
||||
updateFaceshift();
|
||||
updateLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, lookAtSpot);
|
||||
updateMyAvatarLookAtPosition(lookAtSpot, mouseRayOrigin, mouseRayDirection);
|
||||
|
||||
// Find the voxel we are hovering over, and respond if clicked
|
||||
float distance;
|
||||
BoxFace face;
|
||||
|
||||
updateHoverVoxels(deltaTime, mouseRayOrigin, mouseRayDirection, distance, face); // clicking on voxels and making sounds
|
||||
updateMouseVoxels(deltaTime, mouseRayOrigin, mouseRayDirection, distance, face); // UI/UX related to voxels
|
||||
updateHandAndTouch(deltaTime); // Update state for touch sensors
|
||||
updateLeap(deltaTime); // Leap finger-sensing device
|
||||
updateSerialDevices(deltaTime); // Read serial port interface devices
|
||||
updateAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||
updateAvatars(deltaTime, mouseRayOrigin, mouseRayDirection); //loop through all the other avatars and simulate them...
|
||||
updateMyAvatarSimulation(deltaTime); // Simulate myself
|
||||
updateParticles(deltaTime); // Simulate particle cloud movements
|
||||
updateTransmitter(deltaTime); // transmitter drive or pick
|
||||
updateCamera(deltaTime); // handle various camera tweaks like off axis projection
|
||||
updateDialogs(deltaTime); // update various stats dialogs if present
|
||||
updateAudio(deltaTime); // Update audio stats for procedural sounds
|
||||
updateCursor(deltaTime); // Handle cursor updates
|
||||
}
|
||||
|
||||
void Application::updateAvatar(float deltaTime) {
|
||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateAvatar()");
|
||||
|
@ -2743,6 +2866,12 @@ void Application::setupWorldLight(Camera& whichCamera) {
|
|||
glMateriali(GL_FRONT, GL_SHININESS, 96);
|
||||
}
|
||||
|
||||
void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {
|
||||
glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix);
|
||||
glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y,
|
||||
translation.z + _viewMatrixTranslation.z);
|
||||
}
|
||||
|
||||
void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
|
||||
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const {
|
||||
|
||||
|
@ -2776,7 +2905,11 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
glm::vec3 axis = glm::axis(rotation);
|
||||
glRotatef(-glm::angle(rotation), axis.x, axis.y, axis.z);
|
||||
|
||||
glTranslatef(-whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z);
|
||||
// store view matrix without translation, which we'll use for precision-sensitive objects
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix);
|
||||
_viewMatrixTranslation = -whichCamera.getPosition();
|
||||
|
||||
glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z);
|
||||
|
||||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||
setupWorldLight(whichCamera);
|
||||
|
@ -2934,10 +3067,6 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
|||
if (!avatar->isInitialized()) {
|
||||
avatar->init();
|
||||
}
|
||||
// Set lookAt to myCamera on client side if other avatars are looking at client
|
||||
if (isLookingAtMyAvatar(avatar)) {
|
||||
avatar->getHead().setLookAtPosition(whichCamera.getPosition());
|
||||
}
|
||||
avatar->render(false, Menu::getInstance()->isOptionChecked(MenuOption::AvatarAsBalls));
|
||||
avatar->setDisplayingLookatVectors(Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors));
|
||||
}
|
||||
|
@ -3258,6 +3387,8 @@ void Application::displayStats() {
|
|||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, avatarStats);
|
||||
|
||||
|
||||
QLocale locale(QLocale::English);
|
||||
|
||||
std::stringstream voxelStats;
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxels " <<
|
||||
|
@ -3289,9 +3420,9 @@ void Application::displayStats() {
|
|||
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
"Local Voxels Total: " << VoxelNode::getNodeCount() << ", " <<
|
||||
"Internal: " << VoxelNode::getInternalNodeCount() << " , " <<
|
||||
"Leaves: " << VoxelNode::getLeafNodeCount() << "";
|
||||
"Local Voxels Total: " << localTotalString.toLocal8Bit().constData() << " / " <<
|
||||
"Internal: " << localInternalString.toLocal8Bit().constData() << " / " <<
|
||||
"Leaves: " << localLeavesString.toLocal8Bit().constData() << "";
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
|
@ -3360,7 +3491,28 @@ void Application::displayStats() {
|
|||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
|
||||
voxelStats.str("");
|
||||
int voxelPacketsToProcess = _voxelProcessor.packetsToProcessCount();
|
||||
QString packetsString = locale.toString((int)voxelPacketsToProcess);
|
||||
QString maxString = locale.toString((int)_recentMaxPackets);
|
||||
|
||||
voxelStats << "Voxel Packets to Process: " << packetsString.toLocal8Bit().constData()
|
||||
<< " [Recent Max: " << maxString.toLocal8Bit().constData() << "]";
|
||||
|
||||
if (_resetRecentMaxPacketsSoon && voxelPacketsToProcess > 0) {
|
||||
_recentMaxPackets = 0;
|
||||
_resetRecentMaxPacketsSoon = false;
|
||||
}
|
||||
if (voxelPacketsToProcess == 0) {
|
||||
_resetRecentMaxPacketsSoon = true;
|
||||
} else {
|
||||
if (voxelPacketsToProcess > _recentMaxPackets) {
|
||||
_recentMaxPackets = voxelPacketsToProcess;
|
||||
}
|
||||
}
|
||||
statsVerticalOffset += PELS_PER_LINE;
|
||||
drawtext(10, statsVerticalOffset, 0.10f, 0, 1.0, 0, (char*)voxelStats.str().c_str());
|
||||
|
||||
Node *avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
|
||||
|
|
|
@ -152,6 +152,10 @@ public:
|
|||
|
||||
void setupWorldLight(Camera& whichCamera);
|
||||
|
||||
/// Loads a view matrix that incorporates the specified model translation without the precision issues that can
|
||||
/// result from matrix multiplication at high translation magnitudes.
|
||||
void loadTranslatedViewMatrix(const glm::vec3& translation);
|
||||
|
||||
/// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account.
|
||||
void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& near,
|
||||
float& far, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const;
|
||||
|
@ -223,9 +227,29 @@ private:
|
|||
void init();
|
||||
|
||||
void update(float deltaTime);
|
||||
|
||||
|
||||
// Various helper functions called during update()
|
||||
void updateMouseRay(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection);
|
||||
void updateFaceshift();
|
||||
void updateMyAvatarLookAtPosition(glm::vec3& lookAtSpot, glm::vec3& lookAtRayOrigin, glm::vec3& lookAtRayDirection);
|
||||
void updateHoverVoxels(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
|
||||
float& distance, BoxFace& face);
|
||||
void updateMouseVoxels(float deltaTime, glm::vec3& mouseRayOrigin, glm::vec3& mouseRayDirection,
|
||||
float& distance, BoxFace& face);
|
||||
void updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection,
|
||||
glm::vec3& eyePosition);
|
||||
void updateHandAndTouch(float deltaTime);
|
||||
void updateLeap(float deltaTime);
|
||||
void updateSerialDevices(float deltaTime);
|
||||
void updateThreads(float deltaTime);
|
||||
void updateMyAvatarSimulation(float deltaTime);
|
||||
void updateParticles(float deltaTime);
|
||||
void updateTransmitter(float deltaTime);
|
||||
void updateCamera(float deltaTime);
|
||||
void updateDialogs(float deltaTime);
|
||||
void updateAudio(float deltaTime);
|
||||
void updateCursor(float deltaTime);
|
||||
|
||||
Avatar* findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection,
|
||||
glm::vec3& eyePosition, QUuid &nodeUUID);
|
||||
bool isLookingAtMyAvatar(Avatar* avatar);
|
||||
|
@ -317,6 +341,9 @@ private:
|
|||
QRect _mirrorViewRect;
|
||||
RearMirrorTools* _rearMirrorTools;
|
||||
|
||||
glm::mat4 _untranslatedViewMatrix;
|
||||
glm::vec3 _viewMatrixTranslation;
|
||||
|
||||
Environment _environment;
|
||||
|
||||
int _headMouseX, _headMouseY;
|
||||
|
@ -407,6 +434,9 @@ private:
|
|||
int _bytesPerSecond;
|
||||
int _bytesCount;
|
||||
|
||||
int _recentMaxPackets; // recent max incoming voxel packets to process
|
||||
bool _resetRecentMaxPacketsSoon;
|
||||
|
||||
StDev _idleLoopStdev;
|
||||
float _idleLoopMeasuredJitter;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ void VoxelPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char*
|
|||
"VoxelPacketProcessor::processPacket()");
|
||||
|
||||
const int WAY_BEHIND = 300;
|
||||
if (packetsToProcessCount() > WAY_BEHIND && Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
|
||||
if (packetsToProcessCount() > WAY_BEHIND && Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)) {
|
||||
qDebug("VoxelPacketProcessor::processPacket() packets to process=%d\n", packetsToProcessCount());
|
||||
}
|
||||
ssize_t messageLength = packetLength;
|
||||
|
|
|
@ -110,6 +110,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
|||
|
||||
_culledOnce = false;
|
||||
_inhideOutOfView = false;
|
||||
_treeIsBusy = false;
|
||||
}
|
||||
|
||||
void VoxelSystem::voxelDeleted(VoxelNode* node) {
|
||||
|
@ -595,9 +596,9 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
"readBitstreamToTree()");
|
||||
// ask the VoxelTree to read the bitstream into the tree
|
||||
ReadBitstreamToTreeParams args(WANT_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID());
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, args);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
}
|
||||
break;
|
||||
case PACKET_TYPE_VOXEL_DATA_MONOCHROME: {
|
||||
|
@ -605,9 +606,9 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) {
|
|||
"readBitstreamToTree()");
|
||||
// ask the VoxelTree to read the MONOCHROME bitstream into the tree
|
||||
ReadBitstreamToTreeParams args(NO_COLOR, WANT_EXISTS_BITS, NULL, getDataSourceUUID());
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->readBitstreamToTree(voxelData, numBytes - numBytesPacketHeader, args);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
}
|
||||
break;
|
||||
case PACKET_TYPE_Z_COMMAND:
|
||||
|
@ -1002,7 +1003,9 @@ int VoxelSystem::updateNodeInArrays(VoxelNode* node, bool reuseIndex, bool force
|
|||
// not render these Voxels. We need to think about ways to keep the entire scene intact but maybe lower quality
|
||||
// possibly shifting down to lower LOD or something. This debug message is to help identify, if/when/how this
|
||||
// state actually occurs.
|
||||
qDebug("OHHHH NOOOOOO!!!! updateNodeInArrays() BAILING (_voxelsInWriteArrays >= _maxVoxels)\n");
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)) {
|
||||
qDebug("OHHHH NOOOOOO!!!! updateNodeInArrays() BAILING (_voxelsInWriteArrays >= _maxVoxels)\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1405,9 +1408,9 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) {
|
|||
int VoxelSystem::_nodeCount = 0;
|
||||
|
||||
void VoxelSystem::killLocalVoxels() {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->eraseAllVoxels();
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
clearFreeBufferIndexes();
|
||||
_voxelsInReadArrays = 0; // do we need to do this?
|
||||
setupNewVoxelsForDrawing();
|
||||
|
@ -1426,9 +1429,9 @@ bool VoxelSystem::clearAllNodesBufferIndexOperation(VoxelNode* node, void* extra
|
|||
|
||||
void VoxelSystem::clearAllNodesBufferIndex() {
|
||||
_nodeCount = 0;
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->recurseTreeWithOperation(clearAllNodesBufferIndexOperation);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings)) {
|
||||
qDebug("clearing buffer index of %d nodes\n", _nodeCount);
|
||||
}
|
||||
|
@ -1882,7 +1885,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
|||
_inhideOutOfView = true;
|
||||
|
||||
bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showDebugDetails, "hideOutOfView()", showDebugDetails);
|
||||
PerformanceWarning warn(showDebugDetails, "hideOutOfView()");
|
||||
bool widenFrustum = true;
|
||||
|
||||
// When using "delta" view frustums and only hide/show items that are in the difference
|
||||
|
@ -1916,9 +1919,9 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
|||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
_lastCulledViewFrustum = args.thisViewFrustum; // save last stable
|
||||
_culledOnce = true;
|
||||
|
||||
|
@ -1927,7 +1930,8 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) {
|
|||
setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
|
||||
}
|
||||
|
||||
if (showDebugDetails) {
|
||||
bool extraDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging);
|
||||
if (extraDebugDetails) {
|
||||
qDebug("hideOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld\n",
|
||||
args.nodesScanned, args.nodesRemoved, args.nodesInside,
|
||||
args.nodesIntersect, args.nodesOutside
|
||||
|
@ -2106,10 +2110,10 @@ bool VoxelSystem::hideOutOfViewOperation(VoxelNode* node, void* extraData) {
|
|||
|
||||
bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
VoxelDetail& detail, float& distance, BoxFace& face) {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
VoxelNode* node;
|
||||
if (!_tree->findRayIntersection(origin, direction, node, distance, face)) {
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
return false;
|
||||
}
|
||||
detail.x = node->getCorner().x;
|
||||
|
@ -2119,21 +2123,21 @@ bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3&
|
|||
detail.red = node->getColor()[0];
|
||||
detail.green = node->getColor()[1];
|
||||
detail.blue = node->getColor()[2];
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VoxelSystem::findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
bool result = _tree->findSpherePenetration(center, radius, penetration);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VoxelSystem::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
bool result = _tree->findCapsulePenetration(start, end, radius, penetration);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2307,9 +2311,9 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
|
|||
|
||||
|
||||
void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->deleteVoxelAt(x, y, z, s);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
|
||||
// redraw!
|
||||
setupNewVoxelsForDrawing(); // do we even need to do this? Or will the next network receive kick in?
|
||||
|
@ -2324,9 +2328,9 @@ void VoxelSystem::createVoxel(float x, float y, float z, float s,
|
|||
unsigned char red, unsigned char green, unsigned char blue, bool destructive) {
|
||||
|
||||
//qDebug("VoxelSystem::createVoxel(%f,%f,%f,%f)\n",x,y,z,s);
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->createVoxel(x, y, z, s, red, green, blue, destructive);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
|
||||
setupNewVoxelsForDrawing();
|
||||
};
|
||||
|
@ -2649,9 +2653,9 @@ void VoxelSystem::nodeKilled(Node* node) {
|
|||
if (_voxelServerCount > 0) {
|
||||
// Kill any voxels from the local tree that match this nodeID
|
||||
// commenting out for removal of 16 bit node IDs
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
lockTree();
|
||||
_tree->recurseTreeWithOperation(killSourceVoxelsOperation, &nodeUUID);
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
unlockTree();
|
||||
_tree->setDirtyBit();
|
||||
setupNewVoxelsForDrawing();
|
||||
} else {
|
||||
|
@ -2719,5 +2723,15 @@ unsigned long VoxelSystem::getVoxelMemoryUsageGPU() {
|
|||
return (_initialMemoryUsageGPU - currentFreeMemory);
|
||||
}
|
||||
|
||||
void VoxelSystem::lockTree() {
|
||||
pthread_mutex_lock(&_treeLock);
|
||||
_treeIsBusy = true;
|
||||
}
|
||||
|
||||
void VoxelSystem::unlockTree() {
|
||||
_treeIsBusy = false;
|
||||
pthread_mutex_unlock(&_treeLock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ public:
|
|||
virtual void nodeKilled(Node* node);
|
||||
virtual void domainChanged(QString domain);
|
||||
|
||||
bool treeIsBusy() const { return _treeIsBusy; }
|
||||
|
||||
signals:
|
||||
void importSize(float x, float y, float z);
|
||||
void importProgress(int progress);
|
||||
|
@ -302,6 +304,10 @@ private:
|
|||
bool _useFastVoxelPipeline;
|
||||
|
||||
bool _inhideOutOfView;
|
||||
bool _treeIsBusy; // is the tree mutex locked? if so, it's busy, and if you can avoid it, don't access the tree
|
||||
|
||||
void lockTree();
|
||||
void unlockTree();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,7 +62,7 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
|
|||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f));
|
||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
||||
_owningHead->getSaccade(), 1.0f));
|
||||
_owningHead->getSaccade() - _translation, 1.0f));
|
||||
glm::quat between = rotationBetween(front, lookAt);
|
||||
const float MAX_ANGLE = 30.0f;
|
||||
state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||
|
|
|
@ -415,6 +415,10 @@ glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const {
|
|||
return rotationBetween(orientation * IDENTITY_FRONT, _lookAtPosition + _saccade - eyePosition) * orientation;
|
||||
}
|
||||
|
||||
glm::vec3 Head::getScalePivot() const {
|
||||
return _faceModel.isActive() ? _faceModel.getTranslation() : _position;
|
||||
}
|
||||
|
||||
void Head::renderHeadSphere() {
|
||||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z); //translate to head position
|
||||
|
|
|
@ -83,6 +83,9 @@ public:
|
|||
float getAverageLoudness() const { return _averageLoudness; }
|
||||
glm::vec3 calculateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; }
|
||||
|
||||
/// Returns the point about which scaling occurs.
|
||||
glm::vec3 getScalePivot() const;
|
||||
|
||||
float yawRate;
|
||||
|
||||
private:
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Avatar.h"
|
||||
#include "SkeletonModel.h"
|
||||
|
||||
|
@ -47,7 +48,7 @@ bool SkeletonModel::render(float alpha) {
|
|||
|
||||
glm::vec3 position;
|
||||
getJointPosition(i, position);
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
Application::getInstance()->loadTranslatedViewMatrix(position);
|
||||
|
||||
glm::quat rotation;
|
||||
getJointRotation(i, rotation);
|
||||
|
@ -85,9 +86,9 @@ void SkeletonModel::updateJointState(int index) {
|
|||
|
||||
if (index == _geometry->getFBXGeometry().rootJointIndex) {
|
||||
JointState& state = _jointStates[index];
|
||||
state.transform[3][0] = _translation.x;
|
||||
state.transform[3][1] = _translation.y;
|
||||
state.transform[3][2] = _translation.z;
|
||||
state.transform[3][0] = 0.0f;
|
||||
state.transform[3][1] = 0.0f;
|
||||
state.transform[3][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ Faceshift::Faceshift() :
|
|||
_jawOpenIndex(21),
|
||||
_longTermAverageEyePitch(0.0f),
|
||||
_longTermAverageEyeYaw(0.0f),
|
||||
_longTermAverageInitialized(false),
|
||||
_estimatedEyePitch(0.0f),
|
||||
_estimatedEyeYaw(0.0f)
|
||||
{
|
||||
|
@ -62,25 +63,23 @@ void Faceshift::update() {
|
|||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
float averageEyePitch = (_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f;
|
||||
float averageEyeYaw = (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f;
|
||||
// get the euler angles relative to the window
|
||||
glm::vec3 eulers = safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
|
||||
(_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f))));
|
||||
|
||||
// get the gaze relative to the window
|
||||
glm::vec3 eyeEulers = safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
|
||||
averageEyePitch, averageEyeYaw, 0.0f))));
|
||||
|
||||
// smooth relative to the window
|
||||
const float LONG_TERM_AVERAGE_SMOOTHING = 0.999f;
|
||||
_longTermAverageEyePitch = glm::mix(eyeEulers.x, _longTermAverageEyePitch, LONG_TERM_AVERAGE_SMOOTHING);
|
||||
_longTermAverageEyeYaw = glm::mix(eyeEulers.y, _longTermAverageEyeYaw, LONG_TERM_AVERAGE_SMOOTHING);
|
||||
|
||||
// back to head-relative
|
||||
float windowEyePitch = eyeEulers.x - _longTermAverageEyePitch;
|
||||
float windowEyeYaw = eyeEulers.y - _longTermAverageEyeYaw;
|
||||
glm::vec3 relativeEyeEulers = safeEulerAngles(glm::inverse(_headRotation) * glm::quat(glm::radians(glm::vec3(
|
||||
windowEyePitch, windowEyeYaw, 0.0f))));
|
||||
_estimatedEyePitch = relativeEyeEulers.x;
|
||||
_estimatedEyeYaw = relativeEyeEulers.y;
|
||||
// compute and subtract the long term average
|
||||
const float LONG_TERM_AVERAGE_SMOOTHING = 0.9999f;
|
||||
if (!_longTermAverageInitialized) {
|
||||
_longTermAverageEyePitch = eulers.x;
|
||||
_longTermAverageEyeYaw = eulers.y;
|
||||
_longTermAverageInitialized = true;
|
||||
|
||||
} else {
|
||||
_longTermAverageEyePitch = glm::mix(eulers.x, _longTermAverageEyePitch, LONG_TERM_AVERAGE_SMOOTHING);
|
||||
_longTermAverageEyeYaw = glm::mix(eulers.y, _longTermAverageEyeYaw, LONG_TERM_AVERAGE_SMOOTHING);
|
||||
}
|
||||
_estimatedEyePitch = eulers.x - _longTermAverageEyePitch;
|
||||
_estimatedEyeYaw = eulers.y - _longTermAverageEyeYaw;
|
||||
}
|
||||
|
||||
void Faceshift::reset() {
|
||||
|
@ -89,6 +88,7 @@ void Faceshift::reset() {
|
|||
fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral());
|
||||
send(message);
|
||||
}
|
||||
_longTermAverageInitialized = false;
|
||||
}
|
||||
|
||||
void Faceshift::setTCPEnabled(bool enabled) {
|
||||
|
|
|
@ -120,6 +120,7 @@ private:
|
|||
|
||||
float _longTermAverageEyePitch;
|
||||
float _longTermAverageEyeYaw;
|
||||
bool _longTermAverageInitialized;
|
||||
|
||||
float _estimatedEyePitch;
|
||||
float _estimatedEyeYaw;
|
||||
|
|
|
@ -175,7 +175,7 @@ void Model::simulate(float deltaTime) {
|
|||
}
|
||||
sourceVertices = _blendedVertices.constData();
|
||||
}
|
||||
glm::mat4 transform;
|
||||
glm::mat4 transform = glm::translate(_translation);
|
||||
if (mesh.clusters.size() > 1) {
|
||||
_blendedVertices.resize(max(_blendedVertices.size(), vertexCount));
|
||||
|
||||
|
@ -283,6 +283,9 @@ bool Model::render(float alpha) {
|
|||
ProgramObject* activeProgram = program;
|
||||
int tangentLocation = _normalMapTangentLocation;
|
||||
if (state.worldSpaceVertices.isEmpty()) {
|
||||
glPushMatrix();
|
||||
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
skinProgram->bind();
|
||||
glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||
|
@ -298,8 +301,7 @@ bool Model::render(float alpha) {
|
|||
activeProgram = skinProgram;
|
||||
tangentLocation = skinLocations->tangent;
|
||||
|
||||
} else {
|
||||
glPushMatrix();
|
||||
} else {
|
||||
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
||||
program->bind();
|
||||
}
|
||||
|
@ -427,11 +429,9 @@ bool Model::render(float alpha) {
|
|||
if (state.worldSpaceVertices.isEmpty()) {
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
|
||||
} else {
|
||||
glPopMatrix();
|
||||
}
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
activeProgram->release();
|
||||
}
|
||||
|
@ -513,8 +513,7 @@ void Model::updateJointState(int index) {
|
|||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
|
||||
if (joint.parentIndex == -1) {
|
||||
glm::mat4 baseTransform = glm::translate(_translation) * glm::mat4_cast(_rotation) *
|
||||
glm::scale(_scale) * glm::translate(_offset);
|
||||
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset);
|
||||
|
||||
glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation;
|
||||
state.transform = baseTransform * geometry.offset * joint.preTransform *
|
||||
|
@ -555,7 +554,7 @@ bool Model::getJointPosition(int jointIndex, glm::vec3& position) const {
|
|||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
position = extractTranslation(_jointStates[jointIndex].transform);
|
||||
position = _translation + extractTranslation(_jointStates[jointIndex].transform);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -572,6 +571,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
|||
if (jointIndex == -1 || _jointStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
glm::vec3 relativePosition = position - _translation;
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const QVector<int>& freeLineage = geometry.joints.at(jointIndex).freeLineage;
|
||||
|
||||
|
@ -583,7 +583,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
|||
glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].transform);
|
||||
for (int j = 1; j < freeLineage.size(); j++) {
|
||||
int index = freeLineage.at(j);
|
||||
if (glm::distance(endPosition, position) < EPSILON) {
|
||||
if (glm::distance(endPosition, relativePosition) < EPSILON) {
|
||||
return true; // close enough to target position
|
||||
}
|
||||
const FBXJoint& joint = geometry.joints.at(index);
|
||||
|
@ -593,7 +593,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position) {
|
|||
JointState& state = _jointStates[index];
|
||||
glm::vec3 jointPosition = extractTranslation(state.transform);
|
||||
glm::vec3 jointVector = endPosition - jointPosition;
|
||||
glm::quat deltaRotation = rotationBetween(jointVector, position - jointPosition);
|
||||
glm::quat deltaRotation = rotationBetween(jointVector, relativePosition - jointPosition);
|
||||
state.rotation = state.rotation * glm::inverse(state.combinedRotation) * deltaRotation * state.combinedRotation;
|
||||
endPosition = deltaRotation * jointVector + jointPosition;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@ public:
|
|||
/// \param ssize_t packetLength size of received data
|
||||
/// \thread network receive thread
|
||||
void queueReceivedPacket(sockaddr& senderAddress, unsigned char* packetData, ssize_t packetLength);
|
||||
|
||||
/// Are there received packets waiting to be processed
|
||||
bool hasPacketsToProcess() const { return _packets.size() > 0; }
|
||||
|
||||
/// How many received packets waiting are to be processed
|
||||
int packetsToProcessCount() const { return _packets.size(); }
|
||||
|
||||
protected:
|
||||
/// Callback for processing of recieved packets. Implement this to process the incoming packets.
|
||||
|
@ -36,12 +42,6 @@ protected:
|
|||
/// Implements generic processing behavior for this thread.
|
||||
virtual bool process();
|
||||
|
||||
/// Are there received packets waiting to be processed
|
||||
bool hasPacketsToProcess() const { return _packets.size() > 0; }
|
||||
|
||||
/// How many received packets waiting are to be processed
|
||||
int packetsToProcessCount() const { return _packets.size(); }
|
||||
|
||||
private:
|
||||
|
||||
std::vector<NetworkPacket> _packets;
|
||||
|
|
|
@ -24,7 +24,7 @@ VoxelSendThread::VoxelSendThread(const QUuid& nodeUUID, VoxelServer* myServer) :
|
|||
}
|
||||
|
||||
bool VoxelSendThread::process() {
|
||||
uint64_t lastSendTime = usecTimestampNow();
|
||||
uint64_t start = usecTimestampNow();
|
||||
|
||||
Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);
|
||||
VoxelNodeData* nodeData = NULL;
|
||||
|
@ -32,6 +32,8 @@ bool VoxelSendThread::process() {
|
|||
if (node) {
|
||||
nodeData = (VoxelNodeData*) node->getLinkedData();
|
||||
}
|
||||
|
||||
int packetsSent = 0;
|
||||
|
||||
// Sometimes the node data has not yet been linked, in which case we can't really do anything
|
||||
if (nodeData) {
|
||||
|
@ -39,11 +41,12 @@ bool VoxelSendThread::process() {
|
|||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
|
||||
}
|
||||
deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
||||
packetsSent = deepestLevelVoxelDistributor(node, nodeData, viewFrustumChanged);
|
||||
}
|
||||
|
||||
// dynamically sleep until we need to fire off the next set of voxels
|
||||
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - (usecTimestampNow() - lastSendTime);
|
||||
int elapsed = (usecTimestampNow() - start);
|
||||
int usecToSleep = VOXEL_SEND_INTERVAL_USECS - elapsed;
|
||||
|
||||
if (usecToSleep > 0) {
|
||||
usleep(usecToSleep);
|
||||
|
@ -52,19 +55,19 @@ bool VoxelSendThread::process() {
|
|||
std::cout << "Last send took too much time, not sleeping!\n";
|
||||
}
|
||||
}
|
||||
|
||||
return isStillRunning(); // keep running till they terminate us
|
||||
}
|
||||
|
||||
|
||||
void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
||||
int VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent) {
|
||||
|
||||
int packetsSent = 0;
|
||||
// Here's where we check to see if this packet is a duplicate of the last packet. If it is, we will silently
|
||||
// obscure the packet and not send it. This allows the callers and upper level logic to not need to know about
|
||||
// this rate control savings.
|
||||
if (nodeData->shouldSuppressDuplicatePacket()) {
|
||||
nodeData->resetVoxelPacket(); // we still need to reset it though!
|
||||
return; // without sending...
|
||||
return packetsSent; // without sending...
|
||||
}
|
||||
|
||||
// If we've got a stats message ready to send, then see if we can piggyback them together
|
||||
|
@ -85,6 +88,10 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
|||
} else {
|
||||
// not enough room in the packet, send two packets
|
||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), statsMessage, statsMessageLength);
|
||||
trueBytesSent += statsMessageLength;
|
||||
truePacketsSent++;
|
||||
packetsSent++;
|
||||
|
||||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
}
|
||||
|
@ -98,16 +105,21 @@ void VoxelSendThread::handlePacketSend(Node* node, VoxelNodeData* nodeData, int&
|
|||
nodeData->stats.packetSent(nodeData->getPacketLength());
|
||||
trueBytesSent += nodeData->getPacketLength();
|
||||
truePacketsSent++;
|
||||
packetsSent++;
|
||||
nodeData->resetVoxelPacket();
|
||||
return packetsSent;
|
||||
}
|
||||
|
||||
/// Version of voxel distributor that sends the deepest LOD level at once
|
||||
void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
||||
int VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged) {
|
||||
|
||||
_myServer->lockTree();
|
||||
|
||||
int truePacketsSent = 0;
|
||||
int trueBytesSent = 0;
|
||||
int packetsSentThisInterval = 0;
|
||||
bool somethingToSend = true; // assume we have something
|
||||
|
||||
|
||||
// FOR NOW... node tells us if it wants to receive only view frustum deltas
|
||||
bool wantDelta = viewFrustumChanged && nodeData->getWantDelta();
|
||||
|
@ -128,8 +140,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()));
|
||||
}
|
||||
|
||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
} else {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n",
|
||||
|
@ -218,21 +229,26 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
// If we have something in our nodeBag, then turn them into packets and send them out...
|
||||
if (!nodeData->nodeBag.isEmpty()) {
|
||||
int bytesWritten = 0;
|
||||
int packetsSentThisInterval = 0;
|
||||
uint64_t start = usecTimestampNow();
|
||||
|
||||
bool shouldSendEnvironments = _myServer->wantSendEnvironments() && shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||
|
||||
int clientMaxPacketsPerInterval = nodeData->getMaxVoxelPacketsPerSecond() / INTERVALS_PER_SECOND;
|
||||
int maxPacketsPerInterval = std::max(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||
int clientMaxPacketsPerInterval = std::max(1,(nodeData->getMaxVoxelPacketsPerSecond() / INTERVALS_PER_SECOND));
|
||||
int maxPacketsPerInterval = std::min(clientMaxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval());
|
||||
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||
packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||
}
|
||||
while (somethingToSend && packetsSentThisInterval < maxPacketsPerInterval - (shouldSendEnvironments ? 1 : 0)) {
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||
}
|
||||
|
||||
|
||||
while (packetsSentThisInterval < maxPacketsPerInterval - (shouldSendEnvironments ? 1 : 0)) {
|
||||
// Check to see if we're taking too long, and if so bail early...
|
||||
uint64_t now = usecTimestampNow();
|
||||
long elapsedUsec = (now - start);
|
||||
|
@ -277,17 +293,18 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
if (nodeData->getAvailable() >= bytesWritten) {
|
||||
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
||||
} else {
|
||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
packetsSentThisInterval++;
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
nodeData->writeToPacket(_tempOutputBuffer, bytesWritten);
|
||||
}
|
||||
} else {
|
||||
if (nodeData->isPacketWaiting()) {
|
||||
handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
packetsSentThisInterval += handlePacketSend(node, nodeData, trueBytesSent, truePacketsSent);
|
||||
}
|
||||
packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
||||
//packetsSentThisInterval = _myServer->getPacketsPerClientPerInterval(); // done for now, no nodes left
|
||||
somethingToSend = false;
|
||||
}
|
||||
}
|
||||
|
||||
// send the environment packet
|
||||
if (shouldSendEnvironments) {
|
||||
int numBytesPacketHeader = populateTypeAndVersion(_tempOutputBuffer, PACKET_TYPE_ENVIRONMENT_DATA);
|
||||
|
@ -301,6 +318,7 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
NodeList::getInstance()->getNodeSocket()->send(node->getActiveSocket(), _tempOutputBuffer, envPacketLength);
|
||||
trueBytesSent += envPacketLength;
|
||||
truePacketsSent++;
|
||||
packetsSentThisInterval++;
|
||||
}
|
||||
|
||||
uint64_t end = usecTimestampNow();
|
||||
|
@ -329,9 +347,17 @@ void VoxelSendThread::deepestLevelVoxelDistributor(Node* node, VoxelNodeData* no
|
|||
}
|
||||
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
|
||||
}
|
||||
|
||||
if (_myServer->wantsDebugVoxelSending()) {
|
||||
printf("truePacketsSent=%d packetsSentThisInterval=%d maxPacketsPerInterval=%d server PPI=%d nodePPS=%d nodePPI=%d\n",
|
||||
truePacketsSent, packetsSentThisInterval, maxPacketsPerInterval, _myServer->getPacketsPerClientPerInterval(),
|
||||
nodeData->getMaxVoxelPacketsPerSecond(), clientMaxPacketsPerInterval);
|
||||
}
|
||||
|
||||
} // end if bag wasn't empty, and so we sent stuff...
|
||||
|
||||
_myServer->unlockTree();
|
||||
|
||||
return truePacketsSent;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ private:
|
|||
QUuid _nodeUUID;
|
||||
VoxelServer* _myServer;
|
||||
|
||||
void handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||
void deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged);
|
||||
int handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent);
|
||||
int deepestLevelVoxelDistributor(Node* node, VoxelNodeData* nodeData, bool viewFrustumChanged);
|
||||
|
||||
unsigned char _tempOutputBuffer[MAX_VOXEL_PACKET_SIZE];
|
||||
};
|
||||
|
|
|
@ -112,6 +112,18 @@ int VoxelServer::civetwebRequestHandler(struct mg_connection* connection) {
|
|||
// return a 200
|
||||
mg_printf(connection, "%s", "HTTP/1.0 200 OK\r\n\r\n");
|
||||
mg_printf(connection, "%s", "Your Voxel Server is running.\r\n");
|
||||
|
||||
|
||||
|
||||
mg_printf(connection, "%s", "\r\n");
|
||||
mg_printf(connection, "%s", "Configuration: \r\n ");
|
||||
for (int i = 1; i < GetInstance()->_argc; i++) {
|
||||
mg_printf(connection, "%s ", GetInstance()->_argv[i]);
|
||||
}
|
||||
mg_printf(connection, "%s", "\r\n");
|
||||
mg_printf(connection, "%s", "\r\n");
|
||||
|
||||
|
||||
mg_printf(connection, "%s", "Current Statistics\r\n");
|
||||
mg_printf(connection, "%s", "\r\n");
|
||||
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
|
||||
|
||||
const int MAX_FILENAME_LENGTH = 1024;
|
||||
const int VOXEL_SIZE_BYTES = 3 + (3 * sizeof(float));
|
||||
const int VOXELS_PER_PACKET = (MAX_PACKET_SIZE - 1) / VOXEL_SIZE_BYTES;
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 17 * 1000; // approximately 60fps
|
||||
const int INTERVALS_PER_SECOND = 60;
|
||||
const int VOXEL_SEND_INTERVAL_USECS = (1000 * 1000)/INTERVALS_PER_SECOND;
|
||||
const int SENDING_TIME_TO_SPARE = 5 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
const int INTERVALS_PER_SECOND = 1000 * 1000 / VOXEL_SEND_INTERVAL_USECS;
|
||||
const int ENVIRONMENT_SEND_INTERVAL_USECS = 1000000;
|
||||
|
||||
extern const char* LOCAL_VOXELS_PERSIST_FILE;
|
||||
|
|
|
@ -33,7 +33,9 @@ void JurisdictionListener::nodeAdded(Node* node) {
|
|||
}
|
||||
|
||||
void JurisdictionListener::nodeKilled(Node* node) {
|
||||
_jurisdictions.erase(_jurisdictions.find(node->getUUID()));
|
||||
if (_jurisdictions.find(node->getUUID()) != _jurisdictions.end()) {
|
||||
_jurisdictions.erase(_jurisdictions.find(node->getUUID()));
|
||||
}
|
||||
}
|
||||
|
||||
bool JurisdictionListener::queueJurisdictionRequest() {
|
||||
|
|
|
@ -109,10 +109,10 @@ void VoxelTree::recurseNodeWithOperationDistanceSorted(VoxelNode* node, RecurseV
|
|||
|
||||
if (operation(node, extraData)) {
|
||||
// determine the distance sorted order of our children
|
||||
VoxelNode* sortedChildren[NUMBER_OF_CHILDREN];
|
||||
float distancesToChildren[NUMBER_OF_CHILDREN];
|
||||
int indexOfChildren[NUMBER_OF_CHILDREN]; // not really needed
|
||||
int currentCount = 0;
|
||||
VoxelNode* sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int currentCount = 0;
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
VoxelNode* childNode = node->getChildAtIndex(i);
|
||||
|
@ -1231,10 +1231,10 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp
|
|||
int inViewNotLeafCount = 0;
|
||||
int inViewWithColorCount = 0;
|
||||
|
||||
VoxelNode* sortedChildren[NUMBER_OF_CHILDREN];
|
||||
float distancesToChildren[NUMBER_OF_CHILDREN];
|
||||
int indexOfChildren[NUMBER_OF_CHILDREN]; // not really needed
|
||||
int currentCount = 0;
|
||||
VoxelNode* sortedChildren[NUMBER_OF_CHILDREN] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
float distancesToChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int indexOfChildren[NUMBER_OF_CHILDREN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
int currentCount = 0;
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
|
||||
VoxelNode* childNode = node->getChildAtIndex(i);
|
||||
|
|
Loading…
Reference in a new issue