|
|
@@ -17,6 +17,7 @@
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "graphicsEngine.h"
|
|
|
+#include "config_display.h"
|
|
|
#include "pipeline.h"
|
|
|
#include "drawCullHandler.h"
|
|
|
#include "binCullHandler.h"
|
|
|
@@ -79,8 +80,11 @@ remove_window(GraphicsWindow *window) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void GraphicsEngine::
|
|
|
render_frame() {
|
|
|
- // cull_and_draw_together();
|
|
|
- cull_bin_draw();
|
|
|
+ if (cull_sorting) {
|
|
|
+ cull_bin_draw();
|
|
|
+ } else {
|
|
|
+ cull_and_draw_together();
|
|
|
+ }
|
|
|
|
|
|
// **** This doesn't belong here; it really belongs in the Pipeline,
|
|
|
// but here it is for now.
|
|
|
@@ -120,68 +124,18 @@ cull_and_draw_together() {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void GraphicsEngine::
|
|
|
cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) {
|
|
|
- const NodeChain &camera = dr->get_qpcamera();
|
|
|
- if (camera.is_empty()) {
|
|
|
- // No camera, no draw.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- qpCamera *camera_node;
|
|
|
- DCAST_INTO_V(camera_node, camera.node());
|
|
|
-
|
|
|
- if (!camera_node->is_active()) {
|
|
|
- // Camera inactive, no draw.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- Lens *lens = camera_node->get_lens();
|
|
|
- if (lens == (Lens *)NULL) {
|
|
|
- // No lens, no draw.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- NodeChain scene = camera_node->get_scene();
|
|
|
- if (scene.is_empty()) {
|
|
|
- // No scene, no draw.
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
GraphicsStateGuardian *gsg = win->get_gsg();
|
|
|
nassertv(gsg != (GraphicsStateGuardian *)NULL);
|
|
|
|
|
|
- if (!gsg->set_lens(lens)) {
|
|
|
- // The lens is inappropriate somehow.
|
|
|
- display_cat.error()
|
|
|
- << gsg->get_type() << " cannot render with " << lens->get_type()
|
|
|
- << "\n";
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- DrawCullHandler cull_handler(gsg);
|
|
|
- qpCullTraverser trav;
|
|
|
- trav.set_cull_handler(&cull_handler);
|
|
|
-
|
|
|
- // The world transform is computed from the camera's position; we
|
|
|
- // then might need to adjust it into the GSG's internal coordinate
|
|
|
- // system.
|
|
|
- trav.set_camera_transform(scene.get_rel_transform(camera));
|
|
|
-
|
|
|
- CPT(TransformState) render_transform = camera.get_rel_transform(scene);
|
|
|
- CoordinateSystem external_cs = gsg->get_coordinate_system();
|
|
|
- CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
|
|
|
- if (internal_cs != CS_default && internal_cs != external_cs) {
|
|
|
- CPT(TransformState) cs_transform =
|
|
|
- TransformState::make_mat(LMatrix4f::convert_mat(external_cs, internal_cs));
|
|
|
- render_transform = cs_transform->compose(render_transform);
|
|
|
+ if (set_gsg_lens(gsg, dr)) {
|
|
|
+ DisplayRegionStack old_dr = gsg->push_display_region(dr);
|
|
|
+ gsg->prepare_display_region();
|
|
|
+
|
|
|
+ DrawCullHandler cull_handler(gsg);
|
|
|
+ do_cull(&cull_handler, dr->get_qpcamera(), gsg);
|
|
|
+
|
|
|
+ gsg->pop_display_region(old_dr);
|
|
|
}
|
|
|
- trav.set_render_transform(render_transform);
|
|
|
-
|
|
|
- DisplayRegionStack old_dr = gsg->push_display_region(dr);
|
|
|
- gsg->prepare_display_region();
|
|
|
-
|
|
|
- trav.traverse(scene.node());
|
|
|
-
|
|
|
- gsg->pop_display_region(old_dr);
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -217,7 +171,34 @@ cull_bin_draw() {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void GraphicsEngine::
|
|
|
cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
|
|
|
- const NodeChain &camera = dr->get_qpcamera();
|
|
|
+ GraphicsStateGuardian *gsg = win->get_gsg();
|
|
|
+ nassertv(gsg != (GraphicsStateGuardian *)NULL);
|
|
|
+
|
|
|
+ PT(CullResult) cull_result = dr->_cull_result;
|
|
|
+ if (cull_result == (CullResult *)NULL) {
|
|
|
+ cull_result = new CullResult(gsg);
|
|
|
+ }
|
|
|
+
|
|
|
+ BinCullHandler cull_handler(cull_result);
|
|
|
+ do_cull(&cull_handler, dr->get_qpcamera(), gsg);
|
|
|
+
|
|
|
+ cull_result->finish_cull();
|
|
|
+
|
|
|
+ // Save the results for next frame.
|
|
|
+ dr->_cull_result = cull_result->make_next();
|
|
|
+
|
|
|
+ // Now draw.
|
|
|
+ do_draw(cull_result, gsg, dr);
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GraphicsEngine::do_cull
|
|
|
+// Access: Private
|
|
|
+// Description: Fires off a cull traversal using the indicated camera.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void GraphicsEngine::
|
|
|
+do_cull(CullHandler *cull_handler, const NodeChain &camera,
|
|
|
+ GraphicsStateGuardian *gsg) {
|
|
|
if (camera.is_empty()) {
|
|
|
// No camera, no draw.
|
|
|
return;
|
|
|
@@ -243,32 +224,21 @@ cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- GraphicsStateGuardian *gsg = win->get_gsg();
|
|
|
- nassertv(gsg != (GraphicsStateGuardian *)NULL);
|
|
|
-
|
|
|
- if (!gsg->set_lens(lens)) {
|
|
|
- // The lens is inappropriate somehow.
|
|
|
- display_cat.error()
|
|
|
- << gsg->get_type() << " cannot render with " << lens->get_type()
|
|
|
- << "\n";
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- PT(CullResult) cull_result = dr->_cull_result;
|
|
|
- if (cull_result == (CullResult *)NULL) {
|
|
|
- cull_result = new CullResult(gsg);
|
|
|
- }
|
|
|
-
|
|
|
- BinCullHandler cull_handler(cull_result);
|
|
|
qpCullTraverser trav;
|
|
|
- trav.set_cull_handler(&cull_handler);
|
|
|
+ trav.set_cull_handler(cull_handler);
|
|
|
|
|
|
- // The world transform is computed from the camera's position; we
|
|
|
- // then might need to adjust it into the GSG's internal coordinate
|
|
|
- // system.
|
|
|
- trav.set_camera_transform(scene.get_rel_transform(camera));
|
|
|
+ // We will need both the camera transform (the net transform from
|
|
|
+ // the scene to the camera) and the world transform (the camera
|
|
|
+ // transform inverse, or the net transform from the camera to the
|
|
|
+ // scene).
|
|
|
+ CPT(TransformState) camera_transform = scene.get_rel_transform(camera);
|
|
|
+ CPT(TransformState) world_transform = camera.get_rel_transform(scene);
|
|
|
+
|
|
|
+ // The render transform is the same as the world transform, except
|
|
|
+ // it is converted into the GSG's internal coordinate system. This
|
|
|
+ // is the transform that the GSG will apply to all of its vertices.
|
|
|
+ CPT(TransformState) render_transform = world_transform;
|
|
|
|
|
|
- CPT(TransformState) render_transform = camera.get_rel_transform(scene);
|
|
|
CoordinateSystem external_cs = gsg->get_coordinate_system();
|
|
|
CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
|
|
|
if (internal_cs != CS_default && internal_cs != external_cs) {
|
|
|
@@ -276,17 +246,80 @@ cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) {
|
|
|
TransformState::make_mat(LMatrix4f::convert_mat(external_cs, internal_cs));
|
|
|
render_transform = cs_transform->compose(render_transform);
|
|
|
}
|
|
|
+
|
|
|
+ trav.set_camera_transform(scene.get_rel_transform(camera));
|
|
|
trav.set_render_transform(render_transform);
|
|
|
+
|
|
|
+ if (qpview_frustum_cull) {
|
|
|
+ // If we're to be performing view-frustum culling, determine the
|
|
|
+ // bounding volume associated with the current viewing frustum.
|
|
|
+
|
|
|
+ // First, we have to get the current viewing frustum, which comes
|
|
|
+ // from the lens.
|
|
|
+ PT(BoundingVolume) bv = lens->make_bounds();
|
|
|
+
|
|
|
+ if (bv != (BoundingVolume *)NULL &&
|
|
|
+ bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
|
|
|
+ // Transform it into the appropriate coordinate space.
|
|
|
+ PT(GeometricBoundingVolume) local_frustum;
|
|
|
+ local_frustum = DCAST(GeometricBoundingVolume, bv->make_copy());
|
|
|
+ local_frustum->xform(camera_transform->get_mat());
|
|
|
+
|
|
|
+ trav.set_view_frustum(local_frustum);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
trav.traverse(scene.node());
|
|
|
- cull_result->finish_cull();
|
|
|
+}
|
|
|
|
|
|
- // Save the results for next frame.
|
|
|
- dr->_cull_result = cull_result->make_next();
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GraphicsEngine::do_draw
|
|
|
+// Access: Private
|
|
|
+// Description: Draws the previously-culled scene.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void GraphicsEngine::
|
|
|
+do_draw(CullResult *cull_result, GraphicsStateGuardian *gsg,
|
|
|
+ DisplayRegion *dr) {
|
|
|
+ if (set_gsg_lens(gsg, dr)) {
|
|
|
+ DisplayRegionStack old_dr = gsg->push_display_region(dr);
|
|
|
+ gsg->prepare_display_region();
|
|
|
+ cull_result->draw();
|
|
|
+ gsg->pop_display_region(old_dr);
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- // Now draw.
|
|
|
- DisplayRegionStack old_dr = gsg->push_display_region(dr);
|
|
|
- gsg->prepare_display_region();
|
|
|
- cull_result->draw();
|
|
|
- gsg->pop_display_region(old_dr);
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GraphicsEngine::set_gsg_lens
|
|
|
+// Access: Private
|
|
|
+// Description: Sets up the GSG to draw with the lens from the
|
|
|
+// indicated DisplayRegion. Returns true if the lens is
|
|
|
+// acceptable, false otherwise.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+bool GraphicsEngine::
|
|
|
+set_gsg_lens(GraphicsStateGuardian *gsg, DisplayRegion *dr) {
|
|
|
+ const NodeChain &camera = dr->get_qpcamera();
|
|
|
+ if (camera.is_empty()) {
|
|
|
+ // No camera, no draw.
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ qpCamera *camera_node;
|
|
|
+ DCAST_INTO_R(camera_node, camera.node(), false);
|
|
|
+
|
|
|
+ Lens *lens = camera_node->get_lens();
|
|
|
+ if (lens == (Lens *)NULL) {
|
|
|
+ // No lens, no draw.
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!gsg->set_lens(lens)) {
|
|
|
+ // The lens is inappropriate somehow.
|
|
|
+ display_cat.error()
|
|
|
+ << gsg->get_type() << " cannot render with " << lens->get_type()
|
|
|
+ << "\n";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|