Panda3D
Loading...
Searching...
No Matches
sheetNode.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 sheetNode.cxx
10 * @author drose
11 * @date 2003-10-11
12 */
13
14#include "sheetNode.h"
15#include "cullTraverser.h"
16#include "cullTraverserData.h"
17#include "cullableObject.h"
18#include "cullHandler.h"
19#include "bamWriter.h"
20#include "bamReader.h"
21#include "datagram.h"
22#include "datagramIterator.h"
23#include "pStatTimer.h"
24#include "geom.h"
25#include "geomTristrips.h"
26#include "geomVertexWriter.h"
27#include "boundingSphere.h"
28#include "colorAttrib.h"
29#include "renderState.h"
30
31TypeHandle SheetNode::_type_handle;
32
33PStatCollector SheetNode::_sheet_node_pcollector("*:SheetNode");
34
35/**
36 *
37 */
38CycleData *SheetNode::CData::
39make_copy() const {
40 return new CData(*this);
41}
42
43/**
44 * Writes the contents of this object to the datagram for shipping out to a
45 * Bam file.
46 */
47void SheetNode::CData::
48write_datagram(BamWriter *writer, Datagram &dg) const {
49 // For now, we write a NULL pointer. Eventually we will write out the
50 // NurbsSurfaceEvaluator pointer.
51 writer->write_pointer(dg, nullptr);
52}
53
54/**
55 * This internal function is called by make_from_bam to read in all of the
56 * relevant data from the BamFile for the new SheetNode.
57 */
58void SheetNode::CData::
59fillin(DatagramIterator &scan, BamReader *reader) {
60 // For now, we skip over the NULL pointer that we wrote out.
61 reader->skip_pointer(scan);
62 _surface.clear();
63}
64
65/**
66 *
67 */
68SheetNode::
69SheetNode(const std::string &name) :
70 PandaNode(name)
71{
72 set_cull_callback();
73}
74
75/**
76 *
77 */
78SheetNode::
79SheetNode(const SheetNode &copy) :
80 PandaNode(copy),
81 _cycler(copy._cycler)
82{
83}
84
85/**
86 * Returns a newly-allocated Node that is a shallow copy of this one. It will
87 * be a different Node pointer, but its internal data may or may not be shared
88 * with that of the original Node.
89 */
91make_copy() const {
92 return new SheetNode(*this);
93}
94
95/**
96 * Returns true if it is generally safe to transform this particular kind of
97 * Node by calling the xform() method, false otherwise. For instance, it's
98 * usually a bad idea to attempt to xform a SheetNode.
99 */
101safe_to_transform() const {
102 return false;
103}
104
105/**
106 * This function will be called during the cull traversal to perform any
107 * additional operations that should be performed at cull time. This may
108 * include additional manipulation of render state or additional
109 * visible/invisible decisions, or any other arbitrary operation.
110 *
111 * Note that this function will *not* be called unless set_cull_callback() is
112 * called in the constructor of the derived class. It is necessary to call
113 * set_cull_callback() to indicated that we require cull_callback() to be
114 * called.
115 *
116 * By the time this function is called, the node has already passed the
117 * bounding-volume test for the viewing frustum, and the node's transform and
118 * state have already been applied to the indicated CullTraverserData object.
119 *
120 * The return value is true if this node should be visible, or false if it
121 * should be culled.
122 */
125 // Statistics
126 PStatTimer timer(_sheet_node_pcollector);
127
128 // Create some geometry on-the-fly to render the sheet.
129 if (get_num_u_subdiv() > 0 && get_num_v_subdiv() > 0) {
131 if (surface != nullptr) {
132 PT(NurbsSurfaceResult) result = surface->evaluate(data.get_node_path());
133
134 if (result->get_num_u_segments() > 0 && result->get_num_v_segments() > 0) {
135 render_sheet(trav, data, result);
136 }
137 }
138 }
139
140 return true;
141}
142
143/**
144 * Returns true if there is some value to visiting this particular node during
145 * the cull traversal for any camera, false otherwise. This will be used to
146 * optimize the result of get_net_draw_show_mask(), so that any subtrees that
147 * contain only nodes for which is_renderable() is false need not be visited.
148 */
150is_renderable() const {
151 return true;
152}
153
154/**
155 *
156 */
157void SheetNode::
158output(std::ostream &out) const {
159 PandaNode::output(out);
161 if (surface != nullptr) {
162 out << " " << *surface;
163 } else {
164 out << " (no surface)";
165 }
166}
167
168/**
169 *
170 */
171void SheetNode::
172write(std::ostream &out, int indent_level) const {
173 PandaNode::write(out, indent_level);
175 if (surface != nullptr) {
176 indent(out, indent_level + 2) << *surface << "\n";
177 } else {
178 indent(out, indent_level + 2) << "(no surface)\n";
179 }
180}
181
182/**
183 * Recomputes the bounding volume. This is normally called automatically, but
184 * it must occasionally be called explicitly when the surface has changed
185 * properties outside of this node's knowledge.
186 */
188reset_bound(const NodePath &rel_to) {
189 Thread *current_thread = Thread::get_current_thread();
190 int pipeline_stage = current_thread->get_pipeline_stage();
191 do_recompute_bounds(rel_to, pipeline_stage, current_thread);
192 mark_internal_bounds_stale(current_thread);
193}
194
195/**
196 * Called when needed to recompute the node's _internal_bound object. Nodes
197 * that contain anything of substance should redefine this to do the right
198 * thing.
199 */
200void SheetNode::
201compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
202 int &internal_vertices,
203 int pipeline_stage,
204 Thread *current_thread) const {
205 PT(BoundingVolume) bounds =
206 do_recompute_bounds(NodePath((PandaNode *)this), pipeline_stage,
207 current_thread);
208
209 internal_bounds = bounds;
210 internal_vertices = 0; // TODO--estimate this better.
211}
212
213/**
214 * Does the actual internal recompute.
215 */
216PT(BoundingVolume) SheetNode::
217do_recompute_bounds(const NodePath &rel_to, int pipeline_stage,
218 Thread *current_thread) const {
219 // TODO: fix the bounds so that it properly reflects the indicated pipeline
220 // stage. At the moment, we cheat and get some of the properties from the
221 // current pipeline stage, the lazy way.
222
223 // First, get ourselves a fresh, empty bounding volume.
224 PT(BoundingVolume) bound = new BoundingSphere;
225
227 if (surface != nullptr) {
229 get_surface()->get_vertices(verts, rel_to);
230
232 DCAST_INTO_R(gbv, bound, bound);
233 gbv->around(&verts[0], &verts[0] + verts.size());
234 }
235 return bound;
236}
237
238/**
239 * Draws the sheet as a series of tristrips along its length.
240 */
241void SheetNode::
242render_sheet(CullTraverser *trav, CullTraverserData &data,
243 NurbsSurfaceResult *result) {
244 bool use_vertex_color = get_use_vertex_color();
245
246 int num_u_segments = result->get_num_u_segments();
247 int num_v_segments = result->get_num_v_segments();
248 int num_u_verts = get_num_u_subdiv() + 1;
249 int num_v_verts = get_num_v_subdiv() + 1;
250
251 CPT(GeomVertexFormat) format;
252 if (use_vertex_color) {
254 } else {
256 }
257 PT(GeomVertexData) vdata = new GeomVertexData
258 ("sheet", format, Geom::UH_stream);
259 int expected_num_vertices = num_u_segments * (num_u_verts + 1) * num_v_segments * num_v_verts;
260 vdata->reserve_num_rows(expected_num_vertices);
261
262 GeomVertexWriter vertex(vdata, InternalName::get_vertex());
263 GeomVertexWriter normal(vdata, InternalName::get_normal());
264 GeomVertexWriter color(vdata, InternalName::get_color());
265 GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
266
267 for (int ui = 0; ui < num_u_segments; ui++) {
268 for (int uni = 0; uni <= num_u_verts; uni++) {
269 PN_stdfloat u0 = (PN_stdfloat)uni / (PN_stdfloat)num_u_verts;
270 PN_stdfloat u0_tc = result->get_segment_u(ui, u0);
271
272 for (int vi = 0; vi < num_v_segments; vi++) {
273 for (int vni = 0; vni < num_v_verts; vni++) {
274 PN_stdfloat v = (PN_stdfloat)vni / (PN_stdfloat)(num_v_verts - 1);
275 PN_stdfloat v_tc = result->get_segment_v(vi, v);
276
277 LPoint3 point;
278 LVector3 norm;
279 result->eval_segment_point(ui, vi, u0, v, point);
280 result->eval_segment_normal(ui, vi, u0, v, norm);
281 vertex.add_data3(point);
282 normal.add_data3(norm);
283 texcoord.add_data2(u0_tc, v_tc);
284
285 if (use_vertex_color) {
286 LColor c0;
287 result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4);
288 color.add_data4(c0);
289 }
290 }
291 }
292 }
293 }
294 nassertv(vdata->get_num_rows() == expected_num_vertices);
295
296 PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_stream);
297
298 int expected_num_tristrips = num_u_segments * num_u_verts * num_v_segments;
299 int expected_verts_per_tristrip = num_v_verts * 2;
300
301 int expected_prim_vertices = (expected_num_tristrips - 1) * (expected_verts_per_tristrip + strip->get_num_unused_vertices_per_primitive()) + expected_verts_per_tristrip;
302
303 strip->reserve_num_vertices(expected_prim_vertices);
304
305 int verts_per_row = num_v_segments * num_v_verts;
306
307 for (int ui = 0; ui < num_u_segments; ui++) {
308 for (int uni = 0; uni < num_u_verts; uni++) {
309 int row_start_index = ((ui * (num_u_verts + 1)) + uni) * verts_per_row;
310
311 for (int vi = 0; vi < num_v_segments; vi++) {
312 for (int vni = 0; vni < num_v_verts; vni++) {
313 int vert_index_0 = row_start_index + (vi * num_v_verts) + vni;
314 int vert_index_1 = vert_index_0 + verts_per_row;
315 strip->add_vertex(vert_index_0);
316 strip->add_vertex(vert_index_1);
317 }
318 strip->close_primitive();
319 }
320 }
321 }
322 nassertv(strip->get_num_vertices() == expected_prim_vertices);
323
324 PT(Geom) geom = new Geom(vdata);
325 geom->add_primitive(strip);
326
327 CPT(RenderState) state = data._state;
328 if (use_vertex_color) {
329 state = state->add_attrib(ColorAttrib::make_vertex());
330 }
331
332 CullableObject *object =
333 new CullableObject(geom, state,
334 data.get_internal_transform(trav));
335 trav->get_cull_handler()->record_object(object, trav);
336}
337
338/**
339 * Tells the BamReader how to create objects of type SheetNode.
340 */
343 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
344}
345
346/**
347 * Writes the contents of this object to the datagram for shipping out to a
348 * Bam file.
349 */
351write_datagram(BamWriter *manager, Datagram &dg) {
352 PandaNode::write_datagram(manager, dg);
353 manager->write_cdata(dg, _cycler);
354}
355
356/**
357 * This function is called by the BamReader's factory when a new object of
358 * type SheetNode is encountered in the Bam file. It should create the
359 * SheetNode and extract its information from the file.
360 */
361TypedWritable *SheetNode::
362make_from_bam(const FactoryParams &params) {
363 SheetNode *node = new SheetNode("");
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 SheetNode.
376 */
377void SheetNode::
378fillin(DatagramIterator &scan, BamReader *manager) {
379 PandaNode::fillin(scan, manager);
380 manager->read_cdata(scan, _cycler);
381}
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
void skip_pointer(DatagramIterator &scan)
Reads and discards a pointer value from the Bam file.
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
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
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
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 single page of data maintained by a PipelineCycler.
Definition cycleData.h:50
A class to retrieve the individual data elements previously stored in a Datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
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 triangle strips.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This class defines the physical layout of the vertex data stored within a Geom.
static const GeomVertexFormat * get_v3n3cpt2()
Returns a standard vertex format with a 2-component texture coordinate pair, a packed color,...
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...
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.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
This class is an abstraction for evaluating NURBS surfaces.
The result of a NurbsSurfaceEvaluator.
void eval_segment_point(int ui, int vi, PN_stdfloat u, PN_stdfloat v, LVecBase3 &point) const
Evaluates the point on the surface corresponding to the indicated value in parametric time within the...
int get_num_u_segments() const
Returns the number of piecewise continuous segments within the surface in the U direction.
PN_stdfloat get_segment_u(int ui, PN_stdfloat u) const
Accepts a u value in the range [0, 1], and assumed to be relative to the indicated segment (as in eva...
PN_stdfloat get_segment_v(int vi, PN_stdfloat v) const
Accepts a v value in the range [0, 1], and assumed to be relative to the indicated segment (as in eva...
void eval_segment_normal(int ui, int vi, PN_stdfloat u, PN_stdfloat v, LVecBase3 &normal) const
As eval_segment_point, but computes the normal to the surface at the indicated point.
void eval_segment_extended_points(int ui, int vi, PN_stdfloat u, PN_stdfloat v, int d, PN_stdfloat result[], int num_values) const
Simultaneously performs eval_extended_point on a contiguous sequence of dimensions.
int get_num_v_segments() const
Returns the number of piecewise continuous segments within the surface in the V direction.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition pStatTimer.h:30
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
This class draws a visible representation of the NURBS surface stored in its NurbsSurfaceEvaluator.
Definition sheetNode.h:32
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
Definition sheetNode.cxx:91
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
NurbsSurfaceEvaluator * get_surface() const
Returns the surface represented by the SheetNode.
Definition sheetNode.I:50
static void register_with_read_factory()
Tells the BamReader how to create objects of type SheetNode.
bool get_use_vertex_color() const
Returns the "use vertex color" flag.
Definition sheetNode.I:71
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
int get_num_u_subdiv() const
Returns the number of subdivisions per cubic segment to draw in the U direction.
Definition sheetNode.I:93
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
int get_num_v_subdiv() const
Returns the number of subdivisions per cubic segment to draw in the V direction.
Definition sheetNode.I:115
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
void reset_bound(const NodePath &rel_to)
Recomputes the bounding volume.
A thread; that is, a lightweight process.
Definition thread.h:46
get_pipeline_stage
Returns the Pipeline stage number associated with this thread.
Definition thread.h:105
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition thread.h:109
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.
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.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.