resolve conflicts on merge with upstream master

This commit is contained in:
Stephen Birarda 2013-07-03 15:12:50 -07:00
commit 0be42698b5
10 changed files with 129 additions and 35 deletions

View file

@ -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})

View file

@ -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();

View file

@ -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;

View file

@ -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;};

View file

@ -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() {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;
};

View file

@ -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);