mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:24:07 +02:00
resolve conflicts on merge with upstream master
This commit is contained in:
commit
0be42698b5
10 changed files with 129 additions and 35 deletions
5
interface/external/fervor/CMakeLists.txt
vendored
5
interface/external/fervor/CMakeLists.txt
vendored
|
@ -6,6 +6,11 @@ add_definitions(-DFV_GUI)
|
|||
|
||||
file(GLOB FERVOR_SOURCES *.cpp)
|
||||
file(GLOB FERVOR_HEADERS *.h)
|
||||
|
||||
LIST(GET FERVOR_HEADERS 1 FIRST_HEADER)
|
||||
GET_FILENAME_COMPONENT(HEADER_PATH ${FIRST_HEADER} PATH)
|
||||
list(REMOVE_ITEM FERVOR_HEADERS ${HEADER_PATH}/fvversioncomparator.h)
|
||||
|
||||
file(GLOB FERVOR_UI *.ui)
|
||||
|
||||
qt4_wrap_ui(FERVOR_WRAPPED_UI ${FERVOR_UI})
|
||||
|
|
|
@ -362,9 +362,7 @@ void Application::paintGL() {
|
|||
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
float headCameraScale = (_serialHeadSensor.isActive() || _webcam.isActive()) ? _headCameraPitchYawScale : 1.0f;
|
||||
|
||||
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_myCamera.setTightness (100.0f);
|
||||
_myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition());
|
||||
|
@ -380,11 +378,11 @@ void Application::paintGL() {
|
|||
} else if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||
_myCamera.setTightness(0.0f); // In first person, camera follows head exactly without delay
|
||||
_myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(headCameraScale));
|
||||
_myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation());
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setTargetPosition(_myAvatar.getUprightHeadPosition());
|
||||
_myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation(headCameraScale));
|
||||
_myCamera.setTargetRotation(_myAvatar.getHead().getCameraOrientation());
|
||||
}
|
||||
|
||||
// Update camera position
|
||||
|
@ -946,6 +944,15 @@ void Application::idle() {
|
|||
// Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran
|
||||
|
||||
if (diffclock(&_lastTimeIdle, &check) > IDLE_SIMULATE_MSECS) {
|
||||
// We call processEvents() here because the idle timer takes priority over
|
||||
// event handling in Qt, so when the framerate gets low events will pile up
|
||||
// unless we handle them here.
|
||||
|
||||
// NOTE - this is commented out for now - causing event processing issues reported by Philip and Ryan
|
||||
// birarda - July 3rd
|
||||
|
||||
// processEvents();
|
||||
|
||||
update(1.0f / _fps);
|
||||
|
||||
_glWidget->updateGL();
|
||||
|
@ -1453,8 +1460,8 @@ void Application::initMenu() {
|
|||
(_echoAudioMode = optionsMenu->addAction("Echo Audio"))->setCheckable(true);
|
||||
|
||||
optionsMenu->addAction("Noise", this, SLOT(setNoise(bool)), Qt::Key_N)->setCheckable(true);
|
||||
(_gyroLook = optionsMenu->addAction("Gyro Look"))->setCheckable(true);
|
||||
_gyroLook->setChecked(false);
|
||||
(_gyroLook = optionsMenu->addAction("Smooth Gyro Look"))->setCheckable(true);
|
||||
_gyroLook->setChecked(true);
|
||||
(_mouseLook = optionsMenu->addAction("Mouse Look"))->setCheckable(true);
|
||||
_mouseLook->setChecked(true);
|
||||
(_touchLook = optionsMenu->addAction("Touch Look"))->setCheckable(true);
|
||||
|
@ -1908,18 +1915,13 @@ void Application::update(float deltaTime) {
|
|||
void Application::updateAvatar(float deltaTime) {
|
||||
|
||||
// Update my avatar's head position from gyros and/or webcam
|
||||
_myAvatar.updateHeadFromGyrosAndOrWebcam();
|
||||
_myAvatar.updateHeadFromGyrosAndOrWebcam(_gyroLook->isChecked(),
|
||||
glm::vec3(_headCameraPitchYawScale,
|
||||
_headCameraPitchYawScale,
|
||||
_headCameraPitchYawScale));
|
||||
|
||||
if (_serialHeadSensor.isActive()) {
|
||||
|
||||
// Update avatar head translation
|
||||
if (_gyroLook->isChecked()) {
|
||||
glm::vec3 headPosition = _serialHeadSensor.getEstimatedPosition();
|
||||
const float HEAD_OFFSET_SCALING = 3.f;
|
||||
headPosition *= HEAD_OFFSET_SCALING;
|
||||
_myCamera.setEyeOffsetPosition(headPosition);
|
||||
}
|
||||
|
||||
// Grab latest readings from the gyros
|
||||
float measuredPitchRate = _serialHeadSensor.getLastPitchRate();
|
||||
float measuredYawRate = _serialHeadSensor.getLastYawRate();
|
||||
|
|
|
@ -285,10 +285,7 @@ void Avatar::reset() {
|
|||
}
|
||||
|
||||
// Update avatar head rotation with sensor data
|
||||
void Avatar::updateHeadFromGyrosAndOrWebcam() {
|
||||
const float AMPLIFY_PITCH = 2.f;
|
||||
const float AMPLIFY_YAW = 2.f;
|
||||
const float AMPLIFY_ROLL = 2.f;
|
||||
void Avatar::updateHeadFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngle) {
|
||||
|
||||
SerialInterface* gyros = Application::getInstance()->getSerialHeadSensor();
|
||||
Webcam* webcam = Application::getInstance()->getWebcam();
|
||||
|
@ -306,9 +303,10 @@ void Avatar::updateHeadFromGyrosAndOrWebcam() {
|
|||
} else {
|
||||
return;
|
||||
}
|
||||
_head.setPitch(estimatedRotation.x * AMPLIFY_PITCH);
|
||||
_head.setYaw(estimatedRotation.y * AMPLIFY_YAW);
|
||||
_head.setRoll(estimatedRotation.z * AMPLIFY_ROLL);
|
||||
_head.setPitch(estimatedRotation.x * amplifyAngle.x);
|
||||
_head.setYaw(estimatedRotation.y * amplifyAngle.y);
|
||||
_head.setRoll(estimatedRotation.z * amplifyAngle.z);
|
||||
_head.setCameraFollowsHead(gyroLook);
|
||||
|
||||
// Update torso lean distance based on accelerometer data
|
||||
const float TORSO_LENGTH = 0.5f;
|
||||
|
|
|
@ -87,7 +87,7 @@ public:
|
|||
void reset();
|
||||
void simulate(float deltaTime, Transmitter* transmitter);
|
||||
void updateThrust(float deltaTime, Transmitter * transmitter);
|
||||
void updateHeadFromGyrosAndOrWebcam();
|
||||
void updateHeadFromGyrosAndOrWebcam(bool gyroLook, const glm::vec3& amplifyAngles);
|
||||
void updateFromMouse(int mouseX, int mouseY, int screenWidth, int screenHeight);
|
||||
void updateFromTouch(float touchAvgDistX, float touchAvgDistY);
|
||||
void addBodyYaw(float y) {_bodyYaw += y;};
|
||||
|
|
|
@ -77,7 +77,12 @@ Head::Head(Avatar* owningAvatar) :
|
|||
_rightEyeBlink(0.0f),
|
||||
_leftEyeBlinkVelocity(0.0f),
|
||||
_rightEyeBlinkVelocity(0.0f),
|
||||
_timeWithoutTalking(0.0f)
|
||||
_timeWithoutTalking(0.0f),
|
||||
_cameraPitch(_pitch),
|
||||
_cameraYaw(_yaw),
|
||||
_isCameraMoving(false),
|
||||
_cameraFollowsHead(false),
|
||||
_cameraFollowHeadRate(0.0f)
|
||||
{
|
||||
if (USING_PHYSICAL_MOHAWK) {
|
||||
resetHairPhysics();
|
||||
|
@ -213,6 +218,37 @@ void Head::simulate(float deltaTime, bool isMine) {
|
|||
updateHairPhysics(deltaTime);
|
||||
}
|
||||
|
||||
// Update camera pitch and yaw independently from motion of head (for gyro-based interface)
|
||||
if (isMine && _cameraFollowsHead) {
|
||||
// If we are using gyros and using gyroLook, have the camera follow head but with a null region
|
||||
// to create stable rendering view with small head movements.
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_START = 0.05f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_MAX = 0.25f;
|
||||
const float CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE = 1.5f;
|
||||
const float CAMERA_STOP_TOLERANCE_DEGREES = 0.25f;
|
||||
const float CAMERA_START_TOLERANCE_DEGREES = 15.0f;
|
||||
float cameraHeadAngleDifference = glm::length(glm::vec2(_pitch - _cameraPitch, _yaw - _cameraYaw));
|
||||
if (_isCameraMoving) {
|
||||
_cameraFollowHeadRate = glm::clamp(_cameraFollowHeadRate * CAMERA_FOLLOW_HEAD_RATE_RAMP_RATE,
|
||||
0.f,
|
||||
CAMERA_FOLLOW_HEAD_RATE_MAX);
|
||||
|
||||
_cameraPitch += (_pitch - _cameraPitch) * _cameraFollowHeadRate;
|
||||
_cameraYaw += (_yaw - _cameraYaw) * _cameraFollowHeadRate;
|
||||
if (cameraHeadAngleDifference < CAMERA_STOP_TOLERANCE_DEGREES) {
|
||||
_isCameraMoving = false;
|
||||
}
|
||||
} else {
|
||||
if (cameraHeadAngleDifference > CAMERA_START_TOLERANCE_DEGREES) {
|
||||
_isCameraMoving = true;
|
||||
_cameraFollowHeadRate = CAMERA_FOLLOW_HEAD_RATE_START;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Camera always locked to head
|
||||
_cameraPitch = _pitch;
|
||||
_cameraYaw = _yaw;
|
||||
}
|
||||
}
|
||||
|
||||
void Head::calculateGeometry() {
|
||||
|
@ -358,10 +394,10 @@ glm::quat Head::getOrientation() const {
|
|||
glm::vec3(_pitch, -_yaw, -_roll) : glm::vec3(_pitch, _yaw, _roll)));
|
||||
}
|
||||
|
||||
glm::quat Head::getCameraOrientation (float pitchYawScale) const {
|
||||
glm::quat Head::getCameraOrientation () const {
|
||||
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
|
||||
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(
|
||||
_pitch * pitchYawScale, _yaw * pitchYawScale, 0.0f)));
|
||||
return owningAvatar->getWorldAlignedOrientation()
|
||||
* glm::quat(glm::radians(glm::vec3(_cameraPitch, _cameraYaw, 0.0f)));
|
||||
}
|
||||
|
||||
void Head::renderHeadSphere() {
|
||||
|
|
|
@ -48,8 +48,10 @@ public:
|
|||
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
|
||||
void setRenderLookatVectors(bool onOff ) { _renderLookatVectors = onOff; }
|
||||
|
||||
void setCameraFollowsHead(bool cameraFollowsHead) { _cameraFollowsHead = cameraFollowsHead; }
|
||||
|
||||
glm::quat getOrientation() const;
|
||||
glm::quat getCameraOrientation (float pitchYawScale) const;
|
||||
glm::quat getCameraOrientation () const;
|
||||
|
||||
glm::vec3 getPosition() const { return _position; }
|
||||
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||
|
@ -112,6 +114,11 @@ private:
|
|||
float _leftEyeBlinkVelocity;
|
||||
float _rightEyeBlinkVelocity;
|
||||
float _timeWithoutTalking;
|
||||
float _cameraPitch; // Used to position the camera differently from the head
|
||||
float _cameraYaw;
|
||||
bool _isCameraMoving;
|
||||
bool _cameraFollowsHead;
|
||||
float _cameraFollowHeadRate;
|
||||
|
||||
static ProgramObject* _irisProgram;
|
||||
static GLuint _irisTextureID;
|
||||
|
|
|
@ -17,6 +17,9 @@ HifiLeapListener* LeapManager::_listener = NULL;
|
|||
|
||||
class HifiLeapListener : public Leap::Listener {
|
||||
public:
|
||||
HifiLeapListener() {}
|
||||
virtual ~HifiLeapListener() {}
|
||||
|
||||
Leap::Frame lastFrame;
|
||||
std::vector<glm::vec3> fingerTips;
|
||||
std::vector<glm::vec3> fingerRoots;
|
||||
|
|
|
@ -16,7 +16,8 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) :
|
|||
_viewSent(false),
|
||||
_voxelPacketAvailableBytes(MAX_VOXEL_PACKET_SIZE),
|
||||
_maxSearchLevel(1),
|
||||
_maxLevelReachedInLastSearch(1)
|
||||
_maxLevelReachedInLastSearch(1),
|
||||
_lastTimeBagEmpty(0)
|
||||
{
|
||||
_voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE];
|
||||
_voxelPacketAt = _voxelPacket;
|
||||
|
|
|
@ -50,6 +50,10 @@ public:
|
|||
bool getViewSent() const { return _viewSent; };
|
||||
void setViewSent(bool viewSent) { _viewSent = viewSent; }
|
||||
|
||||
long long getLastTimeBagEmpty() const { return _lastTimeBagEmpty; };
|
||||
void setLastTimeBagEmpty(long long lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; };
|
||||
|
||||
|
||||
private:
|
||||
VoxelNodeData(const VoxelNodeData &);
|
||||
VoxelNodeData& operator= (const VoxelNodeData&);
|
||||
|
@ -63,6 +67,7 @@ private:
|
|||
int _maxLevelReachedInLastSearch;
|
||||
ViewFrustum _currentViewFrustum;
|
||||
ViewFrustum _lastKnownViewFrustum;
|
||||
long long _lastTimeBagEmpty;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ const float MAX_CUBE = 0.05f;
|
|||
|
||||
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
|
||||
int PACKETS_PER_CLIENT_PER_INTERVAL = 30;
|
||||
const int SENDING_TIME_TO_SPARE = 20 * 1000; // usec of sending interval to spare for calculating voxels
|
||||
|
||||
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
|
||||
|
||||
|
@ -263,6 +264,28 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
// If the current view frustum has changed OR we have nothing to send, then search against
|
||||
// the current view frustum for things to send.
|
||||
if (viewFrustumChanged || nodeData->nodeBag.isEmpty()) {
|
||||
if (::debugVoxelSending) {
|
||||
printf("(viewFrustumChanged=%s || agentData->nodeBag.isEmpty() =%s)...\n",
|
||||
debug::valueOf(viewFrustumChanged), debug::valueOf(agentData->nodeBag.isEmpty()));
|
||||
long long now = usecTimestampNow();
|
||||
if (agentData->getLastTimeBagEmpty() > 0) {
|
||||
float elapsedSceneSend = (now - agentData->getLastTimeBagEmpty()) / 1000000.0f;
|
||||
|
||||
if (viewFrustumChanged) {
|
||||
printf("viewFrustumChanged resetting after elapsed time to send scene = %f seconds", elapsedSceneSend);
|
||||
} else {
|
||||
printf("elapsed time to send scene = %f seconds", elapsedSceneSend);
|
||||
}
|
||||
printf(" [occlusionCulling: %s]\n", debug::valueOf(agentData->getWantOcclusionCulling()));
|
||||
}
|
||||
agentData->setLastTimeBagEmpty(now);
|
||||
}
|
||||
|
||||
// if our view has changed, we need to reset these things...
|
||||
if (viewFrustumChanged) {
|
||||
agentData->nodeBag.deleteAll();
|
||||
agentData->map.erase();
|
||||
}
|
||||
|
||||
// For now, we're going to disable the "search for colored nodes" because that strategy doesn't work when we support
|
||||
// deletion of nodes. Instead if we just start at the root we get the correct behavior we want. We are keeping this
|
||||
|
@ -309,7 +332,22 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
long long start = usecTimestampNow();
|
||||
|
||||
bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS);
|
||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) {
|
||||
while (packetsSentThisInterval < PACKETS_PER_CLIENT_PER_INTERVAL - (shouldSendEnvironments ? 1 : 0)) {
|
||||
// Check to see if we're taking too long, and if so bail early...
|
||||
long long now = usecTimestampNow();
|
||||
long elapsedUsec = (now - start);
|
||||
long elapsedUsecPerPacket = (truePacketsSent == 0) ? 0 : (elapsedUsec / truePacketsSent);
|
||||
long usecRemaining = (VOXEL_SEND_INTERVAL_USECS - elapsedUsec);
|
||||
|
||||
if (elapsedUsecPerPacket + SENDING_TIME_TO_SPARE > usecRemaining) {
|
||||
if (::debugVoxelSending) {
|
||||
printf("packetLoop() usecRemaining=%ld bailing early took %ld usecs to generate %d bytes in %d packets (%ld usec avg), %d nodes still to send\n",
|
||||
usecRemaining, elapsedUsec, trueBytesSent, truePacketsSent, elapsedUsecPerPacket,
|
||||
agentData->nodeBag.count());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nodeData->nodeBag.isEmpty()) {
|
||||
VoxelNode* subTree = nodeData->nodeBag.extract();
|
||||
|
||||
|
@ -323,8 +361,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1,
|
||||
nodeData->nodeBag, params);
|
||||
|
||||
if (nodeData->getAvailable() >= bytesWritten) {
|
||||
nodeData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
if (agentData->getAvailable() >= bytesWritten) {
|
||||
agentData->writeToPacket(&tempOutputBuffer[0], bytesWritten);
|
||||
} else {
|
||||
nodeList->getNodeSocket()->send(node->getActiveSocket(),
|
||||
nodeData->getPacket(), nodeData->getPacketLength());
|
||||
|
@ -379,10 +417,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList,
|
|||
if (nodeData->nodeBag.isEmpty()) {
|
||||
nodeData->updateLastKnownViewFrustum();
|
||||
nodeData->setViewSent(true);
|
||||
nodeData->map.erase();
|
||||
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
|
||||
}
|
||||
|
||||
|
||||
} // end if bag wasn't empty, and so we sent stuff...
|
||||
|
||||
pthread_mutex_unlock(&::treeLock);
|
||||
|
|
Loading…
Reference in a new issue