mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 10:07:58 +02:00
Merge pull request #974 from ey6es/blendface
Render blended faces as solid and remove the "Use Faceshift Rig" option (which isn't visible to others).
This commit is contained in:
commit
297652a83b
9 changed files with 25 additions and 87 deletions
|
@ -275,8 +275,6 @@ 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);
|
||||||
|
|
|
@ -199,7 +199,6 @@ 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";
|
||||||
|
|
|
@ -46,12 +46,13 @@ bool BlendFace::render(float alpha) {
|
||||||
glScalef(_owningHead->getScale() * MODEL_SCALE, _owningHead->getScale() * MODEL_SCALE,
|
glScalef(_owningHead->getScale() * MODEL_SCALE, _owningHead->getScale() * MODEL_SCALE,
|
||||||
-_owningHead->getScale() * MODEL_SCALE);
|
-_owningHead->getScale() * MODEL_SCALE);
|
||||||
|
|
||||||
glColor4f(1.0f, 1.0f, 1.0f, alpha);
|
|
||||||
|
|
||||||
// start with the base
|
// start with the base
|
||||||
int vertexCount = _geometry.vertices.size();
|
int vertexCount = _geometry.vertices.size();
|
||||||
|
int normalCount = _geometry.normals.size();
|
||||||
_blendedVertices.resize(vertexCount);
|
_blendedVertices.resize(vertexCount);
|
||||||
|
_blendedNormals.resize(normalCount);
|
||||||
memcpy(_blendedVertices.data(), _geometry.vertices.constData(), vertexCount * sizeof(glm::vec3));
|
memcpy(_blendedVertices.data(), _geometry.vertices.constData(), vertexCount * sizeof(glm::vec3));
|
||||||
|
memcpy(_blendedNormals.data(), _geometry.normals.constData(), normalCount * sizeof(glm::vec3));
|
||||||
|
|
||||||
// blend in each coefficient
|
// blend in each coefficient
|
||||||
const vector<float>& coefficients = _owningHead->getBlendshapeCoefficients();
|
const vector<float>& coefficients = _owningHead->getBlendshapeCoefficients();
|
||||||
|
@ -60,31 +61,44 @@ bool BlendFace::render(float alpha) {
|
||||||
if (coefficient == 0.0f || i >= _geometry.blendshapes.size() || _geometry.blendshapes[i].vertices.isEmpty()) {
|
if (coefficient == 0.0f || i >= _geometry.blendshapes.size() || _geometry.blendshapes[i].vertices.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const glm::vec3* source = _geometry.blendshapes[i].vertices.constData();
|
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
||||||
|
float normalCoefficient = coefficient * NORMAL_COEFFICIENT_SCALE;
|
||||||
|
const glm::vec3* vertex = _geometry.blendshapes[i].vertices.constData();
|
||||||
|
const glm::vec3* normal = _geometry.blendshapes[i].normals.constData();
|
||||||
for (const int* index = _geometry.blendshapes[i].indices.constData(),
|
for (const int* index = _geometry.blendshapes[i].indices.constData(),
|
||||||
*end = index + _geometry.blendshapes[i].indices.size(); index != end; index++, source++) {
|
*end = index + _geometry.blendshapes[i].indices.size(); index != end; index++, vertex++, normal++) {
|
||||||
_blendedVertices[*index] += *source * coefficient;
|
_blendedVertices[*index] += *vertex * coefficient;
|
||||||
|
_blendedNormals[*index] += *normal * normalCoefficient;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use the head skin color
|
||||||
|
glColor4f(_owningHead->getSkinColor().r, _owningHead->getSkinColor().g, _owningHead->getSkinColor().b, alpha);
|
||||||
|
|
||||||
// update the blended vertices
|
// update the blended vertices
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * sizeof(glm::vec3), _blendedVertices.constData());
|
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * sizeof(glm::vec3), _blendedVertices.constData());
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexCount * sizeof(glm::vec3),
|
||||||
|
normalCount * sizeof(glm::vec3), _blendedNormals.constData());
|
||||||
|
|
||||||
// tell OpenGL where to find vertex information
|
// tell OpenGL where to find vertex information
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glNormalPointer(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
// enable normalization under the expectation that the GPU can do it faster
|
||||||
|
glEnable(GL_NORMALIZE);
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iboID);
|
||||||
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, _geometry.quadIndices.size(), GL_UNSIGNED_INT, 0);
|
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, _geometry.quadIndices.size(), GL_UNSIGNED_INT, 0);
|
||||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, _geometry.triangleIndices.size(), GL_UNSIGNED_INT,
|
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, _geometry.triangleIndices.size(), GL_UNSIGNED_INT,
|
||||||
(void*)(_geometry.quadIndices.size() * sizeof(int)));
|
(void*)(_geometry.quadIndices.size() * sizeof(int)));
|
||||||
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glDisable(GL_NORMALIZE);
|
||||||
|
|
||||||
// deactivate vertex arrays after drawing
|
// deactivate vertex arrays after drawing
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
// bind with 0 to switch back to normal operation
|
// bind with 0 to switch back to normal operation
|
||||||
|
@ -129,41 +143,6 @@ glm::vec3 createVec3(const fsVector3f& vector) {
|
||||||
return glm::vec3(vector.x, vector.y, vector.z);
|
return glm::vec3(vector.x, vector.y, vector.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendFace::setRig(const fsMsgRig& rig) {
|
|
||||||
// convert to FBX geometry
|
|
||||||
FBXGeometry geometry;
|
|
||||||
|
|
||||||
for (vector<fsVector4i>::const_iterator it = rig.mesh().m_quads.begin(), end = rig.mesh().m_quads.end(); it != end; it++) {
|
|
||||||
geometry.quadIndices.append(it->x);
|
|
||||||
geometry.quadIndices.append(it->y);
|
|
||||||
geometry.quadIndices.append(it->z);
|
|
||||||
geometry.quadIndices.append(it->w);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vector<fsVector3i>::const_iterator it = rig.mesh().m_tris.begin(), end = rig.mesh().m_tris.end(); it != end; it++) {
|
|
||||||
geometry.triangleIndices.append(it->x);
|
|
||||||
geometry.triangleIndices.append(it->y);
|
|
||||||
geometry.triangleIndices.append(it->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vector<fsVector3f>::const_iterator it = rig.mesh().m_vertex_data.m_vertices.begin(),
|
|
||||||
end = rig.mesh().m_vertex_data.m_vertices.end(); it != end; it++) {
|
|
||||||
geometry.vertices.append(glm::vec3(it->x, it->y, it->z));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vector<fsVertexData>::const_iterator it = rig.blendshapes().begin(), end = rig.blendshapes().end(); it != end; it++) {
|
|
||||||
FBXBlendshape blendshape;
|
|
||||||
for (int i = 0, n = it->m_vertices.size(); i < n; i++) {
|
|
||||||
// subtract the base vertex position; we want the deltas
|
|
||||||
blendshape.vertices.append(createVec3(it->m_vertices[i]) - geometry.vertices[i]);
|
|
||||||
blendshape.indices.append(i);
|
|
||||||
}
|
|
||||||
geometry.blendshapes.append(blendshape);
|
|
||||||
}
|
|
||||||
|
|
||||||
setGeometry(geometry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlendFace::handleModelDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
void BlendFace::handleModelDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||||
if (bytesReceived < bytesTotal && !_modelReply->isFinished()) {
|
if (bytesReceived < bytesTotal && !_modelReply->isFinished()) {
|
||||||
return;
|
return;
|
||||||
|
@ -214,7 +193,8 @@ void BlendFace::setGeometry(const FBXGeometry& geometry) {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
|
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
|
||||||
glBufferData(GL_ARRAY_BUFFER, geometry.vertices.size() * sizeof(glm::vec3), NULL, GL_DYNAMIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, (geometry.vertices.size() + geometry.normals.size()) * sizeof(glm::vec3),
|
||||||
|
NULL, GL_DYNAMIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
_geometry = geometry;
|
_geometry = geometry;
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include <fsbinarystream.h>
|
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "renderer/FBXReader.h"
|
#include "renderer/FBXReader.h"
|
||||||
|
|
||||||
|
@ -36,10 +34,6 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void setModelURL(const QUrl& url);
|
Q_INVOKABLE void setModelURL(const QUrl& url);
|
||||||
const QUrl& getModelURL() const { return _modelURL; }
|
const QUrl& getModelURL() const { return _modelURL; }
|
||||||
|
|
||||||
public slots:
|
|
||||||
|
|
||||||
void setRig(const fs::fsMsgRig& rig);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -61,6 +55,7 @@ private:
|
||||||
|
|
||||||
FBXGeometry _geometry;
|
FBXGeometry _geometry;
|
||||||
QVector<glm::vec3> _blendedVertices;
|
QVector<glm::vec3> _blendedVertices;
|
||||||
|
QVector<glm::vec3> _blendedNormals;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__interface__BlendFace__) */
|
#endif /* defined(__interface__BlendFace__) */
|
||||||
|
|
|
@ -66,6 +66,7 @@ public:
|
||||||
|
|
||||||
float getScale() const { return _scale; }
|
float getScale() const { return _scale; }
|
||||||
glm::vec3 getPosition() const { return _position; }
|
glm::vec3 getPosition() const { return _position; }
|
||||||
|
const glm::vec3& getSkinColor() const { return _skinColor; }
|
||||||
const glm::vec3& getEyePosition() const { return _eyePosition; }
|
const glm::vec3& getEyePosition() const { return _eyePosition; }
|
||||||
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||||
glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||||
|
|
|
@ -59,14 +59,6 @@ MyAvatar::MyAvatar(Node* owningNode) :
|
||||||
_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() {
|
||||||
_head.reset();
|
_head.reset();
|
||||||
_hand.reset();
|
_hand.reset();
|
||||||
|
|
|
@ -15,7 +15,6 @@ 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,17 +87,6 @@ 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,11 +103,6 @@ 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) {
|
||||||
|
@ -214,11 +198,6 @@ void Faceshift::receive(const QByteArray& buffer) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case fsMsg::MSG_OUT_RIG: {
|
|
||||||
fsMsgRig* rig = static_cast<fsMsgRig*>(msg.get());
|
|
||||||
emit rigReceived(*rig);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,15 +60,10 @@ 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:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue