Merge branch 'master' of https://github.com/worklist/hifi into voxel_animation

This commit is contained in:
ZappoMan 2013-05-20 15:52:04 -07:00
commit e1c89aac87
12 changed files with 316 additions and 165 deletions

View file

@ -138,6 +138,7 @@ Application::Application(int& argc, char** argv) :
_mouseY(0), _mouseY(0),
_mousePressed(false), _mousePressed(false),
_mouseVoxelScale(1.0f / 1024.0f), _mouseVoxelScale(1.0f / 1024.0f),
_justEditedVoxel(false),
_paintOn(false), _paintOn(false),
_dominantColor(0), _dominantColor(0),
_perfStatsOn(false), _perfStatsOn(false),
@ -306,7 +307,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());
@ -739,8 +739,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();
}
} }
} }
@ -749,13 +754,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();
} }
@ -928,6 +928,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
@ -1207,6 +1213,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);
@ -1684,7 +1692,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
@ -2026,18 +2034,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);
} }
} }
@ -2049,7 +2061,7 @@ void Application::deleteVoxelUnderCursor() {
//_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s); //_voxels.deleteVoxelAt(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z, _mouseVoxel.s);
// remember the position for drag detection // remember the position for drag detection
_lastMouseVoxelPos = glm::vec3(_mouseVoxel.x, _mouseVoxel.y, _mouseVoxel.z); _justEditedVoxel = true;
} }
} }

View file

@ -117,7 +117,7 @@ private:
void setupPaintingVoxel(); void setupPaintingVoxel();
void shiftPaintingColor(); void shiftPaintingColor();
void addVoxelUnderCursor(); void maybeEditVoxelUnderCursor();
void deleteVoxelUnderCursor(); void deleteVoxelUnderCursor();
void resetSensors(); void resetSensors();
@ -136,6 +136,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
@ -188,6 +189,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
@ -204,6 +206,7 @@ private:
VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor VoxelDetail _mouseVoxel; // details of the voxel under the mouse cursor
float _mouseVoxelScale; // the scale for adding/removing voxels float _mouseVoxelScale; // the scale for adding/removing voxels
glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit glm::vec3 _lastMouseVoxelPos; // the position of the last mouse voxel edit
bool _justEditedVoxel; // set when we've just added/deleted/colored a voxel
bool _paintOn; // Whether to paint voxels as you fly around bool _paintOn; // Whether to paint voxels as you fly around
unsigned char _dominantColor; // The dominant color of the voxel we're painting unsigned char _dominantColor; // The dominant color of the voxel we're painting

View file

@ -50,14 +50,16 @@ 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(); _orientation.setToIdentity();
@ -393,17 +395,20 @@ void Avatar::simulate(float deltaTime) {
_joint[ AVATAR_JOINT_HEAD_BASE ].radius _joint[ AVATAR_JOINT_HEAD_BASE ].radius
); );
_head.setBodyYaw(_bodyYaw); 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) {
setLookatPosition(_interactingOther->getSpringyHeadPosition());
}
} else { } else {
_head.setLooking(false); _head.setLooking(false);
} }
_head.setBodyYaw(_bodyYaw);
_head.setLookatPosition(_lookatPosition);
_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 +697,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 +707,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 +1033,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 +1129,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);
@ -1378,3 +1387,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();
}

View file

@ -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"
@ -217,6 +218,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

View file

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

View file

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

View file

@ -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};
@ -66,12 +70,13 @@ 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) { void Head::setPositionRotationAndScale(glm::vec3 p, glm::vec3 r, float s) {
_position = p; _position = p;
_scale = s; _scale = s;
@ -219,16 +224,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 +251,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 +331,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 +351,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 +359,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();
} }

View file

@ -81,7 +81,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;

View file

@ -46,7 +46,8 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- .
VoxelSystem::VoxelSystem() { VoxelSystem::VoxelSystem() {
_voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
_renderFullVBO = true; _writeRenderFullVBO = true;
_readRenderFullVBO = true;
_tree = new VoxelTree(); _tree = new VoxelTree();
pthread_mutex_init(&_bufferWriteLock, NULL); pthread_mutex_init(&_bufferWriteLock, NULL);
pthread_mutex_init(&_treeLock, NULL); pthread_mutex_init(&_treeLock, NULL);
@ -57,7 +58,8 @@ VoxelSystem::~VoxelSystem() {
delete[] _writeVerticesArray; delete[] _writeVerticesArray;
delete[] _readColorsArray; delete[] _readColorsArray;
delete[] _writeColorsArray; delete[] _writeColorsArray;
delete[] _voxelDirtyArray; delete[] _writeVoxelDirtyArray;
delete[] _readVoxelDirtyArray;
delete _tree; delete _tree;
pthread_mutex_destroy(&_bufferWriteLock); pthread_mutex_destroy(&_bufferWriteLock);
pthread_mutex_destroy(&_treeLock); pthread_mutex_destroy(&_treeLock);
@ -188,14 +190,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);
@ -203,16 +206,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;
@ -226,30 +235,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;
@ -298,14 +309,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();
@ -335,7 +344,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) {
} }
} }
} }
if (_renderFullVBO) { if (_writeRenderFullVBO) {
voxelsUpdated += updateNodeInArraysAsFullVBO(node); voxelsUpdated += updateNodeInArraysAsFullVBO(node);
} else { } else {
voxelsUpdated += updateNodeInArraysAsPartialVBO(node); voxelsUpdated += updateNodeInArraysAsPartialVBO(node);
@ -373,7 +382,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
} }
@ -410,7 +419,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
@ -440,9 +449,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];
@ -539,7 +550,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);
@ -553,21 +564,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) {
@ -587,13 +598,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);
@ -612,22 +623,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
@ -644,9 +660,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);
@ -659,9 +677,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);
@ -673,6 +693,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;
@ -1021,7 +1043,7 @@ void VoxelSystem::collectStatsForTreesAndVBOs() {
glBufferIndex maxDirty = 0; glBufferIndex maxDirty = 0;
for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
if (_voxelDirtyArray[i]) { if (_writeVoxelDirtyArray[i]) {
minDirty = std::min(minDirty,i); minDirty = std::min(minDirty,i);
maxDirty = std::max(maxDirty,i); maxDirty = std::max(maxDirty,i);
} }

View file

@ -36,7 +36,7 @@ public:
void init(); void init();
void simulate(float deltaTime) { }; void simulate(float deltaTime) { };
void render(); void render(bool texture);
unsigned long getVoxelsUpdated() const {return _voxelsUpdated;}; unsigned long getVoxelsUpdated() const {return _voxelsUpdated;};
unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;}; unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;};
@ -121,13 +121,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;
@ -151,7 +153,7 @@ private:
void cleanupRemovedVoxels(); void cleanupRemovedVoxels();
void setupNewVoxelsForDrawing(); void setupNewVoxelsForDrawing();
void copyWrittenDataToReadArrays(); void copyWrittenDataToReadArrays(bool fullVBOs);
bool _voxelsDirty; bool _voxelsDirty;

View file

@ -35,6 +35,7 @@ int unpackFloatAngleFromTwoByte(uint16_t* byteAnglePointer, float* destinationPo
AvatarData::AvatarData() : AvatarData::AvatarData() :
_handPosition(0,0,0), _handPosition(0,0,0),
_lookatPosition(0,0,0),
_bodyYaw(-90.0), _bodyYaw(-90.0),
_bodyPitch(0.0), _bodyPitch(0.0),
_bodyRoll(0.0), _bodyRoll(0.0),
@ -91,6 +92,10 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
// 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, &_lookatPosition, sizeof(_lookatPosition));
destinationBuffer += sizeof(_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));
@ -175,6 +180,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
memcpy(&_handPosition, sourceBuffer, sizeof(float) * 3); memcpy(&_handPosition, sourceBuffer, sizeof(float) * 3);
sourceBuffer += sizeof(float) * 3; sourceBuffer += sizeof(float) * 3;
// Lookat Position
memcpy(&_lookatPosition, sourceBuffer, sizeof(_lookatPosition));
sourceBuffer += sizeof(_lookatPosition);
// Hand State // Hand State
memcpy(&_handState, sourceBuffer, sizeof(char)); memcpy(&_handState, sourceBuffer, sizeof(char));
sourceBuffer += sizeof(char); sourceBuffer += sizeof(char);

View file

@ -32,8 +32,10 @@ public:
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; }
void setLookatPosition(const glm::vec3 lookatPosition) { _lookatPosition = lookatPosition; }
int getBroadcastData(unsigned char* destinationBuffer); int getBroadcastData(unsigned char* destinationBuffer);
int parseData(unsigned char* sourceBuffer, int numBytes); int parseData(unsigned char* sourceBuffer, int numBytes);
@ -116,6 +118,7 @@ protected:
glm::vec3 _position; glm::vec3 _position;
glm::vec3 _handPosition; glm::vec3 _handPosition;
glm::vec3 _lookatPosition;
// Body rotation // Body rotation
float _bodyYaw; float _bodyYaw;