144 lines
4.9 KiB
C++
144 lines
4.9 KiB
C++
/**
|
|
* PANDA 3D SOFTWARE
|
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
|
*
|
|
* All use of this software is subject to the terms of the revised BSD
|
|
* license. You should have received a copy of this license along
|
|
* with this source code in a file named "LICENSE."
|
|
*
|
|
* @file cubicCurveseg.h
|
|
* @author drose
|
|
* @date 2001-03-04
|
|
*/
|
|
|
|
#ifndef CUBICCURVESEG_H
|
|
#define CUBICCURVESEG_H
|
|
|
|
#include "pandabase.h"
|
|
|
|
#include "parametricCurve.h"
|
|
|
|
|
|
// These symbols are used to define the shape of the curve segment to
|
|
// CubicCurveseg::compute_seg().
|
|
|
|
#define RT_POINT 0x01
|
|
#define RT_TANGENT 0x02
|
|
#define RT_CV 0x03
|
|
#define RT_BASE_TYPE 0xff
|
|
|
|
#define RT_KEEP_ORIG 0x100
|
|
|
|
|
|
/**
|
|
* A CubicCurveseg is any curve that can be completely described by four
|
|
* 4-valued basis vectors, one for each dimension in three-space, and one for
|
|
* the homogeneous coordinate. This includes Beziers, Hermites, and NURBS.
|
|
*
|
|
* This class encapsulates a single curve segment of the cubic curve.
|
|
* Normally, when we think of Bezier and Hermite curves, we think of a
|
|
* piecewise collection of such segments.
|
|
*
|
|
* Although this class includes methods such as hermite_basis() and
|
|
* nurbs_basis(), to generate a Hermite and NURBS curve segment, respectively,
|
|
* only the final basis vectors are stored: the product of the basis matrix of
|
|
* the corresponding curve type, and its geometry vectors. This is the
|
|
* minimum information needed to evaluate the curve. However, the individual
|
|
* CV's that were used to compute these basis vectors are not retained; this
|
|
* might be handled in a subclass (for instance, HermiteCurve).
|
|
*/
|
|
class EXPCL_PANDA_PARAMETRICS CubicCurveseg : public ParametricCurve {
|
|
PUBLISHED:
|
|
virtual bool get_point(PN_stdfloat t, LVecBase3 &point) const;
|
|
virtual bool get_tangent(PN_stdfloat t, LVecBase3 &tangent) const;
|
|
virtual bool get_pt(PN_stdfloat t, LVecBase3 &point, LVecBase3 &tangent) const;
|
|
virtual bool get_2ndtangent(PN_stdfloat t, LVecBase3 &tangent2) const;
|
|
|
|
public:
|
|
CubicCurveseg();
|
|
CubicCurveseg(const LMatrix4 &basis);
|
|
CubicCurveseg(const BezierSeg &seg);
|
|
CubicCurveseg(int order, const PN_stdfloat knots[], const LVecBase4 cvs[]);
|
|
|
|
virtual ~CubicCurveseg();
|
|
|
|
void hermite_basis(const HermiteCurveCV &cv0,
|
|
const HermiteCurveCV &cv1,
|
|
PN_stdfloat tlength = 1.0f);
|
|
void bezier_basis(const BezierSeg &seg);
|
|
void nurbs_basis(int order, const PN_stdfloat knots[], const LVecBase4 cvs[]);
|
|
|
|
/*
|
|
* evaluate_point() and evaluate_vector() both evaluate the curve at a given
|
|
* point by applying the basis vector against the vector [t3 t2 t 1] (or some
|
|
* derivative). The difference between the two is that evaluate_point() is
|
|
* called only with the vector [t3 t2 t 1] and computes a point in three-space
|
|
* and will scale by the homogeneous coordinate when the curve demands it
|
|
* (e.g. a NURBS), while evaluate_vector() is called with some derivative
|
|
* vector like [3t2 2t 1 0] and computes a vector difference between points,
|
|
* and will never scale by the homogeneous coordinate (which would be zero
|
|
* anyway).
|
|
*/
|
|
|
|
void evaluate_point(const LVecBase4 &tv, LVecBase3 &result) const {
|
|
PN_stdfloat recip_h = (rational) ? 1.0f/tv.dot(Bw) : 1.0f;
|
|
result.set(tv.dot(Bx) * recip_h,
|
|
tv.dot(By) * recip_h,
|
|
tv.dot(Bz) * recip_h);
|
|
}
|
|
|
|
void evaluate_vector(const LVecBase4 &tv, LVecBase3 &result) const {
|
|
result.set(tv.dot(Bx),
|
|
tv.dot(By),
|
|
tv.dot(Bz));
|
|
}
|
|
|
|
virtual bool get_bezier_seg(BezierSeg &seg) const;
|
|
|
|
static bool compute_seg(int rtype0, PN_stdfloat t0, const LVecBase4 &v0,
|
|
int rtype1, PN_stdfloat t1, const LVecBase4 &v1,
|
|
int rtype2, PN_stdfloat t2, const LVecBase4 &v2,
|
|
int rtype3, PN_stdfloat t3, const LVecBase4 &v3,
|
|
const LMatrix4 &B,
|
|
const LMatrix4 &Bi,
|
|
LMatrix4 &G);
|
|
|
|
LVecBase4 Bx, By, Bz, Bw;
|
|
bool rational;
|
|
|
|
|
|
// TypedWritable stuff
|
|
public:
|
|
static void register_with_read_factory();
|
|
|
|
protected:
|
|
static TypedWritable *make_CubicCurveseg(const FactoryParams ¶ms);
|
|
virtual void write_datagram(BamWriter *manager, Datagram &me);
|
|
void fillin(DatagramIterator &scan, BamReader *manager);
|
|
|
|
public:
|
|
static TypeHandle get_class_type() {
|
|
return _type_handle;
|
|
}
|
|
static void init_type() {
|
|
ParametricCurve::init_type();
|
|
register_type(_type_handle, "CubicCurveseg",
|
|
ParametricCurve::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;
|
|
};
|
|
|
|
// This function is used internally to build the NURBS basis matrix based on a
|
|
// given knot sequence.
|
|
void compute_nurbs_basis(int order,
|
|
const PN_stdfloat knots_in[],
|
|
LMatrix4 &basis);
|
|
|
|
|
|
#endif
|