scissor MouseWatcherRegions too

This commit is contained in:
David Rose 2008-08-01 22:48:42 +00:00
parent ab6e8bbc3c
commit 4d59f04134
5 changed files with 97 additions and 30 deletions

View File

@ -366,6 +366,25 @@ get_clip_plane() const {
return _clip_plane; return _clip_plane;
} }
////////////////////////////////////////////////////////////////////
// Function: RenderState::get_scissor
// Access: Published
// Description: This function is provided as an optimization, to
// speed up the render-time checking for the existance
// of a ScissorAttrib on this state. It returns a
// pointer to the ScissorAttrib, if there is one, or
// NULL if there is not.
////////////////////////////////////////////////////////////////////
INLINE const ScissorAttrib *RenderState::
get_scissor() const {
if ((_flags & F_checked_scissor) == 0) {
// We pretend this function is const, even though it transparently
// modifies the internal scissor cache.
((RenderState *)this)->determine_scissor();
}
return _scissor;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: RenderState::get_shader // Function: RenderState::get_shader
// Access: Published // Access: Published

View File

@ -18,6 +18,7 @@
#include "cullBinManager.h" #include "cullBinManager.h"
#include "fogAttrib.h" #include "fogAttrib.h"
#include "clipPlaneAttrib.h" #include "clipPlaneAttrib.h"
#include "scissorAttrib.h"
#include "transparencyAttrib.h" #include "transparencyAttrib.h"
#include "colorAttrib.h" #include "colorAttrib.h"
#include "colorScaleAttrib.h" #include "colorScaleAttrib.h"
@ -1972,6 +1973,27 @@ determine_clip_plane() {
_flags |= F_checked_clip_plane; _flags |= F_checked_clip_plane;
} }
////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_scissor
// Access: Private
// Description: This is the private implementation of get_scissor().
////////////////////////////////////////////////////////////////////
void RenderState::
determine_scissor() {
MutexHolder holder(_lock);
if ((_flags & F_checked_scissor) != 0) {
// Someone else checked it first.
return;
}
const RenderAttrib *attrib = get_attrib(ScissorAttrib::get_class_type());
_scissor = (const ScissorAttrib *)NULL;
if (attrib != (const RenderAttrib *)NULL) {
_scissor = DCAST(ScissorAttrib, attrib);
}
_flags |= F_checked_scissor;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: RenderState::determine_shader // Function: RenderState::determine_shader
// Access: Private // Access: Private

View File

@ -42,6 +42,7 @@ class ColorScaleAttrib;
class TextureAttrib; class TextureAttrib;
class TexGenAttrib; class TexGenAttrib;
class ClipPlaneAttrib; class ClipPlaneAttrib;
class ScissorAttrib;
class ShaderAttrib; class ShaderAttrib;
class FactoryParams; class FactoryParams;
class AudioVolumeAttrib; class AudioVolumeAttrib;
@ -147,6 +148,7 @@ PUBLISHED:
INLINE const TexMatrixAttrib *get_tex_matrix() const; INLINE const TexMatrixAttrib *get_tex_matrix() const;
INLINE const RenderModeAttrib *get_render_mode() const; INLINE const RenderModeAttrib *get_render_mode() const;
INLINE const ClipPlaneAttrib *get_clip_plane() const; INLINE const ClipPlaneAttrib *get_clip_plane() const;
INLINE const ScissorAttrib *get_scissor() const;
INLINE const ShaderAttrib *get_shader() const; INLINE const ShaderAttrib *get_shader() const;
INLINE const AudioVolumeAttrib *get_audio_volume() const; INLINE const AudioVolumeAttrib *get_audio_volume() const;
@ -201,6 +203,7 @@ private:
void determine_tex_matrix(); void determine_tex_matrix();
void determine_render_mode(); void determine_render_mode();
void determine_clip_plane(); void determine_clip_plane();
void determine_scissor();
void determine_shader(); void determine_shader();
void determine_cull_callback(); void determine_cull_callback();
void determine_audio_volume(); void determine_audio_volume();
@ -315,28 +318,30 @@ private:
const TexMatrixAttrib *_tex_matrix; const TexMatrixAttrib *_tex_matrix;
const RenderModeAttrib *_render_mode; const RenderModeAttrib *_render_mode;
const ClipPlaneAttrib *_clip_plane; const ClipPlaneAttrib *_clip_plane;
const ScissorAttrib *_scissor;
const ShaderAttrib *_shader; const ShaderAttrib *_shader;
const AudioVolumeAttrib *_audio_volume; const AudioVolumeAttrib *_audio_volume;
enum Flags { enum Flags {
F_checked_bin_index = 0x0001, F_checked_bin_index = 0x000001,
F_checked_fog = 0x0002, F_checked_fog = 0x000002,
F_checked_bin = 0x0004, F_checked_bin = 0x000004,
F_checked_transparency = 0x0008, F_checked_transparency = 0x000008,
F_checked_color = 0x0010, F_checked_color = 0x000010,
F_checked_color_scale = 0x0020, F_checked_color_scale = 0x000020,
F_checked_texture = 0x0040, F_checked_texture = 0x000040,
F_checked_tex_gen = 0x0080, F_checked_tex_gen = 0x000080,
F_checked_tex_matrix = 0x0100, F_checked_tex_matrix = 0x000100,
F_checked_render_mode = 0x0200, F_checked_render_mode = 0x000200,
F_checked_clip_plane = 0x0400, F_checked_clip_plane = 0x000400,
F_checked_shader = 0x0800, F_checked_shader = 0x000800,
F_checked_cull_callback = 0x1000, F_checked_cull_callback = 0x001000,
F_checked_audio_volume = 0x2000, F_checked_audio_volume = 0x002000,
F_has_cull_callback = 0x4000, F_has_cull_callback = 0x004000,
F_is_destructing = 0x8000, F_is_destructing = 0x008000,
F_checked_scissor = 0x010000,
}; };
unsigned short _flags; unsigned int _flags;
// This mutex protects _flags, and all of the above computed values. // This mutex protects _flags, and all of the above computed values.
Mutex _lock; Mutex _lock;

View File

@ -26,6 +26,7 @@
#include "cullTraverserData.h" #include "cullTraverserData.h"
#include "cullBinManager.h" #include "cullBinManager.h"
#include "clipPlaneAttrib.h" #include "clipPlaneAttrib.h"
#include "scissorAttrib.h"
#include "dcast.h" #include "dcast.h"
#include "boundingSphere.h" #include "boundingSphere.h"
#include "boundingBox.h" #include "boundingBox.h"
@ -252,7 +253,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
// which only provides one. // which only provides one.
sort = (bin_sort << 16) | ((sort + 0x8000) & 0xffff); sort = (bin_sort << 16) | ((sort + 0x8000) & 0xffff);
if (activate_region(transform, sort, data._state->get_clip_plane())) { if (activate_region(transform, sort, data._state->get_clip_plane(),
data._state->get_scissor())) {
pg_trav->_top->add_region(get_region()); pg_trav->_top->add_region(get_region());
} }
} }
@ -379,7 +381,8 @@ xform(const LMatrix4f &mat) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool PGItem:: bool PGItem::
activate_region(const LMatrix4f &transform, int sort, activate_region(const LMatrix4f &transform, int sort,
const ClipPlaneAttrib *cpa) { const ClipPlaneAttrib *cpa,
const ScissorAttrib *sa) {
// Transform all four vertices, and get the new bounding box. This // Transform all four vertices, and get the new bounding box. This
// way the region works (mostly) even if has been rotated. // way the region works (mostly) even if has been rotated.
LPoint3f ll(_frame[0], 0.0f, _frame[2]); LPoint3f ll(_frame[0], 0.0f, _frame[2]);
@ -391,8 +394,10 @@ activate_region(const LMatrix4f &transform, int sort,
ul = ul * transform; ul = ul * transform;
ur = ur * transform; ur = ur * transform;
LVecBase4f frame;
if (cpa != (ClipPlaneAttrib *)NULL && cpa->get_num_on_planes() != 0) { if (cpa != (ClipPlaneAttrib *)NULL && cpa->get_num_on_planes() != 0) {
// Apply the clip plane(s) now that we are here in world space. // Apply the clip plane(s) and/or scissor region now that we are
// here in world space.
pvector<LPoint2f> points; pvector<LPoint2f> points;
points.reserve(4); points.reserve(4);
@ -406,13 +411,13 @@ activate_region(const LMatrix4f &transform, int sort,
NodePath plane_path = cpa->get_on_plane(i); NodePath plane_path = cpa->get_on_plane(i);
Planef plane = DCAST(PlaneNode, plane_path.node())->get_plane(); Planef plane = DCAST(PlaneNode, plane_path.node())->get_plane();
plane.xform(plane_path.get_net_transform()->get_mat()); plane.xform(plane_path.get_net_transform()->get_mat());
// We ignore the y coordinate, assuming the frame is still in // We ignore the y coordinate, assuming the frame is still in
// the X-Z plane after being transformed. Not sure if we really // the X-Z plane after being transformed. Not sure if we really
// need to support general 3-D transforms on 2-D objects. // need to support general 3-D transforms on 2-D objects.
clip_frame(points, plane); clip_frame(points, plane);
} }
if (points.empty()) { if (points.empty()) {
// Turns out it's completely clipped after all. // Turns out it's completely clipped after all.
return false; return false;
@ -420,7 +425,7 @@ activate_region(const LMatrix4f &transform, int sort,
pvector<LPoint2f>::iterator pi; pvector<LPoint2f>::iterator pi;
pi = points.begin(); pi = points.begin();
LVecBase4f frame((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]); frame.set((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]);
++pi; ++pi;
while (pi != points.end()) { while (pi != points.end()) {
frame[0] = min(frame[0], (*pi)[0]); frame[0] = min(frame[0], (*pi)[0]);
@ -429,15 +434,29 @@ activate_region(const LMatrix4f &transform, int sort,
frame[3] = max(frame[3], (*pi)[1]); frame[3] = max(frame[3], (*pi)[1]);
++pi; ++pi;
} }
_region->set_frame(frame);
} else { } else {
// Since there are no clip planes involved, just set the frame. // Since there are no clip planes involved, just set the frame.
_region->set_frame(min(min(ll[0], lr[0]), min(ul[0], ur[0])), frame.set(min(min(ll[0], lr[0]), min(ul[0], ur[0])),
max(max(ll[0], lr[0]), max(ul[0], ur[0])), max(max(ll[0], lr[0]), max(ul[0], ur[0])),
min(min(ll[2], lr[2]), min(ul[2], ur[2])), min(min(ll[2], lr[2]), min(ul[2], ur[2])),
max(max(ll[2], lr[2]), max(ul[2], ur[2]))); max(max(ll[2], lr[2]), max(ul[2], ur[2])));
} }
if (sa != (ScissorAttrib *)NULL) {
// Also restrict it to within the scissor region.
const LVecBase4f &sf = sa->get_frame();
// Expand sf from 0..1 to -1..1.
frame.set(max(frame[0], sf[0] * 2.0f - 1.0f),
min(frame[1], sf[1] * 2.0f - 1.0f),
max(frame[2], sf[2] * 2.0f - 1.0f),
min(frame[3], sf[3] * 2.0f - 1.0f));
if (frame[1] <= frame[0] || frame[3] <= frame[2]) {
// Completely outside the scissor region.
return false;
}
}
_region->set_frame(frame);
_region->set_sort(sort); _region->set_sort(sort);
_region->set_active(true); _region->set_active(true);

View File

@ -34,6 +34,7 @@ class PGTop;
class MouseWatcherParameter; class MouseWatcherParameter;
class AudioSound; class AudioSound;
class ClipPlaneAttrib; class ClipPlaneAttrib;
class ScissorAttrib;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : PGItem // Class : PGItem
@ -70,7 +71,8 @@ protected:
public: public:
virtual void xform(const LMatrix4f &mat); virtual void xform(const LMatrix4f &mat);
bool activate_region(const LMatrix4f &transform, int sort, bool activate_region(const LMatrix4f &transform, int sort,
const ClipPlaneAttrib *cpa); const ClipPlaneAttrib *cpa,
const ScissorAttrib *sa);
INLINE PGMouseWatcherRegion *get_region() const; INLINE PGMouseWatcherRegion *get_region() const;
virtual void enter_region(const MouseWatcherParameter &param); virtual void enter_region(const MouseWatcherParameter &param);