initial rough pass at hierarchical z-buffer visibility. experimental.
This commit is contained in:
parent
f594fa67ad
commit
c0844239f1
|
|
@ -9,13 +9,15 @@
|
|||
#define TARGET cull
|
||||
|
||||
#define SOURCES \
|
||||
binCullHandler.h \
|
||||
binCullHandler.h binCullHandler.I \
|
||||
config_cull.h \
|
||||
cullBinBackToFront.h cullBinFixed.h \
|
||||
cullBinFrontToBack.h cullBinStateSorted.h cullBinUnsorted.h \
|
||||
drawCullHandler.h binCullHandler.I cullBinBackToFront.I \
|
||||
cullBinFixed.I cullBinFrontToBack.I cullBinStateSorted.I \
|
||||
cullBinUnsorted.I drawCullHandler.I
|
||||
cullBinBackToFront.h cullBinBackToFront.I \
|
||||
cullBinFixed.h cullBinFixed.I \
|
||||
cullBinFrontToBack.h cullBinFrontToBack.I \
|
||||
cullBinHierarchicalZBuffer.h cullBinHierarchicalZBuffer.I \
|
||||
cullBinStateSorted.h cullBinStateSorted.I \
|
||||
cullBinUnsorted.h cullBinUnsorted.I \
|
||||
drawCullHandler.h drawCullHandler.I
|
||||
|
||||
#define COMBINED_SOURCES \
|
||||
$[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
|
@ -26,18 +28,21 @@
|
|||
cullBinBackToFront.cxx \
|
||||
cullBinFixed.cxx \
|
||||
cullBinFrontToBack.cxx \
|
||||
cullBinHierarchicalZBuffer.cxx \
|
||||
cullBinStateSorted.cxx \
|
||||
cullBinUnsorted.cxx \
|
||||
drawCullHandler.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
binCullHandler.h \
|
||||
binCullHandler.h binCullHandler.I \
|
||||
config_cull.h \
|
||||
cullBinBackToFront.h cullBinFixed.h \
|
||||
cullBinFrontToBack.h cullBinStateSorted.h cullBinUnsorted.h \
|
||||
drawCullHandler.h binCullHandler.I cullBinBackToFront.I \
|
||||
cullBinFixed.I cullBinFrontToBack.I cullBinStateSorted.I \
|
||||
cullBinUnsorted.I drawCullHandler.I
|
||||
cullBinBackToFront.h cullBinBackToFront.I \
|
||||
cullBinFixed.h cullBinFixed.I \
|
||||
cullBinFrontToBack.h cullBinFrontToBack.I \
|
||||
cullBinHierarchicalZBuffer.h cullBinHierarchicalZBuffer.I \
|
||||
cullBinStateSorted.h cullBinStateSorted.I \
|
||||
cullBinUnsorted.h cullBinUnsorted.I \
|
||||
drawCullHandler.h drawCullHandler.I
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "cullBinBackToFront.h"
|
||||
#include "cullBinFixed.h"
|
||||
#include "cullBinFrontToBack.h"
|
||||
#include "cullBinHierarchicalZBuffer.h"
|
||||
#include "cullBinStateSorted.h"
|
||||
#include "cullBinUnsorted.h"
|
||||
|
||||
|
|
@ -34,6 +35,18 @@ ConfigureFn(config_cull) {
|
|||
init_libcull();
|
||||
}
|
||||
|
||||
ConfigVariableInt max_objects_per_octree_node
|
||||
("max-objects-per-octree-node", 10,
|
||||
PRC_DESC("Specifies the maximum number of objects collected per octree "
|
||||
"node, by the hierarchical-z cull bin algorithm."));
|
||||
|
||||
ConfigVariableDouble octree_multiassign_ratio
|
||||
("octree-multiassign-ratio", 0.1,
|
||||
PRC_DESC("Objects that intersect a bisecting plane of an octree node must "
|
||||
"be at least this fraction of the node's linear dimension in "
|
||||
"order to be assigned to the node itself. If the object is smaller "
|
||||
"than this, it will be multiply assigned to the node's children."));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libcull
|
||||
// Description: Initializes the library. This must be called at
|
||||
|
|
@ -53,6 +66,7 @@ init_libcull() {
|
|||
CullBinBackToFront::init_type();
|
||||
CullBinFixed::init_type();
|
||||
CullBinFrontToBack::init_type();
|
||||
CullBinHierarchicalZBuffer::init_type();
|
||||
CullBinStateSorted::init_type();
|
||||
CullBinUnsorted::init_type();
|
||||
|
||||
|
|
@ -67,4 +81,6 @@ init_libcull() {
|
|||
CullBinFrontToBack::make_bin);
|
||||
bin_manager->register_bin_type(CullBinManager::BT_fixed,
|
||||
CullBinFixed::make_bin);
|
||||
bin_manager->register_bin_type(CullBinManager::BT_hierarchical_z,
|
||||
CullBinHierarchicalZBuffer::make_bin);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,17 @@
|
|||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "dconfig.h"
|
||||
#include "configVariableInt.h"
|
||||
#include "configVariableDouble.h"
|
||||
|
||||
class DSearchPath;
|
||||
|
||||
ConfigureDecl(config_cull, EXPCL_PANDA, EXPTP_PANDA);
|
||||
NotifyCategoryDecl(cull, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
||||
extern ConfigVariableInt max_objects_per_octree_node;
|
||||
extern ConfigVariableDouble octree_multiassign_ratio;
|
||||
|
||||
extern EXPCL_PANDA void init_libcull();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -63,8 +63,7 @@ add_object(CullableObject *object) {
|
|||
// Determine the center of the bounding volume.
|
||||
CPT(BoundingVolume) volume = object->_geom->get_bounds();
|
||||
|
||||
if (!volume->is_empty() &&
|
||||
volume->is_of_type(GeometricBoundingVolume::get_class_type())) {
|
||||
if (!volume->is_empty()) {
|
||||
const GeometricBoundingVolume *gbv;
|
||||
DCAST_INTO_V(gbv, volume);
|
||||
|
||||
|
|
|
|||
|
|
@ -63,8 +63,7 @@ add_object(CullableObject *object) {
|
|||
// Determine the center of the bounding volume.
|
||||
CPT(BoundingVolume) volume = object->_geom->get_bounds();
|
||||
|
||||
if (!volume->is_empty() &&
|
||||
volume->is_of_type(GeometricBoundingVolume::get_class_type())) {
|
||||
if (!volume->is_empty()) {
|
||||
const GeometricBoundingVolume *gbv;
|
||||
DCAST_INTO_V(gbv, volume);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
// Filename: cullBinHierarchicalZBuffer.I
|
||||
// Created by: drose (24Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::ObjectData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullBinHierarchicalZBuffer::ObjectData::
|
||||
ObjectData(CullableObject *object, BoundingSphere *bounds) :
|
||||
_object(object),
|
||||
_bounds(bounds)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::ObjectData::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullBinHierarchicalZBuffer::ObjectData::
|
||||
ObjectData(const CullBinHierarchicalZBuffer::ObjectData ©) :
|
||||
_object(copy._object),
|
||||
_bounds(copy._bounds)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::ObjectData::Copy Assignment
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullBinHierarchicalZBuffer::ObjectData::
|
||||
operator = (const CullBinHierarchicalZBuffer::ObjectData ©) {
|
||||
_object = copy._object;
|
||||
_bounds = copy._bounds;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CullBinHierarchicalZBuffer::
|
||||
CullBinHierarchicalZBuffer(const string &name, GraphicsStateGuardianBase *gsg) :
|
||||
CullBin(name, gsg)
|
||||
{
|
||||
nassertv(_gsg->get_supports_occlusion_query());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::initial_assign
|
||||
// Access: Public
|
||||
// Description: Assigns the object to the node, in preparation for
|
||||
// calling group_objects().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
initial_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) {
|
||||
_objects.push_back(object_data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::reassign
|
||||
// Access: Public
|
||||
// Description: After determining that the object bisects one of the
|
||||
// major planes of the node, reassigns it back to the
|
||||
// same node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
reassign(const CullBinHierarchicalZBuffer::ObjectData &object_data) {
|
||||
if (object_data._bounds->get_radius() / _half_side >= octree_multiassign_ratio) {
|
||||
// The object is large enough to keep in this node.
|
||||
//cerr << " reassigning.\n";
|
||||
_objects.push_back(object_data);
|
||||
} else {
|
||||
//cerr << " multidistributing.\n";
|
||||
multi_assign(object_data);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::assign_to_corner
|
||||
// Access: Private
|
||||
// Description: Assigns the object to the octree node in the
|
||||
// indicated corner.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
assign_to_corner(int index, const CullBinHierarchicalZBuffer::ObjectData &object_data) {
|
||||
//cerr << " Assigning to corner " << hex << index << dec << ".\n";
|
||||
nassertv(index >= 0 && index < 8);
|
||||
if (_corners[index] == NULL) {
|
||||
make_corner(index);
|
||||
}
|
||||
_corners[index]->initial_assign(object_data);
|
||||
}
|
||||
|
|
@ -0,0 +1,779 @@
|
|||
// Filename: cullBinHierarchicalZBuffer.cxx
|
||||
// Created by: drose (24Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cullBinHierarchicalZBuffer.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geometricBoundingVolume.h"
|
||||
#include "geomLines.h"
|
||||
#include "geomTriangles.h"
|
||||
#include "geomVertexWriter.h"
|
||||
#include "depthWriteAttrib.h"
|
||||
#include "depthTestAttrib.h"
|
||||
#include "colorWriteAttrib.h"
|
||||
#include "cullableObject.h"
|
||||
#include "cullHandler.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "config_cull.h"
|
||||
#include "thread.h"
|
||||
|
||||
PStatCollector CullBinHierarchicalZBuffer::_wait_occlusion_pcollector("Wait:Occlusion test");
|
||||
|
||||
PT(Geom) CullBinHierarchicalZBuffer::_octree_solid_test;
|
||||
PT(Geom) CullBinHierarchicalZBuffer::_octree_wireframe_viz;
|
||||
CPT(RenderState) CullBinHierarchicalZBuffer::_octree_solid_test_state;
|
||||
TypeHandle CullBinHierarchicalZBuffer::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBinHierarchicalZBuffer::
|
||||
~CullBinHierarchicalZBuffer() {
|
||||
ObjectPointers::iterator pi;
|
||||
for (pi = _object_pointers.begin(); pi != _object_pointers.end(); ++pi) {
|
||||
delete (*pi);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::make_bin
|
||||
// Access: Public, Static
|
||||
// Description: Factory constructor for passing to the CullBinManager.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBin *CullBinHierarchicalZBuffer::
|
||||
make_bin(const string &name, GraphicsStateGuardianBase *gsg) {
|
||||
return new CullBinHierarchicalZBuffer(name, gsg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::make_next
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a newly-allocated CullBin object that
|
||||
// contains a copy of just the subset of the data from
|
||||
// this CullBin object that is worth keeping around
|
||||
// for next frame.
|
||||
//
|
||||
// If a particular CullBin object has no data worth
|
||||
// preserving till next frame, it is acceptable to
|
||||
// return NULL (which is the default behavior of this
|
||||
// method).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(CullBin) CullBinHierarchicalZBuffer::
|
||||
make_next() const {
|
||||
return (CullBin *)NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::add_object
|
||||
// Access: Public, Virtual
|
||||
// Description: Adds a geom, along with its associated state, to
|
||||
// the bin for rendering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::
|
||||
add_object(CullableObject *object) {
|
||||
// Determine the world-space bounding sphere for the object.
|
||||
CPT(BoundingVolume) volume = object->_geom->get_bounds();
|
||||
if (volume->is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PT(BoundingSphere) sphere;
|
||||
|
||||
if (volume->is_exact_type(BoundingSphere::get_class_type())) {
|
||||
sphere = DCAST(BoundingSphere, volume->make_copy());
|
||||
} else {
|
||||
const GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, volume);
|
||||
PT(BoundingSphere) sphere = new BoundingSphere;
|
||||
sphere->around(&gbv, &gbv + 1);
|
||||
}
|
||||
|
||||
object->_already_drawn = false;
|
||||
sphere->xform(object->_net_transform->get_mat());
|
||||
_root.initial_assign(ObjectData(object, sphere));
|
||||
_object_pointers.push_back(object);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::finish_cull
|
||||
// Access: Public
|
||||
// Description: Called after all the geoms have been added, this
|
||||
// indicates that the cull process is finished for this
|
||||
// frame and gives the bins a chance to do any
|
||||
// post-processing (like sorting) before moving on to
|
||||
// draw.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::
|
||||
finish_cull() {
|
||||
PStatTimer timer(_cull_this_pcollector);
|
||||
|
||||
// Now we have a loose list of objects that are to be rendered.
|
||||
// We'd rather have them in an octree, which has much better
|
||||
// grouping properties for the purpose of this algorithm.
|
||||
|
||||
// For now, we'll just build an octree here at runtime, a new one
|
||||
// fresh for each frame. Maybe it won't be *too* bad. But later,
|
||||
// we can optimize this to take advantage of temporal coherence by
|
||||
// starting from the previous frame's octree.
|
||||
_root.make_initial_bounds();
|
||||
_root.group_objects();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::draw
|
||||
// Access: Public
|
||||
// Description: Draws all the geoms in the bin, in the appropriate
|
||||
// order.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::
|
||||
draw() {
|
||||
PStatTimer timer(_draw_this_pcollector);
|
||||
_root.draw(*this);
|
||||
|
||||
while (!_pending_nodes.empty()) {
|
||||
PendingNode &pending = _pending_nodes.front();
|
||||
bool is_occluded;
|
||||
if (!pending._query->is_answer_ready()) {
|
||||
// The answer isn't ready yet. We have to wait.
|
||||
PStatTimer timer(_wait_occlusion_pcollector);
|
||||
is_occluded = (pending._query->get_num_fragments() == 0);
|
||||
} else {
|
||||
// The answer is ready right now. There will be no waiting.
|
||||
is_occluded = (pending._query->get_num_fragments() == 0);
|
||||
}
|
||||
if (!is_occluded) {
|
||||
// The octree cell is at least partially visible. Draw it, and
|
||||
// continue recursion.
|
||||
pending._octree_node->draw(*this);
|
||||
} else {
|
||||
pending._octree_node->draw_wireframe(*this);
|
||||
}
|
||||
_pending_nodes.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBinHierarchicalZBuffer::OctreeNode::
|
||||
OctreeNode() {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
_corners[i] = (OctreeNode *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBinHierarchicalZBuffer::OctreeNode::
|
||||
OctreeNode(float mid_x, float mid_y, float mid_z, float half_side) :
|
||||
_mid(mid_x, mid_y, mid_z),
|
||||
_half_side(half_side)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
_corners[i] = (OctreeNode *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CullBinHierarchicalZBuffer::OctreeNode::
|
||||
~OctreeNode() {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (_corners[i] != (OctreeNode *)NULL) {
|
||||
delete _corners[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::make_initial_bounds
|
||||
// Access: Public
|
||||
// Description: Determines the minmax bounding volume of the root
|
||||
// OctreeNode, based on the objects it contains.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
make_initial_bounds() {
|
||||
if (_objects.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LPoint3f scene_min = _objects[0]._bounds->get_center();
|
||||
LPoint3f scene_max = _objects[0]._bounds->get_center();
|
||||
|
||||
Objects::const_iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
LPoint3f object_min = (*oi)._bounds->get_min();
|
||||
LPoint3f object_max = (*oi)._bounds->get_max();
|
||||
scene_min[0] = min(scene_min[0], object_min[0]);
|
||||
scene_min[1] = min(scene_min[1], object_min[1]);
|
||||
scene_min[2] = min(scene_min[2], object_min[2]);
|
||||
scene_max[0] = max(scene_max[0], object_max[0]);
|
||||
scene_max[1] = max(scene_max[1], object_max[1]);
|
||||
scene_max[2] = max(scene_max[2], object_max[2]);
|
||||
}
|
||||
|
||||
float side = max(max(scene_max[0] - scene_min[0],
|
||||
scene_max[1] - scene_min[1]),
|
||||
scene_max[2] - scene_min[2]);
|
||||
|
||||
_mid.set((scene_min[0] + scene_max[0]) * 0.5f,
|
||||
(scene_min[1] + scene_max[1]) * 0.5f,
|
||||
(scene_min[2] + scene_max[2]) * 0.5f);
|
||||
_half_side = side * 0.5f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::group_objects
|
||||
// Access: Public
|
||||
// Description: Recursively groups the objects assigned to this node
|
||||
// into smaller octree nodes, as appropriate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
group_objects() {
|
||||
//cerr << "group_objects, " << _objects.size() << " objects.\n";
|
||||
if ((int)_objects.size() <= max_objects_per_octree_node) {
|
||||
// No need to do any more subdividing.
|
||||
//cerr << " small enough.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Assign all objects to one or more corners.
|
||||
|
||||
Objects old_objects;
|
||||
old_objects.swap(_objects);
|
||||
|
||||
Objects::const_iterator oi;
|
||||
for (oi = old_objects.begin(); oi != old_objects.end(); ++oi) {
|
||||
//cerr << " object " << (oi - old_objects.begin()) << "\n";
|
||||
const ObjectData &object_data = (*oi);
|
||||
const LPoint3f &c = object_data._bounds->get_center();
|
||||
float r = object_data._bounds->get_radius();
|
||||
|
||||
if (c[0] + r <= _mid[0]) {
|
||||
// -X
|
||||
if (c[1] + r <= _mid[1]) {
|
||||
// -X, -Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// -X, -Y, -Z
|
||||
assign_to_corner(0, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// -X, -Y, +Z
|
||||
assign_to_corner(OC_z, object_data);
|
||||
} else {
|
||||
// -X, -Y, 0
|
||||
reassign(object_data);
|
||||
}
|
||||
} else if (c[1] - r >= _mid[1]) {
|
||||
// -X, +Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// -X, +Y, -Z
|
||||
assign_to_corner(OC_y, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// -X, +Y, +Z
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
} else {
|
||||
// -X, +Y, 0
|
||||
reassign(object_data);
|
||||
}
|
||||
} else {
|
||||
// -X, 0
|
||||
reassign(object_data);
|
||||
}
|
||||
} else if (c[0] - r >= _mid[0]) {
|
||||
// +X
|
||||
if (c[1] + r <= _mid[1]) {
|
||||
// +X, -Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// +X, -Y, -Z
|
||||
assign_to_corner(OC_x, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// +X, -Y, +Z
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
} else {
|
||||
// +X, -Y, 0
|
||||
reassign(object_data);
|
||||
}
|
||||
} else if (c[1] - r >= _mid[1]) {
|
||||
// +X, +Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// +X, +Y, -Z
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// +X, +Y, +Z
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
} else {
|
||||
// +X, +Y, 0
|
||||
reassign(object_data);
|
||||
}
|
||||
} else {
|
||||
// +X, 0
|
||||
reassign(object_data);
|
||||
}
|
||||
} else {
|
||||
// 0
|
||||
reassign(object_data);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (_corners[i] != (OctreeNode *)NULL) {
|
||||
_corners[i]->group_objects();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::occlusion_test
|
||||
// Access: Public
|
||||
// Description: Tests the octree node for visibility by rendering the
|
||||
// octree cube, invisibly, with a query. Returns the
|
||||
// occlusion query object representing this test.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(OcclusionQueryContext) CullBinHierarchicalZBuffer::OctreeNode::
|
||||
occlusion_test(GraphicsStateGuardianBase *gsg) {
|
||||
// Draw the bounding volume for visualization. This is
|
||||
// complicated because we're doing this at such a low level, here
|
||||
// in the middle of the draw task--we've already completed the
|
||||
// cull traversal, so we can't just create a CullableObject or do
|
||||
// anything else that requires a pointer to a CullTraverser.
|
||||
// Instead, we have to do the relevant code by hand.
|
||||
CPT(TransformState) net_transform = TransformState::make_pos_hpr_scale
|
||||
(_mid, LVecBase3f(0.0f, 0.0f, 0.0f),
|
||||
LVecBase3f(_half_side, _half_side, _half_side));
|
||||
CPT(TransformState) world_transform = gsg->get_scene()->get_world_transform();
|
||||
CPT(TransformState) modelview_transform = world_transform->compose(net_transform);
|
||||
|
||||
CPT(RenderState) state = get_octree_solid_test_state();
|
||||
PT(GeomMunger) munger = gsg->get_geom_munger(state);
|
||||
|
||||
CPT(Geom) viz = get_octree_solid_test();
|
||||
CPT(GeomVertexData) munged_data = viz->get_vertex_data();
|
||||
munger->munge_geom(viz, munged_data);
|
||||
|
||||
gsg->set_state_and_transform(state, modelview_transform);
|
||||
|
||||
gsg->begin_occlusion_query();
|
||||
viz->draw(gsg, munger, munged_data);
|
||||
return gsg->end_occlusion_query();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::draw
|
||||
// Access: Public
|
||||
// Description: Draws all of the objects in this node, and
|
||||
// recursively performs occlusion tests on all of the
|
||||
// nested nodes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
draw(CullBinHierarchicalZBuffer &bin) {
|
||||
if (!_objects.empty()) {
|
||||
// Now draw the objects within the octree node.
|
||||
Objects::const_iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
if (object->_already_drawn) {
|
||||
//cerr << "skipping object.\n";
|
||||
} else {
|
||||
//cerr << "drawing object.\n";
|
||||
CullHandler::draw(object, bin._gsg);
|
||||
object->_already_drawn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (_corners[i] != (OctreeNode *)NULL) {
|
||||
PendingNode pending;
|
||||
pending._octree_node = _corners[i];
|
||||
pending._query = _corners[i]->occlusion_test(bin._gsg);
|
||||
bin._pending_nodes.push_back(pending);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::draw_wireframe
|
||||
// Access: Public
|
||||
// Description: Draws a wireframe representation of the octree cube,
|
||||
// for debugging and visualization purposes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
draw_wireframe(CullBinHierarchicalZBuffer &bin) {
|
||||
// As above, this is complicated because we're doing this at such a
|
||||
// low level.
|
||||
CPT(TransformState) net_transform = TransformState::make_pos_hpr_scale
|
||||
(_mid, LVecBase3f(0.0f, 0.0f, 0.0f),
|
||||
LVecBase3f(_half_side, _half_side, _half_side));
|
||||
CPT(TransformState) world_transform = bin._gsg->get_scene()->get_world_transform();
|
||||
CPT(TransformState) modelview_transform = world_transform->compose(net_transform);
|
||||
|
||||
CPT(RenderState) state = RenderState::make_empty();
|
||||
PT(GeomMunger) munger = bin._gsg->get_geom_munger(state);
|
||||
|
||||
CPT(Geom) viz = get_octree_wireframe_viz();
|
||||
CPT(GeomVertexData) munged_data = viz->get_vertex_data();
|
||||
munger->munge_geom(viz, munged_data);
|
||||
|
||||
bin._gsg->set_state_and_transform(state, modelview_transform);
|
||||
viz->draw(bin._gsg, munger, munged_data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::get_octree_solid_test
|
||||
// Access: Private, Static
|
||||
// Description: Returns a Geom that may be used to render the solid
|
||||
// faces of octree cube, presumably invisibly. This
|
||||
// returns a cube over the range (-1, -1, -1) - (1, 1,
|
||||
// 1).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(Geom) CullBinHierarchicalZBuffer::
|
||||
get_octree_solid_test() {
|
||||
if (_octree_solid_test == (Geom *)NULL) {
|
||||
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3();
|
||||
PT(GeomVertexData) vdata =
|
||||
new GeomVertexData("octree", format, Geom::UH_static);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
vertex.add_data3f(-1.0f, -1.0f, -1.0f);
|
||||
vertex.add_data3f(1.0f, -1.0f, -1.0f);
|
||||
vertex.add_data3f(-1.0f, -1.0f, 1.0f);
|
||||
vertex.add_data3f(1.0f, -1.0f, 1.0f);
|
||||
vertex.add_data3f(-1.0f, 1.0f, -1.0f);
|
||||
vertex.add_data3f(1.0f, 1.0f, -1.0f);
|
||||
vertex.add_data3f(-1.0f, 1.0f, 1.0f);
|
||||
vertex.add_data3f(1.0f, 1.0f, 1.0f);
|
||||
PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static);
|
||||
tris->add_vertices(2, 0, 3); tris->close_primitive();
|
||||
tris->add_vertices(0, 1, 3); tris->close_primitive();
|
||||
tris->add_vertices(3, 1, 7); tris->close_primitive();
|
||||
tris->add_vertices(1, 5, 7); tris->close_primitive();
|
||||
tris->add_vertices(7, 5, 6); tris->close_primitive();
|
||||
tris->add_vertices(5, 4, 6); tris->close_primitive();
|
||||
tris->add_vertices(6, 4, 2); tris->close_primitive();
|
||||
tris->add_vertices(4, 0, 2); tris->close_primitive();
|
||||
tris->add_vertices(6, 2, 7); tris->close_primitive();
|
||||
tris->add_vertices(2, 3, 7); tris->close_primitive();
|
||||
tris->add_vertices(0, 4, 1); tris->close_primitive();
|
||||
tris->add_vertices(4, 5, 1); tris->close_primitive();
|
||||
|
||||
_octree_solid_test = new Geom(vdata);
|
||||
_octree_solid_test->add_primitive(tris);
|
||||
}
|
||||
|
||||
return _octree_solid_test;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::get_octree_wireframe_viz
|
||||
// Access: Private, Static
|
||||
// Description: Returns a Geom that may be used to render an
|
||||
// OctreeNode in wireframe. This actually draws a
|
||||
// wireframe cube in the range (-1, -1, -1) - (1, 1, 1).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(Geom) CullBinHierarchicalZBuffer::
|
||||
get_octree_wireframe_viz() {
|
||||
if (_octree_wireframe_viz == (Geom *)NULL) {
|
||||
CPT(GeomVertexFormat) format = GeomVertexFormat::get_v3cp();
|
||||
PT(GeomVertexData) vdata =
|
||||
new GeomVertexData("octree", format, Geom::UH_static);
|
||||
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
||||
vertex.add_data3f(-1.0f, -1.0f, -1.0f);
|
||||
vertex.add_data3f(1.0f, -1.0f, -1.0f);
|
||||
vertex.add_data3f(-1.0f, -1.0f, 1.0f);
|
||||
vertex.add_data3f(1.0f, -1.0f, 1.0f);
|
||||
vertex.add_data3f(-1.0f, 1.0f, -1.0f);
|
||||
vertex.add_data3f(1.0f, 1.0f, -1.0f);
|
||||
vertex.add_data3f(-1.0f, 1.0f, 1.0f);
|
||||
vertex.add_data3f(1.0f, 1.0f, 1.0f);
|
||||
CPT(GeomVertexData) cvdata = vdata->set_color(Colorf(1.0f, 0.5f, 0.0f, 1.0f));
|
||||
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
||||
lines->add_vertices(0, 1); lines->close_primitive();
|
||||
lines->add_vertices(1, 3); lines->close_primitive();
|
||||
lines->add_vertices(3, 2); lines->close_primitive();
|
||||
lines->add_vertices(2, 0); lines->close_primitive();
|
||||
lines->add_vertices(0, 4); lines->close_primitive();
|
||||
lines->add_vertices(4, 6); lines->close_primitive();
|
||||
lines->add_vertices(6, 7); lines->close_primitive();
|
||||
lines->add_vertices(7, 5); lines->close_primitive();
|
||||
lines->add_vertices(5, 4); lines->close_primitive();
|
||||
lines->add_vertices(1, 5); lines->close_primitive();
|
||||
lines->add_vertices(3, 7); lines->close_primitive();
|
||||
lines->add_vertices(2, 6); lines->close_primitive();
|
||||
|
||||
_octree_wireframe_viz = new Geom(cvdata);
|
||||
_octree_wireframe_viz->add_primitive(lines);
|
||||
}
|
||||
|
||||
return _octree_wireframe_viz;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::get_octree_solid_test_state
|
||||
// Access: Private, Static
|
||||
// Description: Returns the RenderState appropriate to rendering the
|
||||
// octree test invisibly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderState) CullBinHierarchicalZBuffer::
|
||||
get_octree_solid_test_state() {
|
||||
if (_octree_solid_test_state == (RenderState *)NULL) {
|
||||
_octree_solid_test_state = RenderState::make
|
||||
(DepthWriteAttrib::make(DepthWriteAttrib::M_off),
|
||||
DepthTestAttrib::make(DepthTestAttrib::M_less),
|
||||
ColorWriteAttrib::make(ColorWriteAttrib::C_off));
|
||||
}
|
||||
|
||||
return _octree_solid_test_state;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::multi_assign
|
||||
// Access: Public
|
||||
// Description: The object intersects a center plane, but is too
|
||||
// small to justify keeping within this big node.
|
||||
// Duplicate it into the sub-nodes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
multi_assign(const CullBinHierarchicalZBuffer::ObjectData &object_data) {
|
||||
const LPoint3f &c = object_data._bounds->get_center();
|
||||
float r = object_data._bounds->get_radius();
|
||||
|
||||
//cerr << "multi_assigning " << c << " vs. " << _mid << "\n";
|
||||
|
||||
if (c[0] + r <= _mid[0]) {
|
||||
// -X
|
||||
if (c[1] + r <= _mid[1]) {
|
||||
// -X, -Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// -X, -Y, -Z
|
||||
nassertv(false);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// -X, -Y, +Z
|
||||
nassertv(false);
|
||||
} else {
|
||||
// -X, -Y, 0
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_z, object_data);
|
||||
}
|
||||
} else if (c[1] - r >= _mid[1]) {
|
||||
// -X, +Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// -X, +Y, -Z
|
||||
nassertv(false);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// -X, +Y, +Z
|
||||
nassertv(false);
|
||||
} else {
|
||||
// -X, +Y, 0
|
||||
assign_to_corner(OC_y, object_data);
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
}
|
||||
} else {
|
||||
// -X, 0
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// -X, 0, -Z
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_y, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// -X, 0, +Z
|
||||
assign_to_corner(OC_z, object_data);
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
} else {
|
||||
// -X, 0, 0
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_z, object_data);
|
||||
assign_to_corner(OC_y, object_data);
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
}
|
||||
}
|
||||
} else if (c[0] - r >= _mid[0]) {
|
||||
// +X
|
||||
if (c[1] + r <= _mid[1]) {
|
||||
// +X, -Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// +X, -Y, -Z
|
||||
nassertv(false);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// +X, -Y, +Z
|
||||
nassertv(false);
|
||||
} else {
|
||||
// +X, -Y, 0
|
||||
assign_to_corner(OC_x, object_data);
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
}
|
||||
} else if (c[1] - r >= _mid[1]) {
|
||||
// +X, +Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// +X, +Y, -Z
|
||||
nassertv(false);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// +X, +Y, +Z
|
||||
nassertv(false);
|
||||
} else {
|
||||
// +X, +Y, 0
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
}
|
||||
} else {
|
||||
// +X, 0
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// +X, 0, -Z
|
||||
assign_to_corner(OC_x, object_data);
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// +X, 0, +Z
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
} else {
|
||||
// +X, 0, 0
|
||||
assign_to_corner(OC_x, object_data);
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 0
|
||||
if (c[1] + r <= _mid[1]) {
|
||||
// 0, -Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// 0, -Y, -Z
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_x, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// 0, -Y, +Z
|
||||
assign_to_corner(OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
} else {
|
||||
// 0, -Y, 0
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_z, object_data);
|
||||
assign_to_corner(OC_x, object_data);
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
}
|
||||
} else if (c[1] - r >= _mid[1]) {
|
||||
// 0, +Y
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// 0, +Y, -Z
|
||||
assign_to_corner(OC_y, object_data);
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// 0, +Y, +Z
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
} else {
|
||||
// 0, +Y, 0
|
||||
assign_to_corner(OC_y, object_data);
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
}
|
||||
} else {
|
||||
// 0, 0
|
||||
if (c[2] + r <= _mid[2]) {
|
||||
// 0, 0, -Z
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_y, object_data);
|
||||
assign_to_corner(OC_x, object_data);
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
} else if (c[2] - r >= _mid[2]) {
|
||||
// 0, 0, +Z
|
||||
assign_to_corner(OC_z, object_data);
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
} else {
|
||||
// 0, 0, 0
|
||||
assign_to_corner(0, object_data);
|
||||
assign_to_corner(OC_z, object_data);
|
||||
assign_to_corner(OC_y, object_data);
|
||||
assign_to_corner(OC_y | OC_z, object_data);
|
||||
assign_to_corner(OC_x, object_data);
|
||||
assign_to_corner(OC_x | OC_z, object_data);
|
||||
assign_to_corner(OC_x | OC_y, object_data);
|
||||
assign_to_corner(OC_x | OC_y | OC_z, object_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CullBinHierarchicalZBuffer::OctreeNode::make_corner
|
||||
// Access: Private
|
||||
// Description: Makes a new octree node for the indicated corner.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CullBinHierarchicalZBuffer::OctreeNode::
|
||||
make_corner(int index) {
|
||||
//cerr << "making corner " << hex << index << dec << "\n";
|
||||
nassertv(_corners[index] == NULL);
|
||||
|
||||
OctreeNode *node = NULL;
|
||||
|
||||
double q = _half_side * 0.5f;
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
// -X, -Y, -Z
|
||||
node = new OctreeNode(_mid[0] - q, _mid[1] - q, _mid[2] - q, q);
|
||||
break;
|
||||
|
||||
case OC_x:
|
||||
// +X, -Y, -Z
|
||||
node = new OctreeNode(_mid[0] + q, _mid[1] - q, _mid[2] - q, q);
|
||||
break;
|
||||
|
||||
case OC_y:
|
||||
// -X, +Y, -Z
|
||||
node = new OctreeNode(_mid[0] - q, _mid[1] + q, _mid[2] - q, q);
|
||||
break;
|
||||
|
||||
case OC_x | OC_y:
|
||||
// +X, +Y, -Z
|
||||
node = new OctreeNode(_mid[0] + q, _mid[1] + q, _mid[2] - q, q);
|
||||
break;
|
||||
|
||||
case OC_z:
|
||||
// -X, -Y, +Z
|
||||
node = new OctreeNode(_mid[0] - q, _mid[1] - q, _mid[2] + q, q);
|
||||
break;
|
||||
|
||||
case OC_x | OC_z:
|
||||
// +X, -Y, +Z
|
||||
node = new OctreeNode(_mid[0] + q, _mid[1] - q, _mid[2] + q, q);
|
||||
break;
|
||||
|
||||
case OC_y | OC_z:
|
||||
// -X, +Y, +Z
|
||||
node = new OctreeNode(_mid[0] - q, _mid[1] + q, _mid[2] + q, q);
|
||||
break;
|
||||
|
||||
case OC_x | OC_y | OC_z:
|
||||
// +X, +Y, +Z
|
||||
node = new OctreeNode(_mid[0] + q, _mid[1] + q, _mid[2] + q, q);
|
||||
break;
|
||||
}
|
||||
nassertv(node != (OctreeNode *)NULL);
|
||||
_corners[index] = node;
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
// Filename: cullBinHierarchicalZBuffer.h
|
||||
// Created by: drose (24Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CULLBINHIERARCHICALZBUFFER_H
|
||||
#define CULLBINHIERARCHICALZBUFFER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "cullBin.h"
|
||||
#include "geom.h"
|
||||
#include "transformState.h"
|
||||
#include "renderState.h"
|
||||
#include "pointerTo.h"
|
||||
#include "boundingSphere.h"
|
||||
#include "config_cull.h"
|
||||
#include "occlusionQueryContext.h"
|
||||
#include "pdeque.h"
|
||||
#include "pStatCollector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CullBinHierarchicalZBuffer
|
||||
// Description : This cull bin uses a hierarchical Z-buffer algorithm
|
||||
// to attempt to further eliminate geometry that is
|
||||
// obscured behind walls, etc. It imposes some
|
||||
// significant overhead over most of the other kinds of
|
||||
// CullBins, and requires additional support from the
|
||||
// graphics card, so it is most appropriate for scenes
|
||||
// in which there might be a large amount of geometry,
|
||||
// within the viewing frustum, but obscured behind large
|
||||
// objects or walls.
|
||||
//
|
||||
// This code is still experimental. Use with caution.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA CullBinHierarchicalZBuffer : public CullBin {
|
||||
public:
|
||||
INLINE CullBinHierarchicalZBuffer(const string &name, GraphicsStateGuardianBase *gsg);
|
||||
virtual ~CullBinHierarchicalZBuffer();
|
||||
|
||||
static CullBin *make_bin(const string &name, GraphicsStateGuardianBase *gsg);
|
||||
virtual PT(CullBin) make_next() const;
|
||||
|
||||
virtual void add_object(CullableObject *object);
|
||||
virtual void finish_cull();
|
||||
virtual void draw();
|
||||
|
||||
private:
|
||||
void draw_next();
|
||||
|
||||
static CPT(Geom) get_octree_solid_test();
|
||||
static CPT(Geom) get_octree_wireframe_viz();
|
||||
|
||||
static CPT(RenderState) get_octree_solid_test_state();
|
||||
|
||||
// We keep the original list of CullableObjects here in the bin
|
||||
// class, so we can delete them on destruction. This allows us to
|
||||
// duplicate pointers between different OctreeNodes.
|
||||
typedef pvector<CullableObject *> ObjectPointers;
|
||||
ObjectPointers _object_pointers;
|
||||
|
||||
class ObjectData {
|
||||
public:
|
||||
INLINE ObjectData(CullableObject *object, BoundingSphere *bounds);
|
||||
INLINE ObjectData(const ObjectData ©);
|
||||
INLINE void operator = (const ObjectData ©);
|
||||
|
||||
CullableObject *_object;
|
||||
PT(BoundingSphere) _bounds;
|
||||
};
|
||||
|
||||
typedef pvector<ObjectData> Objects;
|
||||
|
||||
enum OctreeCorners {
|
||||
OC_x = 0x01,
|
||||
OC_y = 0x02,
|
||||
OC_z = 0x04,
|
||||
};
|
||||
|
||||
class OctreeNode {
|
||||
public:
|
||||
OctreeNode();
|
||||
OctreeNode(float mid_x, float mid_y, float mid_z, float half_side);
|
||||
~OctreeNode();
|
||||
|
||||
void make_initial_bounds();
|
||||
void group_objects();
|
||||
PT(OcclusionQueryContext) occlusion_test(GraphicsStateGuardianBase *gsg);
|
||||
void draw(CullBinHierarchicalZBuffer &bin);
|
||||
void draw_wireframe(CullBinHierarchicalZBuffer &bin);
|
||||
|
||||
INLINE void initial_assign(const ObjectData &object_data);
|
||||
|
||||
private:
|
||||
INLINE void reassign(const ObjectData &object_data);
|
||||
INLINE void assign_to_corner(int index, const ObjectData &object_data);
|
||||
void multi_assign(const ObjectData &object_data);
|
||||
void make_corner(int index);
|
||||
|
||||
Objects _objects;
|
||||
OctreeNode *_corners[8];
|
||||
LPoint3f _mid;
|
||||
float _half_side;
|
||||
};
|
||||
|
||||
OctreeNode _root;
|
||||
|
||||
// During draw(), we maintain a list of OctreeNodes that have been
|
||||
// tested and have yet to pass the occlusion query and be drawn (or
|
||||
// fail and be omitted).
|
||||
class PendingNode {
|
||||
public:
|
||||
OctreeNode *_octree_node;
|
||||
PT(OcclusionQueryContext) _query;
|
||||
};
|
||||
typedef pdeque<PendingNode> PendingNodes;
|
||||
PendingNodes _pending_nodes;
|
||||
|
||||
static PStatCollector _wait_occlusion_pcollector;
|
||||
|
||||
static PT(Geom) _octree_solid_test;
|
||||
static PT(Geom) _octree_wireframe_viz;
|
||||
static CPT(RenderState) _octree_solid_test_state;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CullBin::init_type();
|
||||
register_type(_type_handle, "CullBinHierarchicalZBuffer",
|
||||
CullBin::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class OctreeNode;
|
||||
};
|
||||
|
||||
#include "cullBinHierarchicalZBuffer.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "cullBinStateSorted.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "geometricBoundingVolume.h"
|
||||
#include "cullableObject.h"
|
||||
#include "cullHandler.h"
|
||||
#include "pStatTimer.h"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "cullBinFrontToBack.cxx"
|
||||
#include "cullBinHierarchicalZBuffer.cxx"
|
||||
#include "cullBinStateSorted.cxx"
|
||||
#include "cullBinUnsorted.cxx"
|
||||
#include "drawCullHandler.cxx"
|
||||
|
|
|
|||
|
|
@ -593,17 +593,6 @@ get_global_gsg() {
|
|||
return _global_gsg;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_scene
|
||||
// Access: Public
|
||||
// Description: Returns the SceneSetup object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE SceneSetup *GraphicsStateGuardian::
|
||||
get_scene() const {
|
||||
return _scene_setup;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::reset_if_new
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "geomLinestrips.h"
|
||||
#include "colorWriteAttrib.h"
|
||||
#include "shader.h"
|
||||
#include "pnotify.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
|
|
@ -137,6 +138,8 @@ GraphicsStateGuardian(const FrameBufferProperties &properties,
|
|||
_max_vertex_transforms = 0;
|
||||
_max_vertex_transform_indices = 0;
|
||||
|
||||
_supports_occlusion_query = false;
|
||||
|
||||
// Initially, we set this to false; a GSG that knows it has this
|
||||
// property should set it to true.
|
||||
_copy_texture_inverted = false;
|
||||
|
|
@ -362,6 +365,16 @@ set_scene(SceneSetup *scene_setup) {
|
|||
return prepare_lens();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_scene
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the current SceneSetup object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SceneSetup *GraphicsStateGuardian::
|
||||
get_scene() const {
|
||||
return _scene_setup;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_prepared_objects
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -511,6 +524,58 @@ void GraphicsStateGuardian::
|
|||
release_index_buffer(IndexBufferContext *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_supports_occlusion_query
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if this GSG supports an occlusion query.
|
||||
// If this is true, then begin_occlusion_query() and
|
||||
// end_occlusion_query() may be called to bracket a
|
||||
// sequence of draw_triangles() (or whatever) calls to
|
||||
// measure pixels that pass the depth test.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
get_supports_occlusion_query() const {
|
||||
return _supports_occlusion_query;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::begin_occlusion_query
|
||||
// Access: Public, Virtual
|
||||
// Description: Begins a new occlusion query. After this call, you
|
||||
// may call begin_draw_primitives() and
|
||||
// draw_triangles()/draw_whatever() repeatedly.
|
||||
// Eventually, you should call end_occlusion_query()
|
||||
// before the end of the frame; that will return a new
|
||||
// OcclusionQueryContext object that will tell you how
|
||||
// many pixels represented by the bracketed geometry
|
||||
// passed the depth test.
|
||||
//
|
||||
// It is not valid to call begin_occlusion_query()
|
||||
// between another begin_occlusion_query()
|
||||
// .. end_occlusion_query() sequence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
begin_occlusion_query() {
|
||||
nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::end_occlusion_query
|
||||
// Access: Public, Virtual
|
||||
// Description: Ends a previous call to begin_occlusion_query().
|
||||
// This call returns the OcclusionQueryContext object
|
||||
// that will (eventually) report the number of pixels
|
||||
// that passed the depth test between the call to
|
||||
// begin_occlusion_query() and end_occlusion_query().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(OcclusionQueryContext) GraphicsStateGuardian::
|
||||
end_occlusion_query() {
|
||||
nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL);
|
||||
PT(OcclusionQueryContext) result = _current_occlusion_query;
|
||||
_current_occlusion_query = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::get_geom_munger
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "shaderContext.h"
|
||||
#include "bitMask.h"
|
||||
#include "texture.h"
|
||||
#include "occlusionQueryContext.h"
|
||||
|
||||
class DrawableRegion;
|
||||
class GraphicsEngine;
|
||||
|
|
@ -132,7 +133,7 @@ PUBLISHED:
|
|||
|
||||
public:
|
||||
bool set_scene(SceneSetup *scene_setup);
|
||||
INLINE SceneSetup *get_scene() const;
|
||||
virtual SceneSetup *get_scene() const;
|
||||
|
||||
virtual PreparedGraphicsObjects *get_prepared_objects();
|
||||
|
||||
|
|
@ -152,6 +153,10 @@ public:
|
|||
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data);
|
||||
virtual void release_index_buffer(IndexBufferContext *ibc);
|
||||
|
||||
virtual bool get_supports_occlusion_query() const;
|
||||
virtual void begin_occlusion_query();
|
||||
virtual PT(OcclusionQueryContext) end_occlusion_query();
|
||||
|
||||
PT(GeomMunger) get_geom_munger(const RenderState *state);
|
||||
virtual PT(GeomMunger) make_geom_munger(const RenderState *state);
|
||||
|
||||
|
|
@ -338,6 +343,9 @@ protected:
|
|||
int _max_vertex_transforms;
|
||||
int _max_vertex_transform_indices;
|
||||
|
||||
bool _supports_occlusion_query;
|
||||
PT(OcclusionQueryContext) _current_occlusion_query;
|
||||
|
||||
bool _copy_texture_inverted;
|
||||
bool _supports_multisample;
|
||||
bool _supports_generate_mipmap;
|
||||
|
|
|
|||
|
|
@ -13,36 +13,39 @@
|
|||
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
panda_glext.h \
|
||||
glGeomContext_src.I \
|
||||
glGeomContext_src.cxx \
|
||||
glGeomContext_src.h \
|
||||
glGeomMunger_src.I \
|
||||
glGeomMunger_src.cxx \
|
||||
glGeomMunger_src.h \
|
||||
glGraphicsStateGuardian_src.I \
|
||||
glGraphicsStateGuardian_src.cxx \
|
||||
glGraphicsStateGuardian_src.h \
|
||||
glImmediateModeSender_src.I \
|
||||
glImmediateModeSender_src.cxx \
|
||||
glImmediateModeSender_src.h \
|
||||
glIndexBufferContext_src.I \
|
||||
glIndexBufferContext_src.cxx \
|
||||
glIndexBufferContext_src.h \
|
||||
glOcclusionQueryContext_src.I \
|
||||
glOcclusionQueryContext_src.cxx \
|
||||
glOcclusionQueryContext_src.h \
|
||||
glShaderContext_src.I \
|
||||
glShaderContext_src.cxx \
|
||||
glShaderContext_src.h \
|
||||
glTextureContext_src.I \
|
||||
glTextureContext_src.cxx \
|
||||
glTextureContext_src.h \
|
||||
glVertexBufferContext_src.I \
|
||||
glVertexBufferContext_src.cxx \
|
||||
glVertexBufferContext_src.h \
|
||||
glmisc_src.cxx \
|
||||
glmisc_src.h \
|
||||
glstuff_src.cxx \
|
||||
glstuff_src.h \
|
||||
glstuff_undef_src.h \
|
||||
glVertexBufferContext_src.cxx \
|
||||
glVertexBufferContext_src.I \
|
||||
glVertexBufferContext_src.h \
|
||||
glImmediateModeSender_src.cxx \
|
||||
glImmediateModeSender_src.I \
|
||||
glImmediateModeSender_src.h \
|
||||
glIndexBufferContext_src.cxx \
|
||||
glIndexBufferContext_src.I \
|
||||
glIndexBufferContext_src.h \
|
||||
glGeomContext_src.cxx \
|
||||
glGeomContext_src.I \
|
||||
glGeomContext_src.h \
|
||||
glGeomMunger_src.cxx \
|
||||
glGeomMunger_src.I \
|
||||
glGeomMunger_src.h \
|
||||
glGraphicsStateGuardian_src.cxx \
|
||||
glGraphicsStateGuardian_src.I \
|
||||
glGraphicsStateGuardian_src.h \
|
||||
glTextureContext_src.cxx \
|
||||
glTextureContext_src.I \
|
||||
glTextureContext_src.h \
|
||||
glShaderContext_src.cxx \
|
||||
glShaderContext_src.h \
|
||||
glShaderContext_src.I \
|
||||
panda_glext.h
|
||||
|
||||
#define SOURCES \
|
||||
$[INSTALL_HEADERS] glpure.cxx
|
||||
|
|
|
|||
|
|
@ -721,11 +721,52 @@ reset() {
|
|||
}
|
||||
|
||||
_glDrawBuffers = NULL;
|
||||
if (has_extension("GL_ARB_draw_buffers")) {
|
||||
_glDrawBuffers = (PFNGLDRAWBUFFERSARBPROC)
|
||||
if (is_at_least_version(2, 0)) {
|
||||
_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawBuffers");
|
||||
} else if (has_extension("GL_ARB_draw_buffers")) {
|
||||
_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DrawBuffersARB");
|
||||
}
|
||||
|
||||
_supports_occlusion_query = false;
|
||||
if (CLP(support_occlusion_query)) {
|
||||
if (is_at_least_version(1, 5)) {
|
||||
_supports_occlusion_query = true;
|
||||
_glGenQueries = (PFNGLGENQUERIESPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GenQueries");
|
||||
_glBeginQuery = (PFNGLBEGINQUERYPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "BeginQuery");
|
||||
_glEndQuery = (PFNGLENDQUERYPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "EndQuery");
|
||||
_glDeleteQueries = (PFNGLDELETEQUERIESPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DeleteQueries");
|
||||
_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GetQueryObjectuiv");
|
||||
} else if (has_extension("GL_ARB_occlusion_query")) {
|
||||
_supports_occlusion_query = true;
|
||||
_glGenQueries = (PFNGLGENQUERIESPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GenQueriesARB");
|
||||
_glBeginQuery = (PFNGLBEGINQUERYPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "BeginQueryARB");
|
||||
_glEndQuery = (PFNGLENDQUERYPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "EndQueryARB");
|
||||
_glDeleteQueries = (PFNGLDELETEQUERIESPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "DeleteQueriesARB");
|
||||
_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)
|
||||
get_extension_func(GLPREFIX_QUOTED, "GetQueryObjectuivARB");
|
||||
}
|
||||
}
|
||||
|
||||
if (_supports_occlusion_query &&
|
||||
(_glGenQueries == NULL || _glBeginQuery == NULL ||
|
||||
_glEndQuery == NULL || _glDeleteQueries == NULL ||
|
||||
_glGetQueryObjectuiv == NULL)) {
|
||||
GLCAT.warning()
|
||||
<< "Occlusion queries advertised as supported by OpenGL runtime, but could not get pointers to extension functions.\n";
|
||||
_supports_occlusion_query = false;
|
||||
}
|
||||
|
||||
_glBlendEquation = NULL;
|
||||
bool supports_blend_equation = false;
|
||||
if (is_at_least_version(1, 2)) {
|
||||
|
|
@ -1265,12 +1306,27 @@ end_frame() {
|
|||
++ddli) {
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "releasing index " << (*ddli) << "\n";
|
||||
<< "releasing display list index " << (*ddli) << "\n";
|
||||
}
|
||||
GLP(DeleteLists)((*ddli), 1);
|
||||
}
|
||||
_deleted_display_lists.clear();
|
||||
}
|
||||
|
||||
// And deleted occlusion queries, too.
|
||||
if (!_deleted_queries.empty()) {
|
||||
DeletedDisplayLists::iterator ddli;
|
||||
for (ddli = _deleted_queries.begin();
|
||||
ddli != _deleted_queries.end();
|
||||
++ddli) {
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "releasing query index " << (*ddli) << "\n";
|
||||
}
|
||||
_glDeleteQueries(1, &(*ddli));
|
||||
}
|
||||
_deleted_queries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -2845,6 +2901,53 @@ setup_primitive(const GeomPrimitive *data) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::begin_occlusion_query
|
||||
// Access: Public, Virtual
|
||||
// Description: Begins a new occlusion query. After this call, you
|
||||
// may call begin_draw_primitives() and
|
||||
// draw_triangles()/draw_whatever() repeatedly.
|
||||
// Eventually, you should call end_occlusion_query()
|
||||
// before the end of the frame; that will return a new
|
||||
// OcclusionQueryContext object that will tell you how
|
||||
// many pixels represented by the bracketed geometry
|
||||
// passed the depth test.
|
||||
//
|
||||
// It is not valid to call begin_occlusion_query()
|
||||
// between another begin_occlusion_query()
|
||||
// .. end_occlusion_query() sequence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
begin_occlusion_query() {
|
||||
nassertv(_supports_occlusion_query);
|
||||
nassertv(_current_occlusion_query == (OcclusionQueryContext *)NULL);
|
||||
PT(CLP(OcclusionQueryContext)) query = new CLP(OcclusionQueryContext)(this);
|
||||
|
||||
_glGenQueries(1, &query->_index);
|
||||
_glBeginQuery(GL_SAMPLES_PASSED, query->_index);
|
||||
|
||||
_current_occlusion_query = query;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::end_occlusion_query
|
||||
// Access: Public, Virtual
|
||||
// Description: Ends a previous call to begin_occlusion_query().
|
||||
// This call returns the OcclusionQueryContext object
|
||||
// that will (eventually) report the number of pixels
|
||||
// that passed the depth test between the call to
|
||||
// begin_occlusion_query() and end_occlusion_query().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PT(OcclusionQueryContext) CLP(GraphicsStateGuardian)::
|
||||
end_occlusion_query() {
|
||||
nassertr(_current_occlusion_query != (OcclusionQueryContext *)NULL, NULL);
|
||||
PT(OcclusionQueryContext) result = _current_occlusion_query;
|
||||
_current_occlusion_query = NULL;
|
||||
_glEndQuery(GL_SAMPLES_PASSED);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLGraphicsStateGuardian::make_geom_munger
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
|
|||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
|
||||
typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
|
||||
typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
|
||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
|
||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
|
||||
|
|
@ -82,8 +82,6 @@ class EXPCL_GL CLP(GraphicsStateGuardian) : public GraphicsStateGuardian {
|
|||
public:
|
||||
CLP(GraphicsStateGuardian)(const FrameBufferProperties &properties);
|
||||
virtual ~CLP(GraphicsStateGuardian)();
|
||||
friend class CLP(ShaderContext);
|
||||
friend class CLP(GraphicsBuffer);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
|
|
@ -131,6 +129,9 @@ public:
|
|||
virtual void release_index_buffer(IndexBufferContext *ibc);
|
||||
const unsigned char *setup_primitive(const GeomPrimitive *data);
|
||||
|
||||
virtual void begin_occlusion_query();
|
||||
virtual PT(OcclusionQueryContext) end_occlusion_query();
|
||||
|
||||
virtual PT(GeomMunger) make_geom_munger(const RenderState *state);
|
||||
|
||||
virtual void framebuffer_copy_to_texture
|
||||
|
|
@ -424,7 +425,13 @@ public:
|
|||
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC _glGetFramebufferAttachmentParameteriv;
|
||||
PFNGLGENERATEMIPMAPEXTPROC _glGenerateMipmap;
|
||||
|
||||
PFNGLDRAWBUFFERSARBPROC _glDrawBuffers;
|
||||
PFNGLDRAWBUFFERSPROC _glDrawBuffers;
|
||||
|
||||
PFNGLGENQUERIESPROC _glGenQueries;
|
||||
PFNGLBEGINQUERYPROC _glBeginQuery;
|
||||
PFNGLENDQUERYPROC _glEndQuery;
|
||||
PFNGLDELETEQUERIESPROC _glDeleteQueries;
|
||||
PFNGLGETQUERYOBJECTUIVPROC _glGetQueryObjectuiv;
|
||||
|
||||
GLenum _edge_clamp;
|
||||
GLenum _border_clamp;
|
||||
|
|
@ -436,6 +443,7 @@ public:
|
|||
Mutex _lock;
|
||||
typedef pvector<GLuint> DeletedDisplayLists;
|
||||
DeletedDisplayLists _deleted_display_lists;
|
||||
DeletedDisplayLists _deleted_queries;
|
||||
|
||||
static PStatCollector _load_display_list_pcollector;
|
||||
static PStatCollector _primitive_batches_display_list_pcollector;
|
||||
|
|
@ -461,6 +469,10 @@ public:
|
|||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class CLP(ShaderContext);
|
||||
friend class CLP(GraphicsBuffer);
|
||||
friend class CLP(OcclusionQueryContext);
|
||||
};
|
||||
|
||||
#include "glGraphicsStateGuardian_src.I"
|
||||
|
|
|
|||
|
|
@ -62,6 +62,13 @@ ConfigVariableBool CLP(color_mask)
|
|||
"is broken (some are). This will force the use of a (presumably) "
|
||||
"more expensive blending operation instead."));
|
||||
|
||||
ConfigVariableBool CLP(support_occlusion_query)
|
||||
("gl-support-occlusion-query", true,
|
||||
PRC_DESC("Configure this true to enable the use of the occlusion_query "
|
||||
"extension if the GL claims to support it, or false not to "
|
||||
"use it even if it appears to be available. (On some OpenGL "
|
||||
"drivers, enabling this mode can force software rendering.)"));
|
||||
|
||||
ConfigVariableBool CLP(compile_and_execute)
|
||||
("gl-compile-and-execute", false,
|
||||
PRC_DESC("Configure this true if you know your GL's implementation of "
|
||||
|
|
@ -73,13 +80,14 @@ ConfigVariableBool CLP(compile_and_execute)
|
|||
"rendered at the same time it is being compiled."));
|
||||
|
||||
void CLP(init_classes)() {
|
||||
CLP(GraphicsStateGuardian)::init_type();
|
||||
CLP(TextureContext)::init_type();
|
||||
CLP(GeomContext)::init_type();
|
||||
CLP(VertexBufferContext)::init_type();
|
||||
CLP(IndexBufferContext)::init_type();
|
||||
CLP(GeomMunger)::init_type();
|
||||
CLP(GraphicsStateGuardian)::init_type();
|
||||
CLP(IndexBufferContext)::init_type();
|
||||
CLP(OcclusionQueryContext)::init_type();
|
||||
CLP(ShaderContext)::init_type();
|
||||
CLP(TextureContext)::init_type();
|
||||
CLP(VertexBufferContext)::init_type();
|
||||
|
||||
PandaSystem *ps = PandaSystem::get_global_ptr();
|
||||
ps->add_system(GLSYSTEM_NAME);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ extern ConfigVariableBool CLP(ignore_filters);
|
|||
extern ConfigVariableBool CLP(ignore_mipmaps);
|
||||
extern ConfigVariableBool CLP(force_mipmaps);
|
||||
extern ConfigVariableBool CLP(color_mask);
|
||||
extern ConfigVariableBool CLP(support_occlusion_query);
|
||||
extern ConfigVariableBool CLP(compile_and_execute);
|
||||
|
||||
extern EXPCL_GL void CLP(init_classes)();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "glTextureContext_src.cxx"
|
||||
#include "glVertexBufferContext_src.cxx"
|
||||
#include "glIndexBufferContext_src.cxx"
|
||||
#include "glOcclusionQueryContext_src.cxx"
|
||||
#include "glGeomContext_src.cxx"
|
||||
#include "glGeomMunger_src.cxx"
|
||||
#include "glShaderContext_src.cxx"
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "glTextureContext_src.h"
|
||||
#include "glVertexBufferContext_src.h"
|
||||
#include "glIndexBufferContext_src.h"
|
||||
#include "glOcclusionQueryContext_src.h"
|
||||
#include "glGeomContext_src.h"
|
||||
#include "glGeomMunger_src.h"
|
||||
#include "glShaderContext_src.h"
|
||||
|
|
|
|||
|
|
@ -41,10 +41,12 @@
|
|||
internalName.I internalName.h \
|
||||
material.I material.h materialPool.I materialPool.h \
|
||||
matrixLens.I matrixLens.h \
|
||||
occlusionQueryContext.I occlusionQueryContext.h \
|
||||
orthographicLens.I orthographicLens.h perspectiveLens.I \
|
||||
perspectiveLens.h \
|
||||
preparedGraphicsObjects.I preparedGraphicsObjects.h \
|
||||
lens.h lens.I \
|
||||
queryContext.I queryContext.h \
|
||||
savedContext.I savedContext.h \
|
||||
shaderContext.h shaderContext.I \
|
||||
shaderExpansion.h shaderExpansion.I \
|
||||
|
|
@ -93,10 +95,13 @@
|
|||
indexBufferContext.cxx \
|
||||
material.cxx \
|
||||
internalName.cxx \
|
||||
materialPool.cxx matrixLens.cxx orthographicLens.cxx \
|
||||
materialPool.cxx matrixLens.cxx \
|
||||
occlusionQuery.cxx \
|
||||
orthographicLens.cxx \
|
||||
perspectiveLens.cxx \
|
||||
preparedGraphicsObjects.cxx \
|
||||
lens.cxx \
|
||||
queryContext.cxx \
|
||||
savedContext.cxx \
|
||||
shaderContext.cxx \
|
||||
shaderExpansion.cxx \
|
||||
|
|
@ -146,10 +151,12 @@
|
|||
internalName.I internalName.h \
|
||||
material.I material.h \
|
||||
materialPool.I materialPool.h matrixLens.I matrixLens.h \
|
||||
occlusionQueryContext.I occlusionQueryContext.h \
|
||||
orthographicLens.I orthographicLens.h perspectiveLens.I \
|
||||
perspectiveLens.h \
|
||||
preparedGraphicsObjects.I preparedGraphicsObjects.h \
|
||||
lens.h lens.I \
|
||||
queryContext.I queryContext.h \
|
||||
savedContext.I savedContext.h \
|
||||
shaderContext.h shaderContext.I \
|
||||
shaderExpansion.h shaderExpansion.I \
|
||||
|
|
|
|||
|
|
@ -33,10 +33,12 @@
|
|||
#include "geomVertexData.h"
|
||||
#include "geomVertexFormat.h"
|
||||
#include "material.h"
|
||||
#include "occlusionQueryContext.h"
|
||||
#include "orthographicLens.h"
|
||||
#include "matrixLens.h"
|
||||
#include "perspectiveLens.h"
|
||||
#include "lens.h"
|
||||
#include "queryContext.h"
|
||||
#include "sliderTable.h"
|
||||
#include "texture.h"
|
||||
#include "textureStage.h"
|
||||
|
|
@ -263,10 +265,12 @@ ConfigureFn(config_gobj) {
|
|||
VertexBufferContext::init_type();
|
||||
IndexBufferContext::init_type();
|
||||
Material::init_type();
|
||||
OcclusionQueryContext::init_type();
|
||||
OrthographicLens::init_type();
|
||||
MatrixLens::init_type();
|
||||
PerspectiveLens::init_type();
|
||||
Lens::init_type();
|
||||
QueryContext::init_type();
|
||||
SliderTable::init_type();
|
||||
Texture::init_type();
|
||||
TextureStage::init_type();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "config_gobj.cxx"
|
||||
#include "indexBufferContext.cxx"
|
||||
#include "internalName.cxx"
|
||||
|
|
@ -6,9 +5,11 @@
|
|||
#include "material.cxx"
|
||||
#include "materialPool.cxx"
|
||||
#include "matrixLens.cxx"
|
||||
#include "occlusionQueryContext.cxx"
|
||||
#include "orthographicLens.cxx"
|
||||
#include "perspectiveLens.cxx"
|
||||
#include "preparedGraphicsObjects.cxx"
|
||||
#include "queryContext.cxx"
|
||||
#include "savedContext.cxx"
|
||||
#include "sliderTable.cxx"
|
||||
#include "texture.cxx"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// Filename: occlusionQueryContext.I
|
||||
// Created by: drose (27Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OcclusionQueryContext::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE OcclusionQueryContext::
|
||||
OcclusionQueryContext() {
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Filename: occlusionQueryContext.cxx
|
||||
// Created by: drose (27Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "occlusionQueryContext.h"
|
||||
|
||||
TypeHandle OcclusionQueryContext::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OcclusionQueryContext::get_num_fragments
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns the number of fragments (pixels) of the
|
||||
// specified geometry that passed the depth test.
|
||||
// If is_answer_ready() did not return true, this
|
||||
// function may block before it returns.
|
||||
//
|
||||
// It is only valid to call this from the draw thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int OcclusionQueryContext::
|
||||
get_num_fragments() const {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// Filename: occlusionQueryContext.h
|
||||
// Created by: drose (27Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef OCCLUSIONQUERYCONTEXT_H
|
||||
#define OCCLUSIONQUERYCONTEXT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "queryContext.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : OcclusionQueryContext
|
||||
// Description : Returned from a GSG in response to
|
||||
// begin_occlusion_query() .. end_occlusion_query(),
|
||||
// this records the number of fragments (pixels) that
|
||||
// passed the depth test between the bracketing calls.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA OcclusionQueryContext : public QueryContext {
|
||||
public:
|
||||
INLINE OcclusionQueryContext();
|
||||
|
||||
virtual int get_num_fragments() const=0;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
QueryContext::init_type();
|
||||
register_type(_type_handle, "OcclusionQueryContext",
|
||||
QueryContext::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class PreparedGraphicsObjects;
|
||||
};
|
||||
|
||||
#include "occlusionQueryContext.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Filename: queryContext.I
|
||||
// Created by: drose (27Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: QueryContext::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE QueryContext::
|
||||
QueryContext() {
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// Filename: queryContext.cxx
|
||||
// Created by: drose (27Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "queryContext.h"
|
||||
|
||||
TypeHandle QueryContext::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: QueryContext::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
QueryContext::
|
||||
~QueryContext() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: QueryContext::is_answer_ready
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if the query's answer is ready, false
|
||||
// otherwise. If this returns false, the application
|
||||
// must continue to poll until it returns true.
|
||||
//
|
||||
// It is only valid to call this from the draw thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool QueryContext::
|
||||
is_answer_ready() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: QueryContext::waiting_for_answer
|
||||
// Access: Public, Virtual
|
||||
// Description: Requests the graphics engine to expedite the pending
|
||||
// answer--the application is now waiting until the
|
||||
// answer is ready.
|
||||
//
|
||||
// It is only valid to call this from the draw thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void QueryContext::
|
||||
waiting_for_answer() {
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// Filename: queryContext.h
|
||||
// Created by: drose (27Mar06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef QUERYCONTEXT_H
|
||||
#define QUERYCONTEXT_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
|
||||
class PreparedGraphicsObjects;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : QueryContext
|
||||
// Description : This is a base class for queries that might require a
|
||||
// round-trip to the graphics engine. The idea is that
|
||||
// when you ask the GSG to make a particular query, it
|
||||
// returns a QueryContext, which does not necessarily
|
||||
// have the answer right away (but it will eventually).
|
||||
//
|
||||
// Unlike SavedContext, QueryContext is
|
||||
// reference-counted. It removes itself from the GSG
|
||||
// when the last reference goes away. You're
|
||||
// responsible for keeping the pointer to the
|
||||
// QueryContext as long as you are interested in the
|
||||
// answer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA QueryContext : public TypedReferenceCount {
|
||||
public:
|
||||
INLINE QueryContext();
|
||||
virtual ~QueryContext();
|
||||
|
||||
virtual bool is_answer_ready() const=0;
|
||||
virtual void waiting_for_answer();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "QueryContext",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "queryContext.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -32,6 +32,7 @@ class NodePath;
|
|||
|
||||
class VertexBufferContext;
|
||||
class IndexBufferContext;
|
||||
class OcclusionQueryContext;
|
||||
class GeomContext;
|
||||
class GeomNode;
|
||||
class Geom;
|
||||
|
|
@ -57,6 +58,7 @@ class GeomLinestrips;
|
|||
class GeomPoints;
|
||||
class GeomMunger;
|
||||
|
||||
class SceneSetup;
|
||||
class PreparedGraphicsObjects;
|
||||
class GraphicsOutput;
|
||||
class Texture;
|
||||
|
|
@ -118,11 +120,13 @@ class EXPCL_PANDA GraphicsStateGuardianBase : public TypedWritableReferenceCount
|
|||
PUBLISHED:
|
||||
virtual bool get_supports_multisample() const=0;
|
||||
virtual int get_supported_geom_rendering() const=0;
|
||||
virtual bool get_supports_occlusion_query() const=0;
|
||||
|
||||
public:
|
||||
// These are some general interface functions; they're defined here
|
||||
// mainly to make it easy to call these from code in some directory
|
||||
// that display depends on.
|
||||
virtual SceneSetup *get_scene() const=0;
|
||||
virtual PreparedGraphicsObjects *get_prepared_objects()=0;
|
||||
|
||||
virtual TextureContext *prepare_texture(Texture *tex)=0;
|
||||
|
|
@ -140,6 +144,9 @@ public:
|
|||
virtual IndexBufferContext *prepare_index_buffer(GeomPrimitive *data)=0;
|
||||
virtual void release_index_buffer(IndexBufferContext *ibc)=0;
|
||||
|
||||
virtual void begin_occlusion_query()=0;
|
||||
virtual PT(OcclusionQueryContext) end_occlusion_query()=0;
|
||||
|
||||
virtual PT(GeomMunger) get_geom_munger(const RenderState *state)=0;
|
||||
|
||||
virtual void set_state_and_transform(const RenderState *state,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ PUBLISHED:
|
|||
C_red = 0x001,
|
||||
C_green = 0x002,
|
||||
C_blue = 0x004,
|
||||
C_rgb = 0x007, // == C_red | C_green | C_blue
|
||||
C_alpha = 0x008,
|
||||
C_all = 0x00f,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -338,23 +338,17 @@ parse_bin_type(const string &bin_type) {
|
|||
} else if (cmp_nocase_uh(bin_type, "state_sorted") == 0) {
|
||||
return BT_state_sorted;
|
||||
|
||||
} else if (cmp_nocase_uh(bin_type, "statesorted") == 0) {
|
||||
return BT_state_sorted;
|
||||
|
||||
} else if (cmp_nocase_uh(bin_type, "fixed") == 0) {
|
||||
return BT_fixed;
|
||||
|
||||
} else if (cmp_nocase_uh(bin_type, "back_to_front") == 0) {
|
||||
return BT_back_to_front;
|
||||
|
||||
} else if (cmp_nocase_uh(bin_type, "backtofront") == 0) {
|
||||
return BT_back_to_front;
|
||||
|
||||
} else if (cmp_nocase_uh(bin_type, "front_to_back") == 0) {
|
||||
return BT_front_to_back;
|
||||
|
||||
} else if (cmp_nocase_uh(bin_type, "fronttoback") == 0) {
|
||||
return BT_front_to_back;
|
||||
} else if (cmp_nocase_uh(bin_type, "hierarchical_z") == 0) {
|
||||
return BT_hierarchical_z;
|
||||
|
||||
} else {
|
||||
return BT_invalid;
|
||||
|
|
@ -385,6 +379,9 @@ operator << (ostream &out, CullBinManager::BinType bin_type) {
|
|||
|
||||
case CullBinManager::BT_fixed:
|
||||
return out << "fixed";
|
||||
|
||||
case CullBinManager::BT_hierarchical_z:
|
||||
return out << "hierarchical_z";
|
||||
}
|
||||
|
||||
return out << "**invalid BinType(" << (int)bin_type << ")**";
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ PUBLISHED:
|
|||
BT_back_to_front,
|
||||
BT_front_to_back,
|
||||
BT_fixed,
|
||||
BT_hierarchical_z,
|
||||
};
|
||||
|
||||
int add_bin(const string &name, BinType type, int sort);
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ public:
|
|||
CPT(TransformState) _modelview_transform;
|
||||
CullableObject *_next;
|
||||
|
||||
// This flag is only used by certain CullBin types. In particular,
|
||||
// it is used by CullBinHierarchicalZBuffer.
|
||||
bool _already_drawn;
|
||||
|
||||
private:
|
||||
void munge_points_to_quads(const CullTraverser *traverser);
|
||||
void munge_texcoord_light_vector(const CullTraverser *traverser);
|
||||
|
|
|
|||
|
|
@ -99,9 +99,9 @@ PortalNode(const PortalNode ©) :
|
|||
_vertices(copy._vertices),
|
||||
_cell_in(copy._cell_in),
|
||||
_cell_out(copy._cell_out),
|
||||
_clip_plane(copy._clip_plane),
|
||||
_visible(copy._visible),
|
||||
_open(copy._open),
|
||||
_clip_plane(copy._clip_plane)
|
||||
_open(copy._open)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue