Bladeren bron

extend nurbs interface for egg-qtess

David Rose 22 jaren geleden
bovenliggende
commit
3791dbaa71

+ 14 - 0
panda/src/egg/eggPrimitive.cxx

@@ -150,6 +150,20 @@ determine_bin() {
   return result;
   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
 //     Function: EggPrimitive::has_vertex_normal
 //       Access: Public
 //       Access: Public

+ 2 - 0
panda/src/egg/eggPrimitive.h

@@ -87,6 +87,8 @@ PUBLISHED:
   INLINE void set_bface_flag(bool flag);
   INLINE void set_bface_flag(bool flag);
   INLINE bool get_bface_flag() const;
   INLINE bool get_bface_flag() const;
 
 
+  void copy_attributes(const EggPrimitive &other);
+
   bool has_vertex_normal() const;
   bool has_vertex_normal() const;
   bool has_vertex_color() const;
   bool has_vertex_color() const;
 
 

+ 3 - 1
panda/src/egg2pg/Sources.pp

@@ -19,6 +19,7 @@
     deferredNodeProperty.h \
     deferredNodeProperty.h \
     eggBinner.h \
     eggBinner.h \
     eggLoader.h \
     eggLoader.h \
+    egg_parametrics.h \
     load_egg_file.h \
     load_egg_file.h \
     loaderFileTypeEgg.h
     loaderFileTypeEgg.h
 
 
@@ -30,6 +31,7 @@
     deferredNodeProperty.cxx \
     deferredNodeProperty.cxx \
     eggBinner.cxx \
     eggBinner.cxx \
     eggLoader.cxx \
     eggLoader.cxx \
+    egg_parametrics.cxx \
     load_egg_file.cxx \
     load_egg_file.cxx \
     loaderFileTypeEgg.cxx
     loaderFileTypeEgg.cxx
 
 
@@ -40,7 +42,7 @@
   #endif
   #endif
 
 
   #define INSTALL_HEADERS \
   #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 
   #define IGATESCAN load_egg_file.h 
 
 

+ 1 - 0
panda/src/egg2pg/egg2pg_composite1.cxx

@@ -2,3 +2,4 @@
 #include "characterMaker.cxx"
 #include "characterMaker.cxx"
 #include "computedVerticesMaker.cxx"
 #include "computedVerticesMaker.cxx"
 #include "config_egg2pg.cxx"
 #include "config_egg2pg.cxx"
+#include "egg_parametrics.cxx"

+ 5 - 98
panda/src/egg2pg/eggLoader.cxx

@@ -19,6 +19,7 @@
 #include "pandabase.h"
 #include "pandabase.h"
 
 
 #include "eggLoader.h"
 #include "eggLoader.h"
+#include "egg_parametrics.h"
 #include "config_egg2pg.h"
 #include "config_egg2pg.h"
 #include "nodePath.h"
 #include "nodePath.h"
 #include "renderState.h"
 #include "renderState.h"
@@ -463,46 +464,12 @@ make_nurbs_curve(EggNurbsCurve *egg_curve, PandaNode *parent,
   assert(parent != NULL);
   assert(parent != NULL);
   assert(!parent->is_geom_node());
   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";
-    _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";
+  PT(NurbsCurveEvaluator) nurbs = ::make_nurbs_curve(egg_curve, mat);
+  if (nurbs == (NurbsCurveEvaluator *)NULL) {
     _error = true;
     _error = true;
     return;
     return;
   }
   }
 
 
-  for (int i = 0; i < num_knots; i++) {
-    nurbs->set_knot(i, egg_curve->get_knot(i));
-  }
-
   /*
   /*
   switch (egg_curve->get_curve_type()) {
   switch (egg_curve->get_curve_type()) {
   case EggCurve::CT_xyz:
   case EggCurve::CT_xyz:
@@ -662,72 +629,12 @@ make_nurbs_surface(EggNurbsSurface *egg_surface, PandaNode *parent,
   assert(parent != NULL);
   assert(parent != NULL);
   assert(!parent->is_geom_node());
   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;
     _error = true;
     return;
     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());
   PT(SheetNode) sheet = new SheetNode(egg_surface->get_name());
   sheet->set_surface(nurbs);
   sheet->set_surface(nurbs);
 
 

+ 141 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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;
+}

+ 57 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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

+ 13 - 0
panda/src/parametrics/nurbsBasisVector.cxx

@@ -66,6 +66,19 @@ append_segment(int vertex_index, const float knots[]) {
   _segments.push_back(segment);
   _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
 //     Function: NurbsBasisVector::nurbs_blending_function
 //       Access: Private, Static
 //       Access: Private, Static

+ 2 - 0
panda/src/parametrics/nurbsBasisVector.h

@@ -59,6 +59,8 @@ public:
   void clear(int order);
   void clear(int order);
   void append_segment(int vertex_index, const float knots[]);
   void append_segment(int vertex_index, const float knots[]);
 
 
+  void transpose();
+
 private:
 private:
   static LVecBase4f nurbs_blending_function(int order, int i, int j, 
   static LVecBase4f nurbs_blending_function(int order, int i, int j, 
                                             const float knots[]);
                                             const float knots[]);

+ 43 - 0
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);
   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
 //     Function: NurbsCurveEvaluator::set_knot
 //       Access: Published
 //       Access: Published
@@ -106,6 +125,30 @@ get_knot(int i) const {
   return _knots[i];
   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
 //     Function: NurbsCurveEvaluator::evaluate
 //       Access: Published
 //       Access: Published

+ 3 - 0
panda/src/parametrics/nurbsCurveEvaluator.h

@@ -67,10 +67,13 @@ PUBLISHED:
 
 
   INLINE void set_extended_vertex(int i, int d, float value);
   INLINE void set_extended_vertex(int i, int d, float value);
   INLINE float get_extended_vertex(int i, int d) const;
   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;
   INLINE int get_num_knots() const;
   void set_knot(int i, float knot);
   void set_knot(int i, float knot);
   float get_knot(int i) const;
   float get_knot(int i) const;
+  void normalize_knots();
 
 
   INLINE int get_num_segments() const;
   INLINE int get_num_segments() const;
 
 

+ 22 - 1
panda/src/parametrics/nurbsCurveResult.I

@@ -52,7 +52,7 @@ get_end_t() const {
 //       Access: Published
 //       Access: Published
 //  Description: Computes the point on the curve corresponding to the
 //  Description: Computes the point on the curve corresponding to the
 //               indicated value in parametric time.  Returns true if
 //               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::
 INLINE bool NurbsCurveResult::
 eval_point(float t, LVecBase3f &point) {
 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);
   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
 //     Function: NurbsCurveResult::get_num_segments
 //       Access: Public
 //       Access: Public

+ 48 - 2
panda/src/parametrics/nurbsCurveResult.cxx

@@ -121,6 +121,13 @@ float NurbsCurveResult::
 eval_segment_extended_point(int segment, float t, int d) const {
 eval_segment_extended_point(int segment, float t, int d) const {
   nassertr(segment >= 0 && segment < _basis.get_num_segments(), 0.0f);
   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 order = _basis.get_order();
   int vi = _basis.get_vertex_index(segment);
   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(1).dot(geom),
                            basis.get_row(2).dot(geom),
                            basis.get_row(2).dot(geom),
                            basis.get_row(3).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;
   float t2 = t*t;
   LVecBase4f tvec(t*t2, t2, t, 1.0f);
   LVecBase4f tvec(t*t2, t2, t, 1.0f);
 
 
   float weight = tvec.dot(_composed[segment].get_col(3));
   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;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 4 - 0
panda/src/parametrics/nurbsCurveResult.h

@@ -54,11 +54,15 @@ PUBLISHED:
   INLINE bool eval_point(float t, LVecBase3f &point);
   INLINE bool eval_point(float t, LVecBase3f &point);
   INLINE bool eval_tangent(float t, LVecBase3f &tangent);
   INLINE bool eval_tangent(float t, LVecBase3f &tangent);
   INLINE float eval_extended_point(float t, int d);
   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;
   INLINE int get_num_segments() const;
   void eval_segment_point(int segment, float t, LVecBase3f &point) const;
   void eval_segment_point(int segment, float t, LVecBase3f &point) const;
   void eval_segment_tangent(int segment, float t, LVecBase3f &tangent) const;
   void eval_segment_tangent(int segment, float t, LVecBase3f &tangent) const;
   float eval_segment_extended_point(int segment, float t, int d) 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;
   INLINE float get_segment_t(int segment, float t) const;
   
   
 private:
 private:

+ 69 - 0
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);
   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
 //     Function: NurbsSurfaceEvaluator::set_u_knot
 //       Access: Published
 //       Access: Published
@@ -115,6 +136,30 @@ get_u_knot(int i) const {
   return _u_knots[i];
   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
 //     Function: NurbsSurfaceEvaluator::set_v_knot
 //       Access: Published
 //       Access: Published
@@ -146,6 +191,30 @@ get_v_knot(int i) const {
   return _v_knots[i];
   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
 //     Function: NurbsSurfaceEvaluator::evaluate
 //       Access: Published
 //       Access: Published

+ 4 - 0
panda/src/parametrics/nurbsSurfaceEvaluator.h

@@ -64,14 +64,18 @@ PUBLISHED:
 
 
   INLINE void set_extended_vertex(int ui, int vi, int d, float value);
   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;
   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;
   INLINE int get_num_u_knots() const;
   void set_u_knot(int i, float knot);
   void set_u_knot(int i, float knot);
   float get_u_knot(int i) const;
   float get_u_knot(int i) const;
+  void normalize_u_knots();
 
 
   INLINE int get_num_v_knots() const;
   INLINE int get_num_v_knots() const;
   void set_v_knot(int i, float knot);
   void set_v_knot(int i, float knot);
   float get_v_knot(int i) const;
   float get_v_knot(int i) const;
+  void normalize_v_knots();
 
 
   INLINE int get_num_u_segments() const;
   INLINE int get_num_u_segments() const;
   INLINE int get_num_v_segments() const;
   INLINE int get_num_v_segments() const;

+ 25 - 1
panda/src/parametrics/nurbsSurfaceResult.I

@@ -73,7 +73,7 @@ get_end_v() const {
 //       Access: Published
 //       Access: Published
 //  Description: Computes the point on the surface corresponding to the
 //  Description: Computes the point on the surface corresponding to the
 //               indicated value in parametric time.  Returns true if
 //               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::
 INLINE bool NurbsSurfaceResult::
 eval_point(float u, float v, LVecBase3f &point) {
 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);
                                      _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
 //     Function: NurbsSurfaceResult::get_num_u_segments
 //       Access: Public
 //       Access: Public

+ 57 - 4
panda/src/parametrics/nurbsSurfaceResult.cxx

@@ -37,6 +37,9 @@ NurbsSurfaceResult(const NurbsBasisVector &u_basis,
   _num_u_vertices(num_u_vertices),
   _num_u_vertices(num_u_vertices),
   _num_v_vertices(num_v_vertices)
   _num_v_vertices(num_v_vertices)
 {
 {
+  // The V basis matrices will always be transposed.
+  _v_basis.transpose();
+
   _last_u_segment = -1;
   _last_u_segment = -1;
   _last_v_segment = -1;
   _last_v_segment = -1;
   int u_order = _u_basis.get_order();
   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++) {
   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);
     int vn = _v_basis.get_vertex_index(vi);
     nassertv(vn >= 0 && vn + v_order - 1 < _num_v_vertices);
     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::
 float NurbsSurfaceResult::
 eval_segment_extended_point(int ui, int vi, float u, float v, int d) const {
 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
   // Calculate the composition of the basis matrices and the geometry
   // matrix on-the-fly.
   // 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);
   const LMatrix4f &u_basis_mat = _u_basis.get_basis(ui);
   int u_order = _u_basis.get_order();
   int u_order = _u_basis.get_order();
   int v_order = _v_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;
   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);
   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;
   float u2 = u*u;
   LVecBase4f uvec(u*u2, u2, u, 1.0f);
   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);
   LVecBase4f vvec(v*v2, v2, v, 1.0f);
 
 
   float weight = vvec.dot(uvec * _composed[i]._w);
   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;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 4 - 0
panda/src/parametrics/nurbsSurfaceResult.h

@@ -51,12 +51,16 @@ PUBLISHED:
   INLINE bool eval_point(float u, float v, LVecBase3f &point);
   INLINE bool eval_point(float u, float v, LVecBase3f &point);
   INLINE bool eval_normal(float u, float v, LVecBase3f &normal);
   INLINE bool eval_normal(float u, float v, LVecBase3f &normal);
   INLINE float eval_extended_point(float u, float v, int d);
   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_u_segments() const;
   INLINE int get_num_v_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_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;
   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;
   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_u(int ui, float u) const;
   INLINE float get_segment_v(int vi, float v) const;
   INLINE float get_segment_v(int vi, float v) const;
   
   

+ 2 - 4
panda/src/parametrics/ropeNode.cxx

@@ -287,10 +287,8 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
       verts.push_back(point);
       verts.push_back(point);
 
 
       if (use_vertex_color) {
       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);
         colors.push_back(color);
       }
       }
 
 

+ 4 - 8
panda/src/parametrics/sheetNode.cxx

@@ -293,15 +293,11 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
           uvs.push_back(TexCoordf(u1_tc, v_tc));
           uvs.push_back(TexCoordf(u1_tc, v_tc));
 
 
           if (use_vertex_color) {
           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);
             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);
             colors.push_back(c1);
           }
           }
         }
         }