mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
joined from add-parametrics
This commit is contained in:
parent
7a7ba255b7
commit
386cc76544
35
panda/src/parametrics/Sources.pp
Normal file
35
panda/src/parametrics/Sources.pp
Normal file
@ -0,0 +1,35 @@
|
||||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolutil:c dtoolbase:c dtool:m
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET parametrics
|
||||
#define LOCAL_LIBS \
|
||||
grutil linmath express putil pandabase
|
||||
|
||||
#define SOURCES \
|
||||
config_parametrics.cxx config_parametrics.h \
|
||||
curve.cxx curve.h \
|
||||
curveDrawer.cxx curveDrawer.h \
|
||||
nurbsCurve.cxx nurbsCurve.h \
|
||||
nurbsCurveDrawer.cxx nurbsCurveDrawer.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_parametrics.h \
|
||||
curve.h \
|
||||
curveDrawer.h \
|
||||
nurbsCurve.h \
|
||||
nurbsCurveDrawer.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_parametrics
|
||||
#define LOCAL_LIBS \
|
||||
parametrics
|
||||
|
||||
#define SOURCES \
|
||||
test_parametrics.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
34
panda/src/parametrics/config_parametrics.cxx
Normal file
34
panda/src/parametrics/config_parametrics.cxx
Normal file
@ -0,0 +1,34 @@
|
||||
// Filename: config_parametrics.cxx
|
||||
// Created by: drose (19Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_parametrics.h"
|
||||
#include "luse.h"
|
||||
#include "typedWriteableReferenceCount.h"
|
||||
#include "namable.h"
|
||||
#include "curve.h"
|
||||
#include "curveDrawer.h"
|
||||
#include "nurbsCurve.h"
|
||||
#include "nurbsCurveDrawer.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
#include <get_config_path.h>
|
||||
|
||||
Configure(config_parametrics);
|
||||
NotifyCategoryDef(parametrics, "");
|
||||
|
||||
ConfigureFn(config_parametrics) {
|
||||
ParametricCurve::init_type();
|
||||
PiecewiseCurve::init_type();
|
||||
CubicCurveseg::init_type();
|
||||
ParametricCurveDrawer::init_type();
|
||||
NurbsCurve::init_type();
|
||||
NurbsCurveDrawer::init_type();
|
||||
}
|
||||
|
||||
const DSearchPath &
|
||||
get_parametrics_path() {
|
||||
static DSearchPath *parametrics_path = NULL;
|
||||
return get_config_path("parametrics-path", parametrics_path);
|
||||
}
|
14
panda/src/parametrics/config_parametrics.h
Normal file
14
panda/src/parametrics/config_parametrics.h
Normal file
@ -0,0 +1,14 @@
|
||||
// Filename: config_parametrics.h
|
||||
// Created by: drose (19Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_PARAMETRICS_H
|
||||
#define CONFIG_PARAMETRICS_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <notifyCategoryProxy.h>
|
||||
|
||||
NotifyCategoryDecl(parametrics, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
||||
#endif
|
1597
panda/src/parametrics/curve.cxx
Normal file
1597
panda/src/parametrics/curve.cxx
Normal file
File diff suppressed because it is too large
Load Diff
402
panda/src/parametrics/curve.h
Normal file
402
panda/src/parametrics/curve.h
Normal file
@ -0,0 +1,402 @@
|
||||
// Filename: curve.h
|
||||
// Created by: drose (14Mar97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
#ifndef CURVE_H
|
||||
#define CURVE_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include <typedef.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#include "typedWriteableReferenceCount.h"
|
||||
#include "namable.h"
|
||||
#include "luse.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Defines
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Parametric curve semantic types. A parametric curve may have one
|
||||
// of these types specified. These serve as hints to the egg reader
|
||||
// and writer code about the intention of this curve, and have no
|
||||
// other effect on the curve.
|
||||
|
||||
BEGIN_PUBLISH //[
|
||||
#define PCT_NONE 0
|
||||
// Unspecified type.
|
||||
|
||||
#define PCT_XYZ 1
|
||||
// A three-dimensional curve in space.
|
||||
|
||||
#define PCT_HPR 2
|
||||
// The curve represents Euler rotation angles.
|
||||
|
||||
#define PCT_T 3
|
||||
// A one-dimensional timewarp curve.
|
||||
END_PUBLISH //]
|
||||
|
||||
|
||||
//#define LVector3f LVector3f
|
||||
//typedef LVector3f LVector3f;
|
||||
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
class ParametricCurveDrawer;
|
||||
class HermiteCurveCV;
|
||||
class HermiteCurve;
|
||||
class NurbsCurve;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ParametricCurve
|
||||
// Description : A virtual base class for parametric curves.
|
||||
// This encapsulates all curves in 3-d space defined
|
||||
// for a single parameter t in the range [0,get_max_t()].
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ParametricCurve : public TypedWriteableReferenceCount,
|
||||
public Namable {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
PUBLISHED:
|
||||
virtual bool is_valid() const;
|
||||
|
||||
virtual double get_max_t() const;
|
||||
|
||||
void set_curve_type(int type);
|
||||
int get_curve_type() const;
|
||||
|
||||
void set_num_dimensions(int num);
|
||||
int get_num_dimensions() const;
|
||||
|
||||
float calc_length() const;
|
||||
float calc_length(double from, double to) const;
|
||||
double compute_t(double start_t, double length_offset, double guess,
|
||||
double threshold) const;
|
||||
|
||||
////bool convert_to_hermite(HermiteCurve &hc) const;
|
||||
bool convert_to_nurbs(NurbsCurve &nc) const;
|
||||
|
||||
void ascii_draw() const;
|
||||
|
||||
public:
|
||||
virtual bool get_point(double t, LVector3f &point) const=0;
|
||||
virtual bool get_tangent(double t, LVector3f &tangent) const=0;
|
||||
virtual bool get_pt(double t, LVector3f &point, LVector3f &tangent) const=0;
|
||||
virtual bool get_2ndtangent(double t, LVector3f &tangent2) const=0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions not visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
|
||||
struct BezierSeg {
|
||||
public:
|
||||
LVector3f _v[4];
|
||||
double _t;
|
||||
};
|
||||
typedef vector<BezierSeg> BezierSegs;
|
||||
|
||||
ParametricCurve();
|
||||
|
||||
virtual void write_datagram(BamWriter *, Datagram &);
|
||||
|
||||
virtual bool GetBezierSegs(BezierSegs &) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool GetBezierSeg(BezierSeg &) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void register_drawer(ParametricCurveDrawer *drawer);
|
||||
void unregister_drawer(ParametricCurveDrawer *drawer);
|
||||
|
||||
protected:
|
||||
virtual ~ParametricCurve();
|
||||
|
||||
void invalidate(double t1, double t2);
|
||||
void invalidate_all();
|
||||
|
||||
float r_calc_length(double t1, double t2,
|
||||
const LVector3f &p1, const LVector3f &p2,
|
||||
float seglength) const;
|
||||
|
||||
typedef list< ParametricCurveDrawer * > DrawerList;
|
||||
DrawerList _drawers;
|
||||
int _curve_type;
|
||||
int _num_dimensions;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
register_type(_type_handle, "ParametricCurve");
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PiecewiseCurve
|
||||
// Description : A PiecewiseCurve is a curve made up of several curve
|
||||
// segments, connected in a head-to-tail fashion. The
|
||||
// length of each curve segment in parametric space is
|
||||
// definable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA PiecewiseCurve : public ParametricCurve {
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PUBLISHED:
|
||||
virtual bool is_valid() const;
|
||||
virtual double get_max_t() const;
|
||||
|
||||
virtual bool get_point(double t, LVector3f &point) const;
|
||||
virtual bool get_tangent(double t, LVector3f &tangent) const;
|
||||
virtual bool get_pt(double t, LVector3f &point, LVector3f &tangent) const;
|
||||
virtual bool get_2ndtangent(double t, LVector3f &tangent2) const;
|
||||
|
||||
bool adjust_point(double t,
|
||||
float px, float py, float pz);
|
||||
bool adjust_tangent(double t,
|
||||
float tx, float ty, float tz);
|
||||
bool adjust_pt(double t,
|
||||
float px, float py, float pz,
|
||||
float tx, float ty, float tz);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions not visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
PiecewiseCurve();
|
||||
|
||||
int get_num_segs() const;
|
||||
|
||||
ParametricCurve *get_curveseg(int ti);
|
||||
bool insert_curveseg(int ti, ParametricCurve *seg, double tlength);
|
||||
|
||||
bool remove_curveseg(int ti);
|
||||
void remove_all_curvesegs();
|
||||
|
||||
double get_tlength(int ti) const;
|
||||
double get_tstart(int ti) const;
|
||||
double get_tend(int ti) const;
|
||||
bool set_tlength(int ti, double tlength);
|
||||
|
||||
void make_nurbs(int order, int num_cvs,
|
||||
const double knots[], const LVector4f cvs[]);
|
||||
|
||||
virtual bool GetBezierSegs(BezierSegs &bz_segs) const;
|
||||
|
||||
virtual bool
|
||||
rebuild_curveseg(int rtype0, double t0, const LVector4f &v0,
|
||||
int rtype1, double t1, const LVector4f &v1,
|
||||
int rtype2, double t2, const LVector4f &v2,
|
||||
int rtype3, double t3, const LVector4f &v3);
|
||||
|
||||
protected:
|
||||
~PiecewiseCurve();
|
||||
|
||||
bool find_curve(const ParametricCurve *&curve, double &t) const;
|
||||
double current_seg_range(double t) const;
|
||||
|
||||
class Curveseg {
|
||||
public:
|
||||
Curveseg() {}
|
||||
Curveseg(ParametricCurve *c, double t) : _curve(c), _tend(t) {}
|
||||
|
||||
int descend_pfb(void *handle);
|
||||
int store_pfb(void *handle);
|
||||
int load_pfb(void *handle);
|
||||
|
||||
ParametricCurve *_curve;
|
||||
double _tend;
|
||||
};
|
||||
|
||||
vector<Curveseg> _segs;
|
||||
int _last_ti;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ParametricCurve::init_type();
|
||||
register_type(_type_handle, "PiecewiseCurve",
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CubicCurveseg
|
||||
// Description : 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 CubicCurveseg : public ParametricCurve {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
PUBLISHED:
|
||||
virtual bool get_point(double t, LVector3f &point) const;
|
||||
virtual bool get_tangent(double t, LVector3f &tangent) const;
|
||||
virtual bool get_pt(double t, LVector3f &point, LVector3f &tangent) const;
|
||||
virtual bool get_2ndtangent(double t, LVector3f &tangent2) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions not visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
CubicCurveseg();
|
||||
CubicCurveseg(const LMatrix4f &basis);
|
||||
CubicCurveseg(const HermiteCurveCV &cv0,
|
||||
const HermiteCurveCV &cv1);
|
||||
CubicCurveseg(const BezierSeg &seg);
|
||||
CubicCurveseg(int order, const double knots[], const LVector4f cvs[]);
|
||||
|
||||
void hermite_basis(const HermiteCurveCV &cv0,
|
||||
const HermiteCurveCV &cv1,
|
||||
double tlength = 1.0);
|
||||
void bezier_basis(const BezierSeg &seg);
|
||||
void nurbs_basis(int order, const double knots[], const LVector4f 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 LVector4f &tv, LVector3f &result) const {
|
||||
double h = (rational) ? tv.dot(Bw) : 1.0;
|
||||
result.set(tv.dot(Bx) / h,
|
||||
tv.dot(By) / h,
|
||||
tv.dot(Bz) / h);
|
||||
}
|
||||
|
||||
void evaluate_vector(const LVector4f &tv, LVector3f &result) const {
|
||||
result.set(tv.dot(Bx),
|
||||
tv.dot(By),
|
||||
tv.dot(Bz));
|
||||
}
|
||||
|
||||
virtual bool GetBezierSeg(BezierSeg &seg) const;
|
||||
|
||||
static bool compute_seg(int rtype0, double t0, const LVector4f &v0,
|
||||
int rtype1, double t1, const LVector4f &v1,
|
||||
int rtype2, double t2, const LVector4f &v2,
|
||||
int rtype3, double t3, const LVector4f &v3,
|
||||
const LMatrix4f &B,
|
||||
const LMatrix4f &Bi,
|
||||
LMatrix4f &G);
|
||||
|
||||
LVector4f Bx, By, Bz, Bw;
|
||||
bool rational;
|
||||
|
||||
protected:
|
||||
virtual ~CubicCurveseg();
|
||||
|
||||
|
||||
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 double knots_in[],
|
||||
LMatrix4f &basis);
|
||||
|
||||
|
||||
#endif
|
733
panda/src/parametrics/curveDrawer.cxx
Normal file
733
panda/src/parametrics/curveDrawer.cxx
Normal file
@ -0,0 +1,733 @@
|
||||
// Filename: curveDrawer.C
|
||||
// Created by: drose (14Mar97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "curveDrawer.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "luse.h"
|
||||
#include "parametrics.h"
|
||||
#include "typedWriteableReferenceCount.h"
|
||||
#include "namable.h"
|
||||
|
||||
|
||||
TypeHandle ParametricCurveDrawer::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::Constructor
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ParametricCurveDrawer::
|
||||
ParametricCurveDrawer(ParametricCurve *curve) {
|
||||
_curve = curve;
|
||||
_time_curve = NULL;
|
||||
_lines.set_color(1.0, 1.0, 1.0);
|
||||
_ticks.set_color(1.0, 0.0, 0.0);
|
||||
_tick_scale = 0.1;
|
||||
_num_segs = 100;
|
||||
_num_ticks = 0;
|
||||
_frame_accurate = false;
|
||||
_geom_node = new GeomNode;
|
||||
_drawn = false;
|
||||
_mapper = DefaultMap;
|
||||
_curve->register_drawer(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::Destructor
|
||||
// Access: Public, Scheme, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ParametricCurveDrawer::
|
||||
~ParametricCurveDrawer() {
|
||||
hide();
|
||||
if (_curve!=NULL) {
|
||||
_curve->unregister_drawer(this);
|
||||
}
|
||||
if (_time_curve!=NULL) {
|
||||
_time_curve->unregister_drawer(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_curve
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_curve(ParametricCurve *curve) {
|
||||
if (_curve!=NULL) {
|
||||
_curve->unregister_drawer(this);
|
||||
}
|
||||
_curve = curve;
|
||||
_curve->register_drawer(this);
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_curve
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ParametricCurve *ParametricCurveDrawer::
|
||||
get_curve() {
|
||||
return _curve;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_time_curve
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_time_curve(ParametricCurve *curve) {
|
||||
if (_time_curve!=NULL) {
|
||||
_time_curve->unregister_drawer(this);
|
||||
}
|
||||
_time_curve = curve;
|
||||
if (_time_curve!=NULL) {
|
||||
_time_curve->register_drawer(this);
|
||||
}
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_time_curve
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ParametricCurve *ParametricCurveDrawer::
|
||||
get_time_curve() {
|
||||
return _time_curve;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_geom_node
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns a pointer to the drawer's GeomNode. This is
|
||||
// where the drawer will build the visible
|
||||
// representation of the curve. This GeomNode must be
|
||||
// inserted into the scene graph to make the curve
|
||||
// visible. The GeomNode remains connected to the drawer,
|
||||
// so that future updates to the drawer will reflect in
|
||||
// the GeomNode, and the GeomNode will be emptied when the
|
||||
// drawer destructs. Also see detach_geom_node().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeomNode *ParametricCurveDrawer::
|
||||
get_geom_node() {
|
||||
return _geom_node;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::detach_geom_node
|
||||
// Access: Public, Scheme
|
||||
// Description: Detaches the GeomNode from the drawer so that the
|
||||
// drawing will remain after the death of the drawer.
|
||||
// Returns the now-static GeomNode. A new, dynamic GeomNode
|
||||
// is created for the drawer's future use; get_geom_node()
|
||||
// will return this new GeomNode which will be empty until
|
||||
// the next call to draw().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeomNode *ParametricCurveDrawer::
|
||||
detach_geom_node() {
|
||||
if (!_drawn) {
|
||||
draw();
|
||||
}
|
||||
PT(GeomNode) g = _geom_node;
|
||||
_geom_node = new GeomNode;
|
||||
_drawn = false;
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_num_segs
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the number of line segments used to
|
||||
// approximate the curve for each parametric unit. This
|
||||
// just affects the visual appearance of the curve as it
|
||||
// is drawn. The total number of segments drawn for the
|
||||
// curve will be get_max_t() * get_num_segs().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_num_segs(int num_segs) {
|
||||
_num_segs = num_segs;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_num_segs
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the number of line segments used to
|
||||
// approximate the curve for each parametric unit. This
|
||||
// just affects the visual appearance of the curve as it
|
||||
// is drawn. The total number of segments drawn for the
|
||||
// curve will be get_max_t() * get_num_segs().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int ParametricCurveDrawer::
|
||||
get_num_segs() const {
|
||||
return _num_segs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_num_ticks
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the number of time tick marks drawn
|
||||
// for each unit of time. These tick marks are drawn at
|
||||
// equal increments in time to give a visual
|
||||
// approximation of speed. Specify 0 to disable drawing
|
||||
// of tick marks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_num_ticks(int num_ticks) {
|
||||
_num_ticks = num_ticks;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_num_ticks
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the number of time tick marks per unit of
|
||||
// time drawn.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int ParametricCurveDrawer::
|
||||
get_num_ticks() const {
|
||||
return _num_ticks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_color
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the color of the curve when it is drawn.
|
||||
// The default is white.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_color(float r, float g, float b) {
|
||||
_lines.set_color(r, g, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_color
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the color of the time tick marks drawn on
|
||||
// the curve. The default is red.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_tick_color(float r, float g, float b) {
|
||||
_ticks.set_color(r, g, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_frame_accurate
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies whether the curve drawn is to be
|
||||
// frame-accurate. If true, then changes made to the
|
||||
// curve dynamically after it has been drawn will be
|
||||
// reflected correctly in the render window. If false,
|
||||
// dynamic updates may be drawn before the rest of the
|
||||
// scene has updated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_frame_accurate(bool frame_accurate) {
|
||||
_frame_accurate = frame_accurate;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_frame_accurate
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns whether the curve is drawn in frame-accurate
|
||||
// mode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ParametricCurveDrawer::
|
||||
get_frame_accurate() const {
|
||||
return _frame_accurate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::draw
|
||||
// Access: Public, Scheme, Virtual
|
||||
// Description: Creates a series of line segments that approximates
|
||||
// the curve. These line segments may be made visible
|
||||
// by adding the GeomNode returned by get_geom_node() into the
|
||||
// scene graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ParametricCurveDrawer::
|
||||
draw() {
|
||||
// First, remove the old drawing, if any.
|
||||
hide();
|
||||
|
||||
// If there's no curve, draw nothing and return false.
|
||||
if (_curve==NULL || !_curve->is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, let's go to town!
|
||||
int total_segs = floor(_curve->get_max_t() * _num_segs + 0.5);
|
||||
|
||||
double scale = _curve->get_max_t() / (double)(total_segs-1);
|
||||
double t;
|
||||
LVector3f point, tangent;
|
||||
bool last_in, next_in;
|
||||
|
||||
last_in = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i<total_segs; i++) {
|
||||
t = (double)i * scale;
|
||||
|
||||
// Since we're just drawing the geometric shape of the curve, we
|
||||
// don't care at this point about the time curve.
|
||||
|
||||
next_in = _curve->get_pt(t, point, tangent);
|
||||
|
||||
LVector3f p = _mapper(point, tangent, t);
|
||||
|
||||
if (!next_in || !last_in) {
|
||||
_lines.move_to(p);
|
||||
} else {
|
||||
_lines.draw_to(p);
|
||||
}
|
||||
last_in = next_in;
|
||||
}
|
||||
|
||||
_lines.create(_geom_node, _frame_accurate);
|
||||
_drawn = true;
|
||||
|
||||
// Now draw the time tick marks.
|
||||
if (_num_ticks > 0) {
|
||||
LVector3f tangent2;
|
||||
int total_ticks = floor(_curve->get_max_t() * _num_ticks + 0.5);
|
||||
|
||||
scale = get_max_t() / (double)(total_ticks-1);
|
||||
for (i = 0; i<total_ticks; i++) {
|
||||
t = (double)i * scale;
|
||||
if (_time_curve!=NULL) {
|
||||
_time_curve->get_point(t, point);
|
||||
t = point[0];
|
||||
}
|
||||
|
||||
_curve->get_pt(t, point, tangent);
|
||||
_curve->get_2ndtangent(t, tangent2);
|
||||
|
||||
LVector3f pt = _mapper(point, tangent, t);
|
||||
LVector3f t1, t2;
|
||||
get_tick_marks(_mapper(tangent, tangent2, t + 1.0), t1, t2);
|
||||
|
||||
_ticks.move_to(pt - t1 * _tick_scale);
|
||||
_ticks.draw_to(pt + t1 * _tick_scale);
|
||||
_ticks.move_to(pt - t2 * _tick_scale);
|
||||
_ticks.draw_to(pt + t2 * _tick_scale);
|
||||
}
|
||||
_ticks.create(_geom_node, _frame_accurate);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::recompute
|
||||
// Access: Public, Scheme, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ParametricCurveDrawer::
|
||||
recompute(double t1, double t2, ParametricCurve *curve) {
|
||||
if (!_drawn || _curve==NULL || !_curve->is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool redraw_curve = true;
|
||||
|
||||
if (_time_curve!=NULL) {
|
||||
if (curve != _time_curve) {
|
||||
// If the recompute call came from the basic curve, and not from
|
||||
// the time curve, the t1 and t2 it gave us aren't the t1 and t2
|
||||
// we need. To be safe, we'll run over the whole range.
|
||||
t1 = 0.0;
|
||||
t2 = get_max_t();
|
||||
} else {
|
||||
// On the other hand, if the recompute call came from the time
|
||||
// curve, we won't be changing the curve's geometric shape at
|
||||
// all--we only need to move the tick marks.
|
||||
redraw_curve = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Scale t1 and t2 to [0, 1].
|
||||
t1 = min(max(t1 / get_max_t(), 0.0), 1.0);
|
||||
t2 = min(max(t2 / get_max_t(), 0.0), 1.0);
|
||||
|
||||
int n1, n2, i;
|
||||
double scale, t;
|
||||
LVector3f point, tangent;
|
||||
|
||||
if (redraw_curve) {
|
||||
// Compute the number of total segments we will draw. This is based
|
||||
// on the parametric length of the curve, _curve->get_max_t().
|
||||
|
||||
int total_segs = floor(_curve->get_max_t() * _num_segs + 0.5);
|
||||
|
||||
n1 = (int)floor(t1 * (total_segs-1));
|
||||
n2 = (int)ceil(t2 * (total_segs-1));
|
||||
|
||||
// This should be implied by the above t1, t2 bounds check.
|
||||
nassertr(n1>=0 && n1<total_segs, false);
|
||||
nassertr(n2>=0 && n2<total_segs, false);
|
||||
|
||||
scale = _curve->get_max_t() / (double)(total_segs-1);
|
||||
|
||||
for (i = n1; i<=n2; i++) {
|
||||
t = (double)i * scale;
|
||||
|
||||
_curve->get_pt(t, point, tangent);
|
||||
|
||||
LVector3f p = _mapper(point, tangent, t);
|
||||
_lines.set_vertex(i, p);
|
||||
}
|
||||
}
|
||||
|
||||
if (_num_ticks > 0) {
|
||||
LVector3f tangent2;
|
||||
int total_ticks = floor(_curve->get_max_t() * _num_ticks + 0.5);
|
||||
|
||||
n1 = (int)floor(t1 * (total_ticks-1));
|
||||
n2 = (int)ceil(t2 * (total_ticks-1));
|
||||
|
||||
scale = get_max_t() / (double)(total_ticks-1);
|
||||
|
||||
for (i = n1; i<=n2; i++) {
|
||||
t = (double)i * scale;
|
||||
if (_time_curve!=NULL) {
|
||||
_time_curve->get_point(t, point);
|
||||
t = point[0];
|
||||
}
|
||||
_curve->get_pt(t, point, tangent);
|
||||
_curve->get_2ndtangent(t, tangent2);
|
||||
|
||||
LVector3f pt = _mapper(point, tangent, t);
|
||||
LVector3f t1, t2;
|
||||
get_tick_marks(_mapper(tangent, tangent2, t + 1.0),
|
||||
t1, t2);
|
||||
|
||||
int ti = i * 4;
|
||||
_ticks.set_vertex(ti, pt - t1 * _tick_scale);
|
||||
_ticks.set_vertex(ti+1, pt + t1 * _tick_scale);
|
||||
_ticks.set_vertex(ti+2, pt - t2 * _tick_scale);
|
||||
_ticks.set_vertex(ti+3, pt + t2 * _tick_scale);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::hide
|
||||
// Access: Public, Scheme
|
||||
// Description: Removes the lines that were created by a previous
|
||||
// call to draw().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
hide() {
|
||||
_geom_node->clear();
|
||||
_drawn = false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_tick_scale
|
||||
// Access: Public, Scheme
|
||||
// Description: Sets the visible size of the time tick marks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_tick_scale(double scale) {
|
||||
_tick_scale = scale;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_tick_scale
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the size of the time tick marks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double ParametricCurveDrawer::
|
||||
get_tick_scale() const {
|
||||
return _tick_scale;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_graph_type
|
||||
// Access: Public, Scheme
|
||||
// Description: Selects one of a handful of pre-canned graph types
|
||||
// the drawer can represent. The default, PCD_DEFAULT,
|
||||
// draws the curve's shape in three-dimensional space;
|
||||
// other possibilites like PCD_XVST draw a graph of X(t)
|
||||
// vs. t in the Z and X axes, respectively.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_graph_type(int graph_type) {
|
||||
switch (graph_type) {
|
||||
case PCD_DEFAULT:
|
||||
set_mapper(DefaultMap);
|
||||
break;
|
||||
|
||||
case PCD_XVST:
|
||||
set_mapper(XvsT);
|
||||
break;
|
||||
|
||||
case PCD_YVST:
|
||||
set_mapper(YvsT);
|
||||
break;
|
||||
|
||||
case PCD_ZVST:
|
||||
set_mapper(ZvsT);
|
||||
break;
|
||||
|
||||
case PCD_DXVST:
|
||||
set_mapper(dXvsT);
|
||||
break;
|
||||
|
||||
case PCD_DYVST:
|
||||
set_mapper(dYvsT);
|
||||
break;
|
||||
|
||||
case PCD_DZVST:
|
||||
set_mapper(dZvsT);
|
||||
break;
|
||||
|
||||
case PCD_IXVST:
|
||||
set_mapper(iXvsT);
|
||||
break;
|
||||
|
||||
case PCD_IYVST:
|
||||
set_mapper(iYvsT);
|
||||
break;
|
||||
|
||||
default:
|
||||
parametrics_cat->warning() << "Invalid graph_type " << graph_type << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::disable
|
||||
// Access: Public
|
||||
// Description: Called by the ParametricCurve destructor to indicate
|
||||
// that a curve we are depending on has just been
|
||||
// deleted. We must no longer attempt to access this
|
||||
// curve.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
disable(ParametricCurve *curve) {
|
||||
if (curve==_time_curve) {
|
||||
_time_curve = NULL;
|
||||
} else if (curve==_curve) {
|
||||
// Hmm, the primary curve has destructed. We're useless now.
|
||||
_curve = NULL;
|
||||
hide();
|
||||
} else {
|
||||
parametrics_cat->warning()
|
||||
<< "ParametricCurveDrawer::disable() called on nonsensible curve"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::set_mapper
|
||||
// Access: Public
|
||||
// Description: This establishes the function that will be applied to
|
||||
// each point of the four-dimensional curve to translate
|
||||
// it to a three-dimensional representation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
set_mapper(LVector3fMapper *mapper) {
|
||||
// If the mapper hasn't changed, don't force a redraw.
|
||||
if (_mapper != mapper) {
|
||||
_mapper = mapper;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::DefaultMap
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function returns the X,Y,Z component of
|
||||
// each point, showing the line's three-dimensional
|
||||
// shape.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
DefaultMap(const LVector3f &point, const LVector3f &, double) {
|
||||
return LVector3f(point[0], point[1], point[2]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::XvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of X(t), with the
|
||||
// x along the Y axis and t along the X axis.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
XvsT(const LVector3f &point, const LVector3f &, double t) {
|
||||
return LVector3f(t, point[0], 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::iXvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of X(t), with the
|
||||
// x along the X axis and t along the Y axis.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
iXvsT(const LVector3f &point, const LVector3f &, double t) {
|
||||
return LVector3f(point[0], t, 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::YvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of Y(t), with the
|
||||
// y along the Y axis and t along the X axis.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
YvsT(const LVector3f &point, const LVector3f &, double t) {
|
||||
return LVector3f(t, point[1], 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::YvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of Y(t), with the
|
||||
// y along the X axis and t along the Y axis.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
iYvsT(const LVector3f &point, const LVector3f &, double t) {
|
||||
return LVector3f(point[1], t, 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::ZvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of Z(t), with the
|
||||
// z along the Y axis and t along the X axis.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
ZvsT(const LVector3f &point, const LVector3f &, double t) {
|
||||
return LVector3f(t, point[2], 0.0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::dXvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of dX(t), the
|
||||
// derivative of X(t).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
dXvsT(const LVector3f &, const LVector3f &tangent, double t) {
|
||||
return LVector3f(t, tangent[0], 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::dYvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of dY(t), the
|
||||
// derivative of Y(t).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
dYvsT(const LVector3f &, const LVector3f &tangent, double t) {
|
||||
return LVector3f(t, tangent[1], 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::dZvsT
|
||||
// Access: Public, Static
|
||||
// Description: This mapping function shows a graph of dZ(t), the
|
||||
// derivative of Z(t).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
LVector3f ParametricCurveDrawer::
|
||||
dZvsT(const LVector3f &, const LVector3f &tangent, double t) {
|
||||
return LVector3f(t, tangent[2], 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ParametricCurveDrawer::get_tick_marks
|
||||
// Access: Protected, Static
|
||||
// Description: Given a tangent vector, computes two vectors at right
|
||||
// angles to the tangent and to each other, suitable for
|
||||
// drawing as tick marks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ParametricCurveDrawer::
|
||||
get_tick_marks(const LVector3f &tangent, LVector3f &t1, LVector3f &t2) {
|
||||
LVector3f tn = tangent;
|
||||
tn.normalize();
|
||||
|
||||
// Decide the smallest axis of tn and cross with the corresponding
|
||||
// unit vector.
|
||||
if (fabs(tn[0]) <= fabs(tn[1]) && fabs(tn[0]) <= fabs(tn[2])) {
|
||||
// X is smallest.
|
||||
t1 = tn.cross(LVector3f(1.0, 0.0, 0.0));
|
||||
|
||||
} else if (fabs(tn[1]) <= fabs(tn[2])) {
|
||||
// Y is smallest.
|
||||
t1 = tn.cross(LVector3f(0.0, 1.0, 0.0));
|
||||
|
||||
} else {
|
||||
// Z is smallest.
|
||||
t1 = tn.cross(LVector3f(0.0, 0.0, 1.0));
|
||||
}
|
||||
|
||||
t2 = tn.cross(t1);
|
||||
}
|
147
panda/src/parametrics/curveDrawer.h
Normal file
147
panda/src/parametrics/curveDrawer.h
Normal file
@ -0,0 +1,147 @@
|
||||
// Filename: curveDrawer.h
|
||||
// Created by: drose (14Mar97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
#ifndef CURVEDRAWER_H
|
||||
#define CURVEDRAWER_H
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "curve.h"
|
||||
#include "lineSegs.h"
|
||||
////#include <Performer/pr/pfLinMath.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Defines
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef LVector3f LVector3fMapper(const LVector3f &point,
|
||||
const LVector3f &tangent,
|
||||
double t);
|
||||
|
||||
BEGIN_PUBLISH //[
|
||||
// The different kinds of ParametricCurveDrawer graph types
|
||||
#define PCD_DEFAULT 1
|
||||
#define PCD_XVST 2
|
||||
#define PCD_YVST 3
|
||||
#define PCD_ZVST 4
|
||||
#define PCD_DXVST 6
|
||||
#define PCD_DYVST 7
|
||||
#define PCD_DZVST 8
|
||||
#define PCD_IXVST 9
|
||||
#define PCD_IYVST 10
|
||||
END_PUBLISH //]
|
||||
|
||||
class ParametricSurface;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ParametricCurveDrawer
|
||||
// Description : Draws a 3-d parametric curve in the scene by creating
|
||||
// a series of line segments to approximate the curve.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ParametricCurveDrawer {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
PUBLISHED:
|
||||
ParametricCurveDrawer(ParametricCurve *curve);
|
||||
virtual ~ParametricCurveDrawer();
|
||||
|
||||
void set_curve(ParametricCurve *curve);
|
||||
ParametricCurve *get_curve();
|
||||
|
||||
void set_time_curve(ParametricCurve *curve);
|
||||
ParametricCurve *get_time_curve();
|
||||
|
||||
GeomNode *get_geom_node();
|
||||
GeomNode *detach_geom_node();
|
||||
|
||||
void set_num_segs(int num_segs);
|
||||
int get_num_segs() const;
|
||||
|
||||
void set_num_ticks(int num_ticks);
|
||||
int get_num_ticks() const;
|
||||
|
||||
void set_color(float r, float g, float b);
|
||||
void set_tick_color(float r, float g, float b);
|
||||
|
||||
void set_frame_accurate(bool frame_accurate);
|
||||
bool get_frame_accurate() const;
|
||||
|
||||
virtual bool draw();
|
||||
virtual bool recompute(double t1, double t2, ParametricCurve *curve=NULL);
|
||||
void hide();
|
||||
|
||||
void set_tick_scale(double scale);
|
||||
double get_tick_scale() const;
|
||||
|
||||
void set_graph_type(int graph_type);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions not visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
double get_max_t() const {
|
||||
return _time_curve==NULL ? _curve->get_max_t() : _time_curve->get_max_t();
|
||||
}
|
||||
|
||||
void disable(ParametricCurve *curve);
|
||||
|
||||
void set_mapper(LVector3fMapper *mapper);
|
||||
|
||||
static LVector3f DefaultMap(const LVector3f &point, const LVector3f &, double);
|
||||
static LVector3f XvsT(const LVector3f &point, const LVector3f &, double t);
|
||||
static LVector3f iXvsT(const LVector3f &point, const LVector3f &, double t);
|
||||
static LVector3f YvsT(const LVector3f &point, const LVector3f &, double t);
|
||||
static LVector3f iYvsT(const LVector3f &point, const LVector3f &, double t);
|
||||
static LVector3f ZvsT(const LVector3f &point, const LVector3f &, double t);
|
||||
static LVector3f dXvsT(const LVector3f &, const LVector3f &tangent, double t);
|
||||
static LVector3f dYvsT(const LVector3f &, const LVector3f &tangent, double t);
|
||||
static LVector3f dZvsT(const LVector3f &, const LVector3f &tangent, double t);
|
||||
|
||||
protected:
|
||||
static void get_tick_marks(const LVector3f &tangent, LVector3f &t1, LVector3f &t2);
|
||||
|
||||
PT(GeomNode) _geom_node;
|
||||
int _num_segs;
|
||||
ParametricCurve *_curve, *_time_curve;
|
||||
LineSegs _lines, _ticks;
|
||||
bool _drawn;
|
||||
int _num_ticks;
|
||||
double _tick_scale;
|
||||
bool _frame_accurate;
|
||||
LVector3fMapper *_mapper;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
register_type(_type_handle, "ParametricCurveDrawer");
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
896
panda/src/parametrics/nurbsCurve.cxx
Normal file
896
panda/src/parametrics/nurbsCurve.cxx
Normal file
@ -0,0 +1,896 @@
|
||||
// Filename: nurbsCurve.C
|
||||
// Created by: drose (27Feb98)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "nurbsCurve.h"
|
||||
#include "luse.h"
|
||||
#include "parametrics.h"
|
||||
////#include <initReg.h>
|
||||
////#include <linMathOutput.h>
|
||||
#include <fstream>
|
||||
////#include <alloca.h>
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Statics
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
TypeHandle NurbsCurve::_type_handle;
|
||||
|
||||
static const LVector3f zero = LVector3f(0.0, 0.0, 0.0);
|
||||
// This is returned occasionally from some of the functions, and is
|
||||
// used from time to time as an initializer.
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Indent
|
||||
// Description: This function duplicates a similar function declared
|
||||
// in eggBasics.C. It prints a specified number of
|
||||
// spaces to indent each line of output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static ostream &
|
||||
Indent(ostream &out, int indent) {
|
||||
for (int i=0; i<indent; i++) {
|
||||
out << ' ';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::Constructor
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsCurve::
|
||||
NurbsCurve() {
|
||||
_order = 4;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::Constructor
|
||||
// Access: Public, Scheme
|
||||
// Description: Constructs a NURBS curve equivalent to the indicated
|
||||
// (possibly non-NURBS) curve.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsCurve::
|
||||
NurbsCurve(const ParametricCurve &pc) {
|
||||
_order = 4;
|
||||
|
||||
if (!pc.convert_to_nurbs(*this)) {
|
||||
///DWARNING(dnparametrics)
|
||||
///<< "Cannot make a NURBS from the indicated curve."
|
||||
///<< dnend;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::Constructor
|
||||
// Access: Public
|
||||
// Description: Constructs a NURBS curve according to the indicated
|
||||
// NURBS parameters.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsCurve::
|
||||
NurbsCurve(int order, int num_cvs,
|
||||
const double knots[], const LVector4f cvs[]) {
|
||||
_order = order;
|
||||
|
||||
int i;
|
||||
_cvs.reserve(num_cvs);
|
||||
for (i = 0; i < num_cvs; i++) {
|
||||
append_cv(cvs[i]);
|
||||
}
|
||||
|
||||
int num_knots = num_cvs + order;
|
||||
for (i = 0; i < num_knots; i++) {
|
||||
set_knot(i, knots[i]);
|
||||
}
|
||||
|
||||
recompute();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::set_order
|
||||
// Access: Public, Scheme
|
||||
// Description: Changes the order of the curve. Must be a value from
|
||||
// 1 to 4. Can only be done when there are no cv's.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
set_order(int order) {
|
||||
if (order < 1 || order > 4) {
|
||||
///DWARNING(dnparametrics)
|
||||
///<< "Invalid NURBS curve order: " << order << dnend;
|
||||
return;
|
||||
}
|
||||
if (!_cvs.empty()) {
|
||||
///DWARNING(dnparametrics)
|
||||
///<< "Cannot change NURBS curve order on a nonempty curve." << dnend;
|
||||
return;
|
||||
}
|
||||
_order = order;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::get_order
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NurbsCurve::
|
||||
get_order() const {
|
||||
return _order;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::get_num_cvs
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NurbsCurve::
|
||||
get_num_cvs() const {
|
||||
return _cvs.size();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::insert_cv
|
||||
// Access: Public, Scheme
|
||||
// Description: Inserts a new CV into the middle of the curve at the
|
||||
// indicated parametric value. This doesn't change the
|
||||
// shape or timing of the curve; however, it is
|
||||
// irreversible: if the new CV is immediately removed,
|
||||
// the curve will be changed. Returns the index of the
|
||||
// newly created CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NurbsCurve::
|
||||
insert_cv(double t) {
|
||||
if (_cvs.empty()) {
|
||||
return append_cv(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
if (t <= 0) {
|
||||
t = 0.0;
|
||||
}
|
||||
|
||||
int k = FindCV(t);
|
||||
if (k < 0) {
|
||||
return append_cv(_cvs.back()._p);
|
||||
}
|
||||
|
||||
// Now we are inserting a knot between k-1 and k. We'll adjust the
|
||||
// CV's according to Bohm's rule.
|
||||
|
||||
// First, get the new values of all the CV's that will change.
|
||||
// These are the CV's in the range [k - (_order-1), k-1].
|
||||
|
||||
LVector4f new_cvs[3];
|
||||
int i;
|
||||
for (i = 0; i < _order-1; i++) {
|
||||
int nk = i + k - (_order-1);
|
||||
double ti = GetKnot(nk);
|
||||
double d = GetKnot(nk + _order-1) - ti;
|
||||
if (d == 0.0) {
|
||||
new_cvs[i] = _cvs[nk-1]._p;
|
||||
} else {
|
||||
double a = (t - ti) / d;
|
||||
new_cvs[i] = (1.0-a)*_cvs[nk-1]._p + a*_cvs[nk]._p;
|
||||
}
|
||||
}
|
||||
|
||||
// Now insert the new CV
|
||||
_cvs.insert(_cvs.begin() + k-1, CV());
|
||||
|
||||
// Set all the new position values
|
||||
for (i = 0; i < _order-1; i++) {
|
||||
int nk = i + k - (_order-1);
|
||||
_cvs[nk]._p = new_cvs[i];
|
||||
}
|
||||
|
||||
// And set the new knot value.
|
||||
_cvs[k-1]._t = t;
|
||||
|
||||
return k-1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::append_cv
|
||||
// Access: Public, Scheme
|
||||
// Description: Adds a new CV to the end of the curve. Creates a new
|
||||
// knot value by adding 1 to the last knot value.
|
||||
// Returns the index of the new CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NurbsCurve::
|
||||
append_cv(float x, float y, float z) {
|
||||
return append_cv(LVector4f(x, y, z, 1.0));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::remove_cv
|
||||
// Access: Public, Scheme
|
||||
// Description: Removes the indicated CV from the curve. Returns
|
||||
// true if the CV index was valid, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
remove_cv(int n) {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_cvs.erase(_cvs.begin() + n);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::remove_all_cvs
|
||||
// Access: Public, Scheme
|
||||
// Description: Removes all CV's from the curve.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
remove_all_cvs() {
|
||||
_cvs.erase(_cvs.begin(), _cvs.end());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::set_cv_point
|
||||
// Access: Public, Scheme
|
||||
// Description: Repositions the indicated CV. Returns true if there
|
||||
// is such a CV, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
set_cv_point(int n, float x, float y, float z) {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float w = _cvs[n]._p[3];
|
||||
_cvs[n]._p.set(x*w, y*w, z*w, w);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::get_cv_point
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the position of the indicated CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
get_cv_point(int n, LVector3f &v) const {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
v = zero;
|
||||
} else {
|
||||
v = (const LVector3f &)_cvs[n]._p / _cvs[n]._p[3];
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::get_cv_point
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the position of the indicated CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const LVector3f &NurbsCurve::
|
||||
get_cv_point(int n) const {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
return zero;
|
||||
} else {
|
||||
static LVector3f result;
|
||||
result = (LVector3f &)_cvs[n]._p / _cvs[n]._p[3];
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::set_cv_weight
|
||||
// Access: Public, Scheme
|
||||
// Description: Sets the weight of the indicated CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
set_cv_weight(int n, float w) {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_cvs[n]._p *= (w / _cvs[n]._p[3]);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::get_cv_weight
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the weight of the indicated CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float NurbsCurve::
|
||||
get_cv_weight(int n) const {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return _cvs[n]._p[3];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::set_knot
|
||||
// Access: Public, Scheme
|
||||
// Description: Sets the value of the indicated knot. There are
|
||||
// get_num_cvs()+_order-1 knot values, but the first
|
||||
// _order-1 and the last _order-1 knot values cannot be
|
||||
// changed. It is also an error to set a knot value
|
||||
// outside the range of its neighbors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
set_knot(int n, double t) {
|
||||
if (n < _order || n-1 >= _cvs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_cvs[n-1]._t = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::get_knot
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the value of the indicated knot. There are
|
||||
// get_num_cvs()+_order-1 knot values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double NurbsCurve::
|
||||
get_knot(int n) const {
|
||||
return GetKnot(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::print
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
print() const {
|
||||
switch (get_curve_type()) {
|
||||
case PCT_T:
|
||||
cout << "Time-warping ";
|
||||
break;
|
||||
|
||||
case PCT_XYZ:
|
||||
cout << "XYZ ";
|
||||
break;
|
||||
|
||||
case PCT_HPR:
|
||||
cout << "HPR ";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cout << "NurbsCurve, order " << _order << ", " << get_num_cvs()
|
||||
<< " CV's. t ranges from 0 to " << get_max_t() << ".\n";
|
||||
|
||||
cout << "CV's:\n";
|
||||
int i;
|
||||
for (i = 0; i < _cvs.size(); i++) {
|
||||
LVector3f p = (const LVector3f &)_cvs[i]._p / _cvs[i]._p[3];
|
||||
cout << i << ") " << p << ", weight " << _cvs[i]._p[3] << "\n";
|
||||
}
|
||||
|
||||
cout << "Knots: ";
|
||||
for (i = 0; i < _cvs.size()+_order; i++) {
|
||||
cout << " " << GetKnot(i);
|
||||
}
|
||||
cout << "\n" << flush;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::print_cv
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
print_cv(int n) const {
|
||||
if (n < 0 || n >= _cvs.size()) {
|
||||
cout << "No such CV: " << n << "\n";
|
||||
} else {
|
||||
LVector3f p = (const LVector3f &)_cvs[n]._p / _cvs[n]._p[3];
|
||||
cout << "CV " << n << ": " << p << ", weight "
|
||||
<< _cvs[n]._p[3] << "\n";
|
||||
}
|
||||
cout << flush;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::recompute
|
||||
// Access: Public, Scheme
|
||||
// Description: Recalculates the curve basis according to the latest
|
||||
// position of the CV's, knots, etc. Until this
|
||||
// function is called, adjusting the NURBS parameters
|
||||
// will have no visible effect on the curve. Returns
|
||||
// true if the resulting curve is valid, false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
recompute() {
|
||||
_segs.erase(_segs.begin(), _segs.end());
|
||||
|
||||
double knots[8];
|
||||
LVector4f cvs[4];
|
||||
|
||||
if (_cvs.size() > _order-1) {
|
||||
for (int cv = 0; cv < _cvs.size()-(_order-1); cv++) {
|
||||
if (GetKnot(cv+_order-1) < GetKnot(cv+_order)) {
|
||||
// There are _order consecutive CV's that define each segment,
|
||||
// beginning at cv. Collect the CV's and knot values that define
|
||||
// this segment.
|
||||
int c;
|
||||
for (c = 0; c < _order; c++) {
|
||||
cvs[c] = _cvs[c+cv]._p;
|
||||
}
|
||||
for (c = 0; c < _order+_order; c++) {
|
||||
knots[c] = GetKnot(c+cv);
|
||||
}
|
||||
|
||||
insert_curveseg(_segs.size(), new CubicCurveseg(_order, knots, cvs),
|
||||
knots[_order] - knots[_order-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !_segs.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::normalize_tlength
|
||||
// Access: Public, Scheme
|
||||
// Description: Recomputes the knot vector so that the curve is
|
||||
// nearly uniformly spaced in parametric time. That is,
|
||||
// calc_length(0, t) == t (approximately) for all t in
|
||||
// [0, get_max_t()]. This is only an approximation; its
|
||||
// precision depends on the placement of the knots.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
normalize_tlength() {
|
||||
int num_knots = _cvs.size() + _order;
|
||||
double *new_t = (double *)alloca(sizeof(double) * num_knots);
|
||||
|
||||
int i;
|
||||
double last_t = 0.0;
|
||||
double last_new_t = 0.0;
|
||||
for (i = 0; i < num_knots; i++) {
|
||||
double this_t = get_knot(i);
|
||||
|
||||
if (this_t == last_t) {
|
||||
|
||||
// Keep the same knot value.
|
||||
new_t[i] = last_new_t;
|
||||
|
||||
} else {
|
||||
// Compute a new knot value that represents the distance on the
|
||||
// curve since the last knot.
|
||||
last_new_t += calc_length(last_t, this_t);
|
||||
new_t[i] = last_new_t;
|
||||
last_t = this_t;
|
||||
}
|
||||
}
|
||||
|
||||
// Now set all the knot values at once.
|
||||
for (i = 0; i < num_knots; i++) {
|
||||
set_knot(i, new_t[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::adjust_pt
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
adjust_pt(double t,
|
||||
float px, float py, float pz,
|
||||
float tx, float ty, float tz) {
|
||||
const ParametricCurve *curve;
|
||||
bool result = find_curve(curve, t);
|
||||
|
||||
if (!result) {
|
||||
cerr << " no curve segment at t\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Figure out which CV's contributed to this segment.
|
||||
int seg = 0;
|
||||
|
||||
dnassert(_cvs.size() > _order-1);
|
||||
|
||||
int cv = 0;
|
||||
for (cv = 0; cv < _cvs.size()-(_order-1); cv++) {
|
||||
if (GetKnot(cv+_order-1) < GetKnot(cv+_order)) {
|
||||
if (seg == _last_ti) {
|
||||
break;
|
||||
}
|
||||
seg++;
|
||||
}
|
||||
}
|
||||
|
||||
// Now copy the cvs and knots in question.
|
||||
double knots[8];
|
||||
LVector4f cvs[4];
|
||||
|
||||
int c;
|
||||
for (c = 0; c < 4; c++) {
|
||||
cvs[c] = (c < _order) ? _cvs[c+cv]._p : LVector4f(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
for (c = 0; c < _order+_order; c++) {
|
||||
knots[c] = GetKnot(c+cv);
|
||||
}
|
||||
|
||||
dnassert(_order>=1 && _order<=4);
|
||||
|
||||
LMatrix4f B;
|
||||
compute_nurbs_basis(_order, knots, B);
|
||||
|
||||
LMatrix4f Bi;
|
||||
if (!Bi.invertFull(B)) {
|
||||
cerr << "Cannot invert B!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// We can rebuild a curve segment given four arbitrary properties of
|
||||
// the segment: any point along the curve, any tangent along the
|
||||
// curve, any control point. Given any four such properties, a
|
||||
// single cubic curve segment is defined.
|
||||
|
||||
// We now want to rebuild the curve segment with the following four
|
||||
// properties: the same first control point, the same last control
|
||||
// point, and the supplied point and tangent at the indicated value
|
||||
// of t. To do this, we build a matrix T such that:
|
||||
|
||||
// Column 0 of T is the same as column 0 of B^(-1)
|
||||
// This refers to the first control point.
|
||||
// Column 1 of T is the vector [ t^3 t^2 t 1 ]
|
||||
// This refers to the point on the curve at t.
|
||||
// Column 2 of T is the vector [ 3t^2 2t 1 0 ]
|
||||
// This refers to the tangent to the curve at t.
|
||||
// Column 3 of T is the same as column 3 of B^(-1)
|
||||
// This refers to the last control point.
|
||||
|
||||
LMatrix4f T = Bi;
|
||||
T.setCol(1, t*t*t, t*t, t, 1.0);
|
||||
T.setCol(2, 3.0*t*t, 2.0*t, 1.0, 0.0);
|
||||
|
||||
LMatrix4f Ti;
|
||||
if (!Ti.invertFull(T)) {
|
||||
cerr << "Cannot invert T!\n";
|
||||
}
|
||||
|
||||
// Now we build the matrix P such that P represents the solution of
|
||||
// T, above, when T is applied to the geometry and basis matrices.
|
||||
// That is, P = G * B * T.
|
||||
|
||||
// Column 0 of P is the first control point.
|
||||
// Column 1 of P is the (new) desired point on the curve at t.
|
||||
// Column 2 of P is the (new) desired tangent to the curve at t.
|
||||
// Column 3 of P is the last control point.
|
||||
|
||||
LMatrix4f P;
|
||||
|
||||
P.setCol(0, cvs[0][0], cvs[0][1], cvs[0][2], cvs[0][3]);
|
||||
P.setCol(1, px, py, pz, 1.0);
|
||||
P.setCol(2, tx, ty, tz, 0.0);
|
||||
P.setCol(3, cvs[3][0], cvs[3][1], cvs[3][2], cvs[3][3]);
|
||||
|
||||
// Now we simply solve for G to get G = P * T^(-1) * B^(-1).
|
||||
|
||||
LMatrix4f G = P * Ti * Bi;
|
||||
|
||||
// Now extract the new CV's from the new G matrix, and restore them
|
||||
// to the curve.
|
||||
for (c = 0; c < _order; c++) {
|
||||
LVector4f &s = _cvs[c+cv]._p;
|
||||
G.getCol(c, &s[0], &s[1], &s[2], &s[3]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::rebuild_curveseg
|
||||
// Access: Public, Virtual
|
||||
// Description: Rebuilds the current curve segment (as selected by
|
||||
// the most recent call to find_curve()) according to
|
||||
// the specified properties (see
|
||||
// CubicCurveseg::compute_seg). Returns true if
|
||||
// possible, false if something goes horribly wrong.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
rebuild_curveseg(int rtype0, double t0, const LVector4f &v0,
|
||||
int rtype1, double t1, const LVector4f &v1,
|
||||
int rtype2, double t2, const LVector4f &v2,
|
||||
int rtype3, double t3, const LVector4f &v3) {
|
||||
// Figure out which CV's contributed to this segment.
|
||||
int seg = 0;
|
||||
|
||||
///dnassert(_cvs.size() > _order-1);
|
||||
|
||||
int cv = 0;
|
||||
for (cv = 0; cv < _cvs.size()-(_order-1); cv++) {
|
||||
if (GetKnot(cv+_order-1) < GetKnot(cv+_order)) {
|
||||
if (seg == _last_ti) {
|
||||
break;
|
||||
}
|
||||
seg++;
|
||||
}
|
||||
}
|
||||
|
||||
// Now copy the cvs and knots in question.
|
||||
LMatrix4f G;
|
||||
double knots[8];
|
||||
|
||||
int c;
|
||||
|
||||
// We only need to build the geometry matrix if at least one of the
|
||||
// properties depends on the original value.
|
||||
if ((rtype0 | rtype1 | rtype2 | rtype3) & RT_KEEP_ORIG) {
|
||||
for (c = 0; c < 4; c++) {
|
||||
static const LVector4f zero(0.0, 0.0, 0.0, 0.0);
|
||||
const LVector4f &s = (c < _order) ? _cvs[c+cv]._p : zero;
|
||||
|
||||
G.set_col(c, s);
|
||||
}
|
||||
}
|
||||
|
||||
// But we always need the knot vector to determine the basis matrix.
|
||||
for (c = 0; c < _order+_order; c++) {
|
||||
knots[c] = GetKnot(c+cv);
|
||||
}
|
||||
|
||||
LMatrix4f B;
|
||||
compute_nurbs_basis(_order, knots, B);
|
||||
|
||||
LMatrix4f Bi;
|
||||
Bi = invert(B);
|
||||
|
||||
if (!CubicCurveseg::compute_seg(rtype0, t0, v0,
|
||||
rtype1, t1, v1,
|
||||
rtype2, t2, v2,
|
||||
rtype3, t3, v3,
|
||||
B, Bi, G)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now extract the new CV's from the new G matrix, and restore them
|
||||
// to the curve.
|
||||
for (c = 0; c < _order; c++) {
|
||||
_cvs[c+cv]._p = G.get_col(c);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::write_egg
|
||||
// Access: Public, Scheme
|
||||
// Description: Writes an egg description of the nurbs curve to the
|
||||
// specified output file. Creates the file if it does
|
||||
// not exist; appends to the end of it if it does.
|
||||
// Returns true if the file is successfully written.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
write_egg(const char *filename) {
|
||||
const char *basename = strrchr(filename, '/');
|
||||
basename = (basename==NULL) ? filename : basename+1;
|
||||
|
||||
ofstream out(filename, ios::app);
|
||||
return write_egg(out, basename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::write_egg
|
||||
// Access: Public, Scheme
|
||||
// Description: Writes an egg description of the nurbs curve to the
|
||||
// specified output stream. Returns true if the file is
|
||||
// successfully written.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurve::
|
||||
write_egg(ostream &out, const char *basename) {
|
||||
if (get_name().empty()) {
|
||||
// If we don't have a name, come up with one.
|
||||
int len = strlen(basename);
|
||||
if (len>4 && strcmp(basename+len-4, ".egg")==0) {
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
char *name = (char *)alloca(len + 5);
|
||||
strncpy(name, basename, len);
|
||||
switch (_curve_type) {
|
||||
case PCT_XYZ:
|
||||
strcpy(name+len, "_xyz");
|
||||
break;
|
||||
|
||||
case PCT_HPR:
|
||||
strcpy(name+len, "_hpr");
|
||||
break;
|
||||
|
||||
case PCT_T:
|
||||
strcpy(name+len, "_t");
|
||||
break;
|
||||
|
||||
default:
|
||||
name[len] = '\0';
|
||||
};
|
||||
|
||||
set_name(name);
|
||||
}
|
||||
|
||||
Output(out);
|
||||
|
||||
if (out) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::splice
|
||||
// Access: Public, Scheme
|
||||
// Description: Joins the indicated curve onto the end of this curve,
|
||||
// beginning at the indicated time (which must be
|
||||
// greater than or equal to max_t). Normally, the first
|
||||
// point of the new curve will be the same as the last
|
||||
// point of this curve, but if they are different, the
|
||||
// curves will automatically connect; however, the
|
||||
// connection may not be smooth and terminal point of
|
||||
// the original curve may be lost.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
splice(double t, const NurbsCurve &other) {
|
||||
if (other._order != _order) {
|
||||
///DWARNING(dnparametrics)
|
||||
///<< "Cannot splice NURBS curves of different orders!" << dnend;
|
||||
return;
|
||||
}
|
||||
|
||||
double old_t = get_max_t();
|
||||
|
||||
if (t < old_t) {
|
||||
///DWARNING(dnparametrics)
|
||||
///<< "Invalid splicing in the middle of a curve!" << dnend;
|
||||
t = old_t;
|
||||
}
|
||||
|
||||
// First, define a vector of all the current CV's except the last
|
||||
// one.
|
||||
vector<CV> new_cvs(_cvs);
|
||||
if (!new_cvs.empty()) {
|
||||
new_cvs.pop_back();
|
||||
}
|
||||
|
||||
// Now add all the new CV's.
|
||||
int cv;
|
||||
for (cv = 0; cv < other._cvs.size(); cv++) {
|
||||
CV new_cv(other._cvs[cv]);
|
||||
|
||||
if (cv+1 < _order) {
|
||||
new_cv._t = old_t;
|
||||
} else {
|
||||
new_cv._t += t;
|
||||
}
|
||||
new_cvs.push_back(new_cv);
|
||||
}
|
||||
|
||||
// Now assign that vector.
|
||||
_cvs = new_cvs;
|
||||
|
||||
recompute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::Output
|
||||
// Access: Public
|
||||
// Description: Formats the Nurbs curve for output to an Egg file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurve::
|
||||
Output(ostream &out, int indent) const {
|
||||
Indent(out, indent)
|
||||
<< "<VertexPool> " << get_name() << ".pool {\n";
|
||||
|
||||
int cv;
|
||||
for (cv = 0; cv < _cvs.size(); cv++) {
|
||||
Indent(out, indent+2) << "<Vertex> " << cv << " { "
|
||||
<< _cvs[cv]._p << " }\n";
|
||||
}
|
||||
Indent(out, indent) << "}\n";
|
||||
|
||||
Indent(out, indent) << "<NURBSCurve> " << get_name() << " {\n";
|
||||
|
||||
if (_curve_type!=PCT_NONE) {
|
||||
Indent(out, indent+2) << "<Char*> type { ";
|
||||
switch (_curve_type) {
|
||||
case PCT_XYZ:
|
||||
out << "XYZ";
|
||||
break;
|
||||
|
||||
case PCT_HPR:
|
||||
out << "HPR";
|
||||
break;
|
||||
|
||||
case PCT_T:
|
||||
out << "T";
|
||||
break;
|
||||
};
|
||||
out << " }\n";
|
||||
}
|
||||
|
||||
Indent(out, indent+2) << "<Order> { " << _order << " }\n";
|
||||
|
||||
Indent(out, indent+2) << "<Knots> {";
|
||||
int k;
|
||||
int num_knots = _cvs.size() + _order;
|
||||
|
||||
for (k = 0; k < num_knots; k++) {
|
||||
if (k%6 == 0) {
|
||||
out << "\n";
|
||||
Indent(out, indent+4);
|
||||
}
|
||||
out << GetKnot(k) << " ";
|
||||
}
|
||||
out << "\n";
|
||||
Indent(out, indent+2) << "}\n";
|
||||
|
||||
Indent(out, indent+2) << "<VertexRef> {";
|
||||
for (cv = 0; cv < _cvs.size(); cv++) {
|
||||
if (cv%10 == 1) {
|
||||
out << "\n";
|
||||
Indent(out, indent+3);
|
||||
}
|
||||
out << " " << cv;
|
||||
}
|
||||
out << "\n";
|
||||
Indent(out, indent+4) << "<Ref> { " << get_name() << ".pool }\n";
|
||||
Indent(out, indent+2) << "}\n";
|
||||
|
||||
Indent(out, indent) << "}\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::Destructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsCurve::
|
||||
~NurbsCurve() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurve::FindCV
|
||||
// Access: Protected
|
||||
// Description: Finds the first knot whose value is >= t, or -1 if t
|
||||
// is beyond the end of the curve.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NurbsCurve::
|
||||
FindCV(double t) {
|
||||
int i;
|
||||
for (i = _order-1; i < _cvs.size(); i++) {
|
||||
if (_cvs[i]._t >= t) {
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
164
panda/src/parametrics/nurbsCurve.h
Normal file
164
panda/src/parametrics/nurbsCurve.h
Normal file
@ -0,0 +1,164 @@
|
||||
// Filename: nurbsCurve.h
|
||||
// Created by: drose (27Feb98)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
#ifndef NURBSCURVE_H
|
||||
#define NURBSCURVE_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#include "curve.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Defines
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////#define LVector3f pfVec3
|
||||
//typedef pfVec3 LVector3f;
|
||||
|
||||
|
||||
class HermiteCurve;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NurbsCurve
|
||||
// Description : A Nonuniform Rational B-Spline.
|
||||
//
|
||||
// This class is actually implemented as a
|
||||
// PiecewiseCurve made up of several CubicCurvesegs,
|
||||
// each of which is created using the nurbs_basis()
|
||||
// method. The list of CV's and knots is kept here,
|
||||
// within the NurbsCurve class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA NurbsCurve : public PiecewiseCurve {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
PUBLISHED:
|
||||
NurbsCurve();
|
||||
NurbsCurve(const ParametricCurve &hc);
|
||||
NurbsCurve(int order, int num_cvs,
|
||||
const double knots[], const LVector4f cvs[]);
|
||||
|
||||
void set_order(int order);
|
||||
int get_order() const;
|
||||
|
||||
int get_num_cvs() const;
|
||||
int get_num_knots() const {
|
||||
return _cvs.size() + _order;
|
||||
}
|
||||
|
||||
int insert_cv(double t);
|
||||
int append_cv(float x, float y, float z);
|
||||
inline int append_cv(const LVector3f &v) {
|
||||
return append_cv(LVector4f(v[0], v[1], v[2], 1.0));
|
||||
}
|
||||
inline int append_cv(const LVector4f &v) {
|
||||
_cvs.push_back(CV(v, GetKnot(_cvs.size())+1.0));
|
||||
return _cvs.size()-1;
|
||||
}
|
||||
|
||||
bool remove_cv(int n);
|
||||
void remove_all_cvs();
|
||||
|
||||
bool set_cv_point(int n, float x, float y, float z);
|
||||
inline bool set_cv_point(int n, const LVector3f &v) {
|
||||
return set_cv_point(n, v[0], v[1], v[2]);
|
||||
}
|
||||
void get_cv_point(int n, LVector3f &v) const;
|
||||
const LVector3f &get_cv_point(int n) const;
|
||||
|
||||
bool set_cv_weight(int n, float w);
|
||||
float get_cv_weight(int n) const;
|
||||
|
||||
bool set_knot(int n, double t);
|
||||
double get_knot(int n) const;
|
||||
|
||||
void print() const;
|
||||
void print_cv(int n) const;
|
||||
|
||||
bool recompute();
|
||||
|
||||
void normalize_tlength();
|
||||
|
||||
bool write_egg(const char *filename);
|
||||
bool write_egg(ostream &out, const char *basename);
|
||||
|
||||
void splice(double t, const NurbsCurve &other);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions not visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual bool
|
||||
rebuild_curveseg(int rtype0, double t0, const LVector4f &v0,
|
||||
int rtype1, double t1, const LVector4f &v1,
|
||||
int rtype2, double t2, const LVector4f &v2,
|
||||
int rtype3, double t3, const LVector4f &v3);
|
||||
|
||||
CubicCurveseg *get_curveseg(int ti) {
|
||||
return (CubicCurveseg *)PiecewiseCurve::get_curveseg(ti);
|
||||
}
|
||||
|
||||
double
|
||||
GetKnot(int n) const {
|
||||
if (n < _order || _cvs.empty()) {
|
||||
return 0.0;
|
||||
} else if (n-1 >= _cvs.size()) {
|
||||
return _cvs.back()._t;
|
||||
} else {
|
||||
return _cvs[n-1]._t;
|
||||
}
|
||||
}
|
||||
|
||||
void Output(ostream &out, int indent=0) const;
|
||||
|
||||
protected:
|
||||
virtual ~NurbsCurve();
|
||||
|
||||
int FindCV(double t);
|
||||
|
||||
int _order;
|
||||
|
||||
class CV {
|
||||
public:
|
||||
CV() {}
|
||||
CV(const LVector4f &p, double t) : _p(p), _t(t) {}
|
||||
LVector4f _p;
|
||||
double _t;
|
||||
};
|
||||
|
||||
vector<CV> _cvs;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
PiecewiseCurve::init_type();
|
||||
register_type(_type_handle, "NurbsCurve",
|
||||
PiecewiseCurve::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;
|
||||
};
|
||||
|
||||
#endif
|
313
panda/src/parametrics/nurbsCurveDrawer.cxx
Normal file
313
panda/src/parametrics/nurbsCurveDrawer.cxx
Normal file
@ -0,0 +1,313 @@
|
||||
// Filename: nurbsCurveDrawer.C
|
||||
// Created by: drose (27Feb98)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "nurbsCurveDrawer.h"
|
||||
#include "luse.h"
|
||||
#include "parametrics.h"
|
||||
#include "typedWriteableReferenceCount.h"
|
||||
#include "namable.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
TypeHandle NurbsCurveDrawer::_type_handle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::Constructor
|
||||
// Access: Public, Scheme
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsCurveDrawer::
|
||||
NurbsCurveDrawer(NurbsCurve *curve) : ParametricCurveDrawer(curve) {
|
||||
set_cv_color(1.0, 0.0, 0.0);
|
||||
set_hull_color(1.0, 0.5, 0.5);
|
||||
set_knot_color(0.0, 0.0, 1.0);
|
||||
|
||||
_cvs.set_thickness(4.0);
|
||||
_hull.set_thickness(1.0);
|
||||
_knots.set_thickness(4.0);
|
||||
|
||||
_show_cvs = true;
|
||||
_show_hull = true;
|
||||
_show_knots = true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::Destructor
|
||||
// Access: Public, Scheme, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
NurbsCurveDrawer::
|
||||
~NurbsCurveDrawer() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::set_cv_color
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the color of the CV's.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurveDrawer::
|
||||
set_cv_color(float r, float g, float b) {
|
||||
_cv_color.set(r, g, b);
|
||||
_cvs.set_color(r, g, b);
|
||||
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::set_knot_color
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the color of the knots.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurveDrawer::
|
||||
set_knot_color(float r, float g, float b) {
|
||||
_knot_color.set(r, g, b);
|
||||
_knots.set_color(r, g, b);
|
||||
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::set_hull_color
|
||||
// Access: Public, Scheme
|
||||
// Description: Specifies the color of the convex hull.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurveDrawer::
|
||||
set_hull_color(float r, float g, float b) {
|
||||
_hull_color.set(r, g, b);
|
||||
_hull.set_color(r, g, b);
|
||||
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::draw
|
||||
// Access: Public, Scheme, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
draw() {
|
||||
NurbsCurve *nurbs = (NurbsCurve *)_curve;
|
||||
// Make sure the curve is fresh.
|
||||
nurbs->recompute();
|
||||
|
||||
// First, draw the curve itself.
|
||||
if (!ParametricCurveDrawer::draw()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i;
|
||||
if (_show_knots) {
|
||||
_num_cvs = nurbs->get_num_cvs();
|
||||
_knotnums.erase(_knotnums.begin(), _knotnums.end());
|
||||
|
||||
double lt = -1.0;
|
||||
int ki = -1;
|
||||
for (i = 0; i < _num_cvs; i++) {
|
||||
double t = nurbs->GetKnot(i);
|
||||
if (t != lt) {
|
||||
lt = t;
|
||||
LVector3f knot_pos, knot_tan;
|
||||
nurbs->get_pt(nurbs->GetKnot(i), knot_pos, knot_tan);
|
||||
_knots.move_to(_mapper(knot_pos, knot_tan, t));
|
||||
ki++;
|
||||
}
|
||||
_knotnums.push_back(ki);
|
||||
}
|
||||
|
||||
_knots.create(_geom_node, _frame_accurate);
|
||||
}
|
||||
|
||||
if (_show_cvs) {
|
||||
_num_cvs = nurbs->get_num_cvs();
|
||||
for (i = 0; i < _num_cvs; i++) {
|
||||
_cvs.move_to(_mapper(nurbs->get_cv_point(i), LVector3f(0.0, 0.0, 0.0),
|
||||
nurbs->GetKnot(i+1)));
|
||||
}
|
||||
|
||||
_cvs.create(_geom_node, _frame_accurate);
|
||||
}
|
||||
|
||||
if (_show_hull) {
|
||||
_num_cvs = nurbs->get_num_cvs();
|
||||
for (i = 0; i < _num_cvs; i++) {
|
||||
_hull.draw_to(_mapper(nurbs->get_cv_point(i), LVector3f(0.0, 0.0, 0.0),
|
||||
nurbs->GetKnot(i+1)));
|
||||
}
|
||||
|
||||
_hull.create(_geom_node, _frame_accurate);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::recompute
|
||||
// Access: Public, Scheme, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
recompute(double t1, double t2, ParametricCurve *curve) {
|
||||
return draw();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::set_show_cvs
|
||||
// Access: Public, Scheme
|
||||
// Description: Sets the flag that hides or shows the CV's.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurveDrawer::
|
||||
set_show_cvs(bool flag) {
|
||||
_show_cvs = flag;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::get_show_cvs
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the current state of the show-CV's flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
get_show_cvs() const {
|
||||
return _show_cvs;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::set_show_hull
|
||||
// Access: Public, Scheme
|
||||
// Description: Sets the flag that hides or shows the convex hull.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurveDrawer::
|
||||
set_show_hull(bool flag) {
|
||||
_show_hull = flag;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::get_show_hull
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the current state of the show-hull flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
get_show_hull() const {
|
||||
return _show_hull;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::set_show_knots
|
||||
// Access: Public, Scheme
|
||||
// Description: Sets the flag that hides or shows the knots.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void NurbsCurveDrawer::
|
||||
set_show_knots(bool flag) {
|
||||
_show_knots = flag;
|
||||
if (_drawn) {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::get_show_knots
|
||||
// Access: Public, Scheme
|
||||
// Description: Returns the current state of the show-knots flag.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
get_show_knots() const {
|
||||
return _show_knots;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::hilight
|
||||
// Access: Public, Scheme
|
||||
// Description: Hilights a particular CV by showing it and its knot
|
||||
// in a different color. Returns true if the CV exists
|
||||
// and has been drawn, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
hilight(int n, float hr, float hg, float hb) {
|
||||
// If there's no curve, do nothing and return false.
|
||||
if (_curve==NULL || !_curve->is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n < 0 || n >= _cvs.get_num_vertices()) {
|
||||
// Also return false if we're out of range.
|
||||
return false;
|
||||
}
|
||||
|
||||
NurbsCurve *nurbs = (NurbsCurve *)_curve;
|
||||
if (_show_cvs) {
|
||||
_cvs.set_vertex_color(n, hr, hg, hb);
|
||||
}
|
||||
if (_show_knots) {
|
||||
///dnassert(_knotnums[n] >= 0 && _knotnums[n] < _knots.get_num_vertices());
|
||||
_knots.set_vertex_color(_knotnums[n], hr, hg, hb);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: NurbsCurveDrawer::unhilight
|
||||
// Access: Public, Scheme
|
||||
// Description: Removes the hilight previously set on a CV.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool NurbsCurveDrawer::
|
||||
unhilight(int n) {
|
||||
if (_curve==NULL || !_curve->is_valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n < 0 || n >= _cvs.get_num_vertices()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NurbsCurve *nurbs = (NurbsCurve *)_curve;
|
||||
if (_show_cvs) {
|
||||
_cvs.set_vertex_color(n, _cv_color[0], _cv_color[1], _cv_color[2]);
|
||||
}
|
||||
if (_show_knots) {
|
||||
///dnassert(_knotnums[n] >= 0 && _knotnums[n] < _knots.get_num_vertices());
|
||||
_knots.set_vertex_color(_knotnums[n],
|
||||
_knot_color[0], _knot_color[1], _knot_color[2]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
96
panda/src/parametrics/nurbsCurveDrawer.h
Normal file
96
panda/src/parametrics/nurbsCurveDrawer.h
Normal file
@ -0,0 +1,96 @@
|
||||
// Filename: nurbsCurveDrawer.h
|
||||
// Created by: drose (27Feb98)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 1992,93,94,95,96,97 Walt Disney Imagineering, Inc.
|
||||
//
|
||||
// These coded instructions, statements, data structures and
|
||||
// computer programs contain unpublished proprietary information of
|
||||
// Walt Disney Imagineering and are protected by Federal copyright
|
||||
// law. They may not be disclosed to third parties or copied or
|
||||
// duplicated in any form, in whole or in part, without the prior
|
||||
// written consent of Walt Disney Imagineering Inc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
#ifndef NURBSCURVEDRAWER_H
|
||||
#define NURBSCURVEDRAWER_H
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "curveDrawer.h"
|
||||
#include "nurbsCurve.h"
|
||||
#include "lineSegs.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Defines
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NurbsCurveDrawer
|
||||
// Description : Draws a Nurbs curve, also drawing in the control
|
||||
// vertices and tangent vectors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA NurbsCurveDrawer : public ParametricCurveDrawer {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
PUBLISHED:
|
||||
NurbsCurveDrawer(NurbsCurve *curve);
|
||||
virtual ~NurbsCurveDrawer();
|
||||
|
||||
void set_cv_color(float r, float g, float b);
|
||||
void set_hull_color(float r, float g, float b);
|
||||
void set_knot_color(float r, float g, float b);
|
||||
|
||||
virtual bool draw();
|
||||
virtual bool recompute(double t1, double t2, ParametricCurve *curve=NULL);
|
||||
|
||||
void set_show_cvs(bool flag);
|
||||
bool get_show_cvs() const;
|
||||
void set_show_hull(bool flag);
|
||||
bool get_show_hull() const;
|
||||
void set_show_knots(bool flag);
|
||||
bool get_show_knots() const;
|
||||
|
||||
bool hilight(int n, float hr=1.0, float hg=1.0, float hb=0.0);
|
||||
bool unhilight(int n);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Member functions not visible to Scheme
|
||||
////////////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
LVector3f _cv_color, _hull_color, _knot_color;
|
||||
int _num_cvs, _num_hull, _num_knots;
|
||||
LineSegs _hull, _knots, _cvs;
|
||||
vector<int> _knotnums;
|
||||
|
||||
bool _show_cvs, _show_hull, _show_knots;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ParametricCurveDrawer::init_type();
|
||||
register_type(_type_handle, "NurbsCurveDrawer",
|
||||
ParametricCurveDrawer::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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
0
panda/src/parametrics/test_parametrics.cxx
Normal file
0
panda/src/parametrics/test_parametrics.cxx
Normal file
Loading…
x
Reference in New Issue
Block a user