16 #include "cullTraverser.h"
17 #include "cullTraverserData.h"
18 #include "cullableObject.h"
19 #include "cullHandler.h"
20 #include "renderState.h"
21 #include "renderModeAttrib.h"
22 #include "colorAttrib.h"
23 #include "bamWriter.h"
24 #include "bamReader.h"
26 #include "datagramIterator.h"
27 #include "pStatTimer.h"
29 #include "geomLines.h"
30 #include "geomTristrips.h"
31 #include "geomVertexWriter.h"
32 #include "boundingSphere.h"
45 return new CData(*
this);
54 void RopeNode::CData::
68 void RopeNode::CData::
80 RopeNode(
const string &name) :
165 if (result->get_num_segments() > 0) {
168 render_thread(trav, data, result);
172 render_tape(trav, data, result);
176 render_billboard(trav, data, result);
180 render_tube(trav, data, result);
211 output(ostream &out)
const {
212 PandaNode::output(out);
215 out <<
" " << *curve;
217 out <<
" (no curve)";
227 write(ostream &out,
int indent_level)
const {
228 PandaNode::write(out, indent_level);
229 indent(out, indent_level) << *
get_curve() <<
"\n";
244 do_recompute_bounds(rel_to, pipeline_stage, current_thread);
258 int &internal_vertices,
260 Thread *current_thread)
const {
265 internal_bounds = bounds;
266 internal_vertices = 0;
277 get_format(
bool support_normals)
const {
278 PT(GeomVertexArrayFormat) array_format = new GeomVertexArrayFormat
279 (InternalName::get_vertex(), 3,
Geom::NT_stdfloat,
283 array_format->add_column
284 (InternalName::get_normal(), 3, Geom::NT_stdfloat,
288 array_format->add_column
289 (InternalName::get_color(), 1, Geom::NT_packed_dabc,
293 array_format->add_column
294 (InternalName::get_texcoord(), 2, Geom::NT_stdfloat,
298 return GeomVertexFormat::register_format(array_format);
307 do_recompute_bounds(const
NodePath &rel_to,
int pipeline_stage,
308 Thread *current_thread)
const {
324 NurbsCurveEvaluator::Vert3Array::iterator vi;
325 for (vi = verts.begin(); vi != verts.end(); ++vi) {
331 DCAST_INTO_R(gbv, bound, bound);
332 gbv->
around(&verts[0], &verts[0] + verts.size());
354 CurveSegments curve_segments;
355 int num_curve_verts = get_connected_segments(curve_segments, result);
360 ("rope", get_format(false),
Geom::UH_stream);
361 compute_thread_vertices(vdata, curve_segments, num_curve_verts);
366 lines->reserve_num_vertices((num_curve_verts - 1) * 2);
368 for (
int vi = 0; vi < num_curve_verts - 1; ++vi) {
369 lines->add_vertex(vi);
370 lines->add_vertex(vi + 1);
371 lines->close_primitive();
375 geom->add_primitive(lines);
378 CPT(
RenderState) state = data._state->add_attrib(thick);
380 state = state->add_attrib(ColorAttrib::make_vertex());
385 data.get_internal_transform(trav));
402 CurveSegments curve_segments;
403 int num_curve_verts = get_connected_segments(curve_segments, result);
409 ("rope", get_format(false),
Geom::UH_stream);
412 curve_segments, num_curve_verts, result);
417 CurveSegments::const_iterator si;
418 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
419 const CurveSegment &segment = (*si);
421 strip->add_next_vertices(segment.size() * 2);
422 strip->close_primitive();
426 geom->add_primitive(strip);
429 if (get_use_vertex_color()) {
430 state = state->add_attrib(ColorAttrib::make_vertex());
435 data.get_internal_transform(trav));
452 const TransformState *net_transform = data.get_net_transform(trav);
455 CPT(TransformState) rel_transform =
456 net_transform->invert_compose(camera_transform);
459 CurveSegments curve_segments;
460 int num_curve_verts = get_connected_segments(curve_segments, result);
466 ("rope", get_format(false),
Geom::UH_stream);
468 compute_billboard_vertices(vdata, camera_vec,
469 curve_segments, num_curve_verts, result);
474 CurveSegments::const_iterator si;
475 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
476 const CurveSegment &segment = (*si);
478 strip->add_next_vertices(segment.size() * 2);
479 strip->close_primitive();
483 geom->add_primitive(strip);
486 if (get_use_vertex_color()) {
487 state = state->add_attrib(ColorAttrib::make_vertex());
492 data.get_internal_transform(trav));
508 CurveSegments curve_segments;
509 int num_curve_verts = get_connected_segments(curve_segments, result);
515 int num_verts_per_slice;
518 ("rope", get_format(true),
Geom::UH_stream);
520 compute_tube_vertices(vdata, num_verts_per_slice,
521 curve_segments, num_curve_verts, result);
529 CurveSegments::const_iterator si;
530 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
531 const CurveSegment &segment = (*si);
533 for (
int s = 0; s < num_slices; ++s) {
534 int s1 = (s + 1) % num_verts_per_slice;
536 for (
size_t j = 0; j < segment.size(); ++j) {
537 strip->add_vertex((vi + j) * num_verts_per_slice + s);
538 strip->add_vertex((vi + j) * num_verts_per_slice + s1);
541 strip->close_primitive();
543 vi += (int)segment.size();
547 geom->add_primitive(strip);
550 if (get_use_vertex_color()) {
551 state = state->add_attrib(ColorAttrib::make_vertex());
556 data.get_internal_transform(trav));
579 int num_curve_verts = 0;
586 CurveSegment *curve_segment = NULL;
589 for (
int segment = 0; segment < num_segments; ++segment) {
593 if (curve_segment == (CurveSegment *)NULL ||
598 curve_segments.push_back(CurveSegment());
599 curve_segment = &curve_segments.back();
604 if (use_vertex_color) {
609 if (use_vertex_thickness) {
615 curve_segment->push_back(vtx);
620 for (
int i = 1; i < num_verts; ++i) {
621 PN_stdfloat t = (PN_stdfloat)i / (PN_stdfloat)(num_verts - 1);
626 if (use_vertex_color) {
631 if (use_vertex_thickness) {
637 curve_segment->push_back(vtx);
644 return num_curve_verts;
657 int num_curve_verts)
const {
669 PN_stdfloat dist = 0.0f;
670 CurveSegments::const_iterator si;
671 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
672 const CurveSegment &segment = (*si);
673 for (
size_t j = 0; j < segment.size(); ++j) {
674 vertex.add_data3(segment[j]._p);
676 if (use_vertex_color) {
677 color.add_data4(segment[j]._c);
680 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
682 if (uv_mode != UV_none) {
684 texcoord.add_data2(uv_t, 0.0f);
686 texcoord.add_data2(0.0f, uv_t);
708 int expected_num_verts = num_curve_verts * 2;
716 PN_stdfloat overall_radius = thickness * 0.5f;
717 PN_stdfloat radius = overall_radius;
724 PN_stdfloat dist = 0.0f;
725 CurveSegments::const_iterator si;
726 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
727 const CurveSegment &segment = (*si);
728 for (
size_t j = 0; j < segment.size(); ++j) {
730 compute_tangent(tangent, segment, j, result);
732 LVector3 norm = cross(tangent, camera_vec);
735 if (use_vertex_thickness) {
736 radius = overall_radius * segment[j]._thickness;
739 vertex.add_data3(segment[j]._p + norm * radius);
740 vertex.add_data3(segment[j]._p - norm * radius);
742 if (use_vertex_color) {
743 color.add_data4(segment[j]._c);
744 color.add_data4(segment[j]._c);
747 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
749 if (uv_mode != UV_none) {
751 texcoord.add_data2(uv_t, 1.0f);
752 texcoord.add_data2(uv_t, 0.0f);
754 texcoord.add_data2(1.0f, uv_t);
755 texcoord.add_data2(0.0f, uv_t);
773 int &num_verts_per_slice,
778 num_verts_per_slice = num_slices;
781 PN_stdfloat overall_radius = thickness * 0.5f;
782 PN_stdfloat radius = overall_radius;
793 if (uv_mode != UV_none) {
794 ++num_verts_per_slice;
797 int expected_num_verts = num_curve_verts * num_verts_per_slice;
807 PN_stdfloat dist = 0.0f;
808 CurveSegments::const_iterator si;
809 for (si = curve_segments.begin(); si != curve_segments.end(); ++si) {
810 const CurveSegment &segment = (*si);
811 for (
size_t j = 0; j < segment.size(); ++j) {
813 compute_tangent(tangent, segment, j, result);
817 up = cross(norm, tangent);
822 PN_stdfloat uv_t = compute_uv_t(dist, uv_mode, uv_scale, segment, j);
824 for (
int s = 0; s < num_verts_per_slice; ++s) {
825 if (use_vertex_thickness) {
826 radius = overall_radius * segment[j]._thickness;
829 vertex.add_data3(segment[j]._p + norm * radius);
831 if (normal_mode == NM_vertex) {
832 normal.add_data3(norm);
835 if (use_vertex_color) {
836 color.add_data4(segment[j]._c);
839 norm = norm * rotate;
841 if (uv_mode != UV_none) {
842 PN_stdfloat uv_s = (PN_stdfloat)s / (PN_stdfloat)num_slices;
844 texcoord.add_data2(uv_t, uv_s);
846 texcoord.add_data2(uv_s, uv_t);
882 tangent = segment[j + 1]._p - segment[j]._p;
883 }
else if (j == segment.size() - 1) {
884 tangent = segment[j]._p - segment[j - 1]._p;
886 tangent = segment[j + 1]._p - segment[j - 1]._p;
896 PN_stdfloat RopeNode::
897 compute_uv_t(PN_stdfloat &dist,
const RopeNode::UVMode &uv_mode,
905 return segment[j]._t * uv_scale;
909 LVector3 vec = segment[j]._p - segment[j - 1]._p;
912 return dist * uv_scale;
916 LVector3 vec = segment[j]._p - segment[j - 1]._p;
919 return dist * uv_scale;
962 parse_params(params, scan, manager);
963 node->fillin(scan, manager);
977 PandaNode::fillin(scan, manager);
int get_num_segments() const
Returns the number of piecewise continuous segments within the curve.
A basic node of the scene graph or data graph.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
PN_stdfloat get_uv_scale() const
Returns the scaling factor to apply to generated UV's for the rope.
NormalMode get_normal_mode() const
Returns the kind of normals to generate for the rope.
This is the base class for a number of render attributes (other than transform) that may be set on sc...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
RenderMode get_render_mode() const
Returns the method used to render the rope.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler)
Reads in the indicated CycleData object.
void eval_segment_point(int segment, PN_stdfloat t, LVecBase3 &point) const
Evaluates the point on the curve corresponding to the indicated value in parametric time within the i...
This defines a bounding sphere, consisting of a center and a radius.
const LVector3 & get_tube_up() const
Returns the normal vector used to control the "top" of the curve, when RenderMode is RM_tube...
A single page of data maintained by a PipelineCycler.
This class is an abstraction for evaluating NURBS curves.
Base class for objects that can be written to and read from Bam files.
void write_cdata(Datagram &packet, const PipelineCyclerBase &cycler)
Writes out the indicated CycleData object.
void skip_pointer(DatagramIterator &scan)
Reads and discards a pointer value from the Bam file.
bool get_uv_direction() const
Returns true if the rope runs down the U coordinate of the texture, or false if it runs down the V co...
float length_squared() const
Returns the square of the vector's length, cheap and easy.
int get_num_slices() const
Returns the number of radial subdivisions to make if RenderMode is RM_tube.
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This class draws a visible representation of the NURBS curve stored in its NurbsCurveEvaluator.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Defines a series of triangle strips.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
const LMatrix4 & get_matrix() const
Returns the optional matrix which is used to transform each control vertex after it has been transfor...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
void eval_segment_extended_points(int segment, PN_stdfloat t, int d, PN_stdfloat result[], int num_values) const
Simultaneously performs eval_extended_point on a contiguous sequence of dimensions.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
float length() const
Returns the length of the vector, by the Pythagorean theorem.
PN_stdfloat eval_segment_extended_point(int segment, PN_stdfloat t, int d) const
Evaluates the curve in n-dimensional space according to the extended vertices associated with the cur...
const TransformState * get_camera_transform() const
Returns the position of the camera relative to the starting node.
A lightweight class that represents a single element that may be timed and/or counted via stats...
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
void mark_internal_bounds_stale(Thread *current_thread=Thread::get_current_thread())
Should be called by a derived class to mark the internal bounding volume stale, so that compute_inter...
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
virtual bool is_renderable() const
Returns true if there is some value to visiting this particular node during the cull traversal for an...
The smallest atom of cull.
NodePath get_node_path() const
Constructs and returns an actual NodePath that represents the same path we have just traversed...
This is a 4-by-4 transform matrix.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
NurbsCurveEvaluator * get_curve() const
Returns the curve represented by the RopeNode.
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
UVMode get_uv_mode() const
Returns the algorithm to use to generate UV's for the rope.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
bool get_use_vertex_color() const
Returns the "use vertex color" flag.
virtual PandaNode * make_copy() const
Returns a newly-allocated Node that is a shallow copy of this one.
bool set_num_rows(int n)
Sets the length of the array to n rows in all of the various arrays (presumably by adding rows)...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
void get_vertices(Vert4Array &verts, const NodePath &rel_to) const
Fills the indicated vector with the set of vertices in the curve, transformed to the given space...
Defines a series of disconnected line segments.
static void register_with_read_factory()
Tells the BamReader how to create objects of type RopeNode.
bool has_matrix() const
Returns true if the node has a matrix set, false otherwise.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
void reset_bound(const NodePath &rel_to)
Recomputes the bounding volume.
A thread; that is, a lightweight process.
bool almost_equal(const LVecBase3f &other, float threshold) const
Returns true if two vectors are memberwise equal within a specified tolerance.
static int get_vertex_thickness_dimension()
Returns the numeric extended dimension in which the thickness component should be found...
static LMatrix3f rotate_mat(float angle)
Returns a matrix that rotates by the given angle in degrees counterclockwise.
Specifies how polygons are to be drawn.
bool get_use_vertex_thickness() const
Returns the "use vertex thickness" flag.
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
A class to retrieve the individual data elements previously stored in a Datagram. ...
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_subdiv() const
Returns the number of subdivisions per cubic segment to draw.
TypeHandle is the identifier used to differentiate C++ class types.
This is a 3-by-3 transform matrix.
bool normalize()
Normalizes the vector in place.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
PN_stdfloat get_segment_t(int segment, PN_stdfloat t) const
Accepts a t value in the range [0, 1], and assumed to be relative to the indicated segment (as in eva...
bool around(const GeometricBoundingVolume **first, const GeometricBoundingVolume **last)
Resets the volume to enclose only the volumes indicated.
The result of a NurbsCurveEvaluator.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
static int get_vertex_color_dimension()
Returns the numeric extended dimension in which the color components should be found.
PN_stdfloat get_thickness() const
Returns the thickness of the rope.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
int get_pipeline_stage() const
Returns the Pipeline stage number associated with this thread.
int get_num_rows() const
Returns the number of rows stored within all the arrays.