mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 15:09:34 +02:00
Merge branch 'master' of git://github.com/worklist/hifi
Conflicts: libraries/avatars/src/AvatarData.cpp
This commit is contained in:
commit
bfaeb4a4d9
16 changed files with 556 additions and 384 deletions
|
@ -135,6 +135,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),
|
||||||
|
@ -290,8 +291,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);
|
||||||
|
@ -299,7 +301,6 @@ void Application::paintGL() {
|
||||||
_myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f,
|
_myCamera.setTargetRotation(_myAvatar.getBodyYaw() - 180.0f,
|
||||||
0.0f,
|
0.0f,
|
||||||
0.0f);
|
0.0f);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
|
||||||
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
_myCamera.setTargetPosition(_myAvatar.getSpringyHeadPosition());
|
||||||
|
@ -732,8 +733,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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,13 +748,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();
|
||||||
}
|
}
|
||||||
|
@ -921,6 +922,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
|
||||||
|
@ -1196,6 +1203,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);
|
||||||
|
@ -1349,29 +1358,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
|
||||||
|
@ -1672,7 +1665,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
|
||||||
|
@ -2014,18 +2007,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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2037,7 +2034,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -187,6 +188,7 @@ private:
|
||||||
Oscilloscope _audioScope;
|
Oscilloscope _audioScope;
|
||||||
|
|
||||||
Avatar _myAvatar; // The rendered avatar of oneself
|
Avatar _myAvatar; // The rendered avatar of oneself
|
||||||
|
|
||||||
Camera _myCamera; // My view onto the world
|
Camera _myCamera; // My view onto the world
|
||||||
Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
Camera _viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
|
||||||
|
|
||||||
|
@ -203,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
|
||||||
|
|
|
@ -50,65 +50,75 @@ const float PERIPERSONAL_RADIUS = 1.0f;
|
||||||
const float AVATAR_BRAKING_STRENGTH = 40.0f;
|
const float AVATAR_BRAKING_STRENGTH = 40.0f;
|
||||||
const float JOINT_TOUCH_RANGE = 0.0005f;
|
const float JOINT_TOUCH_RANGE = 0.0005f;
|
||||||
|
|
||||||
float skinColor [] = {1.0, 0.84, 0.66};
|
float skinColor [] = {1.0, 0.84, 0.66};
|
||||||
float lightBlue [] = {0.7, 0.8, 1.0};
|
float darkSkinColor[] = {0.8, 0.74, 0.6 };
|
||||||
|
float lightBlue [] = {0.7, 0.8, 1.0 };
|
||||||
|
|
||||||
bool usingBigSphereCollisionTest = true;
|
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) :
|
||||||
_orientation.setToIdentity();
|
_isMine(isMine),
|
||||||
|
_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
|
||||||
|
@ -122,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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,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) {
|
||||||
|
@ -219,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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -352,20 +339,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;
|
||||||
|
@ -387,23 +369,21 @@ void Avatar::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// update head state
|
// update head state
|
||||||
_head.setPositionRotationAndScale(
|
_head.setPositionAndScale(_joint[AVATAR_JOINT_HEAD_BASE].springyPosition, _joint[AVATAR_JOINT_HEAD_BASE].radius);
|
||||||
_joint[ AVATAR_JOINT_HEAD_BASE ].springyPosition,
|
|
||||||
glm::vec3(_headYaw, _headPitch, _headRoll),
|
|
||||||
_joint[ AVATAR_JOINT_HEAD_BASE ].radius
|
|
||||||
);
|
|
||||||
|
|
||||||
_head.setBodyYaw(_bodyYaw);
|
_head.setLookAtPosition(glm::vec3(0.0f, 0.0f, 0.0f)); //default lookat position is 0,0,0
|
||||||
|
|
||||||
//the following is still being prototyped (making the eyes look at a specific location), it should be finished by 5/20/13
|
|
||||||
if (_interactingOther) {
|
if (_interactingOther) {
|
||||||
_head.setLooking(true);
|
_head.setLooking(true);
|
||||||
_head.setLookatPosition(_interactingOther->getSpringyHeadPosition());
|
|
||||||
//_head.setLookatPosition(_interactingOther->getApproximateEyePosition());
|
if (_isMine) {
|
||||||
|
_head.setLookAtPosition(_interactingOther->getSpringyHeadPosition());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_head.setLooking(false);
|
_head.setLooking(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_head.setBodyYaw(_bodyYaw);
|
||||||
_head.setAudioLoudness(_audioLoudness);
|
_head.setAudioLoudness(_audioLoudness);
|
||||||
_head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
_head.setSkinColor(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
||||||
_head.simulate(deltaTime, _isMine);
|
_head.simulate(deltaTime, _isMine);
|
||||||
|
@ -692,19 +672,6 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
|
|
||||||
_cameraPosition = cameraPosition; // store this for use in various parts of the code
|
_cameraPosition = cameraPosition; // store this for use in various parts of the code
|
||||||
|
|
||||||
// render a simple round on the ground projected down from the avatar's position
|
|
||||||
renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// show avatar position
|
|
||||||
glColor4f(0.5f, 0.5f, 0.5f, 0.6);
|
|
||||||
glPushMatrix();
|
|
||||||
glTranslatef(_position.x, _position.y, _position.z);
|
|
||||||
glScalef(0.03, 0.03, 0.03);
|
|
||||||
glutSolidSphere(1, 10, 10);
|
|
||||||
glPopMatrix();
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (usingBigSphereCollisionTest) {
|
if (usingBigSphereCollisionTest) {
|
||||||
// show TEST big sphere
|
// show TEST big sphere
|
||||||
glColor4f(0.5f, 0.6f, 0.8f, 0.7);
|
glColor4f(0.5f, 0.6f, 0.8f, 0.7);
|
||||||
|
@ -715,10 +682,12 @@ void Avatar::render(bool lookingInMirror, glm::vec3 cameraPosition) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// render a simple round on the ground projected down from the avatar's position
|
||||||
|
renderDiskShadow(_position, glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f);
|
||||||
|
|
||||||
//render body
|
//render body
|
||||||
renderBody(lookingInMirror);
|
renderBody(lookingInMirror);
|
||||||
|
|
||||||
|
|
||||||
// if this is my avatar, then render my interactions with the other avatar
|
// if this is my avatar, then render my interactions with the other avatar
|
||||||
if (_isMine) {
|
if (_isMine) {
|
||||||
_avatarTouch.render(_cameraPosition);
|
_avatarTouch.render(_cameraPosition);
|
||||||
|
@ -1039,10 +1008,12 @@ void Avatar::updateBodySprings(float deltaTime) {
|
||||||
_joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
_joint[b].springyVelocity = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//apply forces from touch...
|
//apply forces from touch...
|
||||||
if (_joint[b].touchForce > 0.0) {
|
if (_joint[b].touchForce > 0.0) {
|
||||||
_joint[b].springyVelocity += _mouseRayDirection * _joint[b].touchForce * 0.7f;
|
_joint[b].springyVelocity += _mouseRayDirection * _joint[b].touchForce * 0.7f;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//update position by velocity...
|
//update position by velocity...
|
||||||
_joint[b].springyPosition += _joint[b].springyVelocity * deltaTime;
|
_joint[b].springyPosition += _joint[b].springyVelocity * deltaTime;
|
||||||
|
@ -1133,14 +1104,27 @@ void Avatar::renderBody(bool lookingInMirror) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render lines connecting the joint positions
|
|
||||||
glColor3f(0.4f, 0.5f, 0.6f);
|
|
||||||
glLineWidth(3.0);
|
|
||||||
|
|
||||||
for (int b = 1; b < NUM_AVATAR_JOINTS; b++) {
|
for (int b = 1; b < NUM_AVATAR_JOINTS; b++) {
|
||||||
if (_joint[b].parent != AVATAR_JOINT_NULL)
|
if (_joint[b].parent != AVATAR_JOINT_NULL)
|
||||||
if (b != AVATAR_JOINT_HEAD_TOP) {
|
if (b != AVATAR_JOINT_HEAD_TOP) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Render cone sections connecting the joint positions
|
||||||
|
glColor3fv(darkSkinColor);
|
||||||
|
renderJointConnectingCone
|
||||||
|
(
|
||||||
|
_joint[_joint[b].parent ].springyPosition,
|
||||||
|
_joint[b ].springyPosition,
|
||||||
|
_joint[_joint[b].parent ].radius,
|
||||||
|
_joint[b ].radius
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Render lines connecting the joint positions
|
||||||
|
glColor3f(0.4f, 0.5f, 0.6f);
|
||||||
|
glLineWidth(3.0);
|
||||||
glBegin(GL_LINE_STRIP);
|
glBegin(GL_LINE_STRIP);
|
||||||
glVertex3fv(&_joint[ _joint[ b ].parent ].springyPosition.x);
|
glVertex3fv(&_joint[ _joint[ b ].parent ].springyPosition.x);
|
||||||
glVertex3fv(&_joint[ b ].springyPosition.x);
|
glVertex3fv(&_joint[ b ].springyPosition.x);
|
||||||
|
@ -1325,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1378,3 +1356,47 @@ void Avatar::readAvatarDataFromFile() {
|
||||||
fclose(avatarFile);
|
fclose(avatarFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2) {
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
|
||||||
|
int num = 5;
|
||||||
|
|
||||||
|
glm::vec3 axis = glm::normalize(position2 - position1);
|
||||||
|
float length = glm::length(axis);
|
||||||
|
|
||||||
|
if (length > 0.0f) {
|
||||||
|
|
||||||
|
glm::vec3 perpSin = glm::vec3(axis.y, axis.z, axis.x);
|
||||||
|
glm::vec3 perpCos = glm::vec3(axis.z, axis.x, axis.y);
|
||||||
|
|
||||||
|
for (int i = 0; i < num; i ++) {
|
||||||
|
|
||||||
|
float angle1 = ((float)i / (float)num) * PI * 2.0;
|
||||||
|
float angle2 = ((float)(i+1) / (float)num) * PI * 2.0;
|
||||||
|
|
||||||
|
glm::vec3 p1a = position1 + perpSin * sin(angle1) * radius1;
|
||||||
|
glm::vec3 p1b = position1 + perpCos * cos(angle2) * radius1;
|
||||||
|
|
||||||
|
glm::vec3 p2a = position2 + perpSin * sin(angle1) * radius2;
|
||||||
|
glm::vec3 p2b = position2 + perpCos * cos(angle2) * radius2;
|
||||||
|
|
||||||
|
glVertex3f(p1a.x, p1a.y, p1a.z);
|
||||||
|
glVertex3f(p1b.x, p1b.y, p1b.z);
|
||||||
|
glVertex3f(p2a.x, p2a.y, p2a.z);
|
||||||
|
|
||||||
|
/*
|
||||||
|
glVertex3f(p1b.x, p1b.y, p1b.z);
|
||||||
|
glVertex3f(p2a.x, p2a.y, p2a.z);
|
||||||
|
glVertex3f(p2b.x, p2b.y, p2b.z);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <Orientation.h>
|
#include <Orientation.h>
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "AvatarTouch.h"
|
#include "AvatarTouch.h"
|
||||||
|
#include "AvatarRenderer.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "SerialInterface.h"
|
#include "SerialInterface.h"
|
||||||
#include "Balls.h"
|
#include "Balls.h"
|
||||||
|
@ -76,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);
|
||||||
|
@ -91,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
|
||||||
|
@ -105,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);
|
||||||
|
@ -162,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;
|
||||||
|
@ -179,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;
|
||||||
|
@ -217,6 +215,7 @@ private:
|
||||||
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
void applyCollisionWithOtherAvatar( Avatar * other, float deltaTime );
|
||||||
void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime);
|
void setHeadFromGyros(glm::vec3 * eulerAngles, glm::vec3 * angularVelocity, float deltaTime, float smoothingTime);
|
||||||
void checkForMouseRayTouching();
|
void checkForMouseRayTouching();
|
||||||
|
void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,54 +10,61 @@
|
||||||
#include "AvatarRenderer.h"
|
#include "AvatarRenderer.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
|
/*
|
||||||
AvatarRenderer::AvatarRenderer() {
|
AvatarRenderer::AvatarRenderer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method renders the avatar
|
// this method renders the avatar
|
||||||
void AvatarRenderer::render(Avatar *avatarToRender, bool lookingInMirror, glm::vec3 cameraPosition) {
|
void AvatarRenderer::render() {
|
||||||
|
|
||||||
avatar = avatarToRender;
|
|
||||||
|
|
||||||
/*
|
|
||||||
// show avatar position
|
// show avatar position
|
||||||
glColor4f(0.5f, 0.5f, 0.5f, 0.6);
|
glColor4f(0.5f, 0.5f, 0.5f, 0.6);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glm::vec3 j( avatar->getJointPosition( AVATAR_JOINT_PELVIS ) );
|
glm::vec3 j( getJointPosition( AVATAR_JOINT_PELVIS ) );
|
||||||
glTranslatef(j.x, j.y, j.z);
|
glTranslatef(j.x, j.y, j.z);
|
||||||
glScalef(0.08, 0.08, 0.08);
|
glScalef(0.08, 0.08, 0.08);
|
||||||
glutSolidSphere(1, 10, 10);
|
glutSolidSphere(1, 10, 10);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
*/
|
|
||||||
|
|
||||||
//renderDiskShadow(avatar->getJointPosition( AVATAR_JOINT_PELVIS ), glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f);
|
renderDiskShadow(getJointPosition( AVATAR_JOINT_PELVIS ), glm::vec3(0.0f, 1.0f, 0.0f), 0.1f, 0.2f);
|
||||||
|
|
||||||
//renderBody();
|
//renderBody(lookingInMirror);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AvatarRenderer::renderBody() {
|
void AvatarRenderer::renderBody() {
|
||||||
/*
|
|
||||||
// Render joint positions as spheres
|
// Render joint positions as spheres
|
||||||
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
|
||||||
|
|
||||||
if (b != AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case in "renderHead"
|
if (b == AVATAR_JOINT_HEAD_BASE) { // the head is rendered as a special case
|
||||||
|
if (_displayingHead) {
|
||||||
|
_head.render(lookingInMirror);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
//show direction vectors of the bone orientation
|
//show direction vectors of the bone orientation
|
||||||
//renderOrientationDirections(_joint[b].springyPosition, _joint[b].orientation, _joint[b].radius * 2.0);
|
//renderOrientationDirections(_joint[b].springyPosition, _joint[b].orientation, _joint[b].radius * 2.0);
|
||||||
|
|
||||||
glm::vec3 j( avatar->getJointPosition( AVATAR_JOINT_PELVIS ) );
|
glColor3fv(_avatar->skinColor);
|
||||||
glColor3fv(skinColor);
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(j.x, j.y, j.z);
|
glTranslatef(_avatar->[b].springyPosition.x, _avatar->_joint[b].springyPosition.y, _avatar->_joint[b].springyPosition.z);
|
||||||
glutSolidSphere(_joint[b].radius, 20.0f, 20.0f);
|
glutSolidSphere(_avatar->_joint[b].radius, 20.0f, 20.0f);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_joint[b].touchForce > 0.0f) {
|
||||||
|
|
||||||
|
float alpha = _joint[b].touchForce * 0.2;
|
||||||
|
float r = _joint[b].radius * 1.1f + 0.005f;
|
||||||
|
glColor4f(0.5f, 0.2f, 0.2f, alpha);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(_joint[b].springyPosition.x, _joint[b].springyPosition.y, _joint[b].springyPosition.z);
|
||||||
|
glScalef(r, r, r);
|
||||||
|
glutSolidSphere(1, 20, 20);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render lines connecting the joint positions
|
// Render lines connecting the joint positions
|
||||||
glColor3f(0.4f, 0.5f, 0.6f);
|
glColor3f(0.4f, 0.5f, 0.6f);
|
||||||
glLineWidth(3.0);
|
glLineWidth(3.0);
|
||||||
|
@ -71,5 +78,6 @@ void AvatarRenderer::renderBody() {
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,17 @@
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class AvatarRenderer {
|
/*
|
||||||
|
class AvatarRenderer : public Avatar {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AvatarRenderer();
|
AvatarRenderer();
|
||||||
void render(Avatar *avatarToRender, bool lookingInMirror, glm::vec3 cameraPosition );
|
void render();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Avatar *avatar;
|
|
||||||
void renderBody();
|
void renderBody();
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -15,12 +15,16 @@ using namespace std;
|
||||||
const float HEAD_MOTION_DECAY = 0.1;
|
const float HEAD_MOTION_DECAY = 0.1;
|
||||||
const float MINIMUM_EYE_ROTATION = 0.7f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off
|
const float MINIMUM_EYE_ROTATION = 0.7f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off
|
||||||
|
|
||||||
|
const float EYEBALL_RADIUS = 0.02;
|
||||||
|
const float IRIS_RADIUS = 0.007;
|
||||||
|
const float IRIS_PROTRUSION = 0.018f;
|
||||||
|
|
||||||
float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
float _browColor [] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
|
||||||
float _mouthColor[] = {1, 0, 0};
|
float _mouthColor[] = {1, 0, 0};
|
||||||
|
|
||||||
float _BrowRollAngle [5] = {0, 15, 30, -30, -15};
|
float _BrowRollAngle [5] = { 0.0f, 15.0f, 30.0f, -30.0f, -15.0f};
|
||||||
float _BrowPitchAngle[3] = {-70, -60, -50};
|
float _BrowPitchAngle[3] = {-70.0f, -60.0f, -50.0f};
|
||||||
float _eyeColor [3] = {1,1,1};
|
float _eyeColor [3] = { 0.9f, 0.9f, 0.8f};
|
||||||
|
|
||||||
float _MouthWidthChoices[3] = {0.5, 0.77, 0.3};
|
float _MouthWidthChoices[3] = {0.5, 0.77, 0.3};
|
||||||
|
|
||||||
|
@ -35,16 +39,10 @@ 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),
|
||||||
_rotation(0.0f, 0.0f, 0.0f),
|
_rotation(0.0f, 0.0f, 0.0f),
|
||||||
_lookatPosition(0.0f, 0.0f, 0.0f),
|
|
||||||
_yaw(0.0f),
|
|
||||||
_pitch(0.0f),
|
|
||||||
_roll(0.0f),
|
|
||||||
_eyeballPitch(),
|
_eyeballPitch(),
|
||||||
_eyeballYaw(),
|
_eyeballYaw(),
|
||||||
_interBrowDistance(0.75f),
|
_interBrowDistance(0.75f),
|
||||||
|
@ -66,18 +64,16 @@ Head::Head() :
|
||||||
_bodyYaw(0.0f),
|
_bodyYaw(0.0f),
|
||||||
_eyeContactTarget(LEFT_EYE)
|
_eyeContactTarget(LEFT_EYE)
|
||||||
{
|
{
|
||||||
_eyebrowPitch[0] = -30;
|
_eyebrowPitch[0] = -30;
|
||||||
_eyebrowPitch[1] = -30;
|
_eyebrowPitch[1] = -30;
|
||||||
_eyebrowRoll [0] = 20;
|
_eyebrowRoll [0] = 20;
|
||||||
_eyebrowRoll [1] = -20;
|
_eyebrowRoll [1] = -20;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::setPositionRotationAndScale(glm::vec3 p, glm::vec3 r, float s) {
|
|
||||||
_position = p;
|
void Head::setPositionAndScale(glm::vec3 position, float scale) {
|
||||||
_scale = s;
|
_position = position;
|
||||||
_yaw = r.x;
|
_scale = scale;
|
||||||
_pitch = r.y;
|
|
||||||
_roll = r.z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::setNewTarget(float pitch, float yaw) {
|
void Head::setNewTarget(float pitch, float yaw) {
|
||||||
|
@ -85,6 +81,11 @@ void Head::setNewTarget(float pitch, float yaw) {
|
||||||
_yawTarget = yaw;
|
_yawTarget = 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...
|
||||||
|
@ -117,8 +118,8 @@ void Head::simulate(float deltaTime, bool isMine) {
|
||||||
_roll *= 1.f - (HEAD_MOTION_DECAY * deltaTime);
|
_roll *= 1.f - (HEAD_MOTION_DECAY * deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
//
|
//
|
||||||
|
@ -219,16 +220,17 @@ void Head::updateEyePositions() {
|
||||||
+ _orientation.getFront() * frontShift;
|
+ _orientation.getFront() * frontShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Head::setLooking(bool looking) {
|
void Head::setLooking(bool looking) {
|
||||||
|
|
||||||
_looking = 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) {
|
||||||
_looking = false;
|
_lookingAtSomething = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,9 +247,8 @@ void Head::render(bool lookingInMirror) {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
glTranslatef(_position.x, _position.y, _position.z);
|
glTranslatef(_position.x, _position.y, _position.z); //translate to head position
|
||||||
|
glScalef(_scale, _scale, _scale); //scale to head size
|
||||||
glScalef(_scale, _scale, _scale);
|
|
||||||
|
|
||||||
if (lookingInMirror) {
|
if (lookingInMirror) {
|
||||||
glRotatef(_bodyYaw - _yaw, 0, 1, 0);
|
glRotatef(_bodyYaw - _yaw, 0, 1, 0);
|
||||||
|
@ -326,13 +327,14 @@ void Head::render(bool lookingInMirror) {
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
//a new version of eyeballs that has the ability to look at specific targets in the world (algo still not finished yet)
|
|
||||||
renderEyeBalls();
|
renderEyeBalls();
|
||||||
|
|
||||||
if (_looking) {
|
/*
|
||||||
|
if (_lookingAtSomething) {
|
||||||
// Render lines originating from the eyes and converging on the lookatPosition
|
// Render lines originating from the eyes and converging on the lookatPosition
|
||||||
debugRenderLookatVectors(_leftEyePosition, _rightEyePosition, _lookatPosition);
|
debugRenderLookatVectors(_leftEyePosition, _rightEyePosition, _lookatPosition);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::renderEyeBalls() {
|
void Head::renderEyeBalls() {
|
||||||
|
@ -345,7 +347,7 @@ void Head::renderEyeBalls() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the texutre to be used on each eye
|
// setup the texutre to be used on each iris
|
||||||
GLUquadric* irisQuadric = gluNewQuadric();
|
GLUquadric* irisQuadric = gluNewQuadric();
|
||||||
gluQuadricTexture(irisQuadric, GL_TRUE);
|
gluQuadricTexture(irisQuadric, GL_TRUE);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
@ -353,60 +355,90 @@ void Head::renderEyeBalls() {
|
||||||
gluQuadricOrientation(irisQuadric, GLU_OUTSIDE);
|
gluQuadricOrientation(irisQuadric, GLU_OUTSIDE);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, IRIS_TEXTURE_WIDTH, IRIS_TEXTURE_HEIGHT,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, IRIS_TEXTURE_WIDTH, IRIS_TEXTURE_HEIGHT,
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, &::irisTexture[0]);
|
0, GL_RGBA, GL_UNSIGNED_BYTE, &::irisTexture[0]);
|
||||||
|
|
||||||
// left eyeball
|
// render white ball of left eyeball
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor3fv(_eyeColor);
|
glColor3fv(_eyeColor);
|
||||||
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z);
|
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z);
|
||||||
gluSphere(irisQuadric, 0.02, 30, 30);
|
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
// left iris
|
// render left iris
|
||||||
glPushMatrix(); {
|
glPushMatrix(); {
|
||||||
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z);
|
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); //translate to eyeball position
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - _leftEyePosition);
|
|
||||||
|
|
||||||
if (!_looking) {
|
|
||||||
targetLookatAxis = _orientation.getFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
float angle = 180.0f - angleBetween(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f));
|
if (_lookingAtSomething) {
|
||||||
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
|
||||||
glTranslatef( 0.0f, -0.018f, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
//rotate the eyeball to aim towards the lookat position
|
||||||
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _leftEyePosition); // the lookat direction
|
||||||
|
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP);
|
||||||
|
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
||||||
|
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
|
glRotatef(180.0, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//rotate the eyeball to aim straight ahead
|
||||||
|
glm::vec3 rotationAxisToHeadFront = glm::cross(_orientation.getFront(), IDENTITY_UP);
|
||||||
|
float angleToHeadFront = 180.0f - angleBetween(_orientation.getFront(), IDENTITY_UP);
|
||||||
|
glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z);
|
||||||
|
|
||||||
|
//set the amount of roll (for correction after previous rotations)
|
||||||
|
float rollRotation = angleBetween(_orientation.getFront(), IDENTITY_FRONT);
|
||||||
|
float dot = glm::dot(_orientation.getFront(), -IDENTITY_RIGHT);
|
||||||
|
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
||||||
|
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
||||||
|
}
|
||||||
|
|
||||||
|
glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
||||||
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
gluSphere(irisQuadric, 0.007, 15, 15);
|
gluSphere(irisQuadric, IRIS_RADIUS, 15, 15);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
//right eyeball
|
//render white ball of right eyeball
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor3fv(_eyeColor);
|
glColor3fv(_eyeColor);
|
||||||
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z);
|
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z);
|
||||||
gluSphere(irisQuadric, 0.02, 30, 30);
|
gluSphere(irisQuadric, EYEBALL_RADIUS, 30, 30);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
//right iris
|
// render right iris
|
||||||
glPushMatrix(); {
|
glPushMatrix(); {
|
||||||
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z);
|
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); //translate to eyeball position
|
||||||
glm::vec3 targetLookatAxis = glm::normalize(_lookatPosition - _rightEyePosition);
|
|
||||||
|
|
||||||
if (!_looking) {
|
|
||||||
targetLookatAxis = _orientation.getFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f));
|
|
||||||
float angle = 180.0f - angleBetween(targetLookatAxis, glm::vec3(0.0f, 1.0f, 0.0f));
|
if (_lookingAtSomething) {
|
||||||
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
|
||||||
glTranslatef( 0.0f, -0.018f, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
//rotate the eyeball to aim towards the lookat position
|
||||||
|
glm::vec3 targetLookatAxis = glm::normalize(_lookAtPosition - _rightEyePosition);
|
||||||
|
glm::vec3 rotationAxis = glm::cross(targetLookatAxis, IDENTITY_UP);
|
||||||
|
float angle = 180.0f - angleBetween(targetLookatAxis, IDENTITY_UP);
|
||||||
|
glRotatef(angle, rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||||
|
glRotatef(180.0f, 0.0f, 1.0f, 0.0f); //adjust roll to correct after previous rotations
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//rotate the eyeball to aim straight ahead
|
||||||
|
glm::vec3 rotationAxisToHeadFront = glm::cross(_orientation.getFront(), IDENTITY_UP);
|
||||||
|
float angleToHeadFront = 180.0f - angleBetween(_orientation.getFront(), IDENTITY_UP);
|
||||||
|
glRotatef(angleToHeadFront, rotationAxisToHeadFront.x, rotationAxisToHeadFront.y, rotationAxisToHeadFront.z);
|
||||||
|
|
||||||
|
//set the amount of roll (for correction after previous rotations)
|
||||||
|
float rollRotation = angleBetween(_orientation.getFront(), IDENTITY_FRONT);
|
||||||
|
float dot = glm::dot(_orientation.getFront(), -IDENTITY_RIGHT);
|
||||||
|
if ( dot < 0.0f ) { rollRotation = -rollRotation; }
|
||||||
|
glRotatef(rollRotation, 0.0f, 1.0f, 0.0f); //roll the iris or correct roll about the lookat vector
|
||||||
|
}
|
||||||
|
|
||||||
|
glTranslatef( 0.0f, -IRIS_PROTRUSION, 0.0f);//push the iris out a bit (otherwise - inside of eyeball!)
|
||||||
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
glScalef( 1.0f, 0.5f, 1.0f); // flatten the iris
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
gluSphere(irisQuadric, 0.007, 15, 15);
|
gluSphere(irisQuadric, IRIS_RADIUS, 15, 15);
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,18 +23,18 @@ 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);
|
||||||
|
|
||||||
void setLooking(bool looking);
|
void setLooking(bool looking);
|
||||||
void setPositionRotationAndScale(glm::vec3 position, glm::vec3 rotation, float scale);
|
void setPositionAndScale(glm::vec3 position, float scale);
|
||||||
void setNewTarget(float, float);
|
void setNewTarget(float, float);
|
||||||
|
|
||||||
void setLookatPosition (glm::vec3 lookatPosition ) { _lookatPosition = lookatPosition; }
|
|
||||||
void setGravity (glm::vec3 gravity ) { _gravity = gravity; }
|
void setGravity (glm::vec3 gravity ) { _gravity = gravity; }
|
||||||
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
|
void setSkinColor (glm::vec3 skinColor ) { _skinColor = skinColor; }
|
||||||
void setBodyYaw (float bodyYaw ) { _bodyYaw = bodyYaw; }
|
void setBodyYaw (float bodyYaw ) { _bodyYaw = bodyYaw; }
|
||||||
|
@ -50,8 +50,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:
|
||||||
|
|
||||||
|
@ -60,12 +58,8 @@ 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 _pitch;
|
|
||||||
float _roll;
|
|
||||||
float _eyeballPitch[2];
|
float _eyeballPitch[2];
|
||||||
float _eyeballYaw [2];
|
float _eyeballYaw [2];
|
||||||
float _eyebrowPitch[2];
|
float _eyebrowPitch[2];
|
||||||
|
@ -81,7 +75,7 @@ private:
|
||||||
float _scale;
|
float _scale;
|
||||||
int _eyeContact;
|
int _eyeContact;
|
||||||
float _browAudioLift;
|
float _browAudioLift;
|
||||||
bool _looking;
|
bool _lookingAtSomething;
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
float _lastLoudness;
|
float _lastLoudness;
|
||||||
float _averageLoudness;
|
float _averageLoudness;
|
||||||
|
|
|
@ -272,6 +272,9 @@ void LogDisplay::render(unsigned screenWidth, unsigned screenHeight) {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glScalef(xScale, yScale, 1.0f);
|
glScalef(xScale, yScale, 1.0f);
|
||||||
|
glColor3ub(GLubyte(TEXT_COLOR >> 16),
|
||||||
|
GLubyte((TEXT_COLOR >> 8) & 0xff),
|
||||||
|
GLubyte(TEXT_COLOR & 0xff));
|
||||||
for (int y = yStart; y > 0; y -= yStep) {
|
for (int y = yStart; y > 0; y -= yStep) {
|
||||||
|
|
||||||
// debug mode: check line pointer is valid
|
// debug mode: check line pointer is valid
|
||||||
|
@ -293,9 +296,6 @@ void LogDisplay::render(unsigned screenWidth, unsigned screenHeight) {
|
||||||
assert(! (chars < _charsEnd || chars >= _charsEnd + (_charsEnd - _chars)));
|
assert(! (chars < _charsEnd || chars >= _charsEnd + (_charsEnd - _chars)));
|
||||||
|
|
||||||
// render the string
|
// render the string
|
||||||
glColor3ub(GLubyte(TEXT_COLOR >> 16),
|
|
||||||
GLubyte((TEXT_COLOR >> 8) & 0xff),
|
|
||||||
GLubyte(TEXT_COLOR & 0xff));
|
|
||||||
_textRenderer.draw(xStart, y, chars);
|
_textRenderer.draw(xStart, y, chars);
|
||||||
|
|
||||||
//fprintf(stderr, "LogDisplay::render, message = \"%s\"\n", chars);
|
//fprintf(stderr, "LogDisplay::render, message = \"%s\"\n", chars);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
@ -14,8 +14,10 @@
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
|
|
||||||
#include "AvatarData.h"
|
#include "AvatarData.h"
|
||||||
|
#include "avatars_Log.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using avatars_lib::printLog;
|
||||||
|
|
||||||
int packFloatAngleToTwoByte(unsigned char* buffer, float angle) {
|
int packFloatAngleToTwoByte(unsigned char* buffer, float angle) {
|
||||||
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.0);
|
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.0);
|
||||||
|
@ -36,11 +38,6 @@ AvatarData::AvatarData() :
|
||||||
_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),
|
||||||
|
@ -54,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;
|
||||||
|
|
||||||
|
@ -66,6 +68,11 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
|
||||||
// that can pack any type given the number of bytes
|
// that can pack any type given the number of bytes
|
||||||
// and return the number of bytes to push the pointer
|
// and return the number of bytes to push the pointer
|
||||||
|
|
||||||
|
// lazily allocate memory for HeadData in case we're not an Avatar instance
|
||||||
|
if (!_headData) {
|
||||||
|
_headData = new HeadData();
|
||||||
|
}
|
||||||
|
|
||||||
// Body world position
|
// Body world position
|
||||||
memcpy(destinationBuffer, &_position, sizeof(float) * 3);
|
memcpy(destinationBuffer, &_position, sizeof(float) * 3);
|
||||||
destinationBuffer += sizeof(float) * 3;
|
destinationBuffer += sizeof(float) * 3;
|
||||||
|
@ -76,19 +83,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
|
||||||
|
memcpy(destinationBuffer, &_headData->_lookAtPosition, sizeof(_headData->_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));
|
||||||
|
@ -138,7 +149,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);
|
||||||
|
@ -153,25 +167,34 @@ 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
|
||||||
|
memcpy(&_headData->_lookAtPosition, sourceBuffer, sizeof(_headData->_lookAtPosition));
|
||||||
|
sourceBuffer += sizeof(_headData->_lookAtPosition);
|
||||||
|
|
||||||
// Hand State
|
// Hand State
|
||||||
memcpy(&_handState, sourceBuffer, sizeof(char));
|
memcpy(&_handState, sourceBuffer, sizeof(char));
|
||||||
sourceBuffer += sizeof(char);
|
sourceBuffer += sizeof(char);
|
||||||
|
@ -215,11 +238,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);
|
|
||||||
}
|
|
|
@ -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,10 +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 setHandPosition(const glm::vec3 handPosition) { _handPosition = handPosition; }
|
void setPosition (const glm::vec3 position ) { _position = position; }
|
||||||
|
void setHandPosition (const glm::vec3 handPosition ) { _handPosition = handPosition; }
|
||||||
|
|
||||||
int getBroadcastData(unsigned char* destinationBuffer);
|
int getBroadcastData(unsigned char* destinationBuffer);
|
||||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||||
|
@ -44,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; };
|
||||||
|
@ -106,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&);
|
||||||
|
@ -118,14 +106,6 @@ protected:
|
||||||
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;
|
||||||
|
@ -155,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__) */
|
||||||
|
|
38
libraries/avatars/src/HeadData.cpp
Normal file
38
libraries/avatars/src/HeadData.cpp
Normal 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;
|
||||||
|
}
|
60
libraries/avatars/src/HeadData.h
Normal file
60
libraries/avatars/src/HeadData.h
Normal 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__) */
|
Loading…
Reference in a new issue