More work on voxeltars; separated default pose from bind pose.

This commit is contained in:
Andrzej Kapolka 2013-06-04 10:22:58 -07:00
parent 6552a64bb4
commit bc8eadd526
9 changed files with 171 additions and 40 deletions

View file

@ -63,12 +63,12 @@ if (APPLE)
endif (APPLE)
find_package(Qt4 REQUIRED QtCore QtGui QtOpenGL)
find_package(Qt4 REQUIRED QtCore QtGui QtNetwork QtOpenGL)
include(${QT_USE_FILE})
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${QT_QTGUI_INCLUDE_DIR}")
# run qt moc on qt-enabled headers
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h)
qt4_wrap_cpp(INTERFACE_SRCS src/Application.h src/AvatarVoxelSystem.h)
# create the executable, make it a bundle on OS X
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS})

View file

@ -21,16 +21,23 @@
#include <glm/gtx/quaternion.hpp>
#include <QActionGroup>
#include <QBoxLayout>
#include <QColorDialog>
#include <QDialogButtonBox>
#include <QDesktopWidget>
#include <QFormLayout>
#include <QGLWidget>
#include <QKeyEvent>
#include <QLineEdit>
#include <QMainWindow>
#include <QMenuBar>
#include <QMouseEvent>
#include <QNetworkAccessManager>
#include <QWheelEvent>
#include <QSettings>
#include <QShortcut>
#include <QTimer>
#include <QUrl>
#include <QtDebug>
#include <PairingHandler.h>
@ -1122,6 +1129,31 @@ void Application::terminate() {
}
}
void Application::editPreferences() {
QDialog dialog(_glWidget);
dialog.setWindowTitle("Interface Preferences");
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
dialog.setLayout(layout);
QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1);
QLineEdit* avatarURL = new QLineEdit(_settings->value("avatarURL").toString());
form->addRow("Avatar URL:", avatarURL);
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(buttons);
if (dialog.exec() != QDialog::Accepted) {
return;
}
QUrl url(avatarURL->text());
_settings->setValue("avatarURL", url);
_myAvatar.getVoxels()->loadVoxelsFromURL(url);
}
void Application::pair() {
PairingHandler::sendPairRequest();
}
@ -1285,6 +1317,9 @@ void Application::initMenu() {
QMenu* fileMenu = menuBar->addMenu("File");
fileMenu->addAction("Quit", this, SLOT(quit()), Qt::CTRL | Qt::Key_Q);
QMenu* editMenu = menuBar->addMenu("Edit");
editMenu->addAction("Preferences...", this, SLOT(editPreferences()));
QMenu* pairMenu = menuBar->addMenu("Pair");
pairMenu->addAction("Pair", this, SLOT(pair()));
@ -1325,9 +1360,7 @@ void Application::initMenu() {
renderMenu->addAction("First Person", this, SLOT(setRenderFirstPerson(bool)), Qt::Key_P)->setCheckable(true);
QMenu* toolsMenu = menuBar->addMenu("Tools");
(_renderStatsOn = toolsMenu->addAction("Stats"))->setCheckable(true);
_renderStatsOn->setShortcut(Qt::Key_Slash);
(_logOn = toolsMenu->addAction("Log"))->setCheckable(true);
_logOn->setChecked(false);
@ -1381,6 +1414,9 @@ void Application::initMenu() {
debugMenu->addAction("Wants Res-In", this, SLOT(setWantsResIn(bool)))->setCheckable(true);
debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true);
debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true);
_networkAccessManager = new QNetworkAccessManager(this);
_settings = new QSettings("High Fidelity", "Interface", this);
}
void Application::updateFrustumRenderModeAction() {
@ -1431,6 +1467,8 @@ void Application::init() {
_myCamera.setModeShiftRate(1.0f);
_myAvatar.setDisplayingLookatVectors(false);
_myAvatar.getVoxels()->loadVoxelsFromURL(_settings->value("avatarURL").toUrl());
QCursor::setPos(_headMouseX, _headMouseY);
OculusManager::connect();
@ -1727,7 +1765,7 @@ void Application::displayOculus(Camera& whichCamera) {
glPopMatrix();
}
void Application::displaySide(Camera& whichCamera) {
// transform by eye offset

View file

@ -37,6 +37,8 @@ class QGLWidget;
class QKeyEvent;
class QMainWindow;
class QMouseEvent;
class QNetworkAccessManager;
class QSettings;
class QWheelEvent;
class Agent;
@ -70,6 +72,8 @@ public:
Environment* getEnvironment() { return &_environment; }
bool shouldEchoAudio() { return _echoAudioMode->isChecked(); }
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
/*!
@fn getSettingBool
@brief A function for getting boolean settings from the settings file.
@ -127,6 +131,8 @@ private slots:
void idle();
void terminate();
void editPreferences();
void pair();
void setHead(bool head);
@ -227,6 +233,9 @@ private:
QAction* _fullScreenMode; // whether we are in full screen mode
QAction* _frustumRenderModeAction;
QNetworkAccessManager* _networkAccessManager;
QSettings* _settings;
SerialInterface _serialPort;
bool _displayLevels;

View file

@ -89,6 +89,8 @@ public:
glm::quat getOrientation () const;
glm::quat getWorldAlignedOrientation() const;
AvatarVoxelSystem* getVoxels() { return &_voxels; }
// Set what driving keys are being pressed to control thrust levels
void setDriveKeys(int key, bool val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key]; };

View file

@ -7,6 +7,12 @@
#include <cstring>
#include <QNetworkReply>
#include <QUrl>
#include <GeometryUtil.h>
#include "Application.h"
#include "Avatar.h"
#include "AvatarVoxelSystem.h"
#include "renderer/ProgramObject.h"
@ -17,7 +23,7 @@ const int BONE_ELEMENTS_PER_VOXEL = BONE_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXE
AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) :
VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR),
_avatar(avatar) {
_avatar(avatar), _voxelReply(0) {
}
AvatarVoxelSystem::~AvatarVoxelSystem() {
@ -52,16 +58,6 @@ void AvatarVoxelSystem::init() {
glBindBuffer(GL_ARRAY_BUFFER, _vboBoneWeightsID);
glBufferData(GL_ARRAY_BUFFER, BONE_ELEMENTS_PER_VOXEL * sizeof(GLfloat) * _maxVoxels, NULL, GL_DYNAMIC_DRAW);
for (int i = 0; i < 150; i++) {
int power = pow(2, randIntInRange(6, 8));
float size = 1.0f / power;
_tree->createVoxel(
randIntInRange(0, power - 1) * size,
randIntInRange(0, power - 1) * size,
randIntInRange(0, power - 1) * size, size, 255, 0, 255, true);
}
setupNewVoxelsForDrawing();
// load our skin program if this is the first avatar system to initialize
if (_skinProgram != 0) {
return;
@ -75,8 +71,25 @@ void AvatarVoxelSystem::init() {
_boneWeightsLocation = _skinProgram->attributeLocation("boneWeights");
}
void AvatarVoxelSystem::render(bool texture) {
VoxelSystem::render(texture);
void AvatarVoxelSystem::removeOutOfView() {
// no-op for now
}
void AvatarVoxelSystem::loadVoxelsFromURL(const QUrl& url) {
// cancel any current download
if (_voxelReply != 0) {
delete _voxelReply;
}
killLocalVoxels();
// load the URL data asynchronously
if (!url.isValid()) {
return;
}
_voxelReply = Application::getInstance()->getNetworkAccessManager()->get(QNetworkRequest(url));
connect(_voxelReply, SIGNAL(readyRead()), SLOT(readVoxelDataFromReply()));
connect(_voxelReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleVoxelReplyError()));
}
void AvatarVoxelSystem::updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex,
@ -168,6 +181,25 @@ void AvatarVoxelSystem::removeScaleAndReleaseProgram(bool texture) {
_skinProgram->disableAttributeArray(_boneWeightsLocation);
}
void AvatarVoxelSystem::readVoxelDataFromReply() {
// for now, just wait until we have the full business
if (!_voxelReply->isFinished()) {
return;
}
QByteArray entirety = _voxelReply->readAll();
_voxelReply->deleteLater();
_voxelReply = 0;
_tree->readBitstreamToTree((unsigned char*)entirety.data(), entirety.size(), WANT_COLOR, NO_EXISTS_BITS);
setupNewVoxelsForDrawing();
}
void AvatarVoxelSystem::handleVoxelReplyError() {
printLog("%s\n", _voxelReply->errorString().toAscii().constData());
_voxelReply->deleteLater();
_voxelReply = 0;
}
class IndexDistance {
public:
IndexDistance(GLubyte index = 0, float distance = FLT_MAX) : index(index), distance(distance) { }
@ -183,7 +215,10 @@ void AvatarVoxelSystem::computeBoneIndicesAndWeights(const glm::vec3& vertex, Bo
// find the nearest four joints (TODO: use a better data structure for the pose positions to speed this up)
IndexDistance nearest[BONE_ELEMENTS_PER_VERTEX];
for (int i = 0; i < NUM_AVATAR_JOINTS; i++) {
float distance = glm::distance(jointVertex, _avatar->getSkeleton().joint[i].absoluteBindPosePosition);
AvatarJointID parent = _avatar->getSkeleton().joint[i].parent;
float distance = glm::length(computeVectorFromPointToSegment(jointVertex,
_avatar->getSkeleton().joint[parent == AVATAR_JOINT_NULL ? i : parent].absoluteBindPosePosition,
_avatar->getSkeleton().joint[i].absoluteBindPosePosition));
for (int j = 0; j < BONE_ELEMENTS_PER_VERTEX; j++) {
if (distance < nearest[j].distance) {
// move the rest of the indices down

View file

@ -9,22 +9,32 @@
#ifndef __interface__AvatarVoxelSystem__
#define __interface__AvatarVoxelSystem__
#include <QObject>
#include "VoxelSystem.h"
const int BONE_ELEMENTS_PER_VERTEX = 4;
typedef GLubyte BoneIndices[BONE_ELEMENTS_PER_VERTEX];
class QNetworkReply;
class QUrl;
class Avatar;
class AvatarVoxelSystem : public VoxelSystem {
class AvatarVoxelSystem : public QObject, public VoxelSystem {
Q_OBJECT
public:
AvatarVoxelSystem(Avatar* avatar);
virtual ~AvatarVoxelSystem();
virtual void init();
virtual void render(bool texture);
virtual void removeOutOfView();
void loadVoxelsFromURL(const QUrl& url);
protected:
virtual void updateNodeInArrays(glBufferIndex nodeIndex, const glm::vec3& startVertex,
@ -33,6 +43,11 @@ protected:
virtual void updateVBOSegment(glBufferIndex segmentStart, glBufferIndex segmentEnd);
virtual void applyScaleAndBindProgram(bool texture);
virtual void removeScaleAndReleaseProgram(bool texture);
private slots:
void readVoxelDataFromReply();
void handleVoxelReplyError();
private:
@ -48,6 +63,8 @@ private:
GLuint _vboBoneIndicesID;
GLuint _vboBoneWeightsID;
QNetworkReply* _voxelReply;
static ProgramObject* _skinProgram;
static int _boneMatricesLocation;
static int _boneIndicesLocation;

View file

@ -49,7 +49,7 @@ void Skeleton::initialize() {
joint[ AVATAR_JOINT_RIGHT_HEEL ].parent = AVATAR_JOINT_RIGHT_KNEE;
joint[ AVATAR_JOINT_RIGHT_TOES ].parent = AVATAR_JOINT_RIGHT_HEEL;
// specify the default pose position
// specify the bind pose position
joint[ AVATAR_JOINT_PELVIS ].bindPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
joint[ AVATAR_JOINT_TORSO ].bindPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
joint[ AVATAR_JOINT_CHEST ].bindPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
@ -58,29 +58,58 @@ void Skeleton::initialize() {
joint[ AVATAR_JOINT_LEFT_COLLAR ].bindPosePosition = glm::vec3( -0.06, 0.04, 0.01 );
joint[ AVATAR_JOINT_LEFT_SHOULDER ].bindPosePosition = glm::vec3( -0.05, 0.0, 0.01 );
joint[ AVATAR_JOINT_LEFT_ELBOW ].bindPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
joint[ AVATAR_JOINT_LEFT_WRIST ].bindPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].bindPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
joint[ AVATAR_JOINT_LEFT_ELBOW ].bindPosePosition = glm::vec3( -0.16, 0.0, 0.0 );
joint[ AVATAR_JOINT_LEFT_WRIST ].bindPosePosition = glm::vec3( -0.12, 0.0, 0.0 );
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].bindPosePosition = glm::vec3( -0.1, 0.0, 0.0 );
joint[ AVATAR_JOINT_RIGHT_COLLAR ].bindPosePosition = glm::vec3( 0.06, 0.04, 0.01 );
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].bindPosePosition = glm::vec3( 0.05, 0.0, 0.01 );
joint[ AVATAR_JOINT_RIGHT_ELBOW ].bindPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
joint[ AVATAR_JOINT_RIGHT_WRIST ].bindPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].bindPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
joint[ AVATAR_JOINT_RIGHT_ELBOW ].bindPosePosition = glm::vec3( 0.16, 0.0, 0.0 );
joint[ AVATAR_JOINT_RIGHT_WRIST ].bindPosePosition = glm::vec3( 0.12, 0.0, 0.0 );
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].bindPosePosition = glm::vec3( 0.1, 0.0, 0.0 );
joint[ AVATAR_JOINT_LEFT_HIP ].bindPosePosition = glm::vec3( -0.05, 0.0, 0.02 );
joint[ AVATAR_JOINT_LEFT_KNEE ].bindPosePosition = glm::vec3( 0.01, -0.25, -0.03 );
joint[ AVATAR_JOINT_LEFT_HEEL ].bindPosePosition = glm::vec3( 0.01, -0.22, 0.08 );
joint[ AVATAR_JOINT_LEFT_TOES ].bindPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
joint[ AVATAR_JOINT_LEFT_KNEE ].bindPosePosition = glm::vec3( 0.00, -0.25, 0.00 );
joint[ AVATAR_JOINT_LEFT_HEEL ].bindPosePosition = glm::vec3( 0.00, -0.23, 0.00 );
joint[ AVATAR_JOINT_LEFT_TOES ].bindPosePosition = glm::vec3( 0.00, 0.00, -0.06 );
joint[ AVATAR_JOINT_RIGHT_HIP ].bindPosePosition = glm::vec3( 0.05, 0.0, 0.02 );
joint[ AVATAR_JOINT_RIGHT_KNEE ].bindPosePosition = glm::vec3( -0.01, -0.25, -0.03 );
joint[ AVATAR_JOINT_RIGHT_HEEL ].bindPosePosition = glm::vec3( -0.01, -0.22, 0.08 );
joint[ AVATAR_JOINT_RIGHT_TOES ].bindPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
joint[ AVATAR_JOINT_RIGHT_KNEE ].bindPosePosition = glm::vec3( 0.00, -0.25, 0.00 );
joint[ AVATAR_JOINT_RIGHT_HEEL ].bindPosePosition = glm::vec3( 0.00, -0.23, 0.00 );
joint[ AVATAR_JOINT_RIGHT_TOES ].bindPosePosition = glm::vec3( 0.00, 0.00, -0.06 );
// specify the default pose position
joint[ AVATAR_JOINT_PELVIS ].defaultPosePosition = glm::vec3( 0.0, 0.0, 0.0 );
joint[ AVATAR_JOINT_TORSO ].defaultPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
joint[ AVATAR_JOINT_CHEST ].defaultPosePosition = glm::vec3( 0.0, 0.09, -0.01 );
joint[ AVATAR_JOINT_NECK_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.14, 0.01 );
joint[ AVATAR_JOINT_HEAD_BASE ].defaultPosePosition = glm::vec3( 0.0, 0.04, 0.00 );
joint[ AVATAR_JOINT_LEFT_COLLAR ].defaultPosePosition = glm::vec3( -0.06, 0.04, 0.01 );
joint[ AVATAR_JOINT_LEFT_SHOULDER ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.01 );
joint[ AVATAR_JOINT_LEFT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
joint[ AVATAR_JOINT_LEFT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
joint[ AVATAR_JOINT_LEFT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
joint[ AVATAR_JOINT_RIGHT_COLLAR ].defaultPosePosition = glm::vec3( 0.06, 0.04, 0.01 );
joint[ AVATAR_JOINT_RIGHT_SHOULDER ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.01 );
joint[ AVATAR_JOINT_RIGHT_ELBOW ].defaultPosePosition = glm::vec3( 0.0, -0.16, 0.0 );
joint[ AVATAR_JOINT_RIGHT_WRIST ].defaultPosePosition = glm::vec3( 0.0, -0.117, 0.0 );
joint[ AVATAR_JOINT_RIGHT_FINGERTIPS ].defaultPosePosition = glm::vec3( 0.0, -0.1, 0.0 );
joint[ AVATAR_JOINT_LEFT_HIP ].defaultPosePosition = glm::vec3( -0.05, 0.0, 0.02 );
joint[ AVATAR_JOINT_LEFT_KNEE ].defaultPosePosition = glm::vec3( 0.01, -0.25, -0.03 );
joint[ AVATAR_JOINT_LEFT_HEEL ].defaultPosePosition = glm::vec3( 0.01, -0.22, 0.08 );
joint[ AVATAR_JOINT_LEFT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
joint[ AVATAR_JOINT_RIGHT_HIP ].defaultPosePosition = glm::vec3( 0.05, 0.0, 0.02 );
joint[ AVATAR_JOINT_RIGHT_KNEE ].defaultPosePosition = glm::vec3( -0.01, -0.25, -0.03 );
joint[ AVATAR_JOINT_RIGHT_HEEL ].defaultPosePosition = glm::vec3( -0.01, -0.22, 0.08 );
joint[ AVATAR_JOINT_RIGHT_TOES ].defaultPosePosition = glm::vec3( 0.00, -0.03, -0.05 );
// calculate bone length, absolute positions/rotations
// calculate bone length, absolute bind positions/rotations
for (int b = 0; b < NUM_AVATAR_JOINTS; b++) {
joint[b].length = glm::length(joint[b].bindPosePosition);
joint[b].length = glm::length(joint[b].defaultPosePosition);
if (joint[b].parent == AVATAR_JOINT_NULL) {
joint[b].absoluteBindPosePosition = joint[b].bindPosePosition;
@ -106,7 +135,7 @@ void Skeleton::update(float deltaTime, const glm::quat& orientation, glm::vec3 p
joint[b].position = joint[ joint[b].parent ].position;
}
glm::vec3 rotatedJointVector = joint[b].rotation * joint[b].bindPosePosition;
glm::vec3 rotatedJointVector = joint[b].rotation * joint[b].defaultPosePosition;
joint[b].position += rotatedJointVector;
}
}

View file

@ -61,6 +61,7 @@ public:
{
AvatarJointID parent; // which joint is this joint connected to?
glm::vec3 position; // the position at the "end" of the joint - in global space
glm::vec3 defaultPosePosition; // the parent relative position when the avatar is in the default pose
glm::vec3 bindPosePosition; // the parent relative position when the avatar is in the "T-pose"
glm::vec3 absoluteBindPosePosition; // the absolute position when the avatar is in the "T-pose"
glm::quat absoluteBindPoseRotation; // the absolute rotation when the avatar is in the "T-pose"

View file

@ -33,7 +33,7 @@ public:
virtual void init();
void simulate(float deltaTime) { };
virtual void render(bool texture);
void render(bool texture);
unsigned long getVoxelsUpdated() const {return _voxelsUpdated;};
unsigned long getVoxelsRendered() const {return _voxelsInReadArrays;};
@ -59,7 +59,7 @@ public:
void setRenderPipelineWarnings(bool on) { _renderWarningsOn = on; };
bool getRenderPipelineWarnings() const { return _renderWarningsOn; };
void removeOutOfView();
virtual void removeOutOfView();
bool hasViewChanged();
bool isViewChanging();