Pupil dilation.

This commit is contained in:
Andrzej Kapolka 2013-09-26 15:48:11 -07:00
parent a44d665767
commit 91999dfe1f
12 changed files with 123 additions and 19 deletions

View file

@ -17,6 +17,7 @@
#include <QFormLayout>
#include <QLineEdit>
#include <QMainWindow>
#include <QSlider>
#include <QStandardPaths>
#include "Application.h"
@ -749,6 +750,10 @@ void Menu::editPreferences() {
faceURL->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Face URL:", faceURL);
QSlider* pupilDilation = new QSlider(Qt::Horizontal);
pupilDilation->setValue(applicationInstance->getAvatar()->getHead().getPupilDilation() * pupilDilation->maximum());
form->addRow("Pupil Dilation:", pupilDilation);
QSpinBox* fieldOfView = new QSpinBox();
fieldOfView->setMaximum(180);
fieldOfView->setMinimum(1);
@ -790,6 +795,8 @@ void Menu::editPreferences() {
Avatar::sendAvatarURLsMessage(avatarVoxelURL, faceModelURL);
applicationInstance->getAvatar()->getHead().setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
_gyroCameraSensitivity = gyroCameraSensitivity->value();
applicationInstance->getAvatar()->setLeanScale(leanScale->value());

View file

@ -770,6 +770,7 @@ void Avatar::loadData(QSettings* settings) {
_voxels.setVoxelURL(settings->value("voxelURL").toUrl());
_head.getBlendFace().setModelURL(settings->value("faceModelURL").toUrl());
_head.setPupilDilation(settings->value("pupilDilation", 0.0f).toFloat());
_leanScale = loadSetting(settings, "leanScale", 0.05f);
@ -822,6 +823,7 @@ void Avatar::saveData(QSettings* set) {
set->setValue("voxelURL", _voxels.getVoxelURL());
set->setValue("faceModelURL", _head.getBlendFace().getModelURL());
set->setValue("pupilDilation", _head.getPupilDilation());
set->setValue("leanScale", _leanScale);
set->setValue("scale", _newScale);

View file

@ -28,7 +28,7 @@ BlendFace::~BlendFace() {
}
ProgramObject BlendFace::_eyeProgram;
GLuint BlendFace::_eyeTextureID;
DilatedTextureCache BlendFace::_eyeTextureCache("resources/images/eye.png", 50, 210);
void BlendFace::init() {
if (!_eyeProgram.isLinked()) {
@ -40,8 +40,6 @@ void BlendFace::init() {
_eyeProgram.bind();
_eyeProgram.setUniformValue("texture", 0);
_eyeProgram.release();
_eyeTextureID = Application::getInstance()->getTextureCache()->getFileTextureID("resources/images/eye.png");
}
}
@ -92,7 +90,9 @@ bool BlendFace::render(float alpha) {
// use texture coordinates only for the eye, for now
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, _eyeTextureID);
_eyeTexture = _eyeTextureCache.getTexture(_owningHead->getPupilDilation());
glBindTexture(GL_TEXTURE_2D, _eyeTexture->getID());
glEnable(GL_TEXTURE_2D);
_eyeProgram.bind();

View file

@ -15,6 +15,7 @@
#include "InterfaceConfig.h"
#include "renderer/FBXReader.h"
#include "renderer/ProgramObject.h"
#include "renderer/TextureCache.h"
class QNetworkReply;
@ -62,8 +63,10 @@ private:
QVector<glm::vec3> _blendedVertices;
QVector<glm::vec3> _blendedNormals;
QSharedPointer<Texture> _eyeTexture;
static ProgramObject _eyeProgram;
static GLuint _eyeTextureID;
static DilatedTextureCache _eyeTextureCache;
};
#endif /* defined(__interface__BlendFace__) */

View file

@ -29,7 +29,7 @@ const float EYEBALL_RADIUS = 0.017;
const float EYELID_RADIUS = 0.019;
const float EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f };
const float HAIR_SPRING_FORCE = 15.0f;
const float HAIR_SPRING_FORCE = 15.0f;
const float HAIR_TORQUE_FORCE = 0.2f;
const float HAIR_GRAVITY_FORCE = 0.001f;
const float HAIR_DRAG = 10.0f;
@ -46,7 +46,7 @@ const float IRIS_PROTRUSION = 0.0145f;
const char IRIS_TEXTURE_FILENAME[] = "resources/images/iris.png";
ProgramObject Head::_irisProgram;
GLuint Head::_irisTextureID;
DilatedTextureCache Head::_irisTextureCache(IRIS_TEXTURE_FILENAME, 53, 127);
int Head::_eyePositionLocation;
Head::Head(Avatar* owningAvatar) :
@ -102,13 +102,6 @@ void Head::init() {
_irisProgram.setUniformValue("texture", 0);
_eyePositionLocation = _irisProgram.uniformLocation("eyePosition");
_irisTextureID = Application::getInstance()->getTextureCache()->getFileTextureID(IRIS_TEXTURE_FILENAME);
glBindTexture(GL_TEXTURE_2D, _irisTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glBindTexture(GL_TEXTURE_2D, 0);
}
_blendFace.init();
}
@ -667,7 +660,12 @@ void Head::renderEyeBalls() {
glPopMatrix();
_irisProgram.bind();
glBindTexture(GL_TEXTURE_2D, _irisTextureID);
_irisTexture = _irisTextureCache.getTexture(_pupilDilation);
glBindTexture(GL_TEXTURE_2D, _irisTexture->getID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glEnable(GL_TEXTURE_2D);
// render left iris

View file

@ -24,6 +24,7 @@
#include "PerlinFace.h"
#include "world.h"
#include "devices/SerialInterface.h"
#include "renderer/TextureCache.h"
enum eyeContactTargets {
LEFT_EYE,
@ -135,8 +136,10 @@ private:
PerlinFace _perlinFace;
BlendFace _blendFace;
QSharedPointer<Texture> _irisTexture;
static ProgramObject _irisProgram;
static GLuint _irisTextureID;
static DilatedTextureCache _irisTextureCache;
static int _eyePositionLocation;
// private methods

View file

@ -248,7 +248,11 @@ void PerlinFace::render() {
Head::_irisProgram.bind();
glBindTexture(GL_TEXTURE_2D, Head::_irisTextureID);
_owningHead->_irisTexture = Head::_irisTextureCache.getTexture(_owningHead->_pupilDilation);
glBindTexture(GL_TEXTURE_2D, _owningHead->_irisTexture->getID());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glEnable(GL_TEXTURE_2D);
orientation = _owningHead->getOrientation();

View file

@ -154,3 +154,44 @@ QOpenGLFramebufferObject* TextureCache::createFramebufferObject() {
return fbo;
}
Texture::Texture() {
glGenTextures(1, &_id);
}
Texture::~Texture() {
glDeleteTextures(1, &_id);
}
DilatedTextureCache::DilatedTextureCache(const QString& filename, int innerRadius, int outerRadius) :
_innerRadius(innerRadius),
_outerRadius(outerRadius)
{
switchToResourcesParentIfRequired();
_image = QImage(filename).convertToFormat(QImage::Format_ARGB32);
}
QSharedPointer<Texture> DilatedTextureCache::getTexture(float dilation) {
QSharedPointer<Texture> texture = _textures.value(dilation);
if (texture.isNull()) {
texture = QSharedPointer<Texture>(new Texture());
QImage dilatedImage = _image;
QPainter painter;
painter.begin(&dilatedImage);
QPainterPath path;
qreal radius = glm::mix(_innerRadius, _outerRadius, dilation);
path.addEllipse(QPointF(_image.width() / 2.0, _image.height() / 2.0), radius, radius);
painter.fillPath(path, Qt::black);
painter.end();
glBindTexture(GL_TEXTURE_2D, texture->getID());
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dilatedImage.width(), dilatedImage.height(), 1,
GL_BGRA, GL_UNSIGNED_BYTE, dilatedImage.constBits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
_textures.insert(dilation, texture);
}
return texture;
}

View file

@ -10,7 +10,11 @@
#define __interface__TextureCache__
#include <QHash>
#include <QImage>
#include <QMap>
#include <QObject>
#include <QSharedPointer>
#include <QWeakPointer>
#include "InterfaceConfig.h"
@ -62,4 +66,36 @@ private:
QOpenGLFramebufferObject* _tertiaryFramebufferObject;
};
/// A simple object wrapper for an OpenGL texture.
class Texture {
public:
Texture();
~Texture();
GLuint getID() const { return _id; }
private:
GLuint _id;
};
/// Caches textures according to pupillary dilation.
class DilatedTextureCache {
public:
DilatedTextureCache(const QString& filename, int innerRadius, int outerRadius);
/// Returns a pointer to a texture with the requested amount of dilation.
QSharedPointer<Texture> getTexture(float dilation);
private:
QImage _image;
int _innerRadius;
int _outerRadius;
QMap<float, QWeakPointer<Texture> > _textures;
};
#endif /* defined(__interface__TextureCache__) */

View file

@ -211,6 +211,9 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
destinationBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float);
}
// pupil dilation
destinationBuffer += packFloatToByte(destinationBuffer, _headData->_pupilDilation, 1.0f);
// leap hand data
destinationBuffer += _handData->encodeRemoteData(destinationBuffer);
@ -345,7 +348,10 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) {
_headData->_blendshapeCoefficients.size() * sizeof(float));
sourceBuffer += _headData->_blendshapeCoefficients.size() * sizeof(float);
}
// pupil dilation
sourceBuffer += unpackFloatFromByte(sourceBuffer, _headData->_pupilDilation, 1.0f);
// leap hand data
if (sourceBuffer - startPosition < numBytes) {
// check passed, bytes match

View file

@ -46,6 +46,9 @@ public:
const std::vector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
float getPupilDilation() const { return _pupilDilation; }
void setPupilDilation(float pupilDilation) { _pupilDilation = pupilDilation; }
void addYaw(float yaw);
void addPitch(float pitch);
void addRoll(float roll);
@ -70,6 +73,7 @@ protected:
float _averageLoudness;
float _browAudioLift;
std::vector<float> _blendshapeCoefficients;
float _pupilDilation;
AvatarData* _owningAvatar;
private:

View file

@ -20,7 +20,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) {
return 1;
case PACKET_TYPE_HEAD_DATA:
return 7;
return 8;
case PACKET_TYPE_AVATAR_URLS:
return 1;