mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 05:58:35 +02:00
Working on reading and rendering the rig from Faceshift.
This commit is contained in:
parent
86307ea67f
commit
f9426cbecc
10 changed files with 193 additions and 9 deletions
|
@ -275,7 +275,8 @@ Menu::Menu() :
|
||||||
appInstance->getGlowEffect(),
|
appInstance->getGlowEffect(),
|
||||||
SLOT(cycleRenderMode()));
|
SLOT(cycleRenderMode()));
|
||||||
|
|
||||||
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UseFaceshiftRig, 0, false,
|
||||||
|
appInstance->getFaceshift(), SLOT(setUsingRig(bool)));
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UsePerlinFace, 0, false);
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::UsePerlinFace, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtVectors, 0, true);
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtVectors, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtIndicator, 0, true);
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::LookAtIndicator, 0, true);
|
||||||
|
|
|
@ -31,6 +31,8 @@ struct ViewFrustumOffset {
|
||||||
float up;
|
float up;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QSettings;
|
||||||
|
|
||||||
class BandwidthDialog;
|
class BandwidthDialog;
|
||||||
class VoxelStatsDialog;
|
class VoxelStatsDialog;
|
||||||
|
|
||||||
|
@ -197,6 +199,7 @@ namespace MenuOption {
|
||||||
const QString TestRaveGlove = "Test Rave Glove";
|
const QString TestRaveGlove = "Test Rave Glove";
|
||||||
const QString TreeStats = "Calculate Tree Stats";
|
const QString TreeStats = "Calculate Tree Stats";
|
||||||
const QString TransmitterDrive = "Transmitter Drive";
|
const QString TransmitterDrive = "Transmitter Drive";
|
||||||
|
const QString UseFaceshiftRig = "Use Faceshift Rig";
|
||||||
const QString UsePerlinFace = "Use Perlin's Face";
|
const QString UsePerlinFace = "Use Perlin's Face";
|
||||||
const QString Quit = "Quit";
|
const QString Quit = "Quit";
|
||||||
const QString Webcam = "Webcam";
|
const QString Webcam = "Webcam";
|
||||||
|
|
94
interface/src/avatar/BlendFace.cpp
Normal file
94
interface/src/avatar/BlendFace.cpp
Normal 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();
|
||||||
|
}
|
47
interface/src/avatar/BlendFace.h
Normal file
47
interface/src/avatar/BlendFace.h
Normal 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__) */
|
|
@ -87,7 +87,8 @@ Head::Head(Avatar* owningAvatar) :
|
||||||
_cameraFollowsHead(false),
|
_cameraFollowsHead(false),
|
||||||
_cameraFollowHeadRate(0.0f),
|
_cameraFollowHeadRate(0.0f),
|
||||||
_face(this),
|
_face(this),
|
||||||
_perlinFace(this)
|
_perlinFace(this),
|
||||||
|
_blendFace(this)
|
||||||
{
|
{
|
||||||
if (USING_PHYSICAL_MOHAWK) {
|
if (USING_PHYSICAL_MOHAWK) {
|
||||||
resetHairPhysics();
|
resetHairPhysics();
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
#include <VoxelConstants.h>
|
#include <VoxelConstants.h>
|
||||||
|
|
||||||
#include "BendyLine.h"
|
#include "BendyLine.h"
|
||||||
|
#include "BlendFace.h"
|
||||||
#include "Face.h"
|
#include "Face.h"
|
||||||
#include "PerlinFace.h"
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
#include "PerlinFace.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "devices/SerialInterface.h"
|
#include "devices/SerialInterface.h"
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ public:
|
||||||
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
|
||||||
|
|
||||||
Face& getFace() { return _face; }
|
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)
|
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; }
|
float getAverageLoudness() const { return _averageLoudness; }
|
||||||
|
@ -128,6 +130,7 @@ private:
|
||||||
float _cameraFollowHeadRate;
|
float _cameraFollowHeadRate;
|
||||||
Face _face;
|
Face _face;
|
||||||
PerlinFace _perlinFace;
|
PerlinFace _perlinFace;
|
||||||
|
BlendFace _blendFace;
|
||||||
|
|
||||||
static ProgramObject _irisProgram;
|
static ProgramObject _irisProgram;
|
||||||
static GLuint _irisTextureID;
|
static GLuint _irisTextureID;
|
||||||
|
|
|
@ -56,7 +56,15 @@ MyAvatar::MyAvatar(Node* owningNode) :
|
||||||
_driveKeys[i] = false;
|
_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() {
|
void MyAvatar::reset() {
|
||||||
|
|
|
@ -15,6 +15,7 @@ class MyAvatar : public Avatar {
|
||||||
public:
|
public:
|
||||||
MyAvatar(Node* owningNode = NULL);
|
MyAvatar(Node* owningNode = NULL);
|
||||||
|
|
||||||
|
void init();
|
||||||
void reset();
|
void reset();
|
||||||
void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity);
|
void simulate(float deltaTime, Transmitter* transmitter, float gyroCameraSensitivity);
|
||||||
void updateFromGyrosAndOrWebcam(bool gyroLook, float pitchFromTouch);
|
void updateFromGyrosAndOrWebcam(bool gyroLook, float pitchFromTouch);
|
||||||
|
@ -87,4 +88,4 @@ public:
|
||||||
void checkForMouseRayTouching();
|
void checkForMouseRayTouching();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "Faceshift.h"
|
#include "Faceshift.h"
|
||||||
|
#include "Menu.h"
|
||||||
|
|
||||||
using namespace fs;
|
using namespace fs;
|
||||||
using namespace std;
|
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() {
|
void Faceshift::connectSocket() {
|
||||||
if (_tcpEnabled) {
|
if (_tcpEnabled) {
|
||||||
qDebug("Faceshift: Connecting...\n");
|
qDebug("Faceshift: Connecting...\n");
|
||||||
|
@ -114,6 +126,11 @@ void Faceshift::noteConnected() {
|
||||||
string message;
|
string message;
|
||||||
fsBinaryStream::encode_message(message, fsMsgSendBlendshapeNames());
|
fsBinaryStream::encode_message(message, fsMsgSendBlendshapeNames());
|
||||||
send(message);
|
send(message);
|
||||||
|
|
||||||
|
// if using faceshift rig, request it
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::UseFaceshiftRig)) {
|
||||||
|
setUsingRig(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Faceshift::noteError(QAbstractSocket::SocketError error) {
|
void Faceshift::noteError(QAbstractSocket::SocketError error) {
|
||||||
|
@ -208,10 +225,10 @@ void Faceshift::receive(const QByteArray& buffer) {
|
||||||
} else if (names[i] == "EyeBlink_R") {
|
} else if (names[i] == "EyeBlink_R") {
|
||||||
_rightBlinkIndex = i;
|
_rightBlinkIndex = i;
|
||||||
|
|
||||||
}else if (names[i] == "EyeOpen_L") {
|
} else if (names[i] == "EyeOpen_L") {
|
||||||
_leftEyeOpenIndex = i;
|
_leftEyeOpenIndex = i;
|
||||||
|
|
||||||
}else if (names[i] == "EyeOpen_R") {
|
} else if (names[i] == "EyeOpen_R") {
|
||||||
_rightEyeOpenIndex = i;
|
_rightEyeOpenIndex = i;
|
||||||
|
|
||||||
} else if (names[i] == "BrowsD_L") {
|
} else if (names[i] == "BrowsD_L") {
|
||||||
|
@ -237,11 +254,15 @@ void Faceshift::receive(const QByteArray& buffer) {
|
||||||
|
|
||||||
} else if (names[i] == "MouthSmile_R") {
|
} else if (names[i] == "MouthSmile_R") {
|
||||||
_mouthSmileRightIndex = i;
|
_mouthSmileRightIndex = i;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case fsMsg::MSG_OUT_RIG: {
|
||||||
|
fsMsgRig* rig = static_cast<fsMsgRig*>(msg.get());
|
||||||
|
emit rigReceived(*rig);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,15 @@ public:
|
||||||
void update();
|
void update();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void rigReceived(const fs::fsMsgRig& rig);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void setTCPEnabled(bool enabled);
|
void setTCPEnabled(bool enabled);
|
||||||
|
void setUsingRig(bool usingRig);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void connectSocket();
|
void connectSocket();
|
||||||
|
|
Loading…
Reference in a new issue