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

This commit is contained in:
Atlante45 2014-10-16 11:09:33 -07:00
commit d7d0a45990
12 changed files with 163 additions and 96 deletions

View file

@ -8,7 +8,7 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Creates single flexible vertlet-integrated strands that can be used for hair/fur/grass
// Creates single flexible verlet-integrated strands that can be used for hair/fur/grass
#include "Hair.h"
@ -39,7 +39,7 @@ Hair::Hair(int strands,
_angularVelocity(0.0f),
_angularAcceleration(0.0f),
_gravity(0.0f),
_loudness()
_loudness(0.0f)
{
_hairPosition = new glm::vec3[_strands * _links];
_hairOriginalPosition = new glm::vec3[_strands * _links];
@ -90,7 +90,9 @@ Hair::Hair(int strands,
}
}
}
}
}
const float SOUND_THRESHOLD = 50.0f;
void Hair::simulate(float deltaTime) {
deltaTime = glm::clamp(deltaTime, 0.0f, 1.0f / 30.0f);
@ -119,10 +121,10 @@ void Hair::simulate(float deltaTime) {
(_radius - glm::length(_hairPosition[vertexIndex]));
}
// Add random thing driven by loudness
const float LOUD_BASE = 0.0005f;
float loudnessFactor = (_loudness > 0.0f) ? logf(_loudness) / 2000.0f : 0.0f;
float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 8000.0f : 0.0f;
_hairPosition[vertexIndex] += randVector() * (LOUD_BASE + loudnessFactor) * ((float)link / (float)_links);
const float QUIESCENT_LOUDNESS = 0.0f;
_hairPosition[vertexIndex] += randVector() * (QUIESCENT_LOUDNESS + loudnessFactor) * ((float)link / (float)_links);
// Add gravity
const float SCALE_GRAVITY = 0.10f;
@ -178,7 +180,7 @@ void Hair::simulate(float deltaTime) {
}
}
// Store start position for next vertlet pass
// Store start position for next verlet pass
_hairLastPosition[vertexIndex] = thisPosition;
}
}
@ -189,9 +191,9 @@ void Hair::render() {
//
// Before calling this function, translate/rotate to the origin of the owning object
//
float loudnessFactor = (_loudness > 0.0f) ? logf(_loudness) / 16.0f : 0.0f;
float loudnessFactor = (_loudness > SOUND_THRESHOLD) ? logf(_loudness - SOUND_THRESHOLD) / 16.0f : 0.0f;
const int SPARKLE_EVERY = 5;
const float HAIR_SETBACK = 0.125f;
const float HAIR_SETBACK = 0.0f;
int sparkleIndex = (int) (randFloat() * SPARKLE_EVERY);
glPushMatrix();
glTranslatef(0.f, 0.f, HAIR_SETBACK);

View file

@ -122,7 +122,8 @@ Menu::Menu() :
_hasLoginDialogDisplayed(false),
_snapshotsLocation(),
_scriptsLocation(),
_walletPrivateKey()
_walletPrivateKey(),
_shouldRenderTableNeedsRebuilding(true)
{
Application *appInstance = Application::getInstance();
@ -419,10 +420,12 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderFocusIndicator, 0, false);
QMenu* modelDebugMenu = developerMenu->addMenu("Models");
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DontCullMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelBounds, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementProxy, 0, false);
addCheckableActionToQMenuAndActionHash(modelDebugMenu, MenuOption::DisplayModelElementChildProxies, 0, false);
QMenu* modelCullingMenu = modelDebugMenu->addMenu("Culling");
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullOutOfViewMeshParts, 0, false);
addCheckableActionToQMenuAndActionHash(modelCullingMenu, MenuOption::DontCullTooSmallMeshParts, 0, false);
QMenu* voxelOptionsMenu = developerMenu->addMenu("Voxels");
addCheckableActionToQMenuAndActionHash(voxelOptionsMenu, MenuOption::VoxelTextures);
@ -1547,6 +1550,7 @@ void Menu::autoAdjustLOD(float currentFPS) {
&& _voxelSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
_voxelSizeScale *= ADJUST_LOD_DOWN_BY;
if (_voxelSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
_voxelSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
}
@ -1569,6 +1573,7 @@ void Menu::autoAdjustLOD(float currentFPS) {
}
if (changed) {
_shouldRenderTableNeedsRebuilding = true;
if (_lodToolsDialog) {
_lodToolsDialog->reloadSliders();
}
@ -1583,14 +1588,56 @@ void Menu::resetLODAdjust() {
void Menu::setVoxelSizeScale(float sizeScale) {
_voxelSizeScale = sizeScale;
_shouldRenderTableNeedsRebuilding = true;
bumpSettings();
}
void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
_boundaryLevelAdjust = boundaryLevelAdjust;
_shouldRenderTableNeedsRebuilding = true;
bumpSettings();
}
// TODO: This is essentially the same logic used to render voxels, but since models are more detailed then voxels
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) {
const float voxelToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
float voxelSizeScale = getVoxelSizeScale();
int boundaryLevelAdjust = getBoundaryLevelAdjust();
float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, voxelSizeScale) / voxelToMeshRatio;
if (_shouldRenderTableNeedsRebuilding) {
_shouldRenderTable.clear();
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
float scale = maxScale;
float visibleDistanceAtScale = visibleDistanceAtMaxScale;
while (scale > SMALLEST_SCALE_IN_TABLE) {
scale /= 2.0f;
visibleDistanceAtScale /= 2.0f;
_shouldRenderTable[scale] = visibleDistanceAtScale;
}
_shouldRenderTableNeedsRebuilding = false;
}
float closestScale = maxScale;
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
QMap<float, float>::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension);
if (lowerBound != _shouldRenderTable.constEnd()) {
closestScale = lowerBound.key();
visibleDistanceAtClosestScale = lowerBound.value();
}
if (closestScale < largestDimension) {
visibleDistanceAtClosestScale *= 2.0f;
}
return (distanceToCamera <= visibleDistanceAtClosestScale);
}
void Menu::lodTools() {
if (!_lodToolsDialog) {
_lodToolsDialog = new LodToolsDialog(Application::getInstance()->getGLWidget());

View file

@ -143,6 +143,8 @@ public:
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
#ifdef Q_OS_MAC
SpeechRecognizer* getSpeechRecognizer() { return &_speechRecognizer; }
#endif
@ -310,6 +312,9 @@ private:
QString _snapshotsLocation;
QString _scriptsLocation;
QByteArray _walletPrivateKey;
bool _shouldRenderTableNeedsRebuilding;
QMap<float, float> _shouldRenderTable;
};
@ -367,7 +372,8 @@ namespace MenuOption {
const QString Collisions = "Collisions";
const QString Console = "Console...";
const QString ControlWithSpeech = "Control With Speech";
const QString DontCullMeshParts = "Don't Cull Mesh Parts";
const QString DontCullOutOfViewMeshParts = "Don't Cull Out Of View Mesh Parts";
const QString DontCullTooSmallMeshParts = "Don't Cull Too Small Mesh Parts";
const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DecreaseVoxelSize = "Decrease Voxel Size";
const QString DisableActivityLogger = "Disable Activity Logger";

View file

@ -162,36 +162,6 @@ void renderElementProxy(EntityTreeElement* entityTreeElement) {
}
}
float EntityTreeRenderer::distanceToCamera(const glm::vec3& center, const ViewFrustum& viewFrustum) const {
glm::vec3 temp = viewFrustum.getPosition() - center;
float distanceToVoxelCenter = sqrtf(glm::dot(temp, temp));
return distanceToVoxelCenter;
}
// TODO: This could be optimized to be a table, or something that doesn't require recalculation on every
// render call for every entity
// TODO: This is essentially the same logic used to render voxels, but since models are more detailed then voxels
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool EntityTreeRenderer::shouldRenderEntity(float largestDimension, float distanceToCamera) const {
const float voxelToModelRatio = 4.0f; // must be this many times closer to a model than a voxel to see it.
float voxelSizeScale = Menu::getInstance()->getVoxelSizeScale();
int boundaryLevelAdjust = Menu::getInstance()->getBoundaryLevelAdjust();
float scale = (float)TREE_SCALE;
float visibleDistanceAtScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, voxelSizeScale) / voxelToModelRatio;
while (scale > largestDimension) {
scale /= 2.0f;
visibleDistanceAtScale /= 2.0f;
}
if (scale < largestDimension) {
visibleDistanceAtScale *= 2.0f;
}
return (distanceToCamera <= visibleDistanceAtScale);
}
void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) {
bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE;
bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds);
@ -287,7 +257,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
// TODO: some entity types (like lights) might want to be rendered even
// when they are outside of the view frustum...
float distance = distanceToCamera(entityBox.calcCenter(), *args->_viewFrustum);
float distance = args->_viewFrustum->distanceToCamera(entityBox.calcCenter());
if (wantDebug) {
qDebug() << "------- renderElement() ----------";
@ -299,24 +269,28 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args)
qDebug() << " entityBox:" << entityItem->getAABox();
qDebug() << " dimensions:" << entityItem->getDimensionsInMeters() << "in meters";
qDebug() << " largestDimension:" << entityBox.getLargestDimension() << "in meters";
qDebug() << " shouldRender:" << shouldRenderEntity(entityBox.getLargestDimension(), distance);
qDebug() << " shouldRender:" << Menu::getInstance()->shouldRenderMesh(entityBox.getLargestDimension(), distance);
qDebug() << " in frustum:" << (args->_viewFrustum->boxInFrustum(entityBox) != ViewFrustum::OUTSIDE);
}
if (shouldRenderEntity(entityBox.getLargestDimension(), distance) &&
args->_viewFrustum->boxInFrustum(entityBox) != ViewFrustum::OUTSIDE) {
renderProxies(entityItem, args);
Glower* glower = NULL;
if (entityItem->getGlowLevel() > 0.0f) {
glower = new Glower(entityItem->getGlowLevel());
}
entityItem->render(args);
args->_itemsRendered++;
if (glower) {
delete glower;
bool outOfView = args->_viewFrustum->boxInFrustum(entityBox) == ViewFrustum::OUTSIDE;
if (!outOfView) {
bool bigEnoughToRender = Menu::getInstance()->shouldRenderMesh(entityBox.getLargestDimension(), distance);
if (bigEnoughToRender) {
renderProxies(entityItem, args);
Glower* glower = NULL;
if (entityItem->getGlowLevel() > 0.0f) {
glower = new Glower(entityItem->getGlowLevel());
}
entityItem->render(args);
args->_itemsRendered++;
if (glower) {
delete glower;
}
} else {
args->_itemsTooSmall++;
}
} else {
args->_itemsOutOfView++;

View file

@ -76,11 +76,7 @@ public:
void deleteReleasedModels();
private:
QList<Model*> _releasedModels;
float distanceToCamera(const glm::vec3& center, const ViewFrustum& viewFrustum) const;
bool shouldRenderEntity(float largestDimension, float distanceToCamera) const;
void renderProxies(const EntityItem* entity, RenderArgs* args);
};
#endif // hifi_EntityTreeRenderer_h

View file

@ -47,7 +47,7 @@ Model::Model(QObject* parent) :
_blendNumber(0),
_appliedBlendNumber(0),
_calculatedMeshBoxesValid(false),
_meshesGroupsKnown(false) {
_meshGroupsKnown(false) {
// we may have been created in the network thread, but we live in the main thread
moveToThread(Application::getInstance()->thread());
@ -273,7 +273,7 @@ void Model::reset() {
_jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation, 0.0f);
}
_meshesGroupsKnown = false;
_meshGroupsKnown = false;
}
bool Model::updateGeometry() {
@ -323,7 +323,7 @@ bool Model::updateGeometry() {
deleteGeometry();
_dilatedTextures.clear();
_geometry = geometry;
_meshesGroupsKnown = false;
_meshGroupsKnown = false;
setJointStates(newJointStates);
needToRebuild = true;
} else if (_jointStates.isEmpty()) {
@ -426,7 +426,7 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) {
}
}
if (!_meshesGroupsKnown) {
if (!_meshGroupsKnown) {
segregateMeshGroups();
}
@ -1247,7 +1247,7 @@ void Model::applyNextGeometry() {
// we retain a reference to the base geometry so that its reference count doesn't fall to zero
_baseGeometry = _nextBaseGeometry;
_geometry = _nextGeometry;
_meshesGroupsKnown = false;
_meshGroupsKnown = false;
_nextBaseGeometry.reset();
_nextGeometry.reset();
}
@ -1380,7 +1380,7 @@ void Model::segregateMeshGroups() {
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
}
}
_meshesGroupsKnown = true;
_meshGroupsKnown = true;
}
int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
@ -1390,10 +1390,8 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
bool cullMeshParts = args && !Menu::getInstance()->isOptionChecked(MenuOption::DontCullMeshParts);
// depending on which parameters we were called with, pick the correct mesh group to render
QList<int>* whichList = NULL;
QVector<int>* whichList = NULL;
if (translucent && !hasTangents && !hasSpecular && !isSkinned) {
whichList = &_meshesTranslucent;
} else if (translucent && hasTangents && !hasSpecular && !isSkinned) {
@ -1434,7 +1432,7 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
qDebug() << "unexpected!!! we don't know which list of meshes to render...";
return 0;
}
QList<int>& list = *whichList;
QVector<int>& list = *whichList;
ProgramObject* program = &_program;
Locations* locations = &_locations;
@ -1486,6 +1484,14 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
// i is the "index" from the original networkMeshes QVector...
foreach (int i, list) {
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
// to false to rebuild out mesh groups.
if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) {
_meshGroupsKnown = false; // regenerate these lists next time around.
continue;
}
// exit early if the translucency doesn't match what we're drawing
const NetworkMesh& networkMesh = networkMeshes.at(i);
@ -1501,17 +1507,30 @@ int Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold,
// if we got here, then check to see if this mesh is in view
if (args) {
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
bool shouldRender = true;
args->_meshesConsidered++;
if (cullMeshParts && args->_viewFrustum) {
shouldRender = args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
if (args->_viewFrustum) {
shouldRender = dontCullOutOfViewMeshParts ||
args->_viewFrustum->boxInFrustum(_calculatedMeshBoxes.at(i)) != ViewFrustum::OUTSIDE;
if (shouldRender && cullTooSmallMeshParts) {
float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter());
shouldRender = Menu::getInstance()->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(),
distance);
if (!shouldRender) {
args->_meshesTooSmall++;
}
} else {
args->_meshesOutOfView++;
}
}
if (shouldRender) {
args->_meshesRendered++;
} else {
args->_meshesOutOfView++;
continue; // skip this mesh
}
}

View file

@ -31,6 +31,7 @@ class QScriptEngine;
class AnimationHandle;
class Shape;
class RenderArgs;
class ViewFrustum;
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
@ -335,27 +336,27 @@ private:
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
bool _meshesGroupsKnown;
bool _meshGroupsKnown;
QList<int> _meshesTranslucent;
QList<int> _meshesTranslucentTangents;
QList<int> _meshesTranslucentTangentsSpecular;
QList<int> _meshesTranslucentSpecular;
QVector<int> _meshesTranslucent;
QVector<int> _meshesTranslucentTangents;
QVector<int> _meshesTranslucentTangentsSpecular;
QVector<int> _meshesTranslucentSpecular;
QList<int> _meshesTranslucentSkinned;
QList<int> _meshesTranslucentTangentsSkinned;
QList<int> _meshesTranslucentTangentsSpecularSkinned;
QList<int> _meshesTranslucentSpecularSkinned;
QVector<int> _meshesTranslucentSkinned;
QVector<int> _meshesTranslucentTangentsSkinned;
QVector<int> _meshesTranslucentTangentsSpecularSkinned;
QVector<int> _meshesTranslucentSpecularSkinned;
QList<int> _meshesOpaque;
QList<int> _meshesOpaqueTangents;
QList<int> _meshesOpaqueTangentsSpecular;
QList<int> _meshesOpaqueSpecular;
QVector<int> _meshesOpaque;
QVector<int> _meshesOpaqueTangents;
QVector<int> _meshesOpaqueTangentsSpecular;
QVector<int> _meshesOpaqueSpecular;
QList<int> _meshesOpaqueSkinned;
QList<int> _meshesOpaqueTangentsSkinned;
QList<int> _meshesOpaqueTangentsSpecularSkinned;
QList<int> _meshesOpaqueSpecularSkinned;
QVector<int> _meshesOpaqueSkinned;
QVector<int> _meshesOpaqueTangentsSkinned;
QVector<int> _meshesOpaqueTangentsSpecularSkinned;
QVector<int> _meshesOpaqueSpecularSkinned;
};

View file

@ -459,7 +459,7 @@ void Stats::display(
VoxelSystem* voxels = Application::getInstance()->getVoxels();
lines = _expanded ? 14 : 3;
lines = _expanded ? 15 : 3;
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::AudioSpatialProcessing)) {
lines += 10; // spatial audio processing adds 1 spacing line and 8 extra lines of info
}
@ -472,12 +472,16 @@ void Stats::display(
// Model/Entity render details
EntityTreeRenderer* entities = Application::getInstance()->getEntities();
voxelStats.str("");
voxelStats << "Entity Items rendered: " << entities->getItemsRendered() << " Out of view:" << entities->getItemsOutOfView();
voxelStats << "Entity Items rendered: " << entities->getItemsRendered()
<< " Out of view:" << entities->getItemsOutOfView()
<< " Too small:" << entities->getItemsTooSmall();
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
voxelStats.str("");
voxelStats << "Meshes rendered: " << entities->getMeshesRendered() << " Out of view:" << entities->getMeshesOutOfView();
voxelStats << "Meshes rendered: " << entities->getMeshesRendered()
<< " Out of view:" << entities->getMeshesOutOfView()
<< " Too small:" << entities->getMeshesTooSmall();
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);

View file

@ -162,7 +162,8 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
}
void OctreeRenderer::render(RenderMode renderMode) {
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, 0, 0, 0, 0, 0, 0, 0, 0 };
RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
if (_tree) {
_tree->lockForRead();
_tree->recurseTreeWithOperation(renderOperation, &args);
@ -171,10 +172,12 @@ void OctreeRenderer::render(RenderMode renderMode) {
_meshesConsidered = args._meshesConsidered;
_meshesRendered = args._meshesRendered;
_meshesOutOfView = args._meshesOutOfView;
_meshesTooSmall = args._meshesTooSmall;
_elementsTouched = args._elementsTouched;
_itemsRendered = args._itemsRendered;
_itemsOutOfView = args._itemsOutOfView;
_itemsTooSmall = args._itemsTooSmall;
_trianglesRendered = args._trianglesRendered;
_quadsRendered = args._quadsRendered;

View file

@ -67,10 +67,12 @@ public:
int getElementsTouched() const { return _elementsTouched; }
int getItemsRendered() const { return _itemsRendered; }
int getItemsOutOfView() const { return _itemsOutOfView; }
int getItemsTooSmall() const { return _itemsTooSmall; }
int getMeshesConsidered() const { return _meshesConsidered; }
int getMeshesRendered() const { return _meshesRendered; }
int getMeshesOutOfView() const { return _meshesOutOfView; }
int getMeshesTooSmall() const { return _meshesTooSmall; }
int getTrianglesRendered() const { return _trianglesRendered; }
int getQuadsRendered() const { return _quadsRendered; }
@ -86,10 +88,12 @@ protected:
int _elementsTouched;
int _itemsRendered;
int _itemsOutOfView;
int _itemsTooSmall;
int _meshesConsidered;
int _meshesRendered;
int _meshesOutOfView;
int _meshesTooSmall;
int _trianglesRendered;
int _quadsRendered;
@ -109,10 +113,12 @@ public:
int _elementsTouched;
int _itemsRendered;
int _itemsOutOfView;
int _itemsTooSmall;
int _meshesConsidered;
int _meshesRendered;
int _meshesOutOfView;
int _meshesTooSmall;
int _trianglesRendered;
int _quadsRendered;

View file

@ -876,3 +876,10 @@ void ViewFrustum::getFurthestPointFromCameraVoxelScale(const AACube& box, glm::v
}
}
float ViewFrustum::distanceToCamera(const glm::vec3& point) const {
glm::vec3 temp = getPosition() - point;
float distanceToPoint = sqrtf(glm::dot(temp, temp));
return distanceToPoint;
}

View file

@ -118,6 +118,8 @@ public:
// assumes box is in voxel scale, not TREE_SCALE, will scale view frustum's position accordingly
void getFurthestPointFromCameraVoxelScale(const AACube& box, glm::vec3& furthestPoint) const;
float distanceToCamera(const glm::vec3& point) const;
private:
// Used for keyhole calculations