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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Published

View File

@ -18,6 +18,7 @@
#include "cullBinManager.h"
#include "fogAttrib.h"
#include "clipPlaneAttrib.h"
#include "scissorAttrib.h"
#include "transparencyAttrib.h"
#include "colorAttrib.h"
#include "colorScaleAttrib.h"
@ -1972,6 +1973,27 @@ determine_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
// Access: Private

View File

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

View File

@ -26,6 +26,7 @@
#include "cullTraverserData.h"
#include "cullBinManager.h"
#include "clipPlaneAttrib.h"
#include "scissorAttrib.h"
#include "dcast.h"
#include "boundingSphere.h"
#include "boundingBox.h"
@ -252,7 +253,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
// which only provides one.
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());
}
}
@ -379,7 +381,8 @@ xform(const LMatrix4f &mat) {
////////////////////////////////////////////////////////////////////
bool PGItem::
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
// way the region works (mostly) even if has been rotated.
LPoint3f ll(_frame[0], 0.0f, _frame[2]);
@ -391,8 +394,10 @@ activate_region(const LMatrix4f &transform, int sort,
ul = ul * transform;
ur = ur * transform;
LVecBase4f frame;
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;
points.reserve(4);
@ -406,13 +411,13 @@ activate_region(const LMatrix4f &transform, int sort,
NodePath plane_path = cpa->get_on_plane(i);
Planef plane = DCAST(PlaneNode, plane_path.node())->get_plane();
plane.xform(plane_path.get_net_transform()->get_mat());
// We ignore the y coordinate, assuming the frame is still in
// the X-Z plane after being transformed. Not sure if we really
// need to support general 3-D transforms on 2-D objects.
clip_frame(points, plane);
}
if (points.empty()) {
// Turns out it's completely clipped after all.
return false;
@ -420,7 +425,7 @@ activate_region(const LMatrix4f &transform, int sort,
pvector<LPoint2f>::iterator pi;
pi = points.begin();
LVecBase4f frame((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]);
frame.set((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]);
++pi;
while (pi != points.end()) {
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]);
++pi;
}
_region->set_frame(frame);
} else {
// 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])),
max(max(ll[0], lr[0]), max(ul[0], ur[0])),
min(min(ll[2], lr[2]), min(ul[2], ur[2])),
max(max(ll[2], lr[2]), max(ul[2], ur[2])));
frame.set(min(min(ll[0], lr[0]), min(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])),
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_active(true);

View File

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