From 0ad0d4ec33ba7b4ec3bfa689515eb6cbb8f73a2b Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Jan 2015 16:22:16 +0100 Subject: [PATCH] Further optimizations to the cull pipeline. The only transform still stored in CullableObject is internal transform. NB: I haven't tested my PipeOcclusionCullTraverser changes. Please contact me if you encounter problems with it. --- panda/src/collide/collisionVisualizer.cxx | 46 +++---- panda/src/cull/cullBinBackToFront.cxx | 8 +- panda/src/cull/cullBinFrontToBack.cxx | 8 +- panda/src/cull/cullBinStateSorted.I | 4 +- panda/src/display/graphicsEngine.cxx | 3 + panda/src/display/graphicsStateGuardian.I | 2 +- panda/src/display/graphicsStateGuardian.cxx | 10 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 13 ++ .../src/glstuff/glGraphicsStateGuardian_src.h | 2 + .../src/grutil/pipeOcclusionCullTraverser.cxx | 122 +++++++++-------- panda/src/grutil/pipeOcclusionCullTraverser.h | 19 +-- panda/src/gsgbase/graphicsStateGuardianBase.h | 6 +- panda/src/parametrics/ropeNode.cxx | 124 ++++++++---------- panda/src/parametrics/sheetNode.cxx | 38 +++--- panda/src/pgraph/cullBin.cxx | 4 +- panda/src/pgraph/cullHandler.cxx | 7 +- panda/src/pgraph/cullPlanes.cxx | 43 +++--- panda/src/pgraph/cullTraverser.cxx | 21 ++- panda/src/pgraph/cullTraverser.h | 9 +- panda/src/pgraph/cullTraverserData.I | 22 ++++ panda/src/pgraph/cullTraverserData.cxx | 11 -- panda/src/pgraph/cullTraverserData.h | 13 +- panda/src/pgraph/cullableObject.I | 30 ----- panda/src/pgraph/cullableObject.cxx | 36 ++--- panda/src/pgraph/cullableObject.h | 8 -- panda/src/pgraph/geomNode.cxx | 7 +- panda/src/pgraph/geomNode.h | 1 + panda/src/pgraph/nodePath.I | 27 ++++ panda/src/pgraph/nodePath.h | 5 + panda/src/pgraph/occluderNode.cxx | 16 +-- panda/src/pgraph/planeNode.cxx | 14 +- panda/src/pgraph/sceneSetup.I | 25 ++++ panda/src/pgraph/sceneSetup.h | 4 + panda/src/pgraphnodes/callbackNode.cxx | 8 +- panda/src/pgraphnodes/computeNode.cxx | 6 +- .../src/pgraphnodes/nodeCullCallbackData.cxx | 6 +- panda/src/rocket/rocketRenderInterface.cxx | 9 +- panda/src/speedtree/speedTreeNode.cxx | 102 +++++++------- 38 files changed, 436 insertions(+), 403 deletions(-) diff --git a/panda/src/collide/collisionVisualizer.cxx b/panda/src/collide/collisionVisualizer.cxx index 333552dda5..3a09d25803 100644 --- a/panda/src/collide/collisionVisualizer.cxx +++ b/panda/src/collide/collisionVisualizer.cxx @@ -122,14 +122,14 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { const VizInfo &viz_info = (*di).second; CullTraverserData xform_data(data); - + // We don't want to inherit the transform from above! We ignore // whatever transforms were above the CollisionVisualizer node; it // always renders its objects according to their appropriate net // transform. xform_data._net_transform = TransformState::make_identity(); xform_data._view_frustum = trav->get_view_frustum(); - xform_data.apply_transform_and_state(trav, net_transform, + xform_data.apply_transform_and_state(trav, net_transform, RenderState::make_empty(), RenderEffects::make_empty(), ClipPlaneAttrib::make()); @@ -148,7 +148,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { PT(PandaNode) node = solid->get_viz(trav, xform_data, !was_detected); if (node != (PandaNode *)NULL) { CullTraverserData next_data(xform_data, node); - + // We don't want to inherit the render state from above for // these guys. next_data._state = get_viz_state(); @@ -161,16 +161,16 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { CPT(RenderState) empty_state = RenderState::make_empty(); CPT(RenderState) point_state = RenderState::make(RenderModeAttrib::make(RenderModeAttrib::M_unchanged, 1.0f, false)); - PT(GeomVertexArrayFormat) point_array_format = + PT(GeomVertexArrayFormat) point_array_format = new GeomVertexArrayFormat(InternalName::get_vertex(), 3, Geom::NT_stdfloat, Geom::C_point, InternalName::get_color(), 1, Geom::NT_packed_dabc, Geom::C_color, - InternalName::get_size(), 1, + InternalName::get_size(), 1, Geom::NT_stdfloat, Geom::C_other); - CPT(GeomVertexFormat) point_format = + CPT(GeomVertexFormat) point_format = GeomVertexFormat::register_format(point_array_format); - + Points::const_iterator pi; for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) { const CollisionPoint &point = (*pi); @@ -178,9 +178,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { // Draw a small red point at the surface point, and a smaller // white point at the interior point. { - PT(GeomVertexData) point_vdata = + PT(GeomVertexData) point_vdata = new GeomVertexData("viz", point_format, Geom::UH_stream); - + PT(GeomPoints) points = new GeomPoints(Geom::UH_stream); GeomVertexWriter vertex(point_vdata, InternalName::get_vertex()); @@ -203,19 +203,17 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { PT(Geom) geom = new Geom(point_vdata); geom->add_primitive(points); - - CullableObject *object = - new CullableObject(geom, point_state, - xform_data.get_net_transform(trav), - xform_data.get_modelview_transform(trav), - trav->get_scene()); - + + CullableObject *object = + new CullableObject(geom, point_state, + xform_data.get_internal_transform(trav)); + trav->get_cull_handler()->record_object(object, trav); } // Draw the normal vector at the surface point. if (!point._surface_normal.almost_equal(LVector3::zero())) { - PT(GeomVertexData) line_vdata = + PT(GeomVertexData) line_vdata = new GeomVertexData("viz", GeomVertexFormat::get_v3cp(), Geom::UH_stream); @@ -225,7 +223,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { GeomVertexWriter color(line_vdata, InternalName::get_color()); vertex.add_data3(point._surface_point); - vertex.add_data3(point._surface_point + + vertex.add_data3(point._surface_point + point._surface_normal * _normal_scale); color.add_data4(1.0f, 0.0f, 0.0f, 1.0f); color.add_data4(1.0f, 1.0f, 1.0f, 1.0f); @@ -234,13 +232,11 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { PT(Geom) geom = new Geom(line_vdata); geom->add_primitive(lines); - - CullableObject *object = - new CullableObject(geom, empty_state, - xform_data.get_net_transform(trav), - xform_data.get_modelview_transform(trav), - trav->get_scene()); - + + CullableObject *object = + new CullableObject(geom, empty_state, + xform_data.get_internal_transform(trav)); + trav->get_cull_handler()->record_object(object, trav); } } diff --git a/panda/src/cull/cullBinBackToFront.cxx b/panda/src/cull/cullBinBackToFront.cxx index d90fb4968d..6a734c0092 100644 --- a/panda/src/cull/cullBinBackToFront.cxx +++ b/panda/src/cull/cullBinBackToFront.cxx @@ -66,11 +66,11 @@ add_object(CullableObject *object, Thread *current_thread) { const GeometricBoundingVolume *gbv; DCAST_INTO_V(gbv, volume); - + LPoint3 center = gbv->get_approx_center(); - nassertv(object->_modelview_transform != (const TransformState *)NULL); - center = center * object->_modelview_transform->get_mat(); - + nassertv(object->_internal_transform != (const TransformState *)NULL); + center = center * object->_internal_transform->get_mat(); + PN_stdfloat distance = _gsg->compute_distance_to(center); _objects.push_back(ObjectData(object, distance)); } diff --git a/panda/src/cull/cullBinFrontToBack.cxx b/panda/src/cull/cullBinFrontToBack.cxx index ab1a23b777..91e8c99133 100644 --- a/panda/src/cull/cullBinFrontToBack.cxx +++ b/panda/src/cull/cullBinFrontToBack.cxx @@ -66,11 +66,11 @@ add_object(CullableObject *object, Thread *current_thread) { const GeometricBoundingVolume *gbv; DCAST_INTO_V(gbv, volume); - + LPoint3 center = gbv->get_approx_center(); - nassertv(object->_modelview_transform != (const TransformState *)NULL); - center = center * object->_modelview_transform->get_mat(); - + nassertv(object->_internal_transform != (const TransformState *)NULL); + center = center * object->_internal_transform->get_mat(); + PN_stdfloat distance = _gsg->compute_distance_to(center); _objects.push_back(ObjectData(object, distance)); } diff --git a/panda/src/cull/cullBinStateSorted.I b/panda/src/cull/cullBinStateSorted.I index 53141cc9c6..8f16030d0d 100644 --- a/panda/src/cull/cullBinStateSorted.I +++ b/panda/src/cull/cullBinStateSorted.I @@ -47,8 +47,8 @@ INLINE bool CullBinStateSorted::ObjectData:: operator < (const ObjectData &other) const { // First group objects by transform, since transform changes are // supposed to be expensive. - if (_object->_modelview_transform != other._object->_modelview_transform) { - return _object->_modelview_transform < other._object->_modelview_transform; + if (_object->_internal_transform != other._object->_internal_transform) { + return _object->_internal_transform < other._object->_internal_transform; } // Then group by other state changes, in approximate order from diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 6ff2f0f78d..2222214e4a 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -1994,6 +1994,9 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) { CPT(TransformState) cs_transform = gsg->get_cs_transform_for(lens->get_coordinate_system()); scene_setup->set_cs_transform(cs_transform); + CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform); + scene_setup->set_cs_world_transform(cs_world_transform); + return scene_setup; } diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index d9a406c79f..703bc72c7a 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -204,7 +204,7 @@ set_loader(Loader *loader) { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_loader -// Access: Public, Virtual +// Access: Public // Description: Returns the Loader object that will be used by this // GSG to load textures when necessary, if // get_incomplete_render() is true. diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 3dc4cf7e50..2ebbad8420 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -878,14 +878,14 @@ make_geom_munger(const RenderState *state, Thread *current_thread) { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::compute_distance_to // Access: Public, Virtual -// Description: This function may only be called during a render -// traversal; it will compute the distance to the +// Description: This function will compute the distance to the // indicated point, assumed to be in eye coordinates, -// from the camera plane. +// from the camera plane. The point is assumed to be +// in the GSG's internal coordinate system. //////////////////////////////////////////////////////////////////// PN_stdfloat GraphicsStateGuardian:: compute_distance_to(const LPoint3 &point) const { - switch (_coordinate_system) { + switch (_internal_coordinate_system) { case CS_zup_right: return point[1]; @@ -901,7 +901,7 @@ compute_distance_to(const LPoint3 &point) const { default: gsg_cat.error() << "Invalid coordinate system in compute_distance_to: " - << (int)_coordinate_system << "\n"; + << (int)_internal_coordinate_system << "\n"; return 0.0f; } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 3ff7b50a5a..0ccf6dd07c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -5157,6 +5157,19 @@ make_geom_munger(const RenderState *state, Thread *current_thread) { return GeomMunger::register_munger(munger, current_thread); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::compute_distance_to +// Access: Public, Virtual +// Description: This function will compute the distance to the +// indicated point, assumed to be in eye coordinates, +// from the camera plane. The point is assumed to be +// in the GSG's internal coordinate system. +//////////////////////////////////////////////////////////////////// +PN_stdfloat GLGraphicsStateGuardian:: +compute_distance_to(const LPoint3 &point) const { + return -point[2]; +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::framebuffer_copy_to_texture // Access: Public, Virtual diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index d7567a9f63..e91e9a4df7 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -326,6 +326,8 @@ public: virtual PT(GeomMunger) make_geom_munger(const RenderState *state, Thread *current_thread); + virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const; + virtual void clear(DrawableRegion *region); virtual bool framebuffer_copy_to_texture diff --git a/panda/src/grutil/pipeOcclusionCullTraverser.cxx b/panda/src/grutil/pipeOcclusionCullTraverser.cxx index e5783b069b..3ade43d8f0 100644 --- a/panda/src/grutil/pipeOcclusionCullTraverser.cxx +++ b/panda/src/grutil/pipeOcclusionCullTraverser.cxx @@ -76,7 +76,7 @@ static ConfigVariableInt occlusion_depth_bits //////////////////////////////////////////////////////////////////// // Function: PipeOcclusionCullTraverser::Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// PipeOcclusionCullTraverser:: PipeOcclusionCullTraverser(GraphicsOutput *host) { @@ -103,7 +103,7 @@ PipeOcclusionCullTraverser(GraphicsOutput *host) { win_prop.set_size(occlusion_size[0], occlusion_size[1]); } - _buffer = engine->make_output(pipe, "occlusion", 0, fb_prop, win_prop, + _buffer = engine->make_output(pipe, "occlusion", 0, fb_prop, win_prop, GraphicsPipe::BF_refuse_window, gsg, host->get_host()); nassertv(_buffer != (GraphicsOutput *)NULL); @@ -125,7 +125,7 @@ PipeOcclusionCullTraverser(GraphicsOutput *host) { //////////////////////////////////////////////////////////////////// // Function: PipeOcclusionCullTraverser::Copy Constructor // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// PipeOcclusionCullTraverser:: PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser ©) : @@ -137,7 +137,7 @@ PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser ©) : //////////////////////////////////////////////////////////////////// // Function: PipeOcclusionCullTraverser::set_scene // Access: Published, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void PipeOcclusionCullTraverser:: set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase, @@ -154,7 +154,7 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase, Thread *current_thread = get_current_thread(); if (!_buffer->begin_frame(GraphicsOutput::FM_render, current_thread)) { - cerr << "begin_frame failed\n"; + grutil_cat.error() << "begin_frame failed\n"; return; } _buffer->clear(current_thread); @@ -166,7 +166,7 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase, _scene = new SceneSetup(*scene_setup); _scene->set_display_region(_display_region); - _scene->set_viewport_size(_display_region->get_pixel_width(), + _scene->set_viewport_size(_display_region->get_pixel_width(), _display_region->get_pixel_height()); if (_scene->get_cull_center() != _scene->get_camera_path()) { @@ -177,13 +177,22 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase, NodePath scene_parent = _scene->get_scene_root().get_parent(current_thread); CPT(TransformState) camera_transform = cull_center.get_transform(scene_parent, current_thread); CPT(TransformState) world_transform = scene_parent.get_transform(cull_center, current_thread); + CPT(TransformState) cs_world_transform = _scene->get_cs_transform()->compose(world_transform); _scene->set_camera_transform(camera_transform); _scene->set_world_transform(world_transform); + _scene->set_cs_world_transform(cs_world_transform); + + // We use this to recover the original net_transform. + _inv_cs_world_transform = cs_world_transform->get_inverse(); + } else { + _inv_cs_world_transform = _scene->get_cs_world_transform()->get_inverse(); } - + + nassertv(_scene->get_cs_transform() == scene_setup->get_cs_transform()); + gsg->set_scene(_scene); if (!gsg->begin_scene()) { - cerr << "begin_scene failed\n"; + grutil_cat.error() << "begin_scene failed\n"; return; } @@ -202,7 +211,7 @@ set_scene(SceneSetup *scene_setup, GraphicsStateGuardianBase *gsgbase, _current_query = NULL; _next_query = NULL; - + // Begin by rendering all the occluders into our internal scene. PStatTimer timer2(_draw_occlusion_pcollector); _internal_trav->traverse(_scene->get_scene_root()); @@ -299,7 +308,7 @@ get_texture() { //////////////////////////////////////////////////////////////////// // Function: PipeOcclusionCullTraverser::is_in_view // Access: Protected, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// bool PipeOcclusionCullTraverser:: is_in_view(CullTraverserData &data) { @@ -335,12 +344,12 @@ is_in_view(CullTraverserData &data) { CPT(BoundingVolume) vol = node_reader->get_bounds(); CPT(TransformState) net_transform = data.get_net_transform(this); - CPT(TransformState) modelview_transform; + CPT(TransformState) internal_transform; CPT(Geom) geom; - if (get_volume_viz(vol, geom, net_transform, modelview_transform)) { - _next_query = - perform_occlusion_test(geom, net_transform, modelview_transform); + if (get_volume_viz(vol, geom, net_transform, internal_transform)) { + _next_query = + perform_occlusion_test(geom, net_transform, internal_transform); } } @@ -408,12 +417,12 @@ record_object(CullableObject *object, const CullTraverser *traverser) { } else { // Issue an occlusion test for this object. CPT(BoundingVolume) vol = object->_geom->get_bounds(current_thread); - CPT(TransformState) net_transform = object->_net_transform; - CPT(TransformState) modelview_transform; + CPT(TransformState) net_transform = _inv_cs_world_transform->compose(object->_internal_transform); + CPT(TransformState) internal_transform; CPT(Geom) geom; - if (get_volume_viz(vol, geom, net_transform, modelview_transform)) { - pobj._query = - perform_occlusion_test(geom, net_transform, modelview_transform); + if (get_volume_viz(vol, geom, net_transform, internal_transform)) { + pobj._query = + perform_occlusion_test(geom, net_transform, internal_transform); } } @@ -437,7 +446,7 @@ make_sphere() { PT(GeomVertexData) vdata = new GeomVertexData ("occlusion_sphere", GeomVertexFormat::get_v3(), Geom::UH_static); GeomVertexWriter vertex(vdata, InternalName::get_vertex()); - + PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream); for (int sl = 0; sl < num_slices; ++sl) { PN_stdfloat longitude0 = (PN_stdfloat)sl / (PN_stdfloat)num_slices; @@ -449,11 +458,11 @@ make_sphere() { vertex.add_data3(compute_sphere_point(latitude, longitude1)); } vertex.add_data3(compute_sphere_point(1.0, longitude0)); - + strip->add_next_vertices(num_stacks * 2); strip->close_primitive(); } - + _sphere_geom = new Geom(vdata); _sphere_geom->add_primitive(strip); } @@ -462,7 +471,7 @@ make_sphere() { // Function: PipeOcclusionCullTraverser::compute_sphere_point // Access: Private, Static // Description: Returns a point on the surface of the unit sphere. -// latitude and longitude range from 0.0 to 1.0. +// latitude and longitude range from 0.0 to 1.0. //////////////////////////////////////////////////////////////////// LVertex PipeOcclusionCullTraverser:: compute_sphere_point(PN_stdfloat latitude, PN_stdfloat longitude) { @@ -487,7 +496,7 @@ make_box() { PT(GeomVertexData) vdata = new GeomVertexData ("occlusion_box", GeomVertexFormat::get_v3(), Geom::UH_static); GeomVertexWriter vertex(vdata, InternalName::get_vertex()); - + vertex.add_data3(0.0f, 0.0f, 0.0f); vertex.add_data3(0.0f, 0.0f, 1.0f); vertex.add_data3(0.0f, 1.0f, 0.0f); @@ -496,7 +505,7 @@ make_box() { vertex.add_data3(1.0f, 0.0f, 1.0f); vertex.add_data3(1.0f, 1.0f, 0.0f); vertex.add_data3(1.0f, 1.0f, 1.0f); - + PT(GeomTriangles) tris = new GeomTriangles(Geom::UH_static); tris->add_vertices(0, 4, 5); tris->close_primitive(); @@ -522,7 +531,7 @@ make_box() { tris->close_primitive(); tris->add_vertices(2, 4, 0); tris->close_primitive(); - + _box_geom = new Geom(vdata); _box_geom->add_primitive(tris); } @@ -554,14 +563,14 @@ make_solid_test_state() { // transform to the bounding volume. On exit (when // return value is true), it will be composed with a // suitable local transform to render the bounding -// volume properly, and modelview_transform will also be +// volume properly, and internal_transform will also be // filled with the appropriate transform. //////////////////////////////////////////////////////////////////// bool PipeOcclusionCullTraverser:: -get_volume_viz(const BoundingVolume *vol, +get_volume_viz(const BoundingVolume *vol, CPT(Geom) &geom, // OUT CPT(TransformState) &net_transform, // IN-OUT - CPT(TransformState) &modelview_transform // OUT + CPT(TransformState) &internal_transform // OUT ) { if (vol->is_infinite() || vol->is_empty()) { return false; @@ -569,13 +578,14 @@ get_volume_viz(const BoundingVolume *vol, if (vol->is_exact_type(BoundingSphere::get_class_type())) { const BoundingSphere *sphere = DCAST(BoundingSphere, vol); - CPT(TransformState) local_transform = + CPT(TransformState) local_transform = TransformState::make_pos_hpr_scale(sphere->get_center(), LVecBase3(0, 0, 0), sphere->get_radius()); net_transform = net_transform->compose(local_transform); - modelview_transform = _internal_trav->get_world_transform()->compose(net_transform); + CPT(TransformState) modelview_transform = + _internal_trav->get_world_transform()->compose(net_transform); // See if the bounding sphere is clipped by the near plane. If it // is, the occlusion test may fail, so we won't bother performing @@ -587,19 +597,24 @@ get_volume_viz(const BoundingVolume *vol, return false; } + // Construct the internal transform for the internal traverser. + internal_transform = _internal_trav->get_scene()-> + get_cs_transform()->compose(modelview_transform); + // The sphere looks good. geom = _sphere_geom; return true; } else if (vol->is_exact_type(BoundingBox::get_class_type())) { const BoundingBox *box = DCAST(BoundingBox, vol); - CPT(TransformState) local_transform = + CPT(TransformState) local_transform = TransformState::make_pos_hpr_scale(box->get_minq(), LVecBase3(0, 0, 0), box->get_maxq() - box->get_minq()); net_transform = net_transform->compose(local_transform); - modelview_transform = _internal_trav->get_world_transform()->compose(net_transform); + CPT(TransformState) modelview_transform = + _internal_trav->get_world_transform()->compose(net_transform); // See if the bounding box is clipped by the near plane. If it // is, the occlusion test may fail, so we won't bother performing @@ -623,6 +638,10 @@ get_volume_viz(const BoundingVolume *vol, } } + // Construct the internal transform for the internal traverser. + internal_transform = _internal_trav->get_scene()-> + get_cs_transform()->compose(modelview_transform); + // The box looks good. geom = _box_geom; return true; @@ -640,7 +659,7 @@ get_volume_viz(const BoundingVolume *vol, //////////////////////////////////////////////////////////////////// PT(OcclusionQueryContext) PipeOcclusionCullTraverser:: perform_occlusion_test(const Geom *geom, const TransformState *net_transform, - const TransformState *modelview_transform) { + const TransformState *internal_transform) { _occlusion_tests_pcollector.add_level(1); PStatTimer timer(_test_occlusion_pcollector); @@ -648,9 +667,8 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform, gsg->begin_occlusion_query(); - CullableObject *viz = - new CullableObject(geom, _solid_test_state, - net_transform, modelview_transform, get_scene()); + CullableObject *viz = + new CullableObject(geom, _solid_test_state, internal_transform); static ConfigVariableBool test_occlude("test-occlude", false); if (test_occlude) { @@ -658,16 +676,16 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform, } else { _internal_cull_handler->record_object(viz, _internal_trav); } - + PT(OcclusionQueryContext) query = gsg->end_occlusion_query(); - + if (show_occlusion) { // Show the results of the occlusion. To do this, we need to get // the results of the query immediately. This will stall the // pipe, but we're rendering a debug effect, so we don't mind too // much. int num_fragments = query->get_num_fragments(); - show_results(num_fragments, geom, net_transform, modelview_transform); + show_results(num_fragments, geom, net_transform, internal_transform); } return query; @@ -680,18 +698,18 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform, // test for a particular bounding volume. //////////////////////////////////////////////////////////////////// void PipeOcclusionCullTraverser:: -show_results(int num_fragments, const Geom *geom, - const TransformState *net_transform, - const TransformState *modelview_transform) { +show_results(int num_fragments, const Geom *geom, + const TransformState *net_transform, + const TransformState *internal_transform) { LColor color; if (num_fragments == 0) { // Magenta: culled - color.set(0.8f, 0.0f, 1.0f, 0.4); + color.set(0.8f, 0.0f, 1.0f, 0.4f); } else { // Yellow: visible - color.set(1.0f, 1.0f, 0.5f, 0.4); + color.set(1.0f, 1.0f, 0.5f, 0.4f); } - + CPT(RenderState) state = RenderState::make (DepthWriteAttrib::make(DepthWriteAttrib::M_off), DepthTestAttrib::make(DepthTestAttrib::M_less), @@ -700,15 +718,13 @@ show_results(int num_fragments, const Geom *geom, GraphicsStateGuardian *gsg = _buffer->get_gsg(); - CullableObject *internal_viz = - new CullableObject(geom, state, - net_transform, modelview_transform, get_scene()); + CullableObject *internal_viz = + new CullableObject(geom, state, internal_transform); _internal_cull_handler->record_object(internal_viz, _internal_trav); // Also render the viz in the main scene. - modelview_transform = get_world_transform()->compose(net_transform); - CullableObject *main_viz = - new CullableObject(geom, state, - net_transform, modelview_transform, get_scene()); + internal_transform = get_scene()->get_cs_world_transform()->compose(net_transform); + CullableObject *main_viz = + new CullableObject(geom, state, internal_transform); _true_cull_handler->record_object(main_viz, this); } diff --git a/panda/src/grutil/pipeOcclusionCullTraverser.h b/panda/src/grutil/pipeOcclusionCullTraverser.h index fb8636c79d..35bd72159f 100644 --- a/panda/src/grutil/pipeOcclusionCullTraverser.h +++ b/panda/src/grutil/pipeOcclusionCullTraverser.h @@ -75,19 +75,19 @@ private: void make_solid_test_state(); - bool get_volume_viz(const BoundingVolume *vol, + bool get_volume_viz(const BoundingVolume *vol, CPT(Geom) &geom, // OUT CPT(TransformState) &net_transform, // IN-OUT - CPT(TransformState) &modelview_transform // OUT + CPT(TransformState) &internal_transform // OUT ); - PT(OcclusionQueryContext) - perform_occlusion_test(const Geom *geom, + PT(OcclusionQueryContext) + perform_occlusion_test(const Geom *geom, const TransformState *net_transform, - const TransformState *modelview_transform); + const TransformState *internal_transform); - void show_results(int num_fragments, const Geom *geom, - const TransformState *net_transform, - const TransformState *modelview_transform); + void show_results(int num_fragments, const Geom *geom, + const TransformState *net_transform, + const TransformState *internal_transform); private: bool _live; @@ -98,6 +98,7 @@ private: PT(SceneSetup) _scene; PT(CullTraverser) _internal_trav; + CPT(TransformState) _inv_cs_world_transform; CullHandler *_internal_cull_handler; CullHandler *_true_cull_handler; @@ -157,4 +158,4 @@ private: #endif - + diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index d3252b4b74..436c169ee0 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -198,9 +198,9 @@ public: // inconvenient to declare each of those types to be friends of this // class. - virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, + virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, - const GeomVertexDataPipelineReader *data_reader, + const GeomVertexDataPipelineReader *data_reader, bool force)=0; virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)=0; virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)=0; @@ -218,7 +218,7 @@ public: virtual CoordinateSystem get_internal_coordinate_system() const=0; - virtual void bind_light(PointLight *light_obj, const NodePath &light, + virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id) { } virtual void bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) { } diff --git a/panda/src/parametrics/ropeNode.cxx b/panda/src/parametrics/ropeNode.cxx index 0c65a0d6b9..eaf0ef48ed 100644 --- a/panda/src/parametrics/ropeNode.cxx +++ b/panda/src/parametrics/ropeNode.cxx @@ -167,15 +167,15 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { case RM_thread: render_thread(trav, data, result); break; - + case RM_tape: render_tape(trav, data, result); break; - + case RM_billboard: render_billboard(trav, data, result); break; - + case RM_tube: render_tube(trav, data, result); break; @@ -183,7 +183,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { } } } - + return true; } @@ -205,7 +205,7 @@ is_renderable() const { //////////////////////////////////////////////////////////////////// // Function: RopeNode::output // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void RopeNode:: output(ostream &out) const { @@ -221,7 +221,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: RopeNode::write // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void RopeNode:: write(ostream &out, int indent_level) const { @@ -258,8 +258,8 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, int &internal_vertices, int pipeline_stage, Thread *current_thread) const { - PT(BoundingVolume) bounds = - do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, + PT(BoundingVolume) bounds = + do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, current_thread); internal_bounds = bounds; @@ -304,7 +304,7 @@ get_format(bool support_normals) const { // Description: Does the actual internal recompute. //////////////////////////////////////////////////////////////////// PT(BoundingVolume) RopeNode:: -do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, +do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, Thread *current_thread) const { // TODO: fix the bounds so that it properly reflects the indicated // pipeline stage. At the moment, we cheat and get some of the @@ -312,7 +312,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, // First, get ourselves a fresh, empty bounding volume. PT(BoundingVolume) bound = new BoundingSphere; - + NurbsCurveEvaluator *curve = get_curve(); if (curve != (NurbsCurveEvaluator *)NULL) { NurbsCurveEvaluator::Vert3Array verts; @@ -326,7 +326,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, (*vi) = LPoint3(*vi) * mat; } } - + GeometricBoundingVolume *gbv; DCAST_INTO_R(gbv, bound, bound); gbv->around(&verts[0], &verts[0] + verts.size()); @@ -349,7 +349,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, // per-vertex thickness. //////////////////////////////////////////////////////////////////// void RopeNode:: -render_thread(CullTraverser *trav, CullTraverserData &data, +render_thread(CullTraverser *trav, CullTraverserData &data, NurbsCurveResult *result) const { CurveSegments curve_segments; int num_curve_verts = get_connected_segments(curve_segments, result); @@ -370,21 +370,19 @@ render_thread(CullTraverser *trav, CullTraverserData &data, lines->add_vertex(vi + 1); lines->close_primitive(); } - + PT(Geom) geom = new Geom(vdata); geom->add_primitive(lines); - + CPT(RenderAttrib) thick = RenderModeAttrib::make(RenderModeAttrib::M_unchanged, get_thickness()); CPT(RenderState) state = data._state->add_attrib(thick); if (get_use_vertex_color()) { state = state->add_attrib(ColorAttrib::make_vertex()); } - - CullableObject *object = + + CullableObject *object = new CullableObject(geom, state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(object, trav); } @@ -399,7 +397,7 @@ render_thread(CullTraverser *trav, CullTraverserData &data, // determines the width of the triangle strips. //////////////////////////////////////////////////////////////////// void RopeNode:: -render_tape(CullTraverser *trav, CullTraverserData &data, +render_tape(CullTraverser *trav, CullTraverserData &data, NurbsCurveResult *result) const { CurveSegments curve_segments; int num_curve_verts = get_connected_segments(curve_segments, result); @@ -409,8 +407,8 @@ render_tape(CullTraverser *trav, CullTraverserData &data, // either side. PT(GeomVertexData) vdata = new GeomVertexData ("rope", get_format(false), Geom::UH_stream); - - compute_billboard_vertices(vdata, -get_tube_up(), + + compute_billboard_vertices(vdata, -get_tube_up(), curve_segments, num_curve_verts, result); // Since this will be a nonindexed primitive, no need to pre-reserve @@ -419,11 +417,11 @@ render_tape(CullTraverser *trav, CullTraverserData &data, CurveSegments::const_iterator si; for (si = curve_segments.begin(); si != curve_segments.end(); ++si) { const CurveSegment &segment = (*si); - + strip->add_next_vertices(segment.size() * 2); strip->close_primitive(); } - + PT(Geom) geom = new Geom(vdata); geom->add_primitive(strip); @@ -431,12 +429,10 @@ render_tape(CullTraverser *trav, CullTraverserData &data, if (get_use_vertex_color()) { state = state->add_attrib(ColorAttrib::make_vertex()); } - - CullableObject *object = + + CullableObject *object = new CullableObject(geom, state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(object, trav); } @@ -451,7 +447,7 @@ render_tape(CullTraverser *trav, CullTraverserData &data, // determines the width of the triangle strips. //////////////////////////////////////////////////////////////////// void RopeNode:: -render_billboard(CullTraverser *trav, CullTraverserData &data, +render_billboard(CullTraverser *trav, CullTraverserData &data, NurbsCurveResult *result) const { const TransformState *net_transform = data.get_net_transform(trav); const TransformState *camera_transform = trav->get_camera_transform(); @@ -468,21 +464,21 @@ render_billboard(CullTraverser *trav, CullTraverserData &data, // either side. PT(GeomVertexData) vdata = new GeomVertexData ("rope", get_format(false), Geom::UH_stream); - - compute_billboard_vertices(vdata, camera_vec, + + compute_billboard_vertices(vdata, camera_vec, curve_segments, num_curve_verts, result); - + // Since this will be a nonindexed primitive, no need to pre-reserve // the number of vertices. PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream); CurveSegments::const_iterator si; for (si = curve_segments.begin(); si != curve_segments.end(); ++si) { const CurveSegment &segment = (*si); - + strip->add_next_vertices(segment.size() * 2); strip->close_primitive(); } - + PT(Geom) geom = new Geom(vdata); geom->add_primitive(strip); @@ -490,12 +486,10 @@ render_billboard(CullTraverser *trav, CullTraverserData &data, if (get_use_vertex_color()) { state = state->add_attrib(ColorAttrib::make_vertex()); } - - CullableObject *object = + + CullableObject *object = new CullableObject(geom, state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(object, trav); } @@ -509,7 +503,7 @@ render_billboard(CullTraverser *trav, CullTraverserData &data, // determines the diameter of the tube. //////////////////////////////////////////////////////////////////// void RopeNode:: -render_tube(CullTraverser *trav, CullTraverserData &data, +render_tube(CullTraverser *trav, CullTraverserData &data, NurbsCurveResult *result) const { CurveSegments curve_segments; int num_curve_verts = get_connected_segments(curve_segments, result); @@ -522,10 +516,10 @@ render_tube(CullTraverser *trav, CullTraverserData &data, PT(GeomVertexData) vdata = new GeomVertexData ("rope", get_format(true), Geom::UH_stream); - - compute_tube_vertices(vdata, num_verts_per_slice, + + compute_tube_vertices(vdata, num_verts_per_slice, curve_segments, num_curve_verts, result); - + // Finally, go through and build up the index array, to tie all the // triangle strips together. This is difficult to pre-calculate the // number of vertices we'll use, so we'll just let it dynamically @@ -535,20 +529,20 @@ render_tube(CullTraverser *trav, CullTraverserData &data, CurveSegments::const_iterator si; for (si = curve_segments.begin(); si != curve_segments.end(); ++si) { const CurveSegment &segment = (*si); - + for (int s = 0; s < num_slices; ++s) { int s1 = (s + 1) % num_verts_per_slice; - + for (size_t j = 0; j < segment.size(); ++j) { strip->add_vertex((vi + j) * num_verts_per_slice + s); strip->add_vertex((vi + j) * num_verts_per_slice + s1); } - + strip->close_primitive(); } vi += (int)segment.size(); } - + PT(Geom) geom = new Geom(vdata); geom->add_primitive(strip); @@ -556,12 +550,10 @@ render_tube(CullTraverser *trav, CullTraverserData &data, if (get_use_vertex_color()) { state = state->add_attrib(ColorAttrib::make_vertex()); } - - CullableObject *object = + + CullableObject *object = new CullableObject(geom, state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(object, trav); } @@ -598,7 +590,7 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments, LPoint3 point; result->eval_segment_point(segment, 0.0f, point); - if (curve_segment == (CurveSegment *)NULL || + if (curve_segment == (CurveSegment *)NULL || !point.almost_equal(last_point)) { // If the first point of this segment is different from the last // point of the previous segment, end the previous segment and @@ -610,13 +602,13 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments, vtx._p = point; vtx._t = result->get_segment_t(segment, 0.0f); if (use_vertex_color) { - result->eval_segment_extended_points(segment, 0.0f, - get_vertex_color_dimension(), + result->eval_segment_extended_points(segment, 0.0f, + get_vertex_color_dimension(), &vtx._c[0], 4); } if (use_vertex_thickness) { - vtx._thickness = - result->eval_segment_extended_point(segment, 0.0f, + vtx._thickness = + result->eval_segment_extended_point(segment, 0.0f, get_vertex_thickness_dimension()); } @@ -632,13 +624,13 @@ get_connected_segments(RopeNode::CurveSegments &curve_segments, result->eval_segment_point(segment, t, vtx._p); vtx._t = result->get_segment_t(segment, t); if (use_vertex_color) { - result->eval_segment_extended_points(segment, t, + result->eval_segment_extended_points(segment, t, get_vertex_color_dimension(), &vtx._c[0], 4); } if (use_vertex_thickness) { - vtx._thickness = - result->eval_segment_extended_point(segment, t, + vtx._thickness = + result->eval_segment_extended_point(segment, t, get_vertex_thickness_dimension()); } @@ -868,7 +860,7 @@ compute_tube_vertices(GeomVertexData *vdata, // point in the segment. //////////////////////////////////////////////////////////////////// void RopeNode:: -compute_tangent(LVector3 &tangent, const RopeNode::CurveSegment &segment, +compute_tangent(LVector3 &tangent, const RopeNode::CurveSegment &segment, size_t j, NurbsCurveResult *result) { // First, try to evaluate the tangent at the curve. This gives // better results at the ends at the endpoints where the tangent @@ -908,17 +900,17 @@ compute_uv_t(PN_stdfloat &dist, const RopeNode::UVMode &uv_mode, switch (uv_mode) { case UV_none: return 0.0f; - + case UV_parametric: return segment[j]._t * uv_scale; - + case UV_distance: if (j != 0) { LVector3 vec = segment[j]._p - segment[j - 1]._p; dist += vec.length(); } return dist * uv_scale; - + case UV_distance2: if (j != 0) { LVector3 vec = segment[j]._p - segment[j - 1]._p; @@ -929,7 +921,7 @@ compute_uv_t(PN_stdfloat &dist, const RopeNode::UVMode &uv_mode, return 0.0f; } - + //////////////////////////////////////////////////////////////////// // Function: RopeNode::register_with_read_factory // Access: Public, Static diff --git a/panda/src/parametrics/sheetNode.cxx b/panda/src/parametrics/sheetNode.cxx index ce6da994f4..dd2fc4199b 100644 --- a/panda/src/parametrics/sheetNode.cxx +++ b/panda/src/parametrics/sheetNode.cxx @@ -155,13 +155,13 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { NurbsSurfaceEvaluator *surface = get_surface(); if (surface != (NurbsSurfaceEvaluator *)NULL) { PT(NurbsSurfaceResult) result = surface->evaluate(data._node_path.get_node_path()); - + if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) { render_sheet(trav, data, result); } } } - + return true; } @@ -183,7 +183,7 @@ is_renderable() const { //////////////////////////////////////////////////////////////////// // Function: SheetNode::output // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void SheetNode:: output(ostream &out) const { @@ -199,7 +199,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: SheetNode::write // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void SheetNode:: write(ostream &out, int indent_level) const { @@ -241,8 +241,8 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, int &internal_vertices, int pipeline_stage, Thread *current_thread) const { - PT(BoundingVolume) bounds = - do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, + PT(BoundingVolume) bounds = + do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage, current_thread); internal_bounds = bounds; @@ -255,7 +255,7 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, // Description: Does the actual internal recompute. //////////////////////////////////////////////////////////////////// PT(BoundingVolume) SheetNode:: -do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, +do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, Thread *current_thread) const { // TODO: fix the bounds so that it properly reflects the indicated // pipeline stage. At the moment, we cheat and get some of the @@ -263,12 +263,12 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, // First, get ourselves a fresh, empty bounding volume. PT(BoundingVolume) bound = new BoundingSphere; - + NurbsSurfaceEvaluator *surface = get_surface(); if (surface != (NurbsSurfaceEvaluator *)NULL) { NurbsSurfaceEvaluator::Vert3Array verts; get_surface()->get_vertices(verts, rel_to); - + GeometricBoundingVolume *gbv; DCAST_INTO_R(gbv, bound, bound); gbv->around(&verts[0], &verts[0] + verts.size()); @@ -283,7 +283,7 @@ do_recompute_bounds(const NodePath &rel_to, int pipeline_stage, // length. //////////////////////////////////////////////////////////////////// void SheetNode:: -render_sheet(CullTraverser *trav, CullTraverserData &data, +render_sheet(CullTraverser *trav, CullTraverserData &data, NurbsSurfaceResult *result) { bool use_vertex_color = get_use_vertex_color(); @@ -312,12 +312,12 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, for (int uni = 0; uni <= num_u_verts; uni++) { PN_stdfloat u0 = (PN_stdfloat)uni / (PN_stdfloat)num_u_verts; PN_stdfloat u0_tc = result->get_segment_u(ui, u0); - + for (int vi = 0; vi < num_v_segments; vi++) { for (int vni = 0; vni < num_v_verts; vni++) { PN_stdfloat v = (PN_stdfloat)vni / (PN_stdfloat)(num_v_verts - 1); PN_stdfloat v_tc = result->get_segment_v(vi, v); - + LPoint3 point; LVector3 norm; result->eval_segment_point(ui, vi, u0, v, point); @@ -325,7 +325,7 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, vertex.add_data3(point); normal.add_data3(norm); texcoord.add_data2(u0_tc, v_tc); - + if (use_vertex_color) { LColor c0; result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4); @@ -336,7 +336,7 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, } } nassertv(vdata->get_num_rows() == expected_num_vertices); - + PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream); int expected_num_tristrips = num_u_segments * num_u_verts * num_v_segments; @@ -364,7 +364,7 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, } } nassertv(strip->get_num_vertices() == expected_prim_vertices); - + PT(Geom) geom = new Geom(vdata); geom->add_primitive(strip); @@ -372,12 +372,10 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, if (use_vertex_color) { state = state->add_attrib(ColorAttrib::make_vertex()); } - - CullableObject *object = + + CullableObject *object = new CullableObject(geom, state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(object, trav); } diff --git a/panda/src/pgraph/cullBin.cxx b/panda/src/pgraph/cullBin.cxx index c0f4b2a472..7ce254d5b3 100644 --- a/panda/src/pgraph/cullBin.cxx +++ b/panda/src/pgraph/cullBin.cxx @@ -108,12 +108,12 @@ ResultGraphBuilder(PandaNode *root_node) : //////////////////////////////////////////////////////////////////// void CullBin::ResultGraphBuilder:: add_object(CullableObject *object) { - if (_current_transform != object->_modelview_transform || + if (_current_transform != object->_internal_transform || _current_state != object->_state) { // Create a new GeomNode to hold the net transform and state. We // choose to create a new GeomNode for each new state, to make it // clearer to the observer when the state changes. - _current_transform = object->_modelview_transform; + _current_transform = object->_internal_transform; _current_state = object->_state; _current_node = new GeomNode("object_" + format_string(_object_index)); _root_node->add_child(_current_node); diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx index 02c657595c..2bbe56924c 100644 --- a/panda/src/pgraph/cullHandler.cxx +++ b/panda/src/pgraph/cullHandler.cxx @@ -22,7 +22,7 @@ //////////////////////////////////////////////////////////////////// // Function: CullHandler::Constructor // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullHandler:: CullHandler() { @@ -31,7 +31,7 @@ CullHandler() { //////////////////////////////////////////////////////////////////// // Function: CullHandler::Destructor // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// CullHandler:: ~CullHandler() { @@ -50,7 +50,7 @@ CullHandler:: //////////////////////////////////////////////////////////////////// void CullHandler:: record_object(CullableObject *object, const CullTraverser *traverser) { - nout << *object->_geom << " " << *object->_modelview_transform << " " + nout << *object->_geom << " " << *object->_internal_transform << " " << *object->_state << "\n"; delete object; } @@ -65,4 +65,3 @@ record_object(CullableObject *object, const CullTraverser *traverser) { void CullHandler:: end_traverse() { } - diff --git a/panda/src/pgraph/cullPlanes.cxx b/panda/src/pgraph/cullPlanes.cxx index d4b6ce7ed6..d923974baf 100644 --- a/panda/src/pgraph/cullPlanes.cxx +++ b/panda/src/pgraph/cullPlanes.cxx @@ -116,11 +116,11 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, if (net_transform == (TransformState *)NULL) { net_transform = data->get_net_transform(trav); } - + PlaneNode *plane_node = DCAST(PlaneNode, clip_plane.node()); - CPT(TransformState) new_transform = + CPT(TransformState) new_transform = net_transform->invert_compose(clip_plane.get_net_transform()); - + LPlane plane = plane_node->get_plane() * new_transform->get_mat(); new_planes->_planes[clip_plane] = new BoundingPlane(-plane); } @@ -174,17 +174,17 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, ccp[2] = occluder_node->get_vertex(2) * composed_mat; ccp[3] = occluder_node->get_vertex(3) * composed_mat; - LPoint3 ccp_min(min(min(ccp[0][0], ccp[1][0]), + LPoint3 ccp_min(min(min(ccp[0][0], ccp[1][0]), min(ccp[2][0], ccp[3][0])), - min(min(ccp[0][1], ccp[1][1]), + min(min(ccp[0][1], ccp[1][1]), min(ccp[2][1], ccp[3][1])), - min(min(ccp[0][2], ccp[1][2]), + min(min(ccp[0][2], ccp[1][2]), min(ccp[2][2], ccp[3][2]))); - LPoint3 ccp_max(max(max(ccp[0][0], ccp[1][0]), + LPoint3 ccp_max(max(max(ccp[0][0], ccp[1][0]), max(ccp[2][0], ccp[3][0])), - max(max(ccp[0][1], ccp[1][1]), + max(max(ccp[0][1], ccp[1][1]), max(ccp[2][1], ccp[3][1])), - max(max(ccp[0][2], ccp[1][2]), + max(max(ccp[0][2], ccp[1][2]), max(ccp[2][2], ccp[3][2]))); occluder_gbv = new BoundingBox(ccp_min, ccp_max); @@ -209,7 +209,7 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, points_near[2] = occluder_node->get_vertex(2) * occluder_mat_cull; points_near[3] = occluder_node->get_vertex(3) * occluder_mat_cull; LPlane plane(points_near[0], points_near[1], points_near[2]); - + if (plane.get_normal().dot(LVector3::forward()) >= 0.0) { if (occluder_node->is_double_sided()) { swap(points_near[0], points_near[3]); @@ -294,22 +294,21 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, // With these points, construct the bounding frustum of the // occluded region. - PT(BoundingHexahedron) frustum = - new BoundingHexahedron(points_far[1], points_far[2], points_far[3], points_far[0], + PT(BoundingHexahedron) frustum = + new BoundingHexahedron(points_far[1], points_far[2], points_far[3], points_far[0], points_near[1], points_near[2], points_near[3], points_near[0]); new_planes->_occluders[occluder] = frustum; - + if (show_occluder_volumes) { // Draw the frustum for visualization. nassertr(net_transform != NULL, new_planes); - trav->draw_bounding_volume(frustum, net_transform, - data->get_modelview_transform(trav)); + trav->draw_bounding_volume(frustum, data->get_internal_transform(trav)); } } } } - + return new_planes; } @@ -330,13 +329,13 @@ apply_state(const CullTraverser *trav, const CullTraverserData *data, CPT(CullPlanes) CullPlanes:: do_cull(int &result, CPT(RenderState) &state, const GeometricBoundingVolume *node_gbv) const { - result = + result = BoundingVolume::IF_all | BoundingVolume::IF_possible | BoundingVolume::IF_some; CPT(ClipPlaneAttrib) orig_cpa = DCAST(ClipPlaneAttrib, state->get_attrib(ClipPlaneAttrib::get_class_slot())); CPT(CullPlanes) new_planes = this; - + if (orig_cpa == (ClipPlaneAttrib *)NULL) { // If there are no clip planes in the state, the node is completely // in front of all zero of the clip planes. (This can happen if @@ -385,7 +384,7 @@ do_cull(int &result, CPT(RenderState) &state, // The node is completely in front of this occluder. We don't // need to consider this occluder ever again for any descendents of // this node. - + // Reverse the sense of the test, because an occluder volume is // the inverse of a cull plane volume: it describes the volume // that is to be culled, not the volume that is to be kept. @@ -403,7 +402,7 @@ do_cull(int &result, CPT(RenderState) &state, result &= occluder_result; } - + return new_planes; } @@ -456,11 +455,11 @@ remove_occluder(const NodePath &occluder) const { //////////////////////////////////////////////////////////////////// // Function: CullPlanes::write // Access: Public -// Description: +// Description: //////////////////////////////////////////////////////////////////// void CullPlanes:: write(ostream &out) const { - out << "CullPlanes (" << _planes.size() << " planes and " + out << "CullPlanes (" << _planes.size() << " planes and " << _occluders.size() << " occluders):\n"; Planes::const_iterator pi; for (pi = _planes.begin(); pi != _planes.end(); ++pi) { diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index 70c953499a..2a92792e03 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -252,20 +252,19 @@ end_traverse() { //////////////////////////////////////////////////////////////////// void CullTraverser:: draw_bounding_volume(const BoundingVolume *vol, - const TransformState *net_transform, - const TransformState *modelview_transform) const { + const TransformState *internal_transform) const { PT(Geom) bounds_viz = make_bounds_viz(vol); if (bounds_viz != (Geom *)NULL) { _geoms_pcollector.add_level(2); CullableObject *outer_viz = new CullableObject(bounds_viz, get_bounds_outer_viz_state(), - net_transform, modelview_transform, get_scene()); + internal_transform); _cull_handler->record_object(outer_viz, this); CullableObject *inner_viz = new CullableObject(bounds_viz, get_bounds_inner_viz_state(), - net_transform, modelview_transform, get_scene()); + internal_transform); _cull_handler->record_object(inner_viz, this); } } @@ -292,8 +291,7 @@ is_in_view(CullTraverserData &data) { void CullTraverser:: show_bounds(CullTraverserData &data, bool tight) { PandaNode *node = data.node(); - CPT(TransformState) net_transform = data.get_net_transform(this); - CPT(TransformState) modelview_transform = data.get_modelview_transform(this); + CPT(TransformState) internal_transform = data.get_internal_transform(this); if (tight) { PT(Geom) bounds_viz = make_tight_bounds_viz(node); @@ -302,24 +300,21 @@ show_bounds(CullTraverserData &data, bool tight) { _geoms_pcollector.add_level(1); CullableObject *outer_viz = new CullableObject(bounds_viz, get_bounds_outer_viz_state(), - net_transform, modelview_transform, - get_scene()); + internal_transform); _cull_handler->record_object(outer_viz, this); } } else { - draw_bounding_volume(node->get_bounds(), - net_transform, modelview_transform); + draw_bounding_volume(node->get_bounds(), internal_transform); if (node->is_geom_node()) { // Also show the bounding volumes of included Geoms. - net_transform = net_transform->compose(node->get_transform()); - modelview_transform = modelview_transform->compose(node->get_transform()); + internal_transform = internal_transform->compose(node->get_transform()); GeomNode *gnode = DCAST(GeomNode, node); int num_geoms = gnode->get_num_geoms(); for (int i = 0; i < num_geoms; ++i) { draw_bounding_volume(gnode->get_geom(i)->get_bounds(), - net_transform, modelview_transform); + internal_transform); } } } diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index 9c22bec368..a174be5b3d 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -27,7 +27,6 @@ #include "drawMask.h" #include "typedReferenceCount.h" #include "pStatCollector.h" -#include "cullTraverserData.h" #include "fogAttrib.h" class GraphicsStateGuardian; @@ -90,8 +89,7 @@ PUBLISHED: INLINE static void flush_level(); void draw_bounding_volume(const BoundingVolume *vol, - const TransformState *net_transform, - const TransformState *modelview_transform) const; + const TransformState *internal_transform) const; protected: INLINE void do_traverse(CullTraverserData &data); @@ -148,9 +146,8 @@ private: static TypeHandle _type_handle; }; +#include "cullTraverserData.h" + #include "cullTraverser.I" #endif - - - diff --git a/panda/src/pgraph/cullTraverserData.I b/panda/src/pgraph/cullTraverserData.I index 61ea533b39..5cd227322d 100644 --- a/panda/src/pgraph/cullTraverserData.I +++ b/panda/src/pgraph/cullTraverserData.I @@ -136,6 +136,28 @@ node_reader() const { return &_node_reader; } +//////////////////////////////////////////////////////////////////// +// Function: CullTraverserData::get_modelview_transform +// Access: Published +// Description: Returns the modelview transform: the relative +// transform from the camera to the model. +//////////////////////////////////////////////////////////////////// +INLINE CPT(TransformState) CullTraverserData:: +get_modelview_transform(const CullTraverser *trav) const { + return trav->get_world_transform()->compose(_net_transform); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverserData::get_internal_transform +// Access: Published +// Description: Returns the internal transform: the modelview +// transform in the GSG's internal coordinate system. +//////////////////////////////////////////////////////////////////// +INLINE CPT(TransformState) CullTraverserData:: +get_internal_transform(const CullTraverser *trav) const { + return trav->get_scene()->get_cs_world_transform()->compose(_net_transform); +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverserData::get_net_transform // Access: Published diff --git a/panda/src/pgraph/cullTraverserData.cxx b/panda/src/pgraph/cullTraverserData.cxx index 400e1dc9fa..ce665e4806 100644 --- a/panda/src/pgraph/cullTraverserData.cxx +++ b/panda/src/pgraph/cullTraverserData.cxx @@ -28,17 +28,6 @@ #include "renderState.h" -//////////////////////////////////////////////////////////////////// -// Function: CullTraverserData::get_modelview_transform -// Access: Published -// Description: Returns the modelview transform: the relative -// transform from the camera to the model. -//////////////////////////////////////////////////////////////////// -CPT(TransformState) CullTraverserData:: -get_modelview_transform(const CullTraverser *trav) const { - return trav->get_world_transform()->compose(_net_transform); -} - //////////////////////////////////////////////////////////////////// // Function: CullTraverserData::apply_transform_and_state // Access: Published diff --git a/panda/src/pgraph/cullTraverserData.h b/panda/src/pgraph/cullTraverserData.h index bae251a307..73c1b137c2 100644 --- a/panda/src/pgraph/cullTraverserData.h +++ b/panda/src/pgraph/cullTraverserData.h @@ -50,8 +50,8 @@ public: GeometricBoundingVolume *view_frustum, Thread *current_thread); INLINE CullTraverserData(const CullTraverserData ©); - INLINE void operator = (const CullTraverserData ©); - INLINE CullTraverserData(const CullTraverserData &parent, + INLINE void operator = (const CullTraverserData ©); + INLINE CullTraverserData(const CullTraverserData &parent, PandaNode *child); INLINE ~CullTraverserData(); @@ -63,15 +63,16 @@ public: INLINE const PandaNodePipelineReader *node_reader() const; PUBLISHED: - CPT(TransformState) get_modelview_transform(const CullTraverser *trav) const; + INLINE CPT(TransformState) get_modelview_transform(const CullTraverser *trav) const; + INLINE CPT(TransformState) get_internal_transform(const CullTraverser *trav) const; INLINE const TransformState *get_net_transform(const CullTraverser *trav) const; INLINE bool is_in_view(const DrawMask &camera_mask); INLINE bool is_this_node_hidden(const DrawMask &camera_mask) const; void apply_transform_and_state(CullTraverser *trav); - void apply_transform_and_state(CullTraverser *trav, - CPT(TransformState) node_transform, + void apply_transform_and_state(CullTraverser *trav, + CPT(TransformState) node_transform, CPT(RenderState) node_state, CPT(RenderEffects) node_effects, const RenderAttrib *off_clip_planes); @@ -91,6 +92,8 @@ private: static CPT(RenderState) get_fake_view_frustum_cull_state(); }; +#include "cullTraverser.h" + #include "cullTraverserData.I" #endif diff --git a/panda/src/pgraph/cullableObject.I b/panda/src/pgraph/cullableObject.I index f9b32825e5..b2b1a8962a 100644 --- a/panda/src/pgraph/cullableObject.I +++ b/panda/src/pgraph/cullableObject.I @@ -34,35 +34,9 @@ CullableObject() { //////////////////////////////////////////////////////////////////// INLINE CullableObject:: CullableObject(const Geom *geom, const RenderState *state, - const TransformState *net_transform, - const TransformState *modelview_transform, - SceneSetup *scene_setup) : - _geom(geom), - _state(state), - _net_transform(net_transform), - _modelview_transform(modelview_transform), - _internal_transform(scene_setup->get_cs_transform()->compose(modelview_transform)) -{ -#ifdef DO_MEMORY_USAGE - MemoryUsage::update_type(this, get_class_type()); -#endif -} - -//////////////////////////////////////////////////////////////////// -// Function: CullableObject::Constructor -// Access: Public -// Description: Creates a CullableObject based the indicated geom, -// with the indicated render state and transform. -//////////////////////////////////////////////////////////////////// -INLINE CullableObject:: -CullableObject(const Geom *geom, const RenderState *state, - const TransformState *net_transform, - const TransformState *modelview_transform, const TransformState *internal_transform) : _geom(geom), _state(state), - _net_transform(net_transform), - _modelview_transform(modelview_transform), _internal_transform(internal_transform) { #ifdef DO_MEMORY_USAGE @@ -81,8 +55,6 @@ CullableObject(const CullableObject ©) : _munger(copy._munger), _munged_data(copy._munged_data), _state(copy._state), - _net_transform(copy._net_transform), - _modelview_transform(copy._modelview_transform), _internal_transform(copy._internal_transform) { #ifdef DO_MEMORY_USAGE @@ -101,8 +73,6 @@ operator = (const CullableObject ©) { _munger = copy._munger; _munged_data = copy._munged_data; _state = copy._state; - _net_transform = copy._net_transform; - _modelview_transform = copy._modelview_transform; _internal_transform = copy._internal_transform; _draw_callback = copy._draw_callback; } diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index b367cc6a4c..73c049ca15 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -79,7 +79,7 @@ munge_geom(GraphicsStateGuardianBase *gsg, geom_rendering = geom_reader.get_geom_rendering(); geom_rendering = _state->get_geom_rendering(geom_rendering); - geom_rendering = _modelview_transform->get_geom_rendering(geom_rendering); + geom_rendering = _internal_transform->get_geom_rendering(geom_rendering); if (geom_rendering & Geom::GR_point_bits) { if (geom_reader.get_primitive_type() != Geom::PT_points) { @@ -237,7 +237,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { } } - PN_stdfloat point_size = 1.0f; + PN_stdfloat point_size = 1; bool perspective = false; const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot())); if (render_mode != (RenderModeAttrib *)NULL) { @@ -309,11 +309,15 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { } } - const LMatrix4 &modelview = _modelview_transform->get_mat(); + CoordinateSystem internal_cs = gsg->get_internal_coordinate_system(); + LMatrix4 internal = _internal_transform->get_mat(); + PN_stdfloat scale = _internal_transform->get_scale()[1]; SceneSetup *scene = traverser->get_scene(); const Lens *lens = scene->get_lens(); - const LMatrix4 &projection = lens->get_projection_mat(); + LMatrix4 projection = + LMatrix4::convert_mat(internal_cs, lens->get_coordinate_system()) * + lens->get_projection_mat(); int viewport_width = scene->get_viewport_width(); int viewport_height = scene->get_viewport_height(); @@ -324,10 +328,10 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { if (perspective) { height_projection = LMatrix4::convert_mat(CS_yup_right, lens->get_coordinate_system()) * - projection; + lens->get_projection_mat(); } - LMatrix4 render_transform = modelview * projection; + LMatrix4 render_transform = internal * projection; LMatrix4 inv_render_transform; inv_render_transform.invert_from(render_transform); @@ -357,15 +361,16 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { int vi = 0; while (!vertex.is_at_end()) { // Get the point in eye-space coordinates. - LPoint3 eye = modelview.xform_point(vertex.get_data3()); + LPoint3 eye = internal.xform_point(vertex.get_data3()); + PN_stdfloat dist = gsg->compute_distance_to(eye); points[vi]._eye = eye; - points[vi]._dist = gsg->compute_distance_to(points[vi]._eye); + points[vi]._dist = dist; // The point in clip coordinates. LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection; if (has_size) { - point_size = size.get_data1f(); + point_size = size.get_data1(); } PN_stdfloat scale_y = point_size; @@ -374,7 +379,6 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { // height in 3-d units. To arrange that, we need to figure out // the appropriate scaling factor based on the current viewport // and projection matrix. - PN_stdfloat scale = _modelview_transform->get_scale()[1]; LVector3 height(0.0f, point_size * scale, scale); height = height * height_projection; scale_y = height[1] * viewport_height; @@ -382,7 +386,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { // We should then divide the radius by the distance from the // camera plane, to emulate the glPointParameters() behavior. if (!lens->is_orthographic()) { - scale_y /= gsg->compute_distance_to(eye); + scale_y /= dist; } } @@ -392,7 +396,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { PN_stdfloat scale_x = scale_y; if (has_aspect_ratio) { - scale_x *= aspect_ratio.get_data1f(); + scale_x *= aspect_ratio.get_data1(); } // Define the first two corners based on the scales in X and Y. @@ -401,7 +405,7 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { if (has_rotate) { // If we have a rotate factor, apply it to those two corners. - PN_stdfloat r = rotate.get_data1f(); + PN_stdfloat r = rotate.get_data1(); LMatrix3 mat = LMatrix3::rotate_mat(r); c0 = c0 * mat; c1 = c1 * mat; @@ -474,11 +478,9 @@ munge_points_to_quads(const CullTraverser *traverser, bool force) { } // Determine the format we should use to store the indices. + // Don't choose NT_uint8, as Direct3D 9 doesn't support it. const GeomVertexArrayFormat *new_prim_format = NULL; - if (new_verts < 0xff) { - new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint8); - - } else if (new_verts < 0xffff) { + if (new_verts < 0xffff) { new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint16); } else { diff --git a/panda/src/pgraph/cullableObject.h b/panda/src/pgraph/cullableObject.h index 28a166fb52..04250201f6 100644 --- a/panda/src/pgraph/cullableObject.h +++ b/panda/src/pgraph/cullableObject.h @@ -50,12 +50,6 @@ class EXPCL_PANDA_PGRAPH CullableObject public: INLINE CullableObject(); INLINE CullableObject(const Geom *geom, const RenderState *state, - const TransformState *net_transform, - const TransformState *modelview_transform, - SceneSetup *scene_setup); - INLINE CullableObject(const Geom *geom, const RenderState *state, - const TransformState *net_transform, - const TransformState *modelview_transform, const TransformState *internal_transform); INLINE CullableObject(const CullableObject ©); @@ -82,8 +76,6 @@ public: PT(GeomMunger) _munger; CPT(GeomVertexData) _munged_data; CPT(RenderState) _state; - CPT(TransformState) _net_transform; - CPT(TransformState) _modelview_transform; CPT(TransformState) _internal_transform; PT(CallbackObject) _draw_callback; diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index d8101fc778..db7bdd42dd 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -562,9 +562,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { Geoms geoms = get_geoms(trav->get_current_thread()); int num_geoms = geoms.get_num_geoms(); trav->_geoms_pcollector.add_level(num_geoms); - CPT(TransformState) net_transform = data.get_net_transform(trav); - CPT(TransformState) modelview_transform = data.get_modelview_transform(trav); - CPT(TransformState) internal_transform = trav->get_scene()->get_cs_transform()->compose(modelview_transform); + CPT(TransformState) internal_transform = data.get_internal_transform(trav); for (int i = 0; i < num_geoms; i++) { const Geom *geom = geoms.get_geom(i); @@ -611,8 +609,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { } CullableObject *object = - new CullableObject(geom, state, net_transform, - modelview_transform, internal_transform); + new CullableObject(geom, state, internal_transform); trav->get_cull_handler()->record_object(object, trav); } } diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index e839ef8344..285783df99 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -73,6 +73,7 @@ PUBLISHED: INLINE CPT(Geom) get_geom(int n) const; MAKE_SEQ(get_geoms, get_num_geoms, get_geom); INLINE PT(Geom) modify_geom(int n); + MAKE_SEQ(modify_geoms, get_num_geoms, modify_geom); INLINE const RenderState *get_geom_state(int n) const; MAKE_SEQ(get_geom_states, get_num_geoms, get_geom_state); INLINE void set_geom_state(int n, const RenderState *state); diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index c5a0ae25ee..69186c89e9 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -109,6 +109,33 @@ operator = (const NodePath ©) { _error_type = copy._error_type; } +#ifdef USE_MOVE_SEMANTICS +//////////////////////////////////////////////////////////////////// +// Function: NodePath::Move Constructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE NodePath:: +NodePath(NodePath &&from) NOEXCEPT : + _head(move(from._head)), + _backup_key(from._backup_key), + _error_type(from._error_type) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::Move Assignment Operator +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void NodePath:: +operator = (NodePath &&from) NOEXCEPT { + _head = move(from._head); + _backup_key = from._backup_key; + _error_type = from._error_type; +} +#endif // USE_MOVE_SEMANTICS + //////////////////////////////////////////////////////////////////// // Function: NodePath::not_found named constructor // Access: Published, Static diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index a55df7a358..a5d8ecb26a 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -180,6 +180,11 @@ PUBLISHED: INLINE NodePath(const NodePath ©); INLINE void operator = (const NodePath ©); +#ifdef USE_MOVE_SEMANTICS + INLINE NodePath(NodePath &&from) NOEXCEPT; + INLINE void operator = (NodePath &&from) NOEXCEPT; +#endif + EXTENSION(NodePath __copy__() const); EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const); EXTENSION(PyObject *__reduce__(PyObject *self) const); diff --git a/panda/src/pgraph/occluderNode.cxx b/panda/src/pgraph/occluderNode.cxx index 3afecfb25d..543c3eb906 100644 --- a/panda/src/pgraph/occluderNode.cxx +++ b/panda/src/pgraph/occluderNode.cxx @@ -164,20 +164,16 @@ bool OccluderNode:: cull_callback(CullTraverser *trav, CullTraverserData &data) { // Normally, an OccluderNode is invisible. But if someone shows it, // we will draw a visualization, a checkerboard-textured polygon. - CullableObject *occluder_viz = - new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data), - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + CullableObject *occluder_viz = + new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data), + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(occluder_viz, trav); // Also get the frame. nassertr(_frame_viz != (Geom *)NULL, false); - CullableObject *frame_viz = - new CullableObject(_frame_viz, get_frame_viz_state(trav, data), - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + CullableObject *frame_viz = + new CullableObject(_frame_viz, get_frame_viz_state(trav, data), + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(frame_viz, trav); // Now carry on to render our child nodes. diff --git a/panda/src/pgraph/planeNode.cxx b/panda/src/pgraph/planeNode.cxx index 8e2d25f41e..3dfaa6bb89 100644 --- a/panda/src/pgraph/planeNode.cxx +++ b/panda/src/pgraph/planeNode.cxx @@ -99,7 +99,7 @@ PlaneNode(const PlaneNode ©) : //////////////////////////////////////////////////////////////////// // Function: PlaneNode::output // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void PlaneNode:: output(ostream &out) const { @@ -166,11 +166,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { // Normally, a PlaneNode is invisible. But if someone shows it, we // will draw a visualization, a nice yellow wireframe. - CullableObject *plane_viz = - new CullableObject(get_viz(trav, data), data._state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + CullableObject *plane_viz = + new CullableObject(get_viz(trav, data), data._state, + data.get_internal_transform(trav)); trav->get_cull_handler()->record_object(plane_viz, trav); // Now carry on to render our child nodes. @@ -219,7 +217,7 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, PT(Geom) PlaneNode:: get_viz(CullTraverser *trav, CullTraverserData &data) { CDLockedReader cdata(_cycler); - + // Figure out whether we are looking at the front or the back of the // plane. const Lens *lens = trav->get_scene()->get_lens(); @@ -273,7 +271,7 @@ get_viz(CullTraverser *trav, CullTraverserData &data) { static const int num_segs = 10; a *= cdataw->_viz_scale / (num_segs * 2); b *= cdataw->_viz_scale / (num_segs * 2); - + for (int x = -num_segs; x <= num_segs; ++x) { vertex.add_data3(plane.project(a * x - b * num_segs)); vertex.add_data3(plane.project(a * x + b * num_segs)); diff --git a/panda/src/pgraph/sceneSetup.I b/panda/src/pgraph/sceneSetup.I index 7099a559f5..75afb67566 100644 --- a/panda/src/pgraph/sceneSetup.I +++ b/panda/src/pgraph/sceneSetup.I @@ -28,6 +28,7 @@ SceneSetup() { _camera_transform = TransformState::make_identity(); _world_transform = TransformState::make_identity(); _cs_transform = TransformState::make_identity(); + _cs_world_transform = TransformState::make_identity(); } //////////////////////////////////////////////////////////////////// @@ -316,3 +317,27 @@ INLINE const TransformState *SceneSetup:: get_cs_transform() const { return _cs_transform; } + +//////////////////////////////////////////////////////////////////// +// Function: SceneSetup::set_cs_world_transform +// Access: Published +// Description: Specifies the position from the starting node +// relative to the camera, in the GSG's internal +// coordinate system. +//////////////////////////////////////////////////////////////////// +INLINE void SceneSetup:: +set_cs_world_transform(const TransformState *cs_world_transform) { + _cs_world_transform = cs_world_transform; +} + +//////////////////////////////////////////////////////////////////// +// Function: SceneSetup::get_cs_world_transform +// Access: Published +// Description: Returns the position from the starting node +// relative to the camera, in the GSG's internal +// coordinate system. +//////////////////////////////////////////////////////////////////// +INLINE const TransformState *SceneSetup:: +get_cs_world_transform() const { + return _cs_world_transform; +} diff --git a/panda/src/pgraph/sceneSetup.h b/panda/src/pgraph/sceneSetup.h index f2ba3e6cf3..2dd740edf3 100644 --- a/panda/src/pgraph/sceneSetup.h +++ b/panda/src/pgraph/sceneSetup.h @@ -74,6 +74,9 @@ PUBLISHED: INLINE void set_cs_transform(const TransformState *cs_transform); INLINE const TransformState *get_cs_transform() const; + INLINE void set_cs_world_transform(const TransformState *cs_world_transform); + INLINE const TransformState *get_cs_world_transform() const; + private: DisplayRegion *_display_region; int _viewport_width; @@ -87,6 +90,7 @@ private: CPT(TransformState) _camera_transform; CPT(TransformState) _world_transform; CPT(TransformState) _cs_transform; + CPT(TransformState) _cs_world_transform; public: static TypeHandle get_class_type() { diff --git a/panda/src/pgraphnodes/callbackNode.cxx b/panda/src/pgraphnodes/callbackNode.cxx index 19c959f09f..03405835b0 100644 --- a/panda/src/pgraphnodes/callbackNode.cxx +++ b/panda/src/pgraphnodes/callbackNode.cxx @@ -149,7 +149,7 @@ void CallbackNode:: add_for_draw(CullTraverser *trav, CullTraverserData &data) { if (pgraph_cat.is_spam()) { pgraph_cat.spam() - << "Found " << *this << " in state " << *data._state + << "Found " << *this << " in state " << *data._state << " draw_mask = " << data._draw_mask << "\n"; } @@ -158,11 +158,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { // pass any Geoms, however. CallbackObject *cbobj = get_draw_callback(); if (cbobj != (CallbackObject *)NULL) { - CullableObject *object = + CullableObject *object = new CullableObject(NULL, data._state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); object->set_draw_callback(cbobj); trav->get_cull_handler()->record_object(object, trav); } diff --git a/panda/src/pgraphnodes/computeNode.cxx b/panda/src/pgraphnodes/computeNode.cxx index bae35b0e85..fd733e62e8 100644 --- a/panda/src/pgraphnodes/computeNode.cxx +++ b/panda/src/pgraphnodes/computeNode.cxx @@ -105,7 +105,7 @@ void ComputeNode:: add_for_draw(CullTraverser *trav, CullTraverserData &data) { if (pgraph_cat.is_spam()) { pgraph_cat.spam() - << "Found " << *this << " in state " << *data._state + << "Found " << *this << " in state " << *data._state << " draw_mask = " << data._draw_mask << "\n"; } @@ -114,9 +114,7 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { // any Geoms, however. CullableObject *object = new CullableObject(NULL, data._state, - data.get_net_transform(trav), - data.get_modelview_transform(trav), - trav->get_scene()); + data.get_internal_transform(trav)); object->set_draw_callback(_dispatcher); trav->get_cull_handler()->record_object(object, trav); } diff --git a/panda/src/pgraphnodes/nodeCullCallbackData.cxx b/panda/src/pgraphnodes/nodeCullCallbackData.cxx index f762650b04..d05b76babc 100644 --- a/panda/src/pgraphnodes/nodeCullCallbackData.cxx +++ b/panda/src/pgraphnodes/nodeCullCallbackData.cxx @@ -55,11 +55,9 @@ upcall() { // to pass any Geoms, however. CallbackObject *cbobj = cbnode->get_draw_callback(); if (cbobj != (CallbackObject *)NULL) { - CullableObject *object = + CullableObject *object = new CullableObject(NULL, _data._state, - _data.get_net_transform(_trav), - _data.get_modelview_transform(_trav), - _trav->get_scene()); + _data.get_internal_transform(_trav)); object->set_draw_callback(cbobj); _trav->get_cull_handler()->record_object(object, _trav); } diff --git a/panda/src/rocket/rocketRenderInterface.cxx b/panda/src/rocket/rocketRenderInterface.cxx index fe62db3c70..2813b89d5c 100644 --- a/panda/src/rocket/rocketRenderInterface.cxx +++ b/panda/src/rocket/rocketRenderInterface.cxx @@ -123,14 +123,13 @@ render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vect << *state << ", translation (" << offset << ")\n"; } - CPT(TransformState) net_transform, modelview_transform; - net_transform = _net_transform->compose(TransformState::make_pos(offset)); - modelview_transform = _trav->get_world_transform()->compose(net_transform); + CPT(TransformState) internal_transform = + _trav->get_scene()->get_cs_world_transform()->compose( + _net_transform->compose(TransformState::make_pos(offset))); CullableObject *object = new CullableObject(geom, _net_state->compose(state), - net_transform, modelview_transform, - _trav->get_scene()); + internal_transform); _trav->get_cull_handler()->record_object(object, _trav); } diff --git a/panda/src/speedtree/speedTreeNode.cxx b/panda/src/speedtree/speedTreeNode.cxx index 0b7639eb7e..4f15578c4f 100644 --- a/panda/src/speedtree/speedTreeNode.cxx +++ b/panda/src/speedtree/speedTreeNode.cxx @@ -332,7 +332,7 @@ add_instances_from(const SpeedTreeNode *other) { const InstanceList &other_instance_list = other->get_instance_list(ti); const STTree *tree = other_instance_list.get_tree(); InstanceList &this_instance_list = add_tree(tree); - + int num_instances = other_instance_list.get_num_instances(); for (int i = 0; i < num_instances; ++i) { STTransform other_trans = other_instance_list.get_instance(i); @@ -356,7 +356,7 @@ add_instances_from(const SpeedTreeNode *other, const TransformState *transform) const InstanceList &other_instance_list = other->get_instance_list(ti); const STTree *tree = other_instance_list.get_tree(); InstanceList &this_instance_list = add_tree(tree); - + int num_instances = other_instance_list.get_num_instances(); for (int i = 0; i < num_instances; ++i) { CPT(TransformState) other_trans = other_instance_list.get_instance(i); @@ -388,8 +388,8 @@ add_instances_from(const SpeedTreeNode *other, const TransformState *transform) // slope_min and slope_max are ignored. //////////////////////////////////////////////////////////////////// void SpeedTreeNode:: -add_random_instances(const STTree *tree, int quantity, - PN_stdfloat x_min, PN_stdfloat x_max, +add_random_instances(const STTree *tree, int quantity, + PN_stdfloat x_min, PN_stdfloat x_max, PN_stdfloat y_min, PN_stdfloat y_max, PN_stdfloat scale_min, PN_stdfloat scale_max, PN_stdfloat height_min, PN_stdfloat height_max, @@ -417,7 +417,7 @@ add_random_instances(const STTree *tree, int quantity, } } transform._pos[2] = _terrain->get_height(transform._pos[0], transform._pos[1]); - + } else { // No terrain; just pick a random height. transform._pos[2] = randomizer.random_real(height_max - height_min) + height_min; @@ -484,7 +484,7 @@ add_from_stf(const Filename &stf_filename, const LoaderOptions &options) { // NULL, the default global Loader is used instead. //////////////////////////////////////////////////////////////////// bool SpeedTreeNode:: -add_from_stf(istream &in, const Filename &pathname, +add_from_stf(istream &in, const Filename &pathname, const LoaderOptions &options, Loader *loader) { if (loader == NULL) { loader = Loader::get_global_ptr(); @@ -701,7 +701,7 @@ reload_config() { int num_shadow_maps = speedtree_cascading_shadow_splits.get_num_words(); if (num_shadow_maps > SpeedTree::c_nMaxNumShadowMaps) { speedtree_cat.warning() - << "SpeedTree is current compiled to support a maximum of " + << "SpeedTree is current compiled to support a maximum of " << SpeedTree::c_nMaxNumShadowMaps << " shadow maps.\n"; num_shadow_maps = SpeedTree::c_nMaxNumShadowMaps; } @@ -747,7 +747,7 @@ reload_config() { _forest_render.SetRenderInfo(render_info); _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy); - _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, + _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, speedtree_max_num_visible_cells); _visible_terrain.Reserve(speedtree_max_num_visible_cells); @@ -787,12 +787,12 @@ authorize(const string &license) { SpeedTree::CCore::Authorize(speedtree_license.c_str()); } } - + _authorized = SpeedTree::CCore::IsAuthorized(); SpeedTree::CCore::SetTextureFlip(true); } - + return _authorized; } @@ -821,7 +821,7 @@ SpeedTreeNode(const SpeedTreeNode ©) : // No way to copy these parameters, so we just re-assign them. _terrain_render.SetMaxAnisotropy(speedtree_max_anisotropy); - _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, + _terrain_render.SetHint(SpeedTree::CTerrain::HINT_MAX_NUM_VISIBLE_CELLS, speedtree_max_num_visible_cells); _visible_terrain.Reserve(speedtree_max_num_visible_cells); @@ -848,7 +848,7 @@ SpeedTreeNode(const SpeedTreeNode ©) : //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::Destructor // Access: Published, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// SpeedTreeNode:: ~SpeedTreeNode() { @@ -980,7 +980,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { ClockObject *clock = ClockObject::get_global_clock(); _forest_render.SetGlobalTime(clock->get_frame_time() + _time_delta + _global_time_delta); _forest_render.AdvanceGlobalWind(); - + // Compute the modelview and camera transforms, to pass to the // SpeedTree CView structure. CPT(TransformState) orig_modelview = data.get_modelview_transform(trav); @@ -989,11 +989,11 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { LMatrix4f modelview_mat = LCAST(float, modelview->get_mat()); const LPoint3 &camera_pos = camera_transform->get_pos(); const Lens *lens = trav->get_scene()->get_lens(); - + LMatrix4f projection_mat = LCAST(float, LMatrix4::convert_mat(gsg->get_internal_coordinate_system(), lens->get_coordinate_system()) * lens->get_projection_mat()); - + _view.Set(SpeedTree::Vec3(camera_pos[0], camera_pos[1], camera_pos[2]), SpeedTree::Mat4x4(projection_mat.get_data()), SpeedTree::Mat4x4(modelview_mat.get_data()), @@ -1041,7 +1041,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { } } } - + if (dlight != (DirectionalLight *)NULL) { CPT(TransformState) transform = dlight_np.get_transform(trav->get_scene()->get_scene_root().get_parent()); LVector3 dir = dlight->get_direction() * transform->get_mat(); @@ -1118,11 +1118,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) { // We create a CullableObject that has an explicit draw_callback // into this node, so that we can make the appropriate calls into // SpeedTree to render the forest during the actual draw. - CullableObject *object = + CullableObject *object = new CullableObject(NULL, data._state, - TransformState::make_identity(), - TransformState::make_identity(), - trav->get_scene()); + TransformState::make_identity()); object->set_draw_callback(new DrawCallback(this)); trav->get_cull_handler()->record_object(object, trav); } @@ -1208,7 +1206,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::write // Access: Public, Virtual -// Description: +// Description: //////////////////////////////////////////////////////////////////// void SpeedTreeNode:: write(ostream &out, int indent_level) const { @@ -1219,7 +1217,7 @@ write(ostream &out, int indent_level) const { Trees::const_iterator ti; for (ti = _trees.begin(); ti != _trees.end(); ++ti) { InstanceList *instance_list = (*ti); - indent(out, indent_level + 2) + indent(out, indent_level + 2) << *instance_list << "\n"; } */ @@ -1254,7 +1252,7 @@ set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode eMode) const { SpeedTree::CRenderState::SetBlending(false); SpeedTree::CRenderState::SetAlphaTesting(false); SpeedTree::CRenderState::SetAlphaToCoverage(false); - + switch (eMode) { case SpeedTree::TRANS_TEXTURE_ALPHA_TESTING: SpeedTree::CRenderState::SetAlphaTesting(true); @@ -1291,7 +1289,7 @@ init_node() { return; } - _forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS, + _forest_render.SetHint(SpeedTree::CForest::HINT_MAX_NUM_VISIBLE_CELLS, speedtree_max_num_visible_cells); _forest_render.SetCullCellSize(speedtree_cull_cell_size); @@ -1354,7 +1352,7 @@ repopulate() { write_error(speedtree_cat.warning()); } } - + _forest_render.GetPopulationStats(_population_stats); print_forest_stats(_population_stats); @@ -1379,8 +1377,8 @@ repopulate() { } _visible_trees.Reserve(_forest_render.GetBaseTrees(), - _forest_render.GetBaseTrees().size(), - speedtree_max_num_visible_cells, + _forest_render.GetBaseTrees().size(), + speedtree_max_num_visible_cells, max_instances_by_cell, speedtree_horizontal_billboards); } @@ -1401,8 +1399,8 @@ update_terrain_cells() { PN_stdfloat cell_size = _terrain_render.GetCellSize(); // A temporary vertex data object for populating terrain. - PT(GeomVertexData) vertex_data = - new GeomVertexData("terrain", _terrain->get_vertex_format(), + PT(GeomVertexData) vertex_data = + new GeomVertexData("terrain", _terrain->get_vertex_format(), GeomEnums::UH_static); int num_vertices = num_tile_res * num_tile_res; vertex_data->set_num_rows(num_vertices); @@ -1428,7 +1426,7 @@ update_terrain_cells() { nassertv(vbo->NumVertices() == num_tile_res * num_tile_res); nassertv(vbo->NumVertices() * vbo->VertexSize() == handle->get_data_size_bytes()); vbo->OverwriteVertices(data_pointer, num_vertices, 0); - } + } } //////////////////////////////////////////////////////////////////// @@ -1501,12 +1499,12 @@ draw_callback(CallbackData *data) { << "Couldn't set view parameters\n"; write_error(speedtree_cat.warning()); } - + if (has_terrain()) { PStatTimer timer1(_draw_speedtree_terrain_pcollector); // Is this needed for terrain? _terrain_render.UploadShaderConstants - (&_forest_render, _light_dir, + (&_forest_render, _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial); // set terrain render states @@ -1515,14 +1513,14 @@ draw_callback(CallbackData *data) { // render actual terrain bool terrain = _terrain_render.Render (&_forest_render, _visible_terrain, SpeedTree::RENDER_PASS_STANDARD, - _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial, + _light_dir, _forest_render.GetRenderInfo().m_sLightMaterial, &_forest_render.GetRenderStats()); if (!terrain) { speedtree_cat.warning() << "Failed to render terrain\n"; write_error(speedtree_cat.warning()); - + // Clear the terrain so we don't keep spamming error messages. _terrain = NULL; } @@ -1537,7 +1535,7 @@ draw_callback(CallbackData *data) { //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_BLENDING; //SpeedTree::ETextureAlphaRenderMode mode = SpeedTree::TRANS_TEXTURE_NOTHING; set_transparent_texture_mode(SpeedTree::ETextureAlphaRenderMode(mode)); - + bool branches = _forest_render.RenderBranches(_visible_trees, SpeedTree::RENDER_PASS_STANDARD); bool fronds = _forest_render.RenderFronds(_visible_trees, SpeedTree::RENDER_PASS_STANDARD); bool leaf_meshes = _forest_render.RenderLeafMeshes(_visible_trees, SpeedTree::RENDER_PASS_STANDARD); @@ -1548,7 +1546,7 @@ draw_callback(CallbackData *data) { // disabled; but the billboards appear to have been rendered // successfully. Weird. Just removing this test from the // condition. - + if (!branches || !fronds || !leaf_meshes || !leaf_cards /* || !billboards */) { speedtree_cat.warning() << "Failed to render forest completely: " @@ -1592,27 +1590,27 @@ render_forest_into_shadow_maps() { for (int smi = 0; smi < (int)_shadow_infos.size(); ++smi) { const SpeedTree::CView &light_view = _shadow_infos[smi]._light_view; const SpeedTree::SForestCullResults &light_cull = _shadow_infos[smi]._light_cull; - + if (_forest_render.BeginShadowMap(smi, light_view)) { success &= _forest_render.UploadViewShaderParameters(light_view); - + // branch geometry can be rendered with backfacing triangle // removed, so a closer tolerance can be used SpeedTree::CRenderState::SetPolygonOffset(1.0f, 0.125f); - + success &= _forest_render.RenderBranches(light_cull, SpeedTree::RENDER_PASS_SHADOW); - + // the remaining geometry types cannot be backface culled, so we // need a much more aggressive offset SpeedTree::CRenderState::SetPolygonOffset(10.0f, 1.0f); - + success &= _forest_render.RenderFronds(light_cull, SpeedTree::RENDER_PASS_SHADOW); success &= _forest_render.RenderLeafMeshes(light_cull, SpeedTree::RENDER_PASS_SHADOW); success &= _forest_render.RenderLeafCards(light_cull, SpeedTree::RENDER_PASS_SHADOW, light_view); - + // We don't bother to render billboard geometry into the shadow // map(s). - + success &= _forest_render.EndShadowMap(smi); } } @@ -1640,7 +1638,7 @@ setup_for_render(GraphicsStateGuardian *gsg) { // This is the first time we have entered the draw callback since // creating any SpeedTreeNode. Now we have an opportunity to do // any initial setup that requires a graphics context. - + #ifdef SPEEDTREE_OPENGL // For OpenGL, we have to ensure GLEW has been initialized. // (SpeedTree uses it, though Panda doesn't.) @@ -1684,7 +1682,7 @@ setup_for_render(GraphicsStateGuardian *gsg) { if (instances.empty()) { continue; } - + int max_instances = 2; SpeedTree::CMap::const_iterator si; si = _population_stats.m_mMaxNumInstancesPerCellPerBase.find(tree->get_tree()); @@ -1708,7 +1706,7 @@ setup_for_render(GraphicsStateGuardian *gsg) { #endif } - if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(), + if (!_forest_render.InitTreeGraphics((SpeedTree::CTreeRender *)tree->get_tree(), max_instances, speedtree_horizontal_billboards, os_textures_dir.c_str())) { if (speedtree_cat.is_debug()) { @@ -1735,7 +1733,7 @@ setup_for_render(GraphicsStateGuardian *gsg) { if (has_terrain()) { // Now initialize the terrain. - if (!_terrain_render.Init(speedtree_terrain_num_lods, + if (!_terrain_render.Init(speedtree_terrain_num_lods, speedtree_terrain_resolution, speedtree_terrain_cell_size, _terrain->get_st_vertex_format())) { @@ -1780,9 +1778,9 @@ cull_forest() { SpeedTree::SForestCullResultsRender &light_cull = _shadow_infos[smi]._light_cull; _forest_render.ComputeLightView - (_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi, + (_forest_render.GetLightDir(), _view.GetFrustumPoints(), smi, light_view, 0.0f); - + light_view.SetLodRefPoint(_view.GetCameraPos()); _forest_render.CullAndComputeLOD(light_view, light_cull, false); } @@ -1793,7 +1791,7 @@ cull_forest() { //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::print_forest_stats // Access: Private -// Description: +// Description: //////////////////////////////////////////////////////////////////// void SpeedTreeNode:: print_forest_stats(const SpeedTree::CForest::SPopulationStats &forest_stats) const { @@ -1894,7 +1892,7 @@ fillin(DatagramIterator &scan, BamReader *manager) { //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::InstanceList::output // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void SpeedTreeNode::InstanceList:: output(ostream &out) const { @@ -1904,7 +1902,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::InstanceList::write // Access: Published -// Description: +// Description: //////////////////////////////////////////////////////////////////// void SpeedTreeNode::InstanceList:: write(ostream &out, int indent_level) const {