mirror of
https://github.com/panda3d/panda3d.git
synced 2026-04-22 14:41:36 -05:00
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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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) { }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 SpeedTree::CTree*, SpeedTree::st_int32>::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 {
|
||||
|
||||
Reference in New Issue
Block a user