Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Jeffrey Ventrella 2013-05-20 17:33:27 -07:00
commit 6e994ed425
13 changed files with 343 additions and 274 deletions

View file

@ -138,6 +138,7 @@ Application::Application(int& argc, char** argv) :
_mouseY(0), _mouseY(0),
_mousePressed(false), _mousePressed(false),
_mouseVoxelScale(1.0f / 1024.0f), _mouseVoxelScale(1.0f / 1024.0f),
_justEditedVoxel(false),
_paintOn(false), _paintOn(false),
_dominantColor(0), _dominantColor(0),
_perfStatsOn(false), _perfStatsOn(false),
@ -297,8 +298,9 @@ void Application::paintGL() {
_myCamera.setDistance (0.0f); _myCamera.setDistance (0.0f);
_myCamera.setTightness (100.0f); _myCamera.setTightness (100.0f);
_myCamera.setTargetPosition(_myAvatar.getHeadPosition()); _myCamera.setTargetPosition(_myAvatar.getHeadPosition());
_myCamera.setTargetRotation(_myAvatar.getBodyYaw() + _myAvatar.getHeadYaw(), _myCamera.setTargetRotation(_myAvatar.getBodyYaw() + _myAvatar.getHead().getYaw(),
-_myAvatar.getHeadPitch(), _myAvatar.getHeadRoll()); -_myAvatar.getHead().getPitch(),
_myAvatar.getHead().getRoll());
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
_myCamera.setTightness (100.0f); _myCamera.setTightness (100.0f);
@ -738,8 +740,13 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
// detect drag // detect drag
glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); glm::vec3 mouseVoxelPos(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
if (_colorVoxelMode->isChecked() && event->buttons().testFlag(Qt::LeftButton) && mouseVoxelPos != _lastMouseVoxelPos) { if (!_justEditedVoxel && mouseVoxelPos != _lastMouseVoxelPos) {
addVoxelUnderCursor(); if (event->buttons().testFlag(Qt::LeftButton)) {
maybeEditVoxelUnderCursor();
} else if (event->buttons().testFlag(Qt::RightButton) && checkedVoxelModeAction() != 0) {
deleteVoxelUnderCursor();
}
} }
} }
@ -748,13 +755,8 @@ void Application::mousePressEvent(QMouseEvent* event) {
_mouseX = event->x(); _mouseX = event->x();
_mouseY = event->y(); _mouseY = event->y();
_mousePressed = true; _mousePressed = true;
maybeEditVoxelUnderCursor();
if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
addVoxelUnderCursor();
} else if (_deleteVoxelMode->isChecked()) {
deleteVoxelUnderCursor();
}
} else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) { } else if (event->button() == Qt::RightButton && checkedVoxelModeAction() != 0) {
deleteVoxelUnderCursor(); deleteVoxelUnderCursor();
} }
@ -927,6 +929,12 @@ void Application::idle() {
_mouseVoxel.green = paintColor.green(); _mouseVoxel.green = paintColor.green();
_mouseVoxel.blue = paintColor.blue(); _mouseVoxel.blue = paintColor.blue();
} }
// if we just edited, use the currently selected voxel as the "last" for drag detection
if (_justEditedVoxel) {
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
_justEditedVoxel = false;
}
} }
// walking triggers the handControl to stop // walking triggers the handControl to stop
@ -1202,6 +1210,8 @@ void Application::initMenu() {
(_renderVoxels = renderMenu->addAction("Voxels"))->setCheckable(true); (_renderVoxels = renderMenu->addAction("Voxels"))->setCheckable(true);
_renderVoxels->setChecked(true); _renderVoxels->setChecked(true);
_renderVoxels->setShortcut(Qt::Key_V); _renderVoxels->setShortcut(Qt::Key_V);
(_renderVoxelTextures = renderMenu->addAction("Voxel Textures"))->setCheckable(true);
_renderVoxelTextures->setChecked(true);
(_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true); (_renderStarsOn = renderMenu->addAction("Stars"))->setCheckable(true);
_renderStarsOn->setChecked(true); _renderStarsOn->setChecked(true);
_renderStarsOn->setShortcut(Qt::Key_Asterisk); _renderStarsOn->setShortcut(Qt::Key_Asterisk);
@ -1355,29 +1365,13 @@ void Application::updateAvatar(float deltaTime) {
_headMouseY = max(_headMouseY, 0); _headMouseY = max(_headMouseY, 0);
_headMouseY = min(_headMouseY, _glWidget->height()); _headMouseY = min(_headMouseY, _glWidget->height());
// Update head and body pitch and yaw based on measured gyro rates
if (_gyroLook->isChecked()) {
// Render Yaw
/* NOTE: PER - Leave here until I get back and can modify to couple gyros to head pitch, yaw
float renderYawSpring = fabs(_headMouseX - _glWidget->width() / 2.f) / (_glWidget->width() / 2.f);
const float RENDER_YAW_MULTIPLY = 4.f;
_myAvatar.setRenderYaw((1.f - renderYawSpring * deltaTime) * _myAvatar.getRenderYaw() +
renderYawSpring * deltaTime * -_myAvatar.getHeadYaw() * RENDER_YAW_MULTIPLY);
// Render Pitch
float renderPitchSpring = fabs(_headMouseY - _glWidget->height() / 2.f) / (_glWidget->height() / 2.f);
const float RENDER_PITCH_MULTIPLY = 4.f;
_myAvatar.setRenderPitch((1.f - renderPitchSpring * deltaTime) * _myAvatar.getRenderPitch() +
renderPitchSpring * deltaTime * -_myAvatar.getHeadPitch() * RENDER_PITCH_MULTIPLY);
*/
}
if (OculusManager::isConnected()) { if (OculusManager::isConnected()) {
float yaw, pitch, roll; float yaw, pitch, roll;
OculusManager::getEulerAngles(yaw, pitch, roll); OculusManager::getEulerAngles(yaw, pitch, roll);
_myAvatar.setHeadYaw(-yaw); _myAvatar.getHead().setYaw(-yaw);
_myAvatar.setHeadPitch(pitch); _myAvatar.getHead().setPitch(pitch);
_myAvatar.setHeadRoll(roll); _myAvatar.getHead().setRoll(roll);
} }
// Get audio loudness data from audio input device // Get audio loudness data from audio input device
@ -1678,7 +1672,7 @@ void Application::displaySide(Camera& whichCamera) {
// Draw voxels // Draw voxels
if (_renderVoxels->isChecked()) { if (_renderVoxels->isChecked()) {
_voxels.render(); _voxels.render(_renderVoxelTextures->isChecked());
} }
// indicate what we'll be adding/removing in mouse mode, if anything // indicate what we'll be adding/removing in mouse mode, if anything
@ -2020,18 +2014,22 @@ void Application::shiftPaintingColor() {
_paintingVoxel.blue = (_dominantColor == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100); _paintingVoxel.blue = (_dominantColor == 2) ? randIntInRange(200, 255) : randIntInRange(40, 100);
} }
void Application::addVoxelUnderCursor() { void Application::maybeEditVoxelUnderCursor() {
if (_mouseVoxel.s != 0) { if (_addVoxelMode->isChecked() || _colorVoxelMode->isChecked()) {
PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ? if (_mouseVoxel.s != 0) {
PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL); PACKET_HEADER message = (_destructiveAddVoxel->isChecked() ?
sendVoxelEditMessage(message, _mouseVoxel); PACKET_HEADER_SET_VOXEL_DESTRUCTIVE : PACKET_HEADER_SET_VOXEL);
sendVoxelEditMessage(message, _mouseVoxel);
// create the voxel locally so it appears immediately
_voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s,
_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked());
// create the voxel locally so it appears immediately // remember the position for drag detection
_voxels.createVoxel(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s, _justEditedVoxel = true;
_mouseVoxel.red, _mouseVoxel.green, _mouseVoxel.blue, _destructiveAddVoxel->isChecked()); }
} else if (_deleteVoxelMode->isChecked()) {
// remember the position for drag detection deleteVoxelUnderCursor();
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z);
} }
} }
@ -2043,7 +2041,7 @@ void Application::deleteVoxelUnderCursor() {
_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); _voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
// remember the position for drag detection // remember the position for drag detection
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); _justEditedVoxel = true;
} }
} }

View file

@ -116,7 +116,7 @@ private:
void setupPaintingVoxel(); void setupPaintingVoxel();
void shiftPaintingColor(); void shiftPaintingColor();
void addVoxelUnderCursor(); void maybeEditVoxelUnderCursor();
void deleteVoxelUnderCursor(); void deleteVoxelUnderCursor();
void resetSensors(); void resetSensors();
@ -135,6 +135,7 @@ private:
QAction* _gyroLook; // Whether to allow the gyro data from head to move your view QAction* _gyroLook; // Whether to allow the gyro data from head to move your view
QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view QAction* _mouseLook; // Whether the have the mouse near edge of screen move your view
QAction* _renderVoxels; // Whether to render voxels QAction* _renderVoxels; // Whether to render voxels
QAction* _renderVoxelTextures; // Whether to render noise textures on voxels
QAction* _renderStarsOn; // Whether to display the stars QAction* _renderStarsOn; // Whether to display the stars
QAction* _renderAtmosphereOn; // Whether to display the atmosphere QAction* _renderAtmosphereOn; // Whether to display the atmosphere
QAction* _renderAvatarsOn; // Whether to render avatars QAction* _renderAvatarsOn; // Whether to render avatars
@ -204,6 +205,7 @@ private:
VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor
float _mouseVoxelScale; // the scale for adding/removing voxels float _mouseVoxelScale; // the scale for adding/removing voxels
glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit
bool _justEditedVoxel; // set when we've just added/deleted/colored a voxel
bool _paintOn; // Whether to paint voxels as you fly around bool _paintOn; // Whether to paint voxels as you fly around
unsigned char _dominantColor; // The dominant color of the voxel we're painting unsigned char _dominantColor; // The dominant color of the voxel we're painting

View file

@ -59,58 +59,66 @@ bool usingBigSphereCollisionTest = true;
float chatMessageScale = 0.0015; float chatMessageScale = 0.0015;
float chatMessageHeight = 0.45; float chatMessageHeight = 0.45;
Avatar::Avatar(bool isMine) :
Avatar::Avatar(bool isMine) { _isMine(isMine),
_orientation.setToIdentity(); _TEST_bigSphereRadius(0.4f),
_TEST_bigSpherePosition(5.0f, _TEST_bigSphereRadius, 5.0f),
_mousePressed(false),
_bodyPitchDelta(0.0f),
_bodyYawDelta(0.0f),
_bodyRollDelta(0.0f),
_movedHandOffset(0.0f, 0.0f, 0.0f),
_rotation(0.0f, 0.0f, 0.0f, 0.0f),
_mode(AVATAR_MODE_STANDING),
_handHoldingPosition(0.0f, 0.0f, 0.0f),
_velocity(0.0f, 0.0f, 0.0f),
_thrust(0.0f, 0.0f, 0.0f),
_speed(0.0f),
_maxArmLength(0.0f),
_orientation(),
_transmitterIsFirstData(true),
_transmitterHz(0.0f),
_transmitterPackets(0),
_transmitterInitialReading(0.0f, 0.0f, 0.0f),
_isTransmitterV2Connected(false),
_pelvisStandingHeight(0.0f),
_displayingHead(true),
_distanceToNearestAvatar(std::numeric_limits<float>::max()),
_gravity(0.0f, -1.0f, 0.0f),
_mouseRayOrigin(0.0f, 0.0f, 0.0f),
_mouseRayDirection(0.0f, 0.0f, 0.0f),
_cameraPosition(0.0f, 0.0f, 0.0f),
_interactingOther(NULL),
_cumulativeMouseYaw(0.0f),
_isMouseTurningRight(false)
{
_velocity = glm::vec3(0.0f, 0.0f, 0.0f); // give the pointer to our head to inherited _headData variable from AvatarData
_thrust = glm::vec3(0.0f, 0.0f, 0.0f); _headData = &_head;
_rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f);
_bodyYaw = -90.0;
_bodyPitch = 0.0;
_bodyRoll = 0.0;
_bodyPitchDelta = 0.0;
_bodyYawDelta = 0.0;
_bodyRollDelta = 0.0;
_mousePressed = false;
_mode = AVATAR_MODE_STANDING;
_isMine = isMine;
_maxArmLength = 0.0;
_transmitterHz = 0.0;
_transmitterPackets = 0;
_transmitterIsFirstData = true;
_transmitterInitialReading = glm::vec3(0.f, 0.f, 0.f);
_isTransmitterV2Connected = false;
_speed = 0.0;
_pelvisStandingHeight = 0.0f;
_displayingHead = true;
_TEST_bigSphereRadius = 0.4f;
_TEST_bigSpherePosition = glm::vec3(5.0f, _TEST_bigSphereRadius, 5.0f);
_mouseRayOrigin = glm::vec3(0.0f, 0.0f, 0.0f);
_mouseRayDirection = glm::vec3(0.0f, 0.0f, 0.0f);
_cameraPosition = glm::vec3(0.0f, 0.0f, 0.0f);
_interactingOther = NULL;
for (int i = 0; i < MAX_DRIVE_KEYS; i++) _driveKeys[i] = false;
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
_movedHandOffset = glm::vec3(0.0f, 0.0f, 0.0f); _driveKeys[i] = false;
_handHoldingPosition = glm::vec3(0.0f, 0.0f, 0.0f); }
_distanceToNearestAvatar = std::numeric_limits<float>::max();
_gravity = glm::vec3(0.0f, -1.0f, 0.0f);
_cumulativeMouseYaw = 0.f;
_isMouseTurningRight = false;
initializeSkeleton(); initializeSkeleton();
_avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS); _avatarTouch.setReachableRadius(PERIPERSONAL_RADIUS);
if (BALLS_ON) { _balls = new Balls(100); } if (BALLS_ON) {
else { _balls = NULL; } _balls = new Balls(100);
} else {
_balls = NULL;
}
}
Avatar::~Avatar() {
_headData = NULL;
delete _balls;
} }
void Avatar::reset() { void Avatar::reset() {
_headPitch = _headYaw = _headRoll = 0; _head.reset();
_head.leanForward = _head.leanSideways = 0;
} }
// Update avatar head rotation with sensor data // Update avatar head rotation with sensor data
@ -124,23 +132,16 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa
measuredRollRate = serialInterface->getLastRollRate(); measuredRollRate = serialInterface->getLastRollRate();
// Update avatar head position based on measured gyro rates // Update avatar head position based on measured gyro rates
const float MAX_YAW = 85;
const float MIN_YAW = -85;
const float MAX_ROLL = 50;
const float MIN_ROLL = -50;
addHeadPitch(measuredPitchRate * deltaTime); _head.addPitch(measuredPitchRate * deltaTime);
addHeadYaw(measuredYawRate * deltaTime); _head.addYaw(measuredYawRate * deltaTime);
addHeadRoll(measuredRollRate * deltaTime); _head.addRoll(measuredRollRate * deltaTime);
setHeadYaw(glm::clamp(getHeadYaw(), MIN_YAW, MAX_YAW));
setHeadRoll(glm::clamp(getHeadRoll(), MIN_ROLL, MAX_ROLL));
// Update head lean distance based on accelerometer data // Update head lean distance based on accelerometer data
const float LEAN_SENSITIVITY = 0.15; const float LEAN_SENSITIVITY = 0.15;
const float LEAN_MAX = 0.45; const float LEAN_MAX = 0.45;
const float LEAN_AVERAGING = 10.0; const float LEAN_AVERAGING = 10.0;
glm::vec3 headRotationRates(getHeadPitch(), getHeadYaw(), getHeadRoll()); glm::vec3 headRotationRates(_head.getPitch(), _head.getYaw(), _head.getRoll());
float headRateMax = 50.f; float headRateMax = 50.f;
@ -149,35 +150,19 @@ void Avatar::updateHeadFromGyros(float deltaTime, SerialInterface* serialInterfa
* (1.f - fminf(glm::length(headRotationRates), headRateMax) / headRateMax); * (1.f - fminf(glm::length(headRotationRates), headRateMax) / headRateMax);
leaning.y = 0.f; leaning.y = 0.f;
if (glm::length(leaning) < LEAN_MAX) { if (glm::length(leaning) < LEAN_MAX) {
_head.leanForward = _head.leanForward * (1.f - LEAN_AVERAGING * deltaTime) + _head.setLeanForward(_head.getLeanForward() * (1.f - LEAN_AVERAGING * deltaTime) +
(LEAN_AVERAGING * deltaTime) * leaning.z * LEAN_SENSITIVITY; (LEAN_AVERAGING * deltaTime) * leaning.z * LEAN_SENSITIVITY);
_head.leanSideways = _head.leanSideways * (1.f - LEAN_AVERAGING * deltaTime) + _head.setLeanSideways(_head.getLeanSideways() * (1.f - LEAN_AVERAGING * deltaTime) +
(LEAN_AVERAGING * deltaTime) * leaning.x * LEAN_SENSITIVITY; (LEAN_AVERAGING * deltaTime) * leaning.x * LEAN_SENSITIVITY);
} }
setHeadLeanSideways(_head.leanSideways);
setHeadLeanForward(_head.leanForward);
} }
float Avatar::getAbsoluteHeadYaw() const { float Avatar::getAbsoluteHeadYaw() const {
return _bodyYaw + _headYaw; return _bodyYaw + _head.getYaw();
} }
float Avatar::getAbsoluteHeadPitch() const { float Avatar::getAbsoluteHeadPitch() const {
return _bodyPitch + _headPitch; return _bodyPitch + _head.getPitch();
}
void Avatar::addLean(float x, float z) {
//Add lean as impulse
_head.leanSideways += x;
_head.leanForward += z;
}
void Avatar::setLeanForward(float dist){
_head.leanForward = dist;
}
void Avatar::setLeanSideways(float dist){
_head.leanSideways = dist;
} }
void Avatar::setMousePressed(bool mousePressed) { void Avatar::setMousePressed(bool mousePressed) {
@ -221,7 +206,7 @@ void Avatar::updateFromMouse(int mouseX, int mouseY, int screenWidth, int scree
if (fabs(mouseLocationY) > MOUSE_MOVE_RADIUS) { if (fabs(mouseLocationY) > MOUSE_MOVE_RADIUS) {
float mousePitchAdd = (fabs(mouseLocationY) - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED; float mousePitchAdd = (fabs(mouseLocationY) - MOUSE_MOVE_RADIUS) / (0.5f - MOUSE_MOVE_RADIUS) * MOUSE_PITCH_SPEED;
bool downPitching = (mouseLocationY > 0.f); bool downPitching = (mouseLocationY > 0.f);
setHeadPitch(getHeadPitch() + (downPitching ? mousePitchAdd : -mousePitchAdd)); _head.setPitch(_head.getPitch() + (downPitching ? mousePitchAdd : -mousePitchAdd));
} }
} }
@ -355,20 +340,15 @@ void Avatar::simulate(float deltaTime) {
// Decay HeadPitch as a function of acceleration, so that you look straight ahead when // Decay HeadPitch as a function of acceleration, so that you look straight ahead when
// you start moving, but don't do this with an HMD like the Oculus. // you start moving, but don't do this with an HMD like the Oculus.
if (!OculusManager::isConnected()) { if (!OculusManager::isConnected()) {
setHeadPitch(getHeadPitch() * (1.f - acceleration * ACCELERATION_PITCH_DECAY * deltaTime)); _head.setPitch(_head.getPitch() * (1.f - acceleration * ACCELERATION_PITCH_DECAY * deltaTime));
} }
// Get head position data from network for other people
if (!_isMine) {
_head.leanSideways = getHeadLeanSideways();
_head.leanForward = getHeadLeanForward();
}
//apply the head lean values to the springy position... //apply the head lean values to the springy position...
if (fabs(_head.leanSideways + _head.leanForward) > 0.0f) { if (fabs(_head.getLeanSideways() + _head.getLeanForward()) > 0.0f) {
glm::vec3 headLean = glm::vec3 headLean =
_orientation.getRight() * _head.leanSideways + _orientation.getRight() * _head.getLeanSideways() +
_orientation.getFront() * _head.leanForward; _orientation.getFront() * _head.getLeanForward();
// this is not a long-term solution, but it works ok for initial purposes of making the avatar lean // this is not a long-term solution, but it works ok for initial purposes of making the avatar lean
_joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f; _joint[ AVATAR_JOINT_TORSO ].springyPosition += headLean * 0.1f;
@ -395,7 +375,7 @@ void Avatar::simulate(float deltaTime) {
_head.setLooking(true); _head.setLooking(true);
if (_isMine) { if (_isMine) {
setLookatPosition(_interactingOther->getSpringyHeadPosition()); _head.setLookAtPosition(_interactingOther->getSpringyHeadPosition());
} }
} else { } else {
_head.setLooking(false); _head.setLooking(false);
@ -1329,27 +1309,21 @@ void Avatar::setHeadFromGyros(glm::vec3* eulerAngles, glm::vec3* angularVelocity
// absolute eulerAngles passed. // absolute eulerAngles passed.
// //
// //
float const MAX_YAW = 90.f;
float const MIN_YAW = -90.f;
float const MAX_PITCH = 85.f;
float const MIN_PITCH = -85.f;
float const MAX_ROLL = 90.f;
float const MIN_ROLL = -90.f;
if (deltaTime == 0.f) { if (deltaTime == 0.f) {
// On first sample, set head to absolute position // On first sample, set head to absolute position
setHeadYaw(eulerAngles->x); _head.setYaw(eulerAngles->x);
setHeadPitch(eulerAngles->y); _head.setPitch(eulerAngles->y);
setHeadRoll(eulerAngles->z); _head.setRoll(eulerAngles->z);
} else { } else {
glm::vec3 angles(getHeadYaw(), getHeadPitch(), getHeadRoll()); glm::vec3 angles(_head.getYaw(), _head.getPitch(), _head.getRoll());
// Increment by detected velocity // Increment by detected velocity
angles += (*angularVelocity) * deltaTime; angles += (*angularVelocity) * deltaTime;
// Smooth to slowly follow absolute values // Smooth to slowly follow absolute values
angles = ((1.f - deltaTime / smoothingTime) * angles) + (deltaTime / smoothingTime) * (*eulerAngles); angles = ((1.f - deltaTime / smoothingTime) * angles) + (deltaTime / smoothingTime) * (*eulerAngles);
setHeadYaw(fmin(fmax(angles.x, MIN_YAW), MAX_YAW)); _head.setYaw(angles.x);
setHeadPitch(fmin(fmax(angles.y, MIN_PITCH), MAX_PITCH)); _head.setPitch(angles.y);
setHeadRoll(fmin(fmax(angles.z, MIN_ROLL), MAX_ROLL)); _head.setRoll(angles.z);
//printLog("Y/P/R: %3.1f, %3.1f, %3.1f\n", angles.x, angles.y, angles.z); //printLog("Y/P/R: %3.1f, %3.1f, %3.1f\n", angles.x, angles.y, angles.z);
} }
} }

View file

@ -77,6 +77,7 @@ enum AvatarJointID
class Avatar : public AvatarData { class Avatar : public AvatarData {
public: public:
Avatar(bool isMine); Avatar(bool isMine);
~Avatar();
void reset(); void reset();
void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity); void updateHeadFromGyros(float frametime, SerialInterface * serialInterface, glm::vec3 * gravity);
@ -92,9 +93,6 @@ public:
float getAbsoluteHeadYaw() const; float getAbsoluteHeadYaw() const;
float getAbsoluteHeadPitch() const; float getAbsoluteHeadPitch() const;
void setLeanForward(float dist);
void setLeanSideways(float dist);
void addLean(float x, float z);
glm::vec3 getApproximateEyePosition(); glm::vec3 getApproximateEyePosition();
const glm::vec3& getHeadPosition() const ; // get the position of the avatar's rigid body head const glm::vec3& getHeadPosition() const ; // get the position of the avatar's rigid body head
const glm::vec3& getSpringyHeadPosition() const ; // get the springy position of the avatar's head const glm::vec3& getSpringyHeadPosition() const ; // get the springy position of the avatar's head
@ -106,6 +104,7 @@ public:
float getHeight() const { return _height; } float getHeight() const { return _height; }
AvatarMode getMode() const { return _mode; } AvatarMode getMode() const { return _mode; }
Head getHead() const { return _head; }
void setMousePressed(bool pressed); void setMousePressed(bool pressed);
void render(bool lookingInMirror, glm::vec3 cameraPosition); void render(bool lookingInMirror, glm::vec3 cameraPosition);
@ -163,8 +162,8 @@ private:
Head _head; Head _head;
bool _isMine; bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius; float _TEST_bigSphereRadius;
glm::vec3 _TEST_bigSpherePosition;
bool _mousePressed; bool _mousePressed;
float _bodyPitchDelta; float _bodyPitchDelta;
float _bodyYawDelta; float _bodyYawDelta;
@ -180,8 +179,6 @@ private:
float _maxArmLength; float _maxArmLength;
Orientation _orientation; Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS]; int _driveKeys[MAX_DRIVE_KEYS];
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
bool _transmitterIsFirstData; bool _transmitterIsFirstData;
timeval _transmitterTimeLastReceived; timeval _transmitterTimeLastReceived;
timeval _transmitterTimer; timeval _transmitterTimer;

View file

@ -21,7 +21,6 @@ void Environment::init() {
} }
void Environment::renderAtmosphere(Camera& camera) { void Environment::renderAtmosphere(Camera& camera) {
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z); glTranslatef(getAtmosphereCenter().x, getAtmosphereCenter().y, getAtmosphereCenter().z);
@ -72,10 +71,7 @@ void Environment::renderAtmosphere(Camera& camera) {
program->release(); program->release();
glPopMatrix(); glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
} }
ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { ProgramObject* Environment::createSkyProgram(const char* from, int* locations) {

View file

@ -39,8 +39,6 @@ vector<unsigned char> irisTexture;
Head::Head() : Head::Head() :
yawRate(0.0f), yawRate(0.0f),
noise(0.0f), noise(0.0f),
leanForward(0.0f),
leanSideways(0.0f),
_audioLoudness(0.0f), _audioLoudness(0.0f),
_skinColor(0.0f, 0.0f, 0.0f), _skinColor(0.0f, 0.0f, 0.0f),
_position(0.0f, 0.0f, 0.0f), _position(0.0f, 0.0f, 0.0f),
@ -92,6 +90,11 @@ void Head::setNewTarget(float pitch, float yaw) {
} }
*/ */
void Head::reset() {
_yaw = _pitch = _roll = 0.0f;
_leanForward = _leanSideways = 0.0f;
}
void Head::simulate(float deltaTime, bool isMine) { void Head::simulate(float deltaTime, bool isMine) {
//generate orientation directions based on Euler angles... //generate orientation directions based on Euler angles...
@ -131,8 +134,8 @@ void Head::simulate(float deltaTime, bool isMine) {
} }
*/ */
leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime); _leanForward *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
leanSideways *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime); _leanSideways *= (1.f - HEAD_MOTION_DECAY * 30 * deltaTime);
// Update where the avatar's eyes are // Update where the avatar's eyes are
// //
@ -241,7 +244,7 @@ void Head::setLooking(bool looking) {
_lookingAtSomething = looking; _lookingAtSomething = looking;
glm::vec3 averageEyePosition = _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; glm::vec3 averageEyePosition = _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF;
glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - averageEyePosition); glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - averageEyePosition);
float dot = glm::dot(targetLookatAxis, _orientation.getFront()); float dot = glm::dot(targetLookatAxis, _orientation.getFront());
if (dot < MINIMUM_EYE_ROTATION) { if (dot < MINIMUM_EYE_ROTATION) {
@ -424,7 +427,7 @@ void Head::renderEyeBalls() {
if (_lookingAtSomething) { if (_lookingAtSomething) {
//rotate the eyeball to aim towards the lookat position //rotate the eyeball to aim towards the lookat position
glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - _leftEyePosition); // the lookat direction glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP);
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
@ -468,7 +471,7 @@ void Head::renderEyeBalls() {
if (_lookingAtSomething) { if (_lookingAtSomething) {
//rotate the eyeball to aim towards the lookat position //rotate the eyeball to aim towards the lookat position
glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - _rightEyePosition); glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition);
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP); glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP);
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP); float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z); glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);

View file

@ -23,10 +23,11 @@ enum eyeContactTargets
MOUTH MOUTH
}; };
class Head { class Head : public HeadData {
public: public:
Head(); Head();
void reset();
void simulate(float deltaTime, bool isMine); void simulate(float deltaTime, bool isMine);
void render(bool lookingInMirror); void render(bool lookingInMirror);
@ -52,8 +53,6 @@ public:
//some public members (left-over from pulling Head out of Avatar - I may see about privatizing these later). //some public members (left-over from pulling Head out of Avatar - I may see about privatizing these later).
float yawRate; float yawRate;
float noise; float noise;
float leanForward;
float leanSideways;
private: private:
@ -62,7 +61,6 @@ private:
glm::vec3 _skinColor; glm::vec3 _skinColor;
glm::vec3 _position; glm::vec3 _position;
glm::vec3 _rotation; glm::vec3 _rotation;
glm::vec3 _lookatPosition;
glm::vec3 _leftEyePosition; glm::vec3 _leftEyePosition;
glm::vec3 _rightEyePosition; glm::vec3 _rightEyePosition;
//float _yaw; //float _yaw;

View file

@ -46,7 +46,8 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- .
VoxelSystem::VoxelSystem() { VoxelSystem::VoxelSystem() {
_voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
_renderFullVBO = true; _writeRenderFullVBO = true;
_readRenderFullVBO = true;
_tree = new VoxelTree(); _tree = new VoxelTree();
pthread_mutex_init(&_bufferWriteLock, NULL); pthread_mutex_init(&_bufferWriteLock, NULL);
pthread_mutex_init(&_treeLock, NULL); pthread_mutex_init(&_treeLock, NULL);
@ -57,7 +58,8 @@ VoxelSystem::~VoxelSystem() {
delete[] _writeVerticesArray; delete[] _writeVerticesArray;
delete[] _readColorsArray; delete[] _readColorsArray;
delete[] _writeColorsArray; delete[] _writeColorsArray;
delete[] _voxelDirtyArray; delete[] _writeVoxelDirtyArray;
delete[] _readVoxelDirtyArray;
delete _tree; delete _tree;
pthread_mutex_destroy(&_bufferWriteLock); pthread_mutex_destroy(&_bufferWriteLock);
pthread_mutex_destroy(&_treeLock); pthread_mutex_destroy(&_treeLock);
@ -180,14 +182,15 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
_lastViewCullingElapsed = (endViewCulling - start) / 1000.0; _lastViewCullingElapsed = (endViewCulling - start) / 1000.0;
} }
bool didWriteFullVBO = _writeRenderFullVBO;
if (_tree->isDirty()) { if (_tree->isDirty()) {
static char buffer[64] = { 0 }; static char buffer[64] = { 0 };
if (_renderWarningsOn) { if (_renderWarningsOn) {
sprintf(buffer, "newTreeToArrays() _renderFullVBO=%s", (_renderFullVBO ? "yes" : "no")); sprintf(buffer, "newTreeToArrays() _writeRenderFullVBO=%s", (_writeRenderFullVBO ? "yes" : "no"));
}; };
PerformanceWarning warn(_renderWarningsOn, buffer); PerformanceWarning warn(_renderWarningsOn, buffer);
_callsToTreesToArrays++; _callsToTreesToArrays++;
if (_renderFullVBO) { if (_writeRenderFullVBO) {
_voxelsInWriteArrays = 0; // reset our VBO _voxelsInWriteArrays = 0; // reset our VBO
} }
_voxelsUpdated = newTreeToArrays(_tree->rootNode); _voxelsUpdated = newTreeToArrays(_tree->rootNode);
@ -195,16 +198,22 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
// since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are // since we called treeToArrays, we can assume that our VBO is in sync, and so partial updates to the VBOs are
// ok again, until/unless we call removeOutOfView() // ok again, until/unless we call removeOutOfView()
_renderFullVBO = false; _writeRenderFullVBO = false;
} else { } else {
_voxelsUpdated = 0; _voxelsUpdated = 0;
} }
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
pthread_mutex_lock(&_bufferWriteLock);
if (_voxelsUpdated) { if (_voxelsUpdated) {
_voxelsDirty=true; _voxelsDirty=true;
} }
// copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated
copyWrittenDataToReadArrays(); copyWrittenDataToReadArrays(didWriteFullVBO);
pthread_mutex_unlock(&_bufferWriteLock);
double end = usecTimestampNow(); double end = usecTimestampNow();
double elapsedmsec = (end - start) / 1000.0; double elapsedmsec = (end - start) / 1000.0;
@ -218,30 +227,32 @@ void VoxelSystem::cleanupRemovedVoxels() {
while (!_removedVoxels.isEmpty()) { while (!_removedVoxels.isEmpty()) {
delete _removedVoxels.extract(); delete _removedVoxels.extract();
} }
_renderFullVBO = true; // if we remove voxels, we must update our full VBOs _writeRenderFullVBO = true; // if we remove voxels, we must update our full VBOs
} }
} }
void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() { void VoxelSystem::copyWrittenDataToReadArraysFullVBOs() {
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
pthread_mutex_lock(&_bufferWriteLock);
int bytesOfVertices = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); int bytesOfVertices = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
int bytesOfColors = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte); int bytesOfColors = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte);
memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices); memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices);
memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
_voxelsInReadArrays = _voxelsInWriteArrays; _voxelsInReadArrays = _voxelsInWriteArrays;
pthread_mutex_unlock(&_bufferWriteLock);
// clear our dirty flags
memset(_writeVoxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool));
// let the reader know to get the full array
_readRenderFullVBO = true;
} }
void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() { void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() {
// lock on the buffer write lock so we can't modify the data when the GPU is reading it
pthread_mutex_lock(&_bufferWriteLock);
glBufferIndex segmentStart = 0; glBufferIndex segmentStart = 0;
glBufferIndex segmentEnd = 0; glBufferIndex segmentEnd = 0;
bool inSegment = false; bool inSegment = false;
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
bool thisVoxelDirty = _voxelDirtyArray[i]; bool thisVoxelDirty = _writeVoxelDirtyArray[i];
_readVoxelDirtyArray[i] |= thisVoxelDirty;
_writeVoxelDirtyArray[i] = false;
if (!inSegment) { if (!inSegment) {
if (thisVoxelDirty) { if (thisVoxelDirty) {
segmentStart = i; segmentStart = i;
@ -290,14 +301,12 @@ void VoxelSystem::copyWrittenDataToReadArraysPartialVBOs() {
// update our length // update our length
_voxelsInReadArrays = _voxelsInWriteArrays; _voxelsInReadArrays = _voxelsInWriteArrays;
pthread_mutex_unlock(&_bufferWriteLock);
} }
void VoxelSystem::copyWrittenDataToReadArrays() { void VoxelSystem::copyWrittenDataToReadArrays(bool fullVBOs) {
PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()");
if (_voxelsDirty && _voxelsUpdated) { if (_voxelsDirty && _voxelsUpdated) {
if (_renderFullVBO) { if (fullVBOs) {
copyWrittenDataToReadArraysFullVBOs(); copyWrittenDataToReadArraysFullVBOs();
} else { } else {
copyWrittenDataToReadArraysPartialVBOs(); copyWrittenDataToReadArraysPartialVBOs();
@ -327,7 +336,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
} }
} }
} }
if (_renderFullVBO) { if (_writeRenderFullVBO) {
voxelsUpdated += updateNodeInArraysAsFullVBO(node); voxelsUpdated += updateNodeInArraysAsFullVBO(node);
} else { } else {
voxelsUpdated += updateNodeInArraysAsPartialVBO(node); voxelsUpdated += updateNodeInArraysAsPartialVBO(node);
@ -365,7 +374,7 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) {
*(writeColorsAt +j) = node->getColor()[j % 3]; *(writeColorsAt +j) = node->getColor()[j % 3];
} }
node->setBufferIndex(nodeIndex); node->setBufferIndex(nodeIndex);
_voxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode _writeVoxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode
_voxelsInWriteArrays++; // our know vertices in the arrays _voxelsInWriteArrays++; // our know vertices in the arrays
return 1; // rendered return 1; // rendered
} }
@ -402,7 +411,7 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) {
node->setBufferIndex(nodeIndex); node->setBufferIndex(nodeIndex);
_voxelsInWriteArrays++; _voxelsInWriteArrays++;
} }
_voxelDirtyArray[nodeIndex] = true; _writeVoxelDirtyArray[nodeIndex] = true;
// populate the array with points for the 8 vertices // populate the array with points for the 8 vertices
// and RGB color for each added vertex // and RGB color for each added vertex
@ -431,9 +440,11 @@ void VoxelSystem::init() {
_voxelsInReadArrays = 0; _voxelsInReadArrays = 0;
_unusedArraySpace = 0; _unusedArraySpace = 0;
// we will track individual dirty sections with this array of bools // we will track individual dirty sections with these arrays of bools
_voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM]; _writeVoxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
memset(_voxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); memset(_writeVoxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
_readVoxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM];
memset(_readVoxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));
// prep the data structures for incoming voxel data // prep the data structures for incoming voxel data
_writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM];
@ -530,7 +541,7 @@ void VoxelSystem::init() {
void VoxelSystem::updateFullVBOs() { void VoxelSystem::updateFullVBOs() {
glBufferIndex segmentStart = 0; glBufferIndex segmentStart = 0;
glBufferIndex segmentEnd = _voxelsInWriteArrays; glBufferIndex segmentEnd = _voxelsInReadArrays;
int segmentLength = (segmentEnd - segmentStart) + 1; int segmentLength = (segmentEnd - segmentStart) + 1;
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
@ -544,21 +555,21 @@ void VoxelSystem::updateFullVBOs() {
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
// consider the _voxelDirtyArray[] clean! // consider the _readVoxelDirtyArray[] clean!
memset(_voxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool)); memset(_readVoxelDirtyArray, false, _voxelsInReadArrays * sizeof(bool));
} }
void VoxelSystem::updatePartialVBOs() { void VoxelSystem::updatePartialVBOs() {
glBufferIndex segmentStart = 0; glBufferIndex segmentStart = 0;
glBufferIndex segmentEnd = 0; glBufferIndex segmentEnd = 0;
bool inSegment = false; bool inSegment = false;
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { for (glBufferIndex i = 0; i < _voxelsInReadArrays; i++) {
bool thisVoxelDirty = _voxelDirtyArray[i]; bool thisVoxelDirty = _readVoxelDirtyArray[i];
if (!inSegment) { if (!inSegment) {
if (thisVoxelDirty) { if (thisVoxelDirty) {
segmentStart = i; segmentStart = i;
inSegment = true; inSegment = true;
_voxelDirtyArray[i] = false; // consider us clean! _readVoxelDirtyArray[i] = false; // consider us clean!
} }
} else { } else {
if (!thisVoxelDirty) { if (!thisVoxelDirty) {
@ -578,13 +589,13 @@ void VoxelSystem::updatePartialVBOs() {
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
} }
_voxelDirtyArray[i] = false; // consider us clean! _readVoxelDirtyArray[i] = false; // consider us clean!
} }
} }
// if we got to the end of the array, and we're in an active dirty segment... // if we got to the end of the array, and we're in an active dirty segment...
if (inSegment) { if (inSegment) {
segmentEnd = _voxelsInWriteArrays - 1; segmentEnd = _voxelsInReadArrays - 1;
inSegment = false; inSegment = false;
int segmentLength = (segmentEnd - segmentStart) + 1; int segmentLength = (segmentEnd - segmentStart) + 1;
GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
@ -603,22 +614,27 @@ void VoxelSystem::updatePartialVBOs() {
void VoxelSystem::updateVBOs() { void VoxelSystem::updateVBOs() {
static char buffer[40] = { 0 }; static char buffer[40] = { 0 };
if (_renderWarningsOn) { if (_renderWarningsOn) {
sprintf(buffer, "updateVBOs() _renderFullVBO=%s", (_renderFullVBO ? "yes" : "no")); sprintf(buffer, "updateVBOs() _readRenderFullVBO=%s", (_readRenderFullVBO ? "yes" : "no"));
}; };
PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays
if (_voxelsDirty) { if (_voxelsDirty) {
if (_renderFullVBO) { if (_readRenderFullVBO) {
updateFullVBOs(); updateFullVBOs();
} else { } else {
updatePartialVBOs(); updatePartialVBOs();
} }
_voxelsDirty = false; _voxelsDirty = false;
_readRenderFullVBO = false;
} }
_callsToTreesToArrays = 0; // clear it _callsToTreesToArrays = 0; // clear it
} }
void VoxelSystem::render() { void VoxelSystem::render(bool texture) {
PerformanceWarning warn(_renderWarningsOn, "render()"); PerformanceWarning warn(_renderWarningsOn, "render()");
// get the lock so that the update thread won't change anything
pthread_mutex_lock(&_bufferWriteLock);
glPushMatrix(); glPushMatrix();
updateVBOs(); updateVBOs();
// tell OpenGL where to find vertex and color information // tell OpenGL where to find vertex and color information
@ -635,9 +651,11 @@ void VoxelSystem::render() {
glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
_perlinModulateProgram->bind(); if (texture) {
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID); _perlinModulateProgram->bind();
glBindTexture(GL_TEXTURE_2D, _permutationNormalTextureID);
}
// for performance, disable blending and enable backface culling // for performance, disable blending and enable backface culling
glDisable(GL_BLEND); glDisable(GL_BLEND);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@ -650,9 +668,11 @@ void VoxelSystem::render() {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
_perlinModulateProgram->release(); if (texture) {
glBindTexture(GL_TEXTURE_2D, 0); _perlinModulateProgram->release();
glBindTexture(GL_TEXTURE_2D, 0);
}
// deactivate vertex and color arrays after drawing // deactivate vertex and color arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_NORMAL_ARRAY);
@ -664,6 +684,8 @@ void VoxelSystem::render() {
// scale back down to 1 so heads aren't massive // scale back down to 1 so heads aren't massive
glPopMatrix(); glPopMatrix();
pthread_mutex_unlock(&_bufferWriteLock);
} }
int VoxelSystem::_nodeCount = 0; int VoxelSystem::_nodeCount = 0;
@ -1012,7 +1034,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
glBufferIndex maxDirty = 0; glBufferIndex maxDirty = 0;
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
if (_voxelDirtyArray[i]) { if (_writeVoxelDirtyArray[i]) {
minDirty = std::min(minDirty,i); minDirty = std::min(minDirty,i);
maxDirty = std::max(maxDirty,i); maxDirty = std::max(maxDirty,i);
} }

View file

@ -36,7 +36,7 @@ public:
void init(); void init();
void simulate(float deltaTime) { }; void simulate(float deltaTime) { };
void render(); void render(bool texture);
unsigned long getVoxelsUpdated() const {return _voxelsUpdated;}; unsigned long getVoxelsUpdated() const {return _voxelsUpdated;};
unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;}; unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;};
@ -118,13 +118,15 @@ private:
GLubyte* _readColorsArray; GLubyte* _readColorsArray;
GLfloat* _writeVerticesArray; GLfloat* _writeVerticesArray;
GLubyte* _writeColorsArray; GLubyte* _writeColorsArray;
bool* _voxelDirtyArray; bool* _writeVoxelDirtyArray;
bool* _readVoxelDirtyArray;
unsigned long _voxelsUpdated; unsigned long _voxelsUpdated;
unsigned long _voxelsInWriteArrays; unsigned long _voxelsInWriteArrays;
unsigned long _voxelsInReadArrays; unsigned long _voxelsInReadArrays;
unsigned long _unusedArraySpace; unsigned long _unusedArraySpace;
bool _renderFullVBO; bool _writeRenderFullVBO;
bool _readRenderFullVBO;
double _setupNewVoxelsForDrawingLastElapsed; double _setupNewVoxelsForDrawingLastElapsed;
double _setupNewVoxelsForDrawingLastFinished; double _setupNewVoxelsForDrawingLastFinished;
@ -148,7 +150,7 @@ private:
void cleanupRemovedVoxels(); void cleanupRemovedVoxels();
void setupNewVoxelsForDrawing(); void setupNewVoxelsForDrawing();
void copyWrittenDataToReadArrays(); void copyWrittenDataToReadArrays(bool fullVBOs);
bool _voxelsDirty; bool _voxelsDirty;

View file

@ -3,7 +3,7 @@
// hifi // hifi
// //
// Created by Stephen Birarda on 4/9/13. // Created by Stephen Birarda on 4/9/13.
// // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// //
#include <cstdio> #include <cstdio>
@ -35,15 +35,9 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo
AvatarData::AvatarData() : AvatarData::AvatarData() :
_handPosition(0,0,0), _handPosition(0,0,0),
_lookatPosition(0,0,0),
_bodyYaw(-90.0), _bodyYaw(-90.0),
_bodyPitch(0.0), _bodyPitch(0.0),
_bodyRoll(0.0), _bodyRoll(0.0),
_headYaw(0),
_headPitch(0),
_headRoll(0),
_headLeanSideways(0),
_headLeanForward(0),
_audioLoudness(0), _audioLoudness(0),
_handState(0), _handState(0),
_cameraPosition(0,0,0), _cameraPosition(0,0,0),
@ -57,11 +51,16 @@ AvatarData::AvatarData() :
_keyState(NO_KEY_DOWN), _keyState(NO_KEY_DOWN),
_wantResIn(false), _wantResIn(false),
_wantColor(true), _wantColor(true),
_wantDelta(false) _wantDelta(false),
_headData(NULL)
{ {
} }
AvatarData::~AvatarData() {
delete _headData;
}
int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
unsigned char* bufferStart = destinationBuffer; unsigned char* bufferStart = destinationBuffer;
@ -79,23 +78,23 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _bodyRoll);
// Head rotation (NOTE: This needs to become a quaternion to save two bytes) // Head rotation (NOTE: This needs to become a quaternion to save two bytes)
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headYaw); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headPitch); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_pitch);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headRoll); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_roll);
// Head lean X,Z (head lateral and fwd/back motion relative to torso) // Head lean X,Z (head lateral and fwd/back motion relative to torso)
memcpy(destinationBuffer, &_headLeanSideways, sizeof(float)); memcpy(destinationBuffer, &_headData->_leanSideways, sizeof(_headData->_leanSideways));
destinationBuffer += sizeof(float); destinationBuffer += sizeof(_headData->_leanSideways);
memcpy(destinationBuffer, &_headLeanForward, sizeof(float)); memcpy(destinationBuffer, &_headData->_leanForward, sizeof(_headData->_leanForward));
destinationBuffer += sizeof(float); destinationBuffer += sizeof(_headData->_leanForward);
// Hand Position // Hand Position
memcpy(destinationBuffer, &_handPosition, sizeof(float) * 3); memcpy(destinationBuffer, &_handPosition, sizeof(float) * 3);
destinationBuffer += sizeof(float) * 3; destinationBuffer += sizeof(float) * 3;
// Lookat Position // Lookat Position
memcpy(destinationBuffer, &_lookatPosition, sizeof(_lookatPosition)); memcpy(destinationBuffer, &_headData->_lookAtPosition, sizeof(_headData->_lookAtPosition));
destinationBuffer += sizeof(_lookatPosition); destinationBuffer += sizeof(_headData->_lookAtPosition);
// Hand State (0 = not grabbing, 1 = grabbing) // Hand State (0 = not grabbing, 1 = grabbing)
memcpy(destinationBuffer, &_handState, sizeof(char)); memcpy(destinationBuffer, &_handState, sizeof(char));
@ -145,7 +144,10 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
// called on the other agents - assigns it to my views of the others // called on the other agents - assigns it to my views of the others
int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
//printf("AvatarData::parseData()\n"); // lazily allocate memory for HeadData in case we're not an Avatar instance
if (!_headData) {
_headData = new HeadData();
}
// increment to push past the packet header // increment to push past the packet header
sourceBuffer += sizeof(PACKET_HEADER_HEAD_DATA); sourceBuffer += sizeof(PACKET_HEADER_HEAD_DATA);
@ -160,28 +162,33 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
sourceBuffer += sizeof(float) * 3; sourceBuffer += sizeof(float) * 3;
// Body rotation (NOTE: This needs to become a quaternion to save two bytes) // Body rotation (NOTE: This needs to become a quaternion to save two bytes)
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_bodyYaw); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyYaw);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_bodyPitch); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyPitch);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_bodyRoll); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_bodyRoll);
// Head rotation (NOTE: This needs to become a quaternion to save two bytes) // Head rotation (NOTE: This needs to become a quaternion to save two bytes)
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_headYaw); float headYaw, headPitch, headRoll;
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_headPitch); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headYaw);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t *)sourceBuffer, &_headRoll); sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headPitch);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headRoll);
_headData->setYaw(headYaw);
_headData->setPitch(headPitch);
_headData->setRoll(headRoll);
// Head position relative to pelvis // Head position relative to pelvis
memcpy(&_headLeanSideways, sourceBuffer, sizeof(float)); memcpy(&_headData->_leanSideways, sourceBuffer, sizeof(_headData->_leanSideways));
sourceBuffer += sizeof(float);
memcpy(&_headLeanForward, sourceBuffer, sizeof(float));
sourceBuffer += sizeof(float); sourceBuffer += sizeof(float);
memcpy(&_headData->_leanForward, sourceBuffer, sizeof(_headData->_leanForward));
sourceBuffer += sizeof(_headData->_leanForward);
// Hand Position // Hand Position
memcpy(&_handPosition, sourceBuffer, sizeof(float) * 3); memcpy(&_handPosition, sourceBuffer, sizeof(float) * 3);
sourceBuffer += sizeof(float) * 3; sourceBuffer += sizeof(float) * 3;
// Lookat Position // Lookat Position
memcpy(&_lookatPosition, sourceBuffer, sizeof(_lookatPosition)); memcpy(&_headData->_lookAtPosition, sourceBuffer, sizeof(_headData->_lookAtPosition));
sourceBuffer += sizeof(_lookatPosition); sourceBuffer += sizeof(_headData->_lookAtPosition);
// Hand State // Hand State
memcpy(&_handState, sourceBuffer, sizeof(char)); memcpy(&_handState, sourceBuffer, sizeof(char));
@ -226,11 +233,4 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
_wantDelta = oneAtBit(wantItems,WANT_DELTA_AT_BIT); _wantDelta = oneAtBit(wantItems,WANT_DELTA_AT_BIT);
return sourceBuffer - startPosition; return sourceBuffer - startPosition;
}
void AvatarData::setHeadPitch(float p) {
// Set head pitch and apply limits
const float MAX_PITCH = 60;
const float MIN_PITCH = -60;
_headPitch = glm::clamp(p, MIN_PITCH, MAX_PITCH);
} }

View file

@ -3,7 +3,7 @@
// hifi // hifi
// //
// Created by Stephen Birarda on 4/9/13. // Created by Stephen Birarda on 4/9/13.
// // Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
// //
#ifndef __hifi__AvatarData__ #ifndef __hifi__AvatarData__
@ -14,6 +14,7 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <AgentData.h> #include <AgentData.h>
#include "HeadData.h"
const int WANT_RESIN_AT_BIT = 0; const int WANT_RESIN_AT_BIT = 0;
const int WANT_COLOR_AT_BIT = 1; const int WANT_COLOR_AT_BIT = 1;
@ -29,12 +30,12 @@ enum KeyState
class AvatarData : public AgentData { class AvatarData : public AgentData {
public: public:
AvatarData(); AvatarData();
~AvatarData();
const glm::vec3& getPosition() const { return _position; } const glm::vec3& getPosition() const { return _position; }
void setPosition (const glm::vec3 position ) { _position = position; } void setPosition (const glm::vec3 position ) { _position = position; }
void setHandPosition (const glm::vec3 handPosition ) { _handPosition = handPosition; } void setHandPosition (const glm::vec3 handPosition ) { _handPosition = handPosition; }
void setLookatPosition(const glm::vec3 lookatPosition) { _lookatPosition = lookatPosition; }
int getBroadcastData(unsigned char* destinationBuffer); int getBroadcastData(unsigned char* destinationBuffer);
int parseData(unsigned char* sourceBuffer, int numBytes); int parseData(unsigned char* sourceBuffer, int numBytes);
@ -46,23 +47,6 @@ public:
void setBodyPitch(float bodyPitch) { _bodyPitch = bodyPitch; } void setBodyPitch(float bodyPitch) { _bodyPitch = bodyPitch; }
float getBodyRoll() const {return _bodyRoll; } float getBodyRoll() const {return _bodyRoll; }
void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; } void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; }
// Head Rotation
void setHeadPitch(float p);
void setHeadYaw(float y) {_headYaw = y; }
void setHeadRoll(float r) {_headRoll = r; };
float getHeadPitch() const { return _headPitch; };
float getHeadYaw() const { return _headYaw; };
float getHeadRoll() const { return _headRoll; };
void addHeadPitch(float p) { setHeadPitch(_headPitch - p); }
void addHeadYaw(float y){_headYaw -= y; }
void addHeadRoll(float r){_headRoll += r; }
// Head vector deflection from pelvix in X,Z
void setHeadLeanSideways(float s) {_headLeanSideways = s; };
float getHeadLeanSideways() const { return _headLeanSideways; };
void setHeadLeanForward(float f) {_headLeanForward = f; };
float getHeadLeanForward() const { return _headLeanForward; };
// Hand State // Hand State
void setHandState(char s) { _handState = s; }; void setHandState(char s) { _handState = s; };
@ -108,6 +92,8 @@ public:
void setWantColor(bool wantColor) { _wantColor = wantColor; } void setWantColor(bool wantColor) { _wantColor = wantColor; }
void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; }
void setHeadData(HeadData* headData) { _headData = headData; }
protected: protected:
// privatize the copy constructor and assignment operator so they cannot be called // privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&); AvatarData(const AvatarData&);
@ -115,20 +101,11 @@ protected:
glm::vec3 _position; glm::vec3 _position;
glm::vec3 _handPosition; glm::vec3 _handPosition;
glm::vec3 _lookatPosition;
// Body rotation // Body rotation
float _bodyYaw; float _bodyYaw;
float _bodyPitch; float _bodyPitch;
float _bodyRoll; float _bodyRoll;
// Head rotation (relative to body)
float _headYaw;
float _headPitch;
float _headRoll;
float _headLeanSideways;
float _headLeanForward;
// Audio loudness (used to drive facial animation) // Audio loudness (used to drive facial animation)
float _audioLoudness; float _audioLoudness;
@ -158,6 +135,8 @@ protected:
bool _wantResIn; bool _wantResIn;
bool _wantColor; bool _wantColor;
bool _wantDelta; bool _wantDelta;
HeadData* _headData;
}; };
#endif /* defined(__hifi__AvatarData__) */ #endif /* defined(__hifi__AvatarData__) */

View file

@ -0,0 +1,38 @@
//
// HeadData.cpp
// hifi
//
// Created by Stephen Birarda on 5/20/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "HeadData.h"
HeadData::HeadData() :
_yaw(0.0f),
_pitch(0.0f),
_roll(0.0f),
_lookAtPosition(0.0f, 0.0f, 0.0f),
_leanSideways(0.0f),
_leanForward(0.0f)
{
}
void HeadData::addYaw(float yaw) {
setYaw(_yaw + yaw);
}
void HeadData::addPitch(float pitch) {
setPitch(_pitch + pitch);
}
void HeadData::addRoll(float roll) {
setRoll(_roll + roll);
}
void HeadData::addLean(float sideways, float forwards) {
// Add lean as impulse
_leanSideways += sideways;
_leanForward += forwards;
}

View file

@ -0,0 +1,60 @@
//
// HeadData.h
// hifi
//
// Created by Stephen Birarda on 5/20/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__HeadData__
#define __hifi__HeadData__
#include <iostream>
#include <glm/glm.hpp>
const float MIN_HEAD_YAW = -85;
const float MAX_HEAD_YAW = 85;
const float MIN_HEAD_PITCH = -60;
const float MAX_HEAD_PITCH = 60;
const float MIN_HEAD_ROLL = -50;
const float MAX_HEAD_ROLL = 50;
class HeadData {
public:
HeadData();
float getLeanSideways() const { return _leanSideways; }
void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; }
float getLeanForward() const { return _leanForward; }
void setLeanForward(float leanForward) { _leanForward = leanForward; }
float getYaw() const { return _yaw; }
void setYaw(float yaw) { _yaw = glm::clamp(yaw, MIN_HEAD_YAW, MAX_HEAD_YAW); }
float getPitch() const { return _pitch; }
void setPitch(float pitch) { _pitch = glm::clamp(pitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); }
float getRoll() const { return _roll; }
void setRoll(float roll) { _roll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); }
void addYaw(float yaw);
void addPitch(float pitch);
void addRoll(float roll);
void addLean(float sideways, float forwards);
const glm::vec3& getLookAtPosition() const { return _lookAtPosition; }
void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; }
friend class AvatarData;
protected:
float _yaw;
float _pitch;
float _roll;
glm::vec3 _lookAtPosition;
float _leanSideways;
float _leanForward;
};
#endif /* defined(__hifi__HeadData__) */