354 lines
12 KiB
C++
354 lines
12 KiB
C++
// Filename: planeNode.cxx
|
|
// Created by: drose (11Jul02)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
|
//
|
|
// All use of this software is subject to the terms of the Panda 3d
|
|
// Software license. You should have received a copy of this license
|
|
// along with this source code; you will also find a current copy of
|
|
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "planeNode.h"
|
|
#include "geometricBoundingVolume.h"
|
|
#include "bamWriter.h"
|
|
#include "bamReader.h"
|
|
#include "datagram.h"
|
|
#include "datagramIterator.h"
|
|
#include "geomVertexWriter.h"
|
|
#include "geomVertexData.h"
|
|
#include "geomLines.h"
|
|
#include "geom.h"
|
|
#include "cullableObject.h"
|
|
#include "cullHandler.h"
|
|
#include "boundingPlane.h"
|
|
|
|
UpdateSeq PlaneNode::_sort_seq;
|
|
|
|
TypeHandle PlaneNode::_type_handle;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::CData::make_copy
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
CycleData *PlaneNode::CData::
|
|
make_copy() const {
|
|
return new CData(*this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::CData::write_datagram
|
|
// Access: Public, Virtual
|
|
// Description: Writes the contents of this object to the datagram
|
|
// for shipping out to a Bam file.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::CData::
|
|
write_datagram(BamWriter *, Datagram &dg) const {
|
|
_plane.write_datagram(dg);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::CData::fillin
|
|
// Access: Public, Virtual
|
|
// Description: This internal function is called by make_from_bam to
|
|
// read in all of the relevant data from the BamFile for
|
|
// the new Light.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::CData::
|
|
fillin(DatagramIterator &scan, BamReader *) {
|
|
_plane.read_datagram(scan);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PlaneNode::
|
|
PlaneNode(const string &name, const Planef &plane) :
|
|
PandaNode(name),
|
|
_priority(0)
|
|
{
|
|
set_cull_callback();
|
|
|
|
// PlaneNodes are hidden by default.
|
|
set_overall_hidden(true);
|
|
|
|
set_plane(plane);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::Copy Constructor
|
|
// Access: Protected
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
PlaneNode::
|
|
PlaneNode(const PlaneNode ©) :
|
|
PandaNode(copy),
|
|
_priority(copy._priority),
|
|
_cycler(copy._cycler)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::output
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::
|
|
output(ostream &out) const {
|
|
PandaNode::output(out);
|
|
out << " " << get_plane();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::make_copy
|
|
// Access: Public, Virtual
|
|
// Description: Returns a newly-allocated Node that is a shallow copy
|
|
// of this one. It will be a different Node pointer,
|
|
// but its internal data may or may not be shared with
|
|
// that of the original Node.
|
|
////////////////////////////////////////////////////////////////////
|
|
PandaNode *PlaneNode::
|
|
make_copy() const {
|
|
return new PlaneNode(*this);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::xform
|
|
// Access: Public, Virtual
|
|
// Description: Transforms the contents of this PandaNode by the
|
|
// indicated matrix, if it means anything to do so. For
|
|
// most kinds of PandaNodes, this does nothing.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::
|
|
xform(const LMatrix4f &mat) {
|
|
PandaNode::xform(mat);
|
|
CDWriter cdata(_cycler);
|
|
cdata->_plane = cdata->_plane * mat;
|
|
cdata->_front_viz = NULL;
|
|
cdata->_back_viz = NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::cull_callback
|
|
// Access: Public, Virtual
|
|
// Description: This function will be called during the cull
|
|
// traversal to perform any additional operations that
|
|
// should be performed at cull time. This may include
|
|
// additional manipulation of render state or additional
|
|
// visible/invisible decisions, or any other arbitrary
|
|
// operation.
|
|
//
|
|
// Note that this function will *not* be called unless
|
|
// set_cull_callback() is called in the constructor of
|
|
// the derived class. It is necessary to call
|
|
// set_cull_callback() to indicated that we require
|
|
// cull_callback() to be called.
|
|
//
|
|
// By the time this function is called, the node has
|
|
// already passed the bounding-volume test for the
|
|
// viewing frustum, and the node's transform and state
|
|
// have already been applied to the indicated
|
|
// CullTraverserData object.
|
|
//
|
|
// The return value is true if this node should be
|
|
// visible, or false if it should be culled.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PlaneNode::
|
|
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_gsg());
|
|
trav->get_cull_handler()->record_object(plane_viz, trav);
|
|
|
|
// Now carry on to render our child nodes.
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::is_renderable
|
|
// Access: Public, Virtual
|
|
// Description: Returns true if there is some value to visiting this
|
|
// particular node during the cull traversal for any
|
|
// camera, false otherwise. This will be used to
|
|
// optimize the result of get_net_draw_show_mask(), so
|
|
// that any subtrees that contain only nodes for which
|
|
// is_renderable() is false need not be visited.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool PlaneNode::
|
|
is_renderable() const {
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::compute_internal_bounds
|
|
// Access: Protected, Virtual
|
|
// Description: Returns a newly-allocated BoundingVolume that
|
|
// represents the internal contents of the node. Should
|
|
// be overridden by PandaNode classes that contain
|
|
// something internally.
|
|
////////////////////////////////////////////////////////////////////
|
|
PT(BoundingVolume) PlaneNode::
|
|
compute_internal_bounds(int pipeline_stage, Thread *current_thread) const {
|
|
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
|
|
return new BoundingPlane(cdata->_plane);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::get_viz
|
|
// Access: Protected
|
|
// Description: Returns a Geom that represents the visualization of
|
|
// the PlaneNode.
|
|
////////////////////////////////////////////////////////////////////
|
|
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();
|
|
Planef eye_plane = cdata->_plane * data.get_modelview_transform(trav)->get_mat();
|
|
bool front = (eye_plane.dist_to_plane(lens->get_nodal_point()) >= 0.0f);
|
|
|
|
if (cdata->_front_viz != (Geom *)NULL) {
|
|
return front ? cdata->_front_viz : cdata->_back_viz;
|
|
}
|
|
|
|
if (pgraph_cat.is_debug()) {
|
|
pgraph_cat.debug()
|
|
<< "Recomputing viz for " << *this << "\n";
|
|
}
|
|
|
|
CDWriter cdataw(_cycler, cdata, false);
|
|
const Planef &plane = cdataw->_plane;
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
(get_name(), GeomVertexFormat::get_v3cp(), Geom::UH_static);
|
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
PT(GeomLines) lines = new GeomLines(Geom::UH_static);
|
|
|
|
LVector3f a, b;
|
|
|
|
if (fabs(plane[0]) > fabs(plane[1])) {
|
|
// X > Y
|
|
if (fabs(plane[0]) > fabs(plane[2])) {
|
|
// X > Y && X > Z. X is the largest.
|
|
a.set(0, 1, 0);
|
|
b.set(0, 0, 1);
|
|
} else {
|
|
// X > Y && Z > X. Z is the largest.
|
|
a.set(1, 0, 0);
|
|
b.set(0, 1, 0);
|
|
}
|
|
} else {
|
|
// Y > X
|
|
if (fabs(plane[1]) > fabs(plane[2])) {
|
|
// Y > X && Y > Z. Y is the largest.
|
|
a.set(1, 0, 0);
|
|
b.set(0, 0, 1);
|
|
} else {
|
|
// Y > X && Z > Y. Z is the largest.
|
|
a.set(1, 0, 0);
|
|
b.set(0, 1, 0);
|
|
}
|
|
}
|
|
|
|
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_data3f(plane.project(a * x - b * num_segs));
|
|
vertex.add_data3f(plane.project(a * x + b * num_segs));
|
|
lines->add_next_vertices(2);
|
|
lines->close_primitive();
|
|
}
|
|
for (int y = -num_segs; y <= num_segs; ++y) {
|
|
vertex.add_data3f(plane.project(b * y - a * num_segs));
|
|
vertex.add_data3f(plane.project(b * y + a * num_segs));
|
|
lines->add_next_vertices(2);
|
|
lines->close_primitive();
|
|
}
|
|
|
|
cdataw->_front_viz = new Geom(vdata->set_color(Colorf(1.0f, 1.0f, 0.0f, 1.0f)));
|
|
cdataw->_front_viz->add_primitive(lines);
|
|
|
|
cdataw->_back_viz = new Geom(vdata->set_color(Colorf(0.4f, 0.4f, 0.0f, 1.0f)));
|
|
cdataw->_back_viz->add_primitive(lines);
|
|
|
|
return front ? cdataw->_front_viz : cdataw->_back_viz;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::register_with_read_factory
|
|
// Access: Public, Static
|
|
// Description: Tells the BamReader how to create objects of type
|
|
// PlaneNode.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::
|
|
register_with_read_factory() {
|
|
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::write_datagram
|
|
// Access: Public, Virtual
|
|
// Description: Writes the contents of this object to the datagram
|
|
// for shipping out to a Bam file.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::
|
|
write_datagram(BamWriter *manager, Datagram &dg) {
|
|
PandaNode::write_datagram(manager, dg);
|
|
manager->write_cdata(dg, _cycler);
|
|
dg.add_int32(_priority);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::make_from_bam
|
|
// Access: Protected, Static
|
|
// Description: This function is called by the BamReader's factory
|
|
// when a new object of type PlaneNode is encountered
|
|
// in the Bam file. It should create the PlaneNode
|
|
// and extract its information from the file.
|
|
////////////////////////////////////////////////////////////////////
|
|
TypedWritable *PlaneNode::
|
|
make_from_bam(const FactoryParams ¶ms) {
|
|
PlaneNode *node = new PlaneNode("");
|
|
DatagramIterator scan;
|
|
BamReader *manager;
|
|
|
|
parse_params(params, scan, manager);
|
|
node->fillin(scan, manager);
|
|
|
|
return node;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: PlaneNode::fillin
|
|
// Access: Protected
|
|
// Description: This internal function is called by make_from_bam to
|
|
// read in all of the relevant data from the BamFile for
|
|
// the new PlaneNode.
|
|
////////////////////////////////////////////////////////////////////
|
|
void PlaneNode::
|
|
fillin(DatagramIterator &scan, BamReader *manager) {
|
|
PandaNode::fillin(scan, manager);
|
|
manager->read_cdata(scan, _cycler);
|
|
_priority = scan.get_int32();
|
|
}
|