mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 06:53:59 +02:00
Basic blinking.
This commit is contained in:
parent
81d0373bdc
commit
ef7c6ebdc6
5 changed files with 203 additions and 2 deletions
|
@ -33,6 +33,7 @@
|
|||
#include "ViewFrustum.h"
|
||||
#include "VoxelSystem.h"
|
||||
#include "Webcam.h"
|
||||
#include "renderer/GeometryCache.h"
|
||||
#include "ui/ChatEntry.h"
|
||||
|
||||
class QAction;
|
||||
|
@ -89,6 +90,7 @@ public:
|
|||
bool shouldDynamicallySetJitterBuffer() { return _audioJitterBufferSamples == 0; }
|
||||
|
||||
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
||||
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||
|
||||
private slots:
|
||||
|
||||
|
@ -318,6 +320,8 @@ private:
|
|||
int _scaleInLocation;
|
||||
int _hmdWarpParamLocation;
|
||||
|
||||
GeometryCache _geometryCache;
|
||||
|
||||
#ifndef _WIN32
|
||||
Audio _audio;
|
||||
#endif
|
||||
|
|
|
@ -27,7 +27,8 @@ const float EAR_RIGHT_OFFSET = 1.0;
|
|||
const float MOUTH_UP_OFFSET = -0.3f;
|
||||
const float HEAD_MOTION_DECAY = 0.1;
|
||||
const float MINIMUM_EYE_ROTATION_DOT = 0.5f; // based on a dot product: 1.0 is straight ahead, 0.0 is 90 degrees off
|
||||
const float EYEBALL_RADIUS = 0.017;
|
||||
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 = 10.0f;
|
||||
const float HAIR_TORQUE_FORCE = 0.1f;
|
||||
|
@ -71,7 +72,11 @@ Head::Head(Avatar* owningAvatar) :
|
|||
_mohawkTriangleFan(NULL),
|
||||
_mohawkColors(NULL),
|
||||
_saccade(0.0f, 0.0f, 0.0f),
|
||||
_saccadeTarget(0.0f, 0.0f, 0.0f)
|
||||
_saccadeTarget(0.0f, 0.0f, 0.0f),
|
||||
_leftEyeBlink(0.0f),
|
||||
_rightEyeBlink(0.0f),
|
||||
_leftEyeBlinkVelocity(0.0f),
|
||||
_rightEyeBlinkVelocity(0.0f)
|
||||
{
|
||||
if (USING_PHYSICAL_MOHAWK) {
|
||||
resetHairPhysics();
|
||||
|
@ -162,6 +167,31 @@ void Head::simulate(float deltaTime, bool isMine) {
|
|||
|
||||
_browAudioLift *= 0.7f;
|
||||
|
||||
// update eyelid blinking
|
||||
if (_leftEyeBlinkVelocity == 0.0f && _rightEyeBlinkVelocity == 0.0f) {
|
||||
const float BLINK_INTERVAL = 4.0f;
|
||||
if (shouldDo(BLINK_INTERVAL, deltaTime)) {
|
||||
_leftEyeBlinkVelocity = 5.0f;
|
||||
_rightEyeBlinkVelocity = 5.0f;
|
||||
}
|
||||
} else {
|
||||
_leftEyeBlink = glm::clamp(_leftEyeBlink + _leftEyeBlinkVelocity * deltaTime, 0.0f, 1.0f);
|
||||
_rightEyeBlink = glm::clamp(_rightEyeBlink + _rightEyeBlinkVelocity * deltaTime, 0.0f, 1.0f);
|
||||
|
||||
if (_leftEyeBlink == 1.0f) {
|
||||
_leftEyeBlinkVelocity = -5.0f;
|
||||
|
||||
} else if (_leftEyeBlink == 0.0f) {
|
||||
_leftEyeBlinkVelocity = 0.0f;
|
||||
}
|
||||
if (_rightEyeBlink == 1.0f) {
|
||||
_rightEyeBlinkVelocity = -5.0f;
|
||||
|
||||
} else if (_rightEyeBlink == 0.0f) {
|
||||
_rightEyeBlinkVelocity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// based on the nature of the lookat position, determine if the eyes can look / are looking at it.
|
||||
if (USING_PHYSICAL_MOHAWK) {
|
||||
updateHairPhysics(deltaTime);
|
||||
|
@ -534,6 +564,37 @@ void Head::renderEyeBalls() {
|
|||
_irisProgram->release();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
glColor4f(_skinColor.x, _skinColor.y, _skinColor.z, _renderAlpha);
|
||||
|
||||
// left eyelid
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_leftEyePosition.x, _leftEyePosition.y, _leftEyePosition.z); //translate to eyeball position
|
||||
glm::vec3 rotationAxis = glm::axis(orientation);
|
||||
glRotatef(glm::angle(orientation), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
glScalef(EYELID_RADIUS, EYELID_RADIUS, EYELID_RADIUS);
|
||||
glRotatef(-90 * _leftEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
glRotatef(180 * _leftEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
// right eyelid
|
||||
glPushMatrix(); {
|
||||
glTranslatef(_rightEyePosition.x, _rightEyePosition.y, _rightEyePosition.z); //translate to eyeball position
|
||||
glm::vec3 rotationAxis = glm::axis(orientation);
|
||||
glRotatef(glm::angle(orientation), rotationAxis.x, rotationAxis.y, rotationAxis.z);
|
||||
glScalef(EYELID_RADIUS, EYELID_RADIUS, EYELID_RADIUS);
|
||||
glRotatef(-90 * _rightEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
glRotatef(180 * _rightEyeBlink, 1, 0, 0);
|
||||
Application::getInstance()->getGeometryCache()->renderHemisphere(15, 10);
|
||||
}
|
||||
glPopMatrix();
|
||||
|
||||
glDisable(GL_RESCALE_NORMAL);
|
||||
}
|
||||
|
||||
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||
|
|
|
@ -106,6 +106,10 @@ private:
|
|||
glm::vec3* _mohawkColors;
|
||||
glm::vec3 _saccade;
|
||||
glm::vec3 _saccadeTarget;
|
||||
float _leftEyeBlink;
|
||||
float _rightEyeBlink;
|
||||
float _leftEyeBlinkVelocity;
|
||||
float _rightEyeBlinkVelocity;
|
||||
|
||||
static ProgramObject* _irisProgram;
|
||||
static GLuint _irisTextureID;
|
||||
|
|
101
interface/src/renderer/GeometryCache.cpp
Normal file
101
interface/src/renderer/GeometryCache.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
//
|
||||
// GeometryCache.cpp
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 6/21/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "GeometryCache.h"
|
||||
#include "world.h"
|
||||
|
||||
GeometryCache::~GeometryCache() {
|
||||
foreach (const VerticesIndices& vbo, _hemisphereVBOs) {
|
||||
glDeleteBuffers(1, &vbo.first);
|
||||
glDeleteBuffers(1, &vbo.second);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCache::renderHemisphere(int slices, int stacks) {
|
||||
VerticesIndices& vbo = _hemisphereVBOs[SlicesStacks(slices, stacks)];
|
||||
int vertices = slices * (stacks - 1) + 1;
|
||||
int indices = slices * 2 * 3 * (stacks - 2) + slices * 3;
|
||||
if (vbo.first == 0) {
|
||||
GLfloat* vertexData = new GLfloat[vertices * 3];
|
||||
GLfloat* vertex = vertexData;
|
||||
for (int i = 0; i < stacks - 1; i++) {
|
||||
float phi = PIf * 0.5f * i / (stacks - 1), z, radius;
|
||||
sincosf(phi, &z, &radius);
|
||||
|
||||
for (int j = 0; j < slices; j++) {
|
||||
float theta = PIf * 2.0f * j / slices;
|
||||
float x, y;
|
||||
sincosf(theta, &x, &y);
|
||||
x *= radius;
|
||||
y *= radius;
|
||||
|
||||
*(vertex++) = x;
|
||||
*(vertex++) = y;
|
||||
*(vertex++) = z;
|
||||
}
|
||||
}
|
||||
*(vertex++) = 0.0f;
|
||||
*(vertex++) = 0.0f;
|
||||
*(vertex++) = 1.0f;
|
||||
|
||||
glGenBuffers(1, &vbo.first);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||
const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||
delete[] vertexData;
|
||||
|
||||
GLushort* indexData = new GLushort[indices];
|
||||
GLushort* index = indexData;
|
||||
for (int i = 0; i < stacks - 2; i++) {
|
||||
GLushort bottom = i * slices;
|
||||
GLushort top = bottom + slices;
|
||||
for (int j = 0; j < slices; j++) {
|
||||
int next = (j + 1) % slices;
|
||||
|
||||
*(index++) = bottom + j;
|
||||
*(index++) = top + next;
|
||||
*(index++) = top + j;
|
||||
|
||||
*(index++) = bottom + j;
|
||||
*(index++) = bottom + next;
|
||||
*(index++) = top + next;
|
||||
}
|
||||
}
|
||||
GLushort bottom = (stacks - 2) * slices;
|
||||
GLushort top = bottom + slices;
|
||||
for (int i = 0; i < slices; i++) {
|
||||
*(index++) = bottom + i;
|
||||
*(index++) = bottom + (i + 1) % slices;
|
||||
*(index++) = top;
|
||||
}
|
||||
|
||||
glGenBuffers(1, &vbo.second);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.second);
|
||||
const int BYTES_PER_INDEX = sizeof(GLushort);
|
||||
glBufferData(GL_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||
delete[] indexData;
|
||||
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
||||
}
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
glNormalPointer(GL_FLOAT, 0, 0);
|
||||
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
31
interface/src/renderer/GeometryCache.h
Normal file
31
interface/src/renderer/GeometryCache.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// GeometryCache.h
|
||||
// interface
|
||||
//
|
||||
// Created by Andrzej Kapolka on 6/21/13.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __interface__GeometryCache__
|
||||
#define __interface__GeometryCache__
|
||||
|
||||
#include <QHash>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
class GeometryCache {
|
||||
public:
|
||||
|
||||
~GeometryCache();
|
||||
|
||||
void renderHemisphere(int slices, int stacks);
|
||||
|
||||
private:
|
||||
|
||||
typedef QPair<int, int> SlicesStacks;
|
||||
typedef QPair<GLuint, GLuint> VerticesIndices;
|
||||
|
||||
QHash<SlicesStacks, VerticesIndices> _hemisphereVBOs;
|
||||
};
|
||||
|
||||
#endif /* defined(__interface__GeometryCache__) */
|
Loading…
Reference in a new issue