Panda3D
Loading...
Searching...
No Matches
occluderNode.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file occluderNode.cxx
10 * @author jenes
11 * @date 2011-03-11
12 */
13
14#include "occluderNode.h"
15
16#include "geomNode.h"
17#include "cullTraverserData.h"
18#include "cullTraverser.h"
19#include "renderState.h"
20#include "plane.h"
21#include "pnmImage.h"
22#include "textureAttrib.h"
23#include "colorAttrib.h"
24#include "depthOffsetAttrib.h"
25#include "cullFaceAttrib.h"
26#include "transparencyAttrib.h"
27#include "transformState.h"
28#include "cullableObject.h"
29#include "cullHandler.h"
30#include "boundingSphere.h"
31#include "geomVertexData.h"
32#include "geomTriangles.h"
33#include "geomLinestrips.h"
34#include "geomVertexWriter.h"
35#include "geom.h"
36#include "datagram.h"
37#include "datagramIterator.h"
38#include "bamReader.h"
39#include "bamWriter.h"
40
41#include "plane.h"
42
43TypeHandle OccluderNode::_type_handle;
44PT(Texture) OccluderNode::_viz_tex;
45
46
47/**
48 * The default constructor creates a default occlusion polygon in the XZ plane
49 * (or XY plane in a y-up coordinate system). Use the normal Panda set_pos(),
50 * set_hpr(), set_scale() to position it appropriately, or replace the
51 * vertices with set_vertices().
52 */
53OccluderNode::
54OccluderNode(const std::string &name) :
55 PandaNode(name)
56{
57 set_cull_callback();
58 // OccluderNodes are hidden by default.
59 set_overall_hidden(true);
60 set_double_sided(false);
61 set_min_coverage(0.0);
62 set_vertices(LPoint3::rfu(-1.0, 0.0, -1.0),
63 LPoint3::rfu(1.0, 0.0, -1.0),
64 LPoint3::rfu(1.0, 0.0, 1.0),
65 LPoint3::rfu(-1.0, 0.0, 1.0));
66}
67
68/**
69 *
70 */
71OccluderNode::
72OccluderNode(const OccluderNode &copy) :
73 PandaNode(copy),
74 _double_sided(copy._double_sided),
75 _min_coverage(copy._min_coverage),
76 _vertices(copy._vertices)
77{
78}
79
80/**
81 *
82 */
83OccluderNode::
84~OccluderNode() {
85}
86
87/**
88 * Returns a newly-allocated Node that is a shallow copy of this one. It will
89 * be a different Node pointer, but its internal data may or may not be shared
90 * with that of the original Node.
91 */
93make_copy() const {
94 return new OccluderNode(*this);
95}
96
97/**
98 * Returns true if the node's name has extrinsic meaning and must be preserved
99 * across a flatten operation, false otherwise.
100 */
102preserve_name() const {
103 return true;
104}
105
106/**
107 * Transforms the contents of this node by the indicated matrix, if it means
108 * anything to do so. For most kinds of nodes, this does nothing.
109 */
111xform(const LMatrix4 &mat) {
112 nassertv(!mat.is_nan());
113
114 for (Vertices::iterator vi = _vertices.begin();
115 vi != _vertices.end();
116 ++vi) {
117 (*vi) = (*vi) * mat;
118 }
119}
120
121/**
122 * This function will be called during the cull traversal to perform any
123 * additional operations that should be performed at cull time. This may
124 * include additional manipulation of render state or additional
125 * visible/invisible decisions, or any other arbitrary operation.
126 *
127 * Note that this function will *not* be called unless set_cull_callback() is
128 * called in the constructor of the derived class. It is necessary to call
129 * set_cull_callback() to indicated that we require cull_callback() to be
130 * called.
131 *
132 * By the time this function is called, the node has already passed the
133 * bounding-volume test for the viewing frustum, and the node's transform and
134 * state have already been applied to the indicated CullTraverserData object.
135 *
136 * The return value is true if this node should be visible, or false if it
137 * should be culled.
138 */
141 // Normally, an OccluderNode is invisible. But if someone shows it, we will
142 // draw a visualization, a checkerboard-textured polygon.
143 CullableObject *occluder_viz =
144 new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data),
145 data.get_internal_transform(trav));
146 trav->get_cull_handler()->record_object(occluder_viz, trav);
147
148 // Also get the frame.
149 nassertr(_frame_viz != nullptr, false);
150 CullableObject *frame_viz =
151 new CullableObject(_frame_viz, get_frame_viz_state(trav, data),
152 data.get_internal_transform(trav));
153 trav->get_cull_handler()->record_object(frame_viz, trav);
154
155 // Now carry on to render our child nodes.
156 return true;
157}
158
159/**
160 * Returns true if there is some value to visiting this particular node during
161 * the cull traversal for any camera, false otherwise. This will be used to
162 * optimize the result of get_net_draw_show_mask(), so that any subtrees that
163 * contain only nodes for which is_renderable() is false need not be visited.
164 */
166is_renderable() const {
167 return true;
168}
169
170
171/**
172 * Writes a brief description of the node to the indicated output stream.
173 * This is invoked by the << operator. It may be overridden in derived
174 * classes to include some information relevant to the class.
175 */
177output(std::ostream &out) const {
178 PandaNode::output(out);
179}
180
181/**
182 * Called when needed to recompute the node's _internal_bound object. Nodes
183 * that contain anything of substance should redefine this to do the right
184 * thing.
185 */
186void OccluderNode::
187compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
188 int &internal_vertices,
189 int pipeline_stage,
190 Thread *current_thread) const {
191 // First, get ourselves a fresh, empty bounding volume.
192 PT(BoundingVolume) bound = new BoundingSphere;
194
195 // Now actually compute the bounding volume by putting it around all of our
196 // vertices.
197 if (!_vertices.empty()) {
198 const LPoint3 *vertices_begin = &_vertices[0];
199 const LPoint3 *vertices_end = vertices_begin + _vertices.size();
200 gbv->around(vertices_begin, vertices_end);
201 }
202
203 internal_bounds = bound;
204 internal_vertices = 0;
205}
206
207/**
208 * Returns a Geom that represents the visualization of the OccluderNode, as
209 * seen from the front.
210 */
211PT(Geom) OccluderNode::
212get_occluder_viz(CullTraverser *trav, CullTraverserData &data) {
213 if (_occluder_viz == nullptr) {
214 nassertr(_vertices.size() == 4, nullptr);
215
216 if (pgraph_cat.is_debug()) {
217 pgraph_cat.debug()
218 << "Recomputing viz for " << *this << "\n";
219 }
220
221 PT(GeomVertexData) vdata = new GeomVertexData
222 (get_name(), GeomVertexFormat::get_v3n3t2(), Geom::UH_static);
223
224 // Compute the polygon normal from the first three vertices.
225 LPlane plane(_vertices[0], _vertices[1], _vertices[2]);
226 LVector3 poly_normal = plane.get_normal();
227
228 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
229 GeomVertexWriter normal(vdata, InternalName::get_normal());
230 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
231 vertex.add_data3(_vertices[0]);
232 normal.add_data3(poly_normal);
233 texcoord.add_data2(0.0, 0.0);
234
235 vertex.add_data3(_vertices[1]);
236 normal.add_data3(poly_normal);
237 texcoord.add_data2(8.0, 0.0);
238
239 vertex.add_data3(_vertices[2]);
240 normal.add_data3(poly_normal);
241 texcoord.add_data2(8.0, 8.0);
242
243 vertex.add_data3(_vertices[3]);
244 normal.add_data3(poly_normal);
245 texcoord.add_data2(0.0, 8.0);
246
247 PT(GeomTriangles) triangles = new GeomTriangles(Geom::UH_static);
248 triangles->add_vertices(0, 1, 2);
249 triangles->close_primitive();
250 triangles->add_vertices(0, 2, 3);
251 triangles->close_primitive();
252
253 _occluder_viz = new Geom(vdata);
254 _occluder_viz->add_primitive(triangles);
255
256 PT(GeomLinestrips) lines = new GeomLinestrips(Geom::UH_static);
257 lines->add_vertices(0, 1, 2, 3);
258 lines->add_vertex(0);
259 lines->close_primitive();
260
261 _frame_viz = new Geom(vdata);
262 _frame_viz->add_primitive(lines);
263 }
264
265 return _occluder_viz;
266}
267
268/**
269 * Returns the RenderState to apply to the visualization.
270 */
271CPT(RenderState) OccluderNode::
272get_occluder_viz_state(CullTraverser *trav, CullTraverserData &data) {
273 if (_viz_tex == nullptr) {
274 // Create a default texture. We set it up as a 2x2 graytone checkerboard,
275 // since that's real easy, and it doesn't look like a CollisionPolygon.
276 _viz_tex = new Texture("occluder_viz");
277 _viz_tex->setup_2d_texture(2, 2, Texture::T_unsigned_byte, Texture::F_luminance);
278 PTA_uchar image;
279 image.set_data("\x20\x80\x80\x20");
280 _viz_tex->set_ram_image(image);
281 _viz_tex->set_minfilter(SamplerState::FT_nearest);
282 _viz_tex->set_magfilter(SamplerState::FT_nearest);
283 }
284
285 static CPT(RenderState) viz_state;
286 if (viz_state == nullptr) {
287 viz_state = RenderState::make
288 (ColorAttrib::make_flat(LVecBase4(1.0f, 1.0f, 1.0f, 0.5f)),
289 TransparencyAttrib::make(TransparencyAttrib::M_alpha),
290 DepthOffsetAttrib::make(),
291 TextureAttrib::make(_viz_tex));
292 viz_state = viz_state->adjust_all_priorities(1);
293 }
294
295 CPT(RenderState) state = viz_state;
296 if (is_double_sided()) {
297 state = viz_state->set_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_none), 1);
298 } else {
299 state = viz_state->set_attrib(CullFaceAttrib::make(CullFaceAttrib::M_cull_clockwise), 1);
300 }
301
302 return state->compose(viz_state);
303}
304
305/**
306 * Returns the RenderState to apply to the frame.
307 */
308CPT(RenderState) OccluderNode::
309get_frame_viz_state(CullTraverser *trav, CullTraverserData &data) {
310 static CPT(RenderState) viz_state;
311 if (viz_state == nullptr) {
312 viz_state = RenderState::make
313 (ColorAttrib::make_flat(LVecBase4(0.0f, 0.0f, 0.0f, 1.0f)),
314 TextureAttrib::make_off());
315 viz_state = viz_state->adjust_all_priorities(1);
316 }
317
318 return data._state->compose(viz_state);
319}
320
321/**
322 * Tells the BamReader how to create objects of type OccluderNode.
323 */
326 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
327}
328
329/**
330 * Writes the contents of this object to the datagram for shipping out to a
331 * Bam file.
332 */
334write_datagram(BamWriter *manager, Datagram &dg) {
335 PandaNode::write_datagram(manager, dg);
336
337 dg.add_uint16(_vertices.size());
338 for (Vertices::const_iterator vi = _vertices.begin();
339 vi != _vertices.end();
340 ++vi) {
341 (*vi).write_datagram(dg);
342 }
343}
344
345/**
346 * Receives an array of pointers, one for each time manager->read_pointer()
347 * was called in fillin(). Returns the number of pointers processed.
348 */
350complete_pointers(TypedWritable **p_list, BamReader *manager) {
351 int pi = PandaNode::complete_pointers(p_list, manager);
352
353 return pi;
354}
355
356/**
357 * This function is called by the BamReader's factory when a new object of
358 * type OccluderNode is encountered in the Bam file. It should create the
359 * OccluderNode and extract its information from the file.
360 */
361TypedWritable *OccluderNode::
362make_from_bam(const FactoryParams &params) {
363 OccluderNode *node = new OccluderNode("");
364 DatagramIterator scan;
365 BamReader *manager;
366
367 parse_params(params, scan, manager);
368 node->fillin(scan, manager);
369
370 return node;
371}
372
373/**
374 * This internal function is called by make_from_bam to read in all of the
375 * relevant data from the BamFile for the new OccluderNode.
376 */
377void OccluderNode::
378fillin(DatagramIterator &scan, BamReader *manager) {
379 PandaNode::fillin(scan, manager);
380
381 int num_vertices = scan.get_uint16();
382 _vertices.clear();
383 _vertices.reserve(num_vertices);
384 for (int i = 0; i < num_vertices; i++) {
385 LPoint3 vertex;
386 vertex.read_datagram(scan);
387 _vertices.push_back(vertex);
388 }
389}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition bamReader.I:275
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition bamReader.h:110
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition bamWriter.h:63
This defines a bounding sphere, consisting of a center and a radius.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
The smallest atom of cull.
A class to retrieve the individual data elements previously stored in a Datagram.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition datagram.I:85
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition factory.I:73
Defines a series of line strips.
Defines a series of disconnected triangles.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
static const GeomVertexFormat * get_v3n3t2()
Returns a standard vertex format with a 2-component texture coordinate pair, a 3-component normal,...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_data2(PN_stdfloat x, PN_stdfloat y)
Sets the write row to a particular 2-component value, and advances the write row.
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row.
A container for geometry primitives.
Definition geom.h:54
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
bool around(const GeometricBoundingVolume **first, const GeometricBoundingVolume **last)
Resets the volume to enclose only the volumes indicated.
A node in the scene graph that can hold an occluder polygon, which must be a rectangle.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
static void register_with_read_factory()
Tells the BamReader how to create objects of type OccluderNode.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
is_double_sided
Is this occluder double-sided.
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this node by the indicated matrix, if it means anything to do so.
virtual void output(std::ostream &out) const
Writes a brief description of the node to the indicated output stream.
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
virtual bool preserve_name() const
Returns true if the node's name has extrinsic meaning and must be preserved across a flatten operatio...
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition texture.h:72
A thread; that is, a lightweight process.
Definition thread.h:46
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.