higher-level ScissorEffect fixes
This commit is contained in:
parent
89adb4d176
commit
ab6e8bbc3c
|
|
@ -43,6 +43,7 @@
|
|||
#include "antialiasAttrib.h"
|
||||
#include "audioVolumeAttrib.h"
|
||||
#include "texProjectorEffect.h"
|
||||
#include "scissorEffect.h"
|
||||
#include "texturePool.h"
|
||||
#include "planeNode.h"
|
||||
#include "lensNode.h"
|
||||
|
|
@ -2796,6 +2797,113 @@ has_clip_plane_off(const NodePath &clip_plane) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_scissor
|
||||
// Access: Published
|
||||
// Description: Sets up a scissor region on the nodes rendered at
|
||||
// this level and below. The four coordinates are
|
||||
// understood to define a rectangle in screen space.
|
||||
// These numbers are relative to the current
|
||||
// DisplayRegion, where (0,0) is the lower-left corner
|
||||
// of the DisplayRegion, and (1,1) is the upper-right
|
||||
// corner.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_scissor(float left, float right, float bottom, float top) {
|
||||
set_effect(ScissorEffect::make_screen(LVecBase4f(left, right, bottom, top)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_scissor
|
||||
// Access: Published
|
||||
// Description: Sets up a scissor region on the nodes rendered at
|
||||
// this level and below. The two points are understood
|
||||
// to be relative to this node. When these points are
|
||||
// projected into screen space, they define the
|
||||
// diagonally-opposite points that determine the scissor
|
||||
// region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_scissor(const LPoint3f &a, const LPoint3f &b) {
|
||||
set_effect(ScissorEffect::make_node(a, b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_scissor
|
||||
// Access: Published
|
||||
// Description: Sets up a scissor region on the nodes rendered at
|
||||
// this level and below. The four points are understood
|
||||
// to be relative to this node. When these points are
|
||||
// projected into screen space, they define the
|
||||
// bounding volume of the scissor region (the scissor
|
||||
// region is the smallest onscreen rectangle that
|
||||
// encloses all four points).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_scissor(const LPoint3f &a, const LPoint3f &b,
|
||||
const LPoint3f &c, const LPoint3f &d) {
|
||||
set_effect(ScissorEffect::make_node(a, b, c, d));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_scissor
|
||||
// Access: Published
|
||||
// Description: Sets up a scissor region on the nodes rendered at
|
||||
// this level and below. The two points are understood
|
||||
// to be relative to the indicated other node. When
|
||||
// these points are projected into screen space, they
|
||||
// define the diagonally-opposite points that determine
|
||||
// the scissor region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_scissor(const NodePath &other, const LPoint3f &a, const LPoint3f &b) {
|
||||
set_effect(ScissorEffect::make_node(a, b, other));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_scissor
|
||||
// Access: Published
|
||||
// Description: Sets up a scissor region on the nodes rendered at
|
||||
// this level and below. The four points are understood
|
||||
// to be relative to the indicated other node. When
|
||||
// these points are projected into screen space, they
|
||||
// define the bounding volume of the scissor region (the
|
||||
// scissor region is the smallest onscreen rectangle
|
||||
// that encloses all four points).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
set_scissor(const NodePath &other,
|
||||
const LPoint3f &a, const LPoint3f &b,
|
||||
const LPoint3f &c, const LPoint3f &d) {
|
||||
set_effect(ScissorEffect::make_node(a, b, c, d, other));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::clear_scissor
|
||||
// Access: Published
|
||||
// Description: Removes the scissor region that was defined at this
|
||||
// node level by a previous call to set_scissor().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NodePath::
|
||||
clear_scissor() {
|
||||
clear_effect(ScissorEffect::get_class_type());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::has_scissor
|
||||
// Access: Published
|
||||
// Description: Returns true if a scissor region was defined at this
|
||||
// node by a previous call to set_scissor(). This does
|
||||
// not check for scissor regions inherited from a parent
|
||||
// class. It also does not check for the presence of a
|
||||
// low-level ScissorAttrib, which is different from the
|
||||
// ScissorEffect added by set_scissor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NodePath::
|
||||
has_scissor() const {
|
||||
return has_effect(ScissorEffect::get_class_type());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NodePath::set_bin
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -547,6 +547,18 @@ PUBLISHED:
|
|||
bool has_clip_plane_off() const;
|
||||
bool has_clip_plane_off(const NodePath &clip_plane) const;
|
||||
|
||||
void set_scissor(float left, float right, float bottom, float top);
|
||||
void set_scissor(const LPoint3f &a, const LPoint3f &b);
|
||||
void set_scissor(const LPoint3f &a, const LPoint3f &b,
|
||||
const LPoint3f &c, const LPoint3f &d);
|
||||
void set_scissor(const NodePath &other,
|
||||
const LPoint3f &a, const LPoint3f &b);
|
||||
void set_scissor(const NodePath &other,
|
||||
const LPoint3f &a, const LPoint3f &b,
|
||||
const LPoint3f &c, const LPoint3f &d);
|
||||
void clear_scissor();
|
||||
bool has_scissor() const;
|
||||
|
||||
void set_bin(const string &bin_name, int draw_order, int priority = 0);
|
||||
void clear_bin();
|
||||
bool has_bin() const;
|
||||
|
|
|
|||
|
|
@ -344,7 +344,16 @@ void PandaNode::
|
|||
apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
|
||||
GeomTransformer &transformer) {
|
||||
if ((attrib_types & SceneGraphReducer::TT_transform) != 0) {
|
||||
xform(attribs._transform->get_mat());
|
||||
const LMatrix4f &mat = attribs._transform->get_mat();
|
||||
xform(mat);
|
||||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||
cdata->_effects = cdata->_effects->xform(mat);
|
||||
cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty());
|
||||
}
|
||||
CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,37 @@ compare_to_impl(const RenderAttrib *other) const {
|
|||
return _frame.compare_to(ta->_frame);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorAttrib::compose_impl
|
||||
// Access: Protected, Virtual
|
||||
// Description: Intended to be overridden by derived RenderAttrib
|
||||
// types to specify how two consecutive RenderAttrib
|
||||
// objects of the same type interact.
|
||||
//
|
||||
// This should return the result of applying the other
|
||||
// RenderAttrib to a node in the scene graph below this
|
||||
// RenderAttrib, which was already applied. In most
|
||||
// cases, the result is the same as the other
|
||||
// RenderAttrib (that is, a subsequent RenderAttrib
|
||||
// completely replaces the preceding one). On the other
|
||||
// hand, some kinds of RenderAttrib (for instance,
|
||||
// ColorTransformAttrib) might combine in meaningful
|
||||
// ways.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderAttrib) ScissorAttrib::
|
||||
compose_impl(const RenderAttrib *other) const {
|
||||
const ScissorAttrib *ta;
|
||||
DCAST_INTO_R(ta, other, 0);
|
||||
|
||||
LVecBase4f new_frame(max(ta->_frame[0], _frame[0]),
|
||||
min(ta->_frame[1], _frame[1]),
|
||||
max(ta->_frame[2], _frame[2]),
|
||||
min(ta->_frame[3], _frame[3]));
|
||||
|
||||
ScissorAttrib *attrib = new ScissorAttrib(new_frame);
|
||||
return return_new(attrib);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorAttrib::make_default_impl
|
||||
// Access: Protected, Virtual
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual int compare_to_impl(const RenderAttrib *other) const;
|
||||
virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const;
|
||||
virtual RenderAttrib *make_default_impl() const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -63,7 +63,19 @@ get_num_points() const {
|
|||
INLINE const LPoint3f &ScissorEffect::
|
||||
get_point(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_points.size(), LPoint3f::zero());
|
||||
return _points[n];
|
||||
return _points[n]._p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::get_node
|
||||
// Access: Published
|
||||
// Description: Returns the node to which the nth point is relative,
|
||||
// or empty NodePath to indicate the current node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE NodePath ScissorEffect::
|
||||
get_node(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_points.size(), NodePath());
|
||||
return _points[n]._node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ TypeHandle ScissorEffect::_type_handle;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
ScissorEffect::
|
||||
ScissorEffect(bool screen, const LVecBase4f &frame,
|
||||
const LPoint3f *points, int num_points, bool clip) :
|
||||
const PointDef *points, int num_points, bool clip) :
|
||||
_screen(screen), _frame(frame), _clip(clip)
|
||||
{
|
||||
_points.reserve(num_points);
|
||||
|
|
@ -42,6 +42,21 @@ ScissorEffect(bool screen, const LVecBase4f &frame,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::Copy Constructor
|
||||
// Access: Private
|
||||
// Description: Use ScissorEffect::make() to construct a new
|
||||
// ScissorEffect object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ScissorEffect::
|
||||
ScissorEffect(const ScissorEffect ©) :
|
||||
_screen(copy._screen),
|
||||
_frame(copy._frame),
|
||||
_points(copy._points),
|
||||
_clip(copy._clip)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::make_screen
|
||||
// Access: Published, Static
|
||||
|
|
@ -55,20 +70,37 @@ make_screen(const LVecBase4f &frame, bool clip) {
|
|||
return return_new(effect);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::make_node
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new node-relative ScissorEffect, with no
|
||||
// points. This empty ScissorEffect does nothing. You
|
||||
// must then call add_point a number of times to add the
|
||||
// points you require.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderEffect) ScissorEffect::
|
||||
make_node(bool clip) {
|
||||
ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), NULL, 0, clip);
|
||||
return return_new(effect);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::make_node
|
||||
// Access: Published, Static
|
||||
// Description: Constructs a new node-relative ScissorEffect. The
|
||||
// two points are understood to be relative to the
|
||||
// current node, and determine the diagonally opposite
|
||||
// indicated node, or the current node if the NodePath
|
||||
// is empty, and determine the diagonally opposite
|
||||
// corners of the scissor region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderEffect) ScissorEffect::
|
||||
make_node(const LPoint3f &a, const LPoint3f &b, bool clip) {
|
||||
LPoint3f points[2];
|
||||
points[0] = a;
|
||||
points[1] = b;
|
||||
ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 2, clip);
|
||||
make_node(const LPoint3f &a, const LPoint3f &b, const NodePath &node) {
|
||||
PointDef points[2];
|
||||
points[0]._p = a;
|
||||
points[0]._node = node;
|
||||
points[1]._p = b;
|
||||
points[1]._node = node;
|
||||
ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 2, true);
|
||||
return return_new(effect);
|
||||
}
|
||||
|
||||
|
|
@ -77,30 +109,70 @@ make_node(const LPoint3f &a, const LPoint3f &b, bool clip) {
|
|||
// Access: Published, Static
|
||||
// Description: Constructs a new node-relative ScissorEffect. The
|
||||
// four points are understood to be relative to the
|
||||
// current node, and determine four points surrounding
|
||||
// the scissor region.
|
||||
// indicated node, or the current node if the indicated
|
||||
// NodePath is empty, and determine four points
|
||||
// surrounding the scissor region.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderEffect) ScissorEffect::
|
||||
make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, bool clip) {
|
||||
LPoint3f points[4];
|
||||
points[0] = a;
|
||||
points[1] = b;
|
||||
points[2] = c;
|
||||
points[3] = d;
|
||||
ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 4, clip);
|
||||
make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, const NodePath &node) {
|
||||
PointDef points[4];
|
||||
points[0]._p = a;
|
||||
points[0]._node = node;
|
||||
points[1]._p = b;
|
||||
points[1]._node = node;
|
||||
points[2]._p = c;
|
||||
points[2]._node = node;
|
||||
points[3]._p = d;
|
||||
points[3]._node = node;
|
||||
ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 4, true);
|
||||
return return_new(effect);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::safe_to_transform
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns true if it is generally safe to transform
|
||||
// this particular kind of RenderEffect by calling the
|
||||
// xform() method, false otherwise.
|
||||
// Function: ScissorEffect::add_point
|
||||
// Access: Published
|
||||
// Description: Returns a new ScissorEffect with the indicated point
|
||||
// added. It is only valid to call this on a "node"
|
||||
// type ScissorEffect. The full set of points,
|
||||
// projected into screen space, defines the bounding
|
||||
// volume of the rectangular scissor region.
|
||||
//
|
||||
// Each point may be relative to a different node, if
|
||||
// desired.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ScissorEffect::
|
||||
safe_to_transform() const {
|
||||
return false;
|
||||
CPT(RenderEffect) ScissorEffect::
|
||||
add_point(const LPoint3f &p, const NodePath &node) const {
|
||||
nassertr(!is_screen(), this);
|
||||
ScissorEffect *effect = new ScissorEffect(*this);
|
||||
PointDef point;
|
||||
point._p = p;
|
||||
point._node = node;
|
||||
effect->_points.push_back(point);
|
||||
return return_new(effect);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ScissorEffect::xform
|
||||
// Access: Public, Virtual
|
||||
// Description: Returns a new RenderEffect transformed by the
|
||||
// indicated matrix.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CPT(RenderEffect) ScissorEffect::
|
||||
xform(const LMatrix4f &mat) const {
|
||||
if (is_screen()) {
|
||||
return this;
|
||||
}
|
||||
ScissorEffect *effect = new ScissorEffect(*this);
|
||||
Points::iterator pi;
|
||||
for (pi = effect->_points.begin();
|
||||
pi != effect->_points.end();
|
||||
++pi) {
|
||||
PointDef &point = (*pi);
|
||||
if (point._node.is_empty()) {
|
||||
point._p = point._p * mat;
|
||||
}
|
||||
}
|
||||
return return_new(effect);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -117,7 +189,12 @@ output(ostream &out) const {
|
|||
out << "node";
|
||||
Points::const_iterator pi;
|
||||
for (pi = _points.begin(); pi != _points.end(); ++pi) {
|
||||
out << " [" << (*pi) << "]";
|
||||
const PointDef &point = (*pi);
|
||||
if (point._node.is_empty()) {
|
||||
out << " (" << point._p << ")";
|
||||
} else {
|
||||
out << " (" << point._node << ":" << point._p << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!get_clip()) {
|
||||
|
|
@ -162,8 +239,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data,
|
|||
CPT(RenderState) &node_state) const {
|
||||
LVecBase4f frame;
|
||||
const Lens *lens = trav->get_scene()->get_lens();
|
||||
CPT(TransformState) modelview_transform = data.get_modelview_transform(trav)->compose(node_transform);
|
||||
if (modelview_transform->is_singular()) {
|
||||
CPT(TransformState) modelview_transform = data.get_modelview_transform(trav);
|
||||
CPT(TransformState) net_transform = modelview_transform->compose(node_transform);
|
||||
if (net_transform->is_singular()) {
|
||||
// If we're under a singular transform, never mind.
|
||||
return;
|
||||
}
|
||||
|
|
@ -172,15 +250,24 @@ cull_callback(CullTraverser *trav, CullTraverserData &data,
|
|||
frame = _frame;
|
||||
} else {
|
||||
const LMatrix4f &proj_mat = lens->get_projection_mat();
|
||||
LMatrix4f net_mat = modelview_transform->get_mat() * proj_mat;
|
||||
LMatrix4f net_mat = net_transform->get_mat() * proj_mat;
|
||||
|
||||
bool any_points = false;
|
||||
|
||||
Points::const_iterator pi;
|
||||
for (pi = _points.begin(); pi != _points.end(); ++pi) {
|
||||
const LPoint3f &p = (*pi);
|
||||
LVecBase4f pv(p[0], p[1], p[2], 1.0f);
|
||||
pv = pv * net_mat;
|
||||
const PointDef &point = (*pi);
|
||||
LVecBase4f pv(point._p[0], point._p[1], point._p[2], 1.0f);
|
||||
if (point._node.is_empty()) {
|
||||
// Relative to this node.
|
||||
pv = pv * net_mat;
|
||||
|
||||
} else {
|
||||
// Relative to some other node.
|
||||
LMatrix4f other_mat = point._node.get_net_transform()->get_mat() * proj_mat;
|
||||
pv = pv * other_mat;
|
||||
}
|
||||
|
||||
if (pv[3] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -264,7 +351,11 @@ compare_to_impl(const RenderEffect *other) const {
|
|||
return compare;
|
||||
}
|
||||
for (size_t i = 0; i < _points.size(); ++i) {
|
||||
compare = _points[i].compare_to(ta->_points[i]);
|
||||
compare = _points[i]._p.compare_to(ta->_points[i]._p);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
compare = _points[i]._node.compare_to(ta->_points[i]._node);
|
||||
if (compare != 0) {
|
||||
return compare;
|
||||
}
|
||||
|
|
@ -301,7 +392,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|||
dg.add_uint16(_points.size());
|
||||
Points::const_iterator pi;
|
||||
for (pi = _points.begin(); pi != _points.end(); ++pi) {
|
||||
(*pi).write_datagram(dg);
|
||||
(*pi)._p.write_datagram(dg);
|
||||
}
|
||||
}
|
||||
dg.add_bool(_clip);
|
||||
|
|
@ -345,9 +436,9 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
int num_points = scan.get_uint16();
|
||||
_points.reserve(num_points);
|
||||
for (int i = 0; i < num_points; ++i) {
|
||||
LPoint3f p;
|
||||
p.read_datagram(scan);
|
||||
_points.push_back(p);
|
||||
PointDef point;
|
||||
point._p.read_datagram(scan);
|
||||
_points.push_back(point);
|
||||
}
|
||||
}
|
||||
_clip = scan.get_bool();
|
||||
|
|
|
|||
|
|
@ -31,24 +31,34 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_PGRAPH ScissorEffect : public RenderEffect {
|
||||
private:
|
||||
class PointDef {
|
||||
public:
|
||||
LPoint3f _p;
|
||||
NodePath _node;
|
||||
};
|
||||
|
||||
ScissorEffect(bool screen, const LVecBase4f &frame,
|
||||
const LPoint3f *points, int num_points, bool clip);
|
||||
const PointDef *points, int num_points, bool clip);
|
||||
ScissorEffect(const ScissorEffect ©);
|
||||
|
||||
PUBLISHED:
|
||||
static CPT(RenderEffect) make_screen(const LVecBase4f &frame, bool clip = true);
|
||||
static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, bool clip = true);
|
||||
static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, bool clip = true);
|
||||
static CPT(RenderEffect) make_node(bool clip = true);
|
||||
static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, const NodePath &node = NodePath());
|
||||
static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, const NodePath &node = NodePath());
|
||||
CPT(RenderEffect) add_point(const LPoint3f &point, const NodePath &node = NodePath()) const;
|
||||
|
||||
INLINE bool is_screen() const;
|
||||
INLINE const LVecBase4f &get_frame() const;
|
||||
|
||||
INLINE int get_num_points() const;
|
||||
INLINE const LPoint3f &get_point(int n) const;
|
||||
INLINE NodePath get_node(int n) const;
|
||||
|
||||
INLINE bool get_clip() const;
|
||||
|
||||
public:
|
||||
virtual bool safe_to_transform() const;
|
||||
virtual CPT(RenderEffect) xform(const LMatrix4f &mat) const;
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
virtual bool has_cull_callback() const;
|
||||
|
|
@ -65,7 +75,7 @@ private:
|
|||
private:
|
||||
bool _screen;
|
||||
LVecBase4f _frame;
|
||||
typedef pvector<LPoint3f> Points;
|
||||
typedef pvector<PointDef> Points;
|
||||
Points _points;
|
||||
bool _clip;
|
||||
|
||||
|
|
|
|||
|
|
@ -88,13 +88,11 @@ get_canvas_node() const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGVirtualFrame::get_clip_plane_node
|
||||
// Function: PGVirtualFrame::get_canvas_parent
|
||||
// Access: Published
|
||||
// Description: Returns the special node that holds all of PlaneNodes
|
||||
// that are used for applying the clip planes to the
|
||||
// canvas_node.
|
||||
// Description: Returns the parent node of the canvas_node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PandaNode *PGVirtualFrame::
|
||||
get_clip_plane_node() const {
|
||||
return _clip_plane_node;
|
||||
get_canvas_parent() const {
|
||||
return _canvas_parent;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pgVirtualFrame.h"
|
||||
#include "clipPlaneAttrib.h"
|
||||
#include "planeNode.h"
|
||||
#include "scissorEffect.h"
|
||||
#include "sceneGraphReducer.h"
|
||||
|
||||
TypeHandle PGVirtualFrame::_type_handle;
|
||||
|
|
@ -99,7 +98,7 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
|
|||
// Reassign the canvas_node to point to the new copy, if it's there.
|
||||
const PGVirtualFrame *from_frame = DCAST(PGVirtualFrame, from);
|
||||
PandaNode *from_canvas_node = from_frame->get_canvas_node();
|
||||
PandaNode *from_clip_plane_node = from_frame->get_clip_plane_node();
|
||||
PandaNode *from_canvas_parent = from_frame->get_canvas_parent();
|
||||
|
||||
InstanceMap::const_iterator ci;
|
||||
ci = inst_map.find(from_canvas_node);
|
||||
|
|
@ -108,10 +107,10 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
|
|||
_canvas_node = DCAST(ModelNode, (*ci).second);
|
||||
}
|
||||
|
||||
ci = inst_map.find(from_clip_plane_node);
|
||||
ci = inst_map.find(from_canvas_parent);
|
||||
if (ci != inst_map.end()) {
|
||||
remove_child(_clip_plane_node);
|
||||
_clip_plane_node = (*ci).second;
|
||||
remove_child(_canvas_parent);
|
||||
_canvas_parent = DCAST(ModelNode, (*ci).second);
|
||||
}
|
||||
|
||||
// Reassign the clip planes according to the clip frame.
|
||||
|
|
@ -163,33 +162,14 @@ set_clip_frame(const LVecBase4f &frame) {
|
|||
if (!_has_clip_frame || _clip_frame != frame) {
|
||||
_has_clip_frame = true;
|
||||
_clip_frame = frame;
|
||||
|
||||
CPT(RenderEffect) scissor_effect = ScissorEffect::make_node
|
||||
(LPoint3f(_clip_frame[0], _clip_frame[2], _clip_frame[2]),
|
||||
LPoint3f(_clip_frame[1], _clip_frame[2], _clip_frame[2]),
|
||||
LPoint3f(_clip_frame[1], _clip_frame[3], _clip_frame[3]),
|
||||
LPoint3f(_clip_frame[0], _clip_frame[3], _clip_frame[3]));
|
||||
|
||||
const LVector3f r = LVector3f::right();
|
||||
const LVector3f u = LVector3f::up();
|
||||
|
||||
PT(PlaneNode) left_clip =
|
||||
new PlaneNode("left_clip", Planef(r, r * _clip_frame[0]));
|
||||
PT(PlaneNode) right_clip =
|
||||
new PlaneNode("right_clip", Planef(-r, r * _clip_frame[1]));
|
||||
|
||||
PT(PlaneNode) bottom_clip =
|
||||
new PlaneNode("bottom_clip", Planef(u, u * _clip_frame[2]));
|
||||
PT(PlaneNode) top_clip =
|
||||
new PlaneNode("top_clip", Planef(-u, u * _clip_frame[3]));
|
||||
|
||||
_clip_plane_node->remove_all_children();
|
||||
_clip_plane_node->add_child(left_clip);
|
||||
_clip_plane_node->add_child(right_clip);
|
||||
_clip_plane_node->add_child(bottom_clip);
|
||||
_clip_plane_node->add_child(top_clip);
|
||||
|
||||
CPT(ClipPlaneAttrib) plane_attrib = DCAST(ClipPlaneAttrib, ClipPlaneAttrib::make());
|
||||
plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(left_clip)));
|
||||
plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(right_clip)));
|
||||
plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(bottom_clip)));
|
||||
plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(top_clip)));
|
||||
|
||||
_canvas_node->set_attrib(plane_attrib);
|
||||
_canvas_parent->set_effect(scissor_effect);
|
||||
clip_frame_changed();
|
||||
}
|
||||
}
|
||||
|
|
@ -205,7 +185,7 @@ clear_clip_frame() {
|
|||
if (_has_clip_frame) {
|
||||
_has_clip_frame = false;
|
||||
|
||||
_canvas_node->clear_attrib(ClipPlaneAttrib::get_class_type());
|
||||
_canvas_parent->clear_effect(ScissorEffect::get_class_type());
|
||||
clip_frame_changed();
|
||||
}
|
||||
}
|
||||
|
|
@ -222,17 +202,16 @@ clip_frame_changed() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PGVirtualFrame::setup_child_nodes
|
||||
// Access: Private
|
||||
// Description: Creates the special canvas_node and clip_plane_node
|
||||
// Description: Creates the special canvas_node and canvas_parent
|
||||
// for this object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PGVirtualFrame::
|
||||
setup_child_nodes() {
|
||||
_canvas_parent = new ModelNode("canvas_parent");
|
||||
_canvas_parent->set_preserve_transform(ModelNode::PT_local);
|
||||
add_child(_canvas_parent);
|
||||
|
||||
_canvas_node = new ModelNode("canvas");
|
||||
_canvas_node->set_preserve_transform(ModelNode::PT_local);
|
||||
// We have to preserve the clip plane attribute.
|
||||
_canvas_node->set_preserve_attributes(SceneGraphReducer::TT_other);
|
||||
add_child(_canvas_node);
|
||||
|
||||
_clip_plane_node = new PandaNode("clip_planes");
|
||||
add_child(_clip_plane_node);
|
||||
_canvas_parent->add_child(_canvas_node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,19 +29,19 @@ class TransformState;
|
|||
// only see the portion of the canvas that is below the
|
||||
// window at any given time.
|
||||
//
|
||||
// This works simply by automatically defining clipping
|
||||
// planes to be applied to a special child node, called
|
||||
// This works simply by automatically defining a scissor
|
||||
// effect to be applied to a special child node, called
|
||||
// the canvas_node, of the PGVirtualFrame node. Every
|
||||
// object that is parented to the canvas_node will be
|
||||
// clipped by the clip_frame. Also, you can modify the
|
||||
// canvas_transform through convenience methods here,
|
||||
// which actually modifies the transform on the
|
||||
// clipped by the scissor effect. Also, you can modify
|
||||
// the canvas_transform through convenience methods
|
||||
// here, which actually modifies the transform on the
|
||||
// canvas_node.
|
||||
//
|
||||
// The net effect is that the virtual canvas is
|
||||
// arbitrarily large, and we can peek at it through the
|
||||
// clip_frame, and scroll through different parts of it
|
||||
// by modifying the canvas_transform.
|
||||
// scissor region, and scroll through different parts of
|
||||
// it by modifying the canvas_transform.
|
||||
//
|
||||
// See PGScrollFrame for a specialization of this class
|
||||
// that handles the traditional scrolling canvas, with
|
||||
|
|
@ -71,7 +71,7 @@ PUBLISHED:
|
|||
INLINE const TransformState *get_canvas_transform() const;
|
||||
|
||||
INLINE PandaNode *get_canvas_node() const;
|
||||
INLINE PandaNode *get_clip_plane_node() const;
|
||||
INLINE PandaNode *get_canvas_parent() const;
|
||||
|
||||
protected:
|
||||
virtual void clip_frame_changed();
|
||||
|
|
@ -84,7 +84,7 @@ private:
|
|||
LVecBase4f _clip_frame;
|
||||
|
||||
PT(ModelNode) _canvas_node;
|
||||
PT(PandaNode) _clip_plane_node;
|
||||
PT(ModelNode) _canvas_parent;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue