mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
3b436e04ae
17 changed files with 1449 additions and 202 deletions
|
@ -26,11 +26,14 @@ varying vec4 normal;
|
|||
void main(void) {
|
||||
// transform and store the normal for interpolation
|
||||
vec2 heightCoord = gl_MultiTexCoord0.st;
|
||||
float deltaX = texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r -
|
||||
texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r;
|
||||
float deltaZ = texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r -
|
||||
texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r;
|
||||
normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0));
|
||||
vec4 neighborHeights = vec4(texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r,
|
||||
texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r,
|
||||
texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r,
|
||||
texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r);
|
||||
vec4 neighborsZero = step(1.0 / 255.0, neighborHeights);
|
||||
normal = normalize(gl_ModelViewMatrix * vec4(
|
||||
(neighborHeights.x - neighborHeights.y) * neighborsZero.x * neighborsZero.y, heightScale,
|
||||
(neighborHeights.z - neighborHeights.w) * neighborsZero.z * neighborsZero.w, 0.0));
|
||||
|
||||
// add the height to the position
|
||||
float height = texture2D(heightMap, heightCoord).r;
|
||||
|
|
|
@ -432,6 +432,8 @@ Menu::Menu() :
|
|||
QMenu* metavoxelOptionsMenu = developerMenu->addMenu("Metavoxels");
|
||||
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false,
|
||||
Application::getInstance()->getMetavoxels(), SLOT(refreshVoxelData()));
|
||||
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderHeightfields, 0, true);
|
||||
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderDualContourSurfaces, 0, true);
|
||||
addActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::NetworkSimulator, 0, this,
|
||||
SLOT(showMetavoxelNetworkSimulator()));
|
||||
|
||||
|
|
|
@ -446,8 +446,10 @@ namespace MenuOption {
|
|||
const QString Quit = "Quit";
|
||||
const QString ReloadAllScripts = "Reload All Scripts";
|
||||
const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes";
|
||||
const QString RenderDualContourSurfaces = "Render Dual Contour Surfaces";
|
||||
const QString RenderFocusIndicator = "Show Eye Focus";
|
||||
const QString RenderHeadCollisionShapes = "Show Head Collision Shapes";
|
||||
const QString RenderHeightfields = "Render Heightfields";
|
||||
const QString RenderLookAtVectors = "Show Look-at Vectors";
|
||||
const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes";
|
||||
const QString RenderResolution = "Scale Resolution";
|
||||
|
|
|
@ -2772,40 +2772,39 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
|
|||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
_baseHeightfieldProgram.bind();
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
|
||||
data.guide(heightfieldRenderVisitor);
|
||||
|
||||
_baseHeightfieldProgram.release();
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) {
|
||||
_baseHeightfieldProgram.bind();
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
|
||||
data.guide(heightfieldRenderVisitor);
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
_baseHeightfieldProgram.release();
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
_baseVoxelProgram.bind();
|
||||
|
||||
BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute());
|
||||
data.guide(voxelRenderVisitor);
|
||||
|
||||
_baseVoxelProgram.release();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
_baseVoxelProgram.bind();
|
||||
|
||||
BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute());
|
||||
data.guide(voxelRenderVisitor);
|
||||
|
||||
_baseVoxelProgram.release();
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
}
|
||||
|
|
|
@ -166,6 +166,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
}
|
||||
|
||||
// use data to update fake Faceshift blendshape coefficients
|
||||
|
||||
const float JAW_OPEN_SCALE = 0.015f;
|
||||
const float JAW_OPEN_RATE = 0.9f;
|
||||
const float JAW_CLOSE_RATE = 0.90f;
|
||||
|
@ -177,10 +178,28 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
}
|
||||
_audioJawOpen = glm::clamp(_audioJawOpen, 0.0f, 1.0f);
|
||||
|
||||
// _mouth2 = "mmmm" shape
|
||||
// _mouth3 = "funnel" shape
|
||||
// _mouth4 = "smile" shape
|
||||
const float FUNNEL_PERIOD = 0.985f;
|
||||
const float FUNNEL_RANDOM_PERIOD = 0.01f;
|
||||
const float MMMM_POWER = 0.25f;
|
||||
const float MMMM_PERIOD = 0.91f;
|
||||
const float MMMM_RANDOM_PERIOD = 0.15f;
|
||||
const float SMILE_PERIOD = 0.925f;
|
||||
const float SMILE_RANDOM_PERIOD = 0.05f;
|
||||
|
||||
_mouth3 = glm::mix(_audioJawOpen, _mouth3, FUNNEL_PERIOD + randFloat() * FUNNEL_RANDOM_PERIOD);
|
||||
_mouth2 = glm::mix(_audioJawOpen * MMMM_POWER, _mouth2, MMMM_PERIOD + randFloat() * MMMM_RANDOM_PERIOD);
|
||||
_mouth4 = glm::mix(_audioJawOpen, _mouth4, SMILE_PERIOD + randFloat() * SMILE_RANDOM_PERIOD);
|
||||
|
||||
Application::getInstance()->getFaceshift()->updateFakeCoefficients(_leftEyeBlink,
|
||||
_rightEyeBlink,
|
||||
_browAudioLift,
|
||||
_audioJawOpen,
|
||||
_mouth2,
|
||||
_mouth3,
|
||||
_mouth4,
|
||||
_blendshapeCoefficients);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,6 +129,9 @@ private:
|
|||
float _longTermAverageLoudness;
|
||||
float _audioAttack;
|
||||
float _audioJawOpen;
|
||||
float _mouth2;
|
||||
float _mouth3;
|
||||
float _mouth4;
|
||||
glm::vec3 _angularVelocity;
|
||||
bool _renderLookatVectors;
|
||||
glm::vec3 _saccade;
|
||||
|
|
|
@ -125,8 +125,14 @@ void Faceshift::reset() {
|
|||
}
|
||||
|
||||
void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float browUp,
|
||||
float jawOpen, QVector<float>& coefficients) const {
|
||||
coefficients.resize(max((int)coefficients.size(), _jawOpenIndex + 1));
|
||||
float jawOpen, float mouth2, float mouth3, float mouth4, QVector<float>& coefficients) const {
|
||||
const int MMMM_BLENDSHAPE = 34;
|
||||
const int FUNNEL_BLENDSHAPE = 40;
|
||||
const int SMILE_LEFT_BLENDSHAPE = 28;
|
||||
const int SMILE_RIGHT_BLENDSHAPE = 29;
|
||||
const int MAX_FAKE_BLENDSHAPE = 40; // Largest modified blendshape from above and below
|
||||
|
||||
coefficients.resize(max((int)coefficients.size(), MAX_FAKE_BLENDSHAPE + 1));
|
||||
qFill(coefficients.begin(), coefficients.end(), 0.0f);
|
||||
coefficients[_leftBlinkIndex] = leftBlink;
|
||||
coefficients[_rightBlinkIndex] = rightBlink;
|
||||
|
@ -134,6 +140,9 @@ void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float
|
|||
coefficients[_browUpLeftIndex] = browUp;
|
||||
coefficients[_browUpRightIndex] = browUp;
|
||||
coefficients[_jawOpenIndex] = jawOpen;
|
||||
coefficients[SMILE_LEFT_BLENDSHAPE] = coefficients[SMILE_RIGHT_BLENDSHAPE] = mouth4;
|
||||
coefficients[MMMM_BLENDSHAPE] = mouth2;
|
||||
coefficients[FUNNEL_BLENDSHAPE] = mouth3;
|
||||
}
|
||||
|
||||
void Faceshift::setTCPEnabled(bool enabled) {
|
||||
|
|
|
@ -61,8 +61,14 @@ public:
|
|||
void update();
|
||||
void reset();
|
||||
|
||||
void updateFakeCoefficients(float leftBlink, float rightBlink, float browUp,
|
||||
float jawOpen, QVector<float>& coefficients) const;
|
||||
void updateFakeCoefficients(float leftBlink,
|
||||
float rightBlink,
|
||||
float browUp,
|
||||
float jawOpen,
|
||||
float mouth2,
|
||||
float mouth3,
|
||||
float mouth4,
|
||||
QVector<float>& coefficients) const;
|
||||
|
||||
signals:
|
||||
|
||||
|
|
753
interface/src/gpu/Batch.cpp
Normal file
753
interface/src/gpu/Batch.cpp
Normal file
|
@ -0,0 +1,753 @@
|
|||
//
|
||||
// Batch.cpp
|
||||
// interface/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 10/14/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
|
||||
//
|
||||
#include "Batch.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define ADD_COMMAND(call) _commands.push_back(COMMAND_##call); _commandCalls.push_back(&gpu::Batch::do_##call); _commandOffsets.push_back(_params.size());
|
||||
|
||||
//#define DO_IT_NOW(call, offset) runLastCommand();
|
||||
#define DO_IT_NOW(call, offset)
|
||||
|
||||
#define CHECK_GL_ERROR() ::gpu::backend::checkGLError()
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
Batch::Batch() :
|
||||
_commands(),
|
||||
_commandCalls(),
|
||||
_commandOffsets(),
|
||||
_params(),
|
||||
_resources(),
|
||||
_data(){
|
||||
}
|
||||
|
||||
Batch::~Batch() {
|
||||
}
|
||||
|
||||
void Batch::clear() {
|
||||
_commands.clear();
|
||||
_commandCalls.clear();
|
||||
_commandOffsets.clear();
|
||||
_params.clear();
|
||||
_resources.clear();
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
uint32 Batch::cacheResource(Resource* res) {
|
||||
uint32 offset = _resources.size();
|
||||
_resources.push_back(ResourceCache(res));
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
uint32 Batch::cacheResource(const void* pointer) {
|
||||
uint32 offset = _resources.size();
|
||||
_resources.push_back(ResourceCache(pointer));
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
uint32 Batch::cacheData(uint32 size, const void* data) {
|
||||
uint32 offset = _data.size();
|
||||
uint32 nbBytes = size;
|
||||
_data.resize(offset + nbBytes);
|
||||
memcpy(_data.data() + offset, data, size);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#define CASE_COMMAND(call) case COMMAND_##call: { do_##call(offset); } break;
|
||||
|
||||
void Batch::runCommand(Command com, uint32 offset) {
|
||||
switch (com) {
|
||||
CASE_COMMAND(draw);
|
||||
CASE_COMMAND(drawIndexed);
|
||||
CASE_COMMAND(drawInstanced);
|
||||
CASE_COMMAND(drawIndexedInstanced);
|
||||
CASE_COMMAND(glEnable);
|
||||
CASE_COMMAND(glDisable);
|
||||
CASE_COMMAND(glEnableClientState);
|
||||
CASE_COMMAND(glDisableClientState);
|
||||
CASE_COMMAND(glCullFace);
|
||||
CASE_COMMAND(glAlphaFunc);
|
||||
CASE_COMMAND(glDepthFunc);
|
||||
CASE_COMMAND(glDepthMask);
|
||||
CASE_COMMAND(glDepthRange);
|
||||
CASE_COMMAND(glBindBuffer);
|
||||
CASE_COMMAND(glBindTexture);
|
||||
CASE_COMMAND(glActiveTexture);
|
||||
CASE_COMMAND(glDrawBuffers);
|
||||
CASE_COMMAND(glUseProgram);
|
||||
CASE_COMMAND(glUniform1f);
|
||||
CASE_COMMAND(glUniformMatrix4fv);
|
||||
CASE_COMMAND(glMatrixMode);
|
||||
CASE_COMMAND(glPushMatrix);
|
||||
CASE_COMMAND(glPopMatrix);
|
||||
CASE_COMMAND(glMultMatrixf);
|
||||
CASE_COMMAND(glLoadMatrixf);
|
||||
CASE_COMMAND(glLoadIdentity);
|
||||
CASE_COMMAND(glRotatef);
|
||||
CASE_COMMAND(glScalef);
|
||||
CASE_COMMAND(glTranslatef);
|
||||
CASE_COMMAND(glDrawArrays);
|
||||
CASE_COMMAND(glDrawRangeElements);
|
||||
CASE_COMMAND(glColorPointer);
|
||||
CASE_COMMAND(glNormalPointer);
|
||||
CASE_COMMAND(glTexCoordPointer);
|
||||
CASE_COMMAND(glVertexPointer);
|
||||
CASE_COMMAND(glVertexAttribPointer);
|
||||
CASE_COMMAND(glEnableVertexAttribArray);
|
||||
CASE_COMMAND(glDisableVertexAttribArray);
|
||||
CASE_COMMAND(glColor4f);
|
||||
CASE_COMMAND(glMaterialf);
|
||||
CASE_COMMAND(glMaterialfv);
|
||||
}
|
||||
}
|
||||
|
||||
void Batch::draw(Primitive primitiveType, int nbVertices, int startVertex) {
|
||||
ADD_COMMAND(draw);
|
||||
|
||||
_params.push_back(startVertex);
|
||||
_params.push_back(nbVertices);
|
||||
_params.push_back(primitiveType);
|
||||
}
|
||||
|
||||
void Batch::drawIndexed(Primitive primitiveType, int nbIndices, int startIndex) {
|
||||
ADD_COMMAND(drawIndexed);
|
||||
|
||||
_params.push_back(startIndex);
|
||||
_params.push_back(nbIndices);
|
||||
_params.push_back(primitiveType);
|
||||
}
|
||||
|
||||
void Batch::drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex, int startInstance) {
|
||||
ADD_COMMAND(drawInstanced);
|
||||
|
||||
_params.push_back(startInstance);
|
||||
_params.push_back(startVertex);
|
||||
_params.push_back(nbVertices);
|
||||
_params.push_back(primitiveType);
|
||||
_params.push_back(nbInstances);
|
||||
}
|
||||
|
||||
void Batch::drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex, int startInstance) {
|
||||
ADD_COMMAND(drawIndexedInstanced);
|
||||
|
||||
_params.push_back(startInstance);
|
||||
_params.push_back(startIndex);
|
||||
_params.push_back(nbIndices);
|
||||
_params.push_back(primitiveType);
|
||||
_params.push_back(nbInstances);
|
||||
}
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
|
||||
void Batch::_glEnable(GLenum cap) {
|
||||
ADD_COMMAND(glEnable);
|
||||
|
||||
_params.push_back(cap);
|
||||
|
||||
DO_IT_NOW(_glEnable, 1);
|
||||
}
|
||||
void Batch::do_glEnable(uint32 paramOffset) {
|
||||
glEnable(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDisable(GLenum cap) {
|
||||
ADD_COMMAND(glDisable);
|
||||
|
||||
_params.push_back(cap);
|
||||
|
||||
DO_IT_NOW(_glDisable, 1);
|
||||
}
|
||||
void Batch::do_glDisable(uint32 paramOffset) {
|
||||
glDisable(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glEnableClientState(GLenum array) {
|
||||
ADD_COMMAND(glEnableClientState);
|
||||
|
||||
_params.push_back(array);
|
||||
|
||||
DO_IT_NOW(_glEnableClientState, 1 );
|
||||
}
|
||||
void Batch::do_glEnableClientState(uint32 paramOffset) {
|
||||
glEnableClientState(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDisableClientState(GLenum array) {
|
||||
ADD_COMMAND(glDisableClientState);
|
||||
|
||||
_params.push_back(array);
|
||||
|
||||
DO_IT_NOW(_glDisableClientState, 1);
|
||||
}
|
||||
void Batch::do_glDisableClientState(uint32 paramOffset) {
|
||||
glDisableClientState(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glCullFace(GLenum mode) {
|
||||
ADD_COMMAND(glCullFace);
|
||||
|
||||
_params.push_back(mode);
|
||||
|
||||
DO_IT_NOW(_glCullFace, 1);
|
||||
}
|
||||
void Batch::do_glCullFace(uint32 paramOffset) {
|
||||
glCullFace(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glAlphaFunc(GLenum func, GLclampf ref) {
|
||||
ADD_COMMAND(glAlphaFunc);
|
||||
|
||||
_params.push_back(ref);
|
||||
_params.push_back(func);
|
||||
|
||||
DO_IT_NOW(_glAlphaFunc, 2);
|
||||
}
|
||||
void Batch::do_glAlphaFunc(uint32 paramOffset) {
|
||||
glAlphaFunc(
|
||||
_params[paramOffset + 1]._uint,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDepthFunc(GLenum func) {
|
||||
ADD_COMMAND(glDepthFunc);
|
||||
|
||||
_params.push_back(func);
|
||||
|
||||
DO_IT_NOW(_glDepthFunc, 1);
|
||||
}
|
||||
void Batch::do_glDepthFunc(uint32 paramOffset) {
|
||||
glDepthFunc(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDepthMask(GLboolean flag) {
|
||||
ADD_COMMAND(glDepthMask);
|
||||
|
||||
_params.push_back(flag);
|
||||
|
||||
DO_IT_NOW(_glDepthMask, 1);
|
||||
}
|
||||
void Batch::do_glDepthMask(uint32 paramOffset) {
|
||||
glDepthMask(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) {
|
||||
ADD_COMMAND(glDepthRange);
|
||||
|
||||
_params.push_back(zFar);
|
||||
_params.push_back(zNear);
|
||||
|
||||
DO_IT_NOW(_glDepthRange, 2);
|
||||
}
|
||||
void Batch::do_glDepthRange(uint32 paramOffset) {
|
||||
glDepthRange(
|
||||
_params[paramOffset + 1]._double,
|
||||
_params[paramOffset + 0]._double);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glBindBuffer(GLenum target, GLuint buffer) {
|
||||
ADD_COMMAND(glBindBuffer);
|
||||
|
||||
_params.push_back(buffer);
|
||||
_params.push_back(target);
|
||||
|
||||
DO_IT_NOW(_glBindBuffer, 2);
|
||||
}
|
||||
void Batch::do_glBindBuffer(uint32 paramOffset) {
|
||||
glBindBuffer(
|
||||
_params[paramOffset + 1]._uint,
|
||||
_params[paramOffset + 0]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glBindTexture(GLenum target, GLuint texture) {
|
||||
ADD_COMMAND(glBindTexture);
|
||||
|
||||
_params.push_back(texture);
|
||||
_params.push_back(target);
|
||||
|
||||
DO_IT_NOW(_glBindTexture, 2);
|
||||
}
|
||||
void Batch::do_glBindTexture(uint32 paramOffset) {
|
||||
glBindTexture(
|
||||
_params[paramOffset + 1]._uint,
|
||||
_params[paramOffset + 0]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glActiveTexture(GLenum texture) {
|
||||
ADD_COMMAND(glActiveTexture);
|
||||
|
||||
_params.push_back(texture);
|
||||
|
||||
DO_IT_NOW(_glActiveTexture, 1);
|
||||
}
|
||||
void Batch::do_glActiveTexture(uint32 paramOffset) {
|
||||
glActiveTexture(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDrawBuffers(GLsizei n, const GLenum* bufs) {
|
||||
ADD_COMMAND(glDrawBuffers);
|
||||
|
||||
_params.push_back(cacheData(n * sizeof(GLenum), bufs));
|
||||
_params.push_back(n);
|
||||
|
||||
DO_IT_NOW(_glDrawBuffers, 2);
|
||||
}
|
||||
void Batch::do_glDrawBuffers(uint32 paramOffset) {
|
||||
glDrawBuffers(
|
||||
_params[paramOffset + 1]._uint,
|
||||
(const GLenum*) editData(_params[paramOffset + 0]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glUseProgram(GLuint program) {
|
||||
ADD_COMMAND(glUseProgram);
|
||||
|
||||
_params.push_back(program);
|
||||
|
||||
DO_IT_NOW(_glUseProgram, 1);
|
||||
}
|
||||
void Batch::do_glUseProgram(uint32 paramOffset) {
|
||||
glUseProgram(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glUniform1f(GLint location, GLfloat v0) {
|
||||
ADD_COMMAND(glUniform1f);
|
||||
|
||||
_params.push_back(v0);
|
||||
_params.push_back(location);
|
||||
|
||||
DO_IT_NOW(_glUniform1f, 1);
|
||||
}
|
||||
void Batch::do_glUniform1f(uint32 paramOffset) {
|
||||
glUniform1f(
|
||||
_params[paramOffset + 1]._int,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||
ADD_COMMAND(glUniformMatrix4fv);
|
||||
|
||||
const int MATRIX4_SIZE = 16 * sizeof(float);
|
||||
_params.push_back(cacheData(count * MATRIX4_SIZE, value));
|
||||
_params.push_back(transpose);
|
||||
_params.push_back(count);
|
||||
_params.push_back(location);
|
||||
|
||||
DO_IT_NOW(_glUniformMatrix4fv, 4);
|
||||
}
|
||||
void Batch::do_glUniformMatrix4fv(uint32 paramOffset) {
|
||||
glUniformMatrix4fv(
|
||||
_params[paramOffset + 3]._int,
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._uint,
|
||||
(const GLfloat*) editData(_params[paramOffset + 0]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glMatrixMode(GLenum mode) {
|
||||
ADD_COMMAND(glMatrixMode);
|
||||
|
||||
_params.push_back(mode);
|
||||
|
||||
DO_IT_NOW(_glMatrixMode, 1);
|
||||
}
|
||||
void Batch::do_glMatrixMode(uint32 paramOffset) {
|
||||
glMatrixMode(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glPushMatrix() {
|
||||
ADD_COMMAND(glPushMatrix);
|
||||
|
||||
DO_IT_NOW(_glPushMatrix, 0);
|
||||
}
|
||||
void Batch::do_glPushMatrix(uint32 paramOffset) {
|
||||
glPushMatrix();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glPopMatrix() {
|
||||
ADD_COMMAND(glPopMatrix);
|
||||
|
||||
DO_IT_NOW(_glPopMatrix, 0);
|
||||
}
|
||||
void Batch::do_glPopMatrix(uint32 paramOffset) {
|
||||
glPopMatrix();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glMultMatrixf(const GLfloat *m) {
|
||||
ADD_COMMAND(glMultMatrixf);
|
||||
|
||||
const int MATRIX4_SIZE = 16 * sizeof(float);
|
||||
_params.push_back(cacheData(MATRIX4_SIZE, m));
|
||||
|
||||
DO_IT_NOW(_glMultMatrixf, 1);
|
||||
}
|
||||
void Batch::do_glMultMatrixf(uint32 paramOffset) {
|
||||
glMultMatrixf((const GLfloat*) editData(_params[paramOffset]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glLoadMatrixf(const GLfloat *m) {
|
||||
ADD_COMMAND(glLoadMatrixf);
|
||||
|
||||
const int MATRIX4_SIZE = 16 * sizeof(float);
|
||||
_params.push_back(cacheData(MATRIX4_SIZE, m));
|
||||
|
||||
DO_IT_NOW(_glLoadMatrixf, 1);
|
||||
}
|
||||
void Batch::do_glLoadMatrixf(uint32 paramOffset) {
|
||||
glLoadMatrixf((const GLfloat*)editData(_params[paramOffset]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glLoadIdentity(void) {
|
||||
ADD_COMMAND(glLoadIdentity);
|
||||
|
||||
DO_IT_NOW(_glLoadIdentity, 0);
|
||||
}
|
||||
void Batch::do_glLoadIdentity(uint32 paramOffset) {
|
||||
glLoadIdentity();
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
ADD_COMMAND(glRotatef);
|
||||
|
||||
_params.push_back(z);
|
||||
_params.push_back(y);
|
||||
_params.push_back(x);
|
||||
_params.push_back(angle);
|
||||
|
||||
DO_IT_NOW(_glRotatef, 4);
|
||||
}
|
||||
void Batch::do_glRotatef(uint32 paramOffset) {
|
||||
glRotatef(
|
||||
_params[paramOffset + 3]._float,
|
||||
_params[paramOffset + 2]._float,
|
||||
_params[paramOffset + 1]._float,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
ADD_COMMAND(glScalef);
|
||||
|
||||
_params.push_back(z);
|
||||
_params.push_back(y);
|
||||
_params.push_back(x);
|
||||
|
||||
DO_IT_NOW(_glScalef, 3);
|
||||
}
|
||||
void Batch::do_glScalef(uint32 paramOffset) {
|
||||
glScalef(
|
||||
_params[paramOffset + 2]._float,
|
||||
_params[paramOffset + 1]._float,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
ADD_COMMAND(glTranslatef);
|
||||
|
||||
_params.push_back(z);
|
||||
_params.push_back(y);
|
||||
_params.push_back(x);
|
||||
|
||||
DO_IT_NOW(_glTranslatef, 3);
|
||||
}
|
||||
void Batch::do_glTranslatef(uint32 paramOffset) {
|
||||
glTranslatef(
|
||||
_params[paramOffset + 2]._float,
|
||||
_params[paramOffset + 1]._float,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
ADD_COMMAND(glDrawArrays);
|
||||
|
||||
_params.push_back(count);
|
||||
_params.push_back(first);
|
||||
_params.push_back(mode);
|
||||
|
||||
DO_IT_NOW(_glDrawArrays, 3);
|
||||
}
|
||||
void Batch::do_glDrawArrays(uint32 paramOffset) {
|
||||
glDrawArrays(
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._int,
|
||||
_params[paramOffset + 0]._int);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) {
|
||||
ADD_COMMAND(glDrawRangeElements);
|
||||
|
||||
_params.push_back(cacheResource(indices));
|
||||
_params.push_back(type);
|
||||
_params.push_back(count);
|
||||
_params.push_back(end);
|
||||
_params.push_back(start);
|
||||
_params.push_back(mode);
|
||||
|
||||
DO_IT_NOW(_glDrawRangeElements, 6);
|
||||
}
|
||||
void Batch::do_glDrawRangeElements(uint32 paramOffset) {
|
||||
glDrawRangeElements(
|
||||
_params[paramOffset + 5]._uint,
|
||||
_params[paramOffset + 4]._uint,
|
||||
_params[paramOffset + 3]._uint,
|
||||
_params[paramOffset + 2]._int,
|
||||
_params[paramOffset + 1]._uint,
|
||||
editResource(_params[paramOffset + 0]._uint)->_pointer);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
||||
ADD_COMMAND(glColorPointer);
|
||||
|
||||
_params.push_back(cacheResource(pointer));
|
||||
_params.push_back(stride);
|
||||
_params.push_back(type);
|
||||
_params.push_back(size);
|
||||
|
||||
DO_IT_NOW(_glColorPointer, 4);
|
||||
}
|
||||
void Batch::do_glColorPointer(uint32 paramOffset) {
|
||||
glColorPointer(
|
||||
_params[paramOffset + 3]._int,
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._int,
|
||||
editResource(_params[paramOffset + 0]._uint)->_pointer);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) {
|
||||
ADD_COMMAND(glNormalPointer);
|
||||
|
||||
_params.push_back(cacheResource(pointer));
|
||||
_params.push_back(stride);
|
||||
_params.push_back(type);
|
||||
|
||||
DO_IT_NOW(_glNormalPointer, 3);
|
||||
}
|
||||
void Batch::do_glNormalPointer(uint32 paramOffset) {
|
||||
glNormalPointer(
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._int,
|
||||
editResource(_params[paramOffset + 0]._uint)->_pointer);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
||||
ADD_COMMAND(glTexCoordPointer);
|
||||
|
||||
_params.push_back(cacheResource(pointer));
|
||||
_params.push_back(stride);
|
||||
_params.push_back(type);
|
||||
_params.push_back(size);
|
||||
|
||||
DO_IT_NOW(_glTexCoordPointer, 4);
|
||||
}
|
||||
void Batch::do_glTexCoordPointer(uint32 paramOffset) {
|
||||
glTexCoordPointer(
|
||||
_params[paramOffset + 3]._int,
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._int,
|
||||
editResource(_params[paramOffset + 0]._uint)->_pointer);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) {
|
||||
ADD_COMMAND(glVertexPointer);
|
||||
|
||||
_params.push_back(cacheResource(pointer));
|
||||
_params.push_back(stride);
|
||||
_params.push_back(type);
|
||||
_params.push_back(size);
|
||||
|
||||
DO_IT_NOW(_glVertexPointer, 4);
|
||||
}
|
||||
void Batch::do_glVertexPointer(uint32 paramOffset) {
|
||||
glVertexPointer(
|
||||
_params[paramOffset + 3]._int,
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._int,
|
||||
editResource(_params[paramOffset + 0]._uint)->_pointer);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
||||
void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {
|
||||
ADD_COMMAND(glVertexAttribPointer);
|
||||
|
||||
_params.push_back(cacheResource(pointer));
|
||||
_params.push_back(stride);
|
||||
_params.push_back(normalized);
|
||||
_params.push_back(type);
|
||||
_params.push_back(size);
|
||||
_params.push_back(index);
|
||||
|
||||
DO_IT_NOW(_glVertexAttribPointer, 6);
|
||||
}
|
||||
void Batch::do_glVertexAttribPointer(uint32 paramOffset) {
|
||||
glVertexAttribPointer(
|
||||
_params[paramOffset + 5]._uint,
|
||||
_params[paramOffset + 4]._int,
|
||||
_params[paramOffset + 3]._uint,
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._int,
|
||||
editResource(_params[paramOffset + 0]._uint)->_pointer);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glEnableVertexAttribArray(GLint location) {
|
||||
ADD_COMMAND(glEnableVertexAttribArray);
|
||||
|
||||
_params.push_back(location);
|
||||
|
||||
DO_IT_NOW(_glEnableVertexAttribArray, 1);
|
||||
}
|
||||
void Batch::do_glEnableVertexAttribArray(uint32 paramOffset) {
|
||||
glEnableVertexAttribArray(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glDisableVertexAttribArray(GLint location) {
|
||||
ADD_COMMAND(glDisableVertexAttribArray);
|
||||
|
||||
_params.push_back(location);
|
||||
|
||||
DO_IT_NOW(_glDisableVertexAttribArray, 1);
|
||||
}
|
||||
void Batch::do_glDisableVertexAttribArray(uint32 paramOffset) {
|
||||
glDisableVertexAttribArray(_params[paramOffset]._uint);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||
ADD_COMMAND(glColor4f);
|
||||
|
||||
_params.push_back(alpha);
|
||||
_params.push_back(blue);
|
||||
_params.push_back(green);
|
||||
_params.push_back(red);
|
||||
|
||||
DO_IT_NOW(_glColor4f, 4);
|
||||
}
|
||||
void Batch::do_glColor4f(uint32 paramOffset) {
|
||||
glColor4f(
|
||||
_params[paramOffset + 3]._float,
|
||||
_params[paramOffset + 2]._float,
|
||||
_params[paramOffset + 1]._float,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) {
|
||||
ADD_COMMAND(glMaterialf);
|
||||
|
||||
_params.push_back(param);
|
||||
_params.push_back(pname);
|
||||
_params.push_back(face);
|
||||
|
||||
DO_IT_NOW(_glMaterialf, 3);
|
||||
}
|
||||
void Batch::do_glMaterialf(uint32 paramOffset) {
|
||||
glMaterialf(
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._uint,
|
||||
_params[paramOffset + 0]._float);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
|
||||
ADD_COMMAND(glMaterialfv);
|
||||
|
||||
_params.push_back(cacheData(4 * sizeof(float), params));
|
||||
_params.push_back(pname);
|
||||
_params.push_back(face);
|
||||
|
||||
DO_IT_NOW(_glMaterialfv, 3);
|
||||
}
|
||||
void Batch::do_glMaterialfv(uint32 paramOffset) {
|
||||
glMaterialfv(
|
||||
_params[paramOffset + 2]._uint,
|
||||
_params[paramOffset + 1]._uint,
|
||||
(const GLfloat*) editData(_params[paramOffset + 0]._uint));
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void backend::renderBatch(Batch& batch) {
|
||||
uint32 numCommands = batch._commands.size();
|
||||
Batch::CommandCall* call = batch._commandCalls.data();
|
||||
Batch::CommandOffsets::value_type* offset = batch._commandOffsets.data();
|
||||
|
||||
for (int i = 0; i < numCommands; i++) {
|
||||
(batch.*(*call))(*offset);
|
||||
call++;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
void backend::checkGLError() {
|
||||
GLenum error = glGetError();
|
||||
if (!error) {
|
||||
return;
|
||||
} else {
|
||||
switch (error) {
|
||||
case GL_INVALID_ENUM:
|
||||
qDebug() << "An unacceptable value is specified for an enumerated argument.The offending command is ignored and has no other side effect than to set the error flag.";
|
||||
break;
|
||||
case GL_INVALID_VALUE:
|
||||
qDebug() << "A numeric argument is out of range.The offending command is ignored and has no other side effect than to set the error flag";
|
||||
break;
|
||||
case GL_INVALID_OPERATION:
|
||||
qDebug() << "The specified operation is not allowed in the current state.The offending command is ignored and has no other side effect than to set the error flag..";
|
||||
break;
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
qDebug() << "The framebuffer object is not complete.The offending command is ignored and has no other side effect than to set the error flag.";
|
||||
break;
|
||||
case GL_OUT_OF_MEMORY:
|
||||
qDebug() << "There is not enough memory left to execute the command.The state of the GL is undefined, except for the state of the error flags, after this error is recorded.";
|
||||
break;
|
||||
case GL_STACK_UNDERFLOW:
|
||||
qDebug() << "An attempt has been made to perform an operation that would cause an internal stack to underflow.";
|
||||
break;
|
||||
case GL_STACK_OVERFLOW:
|
||||
qDebug() << "An attempt has been made to perform an operation that would cause an internal stack to overflow.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
318
interface/src/gpu/Batch.h
Normal file
318
interface/src/gpu/Batch.h
Normal file
|
@ -0,0 +1,318 @@
|
|||
//
|
||||
// Batch.h
|
||||
// interface/src/gpu
|
||||
//
|
||||
// Created by Sam Gateau on 10/14/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_gpu_Batch_h
|
||||
#define hifi_gpu_Batch_h
|
||||
|
||||
#include <assert.h>
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class Batch;
|
||||
// TODO: move the backend namespace into dedicated files, for now we keep it close to the gpu objects definition for convenience
|
||||
namespace backend {
|
||||
|
||||
void renderBatch(Batch& batch);
|
||||
|
||||
void checkGLError();
|
||||
};
|
||||
|
||||
class Buffer;
|
||||
class Resource;
|
||||
typedef int Stamp;
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
|
||||
enum Primitive {
|
||||
PRIMITIVE_POINTS = 0,
|
||||
PRIMITIVE_LINES,
|
||||
PRIMITIVE_LINE_STRIP,
|
||||
PRIMITIVE_TRIANGLES,
|
||||
PRIMITIVE_TRIANGLE_STRIP,
|
||||
PRIMITIVE_QUADS,
|
||||
};
|
||||
|
||||
class Batch {
|
||||
public:
|
||||
|
||||
Batch();
|
||||
Batch(const Batch& batch);
|
||||
~Batch();
|
||||
|
||||
void clear();
|
||||
|
||||
void draw(Primitive primitiveType, int nbVertices, int startVertex = 0);
|
||||
void drawIndexed(Primitive primitiveType, int nbIndices, int startIndex = 0);
|
||||
void drawInstanced(uint32 nbInstances, Primitive primitiveType, int nbVertices, int startVertex = 0, int startInstance = 0);
|
||||
void drawIndexedInstanced(uint32 nbInstances, Primitive primitiveType, int nbIndices, int startIndex = 0, int startInstance = 0);
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
void _glEnable(GLenum cap);
|
||||
void _glDisable(GLenum cap);
|
||||
|
||||
void _glEnableClientState(GLenum array);
|
||||
void _glDisableClientState(GLenum array);
|
||||
|
||||
void _glCullFace(GLenum mode);
|
||||
void _glAlphaFunc(GLenum func, GLclampf ref);
|
||||
|
||||
void _glDepthFunc(GLenum func);
|
||||
void _glDepthMask(GLboolean flag);
|
||||
void _glDepthRange(GLclampd zNear, GLclampd zFar);
|
||||
|
||||
void _glBindBuffer(GLenum target, GLuint buffer);
|
||||
|
||||
void _glBindTexture(GLenum target, GLuint texture);
|
||||
void _glActiveTexture(GLenum texture);
|
||||
|
||||
void _glDrawBuffers(GLsizei n, const GLenum* bufs);
|
||||
|
||||
void _glUseProgram(GLuint program);
|
||||
void _glUniform1f(GLint location, GLfloat v0);
|
||||
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
|
||||
void _glMatrixMode(GLenum mode);
|
||||
void _glPushMatrix();
|
||||
void _glPopMatrix();
|
||||
void _glMultMatrixf(const GLfloat *m);
|
||||
void _glLoadMatrixf(const GLfloat *m);
|
||||
void _glLoadIdentity(void);
|
||||
void _glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
void _glTranslatef(GLfloat x, GLfloat y, GLfloat z);
|
||||
|
||||
void _glDrawArrays(GLenum mode, GLint first, GLsizei count);
|
||||
void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
|
||||
|
||||
void _glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void _glNormalPointer(GLenum type, GLsizei stride, const void *pointer);
|
||||
void _glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
|
||||
|
||||
void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
|
||||
void _glEnableVertexAttribArray(GLint location);
|
||||
void _glDisableVertexAttribArray(GLint location);
|
||||
|
||||
void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
|
||||
|
||||
void _glMaterialf(GLenum face, GLenum pname, GLfloat param);
|
||||
void _glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
enum Command {
|
||||
COMMAND_draw = 0,
|
||||
COMMAND_drawIndexed,
|
||||
COMMAND_drawInstanced,
|
||||
COMMAND_drawIndexedInstanced,
|
||||
|
||||
COMMAND_SET_PIPE_STATE,
|
||||
COMMAND_SET_VIEWPORT,
|
||||
COMMAND_SET_FRAMEBUFFER,
|
||||
COMMAND_SET_RESOURCE,
|
||||
COMMAND_SET_VERTEX_STREAM,
|
||||
COMMAND_SET_INDEX_STREAM,
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
COMMAND_glEnable,
|
||||
COMMAND_glDisable,
|
||||
|
||||
COMMAND_glEnableClientState,
|
||||
COMMAND_glDisableClientState,
|
||||
|
||||
COMMAND_glCullFace,
|
||||
COMMAND_glAlphaFunc,
|
||||
|
||||
COMMAND_glDepthFunc,
|
||||
COMMAND_glDepthMask,
|
||||
COMMAND_glDepthRange,
|
||||
|
||||
COMMAND_glBindBuffer,
|
||||
|
||||
COMMAND_glBindTexture,
|
||||
COMMAND_glActiveTexture,
|
||||
|
||||
COMMAND_glDrawBuffers,
|
||||
|
||||
COMMAND_glUseProgram,
|
||||
COMMAND_glUniform1f,
|
||||
COMMAND_glUniformMatrix4fv,
|
||||
|
||||
COMMAND_glMatrixMode,
|
||||
COMMAND_glPushMatrix,
|
||||
COMMAND_glPopMatrix,
|
||||
COMMAND_glMultMatrixf,
|
||||
COMMAND_glLoadMatrixf,
|
||||
COMMAND_glLoadIdentity,
|
||||
COMMAND_glRotatef,
|
||||
COMMAND_glScalef,
|
||||
COMMAND_glTranslatef,
|
||||
|
||||
COMMAND_glDrawArrays,
|
||||
COMMAND_glDrawRangeElements,
|
||||
|
||||
COMMAND_glColorPointer,
|
||||
COMMAND_glNormalPointer,
|
||||
COMMAND_glTexCoordPointer,
|
||||
COMMAND_glVertexPointer,
|
||||
|
||||
COMMAND_glVertexAttribPointer,
|
||||
COMMAND_glEnableVertexAttribArray,
|
||||
COMMAND_glDisableVertexAttribArray,
|
||||
|
||||
COMMAND_glColor4f,
|
||||
|
||||
COMMAND_glMaterialf,
|
||||
COMMAND_glMaterialfv,
|
||||
};
|
||||
typedef std::vector<Command> Commands;
|
||||
typedef void (Batch::*CommandCall)(uint32);
|
||||
typedef std::vector<CommandCall> CommandCalls;
|
||||
typedef std::vector<uint32> CommandOffsets;
|
||||
|
||||
|
||||
class Param {
|
||||
public:
|
||||
union {
|
||||
int32 _int;
|
||||
uint32 _uint;
|
||||
float _float;
|
||||
char _chars[4];
|
||||
double _double;
|
||||
};
|
||||
Param(int32 val) : _int(val) {}
|
||||
Param(uint32 val) : _uint(val) {}
|
||||
Param(float val) : _float(val) {}
|
||||
Param(double val) : _double(val) {}
|
||||
};
|
||||
typedef std::vector<Param> Params;
|
||||
|
||||
class ResourceCache {
|
||||
public:
|
||||
union {
|
||||
Resource* _resource;
|
||||
const void* _pointer;
|
||||
};
|
||||
ResourceCache(Resource* res) : _resource(res) {}
|
||||
ResourceCache(const void* pointer) : _pointer(pointer) {}
|
||||
};
|
||||
typedef std::vector<ResourceCache> Resources;
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef std::vector<Byte> Bytes;
|
||||
|
||||
Commands _commands;
|
||||
CommandCalls _commandCalls;
|
||||
CommandOffsets _commandOffsets;
|
||||
Params _params;
|
||||
Resources _resources;
|
||||
Bytes _data;
|
||||
|
||||
uint32 cacheResource(Resource* res);
|
||||
uint32 cacheResource(const void* pointer);
|
||||
ResourceCache* editResource(uint32 offset) {
|
||||
if (offset >= _resources.size())
|
||||
return 0;
|
||||
return (_resources.data() + offset);
|
||||
}
|
||||
|
||||
uint32 cacheData(uint32 size, const void* data);
|
||||
Byte* editData(uint32 offset) {
|
||||
if (offset >= _data.size())
|
||||
return 0;
|
||||
return (_data.data() + offset);
|
||||
}
|
||||
|
||||
void runCommand(uint32 index) {
|
||||
uint32 offset = _commandOffsets[index];
|
||||
CommandCall call = _commandCalls[index];
|
||||
(this->*(call))(offset);
|
||||
}
|
||||
|
||||
void runLastCommand() {
|
||||
uint32 index = _commands.size() - 1;
|
||||
runCommand(index);
|
||||
}
|
||||
|
||||
void runCommand(Command com, uint32 offset);
|
||||
|
||||
void do_draw(uint32 paramOffset) {}
|
||||
void do_drawIndexed(uint32 paramOffset) {}
|
||||
void do_drawInstanced(uint32 paramOffset) {}
|
||||
void do_drawIndexedInstanced(uint32 paramOffset) {}
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
void do_glEnable(uint32 paramOffset);
|
||||
void do_glDisable(uint32 paramOffset);
|
||||
|
||||
void do_glEnableClientState(uint32 paramOffset);
|
||||
void do_glDisableClientState(uint32 paramOffset);
|
||||
|
||||
void do_glCullFace(uint32 paramOffset);
|
||||
void do_glAlphaFunc(uint32 paramOffset);
|
||||
|
||||
void do_glDepthFunc(uint32 paramOffset);
|
||||
void do_glDepthMask(uint32 paramOffset);
|
||||
void do_glDepthRange(uint32 paramOffset);
|
||||
|
||||
void do_glBindBuffer(uint32 paramOffset);
|
||||
|
||||
void do_glBindTexture(uint32 paramOffset);
|
||||
void do_glActiveTexture(uint32 paramOffset);
|
||||
|
||||
void do_glDrawBuffers(uint32 paramOffset);
|
||||
|
||||
void do_glUseProgram(uint32 paramOffset);
|
||||
void do_glUniform1f(uint32 paramOffset);
|
||||
void do_glUniformMatrix4fv(uint32 paramOffset);
|
||||
|
||||
void do_glMatrixMode(uint32 paramOffset);
|
||||
void do_glPushMatrix(uint32 paramOffset);
|
||||
void do_glPopMatrix(uint32 paramOffset);
|
||||
void do_glMultMatrixf(uint32 paramOffset);
|
||||
void do_glLoadMatrixf(uint32 paramOffset);
|
||||
void do_glLoadIdentity(uint32 paramOffset);
|
||||
void do_glRotatef(uint32 paramOffset);
|
||||
void do_glScalef(uint32 paramOffset);
|
||||
void do_glTranslatef(uint32 paramOffset);
|
||||
|
||||
void do_glDrawArrays(uint32 paramOffset);
|
||||
void do_glDrawRangeElements(uint32 paramOffset);
|
||||
|
||||
void do_glColorPointer(uint32 paramOffset);
|
||||
void do_glNormalPointer(uint32 paramOffset);
|
||||
void do_glTexCoordPointer(uint32 paramOffset);
|
||||
void do_glVertexPointer(uint32 paramOffset);
|
||||
|
||||
void do_glVertexAttribPointer(uint32 paramOffset);
|
||||
void do_glEnableVertexAttribArray(uint32 paramOffset);
|
||||
void do_glDisableVertexAttribArray(uint32 paramOffset);
|
||||
|
||||
void do_glColor4f(uint32 paramOffset);
|
||||
|
||||
void do_glMaterialf(uint32 paramOffset);
|
||||
void do_glMaterialfv(uint32 paramOffset);
|
||||
|
||||
friend void backend::renderBatch(Batch& batch);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -26,6 +26,10 @@
|
|||
#include "Application.h"
|
||||
#include "Model.h"
|
||||
|
||||
#include "gpu/Batch.h"
|
||||
#define GLBATCH( call ) batch._##call
|
||||
//#define GLBATCH( call ) call
|
||||
|
||||
using namespace std;
|
||||
|
||||
static int modelPointerTypeId = qRegisterMetaType<QPointer<Model> >();
|
||||
|
@ -430,97 +434,135 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
|
|||
segregateMeshGroups();
|
||||
}
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
// Let's introduce a gpu::Batch to capture all the calls to the graphics api
|
||||
gpu::Batch batch;
|
||||
|
||||
GLBATCH(glEnableClientState)(GL_VERTEX_ARRAY);
|
||||
GLBATCH(glEnableClientState)(GL_NORMAL_ARRAY);
|
||||
|
||||
GLBATCH(glDisable)(GL_COLOR_MATERIAL);
|
||||
|
||||
if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
||||
glDisable(GL_CULL_FACE);
|
||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||
} else {
|
||||
glEnable(GL_CULL_FACE);
|
||||
GLBATCH(glEnable)(GL_CULL_FACE);
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
glCullFace(GL_FRONT);
|
||||
GLBATCH(glCullFace)(GL_FRONT);
|
||||
}
|
||||
}
|
||||
|
||||
// render opaque meshes with alpha testing
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
|
||||
GLBATCH(glDisable)(GL_BLEND);
|
||||
GLBATCH(glEnable)(GL_ALPHA_TEST);
|
||||
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
glAlphaFunc(GL_EQUAL, 0.0f);
|
||||
GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f);
|
||||
}
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
|
||||
|
||||
|
||||
/*Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(
|
||||
mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE);
|
||||
|
||||
*/
|
||||
{
|
||||
GLenum buffers[3];
|
||||
int bufferCount = 0;
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
}
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
}
|
||||
if (mode == DEFAULT_RENDER_MODE) {
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
}
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
|
||||
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
||||
|
||||
|
||||
//renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args);
|
||||
int opaqueMeshPartsRendered = 0;
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
{
|
||||
GLenum buffers[2];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT1;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT2;
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
|
||||
int translucentMeshPartsRendered = 0;
|
||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
||||
|
||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||
GLBATCH(glEnable)(GL_BLEND);
|
||||
GLBATCH(glDepthMask)(false);
|
||||
GLBATCH(glDepthFunc)(GL_LEQUAL);
|
||||
|
||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
|
||||
{
|
||||
GLenum buffers[1];
|
||||
int bufferCount = 0;
|
||||
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
|
||||
GLBATCH(glDrawBuffers)(bufferCount, buffers);
|
||||
}
|
||||
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
||||
}
|
||||
|
||||
glDepthMask(true);
|
||||
glDepthFunc(GL_LESS);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
GLBATCH(glDepthMask)(true);
|
||||
GLBATCH(glDepthFunc)(GL_LESS);
|
||||
GLBATCH(glDisable)(GL_CULL_FACE);
|
||||
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
glCullFace(GL_BACK);
|
||||
GLBATCH(glCullFace)(GL_BACK);
|
||||
}
|
||||
|
||||
|
||||
// deactivate vertex arrays after drawing
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_NORMAL_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_VERTEX_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// bind with 0 to switch back to normal operation
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0);
|
||||
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||
|
||||
// Render!
|
||||
::gpu::backend::renderBatch(batch);
|
||||
batch.clear();
|
||||
|
||||
// restore all the default material settings
|
||||
Application::getInstance()->setupWorldLight();
|
||||
|
||||
|
@ -1506,7 +1548,7 @@ void Model::segregateMeshGroups() {
|
|||
_meshGroupsKnown = true;
|
||||
}
|
||||
|
||||
int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
||||
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
||||
|
||||
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
|
||||
|
@ -1606,16 +1648,21 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
|
||||
ProgramObject* activeProgram = program;
|
||||
Locations* activeLocations = locations;
|
||||
|
||||
|
||||
if (isSkinned) {
|
||||
skinProgram->bind();
|
||||
activeProgram = skinProgram;
|
||||
activeLocations = skinLocations;
|
||||
} else {
|
||||
program->bind();
|
||||
}
|
||||
activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold);
|
||||
|
||||
// This code replace the "bind()" on the QGLProgram
|
||||
if (!activeProgram->isLinked()) {
|
||||
activeProgram->link();
|
||||
}
|
||||
GLBATCH(glUseProgram)(activeProgram->programId());
|
||||
// activeProgram->setUniformValue(activeLocations->alphaThreshold, alphaThreshold);
|
||||
GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold);
|
||||
|
||||
|
||||
|
||||
// i is the "index" from the original networkMeshes QVector...
|
||||
foreach (int i, list) {
|
||||
|
||||
|
@ -1631,7 +1678,8 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
const NetworkMesh& networkMesh = networkMeshes.at(i);
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
|
||||
const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bind();
|
||||
//const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bind();
|
||||
GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, const_cast<QOpenGLBuffer&>(networkMesh.indexBuffer).bufferId());
|
||||
|
||||
int vertexCount = mesh.vertices.size();
|
||||
if (vertexCount == 0) {
|
||||
|
@ -1666,56 +1714,70 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
}
|
||||
}
|
||||
|
||||
const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bind();
|
||||
|
||||
glPushMatrix();
|
||||
Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||
//const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bind();
|
||||
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bufferId());
|
||||
|
||||
GLBATCH(glPushMatrix)();
|
||||
//Application::getInstance()->loadTranslatedViewMatrix(_translation);
|
||||
GLBATCH(glLoadMatrixf)((const GLfloat*)&Application::getInstance()->getUntranslatedViewMatrix());
|
||||
glm::vec3 viewMatTranslation = Application::getInstance()->getViewMatrixTranslation();
|
||||
GLBATCH(glTranslatef)(_translation.x + viewMatTranslation.x, _translation.y + viewMatTranslation.y,
|
||||
_translation.z + viewMatTranslation.z);
|
||||
|
||||
const MeshState& state = _meshStates.at(i);
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
glUniformMatrix4fvARB(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||
GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
|
||||
(const float*)state.clusterMatrices.constData());
|
||||
int offset = (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3) +
|
||||
mesh.texCoords.size() * sizeof(glm::vec2) +
|
||||
(mesh.blendshapes.isEmpty() ? vertexCount * 2 * sizeof(glm::vec3) : 0);
|
||||
skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4);
|
||||
skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT,
|
||||
offset + vertexCount * sizeof(glm::vec4), 4);
|
||||
skinProgram->enableAttributeArray(skinLocations->clusterIndices);
|
||||
skinProgram->enableAttributeArray(skinLocations->clusterWeights);
|
||||
//skinProgram->setAttributeBuffer(skinLocations->clusterIndices, GL_FLOAT, offset, 4);
|
||||
GLBATCH(glVertexAttribPointer)(skinLocations->clusterIndices, 4, GL_FLOAT, GL_TRUE, 0, (const void*) offset);
|
||||
//skinProgram->setAttributeBuffer(skinLocations->clusterWeights, GL_FLOAT,
|
||||
// offset + vertexCount * sizeof(glm::vec4), 4);
|
||||
GLBATCH(glVertexAttribPointer)(skinLocations->clusterWeights, 4, GL_FLOAT, GL_TRUE, 0, (const void*) (offset + vertexCount * sizeof(glm::vec4)));
|
||||
//skinProgram->enableAttributeArray(skinLocations->clusterIndices);
|
||||
GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterIndices);
|
||||
//skinProgram->enableAttributeArray(skinLocations->clusterWeights);
|
||||
GLBATCH(glEnableVertexAttribArray)(skinLocations->clusterWeights);
|
||||
} else {
|
||||
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
||||
GLBATCH(glMultMatrixf)((const GLfloat*)&state.clusterMatrices[0]);
|
||||
}
|
||||
|
||||
if (mesh.blendshapes.isEmpty()) {
|
||||
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
|
||||
activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
||||
activeProgram->enableAttributeArray(activeLocations->tangent);
|
||||
//activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
||||
GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, (const void*)(vertexCount * 2 * sizeof(glm::vec3)));
|
||||
//activeProgram->enableAttributeArray(activeLocations->tangent);
|
||||
GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent);
|
||||
}
|
||||
glColorPointer(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
|
||||
GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
|
||||
mesh.tangents.size() * sizeof(glm::vec3)));
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
|
||||
GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)(vertexCount * 2 * sizeof(glm::vec3) +
|
||||
(mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
|
||||
|
||||
} else {
|
||||
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
|
||||
activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3);
|
||||
activeProgram->enableAttributeArray(activeLocations->tangent);
|
||||
//activeProgram->setAttributeBuffer(activeLocations->tangent, GL_FLOAT, 0, 3);
|
||||
GLBATCH(glVertexAttribPointer)(activeLocations->tangent, 3, GL_FLOAT, GL_TRUE, 0, 0);
|
||||
//activeProgram->enableAttributeArray(activeLocations->tangent);
|
||||
GLBATCH(glEnableVertexAttribArray)(activeLocations->tangent);
|
||||
}
|
||||
glColorPointer(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3)));
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
|
||||
_blendedVertexBuffers[i].bind();
|
||||
GLBATCH(glColorPointer)(3, GL_FLOAT, 0, (void*)(mesh.tangents.size() * sizeof(glm::vec3)));
|
||||
GLBATCH(glTexCoordPointer)(2, GL_FLOAT, 0, (void*)((mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
|
||||
// _blendedVertexBuffers[i].bind();
|
||||
GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, _blendedVertexBuffers[i].bufferId());
|
||||
}
|
||||
glVertexPointer(3, GL_FLOAT, 0, 0);
|
||||
glNormalPointer(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
|
||||
GLBATCH(glVertexPointer)(3, GL_FLOAT, 0, 0);
|
||||
GLBATCH(glNormalPointer)(GL_FLOAT, 0, (void*)(vertexCount * sizeof(glm::vec3)));
|
||||
|
||||
if (!mesh.colors.isEmpty()) {
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
GLBATCH(glEnableClientState)(GL_COLOR_ARRAY);
|
||||
} else {
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
if (!mesh.texCoords.isEmpty()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
GLBATCH(glEnableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
qint64 offset = 0;
|
||||
|
@ -1726,9 +1788,10 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
offset += (part.quadIndices.size() + part.triangleIndices.size()) * sizeof(int);
|
||||
continue;
|
||||
}
|
||||
|
||||
// apply material properties
|
||||
if (mode == SHADOW_RENDER_MODE) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||
|
||||
} else {
|
||||
if (dontReduceMaterialSwitches || lastMaterialID != part.materialID) {
|
||||
|
@ -1741,36 +1804,36 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
|
||||
glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity);
|
||||
if (!(translucent && alphaThreshold == 0.0f)) {
|
||||
glAlphaFunc(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity());
|
||||
GLBATCH(glAlphaFunc)(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity());
|
||||
}
|
||||
glm::vec4 specular = glm::vec4(part.specularColor, 1.0f);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, part.shininess);
|
||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||
GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.f ? 128.f: part.shininess));
|
||||
|
||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||
if (mesh.isEye && diffuseMap) {
|
||||
diffuseMap = (_dilatedTextures[i][j] =
|
||||
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, !diffuseMap ?
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ?
|
||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
||||
|
||||
if (!mesh.tangents.isEmpty()) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
GLBATCH(glActiveTexture)(GL_TEXTURE1);
|
||||
Texture* normalMap = networkPart.normalTexture.data();
|
||||
glBindTexture(GL_TEXTURE_2D, !normalMap ?
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !normalMap ?
|
||||
Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
if (specularTextureUnit) {
|
||||
glActiveTexture(specularTextureUnit);
|
||||
GLBATCH(glActiveTexture)(specularTextureUnit);
|
||||
Texture* specularMap = networkPart.specularTexture.data();
|
||||
glBindTexture(GL_TEXTURE_2D, !specularMap ?
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ?
|
||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||
}
|
||||
if (args) {
|
||||
args->_materialSwitches++;
|
||||
|
@ -1783,12 +1846,12 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
meshPartsRendered++;
|
||||
|
||||
if (part.quadIndices.size() > 0) {
|
||||
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
|
||||
GLBATCH(glDrawRangeElements)(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
|
||||
offset += part.quadIndices.size() * sizeof(int);
|
||||
}
|
||||
|
||||
if (part.triangleIndices.size() > 0) {
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
|
||||
GLBATCH(glDrawRangeElements)(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
|
||||
GL_UNSIGNED_INT, (void*)offset);
|
||||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
}
|
||||
|
@ -1802,35 +1865,39 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
|
|||
}
|
||||
|
||||
if (!mesh.colors.isEmpty()) {
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_COLOR_ARRAY);
|
||||
}
|
||||
if (!mesh.texCoords.isEmpty()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
GLBATCH(glDisableClientState)(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLBATCH(glActiveTexture)(GL_TEXTURE1);
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||
|
||||
activeProgram->disableAttributeArray(activeLocations->tangent);
|
||||
// activeProgram->disableAttributeArray(activeLocations->tangent);
|
||||
GLBATCH(glDisableVertexAttribArray)(activeLocations->tangent);
|
||||
}
|
||||
|
||||
if (specularTextureUnit) {
|
||||
glActiveTexture(specularTextureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
GLBATCH(glActiveTexture)(specularTextureUnit);
|
||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
if (state.clusterMatrices.size() > 1) {
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
||||
skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
// skinProgram->disableAttributeArray(skinLocations->clusterIndices);
|
||||
GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterIndices);
|
||||
// skinProgram->disableAttributeArray(skinLocations->clusterWeights);
|
||||
GLBATCH(glDisableVertexAttribArray)(skinLocations->clusterWeights);
|
||||
}
|
||||
glPopMatrix();
|
||||
GLBATCH(glPopMatrix)();
|
||||
|
||||
}
|
||||
activeProgram->release();
|
||||
|
||||
//activeProgram->release();
|
||||
GLBATCH(glUseProgram)(0);
|
||||
|
||||
return meshPartsRendered;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ class ViewFrustum;
|
|||
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
||||
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||
|
||||
namespace gpu {
|
||||
class Batch;
|
||||
}
|
||||
|
||||
/// A generic 3D model displaying geometry loaded from a URL.
|
||||
class Model : public QObject, public PhysicsEntity {
|
||||
Q_OBJECT
|
||||
|
@ -255,7 +259,7 @@ private:
|
|||
|
||||
void applyNextGeometry();
|
||||
void deleteGeometry();
|
||||
int renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL);
|
||||
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL);
|
||||
QVector<JointState> createJointStates(const FBXGeometry& geometry);
|
||||
void initJointTransforms();
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <qnetworkrequest.h>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <OAuthNetworkAccessManager.h>
|
||||
|
||||
#include "DataWebPage.h"
|
||||
|
@ -19,13 +22,22 @@ DataWebPage::DataWebPage(QObject* parent) :
|
|||
// use an OAuthNetworkAccessManager instead of regular QNetworkAccessManager so our requests are authed
|
||||
setNetworkAccessManager(OAuthNetworkAccessManager::getInstance());
|
||||
|
||||
// have the page delegate external links so they can be captured by the Application in case they are a hifi link
|
||||
setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);
|
||||
|
||||
// give the page an empty stylesheet
|
||||
settings()->setUserStyleSheetUrl(QUrl());
|
||||
}
|
||||
|
||||
void DataWebPage::javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID) {
|
||||
qDebug() << "JS console message at line" << lineNumber << "from" << sourceID << "-" << message;
|
||||
}
|
||||
|
||||
bool DataWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type) {
|
||||
|
||||
if (!request.url().toString().startsWith(HIFI_URL_SCHEME)) {
|
||||
return true;
|
||||
} else {
|
||||
// this is a hifi URL - have the AddressManager handle it
|
||||
QMetaObject::invokeMethod(&AddressManager::getInstance(), "handleLookupString",
|
||||
Qt::AutoConnection, Q_ARG(const QString&, request.url().toString()));
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ public:
|
|||
DataWebPage(QObject* parent = 0);
|
||||
protected:
|
||||
void javaScriptConsoleMessage(const QString & message, int lineNumber, const QString & sourceID);
|
||||
bool acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type);
|
||||
};
|
||||
|
||||
#endif // hifi_DataWebPage_h
|
|
@ -212,7 +212,7 @@ void Player::loadRecording(RecordingPointer recording) {
|
|||
|
||||
void Player::play() {
|
||||
computeCurrentFrame();
|
||||
if (_currentFrame < 0 || (_currentFrame >= _recording->getFrameNumber() - 1)) {
|
||||
if (_currentFrame < 0 || (_currentFrame >= _recording->getFrameNumber() - 2)) { // -2 because of interpolation
|
||||
if (_loop) {
|
||||
loopRecording();
|
||||
} else {
|
||||
|
|
|
@ -2486,8 +2486,39 @@ bool Heightfield::intersects(const glm::vec3& start, const glm::vec3& end, float
|
|||
if (!getBounds().findRayIntersection(start, direction, rayDistance) || rayDistance > 1.0f) {
|
||||
return false;
|
||||
}
|
||||
glm::vec3 entry = (start + direction * rayDistance - getBounds().minimum) / _increment;
|
||||
direction /= _increment;
|
||||
glm::vec3 entry = start + direction * rayDistance;
|
||||
const float DISTANCE_THRESHOLD = 0.001f;
|
||||
if (glm::abs(entry.x - getBounds().minimum.x) < DISTANCE_THRESHOLD) {
|
||||
normal = glm::vec3(-1.0f, 0.0f, 0.0f);
|
||||
distance = rayDistance;
|
||||
return true;
|
||||
|
||||
} else if (glm::abs(entry.x - getBounds().maximum.x) < DISTANCE_THRESHOLD) {
|
||||
normal = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
distance = rayDistance;
|
||||
return true;
|
||||
|
||||
} else if (glm::abs(entry.y - getBounds().minimum.y) < DISTANCE_THRESHOLD) {
|
||||
normal = glm::vec3(0.0f, -1.0f, 0.0f);
|
||||
distance = rayDistance;
|
||||
return true;
|
||||
|
||||
} else if (glm::abs(entry.y - getBounds().maximum.y) < DISTANCE_THRESHOLD) {
|
||||
normal = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
distance = rayDistance;
|
||||
return true;
|
||||
|
||||
} else if (glm::abs(entry.z - getBounds().minimum.z) < DISTANCE_THRESHOLD) {
|
||||
normal = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
distance = rayDistance;
|
||||
return true;
|
||||
|
||||
} else if (glm::abs(entry.z - getBounds().maximum.z) < DISTANCE_THRESHOLD) {
|
||||
normal = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
distance = rayDistance;
|
||||
return true;
|
||||
}
|
||||
entry = (entry - getBounds().minimum) / _increment;
|
||||
glm::vec3 floors = glm::floor(entry);
|
||||
glm::vec3 ceils = glm::ceil(entry);
|
||||
if (floors.x == ceils.x) {
|
||||
|
|
|
@ -998,10 +998,13 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
|
|||
_spannerBounds.maximum = (glm::ceil(_bounds.maximum / increment) + glm::vec3(1.0f, 0.0f, 1.0f)) * increment;
|
||||
_spannerBounds.minimum.y = bounds.minimum.y;
|
||||
_spannerBounds.maximum.y = bounds.maximum.y;
|
||||
_heightfieldWidth = (int)glm::round((_spannerBounds.maximum.x - _spannerBounds.minimum.x) / increment) + 1;
|
||||
_heightfieldHeight = (int)glm::round((_spannerBounds.maximum.z - _spannerBounds.minimum.z) / increment) + 1;
|
||||
_heightfieldWidth = (int)glm::round((_spannerBounds.maximum.x - _spannerBounds.minimum.x) / increment);
|
||||
_heightfieldHeight = (int)glm::round((_spannerBounds.maximum.z - _spannerBounds.minimum.z) / increment);
|
||||
int heightfieldArea = _heightfieldWidth * _heightfieldHeight;
|
||||
_spanner = spanner = new Heightfield(_spannerBounds, increment, QByteArray(heightfieldArea, 0),
|
||||
Box innerBounds = _spannerBounds;
|
||||
innerBounds.maximum.x -= increment;
|
||||
innerBounds.maximum.z -= increment;
|
||||
_spanner = spanner = new Heightfield(innerBounds, increment, QByteArray(heightfieldArea, 0),
|
||||
QByteArray(heightfieldArea * DataBlock::COLOR_BYTES, 0), QByteArray(heightfieldArea, 0),
|
||||
QVector<SharedObjectPointer>());
|
||||
}
|
||||
|
@ -1049,18 +1052,20 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
|
|||
}
|
||||
|
||||
// if all is gone, clear the node
|
||||
if (!foundNonZero) {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0),
|
||||
encodeInline<HeightfieldHeightDataPointer>(HeightfieldHeightDataPointer()));
|
||||
info.outputValues[1] = AttributeValue(_outputs.at(1),
|
||||
encodeInline<HeightfieldColorDataPointer>(HeightfieldColorDataPointer()));
|
||||
info.outputValues[2] = AttributeValue(_outputs.at(2),
|
||||
encodeInline<HeightfieldMaterialDataPointer>(HeightfieldMaterialDataPointer()));
|
||||
return STOP_RECURSION;
|
||||
if (foundNonZero) {
|
||||
HeightfieldHeightDataPointer newHeightPointer(new HeightfieldHeightData(contents));
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldHeightDataPointer>(newHeightPointer));
|
||||
|
||||
} else {
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0));
|
||||
}
|
||||
|
||||
HeightfieldHeightDataPointer newHeightPointer(new HeightfieldHeightData(contents));
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldHeightDataPointer>(newHeightPointer));
|
||||
// allow a border for what we clear in terms of color/material
|
||||
innerBounds.minimum.x += increment;
|
||||
innerBounds.minimum.z += increment;
|
||||
innerBounds.maximum.x -= increment;
|
||||
innerBounds.maximum.z -= increment;
|
||||
innerOverlap = bounds.getIntersection(innerBounds);
|
||||
|
||||
HeightfieldColorDataPointer colorPointer = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||
if (colorPointer) {
|
||||
|
@ -1083,18 +1088,25 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
|
|||
memcpy(dest, src, destWidth * DataBlock::COLOR_BYTES);
|
||||
}
|
||||
|
||||
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
|
||||
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
|
||||
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
|
||||
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
|
||||
dest = contents.data() + (destY * size + destX) * DataBlock::COLOR_BYTES;
|
||||
|
||||
for (int y = 0; y < destHeight; y++, dest += size * DataBlock::COLOR_BYTES) {
|
||||
memset(dest, 0, destWidth * DataBlock::COLOR_BYTES);
|
||||
if (foundNonZero) {
|
||||
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
|
||||
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
|
||||
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
|
||||
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
|
||||
if (destWidth > 0 && destHeight > 0) {
|
||||
dest = contents.data() + (destY * size + destX) * DataBlock::COLOR_BYTES;
|
||||
|
||||
for (int y = 0; y < destHeight; y++, dest += size * DataBlock::COLOR_BYTES) {
|
||||
memset(dest, 0, destWidth * DataBlock::COLOR_BYTES);
|
||||
}
|
||||
|
||||
HeightfieldColorDataPointer newColorPointer(new HeightfieldColorData(contents));
|
||||
info.outputValues[1] = AttributeValue(_outputs.at(1),
|
||||
encodeInline<HeightfieldColorDataPointer>(newColorPointer));
|
||||
}
|
||||
} else {
|
||||
info.outputValues[1] = AttributeValue(_outputs.at(1));
|
||||
}
|
||||
|
||||
HeightfieldColorDataPointer newColorPointer(new HeightfieldColorData(contents));
|
||||
info.outputValues[1] = AttributeValue(_outputs.at(1), encodeInline<HeightfieldColorDataPointer>(newColorPointer));
|
||||
}
|
||||
|
||||
HeightfieldMaterialDataPointer materialPointer = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
|
||||
|
@ -1130,20 +1142,26 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
|
|||
}
|
||||
}
|
||||
|
||||
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
|
||||
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
|
||||
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
|
||||
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
|
||||
dest = (uchar*)contents.data() + destY * size + destX;
|
||||
|
||||
for (int y = 0; y < destHeight; y++, dest += size) {
|
||||
memset(dest, 0, destWidth);
|
||||
if (foundNonZero) {
|
||||
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
|
||||
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
|
||||
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
|
||||
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
|
||||
if (destWidth > 0 && destHeight > 0) {
|
||||
dest = (uchar*)contents.data() + destY * size + destX;
|
||||
|
||||
for (int y = 0; y < destHeight; y++, dest += size) {
|
||||
memset(dest, 0, destWidth);
|
||||
}
|
||||
|
||||
clearUnusedMaterials(materials, contents);
|
||||
HeightfieldMaterialDataPointer newMaterialPointer(new HeightfieldMaterialData(contents, materials));
|
||||
info.outputValues[2] = AttributeValue(_outputs.at(2),
|
||||
encodeInline<HeightfieldMaterialDataPointer>(newMaterialPointer));
|
||||
}
|
||||
} else {
|
||||
info.outputValues[2] = AttributeValue(_outputs.at(2));
|
||||
}
|
||||
|
||||
clearUnusedMaterials(materials, contents);
|
||||
HeightfieldMaterialDataPointer newMaterialPointer(new HeightfieldMaterialData(contents, materials));
|
||||
info.outputValues[2] = AttributeValue(_outputs.at(2),
|
||||
encodeInline<HeightfieldMaterialDataPointer>(newMaterialPointer));
|
||||
}
|
||||
|
||||
return STOP_RECURSION;
|
||||
|
|
Loading…
Reference in a new issue