commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
211
include/engine/core/octree_renderable.cpp
Normal file
211
include/engine/core/octree_renderable.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "core/octree_renderable.h"
|
||||
#include "core/camera.h"
|
||||
#include "timing/benchmark.h"
|
||||
#include "sort/sort.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
OctreeCullingSystem::Node *OctreeCullingSystem::InsertList(List <CachedNode *> &list)
|
||||
{
|
||||
AutoPtr <Node> node(new Node);
|
||||
if (node.IsNull())
|
||||
return NULL;
|
||||
|
||||
bool to_child = false;
|
||||
if (list.GetCount() <= 4)
|
||||
to_child = true;
|
||||
|
||||
else
|
||||
{
|
||||
// Build list AABB.
|
||||
bool first = true;
|
||||
|
||||
MinMax mm;
|
||||
ListForeachPtr(CachedNode *, cnode, list)
|
||||
{
|
||||
if (first)
|
||||
mm = cnode->minmax;
|
||||
else mm.Grow(cnode->minmax);
|
||||
first = false;
|
||||
}
|
||||
|
||||
// Select split axis.
|
||||
Vector4 size = mm.mx - mm.mn;
|
||||
|
||||
uint axis = 2;
|
||||
if ((size.x > size.y) && (size.x > size.z))
|
||||
axis = 0;
|
||||
else if ((size.y > size.x) && (size.y > size.z))
|
||||
axis = 1;
|
||||
|
||||
List <CachedNode *> split_list[2];
|
||||
|
||||
// Check list for renderable occupying more than 50% of the split axis.
|
||||
bool exclusion_split = false;
|
||||
float size_threshold = size[axis] * 0.5f;
|
||||
|
||||
ListForeachPtr(CachedNode *, cnode, list)
|
||||
if ((cnode->minmax.mx[axis] - cnode->minmax.mn[axis]) > size_threshold)
|
||||
{
|
||||
exclusion_split = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (exclusion_split)
|
||||
ListForeachPtr(CachedNode *, cnode, list)
|
||||
split_list[(cnode->minmax.mx[axis] - cnode->minmax.mn[axis]) > size_threshold ? 0 : 1].Add(cnode);
|
||||
else
|
||||
{
|
||||
float split_coord = (mm.mn[axis] + mm.mx[axis]) * 0.5f;
|
||||
ListForeachPtr(CachedNode *, cnode, list)
|
||||
split_list[cnode->minmax.GetCenter()[axis] < split_coord ? 0 : 1].Add(cnode);
|
||||
}
|
||||
|
||||
// Recurse split lists.
|
||||
if (!split_list[0].GetCount() || !split_list[1].GetCount())
|
||||
to_child = true;
|
||||
|
||||
else
|
||||
{
|
||||
node->child[0] = InsertList(split_list[0]);
|
||||
node->child[1] = InsertList(split_list[1]);
|
||||
node->minmax = node->child[0]->minmax;
|
||||
node->minmax.Grow(node->child[1]->minmax);
|
||||
}
|
||||
}
|
||||
|
||||
if (to_child)
|
||||
{
|
||||
if (node->cached_node.Allocate(list.GetCount()))
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
uint n = 0;
|
||||
ListForeachPtr(CachedNode *, cnode, list)
|
||||
{
|
||||
node->cached_node[n++] = cnode;
|
||||
if (first)
|
||||
node->minmax = cnode->minmax;
|
||||
else node->minmax.Grow(cnode->minmax);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
__ERR__(__LOG_E__ << "Failed to allocatel leaf container.\n", NULL)
|
||||
}
|
||||
return node.Detach();
|
||||
}
|
||||
bool OctreeCullingSystem::Update()
|
||||
{
|
||||
root = NULL;
|
||||
|
||||
if (renderable_list.GetCount())
|
||||
{
|
||||
if (!nodes.Allocate(renderable_list.GetCount()))
|
||||
return false;
|
||||
|
||||
uint n = 0;
|
||||
ArrayListForeachPtr(Renderable *, renderable, renderable_list)
|
||||
{
|
||||
nodes[n].renderable = renderable;
|
||||
renderable->ComputeRenderableMinMax(nodes[n].minmax);
|
||||
++n;
|
||||
}
|
||||
|
||||
// Build root list.
|
||||
List <CachedNode *> root_list;
|
||||
for (uint n = 0; n < nodes.GetCount(); ++n)
|
||||
root_list.Add(&nodes[n]);
|
||||
|
||||
// Perform insertion.
|
||||
root = InsertList(root_list);
|
||||
}
|
||||
|
||||
dirty = false;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void OctreeCullingSystem::ComputeRenderableMinMax(MinMax &mm)
|
||||
{
|
||||
if (root)
|
||||
mm = root->minmax;
|
||||
}
|
||||
void OctreeCullingSystem::GetNodeRenderablePrimitive(Node *node, const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &list, Context ctx)
|
||||
{
|
||||
// Grab leaf content.
|
||||
if (uint count = node->cached_node.GetCount())
|
||||
{
|
||||
for (uint n = 0; n < count; ++n)
|
||||
{
|
||||
Renderable *renderable = node->cached_node[n]->renderable;
|
||||
if (renderable->IsRenderable())
|
||||
renderable->GetRenderablePrimitiveList(view, default_view, list, ctx, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gather branches.
|
||||
GetNodeRenderablePrimitive(node->child[0], view, default_view, list, ctx);
|
||||
GetNodeRenderablePrimitive(node->child[1], view, default_view, list, ctx);
|
||||
}
|
||||
}
|
||||
void OctreeCullingSystem::CullNodeRenderablePrimitive(Node *node, const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &list, Context ctx)
|
||||
{
|
||||
if (node->cached_node.GetCount())
|
||||
GetNodeRenderablePrimitive(node, view, default_view, list, ctx);
|
||||
|
||||
else
|
||||
switch (view.frustum.ClassifyMinMax(node->minmax))
|
||||
{
|
||||
case Frustum::Outside:
|
||||
break;
|
||||
case Frustum::Clipped:
|
||||
CullNodeRenderablePrimitive(node->child[0], view, default_view, list, ctx);
|
||||
CullNodeRenderablePrimitive(node->child[1], view, default_view, list, ctx);
|
||||
break;
|
||||
case Frustum::Inside:
|
||||
GetNodeRenderablePrimitive(node->child[0], view, default_view, list, ctx);
|
||||
GetNodeRenderablePrimitive(node->child[1], view, default_view, list, ctx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint OctreeCullingSystem::GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack <Render::Primitive *> &list, Context ctx, bool cull)
|
||||
{
|
||||
// Rebuild tree if octree is dirty.
|
||||
if (dirty)
|
||||
Update();
|
||||
|
||||
if (root)
|
||||
{
|
||||
if (cull)
|
||||
CullNodeRenderablePrimitive(root, view, default_view, list, ctx);
|
||||
else GetNodeRenderablePrimitive(root, view, default_view, list, ctx);
|
||||
}
|
||||
return renderable_list.GetCount();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void OctreeCullingSystem::AddRenderable(Renderable *r)
|
||||
{
|
||||
renderable_list.Add(r);
|
||||
dirty = true;
|
||||
}
|
||||
void OctreeCullingSystem::DeleteRenderable(Renderable *r)
|
||||
{
|
||||
renderable_list.Remove(r);
|
||||
dirty = true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user