From e001e35a605f45af4be6336fcc518785ee2e30ac Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 25 May 2005 12:27:42 +0000 Subject: [PATCH] support point sprites in more cases, for instance under render2d and under a scale --- panda/src/display/graphicsStateGuardian.cxx | 74 ++++++++++--------- .../glstuff/glGraphicsStateGuardian_src.cxx | 15 +++- panda/src/gobj/lens.cxx | 26 ++++++- panda/src/gobj/lens.h | 2 + panda/src/gobj/orthographicLens.cxx | 14 +++- panda/src/gobj/orthographicLens.h | 1 + panda/src/gobj/perspectiveLens.cxx | 12 +++ panda/src/gobj/perspectiveLens.h | 1 + panda/src/gobj/qpgeomEnums.h | 25 ++++--- panda/src/pgraph/cullableObject.cxx | 19 +++-- panda/src/pgraph/texGenAttrib.I | 2 +- panda/src/pgraph/texMatrixAttrib.I | 2 +- panda/src/pgraph/transformState.I | 46 ++++++++++-- panda/src/pgraph/transformState.h | 7 +- 14 files changed, 179 insertions(+), 67 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index f4027a1dcd..5950c611e1 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -555,42 +555,6 @@ begin_frame() { //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: begin_scene() { - - // Undo any lighting we had enabled last scene, to force the lights - // to be reissued, in case their parameters or positions have - // changed between scenes. - if (_lighting_enabled_this_frame) { - for (int i = 0; i < (int)_light_info.size(); i++) { - if (_light_info[i]._enabled) { - enable_light(i, false); - _light_info[i]._enabled = false; - } - _light_info[i]._light = NodePath(); - } - - // Also force the lighting state to unlit, so that issue_light() - // will be guaranteed to be called next frame even if we have the - // same set of light pointers we had this frame. - modify_state(get_unlit_state()); - - _lighting_enabled_this_frame = false; - } - - // Ditto for the clipping planes. - if (_clip_planes_enabled_this_frame) { - for (int i = 0; i < (int)_clip_plane_info.size(); i++) { - if (_clip_plane_info[i]._enabled) { - enable_clip_plane(i, false); - _clip_plane_info[i]._enabled = false; - } - _clip_plane_info[i]._plane = (PlaneNode *)NULL; - } - - modify_state(get_unclipped_state()); - - _clip_planes_enabled_this_frame = false; - } - return true; } @@ -608,6 +572,44 @@ end_scene() { // We should clear this pointer now, so that we don't keep unneeded // reference counts dangling. _scene_setup = NULL; + + // Undo any lighting we had enabled last scene, to force the lights + // to be reissued, in case their parameters or positions have + // changed between scenes. + if (_lighting_enabled_this_frame) { + for (int i = 0; i < (int)_light_info.size(); i++) { + if (_light_info[i]._enabled) { + enable_light(i, false); + _light_info[i]._enabled = false; + } + _light_info[i]._light = NodePath(); + } + + // Also force the lighting state to unlit, so that issue_light() + // will be guaranteed to be called next frame even if we have the + // same set of light pointers we had this frame. + // modify_state(get_unlit_state()); + + _lighting_enabled_this_frame = false; + } + + // Ditto for the clipping planes. + if (_clip_planes_enabled_this_frame) { + for (int i = 0; i < (int)_clip_plane_info.size(); i++) { + if (_clip_plane_info[i]._enabled) { + enable_clip_plane(i, false); + _clip_plane_info[i]._enabled = false; + } + _clip_plane_info[i]._plane = (PlaneNode *)NULL; + } + + // modify_state(get_unclipped_state()); + + _clip_planes_enabled_this_frame = false; + } + + // Actually, just clear all the state between scenes. + set_state(RenderState::make_empty()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 80506cd193..f4be0d38e7 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -6401,8 +6401,19 @@ do_point_size() { LVector3f height(0.0f, _point_size, 1.0f); height = height * _projection_mat; float s = height[1] * _viewport_height / _point_size; - LVecBase3f square(0.0f, 0.0f, 1.0f / (s * s)); - _glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, square.get_data()); + + if (_current_lens->is_orthographic()) { + // If we have an orthographic lens in effect, we don't actually + // apply a perspective transform: we just scale the points once, + // regardless of the distance from the camera. + LVecBase3f constant(1.0f / (s * s), 0.0f, 0.0f); + _glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, constant.get_data()); + + } else { + // Otherwise, we give it a true perspective adjustment. + LVecBase3f square(0.0f, 0.0f, 1.0f / (s * s)); + _glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, square.get_data()); + } } report_my_gl_errors(); diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index d26a8b5648..ac26c12ae7 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -862,6 +862,30 @@ is_linear() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: Lens::is_perspective +// Access: Published, Virtual +// Description: Returns true if the lens represents a perspective +// projection (i.e. it is a PerspectiveLens), false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool Lens:: +is_perspective() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::is_orthographic +// Access: Published, Virtual +// Description: Returns true if the lens represents a orthographic +// projection (i.e. it is a OrthographicLens), false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool Lens:: +is_orthographic() const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: Lens::make_geometry // Access: Published, Virtual @@ -1274,7 +1298,7 @@ extrude_impl(const LPoint3f &point2d, LPoint3f &near_point, LPoint3f &far_point) // set_view_vector(). // // For all linear lenses, including perspective and -// ortographic lenses, all points on the film compute +// orthographic lenses, all points on the film compute // this same vector (the far plane is a flat plane, so // the normal is the same everywhere). For curved // lenses like fisheye and cylindrical lenses, different diff --git a/panda/src/gobj/lens.h b/panda/src/gobj/lens.h index a44a50d9ee..742379de90 100644 --- a/panda/src/gobj/lens.h +++ b/panda/src/gobj/lens.h @@ -136,6 +136,8 @@ PUBLISHED: void recompute_all(); virtual bool is_linear() const; + virtual bool is_perspective() const; + virtual bool is_orthographic() const; virtual PT(Geom) make_geometry(); virtual PT(BoundingVolume) make_bounds() const; diff --git a/panda/src/gobj/orthographicLens.cxx b/panda/src/gobj/orthographicLens.cxx index 000595781d..695354cbf3 100644 --- a/panda/src/gobj/orthographicLens.cxx +++ b/panda/src/gobj/orthographicLens.cxx @@ -45,6 +45,18 @@ is_linear() const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: OrthographicLens::is_orthographic +// Access: Published, Virtual +// Description: Returns true if the lens represents a orthographic +// projection (i.e. it is a OrthographicLens), false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool OrthographicLens:: +is_orthographic() const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: OrthographicLens::write // Access: Public, Virtual @@ -103,7 +115,7 @@ compute_projection_mat() { default: gobj_cat.error() - << "Invalid coordinate system " << (int)cs << " in PerspectiveLens!\n"; + << "Invalid coordinate system " << (int)cs << " in OrthographicLens!\n"; canonical = LMatrix4f::ident_mat(); } diff --git a/panda/src/gobj/orthographicLens.h b/panda/src/gobj/orthographicLens.h index db5814b83c..52bbc90b2f 100644 --- a/panda/src/gobj/orthographicLens.h +++ b/panda/src/gobj/orthographicLens.h @@ -46,6 +46,7 @@ public: public: virtual PT(Lens) make_copy() const; virtual bool is_linear() const; + virtual bool is_orthographic() const; virtual void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/gobj/perspectiveLens.cxx b/panda/src/gobj/perspectiveLens.cxx index c635336787..aeb2b852ff 100644 --- a/panda/src/gobj/perspectiveLens.cxx +++ b/panda/src/gobj/perspectiveLens.cxx @@ -44,6 +44,18 @@ is_linear() const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::is_perspective +// Access: Published, Virtual +// Description: Returns true if the lens represents a perspective +// projection (i.e. it is a PerspectiveLens), false +// otherwise. +//////////////////////////////////////////////////////////////////// +bool PerspectiveLens:: +is_perspective() const { + return true; +} + //////////////////////////////////////////////////////////////////// // Function: PerspectiveLens::compute_projection_mat // Access: Protected, Virtual diff --git a/panda/src/gobj/perspectiveLens.h b/panda/src/gobj/perspectiveLens.h index c23e3d2b2d..efe8bccb37 100644 --- a/panda/src/gobj/perspectiveLens.h +++ b/panda/src/gobj/perspectiveLens.h @@ -39,6 +39,7 @@ public: public: virtual PT(Lens) make_copy() const; virtual bool is_linear() const; + virtual bool is_perspective() const; protected: virtual void compute_projection_mat(); diff --git a/panda/src/gobj/qpgeomEnums.h b/panda/src/gobj/qpgeomEnums.h index 45008d228c..1f37382526 100644 --- a/panda/src/gobj/qpgeomEnums.h +++ b/panda/src/gobj/qpgeomEnums.h @@ -103,34 +103,37 @@ PUBLISHED: // If the points have a non-square aspect ratio. GR_point_aspect_ratio = 0x0020, + // If the points are under a scale transform, uniform or non-uniform. + GR_point_scale = 0x0040, + // If the points are rotated off the orthonormal axis. - GR_point_rotate = 0x0040, + GR_point_rotate = 0x0080, // If the points require texture coordinates interpolated across // their face, to render textures as sprites. - GR_point_sprite = 0x0080, + GR_point_sprite = 0x0100, // If there is a texture matrix applied to the sprite's generated // texture coordinates. - GR_point_sprite_tex_matrix = 0x0100, + GR_point_sprite_tex_matrix = 0x0200, // The union of all the above point attributes, except GR_indexed_point. - GR_point_bits = 0x01f3, + GR_point_bits = 0x03f3, // If there are any of these composite types. - GR_triangle_strip = 0x0200, - GR_triangle_fan = 0x0400, - GR_line_strip = 0x0800, + GR_triangle_strip = 0x0400, + GR_triangle_fan = 0x0800, + GR_line_strip = 0x1000, // The union of all of the above composite types. - GR_composite_bits = 0x0e00, + GR_composite_bits = 0x1c00, // If the shade model requires a particular vertex for flat shading. - GR_flat_first_vertex = 0x1000, - GR_flat_last_vertex = 0x2000, + GR_flat_first_vertex = 0x2000, + GR_flat_last_vertex = 0x4000, // The union of the above shade model types. - GR_shade_model_bits = 0x3000, + GR_shade_model_bits = 0x6000, }; // The shade model specifies whether the per-vertex colors and diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index 16983f4189..00947e59ac 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -52,7 +52,9 @@ munge_geom(GraphicsStateGuardianBase *gsg, CPT(qpGeom) qpgeom = DCAST(qpGeom, _geom); _munged_data = qpgeom->get_vertex_data(); - int geom_rendering = _state->get_geom_rendering(qpgeom->get_geom_rendering()); + int geom_rendering = qpgeom->get_geom_rendering(); + geom_rendering = _state->get_geom_rendering(geom_rendering); + geom_rendering = _transform->get_geom_rendering(geom_rendering); GraphicsStateGuardianBase *gsg = traverser->get_gsg(); int gsg_bits = gsg->get_supported_geom_rendering(); @@ -331,17 +333,20 @@ munge_points_to_quads(const CullTraverser *traverser) { float scale_y = point_size; if (perspective) { - // Perspective-sized points. Here point_size is a width in 3-d - // units. To arrange that, we need to figure out the appropriate - // scaling factor based on the current viewport and projection - // matrix. - LVector3f height(0.0f, point_size, 1.0f); + // Perspective-sized points. Here point_size is the point's + // 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. + float scale = _transform->get_scale()[1]; + LVector3f height(0.0f, point_size * scale, scale); height = height * projection; scale_y = height[1] * viewport_height; // We should then divide the radius by the distance from the // camera plane, to emulate the glPointParameters() behavior. - scale_y /= gsg->compute_distance_to(eye); + if (!lens->is_orthographic()) { + scale_y /= gsg->compute_distance_to(eye); + } } // Also factor in the homogeneous scale for being in clip diff --git a/panda/src/pgraph/texGenAttrib.I b/panda/src/pgraph/texGenAttrib.I index 0e526c6bfa..5687f650aa 100755 --- a/panda/src/pgraph/texGenAttrib.I +++ b/panda/src/pgraph/texGenAttrib.I @@ -55,7 +55,7 @@ INLINE int TexGenAttrib:: get_geom_rendering(int geom_rendering) const { if ((geom_rendering & qpGeom::GR_point) != 0) { if (_num_point_sprites > 0) { - return geom_rendering |= qpGeom::GR_point_sprite; + geom_rendering |= qpGeom::GR_point_sprite; } } diff --git a/panda/src/pgraph/texMatrixAttrib.I b/panda/src/pgraph/texMatrixAttrib.I index a7af061e1e..6814942850 100644 --- a/panda/src/pgraph/texMatrixAttrib.I +++ b/panda/src/pgraph/texMatrixAttrib.I @@ -52,7 +52,7 @@ INLINE int TexMatrixAttrib:: get_geom_rendering(int geom_rendering) const { if ((geom_rendering & qpGeom::GR_point_sprite) != 0) { if (!is_empty()) { - return geom_rendering |= qpGeom::GR_point_sprite_tex_matrix; + geom_rendering |= qpGeom::GR_point_sprite_tex_matrix; } } diff --git a/panda/src/pgraph/transformState.I b/panda/src/pgraph/transformState.I index 60a653c9a0..5aeb52ab4a 100644 --- a/panda/src/pgraph/transformState.I +++ b/panda/src/pgraph/transformState.I @@ -288,6 +288,18 @@ has_scale() const { return has_components(); } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::has_identity_scale +// Access: Published +// Description: Returns true if the scale is uniform 1.0, or false if +// the scale has some real value. +//////////////////////////////////////////////////////////////////// +INLINE bool TransformState:: +has_identity_scale() const { + check_components(); + return (_flags & F_identity_scale) != 0; +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::has_uniform_scale // Access: Published @@ -363,7 +375,6 @@ INLINE const LVecBase3f &TransformState:: get_hpr() const { check_hpr(); nassertr(!is_invalid(), _hpr); - // nassertr(has_hpr(), _hpr); return _hpr; } @@ -378,7 +389,6 @@ INLINE const LQuaternionf &TransformState:: get_quat() const { check_quat(); nassertr(!is_invalid(), _quat); - // nassertr(has_quat(), _quat); return _quat; } @@ -393,7 +403,6 @@ INLINE const LVecBase3f &TransformState:: get_scale() const { check_components(); nassertr(!is_invalid(), _scale); - // nassertr(has_scale(), _scale); return _scale; } @@ -437,6 +446,27 @@ get_mat() const { return _mat; } +//////////////////////////////////////////////////////////////////// +// Function: TransformState::get_geom_rendering +// Access: Published +// Description: Returns the union of the Geom::GeomRendering bits +// that will be required once this TransformState is +// applied to a geom which includes the indicated +// geom_rendering bits. The RenderState's +// get_geom_rendering() should already have been +// applied. +//////////////////////////////////////////////////////////////////// +INLINE int TransformState:: +get_geom_rendering(int geom_rendering) const { + if ((geom_rendering & qpGeomEnums::GR_point_perspective) != 0) { + if (!has_identity_scale()) { + geom_rendering |= qpGeomEnums::GR_point_scale; + } + } + + return geom_rendering; +} + //////////////////////////////////////////////////////////////////// // Function: TransformState::cache_ref // Access: Published @@ -582,16 +612,20 @@ check_mat() const { // Function: TransformState::check_uniform_scale // Access: Private // Description: Should be called immediately after _scale (and -// F_has_components) is set, this checks for a uniform -// scale (as well as a non-zero shear) and sets the bit -// appropriately. +// F_has_components) is set, this checks for a +// identity and/or uniform scale (as well as a non-zero +// shear) and sets the bit appropriately. //////////////////////////////////////////////////////////////////// INLINE void TransformState:: check_uniform_scale() { if (IS_NEARLY_EQUAL(_scale[0], _scale[1]) && IS_NEARLY_EQUAL(_scale[0], _scale[2])) { _flags |= F_uniform_scale; + if (IS_NEARLY_EQUAL(_scale[0], 1.0f)) { + _flags |= F_identity_scale; + } } + if (!_shear.almost_equal(LVecBase3f::zero())) { _flags |= F_has_nonzero_shear; } diff --git a/panda/src/pgraph/transformState.h b/panda/src/pgraph/transformState.h index c61e4146a6..b45ab8f40c 100644 --- a/panda/src/pgraph/transformState.h +++ b/panda/src/pgraph/transformState.h @@ -28,6 +28,7 @@ #include "event.h" #include "updateSeq.h" #include "pStatCollector.h" +#include "qpgeomEnums.h" class GraphicsStateGuardianBase; class FactoryParams; @@ -106,6 +107,7 @@ PUBLISHED: INLINE bool has_hpr() const; INLINE bool has_quat() const; INLINE bool has_scale() const; + INLINE bool has_identity_scale() const; INLINE bool has_uniform_scale() const; INLINE bool has_shear() const; INLINE bool has_nonzero_shear() const; @@ -127,6 +129,8 @@ PUBLISHED: CPT(TransformState) compose(const TransformState *other) const; CPT(TransformState) invert_compose(const TransformState *other) const; + INLINE int get_geom_rendering(int geom_rendering) const; + int unref() const; INLINE int cache_ref() const; @@ -246,7 +250,8 @@ private: F_hpr_given = 0x0400, F_hpr_known = 0x0800, // set if _hpr is defined F_uniform_scale = 0x1000, - F_has_nonzero_shear = 0x2000, + F_identity_scale = 0x2000, + F_has_nonzero_shear = 0x4000, F_is_destructing = 0x8000, }; LVecBase3f _pos, _hpr, _scale, _shear;