Lod_Group node threshold distances are now calculated based on the distance between the camera and the nearest point in/on the bounding box
This commit is contained in:
@@ -11,6 +11,12 @@
|
|||||||
#include "KRVector2.h"
|
#include "KRVector2.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
|
KRAABB::KRAABB()
|
||||||
|
{
|
||||||
|
min = KRVector3::Min();
|
||||||
|
max = KRVector3::Max();
|
||||||
|
}
|
||||||
|
|
||||||
KRAABB::KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint)
|
KRAABB::KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint)
|
||||||
{
|
{
|
||||||
min = minPoint;
|
min = minPoint;
|
||||||
@@ -144,6 +150,11 @@ KRAABB KRAABB::Infinite()
|
|||||||
return KRAABB(KRVector3::Min(), KRVector3::Max());
|
return KRAABB(KRVector3::Min(), KRVector3::Max());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KRAABB KRAABB::Zero()
|
||||||
|
{
|
||||||
|
return KRAABB(KRVector3::Zero(), KRVector3::Zero());
|
||||||
|
}
|
||||||
|
|
||||||
bool KRAABB::visible(const KRMat4 &matViewProjection) const
|
bool KRAABB::visible(const KRMat4 &matViewProjection) const
|
||||||
{
|
{
|
||||||
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
|
// test if bounding box would be within the visible range of the clip space transformed by matViewProjection
|
||||||
@@ -277,6 +288,7 @@ bool KRAABB::intersectsLine(const KRVector3 &v1, const KRVector3 &v2) const
|
|||||||
|
|
||||||
bool KRAABB::intersectsRay(const KRVector3 &v1, const KRVector3 &dir) const
|
bool KRAABB::intersectsRay(const KRVector3 &v1, const KRVector3 &dir) const
|
||||||
{
|
{
|
||||||
|
// FINDME, TODO - Need to implement this
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,4 +301,9 @@ void KRAABB::encapsulate(const KRAABB & b)
|
|||||||
if(b.max.x > max.x) max.x = b.max.x;
|
if(b.max.x > max.x) max.x = b.max.x;
|
||||||
if(b.max.y > max.y) max.y = b.max.y;
|
if(b.max.y > max.y) max.y = b.max.y;
|
||||||
if(b.max.z > max.z) max.z = b.max.z;
|
if(b.max.z > max.z) max.z = b.max.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KRVector3 KRAABB::nearestPoint(const KRVector3 & v) const
|
||||||
|
{
|
||||||
|
return KRVector3(KRCLAMP(v.x, min.x, max.x), KRCLAMP(v.y, min.y, max.y), KRCLAMP(v.z, min.z, max.z));
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class KRAABB {
|
|||||||
public:
|
public:
|
||||||
KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint);
|
KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint);
|
||||||
KRAABB(const KRVector3 &corner1, const KRVector3 &corner2, const KRMat4 &modelMatrix);
|
KRAABB(const KRVector3 &corner1, const KRVector3 &corner2, const KRMat4 &modelMatrix);
|
||||||
|
KRAABB();
|
||||||
~KRAABB();
|
~KRAABB();
|
||||||
|
|
||||||
void scale(const KRVector3 &s);
|
void scale(const KRVector3 &s);
|
||||||
@@ -48,8 +49,10 @@ public:
|
|||||||
KRVector3 max;
|
KRVector3 max;
|
||||||
|
|
||||||
static KRAABB Infinite();
|
static KRAABB Infinite();
|
||||||
|
static KRAABB Zero();
|
||||||
float coverage(const KRMat4 &matVP, const KRVector2 viewportSize) const;
|
float coverage(const KRMat4 &matVP, const KRVector2 viewportSize) const;
|
||||||
float longest_radius() const;
|
float longest_radius() const;
|
||||||
|
KRVector3 nearestPoint(const KRVector3 & v) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,3 +138,8 @@ void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRLight *> &light
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KRAABB KRDirectionalLight::getBounds()
|
||||||
|
{
|
||||||
|
return KRAABB::Infinite();
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public:
|
|||||||
KRVector3 getWorldLightDirection();
|
KRVector3 getWorldLightDirection();
|
||||||
|
|
||||||
virtual void render(KRCamera *pCamera, std::vector<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
virtual void render(KRCamera *pCamera, std::vector<KRLight *> &lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
|
||||||
|
virtual KRAABB getBounds();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
|||||||
{
|
{
|
||||||
m_min_distance = 0.0f;
|
m_min_distance = 0.0f;
|
||||||
m_max_distance = 0.0f;
|
m_max_distance = 0.0f;
|
||||||
m_referencePoint = KRVector3::Zero();
|
m_reference = KRAABB(KRVector3::Zero(), KRVector3::Zero());
|
||||||
|
m_use_world_units = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
KRLODGroup::~KRLODGroup()
|
KRLODGroup::~KRLODGroup()
|
||||||
@@ -30,9 +31,16 @@ tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
|||||||
e->SetAttribute("min_distance", m_min_distance);
|
e->SetAttribute("min_distance", m_min_distance);
|
||||||
e->SetAttribute("max_distance", m_max_distance);
|
e->SetAttribute("max_distance", m_max_distance);
|
||||||
|
|
||||||
e->SetAttribute("reference_x", m_referencePoint.x);
|
e->SetAttribute("reference_min_x", m_reference.min.x);
|
||||||
e->SetAttribute("reference_y", m_referencePoint.y);
|
e->SetAttribute("reference_min_y", m_reference.min.y);
|
||||||
e->SetAttribute("reference_z", m_referencePoint.z);
|
e->SetAttribute("reference_min_z", m_reference.min.z);
|
||||||
|
|
||||||
|
|
||||||
|
e->SetAttribute("reference_max_x", m_reference.max.x);
|
||||||
|
e->SetAttribute("reference_max_y", m_reference.max.y);
|
||||||
|
e->SetAttribute("reference_max_z", m_reference.max.z);
|
||||||
|
|
||||||
|
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,32 +60,45 @@ void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
|||||||
|
|
||||||
|
|
||||||
float x=0.0f, y=0.0f, z=0.0f;
|
float x=0.0f, y=0.0f, z=0.0f;
|
||||||
if(e->QueryFloatAttribute("reference_x", &x) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||||
x = 0.0f;
|
x = 0.0f;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("reference_y", &y) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||||
y = 0.0f;
|
y = 0.0f;
|
||||||
}
|
}
|
||||||
if(e->QueryFloatAttribute("reference_z", &z) != tinyxml2::XML_SUCCESS) {
|
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||||
z = 0.0f;
|
z = 0.0f;
|
||||||
}
|
}
|
||||||
m_referencePoint = KRVector3(x,y,z);
|
|
||||||
|
m_reference.min = KRVector3(x,y,z);
|
||||||
|
|
||||||
|
x=0.0f; y=0.0f; z=0.0f;
|
||||||
|
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||||
|
x = 0.0f;
|
||||||
|
}
|
||||||
|
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||||
|
y = 0.0f;
|
||||||
|
}
|
||||||
|
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||||
|
z = 0.0f;
|
||||||
|
}
|
||||||
|
m_reference.max = KRVector3(x,y,z);
|
||||||
|
|
||||||
|
m_use_world_units = true;
|
||||||
|
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
||||||
|
m_use_world_units = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const KRVector3 KRLODGroup::getReferencePoint()
|
const KRAABB &KRLODGroup::getReference() const
|
||||||
{
|
{
|
||||||
return m_referencePoint;
|
return m_reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRLODGroup::setReferencePoint(const KRVector3 &referencePoint)
|
void KRLODGroup::setReference(const KRAABB &reference)
|
||||||
{
|
{
|
||||||
m_referencePoint = referencePoint;
|
m_reference = reference;
|
||||||
}
|
|
||||||
|
|
||||||
const KRVector3 KRLODGroup::getWorldReferencePoint()
|
|
||||||
{
|
|
||||||
return localToWorld(m_referencePoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KRLODGroup::getLODVisibility(const KRViewport &viewport)
|
bool KRLODGroup::getLODVisibility(const KRViewport &viewport)
|
||||||
@@ -88,8 +109,20 @@ bool KRLODGroup::getLODVisibility(const KRViewport &viewport)
|
|||||||
// return (m_max_distance == 0); // FINDME, HACK - Test code to enable only the lowest LOD group
|
// return (m_max_distance == 0); // FINDME, HACK - Test code to enable only the lowest LOD group
|
||||||
float lod_bias = viewport.getLODBias();
|
float lod_bias = viewport.getLODBias();
|
||||||
lod_bias = pow(2.0f, -lod_bias);
|
lod_bias = pow(2.0f, -lod_bias);
|
||||||
// Compare square distances as sqrt is expensive
|
|
||||||
float sqr_distance = (viewport.getCameraPosition() - getWorldReferencePoint()).sqrMagnitude() * (lod_bias * lod_bias);
|
float sqr_distance; // Compare using squared distances as sqrt is expensive
|
||||||
|
|
||||||
|
KRVector3 world_camera_position = viewport.getCameraPosition();
|
||||||
|
KRVector3 local_camera_position = worldToLocal(world_camera_position);
|
||||||
|
KRVector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||||
|
|
||||||
|
if(m_use_world_units) {
|
||||||
|
KRVector3 world_reference_point = localToWorld(local_reference_point);
|
||||||
|
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||||
|
} else {
|
||||||
|
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||||
|
}
|
||||||
|
|
||||||
float sqr_min_distance = m_min_distance * m_min_distance;
|
float sqr_min_distance = m_min_distance * m_min_distance;
|
||||||
float sqr_max_distance = m_max_distance * m_max_distance;
|
float sqr_max_distance = m_max_distance * m_max_distance;
|
||||||
return ((sqr_distance >= sqr_min_distance || m_min_distance == 0) && (sqr_distance < sqr_max_distance || m_max_distance == 0));
|
return ((sqr_distance >= sqr_min_distance || m_min_distance == 0) && (sqr_distance < sqr_max_distance || m_max_distance == 0));
|
||||||
@@ -132,3 +165,12 @@ void KRLODGroup::setMaxDistance(float max_distance)
|
|||||||
m_max_distance = max_distance;
|
m_max_distance = max_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
||||||
|
{
|
||||||
|
m_use_world_units = use_world_units;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KRLODGroup::getUseWorldUnits() const
|
||||||
|
{
|
||||||
|
return m_use_world_units;
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,16 +28,17 @@ public:
|
|||||||
void setMinDistance(float min_distance);
|
void setMinDistance(float min_distance);
|
||||||
void setMaxDistance(float max_distance);
|
void setMaxDistance(float max_distance);
|
||||||
|
|
||||||
const KRVector3 getReferencePoint();
|
const KRAABB &getReference() const;
|
||||||
void setReferencePoint(const KRVector3 &referencePoint);
|
void setReference(const KRAABB &reference);
|
||||||
|
void setUseWorldUnits(bool use_world_units);
|
||||||
const KRVector3 getWorldReferencePoint();
|
bool getUseWorldUnits() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getLODVisibility(const KRViewport &viewport);
|
bool getLODVisibility(const KRViewport &viewport);
|
||||||
float m_min_distance;
|
float m_min_distance;
|
||||||
float m_max_distance;
|
float m_max_distance;
|
||||||
KRVector3 m_referencePoint; // Point of reference, used for distance calculation. Usually set to the bounding box center
|
KRAABB m_reference; // Point of reference, used for distance calculation. Usually set to the bounding box center
|
||||||
|
bool m_use_world_units;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -278,16 +278,18 @@ KRScene &KRNode::getScene() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KRAABB KRNode::getBounds() {
|
KRAABB KRNode::getBounds() {
|
||||||
KRAABB bounds = KRAABB::Infinite();
|
KRAABB bounds = KRAABB::Zero();
|
||||||
|
|
||||||
bool first_child = true;
|
bool first_child = true;
|
||||||
for(std::vector<KRNode *>::iterator itr=m_childNodes.begin(); itr < m_childNodes.end(); ++itr) {
|
for(std::vector<KRNode *>::iterator itr=m_childNodes.begin(); itr < m_childNodes.end(); ++itr) {
|
||||||
KRNode *child = (*itr);
|
KRNode *child = (*itr);
|
||||||
if(first_child) {
|
if(child->getBounds() != KRAABB::Zero()) {
|
||||||
first_child = false;
|
if(first_child) {
|
||||||
bounds = child->getBounds();
|
first_child = false;
|
||||||
} else {
|
bounds = child->getBounds();
|
||||||
bounds.encapsulate(child->getBounds());
|
} else {
|
||||||
|
bounds.encapsulate(child->getBounds());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ KROctree::~KROctree()
|
|||||||
void KROctree::add(KRNode *pNode)
|
void KROctree::add(KRNode *pNode)
|
||||||
{
|
{
|
||||||
KRAABB nodeBounds = pNode->getBounds();
|
KRAABB nodeBounds = pNode->getBounds();
|
||||||
if(nodeBounds == KRAABB::Infinite()) {
|
if(nodeBounds == KRAABB::Zero()) {
|
||||||
|
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||||
|
} else if(nodeBounds == KRAABB::Infinite()) {
|
||||||
// This item is infinitely large; we track it separately
|
// This item is infinitely large; we track it separately
|
||||||
m_outerSceneNodes.insert(pNode);
|
m_outerSceneNodes.insert(pNode);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -738,9 +738,7 @@ void LoadNode(KFbxScene* pFbxScene, KRNode *parent_node, std::vector<KRResource
|
|||||||
if(attribute_type == KFbxNodeAttribute::eLODGroup) {
|
if(attribute_type == KFbxNodeAttribute::eLODGroup) {
|
||||||
std::string name = GetFbxObjectName(pNode);
|
std::string name = GetFbxObjectName(pNode);
|
||||||
FbxLODGroup *fbx_lod_group = (FbxLODGroup*) pNode->GetNodeAttribute(); // FbxCast<FbxLODGroup>(pNode);
|
FbxLODGroup *fbx_lod_group = (FbxLODGroup*) pNode->GetNodeAttribute(); // FbxCast<FbxLODGroup>(pNode);
|
||||||
if(!fbx_lod_group->WorldSpace.Get()) {
|
bool use_world_space_units = fbx_lod_group->WorldSpace.Get();
|
||||||
printf("WARNING - LOD Groups only supported with world space distance thresholds.\n");
|
|
||||||
}
|
|
||||||
float group_min_distance = 0.0f;
|
float group_min_distance = 0.0f;
|
||||||
float group_max_distance = 0.0f;
|
float group_max_distance = 0.0f;
|
||||||
if(fbx_lod_group->MinMaxDistance.Get()) {
|
if(fbx_lod_group->MinMaxDistance.Get()) {
|
||||||
@@ -748,7 +746,7 @@ void LoadNode(KFbxScene* pFbxScene, KRNode *parent_node, std::vector<KRResource
|
|||||||
group_max_distance = fbx_lod_group->MinDistance.Get();
|
group_max_distance = fbx_lod_group->MinDistance.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
KRVector3 reference_point;
|
KRAABB reference_bounds;
|
||||||
// Create a lod_group node for each fbx child node
|
// Create a lod_group node for each fbx child node
|
||||||
int child_count = pNode->GetChildCount();
|
int child_count = pNode->GetChildCount();
|
||||||
for(int i = 0; i < child_count; i++)
|
for(int i = 0; i < child_count; i++)
|
||||||
@@ -797,16 +795,17 @@ void LoadNode(KFbxScene* pFbxScene, KRNode *parent_node, std::vector<KRResource
|
|||||||
new_node->setLocalRotation(node_rotation);
|
new_node->setLocalRotation(node_rotation);
|
||||||
new_node->setLocalTranslation(node_translation);
|
new_node->setLocalTranslation(node_translation);
|
||||||
new_node->setLocalScale(node_scale);
|
new_node->setLocalScale(node_scale);
|
||||||
|
new_node->setUseWorldUnits(use_world_space_units);
|
||||||
parent_node->addChild(new_node);
|
parent_node->addChild(new_node);
|
||||||
|
|
||||||
LoadNode(pFbxScene, new_node, resources, pGeometryConverter, pNode->GetChild(i));
|
LoadNode(pFbxScene, new_node, resources, pGeometryConverter, pNode->GetChild(i));
|
||||||
|
|
||||||
if(i == 0) {
|
if(i == 0) {
|
||||||
// Calculate reference point using the bounding box center from the highest quality LOD level
|
// Calculate reference point using the bounding box center from the highest quality LOD level
|
||||||
reference_point = new_node->getBounds().center();
|
reference_bounds = new_node->getBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
new_node->setReferencePoint(new_node->worldToLocal(reference_point));
|
new_node->setReference(KRAABB(reference_bounds.min, reference_bounds.max, new_node->getInverseModelMatrix()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
KRNode *new_node = NULL;
|
KRNode *new_node = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user