mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-05 03:15:07 -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