15 #include "nurbsSurfaceEvaluator.h"
22 NurbsSurfaceEvaluator::
23 NurbsSurfaceEvaluator() {
26 _u_knots_dirty =
true;
27 _v_knots_dirty =
true;
28 _u_basis_dirty =
true;
29 _v_basis_dirty =
true;
37 NurbsSurfaceEvaluator::
38 ~NurbsSurfaceEvaluator() {
51 reset(
int num_u_vertices,
int num_v_vertices) {
52 int num_vertices = num_u_vertices * num_v_vertices;
54 _vertices.reserve(num_vertices);
55 _num_u_vertices = num_u_vertices;
56 _num_v_vertices = num_v_vertices;
58 for (
int i = 0; i < num_vertices; i++) {
61 _u_knots_dirty =
true;
62 _v_knots_dirty =
true;
63 _u_basis_dirty =
true;
64 _v_basis_dirty =
true;
77 nassertr(ui >= 0 && ui < _num_u_vertices &&
78 vi >= 0 && vi < _num_v_vertices, empty_node_path);
80 return vert(ui, vi).get_space(rel_to);
94 const PN_stdfloat values[],
int num_values) {
95 nassertv(ui >= 0 && ui < _num_u_vertices &&
96 vi >= 0 && vi < _num_v_vertices);
99 for (
int n = 0; n < num_values; n++) {
114 if (_u_knots_dirty) {
117 nassertv(i >= 0 && i < (
int)_u_knots.size());
128 if (_u_knots_dirty) {
131 nassertr(i >= 0 && i < (
int)_u_knots.size(), 0.0f);
143 if (_u_knots_dirty) {
147 if (_num_u_vertices > _u_order - 1) {
148 double min_value = _u_knots[_u_order - 1];
149 double max_value = _u_knots[_num_u_vertices];
150 double range = (max_value - min_value);
152 for (Knots::iterator ki = _u_knots.begin(); ki != _u_knots.end(); ++ki) {
153 (*ki) = ((*ki) - min_value) / range;
155 _u_basis_dirty =
true;
169 if (_v_knots_dirty) {
172 nassertv(i >= 0 && i < (
int)_v_knots.size());
183 if (_v_knots_dirty) {
186 nassertr(i >= 0 && i < (
int)_v_knots.size(), 0.0f);
198 if (_v_knots_dirty) {
202 if (_num_v_vertices > _v_order - 1) {
203 double min_value = _v_knots[_v_order - 1];
204 double max_value = _v_knots[_num_v_vertices];
205 double range = (max_value - min_value);
207 for (Knots::iterator ki = _v_knots.begin(); ki != _v_knots.end(); ++ki) {
208 (*ki) = ((*ki) - min_value) / range;
210 _v_basis_dirty =
true;
223 evaluate(const
NodePath &rel_to)
const {
224 if (_u_basis_dirty) {
227 if (_v_basis_dirty) {
233 get_vertices(vecs, rel_to);
238 &vecs[0], &_vertices[0],
239 _num_u_vertices, _num_v_vertices);
247 void NurbsSurfaceEvaluator::
248 output(ostream &out)
const {
266 int num_vertices = (int)_vertices.size();
267 verts.reserve(verts.size() + num_vertices);
269 for (vi = 0; vi < num_vertices; vi++) {
270 NodePath space = _vertices[vi].get_space(rel_to);
271 const LVecBase4 &vertex = _vertices[vi].get_vertex();
273 verts.push_back(vertex);
276 const LMatrix4 &mat = transform->get_mat();
277 verts.push_back(vertex * mat);
295 int num_vertices = (int)_vertices.size();
296 verts.reserve(verts.size() + num_vertices);
298 for (vi = 0; vi < num_vertices; vi++) {
299 const NodePath &space = _vertices[vi].get_space(rel_to);
300 LVecBase4 vertex = _vertices[vi].get_vertex();
303 const LMatrix4 &mat = transform->get_mat();
304 vertex = vertex * mat;
306 LPoint3 v3(vertex[0] / vertex[3], vertex[1] / vertex[3], vertex[2] / vertex[3]);
316 void NurbsSurfaceEvaluator::
317 recompute_u_knots() {
320 _u_knots.reserve(num_knots);
322 PN_stdfloat value = 0.0f;
325 while (i < _u_order) {
326 _u_knots.push_back(value);
329 while (i < num_knots - _u_order) {
331 _u_knots.push_back(value);
335 while (i < num_knots) {
336 _u_knots.push_back(value);
340 _u_knots_dirty =
false;
348 void NurbsSurfaceEvaluator::
349 recompute_v_knots() {
352 _v_knots.reserve(num_knots);
354 PN_stdfloat value = 0.0f;
357 while (i < _v_order) {
358 _v_knots.push_back(value);
361 while (i < num_knots - _v_order) {
363 _v_knots.push_back(value);
367 while (i < num_knots) {
368 _v_knots.push_back(value);
372 _v_knots_dirty =
false;
381 void NurbsSurfaceEvaluator::
382 recompute_u_basis() {
383 if (_u_knots_dirty) {
387 _u_basis.
clear(_u_order);
388 if (_num_u_vertices > _u_order - 1) {
389 int min_knot = _u_order;
390 int max_knot = _num_u_vertices;
392 for (
int i = min_knot; i <= max_knot; i++) {
393 nassertv(i - 1 >= 0 && i < (
int)_u_knots.size());
394 if (_u_knots[i - 1] < _u_knots[i]) {
401 _u_basis_dirty =
false;
410 void NurbsSurfaceEvaluator::
411 recompute_v_basis() {
412 if (_v_knots_dirty) {
416 _v_basis.
clear(_v_order);
417 if (_num_v_vertices > _v_order - 1) {
418 int min_knot = _v_order;
419 int max_knot = _num_v_vertices;
421 for (
int i = min_knot; i <= max_knot; i++) {
422 nassertv(i - 1 >= 0 && i < (
int)_v_knots.size());
423 if (_v_knots[i - 1] < _v_knots[i]) {
430 _v_basis_dirty =
false;
void get_vertices(Vert4Array &verts, const NodePath &rel_to) const
Fills the indicated vector with the set of vertices in the surface, transformed to the given space...
void set_u_knot(int i, PN_stdfloat knot)
Sets the value of the nth knot.
void set_v_knot(int i, PN_stdfloat knot)
Sets the value of the nth knot.
void normalize_v_knots()
Normalizes the knot sequence so that the parametric range of the surface in the U direction is 0 ...
int get_num_v_knots() const
Returns the number of knot values in the surface in the V direction.
PN_stdfloat get_u_knot(int i) const
Returns the value of the nth knot.
void append_segment(int vertex_index, const PN_stdfloat knots[])
Computes a NURBS basis for one segment of the curve and appends it to the set of basis matrices...
void normalize_u_knots()
Normalizes the knot sequence so that the parametric range of the surface in the U direction is 0 ...
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
void set_extended_vertices(int ui, int vi, int d, const PN_stdfloat values[], int num_values)
Simultaneously sets several extended values in the slots d through (d + num_values - 1) from the num_...
This class is an abstraction for evaluating NURBS surfaces.
This represents a single control vertex in a NurbsEvaluator.
NodePath get_vertex_space(int ui, int vi, const NodePath &rel_to) const
Returns the coordinate space of the nth control vertex of the surface, expressed as a NodePath...
This is a 4-by-4 transform matrix.
void clear(int order)
Removes all the segments from the curve.
The result of a NurbsSurfaceEvaluator.
void reset(int num_u_vertices, int num_v_vertices)
Resets all the vertices and knots to their default values, and sets the surface up with the indicated...
This is the base class for all three-component vectors and points.
bool is_empty() const
Returns true if the NodePath contains no nodes.
int get_num_u_knots() const
Returns the number of knot values in the surface in the U direction.
void set_extended_vertex(int d, PN_stdfloat value)
Sets an n-dimensional vertex value.
PN_stdfloat get_v_knot(int i) const
Returns the value of the nth knot.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...