Working on reading and rendering the rig from Faceshift.

This commit is contained in:
Andrzej Kapolka 2013-09-16 15:49:40 -07:00
parent 86307ea67f
commit f9426cbecc
10 changed files with 193 additions and 9 deletions

View file

@ -275,7 +275,8 @@ Menu::Menu() :
appInstance->getGlowEffect(),
SLOT(cycleRenderMode()));
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UseFaceshiftRig, 0, false,
appInstance->getFaceshift(), SLOT(setUsingRig(bool)));
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UsePerlinFace, 0, false);
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtVectors, 0, true);
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtIndicator, 0, true);

View file

@ -31,6 +31,8 @@ struct ViewFrustumOffset {
float up;
};
class QSettings;
class BandwidthDialog;
class VoxelStatsDialog;
@ -197,6 +199,7 @@ namespace MenuOption {
const QString TestRaveGlove = "Test Rave Glove";
const QString TreeStats = "Calculate Tree Stats";
const QString TransmitterDrive = "Transmitter Drive";
const QString UseFaceshiftRig = "Use Faceshift Rig";
const QString UsePerlinFace = "Use Perlin's Face";
const QString Quit = "Quit";
const QString Webcam = "Webcam";

View file

@ -0,0 +1,94 @@
//
// BlendFace.cpp
// interface
//
// Created by Andrzej Kapolka on 9/16/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include "BlendFace.h"
#include "Head.h"
using namespace fs;
BlendFace::BlendFace(Head* owningHead) :
_owningHead(owningHead),
_iboID(0)
{
}
BlendFace::~BlendFace() {
if (_iboID != 0) {
glDeleteBuffers(1, &_iboID);
glDeleteBuffers(1, &_vboID);
}
}
bool BlendFace::render(float alpha) {
if (_iboID == 0) {
return false;
}
glPushMatrix();
glTranslatef(_owningHead->getPosition().x, _owningHead->getPosition().y, _owningHead->getPosition().z);
glm::quat orientation = _owningHead->getOrientation();
glm::vec3 axis = glm::axis(orientation);
glRotatef(glm::angle(orientation), axis.x, axis.y, axis.z);
glScalef(_owningHead->getScale(), _owningHead->getScale(), _owningHead->getScale());
glColor4f(1.0f, 1.0f, 1.0f, alpha);
// update the blended vertices
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glBufferSubData(GL_ARRAY_BUFFER, 0, _baseVertices.size() * sizeof(fsVector3f), _baseVertices.data());
// tell OpenGL where to find vertex information
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID);
glDrawRangeElementsEXT(GL_TRIANGLES, 0, _baseVertices.size() - 1, _indexCount, GL_UNSIGNED_INT, 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// deactivate vertex arrays after drawing
glDisableClientState(GL_VERTEX_ARRAY);
// bind with 0 to switch back to normal operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glPopMatrix();
return true;
}
void BlendFace::setRig(const fsMsgRig& rig) {
if (rig.mesh().m_tris.empty()) {
// clear any existing geometry
if (_iboID != 0) {
glDeleteBuffers(1, &_iboID);
glDeleteBuffers(1, &_vboID);
_iboID = 0;
}
return;
}
if (_iboID == 0) {
glGenBuffers(1, &_iboID);
glGenBuffers(1, &_vboID);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, rig.mesh().m_tris.size() * sizeof(fsVector3i),
rig.mesh().m_tris.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
glBufferData(GL_ARRAY_BUFFER, rig.mesh().m_vertex_data.m_vertices.size() * sizeof(fsVector3f), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
_indexCount = rig.mesh().m_tris.size() * 3;
_baseVertices = rig.mesh().m_vertex_data.m_vertices;
_blendshapes = rig.blendshapes();
}

View file

@ -0,0 +1,47 @@
//
// BlendFace.h
// interface
//
// Created by Andrzej Kapolka on 9/16/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__BlendFace__
#define __interface__BlendFace__
#include <QObject>
#include <fsbinarystream.h>
#include "InterfaceConfig.h"
class Head;
/// A face formed from a linear mix of blendshapes according to a set of coefficients.
class BlendFace : public QObject {
Q_OBJECT
public:
BlendFace(Head* owningHead);
~BlendFace();
bool render(float alpha);
private slots:
void setRig(const fs::fsMsgRig& rig);
private:
Head* _owningHead;
GLuint _iboID;
GLuint _vboID;
GLsizei _indexCount;
std::vector<fs::fsVector3f> _baseVertices;
std::vector<fs::fsVertexData> _blendshapes;
};
#endif /* defined(__interface__BlendFace__) */

View file

@ -87,7 +87,8 @@ Head::Head(Avatar* owningAvatar) :
_cameraFollowsHead(false),
_cameraFollowHeadRate(0.0f),
_face(this),
_perlinFace(this)
_perlinFace(this),
_blendFace(this)
{
if (USING_PHYSICAL_MOHAWK) {
resetHairPhysics();

View file

@ -18,9 +18,10 @@
#include <VoxelConstants.h>
#include "BendyLine.h"
#include "BlendFace.h"
#include "Face.h"
#include "PerlinFace.h"
#include "InterfaceConfig.h"
#include "PerlinFace.h"
#include "world.h"
#include "devices/SerialInterface.h"
@ -71,6 +72,7 @@ public:
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
Face& getFace() { return _face; }
BlendFace& getBlendFace() { return _blendFace; }
const bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected)
float getAverageLoudness() const { return _averageLoudness; }
@ -128,6 +130,7 @@ private:
float _cameraFollowHeadRate;
Face _face;
PerlinFace _perlinFace;
BlendFace _blendFace;
static ProgramObject _irisProgram;
static GLuint _irisTextureID;

View file

@ -56,7 +56,15 @@ MyAvatar::MyAvatar(Node* owningNode) :
_driveKeys[i] = false;
}
_collisionRadius = _height * COLLISION_RADIUS_SCALE;
_collisionRadius = _height * COLLISION_RADIUS_SCALE;
}
void MyAvatar::init() {
Avatar::init();
// when we receive a Faceshift rig, apply it to our own blend face
_head.getBlendFace().connect(Application::getInstance()->getFaceshift(), SIGNAL(rigReceived(fs::fsMsgRig)),
SLOT(setRig(fs::fsMsgRig)));
}
void MyAvatar::reset() {

View file

@ -15,6 +15,7 @@ class MyAvatar : public Avatar {
public:
MyAvatar(Node* owningNode = NULL);
void init();
void reset();
void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity);
void updateFromGyrosAndOrWebcam(bool gyroLook, float pitchFromTouch);
@ -87,4 +88,4 @@ public:
void checkForMouseRayTouching();
};
#endif
#endif

View file

@ -11,6 +11,7 @@
#include <SharedUtil.h>
#include "Faceshift.h"
#include "Menu.h"
using namespace fs;
using namespace std;
@ -98,6 +99,17 @@ void Faceshift::setTCPEnabled(bool enabled) {
}
}
void Faceshift::setUsingRig(bool usingRig) {
if (usingRig && _tcpSocket.state() == QAbstractSocket::ConnectedState) {
string message;
fsBinaryStream::encode_message(message, fsMsgSendRig());
send(message);
} else {
emit rigReceived(fsMsgRig());
}
}
void Faceshift::connectSocket() {
if (_tcpEnabled) {
qDebug("Faceshift: Connecting...\n");
@ -114,6 +126,11 @@ void Faceshift::noteConnected() {
string message;
fsBinaryStream::encode_message(message, fsMsgSendBlendshapeNames());
send(message);
// if using faceshift rig, request it
if (Menu::getInstance()->isOptionChecked(MenuOption::UseFaceshiftRig)) {
setUsingRig(true);
}
}
void Faceshift::noteError(QAbstractSocket::SocketError error) {
@ -208,10 +225,10 @@ void Faceshift::receive(const QByteArray& buffer) {
} else if (names[i] == "EyeBlink_R") {
_rightBlinkIndex = i;
}else if (names[i] == "EyeOpen_L") {
} else if (names[i] == "EyeOpen_L") {
_leftEyeOpenIndex = i;
}else if (names[i] == "EyeOpen_R") {
} else if (names[i] == "EyeOpen_R") {
_rightEyeOpenIndex = i;
} else if (names[i] == "BrowsD_L") {
@ -237,11 +254,15 @@ void Faceshift::receive(const QByteArray& buffer) {
} else if (names[i] == "MouthSmile_R") {
_mouthSmileRightIndex = i;
}
}
break;
}
case fsMsg::MSG_OUT_RIG: {
fsMsgRig* rig = static_cast<fsMsgRig*>(msg.get());
emit rigReceived(*rig);
break;
}
default:
break;
}

View file

@ -57,10 +57,15 @@ public:
void update();
void reset();
signals:
void rigReceived(const fs::fsMsgRig& rig);
public slots:
void setTCPEnabled(bool enabled);
void setUsingRig(bool usingRig);
private slots:
void connectSocket();