Panda3D
|
00001 // Filename: cubicCurveseg.h 00002 // Created by: drose (04Mar01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef CUBICCURVESEG_H 00016 #define CUBICCURVESEG_H 00017 00018 #include "pandabase.h" 00019 00020 #include "parametricCurve.h" 00021 00022 00023 // These symbols are used to define the shape of the curve segment to 00024 // CubicCurveseg::compute_seg(). 00025 00026 #define RT_POINT 0x01 00027 #define RT_TANGENT 0x02 00028 #define RT_CV 0x03 00029 #define RT_BASE_TYPE 0xff 00030 00031 #define RT_KEEP_ORIG 0x100 00032 00033 00034 //////////////////////////////////////////////////////////////////// 00035 // Class : CubicCurveseg 00036 // Description : A CubicCurveseg is any curve that can be completely 00037 // described by four 4-valued basis vectors, one for 00038 // each dimension in three-space, and one for the 00039 // homogeneous coordinate. This includes Beziers, 00040 // Hermites, and NURBS. 00041 // 00042 // This class encapsulates a single curve segment of the 00043 // cubic curve. Normally, when we think of Bezier and 00044 // Hermite curves, we think of a piecewise collection of 00045 // such segments. 00046 // 00047 // Although this class includes methods such as 00048 // hermite_basis() and nurbs_basis(), to generate a 00049 // Hermite and NURBS curve segment, respectively, only 00050 // the final basis vectors are stored: the product of 00051 // the basis matrix of the corresponding curve type, and 00052 // its geometry vectors. This is the minimum 00053 // information needed to evaluate the curve. However, 00054 // the individual CV's that were used to compute these 00055 // basis vectors are not retained; this might be handled 00056 // in a subclass (for instance, HermiteCurve). 00057 //////////////////////////////////////////////////////////////////// 00058 class EXPCL_PANDA_PARAMETRICS CubicCurveseg : public ParametricCurve { 00059 PUBLISHED: 00060 virtual bool get_point(PN_stdfloat t, LVecBase3 &point) const; 00061 virtual bool get_tangent(PN_stdfloat t, LVecBase3 &tangent) const; 00062 virtual bool get_pt(PN_stdfloat t, LVecBase3 &point, LVecBase3 &tangent) const; 00063 virtual bool get_2ndtangent(PN_stdfloat t, LVecBase3 &tangent2) const; 00064 00065 public: 00066 CubicCurveseg(); 00067 CubicCurveseg(const LMatrix4 &basis); 00068 CubicCurveseg(const BezierSeg &seg); 00069 CubicCurveseg(int order, const PN_stdfloat knots[], const LVecBase4 cvs[]); 00070 00071 virtual ~CubicCurveseg(); 00072 00073 void hermite_basis(const HermiteCurveCV &cv0, 00074 const HermiteCurveCV &cv1, 00075 PN_stdfloat tlength = 1.0f); 00076 void bezier_basis(const BezierSeg &seg); 00077 void nurbs_basis(int order, const PN_stdfloat knots[], const LVecBase4 cvs[]); 00078 00079 // evaluate_point() and evaluate_vector() both evaluate the curve at 00080 // a given point by applying the basis vector against the vector 00081 // [t3 t2 t 1] (or some derivative). The difference between the 00082 // two is that evaluate_point() is called only with the vector 00083 // [t3 t2 t 1] and computes a point in three-space and will scale by 00084 // the homogeneous coordinate when the curve demands it (e.g. a 00085 // NURBS), while evaluate_vector() is called with some derivative 00086 // vector like [3t2 2t 1 0] and computes a vector difference between 00087 // points, and will never scale by the homogeneous coordinate (which 00088 // would be zero anyway). 00089 00090 void evaluate_point(const LVecBase4 &tv, LVecBase3 &result) const { 00091 PN_stdfloat recip_h = (rational) ? 1.0f/tv.dot(Bw) : 1.0f; 00092 result.set(tv.dot(Bx) * recip_h, 00093 tv.dot(By) * recip_h, 00094 tv.dot(Bz) * recip_h); 00095 } 00096 00097 void evaluate_vector(const LVecBase4 &tv, LVecBase3 &result) const { 00098 result.set(tv.dot(Bx), 00099 tv.dot(By), 00100 tv.dot(Bz)); 00101 } 00102 00103 virtual bool get_bezier_seg(BezierSeg &seg) const; 00104 00105 static bool compute_seg(int rtype0, PN_stdfloat t0, const LVecBase4 &v0, 00106 int rtype1, PN_stdfloat t1, const LVecBase4 &v1, 00107 int rtype2, PN_stdfloat t2, const LVecBase4 &v2, 00108 int rtype3, PN_stdfloat t3, const LVecBase4 &v3, 00109 const LMatrix4 &B, 00110 const LMatrix4 &Bi, 00111 LMatrix4 &G); 00112 00113 LVecBase4 Bx, By, Bz, Bw; 00114 bool rational; 00115 00116 00117 // TypedWritable stuff 00118 public: 00119 static void register_with_read_factory(); 00120 00121 protected: 00122 static TypedWritable *make_CubicCurveseg(const FactoryParams ¶ms); 00123 virtual void write_datagram(BamWriter *manager, Datagram &me); 00124 void fillin(DatagramIterator &scan, BamReader *manager); 00125 00126 public: 00127 static TypeHandle get_class_type() { 00128 return _type_handle; 00129 } 00130 static void init_type() { 00131 ParametricCurve::init_type(); 00132 register_type(_type_handle, "CubicCurveseg", 00133 ParametricCurve::get_class_type()); 00134 } 00135 virtual TypeHandle get_type() const { 00136 return get_class_type(); 00137 } 00138 virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 00139 00140 private: 00141 static TypeHandle _type_handle; 00142 }; 00143 00144 // This function is used internally to build the NURBS basis matrix 00145 // based on a given knot sequence. 00146 void compute_nurbs_basis(int order, 00147 const PN_stdfloat knots_in[], 00148 LMatrix4 &basis); 00149 00150 00151 #endif