mirror of
https://github.com/overte-org/overte.git
synced 2025-04-24 12:13:36 +02:00
view cull mesh parts
This commit is contained in:
parent
eab96587fe
commit
46cb780aa5
4 changed files with 84 additions and 13 deletions
|
@ -15,9 +15,9 @@
|
|||
|
||||
#include "Joystick.h"
|
||||
|
||||
const float MAX_AXIS = 32768.0f;
|
||||
|
||||
#ifdef HAVE_SDL2
|
||||
const float MAX_AXIS = 32768.0f;
|
||||
|
||||
Joystick::Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController) :
|
||||
_instanceId(instanceId),
|
||||
|
|
|
@ -59,7 +59,7 @@ int RenderableModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned c
|
|||
|
||||
|
||||
void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableModelEntityItem::render");
|
||||
PerformanceTimer perfTimer("RMEIrender");
|
||||
assert(getType() == EntityTypes::Model);
|
||||
|
||||
bool drawAsModel = hasModel();
|
||||
|
@ -119,7 +119,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
// TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render
|
||||
// is significantly more expensive. Is there a way to call this that doesn't cost us as much?
|
||||
PerformanceTimer perfTimer("model->render");
|
||||
_model->render(alpha, modelRenderMode);
|
||||
_model->render(alpha, modelRenderMode, args);
|
||||
} else {
|
||||
// if we couldn't get a model, then just draw a cube
|
||||
glColor3ub(getColor()[RED_INDEX],getColor()[GREEN_INDEX],getColor()[BLUE_INDEX]);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <CapsuleShape.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <PerfStat.h>
|
||||
#include <PhysicsEntity.h>
|
||||
#include <ShapeCollider.h>
|
||||
#include <SphereShape.h>
|
||||
|
@ -44,7 +45,8 @@ Model::Model(QObject* parent) :
|
|||
_pupilDilation(0.0f),
|
||||
_url("http://invalid.com"),
|
||||
_blendNumber(0),
|
||||
_appliedBlendNumber(0) {
|
||||
_appliedBlendNumber(0),
|
||||
_calculatedMeshBoxesValid(false) {
|
||||
|
||||
// we may have been created in the network thread, but we live in the main thread
|
||||
moveToThread(Application::getInstance()->thread());
|
||||
|
@ -384,7 +386,7 @@ void Model::setJointStates(QVector<JointState> states) {
|
|||
_boundingRadius = radius;
|
||||
}
|
||||
|
||||
bool Model::render(float alpha, RenderMode mode) {
|
||||
bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
|
||||
// render the attachments
|
||||
foreach (Model* attachment, _attachments) {
|
||||
attachment->render(alpha, mode);
|
||||
|
@ -392,6 +394,23 @@ bool Model::render(float alpha, RenderMode mode) {
|
|||
if (_meshStates.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we don't have valid mesh boxes, calculate them now, this only matters in cases
|
||||
// where our caller has passed RenderArgs which will include a view frustum we can cull
|
||||
// against. We cache the results of these calculations so long as the model hasn't been
|
||||
// simulated and the mesh hasn't changed.
|
||||
if (args && !_calculatedMeshBoxesValid) {
|
||||
PerformanceTimer perfTimer("calculatedMeshBoxes");
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
int numberOfMeshes = geometry.meshes.size();
|
||||
_calculatedMeshBoxes.resize(numberOfMeshes);
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents);
|
||||
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
||||
}
|
||||
_calculatedMeshBoxesValid = true;
|
||||
}
|
||||
|
||||
// set up dilated textures on first render after load/simulate
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
|
@ -431,11 +450,12 @@ bool Model::render(float alpha, RenderMode mode) {
|
|||
mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE,
|
||||
mode == DEFAULT_RENDER_MODE);
|
||||
|
||||
renderMeshes(mode, false);
|
||||
const float DEFAULT_ALPHA_THRESHOLD = 0.5f;
|
||||
renderMeshes(mode, false, DEFAULT_ALPHA_THRESHOLD, args);
|
||||
|
||||
// render translucent meshes afterwards
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||
renderMeshes(mode, true, 0.75f);
|
||||
renderMeshes(mode, true, 0.75f, args);
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
@ -445,7 +465,7 @@ bool Model::render(float alpha, RenderMode mode) {
|
|||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true);
|
||||
|
||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||
renderMeshes(mode, true, 0.0f);
|
||||
renderMeshes(mode, true, 0.0f, args);
|
||||
}
|
||||
|
||||
glDepthMask(true);
|
||||
|
@ -511,6 +531,22 @@ Extents Model::getUnscaledMeshExtents() const {
|
|||
return scaledExtents;
|
||||
}
|
||||
|
||||
Extents Model::calculateScaledOffsetExtents(const Extents& extents) const {
|
||||
// we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix
|
||||
glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f));
|
||||
glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f));
|
||||
|
||||
Extents scaledOffsetExtents = { ((minimum + _offset) * _scale),
|
||||
((maximum + _offset) * _scale) };
|
||||
|
||||
Extents rotatedExtents = scaledOffsetExtents.getRotated(_rotation);
|
||||
|
||||
Extents translatedExtents = { rotatedExtents.minimum + _translation,
|
||||
rotatedExtents.maximum + _translation };
|
||||
return translatedExtents;
|
||||
}
|
||||
|
||||
|
||||
bool Model::getJointState(int index, glm::quat& rotation) const {
|
||||
if (index == -1 || index >= _jointStates.size()) {
|
||||
return false;
|
||||
|
@ -790,6 +826,8 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
|
|||
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
||||
|
||||
if (isActive() && fullUpdate) {
|
||||
_calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid
|
||||
|
||||
// check for scale to fit
|
||||
if (_scaleToFit && !_scaledToFit) {
|
||||
scaleToFit();
|
||||
|
@ -1200,10 +1238,12 @@ void Model::deleteGeometry() {
|
|||
_blendedBlendshapeCoefficients.clear();
|
||||
}
|
||||
|
||||
void Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold) {
|
||||
void Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args) {
|
||||
updateVisibleJointStates();
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||
|
||||
bool cullMeshParts = args && !Menu::getInstance()->isOptionChecked(MenuOption::DontCullMeshParts);
|
||||
|
||||
for (int i = 0; i < networkMeshes.size(); i++) {
|
||||
// exit early if the translucency doesn't match what we're drawing
|
||||
|
@ -1221,6 +1261,23 @@ void Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold
|
|||
continue;
|
||||
}
|
||||
|
||||
// if we got here, then check to see if this mesh is in view
|
||||
if (args) {
|
||||
bool shouldRender = true;
|
||||
args->_meshesConsidered++;
|
||||
|
||||
if (cullMeshParts && args->_viewFrustum) {
|
||||
shouldRender = args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
|
||||
}
|
||||
|
||||
if (shouldRender) {
|
||||
args->_meshesRendered++;
|
||||
} else {
|
||||
args->_meshesOutOfView++;
|
||||
continue; // skip this mesh
|
||||
}
|
||||
}
|
||||
|
||||
const_cast<QOpenGLBuffer&>(networkMesh.vertexBuffer).bind();
|
||||
|
||||
ProgramObject* program = &_program;
|
||||
|
@ -1372,6 +1429,13 @@ void Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold
|
|||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
|
||||
GL_UNSIGNED_INT, (void*)offset);
|
||||
offset += part.triangleIndices.size() * sizeof(int);
|
||||
|
||||
if (args) {
|
||||
const int INDICES_PER_TRIANGLE = 3;
|
||||
const int INDICES_PER_QUAD = 4;
|
||||
args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE;
|
||||
args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mesh.colors.isEmpty()) {
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
#include <PhysicsEntity.h>
|
||||
|
||||
#include <AABox.h>
|
||||
#include <AnimationCache.h>
|
||||
#include <PhysicsEntity.h>
|
||||
|
||||
#include "GeometryCache.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
@ -30,6 +30,7 @@ class QScriptEngine;
|
|||
|
||||
class AnimationHandle;
|
||||
class Shape;
|
||||
class RenderArgs;
|
||||
|
||||
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
||||
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||
|
@ -84,7 +85,7 @@ public:
|
|||
|
||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE };
|
||||
|
||||
bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE);
|
||||
bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL);
|
||||
|
||||
/// Sets the URL of the model to render.
|
||||
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
||||
|
@ -107,6 +108,9 @@ public:
|
|||
/// Returns the unscaled extents of the model's mesh
|
||||
Extents getUnscaledMeshExtents() const;
|
||||
|
||||
/// Returns the scaled equivalent of some extents in model space.
|
||||
Extents calculateScaledOffsetExtents(const Extents& extents) const;
|
||||
|
||||
/// Returns a reference to the shared geometry.
|
||||
const QSharedPointer<NetworkGeometry>& getGeometry() const { return _geometry; }
|
||||
|
||||
|
@ -247,7 +251,7 @@ private:
|
|||
|
||||
void applyNextGeometry();
|
||||
void deleteGeometry();
|
||||
void renderMeshes(RenderMode mode, bool translucent, float alphaThreshold = 0.5f);
|
||||
void renderMeshes(RenderMode mode, bool translucent, float alphaThreshold = 0.5f, RenderArgs* args = NULL);
|
||||
QVector<JointState> createJointStates(const FBXGeometry& geometry);
|
||||
void initJointTransforms();
|
||||
|
||||
|
@ -325,6 +329,9 @@ private:
|
|||
static SkinLocations _skinTranslucentLocations;
|
||||
|
||||
static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1);
|
||||
|
||||
QVector<AABox> _calculatedMeshBoxes;
|
||||
bool _calculatedMeshBoxesValid;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QPointer<Model>)
|
||||
|
|
Loading…
Reference in a new issue