Merge branch 'master' of https://github.com/highfidelity/hifi into voxelEctomy

This commit is contained in:
ZappoMan 2014-12-30 16:49:38 -08:00
commit 2a129b6635
14 changed files with 239 additions and 468 deletions

View file

@ -15,8 +15,8 @@ macro(INCLUDE_DEPENDENCY_INCLUDES)
# include those in our own target # include those in our own target
include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES}) include_directories(SYSTEM ${${TARGET_NAME}_DEPENDENCY_INCLUDES})
endif ()
# set the property on this target so it can be retreived by targets linking to us
# set the property on this target so it can be retreived by targets linking to us set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}")
set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") endif()
endmacro(INCLUDE_DEPENDENCY_INCLUDES) endmacro(INCLUDE_DEPENDENCY_INCLUDES)

View file

@ -27,7 +27,10 @@ macro(LINK_HIFI_LIBRARIES)
# ask the library what its include dependencies are and link them # ask the library what its include dependencies are and link them
get_target_property(LINKED_TARGET_DEPENDENCY_INCLUDES ${HIFI_LIBRARY} DEPENDENCY_INCLUDES) get_target_property(LINKED_TARGET_DEPENDENCY_INCLUDES ${HIFI_LIBRARY} DEPENDENCY_INCLUDES)
list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES})
if(LINKED_TARGET_DEPENDENCY_INCLUDES)
list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES ${LINKED_TARGET_DEPENDENCY_INCLUDES})
endif()
endforeach() endforeach()
endmacro(LINK_HIFI_LIBRARIES) endmacro(LINK_HIFI_LIBRARIES)

View file

@ -1,256 +0,0 @@
//
// Hair.cpp
// interface/src
//
// Created by Philip on June 26, 2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Creates single flexible verlet-integrated strands that can be used for hair/fur/grass
#include <gpu/GPUConfig.h>
#include "Util.h"
#include "world.h"
#include "Hair.h"
const float HAIR_DAMPING = 0.99f;
const float CONSTRAINT_RELAXATION = 10.0f;
const float HAIR_ACCELERATION_COUPLING = 0.045f;
const float HAIR_ANGULAR_VELOCITY_COUPLING = 0.001f;
const float HAIR_ANGULAR_ACCELERATION_COUPLING = 0.001f;
const float HAIR_MAX_LINEAR_ACCELERATION = 4.0f;
const float HAIR_STIFFNESS = 0.00f;
const glm::vec3 HAIR_COLOR1(0.98f, 0.76f, 0.075f);
const glm::vec3 HAIR_COLOR2(0.912f, 0.184f, 0.101f);
Hair::Hair(int strands,
int links,
float radius,
float linkLength,
float hairThickness) :
_strands(strands),
_links(links),
_linkLength(linkLength),
_hairThickness(hairThickness),
_radius(radius),
_acceleration(0.0f),
_angularVelocity(0.0f),
_angularAcceleration(0.0f),
_gravity(DEFAULT_GRAVITY),
_loudness(0.0f)
{
_hairPosition = new glm::vec3[_strands * _links];
_hairOriginalPosition = new glm::vec3[_strands * _links];
_hairLastPosition = new glm::vec3[_strands * _links];
_hairQuadDelta = new glm::vec3[_strands * _links];
_hairNormals = new glm::vec3[_strands * _links];
_hairColors = new glm::vec3[_strands * _links];
_hairIsMoveable = new int[_strands * _links];
_hairConstraints = new int[_strands * _links * HAIR_CONSTRAINTS]; // Hair can link to two others
glm::vec3 thisVertex;
for (int strand = 0; strand < _strands; strand++) {
float strandAngle = randFloat() * PI;
float azimuth = (float)strand / (float)_strands * PI * 2.0f;
float elevation = 0.0f;
glm::vec3 thisStrand(sinf(azimuth) * cosf(elevation), sinf(elevation), -cosf(azimuth) * cosf(elevation));
thisStrand *= _radius;
for (int link = 0; link < _links; link++) {
int vertexIndex = strand * _links + link;
// Clear constraints
for (int link2 = 0; link2 < HAIR_CONSTRAINTS; link2++) {
_hairConstraints[vertexIndex * HAIR_CONSTRAINTS + link2] = -1;
}
if (vertexIndex % _links == 0) {
// start of strand
thisVertex = thisStrand;
} else {
thisVertex+= glm::normalize(thisStrand) * _linkLength;
// Set constraints to vertex before and maybe vertex after in strand
_hairConstraints[vertexIndex * HAIR_CONSTRAINTS] = vertexIndex - 1;
if (link < (_links - 1)) {
_hairConstraints[vertexIndex * HAIR_CONSTRAINTS + 1] = vertexIndex + 1;
}
}
_hairOriginalPosition[vertexIndex] = _hairLastPosition[vertexIndex] = _hairPosition[vertexIndex] = thisVertex;
_hairQuadDelta[vertexIndex] = glm::vec3(cos(strandAngle) * _hairThickness, 0.0f, sin(strandAngle) * _hairThickness);
_hairQuadDelta[vertexIndex] *= ((float)link / _links);
_hairNormals[vertexIndex] = glm::normalize(randVector());
if (randFloat() < elevation / PI_OVER_TWO) {
_hairColors[vertexIndex] = HAIR_COLOR1 * ((float)(link + 1) / (float)_links);
} else {
_hairColors[vertexIndex] = HAIR_COLOR2 * ((float)(link + 1) / (float)_links);
}
}
}
}
Hair::~Hair() {
delete[] _hairPosition;
delete[] _hairOriginalPosition;
delete[] _hairLastPosition;
delete[] _hairQuadDelta;
delete[] _hairNormals;
delete[] _hairColors;
delete[] _hairIsMoveable;
delete[] _hairConstraints;
}
const float SOUND_THRESHOLD = 40.0f;
void Hair::simulate(float deltaTime) {
deltaTime = glm::clamp(deltaTime, 0.0f, 1.0f / 30.0f);
glm::vec3 acceleration = _acceleration;
if (glm::length(acceleration) > HAIR_MAX_LINEAR_ACCELERATION) {
acceleration = glm::normalize(acceleration) * HAIR_MAX_LINEAR_ACCELERATION;
}
for (int strand = 0; strand < _strands; strand++) {
for (int link = 0; link < _links; link++) {
int vertexIndex = strand * _links + link;
if (vertexIndex % _links == 0) {
// Base Joint - no integration
} else {
//
// Vertlet Integration
//
// Add velocity from last position, with damping
glm::vec3 thisPosition = _hairPosition[vertexIndex];
glm::vec3 diff = thisPosition - _hairLastPosition[vertexIndex];
_hairPosition[vertexIndex] += diff * HAIR_DAMPING;
/*
// Resolve collisions with sphere
if (glm::length(_hairPosition[vertexIndex]) < _radius) {
_hairPosition[vertexIndex] += glm::normalize(_hairPosition[vertexIndex]) *
(_radius - glm::length(_hairPosition[vertexIndex]));
} */
// Collide with a conical body descending from the root of the hair
glm::vec3 thisVertex = _hairPosition[vertexIndex];
float depth = -thisVertex.y;
thisVertex.y = 0.0f;
const float BODY_CONE_ANGLE = 0.30;
if (glm::length(thisVertex) < depth * BODY_CONE_ANGLE) {
_hairPosition[vertexIndex] += glm::normalize(thisVertex) * (depth * BODY_CONE_ANGLE - glm::length(thisVertex));
}
// Add random thing driven by loudness
float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 2000.0f : 0.0f;
const float QUIESCENT_LOUDNESS = 0.0f;
_hairPosition[vertexIndex] += randVector() * (QUIESCENT_LOUDNESS + loudnessFactor) * ((float)link / (float)_links);
// Add gravity
const float SCALE_GRAVITY = 0.001f;
_hairPosition[vertexIndex] += _gravity * deltaTime * SCALE_GRAVITY;
// Add linear acceleration
_hairPosition[vertexIndex] -= acceleration * HAIR_ACCELERATION_COUPLING * deltaTime;
// Add stiffness to return to original position
_hairPosition[vertexIndex] += (_hairOriginalPosition[vertexIndex] - _hairPosition[vertexIndex])
* powf(1.0f - (float)link / _links, 2.0f) * HAIR_STIFFNESS;
// Add angular acceleration
const float ANGULAR_VELOCITY_MIN = 0.001f;
if (glm::length(_angularVelocity) > ANGULAR_VELOCITY_MIN) {
glm::vec3 yawVector = _hairPosition[vertexIndex];
glm::vec3 angularVelocity = _angularVelocity * HAIR_ANGULAR_VELOCITY_COUPLING;
glm::vec3 angularAcceleration = _angularAcceleration * HAIR_ANGULAR_ACCELERATION_COUPLING;
yawVector.y = 0.0f;
if (glm::length(yawVector) > EPSILON) {
float radius = glm::length(yawVector);
yawVector = glm::normalize(yawVector);
float angle = atan2f(yawVector.x, -yawVector.z) + PI;
glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(0, 1, 0));
_hairPosition[vertexIndex] -= delta * radius * (angularVelocity.y - angularAcceleration.y) * deltaTime;
}
glm::vec3 pitchVector = _hairPosition[vertexIndex];
pitchVector.x = 0.0f;
if (glm::length(pitchVector) > EPSILON) {
float radius = glm::length(pitchVector);
pitchVector = glm::normalize(pitchVector);
float angle = atan2f(pitchVector.y, -pitchVector.z) + PI;
glm::vec3 delta = glm::vec3(0.0f, 1.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(1, 0, 0));
_hairPosition[vertexIndex] -= delta * radius * (angularVelocity.x - angularAcceleration.x) * deltaTime;
}
glm::vec3 rollVector = _hairPosition[vertexIndex];
rollVector.z = 0.0f;
if (glm::length(rollVector) > EPSILON) {
float radius = glm::length(rollVector);
pitchVector = glm::normalize(rollVector);
float angle = atan2f(rollVector.x, rollVector.y) + PI;
glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(0, 0, 1));
_hairPosition[vertexIndex] -= delta * radius * (angularVelocity.z - angularAcceleration.z) * deltaTime;
}
}
// Impose link constraints
for (int link = 0; link < HAIR_CONSTRAINTS; link++) {
if (_hairConstraints[vertexIndex * HAIR_CONSTRAINTS + link] > -1) {
// If there is a constraint, try to enforce it
glm::vec3 vectorBetween = _hairPosition[_hairConstraints[vertexIndex * HAIR_CONSTRAINTS + link]] - _hairPosition[vertexIndex];
_hairPosition[vertexIndex] += glm::normalize(vectorBetween) * (glm::length(vectorBetween) - _linkLength) * CONSTRAINT_RELAXATION * deltaTime;
}
}
// Store start position for next verlet pass
_hairLastPosition[vertexIndex] = thisPosition;
}
}
}
}
void Hair::render() {
//
// Before calling this function, translate/rotate to the origin of the owning object
//
float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 16.0f : 0.0f;
const int SPARKLE_EVERY = 5;
const float HAIR_SETBACK = 0.0f;
int sparkleIndex = (int) (randFloat() * SPARKLE_EVERY);
glPushMatrix();
glTranslatef(0.0f, 0.0f, HAIR_SETBACK);
glBegin(GL_QUADS);
for (int strand = 0; strand < _strands; strand++) {
for (int link = 0; link < _links - 1; link++) {
int vertexIndex = strand * _links + link;
glm::vec3 thisColor = _hairColors[vertexIndex];
if (sparkleIndex % SPARKLE_EVERY == 0) {
thisColor.x += (1.0f - thisColor.x) * loudnessFactor;
thisColor.y += (1.0f - thisColor.y) * loudnessFactor;
thisColor.z += (1.0f - thisColor.z) * loudnessFactor;
}
glColor3fv(&thisColor.x);
glNormal3fv(&_hairNormals[vertexIndex].x);
glVertex3f(_hairPosition[vertexIndex].x - _hairQuadDelta[vertexIndex].x,
_hairPosition[vertexIndex].y - _hairQuadDelta[vertexIndex].y,
_hairPosition[vertexIndex].z - _hairQuadDelta[vertexIndex].z);
glVertex3f(_hairPosition[vertexIndex].x + _hairQuadDelta[vertexIndex].x,
_hairPosition[vertexIndex].y + _hairQuadDelta[vertexIndex].y,
_hairPosition[vertexIndex].z + _hairQuadDelta[vertexIndex].z);
glVertex3f(_hairPosition[vertexIndex + 1].x + _hairQuadDelta[vertexIndex].x,
_hairPosition[vertexIndex + 1].y + _hairQuadDelta[vertexIndex].y,
_hairPosition[vertexIndex + 1].z + _hairQuadDelta[vertexIndex].z);
glVertex3f(_hairPosition[vertexIndex + 1].x - _hairQuadDelta[vertexIndex].x,
_hairPosition[vertexIndex + 1].y - _hairQuadDelta[vertexIndex].y,
_hairPosition[vertexIndex + 1].z - _hairQuadDelta[vertexIndex].z);
sparkleIndex++;
}
}
glEnd();
glPopMatrix();
}

View file

@ -1,70 +0,0 @@
//
// Hair.h
// interface/src
//
// Created by Philip on June 26, 2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Hair_h
#define hifi_Hair_h
#include <iostream>
#include <glm/glm.hpp>
#include <SharedUtil.h>
#include "GeometryUtil.h"
#include "InterfaceConfig.h"
#include "Util.h"
const int HAIR_CONSTRAINTS = 2;
const int DEFAULT_HAIR_STRANDS = 20;
const int DEFAULT_HAIR_LINKS = 11;
const float DEFAULT_HAIR_RADIUS = 0.075f;
const float DEFAULT_HAIR_LINK_LENGTH = 0.1f;
const float DEFAULT_HAIR_THICKNESS = 0.07f;
const glm::vec3 DEFAULT_GRAVITY(0.0f, -9.8f, 0.0f);
class Hair {
public:
Hair(int strands = DEFAULT_HAIR_STRANDS,
int links = DEFAULT_HAIR_LINKS,
float radius = DEFAULT_HAIR_RADIUS,
float linkLength = DEFAULT_HAIR_LINK_LENGTH,
float hairThickness = DEFAULT_HAIR_THICKNESS);
~Hair();
void simulate(float deltaTime);
void render();
void setAcceleration(const glm::vec3& acceleration) { _acceleration = acceleration; }
void setAngularVelocity(const glm::vec3& angularVelocity) { _angularVelocity = angularVelocity; }
void setAngularAcceleration(const glm::vec3& angularAcceleration) { _angularAcceleration = angularAcceleration; }
void setLoudness(const float loudness) { _loudness = loudness; }
private:
int _strands;
int _links;
float _linkLength;
float _hairThickness;
float _radius;
glm::vec3* _hairPosition;
glm::vec3* _hairOriginalPosition;
glm::vec3* _hairLastPosition;
glm::vec3* _hairQuadDelta;
glm::vec3* _hairNormals;
glm::vec3* _hairColors;
int* _hairIsMoveable;
int* _hairConstraints;
glm::vec3 _acceleration;
glm::vec3 _angularVelocity;
glm::vec3 _angularAcceleration;
glm::vec3 _gravity;
float _loudness;
};
#endif // hifi_Hair_h

View file

@ -635,9 +635,6 @@ Menu::Menu() :
connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled())); connect(appInstance->getAudio(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
QMenu* experimentalOptionsMenu = developerMenu->addMenu("Experimental");
addCheckableActionToQMenuAndActionHash(experimentalOptionsMenu, MenuOption::StringHair, 0, false);
addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel,
Qt::CTRL | Qt::SHIFT | Qt::Key_V, Qt::CTRL | Qt::SHIFT | Qt::Key_V,
this, this,

View file

@ -475,7 +475,6 @@ namespace MenuOption {
const QString Stats = "Stats"; const QString Stats = "Stats";
const QString StereoAudio = "Stereo Audio"; const QString StereoAudio = "Stereo Audio";
const QString StopAllScripts = "Stop All Scripts"; const QString StopAllScripts = "Stop All Scripts";
const QString StringHair = "String Hair";
const QString SuppressShortTimings = "Suppress Timings Less than 10ms"; const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
const QString TestPing = "Test Ping"; const QString TestPing = "Test Ping";
const QString ToolWindow = "Tool Window"; const QString ToolWindow = "Tool Window";

View file

@ -191,14 +191,6 @@ void Avatar::simulate(float deltaTime) {
head->setScale(_scale); head->setScale(_scale);
head->simulate(deltaTime, false, _shouldRenderBillboard); head->simulate(deltaTime, false, _shouldRenderBillboard);
} }
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
PerformanceTimer perfTimer("hair");
_hair.setAcceleration(getAcceleration() * getHead()->getFinalOrientationInWorldFrame());
_hair.setAngularVelocity((getAngularVelocity() + getHead()->getAngularVelocity()) * getHead()->getFinalOrientationInWorldFrame());
_hair.setAngularAcceleration(getAngularAcceleration() * getHead()->getFinalOrientationInWorldFrame());
_hair.setLoudness((float) getHeadData()->getAudioLoudness());
_hair.simulate(deltaTime);
}
} }
// update animation for display name fade in/out // update animation for display name fade in/out
@ -543,18 +535,6 @@ void Avatar::renderBody(RenderMode renderMode, bool postLighting, float glowLeve
} }
} }
getHead()->render(1.0f, modelRenderMode, postLighting); getHead()->render(1.0f, modelRenderMode, postLighting);
if (!postLighting && Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
// Render Hair
glPushMatrix();
glm::vec3 headPosition = getHead()->getPosition();
glTranslatef(headPosition.x, headPosition.y, headPosition.z);
const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame();
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
_hair.render();
glPopMatrix();
}
} }
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const { bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {

View file

@ -19,7 +19,6 @@
#include <AvatarData.h> #include <AvatarData.h>
#include "Hair.h"
#include "Hand.h" #include "Hand.h"
#include "Head.h" #include "Head.h"
#include "InterfaceConfig.h" #include "InterfaceConfig.h"
@ -34,10 +33,6 @@ static const float RESCALING_TOLERANCE = .02f;
extern const float CHAT_MESSAGE_SCALE; extern const float CHAT_MESSAGE_SCALE;
extern const float CHAT_MESSAGE_HEIGHT; extern const float CHAT_MESSAGE_HEIGHT;
const int HAIR_STRANDS = 150; // Number of strands of hair
const int HAIR_LINKS = 10; // Number of links in a hair strand
const int HAIR_MAX_CONSTRAINTS = 2; // Hair verlet is connected to at most how many others
enum DriveKeys { enum DriveKeys {
FWD = 0, FWD = 0,
BACK, BACK,
@ -187,7 +182,6 @@ signals:
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
protected: protected:
Hair _hair;
SkeletonModel _skeletonModel; SkeletonModel _skeletonModel;
glm::vec3 _skeletonOffset; glm::vec3 _skeletonOffset;
QVector<Model*> _attachmentModels; QVector<Model*> _attachmentModels;

View file

@ -225,17 +225,6 @@ void MyAvatar::simulate(float deltaTime) {
head->simulate(deltaTime, true); head->simulate(deltaTime, true);
} }
{
PerformanceTimer perfTimer("hair");
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
_hair.setAcceleration(getAcceleration() * getHead()->getFinalOrientationInWorldFrame());
_hair.setAngularVelocity((getAngularVelocity() + getHead()->getAngularVelocity()) * getHead()->getFinalOrientationInWorldFrame());
_hair.setAngularAcceleration(getAngularAcceleration() * getHead()->getFinalOrientationInWorldFrame());
_hair.setLoudness((float)getHeadData()->getAudioLoudness());
_hair.simulate(deltaTime);
}
}
{ {
PerformanceTimer perfTimer("physics"); PerformanceTimer perfTimer("physics");
const float minError = 0.00001f; const float minError = 0.00001f;
@ -1139,18 +1128,6 @@ void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLe
const glm::vec3 cameraPos = camera->getPosition(); const glm::vec3 cameraPos = camera->getPosition();
if (shouldRenderHead(cameraPos, renderMode)) { if (shouldRenderHead(cameraPos, renderMode)) {
getHead()->render(1.0f, modelRenderMode, postLighting); getHead()->render(1.0f, modelRenderMode, postLighting);
if (!postLighting && Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
// Render Hair
glPushMatrix();
glm::vec3 headPosition = getHead()->getPosition();
glTranslatef(headPosition.x, headPosition.y, headPosition.z);
const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame();
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
_hair.render();
glPopMatrix();
}
} }
if (postLighting) { if (postLighting) {
getHand()->render(true, modelRenderMode); getHand()->render(true, modelRenderMode);

View file

@ -105,7 +105,7 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r,
} }
} }
void renderReticle(glm::quat orientation, float alpha) { void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) {
glPushMatrix(); { glPushMatrix(); {
glm::vec3 axis = glm::axis(orientation); glm::vec3 axis = glm::axis(orientation);
glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z); glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z);
@ -114,9 +114,12 @@ void renderReticle(glm::quat orientation, float alpha) {
glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f); glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f);
glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f); glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f);
glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha); glColor4f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha);
if (_reticleQuad == GeometryCache::UNKNOWN_QUAD_ID) {
_reticleQuad = DependencyManager::get<GeometryCache>()->allocateQuad();
}
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomLeft, bottomRight, topRight, DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomLeft, bottomRight, topRight,
glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f),
glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f)); glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), _reticleQuad);
} glPopMatrix(); } glPopMatrix();
} }
@ -126,8 +129,13 @@ ApplicationOverlay::ApplicationOverlay() :
_lastMouseMove(0), _lastMouseMove(0),
_alpha(1.0f), _alpha(1.0f),
_oculusUIRadius(1.0f), _oculusUIRadius(1.0f),
_crosshairTexture(0) { _crosshairTexture(0),
_reticleQuad(GeometryCache::UNKNOWN_QUAD_ID),
_magnifierQuad(GeometryCache::UNKNOWN_QUAD_ID),
_audioRedQuad(GeometryCache::UNKNOWN_QUAD_ID),
_audioGreenQuad(GeometryCache::UNKNOWN_QUAD_ID),
_audioBlueQuad(GeometryCache::UNKNOWN_QUAD_ID)
{
memset(_reticleActive, 0, sizeof(_reticleActive)); memset(_reticleActive, 0, sizeof(_reticleActive));
memset(_magActive, 0, sizeof(_reticleActive)); memset(_magActive, 0, sizeof(_reticleActive));
memset(_magSizeMult, 0, sizeof(_magSizeMult)); memset(_magSizeMult, 0, sizeof(_magSizeMult));
@ -389,12 +397,17 @@ void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float as
glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]); glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]);
if (_reticleQuad == GeometryCache::UNKNOWN_QUAD_ID) {
_reticleQuad = DependencyManager::get<GeometryCache>()->allocateQuad();
}
DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance), DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance),
glm::vec3(x + mouseX + reticleSize, y + mouseY, -distance), glm::vec3(x + mouseX + reticleSize, y + mouseY, -distance),
glm::vec3(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance), glm::vec3(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance),
glm::vec3(x + mouseX, y + mouseY - reticleSize, -distance), glm::vec3(x + mouseX, y + mouseY - reticleSize, -distance),
glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f),
glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f)); glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f),
_reticleQuad);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
@ -696,7 +709,7 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) {
} }
//Renders a small magnification of the currently bound texture at the coordinates //Renders a small magnification of the currently bound texture at the coordinates
void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const { void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
GLCanvas::SharedPointer glCanvas = DependencyManager::get<GLCanvas>(); GLCanvas::SharedPointer glCanvas = DependencyManager::get<GLCanvas>();
const int widgetWidth = glCanvas->width(); const int widgetWidth = glCanvas->width();
@ -742,11 +755,16 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool
} }
glColor4f(1.0f, 1.0f, 1.0f, _alpha); glColor4f(1.0f, 1.0f, 1.0f, _alpha);
if (_magnifierQuad == GeometryCache::UNKNOWN_QUAD_ID) {
_magnifierQuad = DependencyManager::get<GeometryCache>()->allocateQuad();
}
DependencyManager::get<GeometryCache>()->renderQuad(bottomLeft, bottomRight, topRight, topLeft, DependencyManager::get<GeometryCache>()->renderQuad(bottomLeft, bottomRight, topRight, topLeft,
glm::vec2(magnifyULeft, magnifyVBottom), glm::vec2(magnifyULeft, magnifyVBottom),
glm::vec2(magnifyURight, magnifyVBottom), glm::vec2(magnifyURight, magnifyVBottom),
glm::vec2(magnifyURight, magnifyVTop), glm::vec2(magnifyURight, magnifyVTop),
glm::vec2(magnifyULeft, magnifyVTop)); glm::vec2(magnifyULeft, magnifyVTop),
_magnifierQuad);
} glPopMatrix(); } glPopMatrix();
} }
@ -845,10 +863,14 @@ void ApplicationOverlay::renderAudioMeter() {
glColor3f(1, 1, 1); glColor3f(1, 1, 1);
} }
// Draw Red Quad // Draw Red Quad
if (_audioRedQuad == GeometryCache::UNKNOWN_QUAD_ID) {
_audioRedQuad = DependencyManager::get<GeometryCache>()->allocateQuad();
}
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START,
audioMeterY + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET,
audioLevel - AUDIO_RED_START, audioLevel - AUDIO_RED_START,
AUDIO_METER_HEIGHT - AUDIO_METER_INSET); AUDIO_METER_HEIGHT - AUDIO_METER_INSET,
_audioRedQuad);
audioLevel = AUDIO_RED_START; audioLevel = AUDIO_RED_START;
} }
@ -860,10 +882,14 @@ void ApplicationOverlay::renderAudioMeter() {
glColor3f(1, 1, 1); glColor3f(1, 1, 1);
} }
// Draw Green Quad // Draw Green Quad
if (_audioGreenQuad == GeometryCache::UNKNOWN_QUAD_ID) {
_audioGreenQuad = DependencyManager::get<GeometryCache>()->allocateQuad();
}
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START,
audioMeterY + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET,
audioLevel - AUDIO_GREEN_START, audioLevel - AUDIO_GREEN_START,
AUDIO_METER_HEIGHT - AUDIO_METER_INSET); AUDIO_METER_HEIGHT - AUDIO_METER_INSET,
_audioGreenQuad);
audioLevel = AUDIO_GREEN_START; audioLevel = AUDIO_GREEN_START;
} }
@ -874,9 +900,13 @@ void ApplicationOverlay::renderAudioMeter() {
glColor3f(1, 1, 1); glColor3f(1, 1, 1);
} }
// Draw Blue (low level) quad // Draw Blue (low level) quad
if (_audioBlueQuad == GeometryCache::UNKNOWN_QUAD_ID) {
_audioBlueQuad = DependencyManager::get<GeometryCache>()->allocateQuad();
}
DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET, DependencyManager::get<GeometryCache>()->renderQuad(AUDIO_METER_X + AUDIO_METER_INSET,
audioMeterY + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET,
audioLevel, AUDIO_METER_HEIGHT - AUDIO_METER_INSET); audioLevel, AUDIO_METER_HEIGHT - AUDIO_METER_INSET,
_audioBlueQuad);
} }
void ApplicationOverlay::renderStatsAndLogs() { void ApplicationOverlay::renderStatsAndLogs() {

View file

@ -79,8 +79,9 @@ private:
VerticesIndices _vbo; VerticesIndices _vbo;
}; };
void renderReticle(glm::quat orientation, float alpha);
void renderPointers();; void renderPointers();;
void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) const; void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder);
void renderControllerPointers(); void renderControllerPointers();
void renderPointersOculus(const glm::vec3& eyePos); void renderPointersOculus(const glm::vec3& eyePos);
@ -106,6 +107,12 @@ private:
float _trailingAudioLoudness; float _trailingAudioLoudness;
GLuint _crosshairTexture; GLuint _crosshairTexture;
int _reticleQuad;
int _magnifierQuad;
int _audioRedQuad;
int _audioGreenQuad;
int _audioBlueQuad;
}; };
#endif // hifi_ApplicationOverlay_h #endif // hifi_ApplicationOverlay_h

View file

@ -18,7 +18,6 @@
#include "EntityTreeElement.h" #include "EntityTreeElement.h"
#include "ModelEntityItem.h" #include "ModelEntityItem.h"
const QString ModelEntityItem::DEFAULT_MODEL_URL = QString(""); const QString ModelEntityItem::DEFAULT_MODEL_URL = QString("");
const QString ModelEntityItem::DEFAULT_ANIMATION_URL = QString(""); const QString ModelEntityItem::DEFAULT_ANIMATION_URL = QString("");
const float ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f; const float ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f;
@ -33,7 +32,7 @@ EntityItem* ModelEntityItem::factory(const EntityItemID& entityID, const EntityI
ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) : ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
EntityItem(entityItemID, properties) EntityItem(entityItemID, properties)
{ {
_type = EntityTypes::Model; _type = EntityTypes::Model;
setProperties(properties); setProperties(properties);
_lastAnimated = usecTimestampNow(); _lastAnimated = usecTimestampNow();
_jointMappingCompleted = false; _jointMappingCompleted = false;
@ -343,9 +342,6 @@ QVector<glm::quat> ModelEntityItem::getAnimationFrame() {
Animation* myAnimation = getAnimation(_animationURL); Animation* myAnimation = getAnimation(_animationURL);
QVector<FBXAnimationFrame> frames = myAnimation->getFrames(); QVector<FBXAnimationFrame> frames = myAnimation->getFrames();
int frameCount = frames.size(); int frameCount = frames.size();
if (_animationLoop.getMaxFrameIndexHint() != frameCount) {
_animationLoop.setMaxFrameIndexHint(frameCount);
}
if (frameCount > 0) { if (frameCount > 0) {
int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount; int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount;
if (animationFrameIndex < 0 || animationFrameIndex > frameCount) { if (animationFrameIndex < 0 || animationFrameIndex > frameCount) {

View file

@ -23,7 +23,13 @@
#include "TextureCache.h" #include "TextureCache.h"
#include "GeometryCache.h" #include "GeometryCache.h"
GeometryCache::GeometryCache() { //#define WANT_DEBUG
const int GeometryCache::UNKNOWN_QUAD_ID = -1;
GeometryCache::GeometryCache() :
_nextQuadID(0)
{
} }
GeometryCache::~GeometryCache() { GeometryCache::~GeometryCache() {
@ -661,27 +667,49 @@ void GeometryCache::renderWireCube(float size) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottomRight) { void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, int quadID) {
Vec2Pair key(topLeft, bottomRight);
VerticesIndices& vbo = _quad2DVBOs[key]; bool registeredQuad = (quadID != UNKNOWN_QUAD_ID);
Vec2Pair key(minCorner, maxCorner);
VerticesIndices& vbo = registeredQuad ? _registeredQuadVBOs[quadID] : _quad2DVBOs[key];
// if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed
if (registeredQuad && vbo.first != 0) {
Vec2Pair& lastKey = _lastRegisteredQuad2D[quadID];
if (lastKey != key) {
glDeleteBuffers(1, &vbo.first);
glDeleteBuffers(1, &vbo.second);
vbo.first = vbo.second = 0;
#ifdef WANT_DEBUG
qDebug() << "renderQuad() vec2... RELEASING REGISTERED QUAD";
#endif // def WANT_DEBUG
}
#ifdef WANT_DEBUG
else {
qDebug() << "renderQuad() vec2... REUSING PREVIOUSLY REGISTERED QUAD";
}
#endif // def WANT_DEBUG
}
const int FLOATS_PER_VERTEX = 2; const int FLOATS_PER_VERTEX = 2;
const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat); const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat);
const int vertices = 4; const int vertices = 4;
const int indices = 4; const int indices = 4;
if (vbo.first == 0) { if (vbo.first == 0) {
_lastRegisteredQuad2D[quadID] = key;
int vertexPoints = vertices * FLOATS_PER_VERTEX; int vertexPoints = vertices * FLOATS_PER_VERTEX;
GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices, no normals because we're a 2D quad GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices, no normals because we're a 2D quad
GLfloat* vertex = vertexData; GLfloat* vertex = vertexData;
static GLubyte cannonicalIndices[indices] = {0, 1, 2, 3}; static GLubyte cannonicalIndices[indices] = {0, 1, 2, 3};
vertex[0] = topLeft.x; vertex[0] = minCorner.x;
vertex[1] = topLeft.y; vertex[1] = minCorner.y;
vertex[2] = bottomRight.x; vertex[2] = maxCorner.x;
vertex[3] = topLeft.y; vertex[3] = minCorner.y;
vertex[4] = bottomRight.x; vertex[4] = maxCorner.x;
vertex[5] = bottomRight.y; vertex[5] = maxCorner.y;
vertex[6] = topLeft.x; vertex[6] = minCorner.x;
vertex[7] = bottomRight.y; vertex[7] = maxCorner.y;
glGenBuffers(1, &vbo.first); glGenBuffers(1, &vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
@ -700,7 +728,11 @@ void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottom
delete[] indexData; delete[] indexData;
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qDebug() << "new quad VBO made -- _quad2DVBOs.size():" << _quad2DVBOs.size(); if (quadID == UNKNOWN_QUAD_ID) {
qDebug() << "new quad VBO made -- _quad2DVBOs.size():" << _quad2DVBOs.size();
} else {
qDebug() << "new registered quad VBO made -- _registeredQuadVBOs.size():" << _registeredQuadVBOs.size();
}
#endif #endif
} else { } else {
@ -717,41 +749,62 @@ void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottom
} }
void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottomRight, void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomRight) { const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, int quadID) {
Vec2PairPair key(Vec2Pair(topLeft, bottomRight), Vec2Pair(texCoordTopLeft, texCoordBottomRight));
bool registeredQuad = (quadID != UNKNOWN_QUAD_ID);
Vec2PairPair key(Vec2Pair(minCorner, maxCorner), Vec2Pair(texCoordMinCorner, texCoordMaxCorner));
VerticesIndices& vbo = registeredQuad ? _registeredQuadVBOs[quadID] : _quad2DTextureVBOs[key];
VerticesIndices& vbo = _quad2DTextureVBOs[key]; // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed
if (registeredQuad && vbo.first != 0) {
Vec2PairPair& lastKey = _lastRegisteredQuad2DTexture[quadID];
if (lastKey != key) {
glDeleteBuffers(1, &vbo.first);
glDeleteBuffers(1, &vbo.second);
vbo.first = vbo.second = 0;
#ifdef WANT_DEBUG
qDebug() << "renderQuad() vec2 + texture... RELEASING REGISTERED QUAD";
#endif // def WANT_DEBUG
}
#ifdef WANT_DEBUG
else {
qDebug() << "renderQuad() vec2 + texture... REUSING PREVIOUSLY REGISTERED QUAD";
}
#endif // def WANT_DEBUG
}
const int FLOATS_PER_VERTEX = 2 * 2; // text coords & vertices const int FLOATS_PER_VERTEX = 2 * 2; // text coords & vertices
const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat); const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat);
const int vertices = 4; const int vertices = 4;
const int indices = 4; const int indices = 4;
if (vbo.first == 0) { if (vbo.first == 0) {
_lastRegisteredQuad2DTexture[quadID] = key;
int vertexPoints = vertices * FLOATS_PER_VERTEX; int vertexPoints = vertices * FLOATS_PER_VERTEX;
GLfloat* vertexData = new GLfloat[vertexPoints]; // text coords & vertices GLfloat* vertexData = new GLfloat[vertexPoints]; // text coords & vertices
GLfloat* vertex = vertexData; GLfloat* vertex = vertexData;
static GLubyte cannonicalIndices[indices] = {0, 1, 2, 3}; static GLubyte cannonicalIndices[indices] = {0, 1, 2, 3};
int v = 0; int v = 0;
vertex[v++] = topLeft.x; vertex[v++] = minCorner.x;
vertex[v++] = topLeft.y; vertex[v++] = minCorner.y;
vertex[v++] = texCoordTopLeft.x; vertex[v++] = texCoordMinCorner.x;
vertex[v++] = texCoordTopLeft.y; vertex[v++] = texCoordMinCorner.y;
vertex[v++] = bottomRight.x; vertex[v++] = maxCorner.x;
vertex[v++] = topLeft.y; vertex[v++] = minCorner.y;
vertex[v++] = texCoordBottomRight.x; vertex[v++] = texCoordMaxCorner.x;
vertex[v++] = texCoordTopLeft.y; vertex[v++] = texCoordMinCorner.y;
vertex[v++] = bottomRight.x; vertex[v++] = maxCorner.x;
vertex[v++] = bottomRight.y; vertex[v++] = maxCorner.y;
vertex[v++] = texCoordBottomRight.x; vertex[v++] = texCoordMaxCorner.x;
vertex[v++] = texCoordBottomRight.y; vertex[v++] = texCoordMaxCorner.y;
vertex[v++] = topLeft.x; vertex[v++] = minCorner.x;
vertex[v++] = bottomRight.y; vertex[v++] = maxCorner.y;
vertex[v++] = texCoordTopLeft.x; vertex[v++] = texCoordMinCorner.x;
vertex[v++] = texCoordBottomRight.y; vertex[v++] = texCoordMaxCorner.y;
glGenBuffers(1, &vbo.first); glGenBuffers(1, &vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
@ -770,7 +823,11 @@ void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottom
delete[] indexData; delete[] indexData;
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qDebug() << "new quad + texture VBO made -- _quad2DTextureVBOs.size():" << _quad2DTextureVBOs.size(); if (quadID == UNKNOWN_QUAD_ID) {
qDebug() << "new quad + texture VBO made -- _quad2DTextureVBOs.size():" << _quad2DTextureVBOs.size();
} else {
qDebug() << "new registered quad VBO made -- _registeredQuadVBOs.size():" << _registeredQuadVBOs.size();
}
#endif #endif
} else { } else {
glBindBuffer(GL_ARRAY_BUFFER, vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
@ -791,35 +848,57 @@ void GeometryCache::renderQuad(const glm::vec2& topLeft, const glm::vec2& bottom
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight) { void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, int quadID) {
Vec3Pair key(topLeft, bottomRight);
VerticesIndices& vbo = _quad3DVBOs[key]; bool registeredQuad = (quadID != UNKNOWN_QUAD_ID);
Vec3Pair key(minCorner, maxCorner);
VerticesIndices& vbo = registeredQuad ? _registeredQuadVBOs[quadID] : _quad3DVBOs[key];
// if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed
if (registeredQuad && vbo.first != 0) {
Vec3Pair& lastKey = _lastRegisteredQuad3D[quadID];
if (lastKey != key) {
glDeleteBuffers(1, &vbo.first);
glDeleteBuffers(1, &vbo.second);
vbo.first = vbo.second = 0;
#ifdef WANT_DEBUG
qDebug() << "renderQuad() vec3... RELEASING REGISTERED QUAD";
#endif // def WANT_DEBUG
}
#ifdef WANT_DEBUG
else {
qDebug() << "renderQuad() vec3... REUSING PREVIOUSLY REGISTERED QUAD";
}
#endif // def WANT_DEBUG
}
const int FLOATS_PER_VERTEX = 3; const int FLOATS_PER_VERTEX = 3;
const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat); const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat);
const int vertices = 4; const int vertices = 4;
const int indices = 4; const int indices = 4;
if (vbo.first == 0) { if (vbo.first == 0) {
_lastRegisteredQuad3D[quadID] = key;
int vertexPoints = vertices * FLOATS_PER_VERTEX; int vertexPoints = vertices * FLOATS_PER_VERTEX;
GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices GLfloat* vertexData = new GLfloat[vertexPoints]; // only vertices
GLfloat* vertex = vertexData; GLfloat* vertex = vertexData;
static GLubyte cannonicalIndices[indices] = {0, 1, 2, 3}; static GLubyte cannonicalIndices[indices] = {0, 1, 2, 3};
int v = 0; int v = 0;
vertex[v++] = topLeft.x; vertex[v++] = minCorner.x;
vertex[v++] = topLeft.y; vertex[v++] = minCorner.y;
vertex[v++] = topLeft.z; vertex[v++] = minCorner.z;
vertex[v++] = bottomRight.x; vertex[v++] = maxCorner.x;
vertex[v++] = topLeft.y; vertex[v++] = minCorner.y;
vertex[v++] = topLeft.z; vertex[v++] = minCorner.z;
vertex[v++] = bottomRight.x; vertex[v++] = maxCorner.x;
vertex[v++] = bottomRight.y; vertex[v++] = maxCorner.y;
vertex[v++] = bottomRight.z; vertex[v++] = maxCorner.z;
vertex[v++] = topLeft.x; vertex[v++] = minCorner.x;
vertex[v++] = bottomRight.y; vertex[v++] = maxCorner.y;
vertex[v++] = bottomRight.z; vertex[v++] = maxCorner.z;
glGenBuffers(1, &vbo.first); glGenBuffers(1, &vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
@ -838,7 +917,11 @@ void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottom
delete[] indexData; delete[] indexData;
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qDebug() << "new quad VBO made -- _quad3DVBOs.size():" << _quad3DVBOs.size(); if (quadID == UNKNOWN_QUAD_ID) {
qDebug() << "new quad VBO made -- _quad3DVBOs.size():" << _quad3DVBOs.size();
} else {
qDebug() << "new registered quad VBO made -- _registeredQuadVBOs.size():" << _registeredQuadVBOs.size();
}
#endif #endif
} else { } else {
@ -858,7 +941,7 @@ void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottom
void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft, void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight, const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft, const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight) { const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight, int quadID) {
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qDebug() << "renderQuad() vec3 + texture VBO..."; qDebug() << "renderQuad() vec3 + texture VBO...";
@ -869,15 +952,35 @@ void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottom
qDebug() << " texCoordTopLeft:" << texCoordTopLeft; qDebug() << " texCoordTopLeft:" << texCoordTopLeft;
qDebug() << " texCoordBottomRight:" << texCoordBottomRight; qDebug() << " texCoordBottomRight:" << texCoordBottomRight;
#endif //def WANT_DEBUG #endif //def WANT_DEBUG
Vec3PairVec2Pair key(Vec3Pair(topLeft, bottomRight), Vec2Pair(texCoordTopLeft, texCoordBottomRight));
VerticesIndices& vbo = _quad3DTextureVBOs[key]; bool registeredQuad = (quadID != UNKNOWN_QUAD_ID);
Vec3PairVec2Pair key(Vec3Pair(topLeft, bottomRight), Vec2Pair(texCoordTopLeft, texCoordBottomRight));
VerticesIndices& vbo = registeredQuad ? _registeredQuadVBOs[quadID] : _quad3DTextureVBOs[key];
// if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed
if (registeredQuad && vbo.first != 0) {
Vec3PairVec2Pair& lastKey = _lastRegisteredQuad3DTexture[quadID];
if (lastKey != key) {
glDeleteBuffers(1, &vbo.first);
glDeleteBuffers(1, &vbo.second);
vbo.first = vbo.second = 0;
#ifdef WANT_DEBUG
qDebug() << "renderQuad() vec3 + texture VBO... RELEASING REGISTERED QUAD";
#endif // def WANT_DEBUG
}
#ifdef WANT_DEBUG
else {
qDebug() << "renderQuad() vec3 + texture... REUSING PREVIOUSLY REGISTERED QUAD";
}
#endif // def WANT_DEBUG
}
const int FLOATS_PER_VERTEX = 5; // text coords & vertices const int FLOATS_PER_VERTEX = 5; // text coords & vertices
const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat); const int NUM_BYTES_PER_VERTEX = FLOATS_PER_VERTEX * sizeof(GLfloat);
const int vertices = 4; const int vertices = 4;
const int indices = 4; const int indices = 4;
if (vbo.first == 0) { if (vbo.first == 0) {
_lastRegisteredQuad3DTexture[quadID] = key;
int vertexPoints = vertices * FLOATS_PER_VERTEX; int vertexPoints = vertices * FLOATS_PER_VERTEX;
GLfloat* vertexData = new GLfloat[vertexPoints]; // text coords & vertices GLfloat* vertexData = new GLfloat[vertexPoints]; // text coords & vertices
GLfloat* vertex = vertexData; GLfloat* vertex = vertexData;
@ -925,7 +1028,11 @@ void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottom
delete[] indexData; delete[] indexData;
#ifdef WANT_DEBUG #ifdef WANT_DEBUG
qDebug() << " _quad3DTextureVBOs.size():" << _quad3DTextureVBOs.size(); if (quadID == UNKNOWN_QUAD_ID) {
qDebug() << " _quad3DTextureVBOs.size():" << _quad3DTextureVBOs.size();
} else {
qDebug() << "new registered quad VBO made -- _registeredQuadVBOs.size():" << _registeredQuadVBOs.size();
}
#endif #endif
} else { } else {
glBindBuffer(GL_ARRAY_BUFFER, vbo.first); glBindBuffer(GL_ARRAY_BUFFER, vbo.first);

View file

@ -90,23 +90,23 @@ public:
void renderSolidCube(float size); void renderSolidCube(float size);
void renderWireCube(float size); void renderWireCube(float size);
int allocateQuad() { return _nextQuadID++; }
static const int UNKNOWN_QUAD_ID;
void renderQuad(int x, int y, int width, int height) { renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height)); } void renderQuad(int x, int y, int width, int height, int quadID = UNKNOWN_QUAD_ID)
void renderQuad(const glm::vec2& topLeft, const glm::vec2& bottomRight); { renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), quadID); }
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, int quadID = UNKNOWN_QUAD_ID);
void renderQuad(const glm::vec2& topLeft, const glm::vec2& bottomRight, void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomRight); const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, int quadID = UNKNOWN_QUAD_ID);
void renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, int quadID = UNKNOWN_QUAD_ID);
void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight);
//void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomRight,
// const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomRight);
void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft, void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight, const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft, const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight); const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight, int quadID = UNKNOWN_QUAD_ID);
/// Loads geometry from the specified URL. /// Loads geometry from the specified URL.
/// \param fallback a fallback URL to load if the desired one is unavailable /// \param fallback a fallback URL to load if the desired one is unavailable
@ -136,6 +136,13 @@ private:
QHash<Vec2PairPair, VerticesIndices> _quad2DTextureVBOs; QHash<Vec2PairPair, VerticesIndices> _quad2DTextureVBOs;
QHash<Vec3Pair, VerticesIndices> _quad3DVBOs; QHash<Vec3Pair, VerticesIndices> _quad3DVBOs;
QHash<Vec3PairVec2Pair, VerticesIndices> _quad3DTextureVBOs; QHash<Vec3PairVec2Pair, VerticesIndices> _quad3DTextureVBOs;
QHash<int, VerticesIndices> _registeredQuadVBOs;
int _nextQuadID;
QHash<int, Vec2Pair> _lastRegisteredQuad2D;
QHash<int, Vec2PairPair> _lastRegisteredQuad2DTexture;
QHash<int, Vec3Pair> _lastRegisteredQuad3D;
QHash<int, Vec3PairVec2Pair> _lastRegisteredQuad3DTexture;
QHash<IntPair, QOpenGLBuffer> _gridBuffers; QHash<IntPair, QOpenGLBuffer> _gridBuffers;