From e7aae0ca54038214aa7236a9cfb37405889b3475 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 5 Dec 2002 17:55:22 +0000 Subject: [PATCH] early pass on RopeNode --- panda/src/parametrics/Sources.pp | 7 +- panda/src/parametrics/config_parametrics.cxx | 3 + panda/src/parametrics/nurbsCurveEvaluator.h | 3 +- panda/src/parametrics/nurbsCurveResult.I | 40 +++ panda/src/parametrics/nurbsCurveResult.cxx | 39 ++- panda/src/parametrics/nurbsCurveResult.h | 9 +- .../parametrics/parametrics_composite2.cxx | 1 + panda/src/parametrics/ropeNode.I | 88 ++++++ panda/src/parametrics/ropeNode.cxx | 262 ++++++++++++++++++ panda/src/parametrics/ropeNode.h | 109 ++++++++ 10 files changed, 532 insertions(+), 29 deletions(-) create mode 100644 panda/src/parametrics/ropeNode.I create mode 100644 panda/src/parametrics/ropeNode.cxx create mode 100644 panda/src/parametrics/ropeNode.h diff --git a/panda/src/parametrics/Sources.pp b/panda/src/parametrics/Sources.pp index cc4c98c480..e0125cb7b7 100644 --- a/panda/src/parametrics/Sources.pp +++ b/panda/src/parametrics/Sources.pp @@ -24,6 +24,7 @@ parametricCurve.h \ parametricCurveCollection.I parametricCurveCollection.h \ piecewiseCurve.h \ + ropeNode.I ropeNode.h \ $[if $[HAVE_NURBSPP], nurbsPPCurve.cxx nurbsPPCurve.h] @@ -37,7 +38,8 @@ nurbsMatrixVector.cxx \ nurbsVertex.cxx \ parametricCurve.cxx parametricCurveCollection.cxx \ - piecewiseCurve.cxx + piecewiseCurve.cxx \ + ropeNode.cxx #define INSTALL_HEADERS \ classicNurbsCurve.I classicNurbsCurve.h \ @@ -56,7 +58,8 @@ nurbsPPCurve.h \ parametricCurve.h \ parametricCurveCollection.I parametricCurveCollection.h \ - piecewiseCurve.h + piecewiseCurve.h \ + ropeNode.I ropeNode.h #define IGATESCAN all diff --git a/panda/src/parametrics/config_parametrics.cxx b/panda/src/parametrics/config_parametrics.cxx index c73c1b0354..603c6962fd 100644 --- a/panda/src/parametrics/config_parametrics.cxx +++ b/panda/src/parametrics/config_parametrics.cxx @@ -26,6 +26,7 @@ #include "parametricCurve.h" #include "parametricCurveDrawer.h" #include "piecewiseCurve.h" +#include "ropeNode.h" #ifdef HAVE_NURBSPP #include "nurbsPPCurve.h" @@ -46,6 +47,7 @@ ConfigureFn(config_parametrics) { ParametricCurve::init_type(); ParametricCurveDrawer::init_type(); PiecewiseCurve::init_type(); + RopeNode::init_type(); #ifdef HAVE_NURBSPP NurbsPPCurve::init_type(); @@ -55,6 +57,7 @@ ConfigureFn(config_parametrics) { ClassicNurbsCurve::register_with_read_factory(); CubicCurveseg::register_with_read_factory(); HermiteCurve::register_with_read_factory(); + RopeNode::register_with_read_factory(); } const DSearchPath & diff --git a/panda/src/parametrics/nurbsCurveEvaluator.h b/panda/src/parametrics/nurbsCurveEvaluator.h index 20425247de..857c26305d 100644 --- a/panda/src/parametrics/nurbsCurveEvaluator.h +++ b/panda/src/parametrics/nurbsCurveEvaluator.h @@ -27,6 +27,7 @@ #include "vector_float.h" #include "pvector.h" #include "nodePath.h" +#include "referenceCount.h" //////////////////////////////////////////////////////////////////// // Class : NurbsCurveEvaluator @@ -43,7 +44,7 @@ // eventually replace the whole ParametricCurve class // hierarchy. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA NurbsCurveEvaluator { +class EXPCL_PANDA NurbsCurveEvaluator : public ReferenceCount { PUBLISHED: NurbsCurveEvaluator(); ~NurbsCurveEvaluator(); diff --git a/panda/src/parametrics/nurbsCurveResult.I b/panda/src/parametrics/nurbsCurveResult.I index fa051d040f..9f4ffb3112 100644 --- a/panda/src/parametrics/nurbsCurveResult.I +++ b/panda/src/parametrics/nurbsCurveResult.I @@ -17,6 +17,15 @@ //////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveResult::Destructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE NurbsCurveResult:: +~NurbsCurveResult() { +} + //////////////////////////////////////////////////////////////////// // Function: NurbsCurveResult::get_start_t // Access: Public @@ -37,3 +46,34 @@ INLINE float NurbsCurveResult:: get_end_t() const { return _prod.get_end_t(); } + +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveResult::eval_point +// Access: Published +// Description: Computes the point on the curve corresponding to the +// indicated value in parametric time. Returns true if +// the t value is value, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool NurbsCurveResult:: +eval_point(float t, LPoint3f &point) { + int segment = find_segment(t); + if (segment == -1) { + return false; + } + + eval_segment_point(segment, _prod.scale_t(segment, t), point); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveResult::get_num_segments +// Access: Public +// Description: Returns the number of piecewise continuous segments +// within the curve. This number is usually not +// important unless you plan to call +// eval_segment_point(). +//////////////////////////////////////////////////////////////////// +INLINE int NurbsCurveResult:: +get_num_segments() const { + return _prod.get_num_segments(); +} diff --git a/panda/src/parametrics/nurbsCurveResult.cxx b/panda/src/parametrics/nurbsCurveResult.cxx index 0e80702062..e5341b8717 100644 --- a/panda/src/parametrics/nurbsCurveResult.cxx +++ b/panda/src/parametrics/nurbsCurveResult.cxx @@ -55,36 +55,31 @@ NurbsCurveResult(const NurbsMatrixVector &basis, int order, } //////////////////////////////////////////////////////////////////// -// Function: NurbsCurveResult::Destructor +// Function: NurbsCurveResult::eval_segment_point // Access: Published -// Description: +// Description: Evaluates the point on the curve corresponding to the +// indicated value in parametric time within the +// indicated curve segment. t should be in the range +// [0, 1]. +// +// The curve is internally represented as a number of +// connected (or possibly unconnected) piecewise +// continuous segments. The exact number of segments +// for a particular curve depends on the knot vector, +// and is returned by get_num_segments(). Normally, +// eval_point() is used to evaluate a point along the +// continuous curve, but when you care more about local +// continuity, you can use eval_segment_point() to +// evaluate the points along each segment. //////////////////////////////////////////////////////////////////// -NurbsCurveResult:: -~NurbsCurveResult() { -} - -//////////////////////////////////////////////////////////////////// -// Function: NurbsCurveResult::eval_point -// Access: Published -// Description: Computes the point on the curve corresponding to the -// indicated value in parametric time. Returns true if -// the t value is value, false otherwise. -//////////////////////////////////////////////////////////////////// -bool NurbsCurveResult:: -eval_point(float t, LPoint3f &point) { - int segment = find_segment(t); - if (segment == -1) { - return false; - } - - t = _prod.scale_t(segment, t); +void NurbsCurveResult:: +eval_segment_point(int segment, float t, LPoint3f &point) const { const LMatrix4f &mat = _prod.get_matrix(segment); float t2 = t*t; LVecBase4f tvec(t*t2, t2, t, 1.0f); LVecBase4f r = tvec * mat; point.set(r[0] / r[3], r[1] / r[3], r[2] / r[3]); - return true; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/parametrics/nurbsCurveResult.h b/panda/src/parametrics/nurbsCurveResult.h index 73f9e48595..5c3fe17f95 100644 --- a/panda/src/parametrics/nurbsCurveResult.h +++ b/panda/src/parametrics/nurbsCurveResult.h @@ -43,12 +43,15 @@ public: const LVecBase4f verts[], int num_vertices); PUBLISHED: - ~NurbsCurveResult(); + INLINE ~NurbsCurveResult(); INLINE float get_start_t() const; INLINE float get_end_t() const; - bool eval_point(float t, LPoint3f &point); + INLINE bool eval_point(float t, LPoint3f &point); + + INLINE int get_num_segments() const; + void eval_segment_point(int segment, float t, LPoint3f &point) const; private: int find_segment(float t); @@ -59,8 +62,6 @@ private: int _last_segment; float _last_from; float _last_to; - - friend class NurbsCurveEvaluator; }; #include "nurbsCurveResult.I" diff --git a/panda/src/parametrics/parametrics_composite2.cxx b/panda/src/parametrics/parametrics_composite2.cxx index 194fa3028f..e3a359014a 100644 --- a/panda/src/parametrics/parametrics_composite2.cxx +++ b/panda/src/parametrics/parametrics_composite2.cxx @@ -7,3 +7,4 @@ #include "nurbsCurveResult.cxx" #include "nurbsMatrixVector.cxx" #include "nurbsVertex.cxx" +#include "ropeNode.cxx" diff --git a/panda/src/parametrics/ropeNode.I b/panda/src/parametrics/ropeNode.I new file mode 100644 index 0000000000..23b2e6c1db --- /dev/null +++ b/panda/src/parametrics/ropeNode.I @@ -0,0 +1,88 @@ +// Filename: ropeNode.I +// Created by: drose (04Dec02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::CData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE RopeNode::CData:: +CData() { + _curve = new NurbsCurveEvaluator; + _num_segs = 10; +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::CData::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE RopeNode::CData:: +CData(const RopeNode::CData ©) : + _curve(copy._curve) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: set_curve +// Access: Public +// Description: Sets the particular curve represented by the +// RopeNode. +//////////////////////////////////////////////////////////////////// +INLINE void RopeNode:: +set_curve(NurbsCurveEvaluator *curve) { + CDWriter cdata(_cycler); + cdata->_curve = curve; +} + +//////////////////////////////////////////////////////////////////// +// Function: get_curve +// Access: Public +// Description: Returns the curve represented by the RopeNode. +//////////////////////////////////////////////////////////////////// +INLINE NurbsCurveEvaluator *RopeNode:: +get_curve() const { + CDReader cdata(_cycler); + return cdata->_curve; +} + +//////////////////////////////////////////////////////////////////// +// Function: set_num_segs +// Access: Public +// Description: Specifies the number of segments per cubic segment +// (that is, per unique knot value) to draw in a fixed +// uniform tesselation of the curve. +//////////////////////////////////////////////////////////////////// +INLINE void RopeNode:: +set_num_segs(int num_segs) { + CDWriter cdata(_cycler); + cdata->_num_segs = num_segs; +} + +//////////////////////////////////////////////////////////////////// +// Function: get_num_segs +// Access: Public +// Description: Returns the number of segments per cubic segment to +// draw. See set_num_segs(). +//////////////////////////////////////////////////////////////////// +INLINE int RopeNode:: +get_num_segs() const { + CDReader cdata(_cycler); + return cdata->_num_segs; +} diff --git a/panda/src/parametrics/ropeNode.cxx b/panda/src/parametrics/ropeNode.cxx new file mode 100644 index 0000000000..f5eb75ca31 --- /dev/null +++ b/panda/src/parametrics/ropeNode.cxx @@ -0,0 +1,262 @@ +// Filename: ropeNode.cxx +// Created by: drose (04Dec02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "ropeNode.h" +#include "cullTraverser.h" +#include "cullTraverserData.h" +#include "cullableObject.h" +#include "cullHandler.h" +#include "bamWriter.h" +#include "bamReader.h" +#include "datagram.h" +#include "datagramIterator.h" + +TypeHandle RopeNode::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::CData::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CycleData *RopeNode::CData:: +make_copy() const { + return new CData(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::CData::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void RopeNode::CData:: +write_datagram(BamWriter *writer, Datagram &dg) const { + // For now, we write a NULL pointer. Eventually we will write out + // the NurbsCurveEvaluator pointer. + writer->write_pointer(dg, (TypedWritable *)NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::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 RopeNode. +//////////////////////////////////////////////////////////////////// +void RopeNode::CData:: +fillin(DatagramIterator &scan, BamReader *reader) { + // For now, we skip over the NULL pointer that we wrote out. + reader->skip_pointer(scan); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +RopeNode:: +RopeNode(const string &name) : + PandaNode(name) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::Copy Constructor +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +RopeNode:: +RopeNode(const RopeNode ©) : + PandaNode(copy), + _cycler(copy._cycler) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::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 *RopeNode:: +make_copy() const { + return new RopeNode(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::safe_to_transform +// Access: Public, Virtual +// Description: Returns true if it is generally safe to transform +// this particular kind of Node by calling the xform() +// method, false otherwise. For instance, it's usually +// a bad idea to attempt to xform a RopeNode. +//////////////////////////////////////////////////////////////////// +bool RopeNode:: +safe_to_transform() const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::has_cull_callback +// Access: Public, Virtual +// Description: Should be overridden by derived classes to return +// true if cull_callback() has been defined. Otherwise, +// returns false to indicate cull_callback() does not +// need to be called for this node during the cull +// traversal. +//////////////////////////////////////////////////////////////////// +bool RopeNode:: +has_cull_callback() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::cull_callback +// Access: Public, Virtual +// Description: If has_cull_callback() returns true, 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. +// +// 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 RopeNode:: +cull_callback(CullTraverser *trav, CullTraverserData &data) { + cerr << "cull_callback\n"; + + // Create a new linestrip on-the-fly to render the rope. + PT(Geom) geom = new GeomLinestrip; + PTA_Vertexf verts; + PTA_int lengths; + + NurbsCurveEvaluator *curve = get_curve(); + PT(NurbsCurveResult) result = curve->evaluate(data._node_path.get_node_path()); + + int num_segments = result->get_num_segments(); + int num_segs = get_num_segs(); + for (int segment = 0; segment < num_segments; segment++) { + cerr << "\nsegment " << segment << "\n"; + for (int i = 0; i < num_segs; i++) { + float t = (float)i / (float)(num_segs - 1); + LPoint3f point; + result->eval_segment_point(segment, t, point); + verts.push_back(point); + cerr << " p " << point << "\n"; + } + lengths.push_back(num_segs); + } + + geom->set_num_prims(num_segments); + geom->set_coords(verts); + geom->set_lengths(lengths); + + CullableObject *object = new CullableObject(geom, data._state, + data._render_transform); + trav->get_cull_handler()->record_object(object); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void RopeNode:: +output(ostream &out) const { + PandaNode::output(out); + out << " " << get_curve(); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void RopeNode:: +write(ostream &out, int indent_level) const { + PandaNode::write(out, indent_level); + indent(out, indent_level) << get_curve() << "\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::register_with_read_factory +// Access: Public, Static +// Description: Tells the BamReader how to create objects of type +// RopeNode. +//////////////////////////////////////////////////////////////////// +void RopeNode:: +register_with_read_factory() { + BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::write_datagram +// Access: Public, Virtual +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void RopeNode:: +write_datagram(BamWriter *manager, Datagram &dg) { + PandaNode::write_datagram(manager, dg); + manager->write_cdata(dg, _cycler); +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::make_from_bam +// Access: Protected, Static +// Description: This function is called by the BamReader's factory +// when a new object of type RopeNode is encountered +// in the Bam file. It should create the RopeNode +// and extract its information from the file. +//////////////////////////////////////////////////////////////////// +TypedWritable *RopeNode:: +make_from_bam(const FactoryParams ¶ms) { + RopeNode *node = new RopeNode(""); + DatagramIterator scan; + BamReader *manager; + + parse_params(params, scan, manager); + node->fillin(scan, manager); + + return node; +} + +//////////////////////////////////////////////////////////////////// +// Function: RopeNode::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 RopeNode. +//////////////////////////////////////////////////////////////////// +void RopeNode:: +fillin(DatagramIterator &scan, BamReader *manager) { + PandaNode::fillin(scan, manager); + manager->read_cdata(scan, _cycler); +} diff --git a/panda/src/parametrics/ropeNode.h b/panda/src/parametrics/ropeNode.h new file mode 100644 index 0000000000..d62bfb049f --- /dev/null +++ b/panda/src/parametrics/ropeNode.h @@ -0,0 +1,109 @@ +// Filename: ropeNode.h +// Created by: drose (04Dec02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, 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://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef ROPENODE_H +#define ROPENODE_H + +#include "pandabase.h" +#include "nurbsCurveEvaluator.h" +#include "pandaNode.h" + +//////////////////////////////////////////////////////////////////// +// Class : RopeNode +// Description : This class draws a visible representation of the +// NURBS curve stored in its NurbsCurveEvaluator. It +// automatically recomputes the curve every frame. +// +// This is not related to NurbsCurve, ClassicNurbsCurve, +// CubicCurveseg or any of the ParametricCurve-derived +// objects in this module. It is a completely parallel +// implementation of NURBS curves, and will probably +// eventually replace the whole ParametricCurve class +// hierarchy. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA RopeNode : public PandaNode { +PUBLISHED: + RopeNode(const string &name); + +protected: + RopeNode(const RopeNode ©); +public: + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level = 0) const; + + virtual PandaNode *make_copy() const; + + virtual bool safe_to_transform() const; + virtual bool has_cull_callback() const; + virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); + +PUBLISHED: + INLINE void set_curve(NurbsCurveEvaluator *curve); + INLINE NurbsCurveEvaluator *get_curve() const; + + INLINE void set_num_segs(int num_segs); + INLINE int get_num_segs() const; + + +private: + // This is the data that must be cycled between pipeline stages. + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + PT(NurbsCurveEvaluator) _curve; + int _num_segs; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + +public: + static void register_with_read_factory(); + virtual void write_datagram(BamWriter *manager, Datagram &dg); + +protected: + static TypedWritable *make_from_bam(const FactoryParams ¶ms); + void fillin(DatagramIterator &scan, BamReader *manager); + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + PandaNode::init_type(); + register_type(_type_handle, "RopeNode", + PandaNode::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "ropeNode.I" + +#endif