From 3791dbaa718b997da5e791d7e429f4f2779d1282 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 14 Oct 2003 19:36:45 +0000 Subject: [PATCH] extend nurbs interface for egg-qtess --- panda/src/egg/eggPrimitive.cxx | 14 ++ panda/src/egg/eggPrimitive.h | 2 + panda/src/egg2pg/Sources.pp | 4 +- panda/src/egg2pg/egg2pg_composite1.cxx | 1 + panda/src/egg2pg/eggLoader.cxx | 103 +------------ panda/src/egg2pg/egg_parametrics.cxx | 141 ++++++++++++++++++ panda/src/egg2pg/egg_parametrics.h | 57 +++++++ panda/src/parametrics/nurbsBasisVector.cxx | 13 ++ panda/src/parametrics/nurbsBasisVector.h | 2 + panda/src/parametrics/nurbsCurveEvaluator.cxx | 43 ++++++ panda/src/parametrics/nurbsCurveEvaluator.h | 3 + panda/src/parametrics/nurbsCurveResult.I | 23 ++- panda/src/parametrics/nurbsCurveResult.cxx | 50 ++++++- panda/src/parametrics/nurbsCurveResult.h | 4 + .../src/parametrics/nurbsSurfaceEvaluator.cxx | 69 +++++++++ panda/src/parametrics/nurbsSurfaceEvaluator.h | 4 + panda/src/parametrics/nurbsSurfaceResult.I | 26 +++- panda/src/parametrics/nurbsSurfaceResult.cxx | 61 +++++++- panda/src/parametrics/nurbsSurfaceResult.h | 4 + panda/src/parametrics/ropeNode.cxx | 6 +- panda/src/parametrics/sheetNode.cxx | 12 +- 21 files changed, 523 insertions(+), 119 deletions(-) create mode 100644 panda/src/egg2pg/egg_parametrics.cxx create mode 100644 panda/src/egg2pg/egg_parametrics.h diff --git a/panda/src/egg/eggPrimitive.cxx b/panda/src/egg/eggPrimitive.cxx index b90033888a..4b26771b63 100644 --- a/panda/src/egg/eggPrimitive.cxx +++ b/panda/src/egg/eggPrimitive.cxx @@ -150,6 +150,20 @@ determine_bin() { return result; } +//////////////////////////////////////////////////////////////////// +// Function: EggPrimitive::copy_attributes +// Access: Public +// Description: Copies the rendering attributes from the indicated +// primitive. +//////////////////////////////////////////////////////////////////// +void EggPrimitive:: +copy_attributes(const EggPrimitive &other) { + EggAttributes::operator = (other); + set_texture(other.get_texture()); + set_material(other.get_material()); + set_bface_flag(other.get_bface_flag()); +} + //////////////////////////////////////////////////////////////////// // Function: EggPrimitive::has_vertex_normal // Access: Public diff --git a/panda/src/egg/eggPrimitive.h b/panda/src/egg/eggPrimitive.h index 211dca0b23..0098f2579d 100644 --- a/panda/src/egg/eggPrimitive.h +++ b/panda/src/egg/eggPrimitive.h @@ -87,6 +87,8 @@ PUBLISHED: INLINE void set_bface_flag(bool flag); INLINE bool get_bface_flag() const; + void copy_attributes(const EggPrimitive &other); + bool has_vertex_normal() const; bool has_vertex_color() const; diff --git a/panda/src/egg2pg/Sources.pp b/panda/src/egg2pg/Sources.pp index 134b18fa98..a1a7071184 100644 --- a/panda/src/egg2pg/Sources.pp +++ b/panda/src/egg2pg/Sources.pp @@ -19,6 +19,7 @@ deferredNodeProperty.h \ eggBinner.h \ eggLoader.h \ + egg_parametrics.h \ load_egg_file.h \ loaderFileTypeEgg.h @@ -30,6 +31,7 @@ deferredNodeProperty.cxx \ eggBinner.cxx \ eggLoader.cxx \ + egg_parametrics.cxx \ load_egg_file.cxx \ loaderFileTypeEgg.cxx @@ -40,7 +42,7 @@ #endif #define INSTALL_HEADERS \ - load_egg_file.h config_egg2pg.h + egg_parametrics.h load_egg_file.h config_egg2pg.h #define IGATESCAN load_egg_file.h diff --git a/panda/src/egg2pg/egg2pg_composite1.cxx b/panda/src/egg2pg/egg2pg_composite1.cxx index 4a6f131d61..52a036a68b 100644 --- a/panda/src/egg2pg/egg2pg_composite1.cxx +++ b/panda/src/egg2pg/egg2pg_composite1.cxx @@ -2,3 +2,4 @@ #include "characterMaker.cxx" #include "computedVerticesMaker.cxx" #include "config_egg2pg.cxx" +#include "egg_parametrics.cxx" diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 888f11725d..d0533ec182 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -19,6 +19,7 @@ #include "pandabase.h" #include "eggLoader.h" +#include "egg_parametrics.h" #include "config_egg2pg.h" #include "nodePath.h" #include "renderState.h" @@ -463,46 +464,12 @@ make_nurbs_curve(EggNurbsCurve *egg_curve, PandaNode *parent, assert(parent != NULL); assert(!parent->is_geom_node()); - PT(NurbsCurveEvaluator) nurbs = new NurbsCurveEvaluator; - - if (egg_curve->get_order() < 1 || egg_curve->get_order() > 4) { - egg2pg_cat.error() - << "Invalid NURBSCurve order for " << egg_curve->get_name() << ": " - << egg_curve->get_order() << "\n"; + PT(NurbsCurveEvaluator) nurbs = ::make_nurbs_curve(egg_curve, mat); + if (nurbs == (NurbsCurveEvaluator *)NULL) { _error = true; return; } - nurbs->set_order(egg_curve->get_order()); - - nurbs->reset(egg_curve->size()); - EggPrimitive::const_iterator pi; - int vi = 0; - for (pi = egg_curve->begin(); pi != egg_curve->end(); ++pi) { - EggVertex *egg_vertex = (*pi); - nurbs->set_vertex(vi, LCAST(float, egg_vertex->get_pos4() * mat)); - Colorf color = egg_vertex->get_color(); - nurbs->set_extended_vertex(vi, 0, color[0]); - nurbs->set_extended_vertex(vi, 1, color[1]); - nurbs->set_extended_vertex(vi, 2, color[2]); - nurbs->set_extended_vertex(vi, 3, color[3]); - vi++; - } - - int num_knots = egg_curve->get_num_knots(); - if (num_knots != nurbs->get_num_knots()) { - egg2pg_cat.error() - << "Invalid NURBSCurve number of knots for " - << egg_curve->get_name() << ": got " << num_knots - << " knots, expected " << nurbs->get_num_knots() << "\n"; - _error = true; - return; - } - - for (int i = 0; i < num_knots; i++) { - nurbs->set_knot(i, egg_curve->get_knot(i)); - } - /* switch (egg_curve->get_curve_type()) { case EggCurve::CT_xyz: @@ -662,72 +629,12 @@ make_nurbs_surface(EggNurbsSurface *egg_surface, PandaNode *parent, assert(parent != NULL); assert(!parent->is_geom_node()); - PT(NurbsSurfaceEvaluator) nurbs = new NurbsSurfaceEvaluator; - - if (egg_surface->get_u_order() < 1 || egg_surface->get_u_order() > 4) { - egg2pg_cat.error() - << "Invalid NURBSSurface U order for " << egg_surface->get_name() << ": " - << egg_surface->get_u_order() << "\n"; + PT(NurbsSurfaceEvaluator) nurbs = ::make_nurbs_surface(egg_surface, mat); + if (nurbs == (NurbsSurfaceEvaluator *)NULL) { _error = true; return; } - if (egg_surface->get_v_order() < 1 || egg_surface->get_v_order() > 4) { - egg2pg_cat.error() - << "Invalid NURBSSurface V order for " << egg_surface->get_name() << ": " - << egg_surface->get_v_order() << "\n"; - _error = true; - return; - } - - nurbs->set_u_order(egg_surface->get_u_order()); - nurbs->set_v_order(egg_surface->get_v_order()); - - int num_u_vertices = egg_surface->get_num_u_cvs(); - int num_v_vertices = egg_surface->get_num_v_cvs(); - nurbs->reset(num_u_vertices, num_v_vertices); - for (int ui = 0; ui < num_u_vertices; ui++) { - for (int vi = 0; vi < num_v_vertices; vi++) { - int i = egg_surface->get_vertex_index(ui, vi); - EggVertex *egg_vertex = egg_surface->get_vertex(i); - nurbs->set_vertex(ui, vi, LCAST(float, egg_vertex->get_pos4() * mat)); - - Colorf color = egg_vertex->get_color(); - nurbs->set_extended_vertex(ui, vi, 0, color[0]); - nurbs->set_extended_vertex(ui, vi, 1, color[1]); - nurbs->set_extended_vertex(ui, vi, 2, color[2]); - nurbs->set_extended_vertex(ui, vi, 3, color[3]); - } - } - - int num_u_knots = egg_surface->get_num_u_knots(); - if (num_u_knots != nurbs->get_num_u_knots()) { - egg2pg_cat.error() - << "Invalid NURBSSurface number of U knots for " - << egg_surface->get_name() << ": got " << num_u_knots - << " knots, expected " << nurbs->get_num_u_knots() << "\n"; - _error = true; - return; - } - - int num_v_knots = egg_surface->get_num_v_knots(); - if (num_v_knots != nurbs->get_num_v_knots()) { - egg2pg_cat.error() - << "Invalid NURBSSurface number of U knots for " - << egg_surface->get_name() << ": got " << num_v_knots - << " knots, expected " << nurbs->get_num_v_knots() << "\n"; - _error = true; - return; - } - - int i; - for (i = 0; i < num_u_knots; i++) { - nurbs->set_u_knot(i, egg_surface->get_u_knot(i)); - } - for (i = 0; i < num_v_knots; i++) { - nurbs->set_v_knot(i, egg_surface->get_v_knot(i)); - } - PT(SheetNode) sheet = new SheetNode(egg_surface->get_name()); sheet->set_surface(nurbs); diff --git a/panda/src/egg2pg/egg_parametrics.cxx b/panda/src/egg2pg/egg_parametrics.cxx new file mode 100644 index 0000000000..85ce0dc9f6 --- /dev/null +++ b/panda/src/egg2pg/egg_parametrics.cxx @@ -0,0 +1,141 @@ +// Filename: egg_parametrics.cxx +// Created by: drose (13Oct03) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "egg_parametrics.h" +#include "config_egg2pg.h" + +//////////////////////////////////////////////////////////////////// +// Function: make_nurbs_surface +// Description: Returns a new NurbsSurfaceEvaluator that's filled in +// with the values from the given EggSurface (and +// transformed by the indicated matrix), or NULL if the +// object is invalid. If there is vertex color, it will +// be applied to values 0 - 3 of the extended vertex +// values. +//////////////////////////////////////////////////////////////////// +PT(NurbsSurfaceEvaluator) +make_nurbs_surface(EggNurbsSurface *egg_surface, const LMatrix4d &mat) { + if (egg_surface->get_u_order() < 1 || egg_surface->get_u_order() > 4) { + egg2pg_cat.error() + << "Invalid NURBSSurface U order for " << egg_surface->get_name() << ": " + << egg_surface->get_u_order() << "\n"; + return NULL; + } + + if (egg_surface->get_v_order() < 1 || egg_surface->get_v_order() > 4) { + egg2pg_cat.error() + << "Invalid NURBSSurface V order for " << egg_surface->get_name() << ": " + << egg_surface->get_v_order() << "\n"; + return NULL; + } + + PT(NurbsSurfaceEvaluator) nurbs = new NurbsSurfaceEvaluator; + + nurbs->set_u_order(egg_surface->get_u_order()); + nurbs->set_v_order(egg_surface->get_v_order()); + + int num_u_vertices = egg_surface->get_num_u_cvs(); + int num_v_vertices = egg_surface->get_num_v_cvs(); + nurbs->reset(num_u_vertices, num_v_vertices); + for (int ui = 0; ui < num_u_vertices; ui++) { + for (int vi = 0; vi < num_v_vertices; vi++) { + int i = egg_surface->get_vertex_index(ui, vi); + EggVertex *egg_vertex = egg_surface->get_vertex(i); + nurbs->set_vertex(ui, vi, LCAST(float, egg_vertex->get_pos4() * mat)); + + Colorf color = egg_vertex->get_color(); + nurbs->set_extended_vertices(ui, vi, 0, color.get_data(), 4); + } + } + + int num_u_knots = egg_surface->get_num_u_knots(); + if (num_u_knots != nurbs->get_num_u_knots()) { + egg2pg_cat.error() + << "Invalid NURBSSurface number of U knots for " + << egg_surface->get_name() << ": got " << num_u_knots + << " knots, expected " << nurbs->get_num_u_knots() << "\n"; + return NULL; + } + + int num_v_knots = egg_surface->get_num_v_knots(); + if (num_v_knots != nurbs->get_num_v_knots()) { + egg2pg_cat.error() + << "Invalid NURBSSurface number of U knots for " + << egg_surface->get_name() << ": got " << num_v_knots + << " knots, expected " << nurbs->get_num_v_knots() << "\n"; + return NULL; + } + + int i; + for (i = 0; i < num_u_knots; i++) { + nurbs->set_u_knot(i, egg_surface->get_u_knot(i)); + } + for (i = 0; i < num_v_knots; i++) { + nurbs->set_v_knot(i, egg_surface->get_v_knot(i)); + } + + return nurbs; +} + +//////////////////////////////////////////////////////////////////// +// Function: make_nurbs_curve +// Description: Returns a new NurbsCurveEvaluator that's filled in +// with the values from the given EggCurve (and +// transformed by the indicated matrix), or NULL if the +// object is invalid. If there is vertex color, it will +// be applied to values 0 - 3 of the extended vertex +// values. +//////////////////////////////////////////////////////////////////// +PT(NurbsCurveEvaluator) +make_nurbs_curve(EggNurbsCurve *egg_curve, const LMatrix4d &mat) { + if (egg_curve->get_order() < 1 || egg_curve->get_order() > 4) { + egg2pg_cat.error() + << "Invalid NURBSCurve order for " << egg_curve->get_name() << ": " + << egg_curve->get_order() << "\n"; + return NULL; + } + + PT(NurbsCurveEvaluator) nurbs = new NurbsCurveEvaluator; + nurbs->set_order(egg_curve->get_order()); + + nurbs->reset(egg_curve->size()); + EggPrimitive::const_iterator pi; + int vi = 0; + for (pi = egg_curve->begin(); pi != egg_curve->end(); ++pi) { + EggVertex *egg_vertex = (*pi); + nurbs->set_vertex(vi, LCAST(float, egg_vertex->get_pos4() * mat)); + Colorf color = egg_vertex->get_color(); + nurbs->set_extended_vertices(vi, 0, color.get_data(), 4); + vi++; + } + + int num_knots = egg_curve->get_num_knots(); + if (num_knots != nurbs->get_num_knots()) { + egg2pg_cat.error() + << "Invalid NURBSCurve number of knots for " + << egg_curve->get_name() << ": got " << num_knots + << " knots, expected " << nurbs->get_num_knots() << "\n"; + return NULL; + } + + for (int i = 0; i < num_knots; i++) { + nurbs->set_knot(i, egg_curve->get_knot(i)); + } + + return nurbs; +} diff --git a/panda/src/egg2pg/egg_parametrics.h b/panda/src/egg2pg/egg_parametrics.h new file mode 100644 index 0000000000..c3a4f671c5 --- /dev/null +++ b/panda/src/egg2pg/egg_parametrics.h @@ -0,0 +1,57 @@ +// Filename: egg_parametrics.h +// Created by: drose (13Oct03) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGG_PARAMETRICS_H +#define EGG_PARAMETRICS_H + +#include "pandabase.h" + +#include "eggNurbsSurface.h" +#include "eggNurbsCurve.h" +#include "nurbsSurfaceEvaluator.h" +#include "nurbsCurveEvaluator.h" + +BEGIN_PUBLISH + +//////////////////////////////////////////////////////////////////// +// Function: make_nurbs_surface +// Description: Returns a new NurbsSurfaceEvaluator that's filled in +// with the values from the given EggSurface (and +// transformed by the indicated matrix), or NULL if the +// object is invalid. If there is vertex color, it will +// be applied to values 0 - 3 of the extended vertex +// values. +//////////////////////////////////////////////////////////////////// +EXPCL_PANDAEGG PT(NurbsSurfaceEvaluator) +make_nurbs_surface(EggNurbsSurface *egg_surface, const LMatrix4d &mat); + +//////////////////////////////////////////////////////////////////// +// Function: make_nurbs_curve +// Description: Returns a new NurbsCurveEvaluator that's filled in +// with the values from the given EggCurve (and +// transformed by the indicated matrix), or NULL if the +// object is invalid. If there is vertex color, it will +// be applied to values 0 - 3 of the extended vertex +// values. +//////////////////////////////////////////////////////////////////// +EXPCL_PANDAEGG PT(NurbsCurveEvaluator) +make_nurbs_curve(EggNurbsCurve *egg_curve, const LMatrix4d &mat); + +END_PUBLISH + +#endif diff --git a/panda/src/parametrics/nurbsBasisVector.cxx b/panda/src/parametrics/nurbsBasisVector.cxx index 5224ef98bd..8e52ee72dd 100644 --- a/panda/src/parametrics/nurbsBasisVector.cxx +++ b/panda/src/parametrics/nurbsBasisVector.cxx @@ -66,6 +66,19 @@ append_segment(int vertex_index, const float knots[]) { _segments.push_back(segment); } +//////////////////////////////////////////////////////////////////// +// Function: NurbsBasisVector::transpose +// Access: Public +// Description: Transposes the basis matrices stored in the vector. +//////////////////////////////////////////////////////////////////// +void NurbsBasisVector:: +transpose() { + Segments::iterator si; + for (si = _segments.begin(); si != _segments.end(); ++si) { + (*si)._basis.transpose_in_place(); + } +} + //////////////////////////////////////////////////////////////////// // Function: NurbsBasisVector::nurbs_blending_function // Access: Private, Static diff --git a/panda/src/parametrics/nurbsBasisVector.h b/panda/src/parametrics/nurbsBasisVector.h index a5d4619910..4b555660a7 100644 --- a/panda/src/parametrics/nurbsBasisVector.h +++ b/panda/src/parametrics/nurbsBasisVector.h @@ -59,6 +59,8 @@ public: void clear(int order); void append_segment(int vertex_index, const float knots[]); + void transpose(); + private: static LVecBase4f nurbs_blending_function(int order, int i, int j, const float knots[]); diff --git a/panda/src/parametrics/nurbsCurveEvaluator.cxx b/panda/src/parametrics/nurbsCurveEvaluator.cxx index 60fdb12d49..f35fe67cae 100644 --- a/panda/src/parametrics/nurbsCurveEvaluator.cxx +++ b/panda/src/parametrics/nurbsCurveEvaluator.cxx @@ -75,6 +75,25 @@ get_vertex_space(int i, const NodePath &rel_to) const { return _vertices[i].get_space(rel_to); } +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveEvaluator::set_extended_vertices +// Access: Public +// Description: Simultaneously sets several extended values in the +// slots d through (d + num_values - 1) from the +// num_values elements of the indicated array. This is +// equivalent to calling set_extended_vertex() +// num_values times. See set_extended_vertex(). +//////////////////////////////////////////////////////////////////// +void NurbsCurveEvaluator:: +set_extended_vertices(int i, int d, const float values[], int num_values) { + nassertv(i >= 0 && i < (int)_vertices.size()); + + NurbsVertex &vertex = _vertices[i]; + for (int n = 0; n < num_values; n++) { + vertex.set_extended_vertex(d + n, values[n]); + } +} + //////////////////////////////////////////////////////////////////// // Function: NurbsCurveEvaluator::set_knot // Access: Published @@ -106,6 +125,30 @@ get_knot(int i) const { return _knots[i]; } +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveEvaluator::normalize_knots +// Access: Published +// Description: Normalizes the knot sequence so that the parametric +// range of the curve is 0 .. 1. +//////////////////////////////////////////////////////////////////// +void NurbsCurveEvaluator:: +normalize_knots() { + if (_knots_dirty) { + recompute_knots(); + } + + if (get_num_vertices() > _order - 1) { + double min_value = _knots[_order - 1]; + double max_value = _knots[get_num_vertices()]; + double range = (max_value - min_value); + + for (Knots::iterator ki = _knots.begin(); ki != _knots.end(); ++ki) { + (*ki) = ((*ki) - min_value) / range; + } + _basis_dirty = true; + } +} + //////////////////////////////////////////////////////////////////// // Function: NurbsCurveEvaluator::evaluate // Access: Published diff --git a/panda/src/parametrics/nurbsCurveEvaluator.h b/panda/src/parametrics/nurbsCurveEvaluator.h index 2c635716b2..e2872b69a8 100644 --- a/panda/src/parametrics/nurbsCurveEvaluator.h +++ b/panda/src/parametrics/nurbsCurveEvaluator.h @@ -67,10 +67,13 @@ PUBLISHED: INLINE void set_extended_vertex(int i, int d, float value); INLINE float get_extended_vertex(int i, int d) const; + void set_extended_vertices(int i, int d, + const float values[], int num_values); INLINE int get_num_knots() const; void set_knot(int i, float knot); float get_knot(int i) const; + void normalize_knots(); INLINE int get_num_segments() const; diff --git a/panda/src/parametrics/nurbsCurveResult.I b/panda/src/parametrics/nurbsCurveResult.I index 1bd4127de9..8c26b100e5 100644 --- a/panda/src/parametrics/nurbsCurveResult.I +++ b/panda/src/parametrics/nurbsCurveResult.I @@ -52,7 +52,7 @@ get_end_t() const { // Access: Published // Description: Computes the point on the curve corresponding to the // indicated value in parametric time. Returns true if -// the t value is value, false otherwise. +// the t value is valid, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool NurbsCurveResult:: eval_point(float t, LVecBase3f &point) { @@ -101,6 +101,27 @@ eval_extended_point(float t, int d) { return eval_segment_extended_point(segment, _basis.scale_t(segment, t), d); } +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveResult::eval_extended_points +// Access: Published +// Description: Simultaneously performs eval_extended_point on a +// contiguous sequence of dimensions. The dimensions +// evaluated are d through (d + num_values - 1); the +// results are filled into the num_values elements in +// the indicated result array. +//////////////////////////////////////////////////////////////////// +INLINE bool NurbsCurveResult:: +eval_extended_points(float t, int d, float result[], int num_values) { + int segment = find_segment(t); + if (segment == -1) { + return false; + } + + eval_segment_extended_points(segment, _basis.scale_t(segment, t), d, + result, num_values); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: NurbsCurveResult::get_num_segments // Access: Public diff --git a/panda/src/parametrics/nurbsCurveResult.cxx b/panda/src/parametrics/nurbsCurveResult.cxx index 6c6a2b643c..c7075e0b0b 100644 --- a/panda/src/parametrics/nurbsCurveResult.cxx +++ b/panda/src/parametrics/nurbsCurveResult.cxx @@ -121,6 +121,13 @@ float NurbsCurveResult:: eval_segment_extended_point(int segment, float t, int d) const { nassertr(segment >= 0 && segment < _basis.get_num_segments(), 0.0f); + float t2 = t*t; + LVecBase4f tvec(t*t2, t2, t, 1.0f); + + float weight = tvec.dot(_composed[segment].get_col(3)); + + // Calculate the composition of the basis matrix and the geometry + // matrix on-the-fly. int order = _basis.get_order(); int vi = _basis.get_vertex_index(segment); @@ -142,14 +149,53 @@ eval_segment_extended_point(int segment, float t, int d) const { basis.get_row(1).dot(geom), basis.get_row(2).dot(geom), basis.get_row(3).dot(geom)); + return tvec.dot(composed_geom) / weight; +} + +//////////////////////////////////////////////////////////////////// +// Function: NurbsCurveResult::eval_segment_extended_points +// Access: Published +// Description: Simultaneously performs eval_extended_point on a +// contiguous sequence of dimensions. The dimensions +// evaluated are d through (d + num_values - 1); the +// results are filled into the num_values elements in +// the indicated result array. +//////////////////////////////////////////////////////////////////// +void NurbsCurveResult:: +eval_segment_extended_points(int segment, float t, int d, + float result[], int num_values) const { + nassertv(segment >= 0 && segment < _basis.get_num_segments()); float t2 = t*t; LVecBase4f tvec(t*t2, t2, t, 1.0f); float weight = tvec.dot(_composed[segment].get_col(3)); - float result = tvec.dot(composed_geom) / weight; - return result; + // Calculate the composition of the basis matrix and the geometry + // matrix on-the-fly. + const LMatrix4f &basis = _basis.get_basis(segment); + int order = _basis.get_order(); + int vi = _basis.get_vertex_index(segment); + + for (int n = 0; n < num_values; n++) { + LVecBase4f geom; + int ci = 0; + while (ci < order) { + geom[ci] = _verts[vi + ci].get_extended_vertex(d + n); + ci++; + } + while (ci < 4) { + geom[ci] = 0.0f; + ci++; + } + + // Compute matrix * column vector. + LVecBase4f composed_geom(basis.get_row(0).dot(geom), + basis.get_row(1).dot(geom), + basis.get_row(2).dot(geom), + basis.get_row(3).dot(geom)); + result[n] = tvec.dot(composed_geom) / weight; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/parametrics/nurbsCurveResult.h b/panda/src/parametrics/nurbsCurveResult.h index 1775d4949d..d8654a054f 100644 --- a/panda/src/parametrics/nurbsCurveResult.h +++ b/panda/src/parametrics/nurbsCurveResult.h @@ -54,11 +54,15 @@ PUBLISHED: INLINE bool eval_point(float t, LVecBase3f &point); INLINE bool eval_tangent(float t, LVecBase3f &tangent); INLINE float eval_extended_point(float t, int d); + INLINE bool eval_extended_points(float t, int d, + float result[], int num_values); INLINE int get_num_segments() const; void eval_segment_point(int segment, float t, LVecBase3f &point) const; void eval_segment_tangent(int segment, float t, LVecBase3f &tangent) const; float eval_segment_extended_point(int segment, float t, int d) const; + void eval_segment_extended_points(int segment, float t, int d, + float result[], int num_values) const; INLINE float get_segment_t(int segment, float t) const; private: diff --git a/panda/src/parametrics/nurbsSurfaceEvaluator.cxx b/panda/src/parametrics/nurbsSurfaceEvaluator.cxx index 69c05e9a7f..4e98fdd6d8 100644 --- a/panda/src/parametrics/nurbsSurfaceEvaluator.cxx +++ b/panda/src/parametrics/nurbsSurfaceEvaluator.cxx @@ -84,6 +84,27 @@ get_vertex_space(int ui, int vi, const NodePath &rel_to) const { return vert(ui, vi).get_space(rel_to); } +//////////////////////////////////////////////////////////////////// +// Function: NurbsSurfaceEvaluator::set_extended_vertices +// Access: Public +// Description: Simultaneously sets several extended values in the +// slots d through (d + num_values - 1) from the +// num_values elements of the indicated array. This is +// equivalent to calling set_extended_vertex() +// num_values times. See set_extended_vertex(). +//////////////////////////////////////////////////////////////////// +void NurbsSurfaceEvaluator:: +set_extended_vertices(int ui, int vi, int d, + const float values[], int num_values) { + nassertv(ui >= 0 && ui < _num_u_vertices && + vi >= 0 && vi < _num_v_vertices); + + NurbsVertex &vertex = vert(ui, vi); + for (int n = 0; n < num_values; n++) { + vertex.set_extended_vertex(d + n, values[n]); + } +} + //////////////////////////////////////////////////////////////////// // Function: NurbsSurfaceEvaluator::set_u_knot // Access: Published @@ -115,6 +136,30 @@ get_u_knot(int i) const { return _u_knots[i]; } +//////////////////////////////////////////////////////////////////// +// Function: NurbsSurfaceEvaluator::normalize_u_knots +// Access: Published +// Description: Normalizes the knot sequence so that the parametric +// range of the surface in the U direction is 0 .. 1. +//////////////////////////////////////////////////////////////////// +void NurbsSurfaceEvaluator:: +normalize_u_knots() { + if (_u_knots_dirty) { + recompute_u_knots(); + } + + if (_num_u_vertices > _u_order - 1) { + double min_value = _u_knots[_u_order - 1]; + double max_value = _u_knots[_num_u_vertices]; + double range = (max_value - min_value); + + for (Knots::iterator ki = _u_knots.begin(); ki != _u_knots.end(); ++ki) { + (*ki) = ((*ki) - min_value) / range; + } + _u_basis_dirty = true; + } +} + //////////////////////////////////////////////////////////////////// // Function: NurbsSurfaceEvaluator::set_v_knot // Access: Published @@ -146,6 +191,30 @@ get_v_knot(int i) const { return _v_knots[i]; } +//////////////////////////////////////////////////////////////////// +// Function: NurbsSurfaceEvaluator::normalize_v_knots +// Access: Published +// Description: Normalizes the knot sequence so that the parametric +// range of the surface in the U direction is 0 .. 1. +//////////////////////////////////////////////////////////////////// +void NurbsSurfaceEvaluator:: +normalize_v_knots() { + if (_v_knots_dirty) { + recompute_v_knots(); + } + + if (_num_v_vertices > _v_order - 1) { + double min_value = _v_knots[_v_order - 1]; + double max_value = _v_knots[_num_v_vertices]; + double range = (max_value - min_value); + + for (Knots::iterator ki = _v_knots.begin(); ki != _v_knots.end(); ++ki) { + (*ki) = ((*ki) - min_value) / range; + } + _v_basis_dirty = true; + } +} + //////////////////////////////////////////////////////////////////// // Function: NurbsSurfaceEvaluator::evaluate // Access: Published diff --git a/panda/src/parametrics/nurbsSurfaceEvaluator.h b/panda/src/parametrics/nurbsSurfaceEvaluator.h index a16d74ab97..b50f54470d 100644 --- a/panda/src/parametrics/nurbsSurfaceEvaluator.h +++ b/panda/src/parametrics/nurbsSurfaceEvaluator.h @@ -64,14 +64,18 @@ PUBLISHED: INLINE void set_extended_vertex(int ui, int vi, int d, float value); INLINE float get_extended_vertex(int ui, int vi, int d) const; + void set_extended_vertices(int ui, int vi, int d, + const float values[], int num_values); INLINE int get_num_u_knots() const; void set_u_knot(int i, float knot); float get_u_knot(int i) const; + void normalize_u_knots(); INLINE int get_num_v_knots() const; void set_v_knot(int i, float knot); float get_v_knot(int i) const; + void normalize_v_knots(); INLINE int get_num_u_segments() const; INLINE int get_num_v_segments() const; diff --git a/panda/src/parametrics/nurbsSurfaceResult.I b/panda/src/parametrics/nurbsSurfaceResult.I index 30a436aed3..df05bfa072 100644 --- a/panda/src/parametrics/nurbsSurfaceResult.I +++ b/panda/src/parametrics/nurbsSurfaceResult.I @@ -73,7 +73,7 @@ get_end_v() const { // Access: Published // Description: Computes the point on the surface corresponding to the // indicated value in parametric time. Returns true if -// the t value is value, false otherwise. +// the u, v values are valid, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool NurbsSurfaceResult:: eval_point(float u, float v, LVecBase3f &point) { @@ -128,6 +128,30 @@ eval_extended_point(float u, float v, int d) { _v_basis.scale_t(vi, v), d); } +//////////////////////////////////////////////////////////////////// +// Function: NurbsSurfaceResult::eval_extended_points +// Access: Published +// Description: Simultaneously performs eval_extended_point on a +// contiguous sequence of dimensions. The dimensions +// evaluated are d through (d + num_values - 1); the +// results are filled into the num_values elements in +// the indicated result array. +//////////////////////////////////////////////////////////////////// +INLINE bool NurbsSurfaceResult:: +eval_extended_points(float u, float v, int d, float result[], + int num_values) { + int ui = find_u_segment(u); + int vi = find_v_segment(v); + if (ui == -1 || vi == -1) { + return false; + } + + eval_segment_extended_points(ui, vi, _u_basis.scale_t(ui, u), + _v_basis.scale_t(vi, v), d, result, + num_values); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: NurbsSurfaceResult::get_num_u_segments // Access: Public diff --git a/panda/src/parametrics/nurbsSurfaceResult.cxx b/panda/src/parametrics/nurbsSurfaceResult.cxx index 6960bdb252..bb7852e801 100644 --- a/panda/src/parametrics/nurbsSurfaceResult.cxx +++ b/panda/src/parametrics/nurbsSurfaceResult.cxx @@ -37,6 +37,9 @@ NurbsSurfaceResult(const NurbsBasisVector &u_basis, _num_u_vertices(num_u_vertices), _num_v_vertices(num_v_vertices) { + // The V basis matrices will always be transposed. + _v_basis.transpose(); + _last_u_segment = -1; _last_v_segment = -1; int u_order = _u_basis.get_order(); @@ -51,7 +54,7 @@ NurbsSurfaceResult(const NurbsBasisVector &u_basis, } for (int vi = 0; vi < num_v_segments; vi++) { - LMatrix4f v_basis_transpose = transpose(_v_basis.get_basis(vi)); + const LMatrix4f &v_basis_transpose = _v_basis.get_basis(vi); int vn = _v_basis.get_vertex_index(vi); nassertv(vn >= 0 && vn + v_order - 1 < _num_v_vertices); @@ -171,9 +174,19 @@ eval_segment_normal(int ui, int vi, float u, float v, LVecBase3f &normal) const //////////////////////////////////////////////////////////////////// float NurbsSurfaceResult:: eval_segment_extended_point(int ui, int vi, float u, float v, int d) const { + int i = segi(ui, vi); + nassertr(i >= 0 && i < (int)_composed.size(), 0.0f); + + float u2 = u*u; + LVecBase4f uvec(u*u2, u2, u, 1.0f); + float v2 = v*v; + LVecBase4f vvec(v*v2, v2, v, 1.0f); + + float weight = vvec.dot(uvec * _composed[i]._w); + // Calculate the composition of the basis matrices and the geometry // matrix on-the-fly. - LMatrix4f v_basis_transpose = transpose(_v_basis.get_basis(vi)); + const LMatrix4f &v_basis_transpose = _v_basis.get_basis(vi); const LMatrix4f &u_basis_mat = _u_basis.get_basis(ui); int u_order = _u_basis.get_order(); int v_order = _v_basis.get_order(); @@ -193,9 +206,23 @@ eval_segment_extended_point(int ui, int vi, float u, float v, int d) const { } LMatrix4f composed = u_basis_mat * geom * v_basis_transpose; + return vvec.dot(uvec * composed) / weight; +} +//////////////////////////////////////////////////////////////////// +// Function: NurbsSurfaceResult::eval_segment_extended_points +// Access: Published +// Description: Simultaneously performs eval_extended_point on a +// contiguous sequence of dimensions. The dimensions +// evaluated are d through (d + num_values - 1); the +// results are filled into the num_values elements in +// the indicated result array. +//////////////////////////////////////////////////////////////////// +void NurbsSurfaceResult:: +eval_segment_extended_points(int ui, int vi, float u, float v, int d, + float result[], int num_values) const { int i = segi(ui, vi); - nassertr(i >= 0 && i < (int)_composed.size(), 0.0f); + nassertv(i >= 0 && i < (int)_composed.size()); float u2 = u*u; LVecBase4f uvec(u*u2, u2, u, 1.0f); @@ -203,7 +230,33 @@ eval_segment_extended_point(int ui, int vi, float u, float v, int d) const { LVecBase4f vvec(v*v2, v2, v, 1.0f); float weight = vvec.dot(uvec * _composed[i]._w); - return vvec.dot(uvec * composed) / weight; + + // Calculate the composition of the basis matrices and the geometry + // matrix on-the-fly. + const LMatrix4f &v_basis_transpose = _v_basis.get_basis(vi); + const LMatrix4f &u_basis_mat = _u_basis.get_basis(ui); + int u_order = _u_basis.get_order(); + int v_order = _v_basis.get_order(); + + int un = _u_basis.get_vertex_index(ui); + int vn = _v_basis.get_vertex_index(vi); + + for (int n = 0; n < num_values; n++) { + LMatrix4f geom; + memset(&geom, 0, sizeof(geom)); + + for (int uni = 0; uni < 4; uni++) { + for (int vni = 0; vni < 4; vni++) { + if (uni < u_order && vni < v_order) { + geom(uni, vni) = + _verts[verti(un + uni, vn + vni)].get_extended_vertex(d + n); + } + } + } + + LMatrix4f composed = u_basis_mat * geom * v_basis_transpose; + result[n] = vvec.dot(uvec * composed) / weight; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/parametrics/nurbsSurfaceResult.h b/panda/src/parametrics/nurbsSurfaceResult.h index 4fcb2b8d12..c596a85d30 100644 --- a/panda/src/parametrics/nurbsSurfaceResult.h +++ b/panda/src/parametrics/nurbsSurfaceResult.h @@ -51,12 +51,16 @@ PUBLISHED: INLINE bool eval_point(float u, float v, LVecBase3f &point); INLINE bool eval_normal(float u, float v, LVecBase3f &normal); INLINE float eval_extended_point(float u, float v, int d); + INLINE bool eval_extended_points(float u, float v, int d, + float result[], int num_values); INLINE int get_num_u_segments() const; INLINE int get_num_v_segments() const; void eval_segment_point(int ui, int vi, float u, float v, LVecBase3f &point) const; void eval_segment_normal(int ui, int vi, float u, float v, LVecBase3f &normal) const; float eval_segment_extended_point(int ui, int vi, float u, float v, int d) const; + void eval_segment_extended_points(int ui, int vi, float u, float v, int d, + float result[], int num_values) const; INLINE float get_segment_u(int ui, float u) const; INLINE float get_segment_v(int vi, float v) const; diff --git a/panda/src/parametrics/ropeNode.cxx b/panda/src/parametrics/ropeNode.cxx index eee90bb370..fac5d9313c 100644 --- a/panda/src/parametrics/ropeNode.cxx +++ b/panda/src/parametrics/ropeNode.cxx @@ -287,10 +287,8 @@ render_thread(CullTraverser *trav, CullTraverserData &data, verts.push_back(point); if (use_vertex_color) { - Colorf color(result->eval_segment_extended_point(segment, t, 0), - result->eval_segment_extended_point(segment, t, 1), - result->eval_segment_extended_point(segment, t, 2), - result->eval_segment_extended_point(segment, t, 3)); + Colorf color; + result->eval_segment_extended_points(segment, t, 0, &color[0], 4), colors.push_back(color); } diff --git a/panda/src/parametrics/sheetNode.cxx b/panda/src/parametrics/sheetNode.cxx index ba616e6b4b..efd6e3a598 100644 --- a/panda/src/parametrics/sheetNode.cxx +++ b/panda/src/parametrics/sheetNode.cxx @@ -293,15 +293,11 @@ render_sheet(CullTraverser *trav, CullTraverserData &data, uvs.push_back(TexCoordf(u1_tc, v_tc)); if (use_vertex_color) { - Colorf c0(result->eval_segment_extended_point(ui, vi, u0, v, 0), - result->eval_segment_extended_point(ui, vi, u0, v, 1), - result->eval_segment_extended_point(ui, vi, u0, v, 2), - result->eval_segment_extended_point(ui, vi, u0, v, 3)); + Colorf c0, c1; + result->eval_segment_extended_points(ui, vi, u0, v, 0, &c0[0], 4); + result->eval_segment_extended_points(ui, vi, u1, v, 0, &c1[0], 4); + colors.push_back(c0); - Colorf c1(result->eval_segment_extended_point(ui, vi, u1, v, 0), - result->eval_segment_extended_point(ui, vi, u1, v, 1), - result->eval_segment_extended_point(ui, vi, u1, v, 2), - result->eval_segment_extended_point(ui, vi, u1, v, 3)); colors.push_back(c1); } }