mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-05 18:59:56 +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 "ViewFrustum.h"
|
||||||
#include "VoxelSystem.h"
|
#include "VoxelSystem.h"
|
||||||
#include "Webcam.h"
|
#include "Webcam.h"
|
||||||
|
#include "renderer/GeometryCache.h"
|
||||||
#include "ui/ChatEntry.h"
|
#include "ui/ChatEntry.h"
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
|
@ -89,6 +90,7 @@ public:
|
||||||
bool shouldDynamicallySetJitterBuffer() { return _audioJitterBufferSamples == 0; }
|
bool shouldDynamicallySetJitterBuffer() { return _audioJitterBufferSamples == 0; }
|
||||||
|
|
||||||
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
|
||||||
|
GeometryCache* getGeometryCache() { return &_geometryCache; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -318,6 +320,8 @@ private:
|
||||||
int _scaleInLocation;
|
int _scaleInLocation;
|
||||||
int _hmdWarpParamLocation;
|
int _hmdWarpParamLocation;
|
||||||
|
|
||||||
|
GeometryCache _geometryCache;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
Audio _audio;
|
Audio _audio;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,7 +27,8 @@ const float EAR_RIGHT_OFFSET = 1.0;
|
||||||
const float MOUTH_UP_OFFSET = -0.3f;
|
const float MOUTH_UP_OFFSET = -0.3f;
|
||||||
const float HEAD_MOTION_DECAY = 0.1;
|
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 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 EYEBALL_COLOR[3] = { 0.9f, 0.9f, 0.8f };
|
||||||
const float HAIR_SPRING_FORCE = 10.0f;
|
const float HAIR_SPRING_FORCE = 10.0f;
|
||||||
const float HAIR_TORQUE_FORCE = 0.1f;
|
const float HAIR_TORQUE_FORCE = 0.1f;
|
||||||
|
@ -71,7 +72,11 @@ Head::Head(Avatar* owningAvatar) :
|
||||||
_mohawkTriangleFan(NULL),
|
_mohawkTriangleFan(NULL),
|
||||||
_mohawkColors(NULL),
|
_mohawkColors(NULL),
|
||||||
_saccade(0.0f, 0.0f, 0.0f),
|
_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) {
|
if (USING_PHYSICAL_MOHAWK) {
|
||||||
resetHairPhysics();
|
resetHairPhysics();
|
||||||
|
@ -162,6 +167,31 @@ void Head::simulate(float deltaTime, bool isMine) {
|
||||||
|
|
||||||
_browAudioLift *= 0.7f;
|
_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.
|
// based on the nature of the lookat position, determine if the eyes can look / are looking at it.
|
||||||
if (USING_PHYSICAL_MOHAWK) {
|
if (USING_PHYSICAL_MOHAWK) {
|
||||||
updateHairPhysics(deltaTime);
|
updateHairPhysics(deltaTime);
|
||||||
|
@ -534,6 +564,37 @@ void Head::renderEyeBalls() {
|
||||||
_irisProgram->release();
|
_irisProgram->release();
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glDisable(GL_TEXTURE_2D);
|
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) {
|
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {
|
||||||
|
|
|
@ -106,6 +106,10 @@ private:
|
||||||
glm::vec3* _mohawkColors;
|
glm::vec3* _mohawkColors;
|
||||||
glm::vec3 _saccade;
|
glm::vec3 _saccade;
|
||||||
glm::vec3 _saccadeTarget;
|
glm::vec3 _saccadeTarget;
|
||||||
|
float _leftEyeBlink;
|
||||||
|
float _rightEyeBlink;
|
||||||
|
float _leftEyeBlinkVelocity;
|
||||||
|
float _rightEyeBlinkVelocity;
|
||||||
|
|
||||||
static ProgramObject* _irisProgram;
|
static ProgramObject* _irisProgram;
|
||||||
static GLuint _irisTextureID;
|
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