Panda3D
cubicCurveseg.cxx
1 // Filename: cubicCurveseg.cxx
2 // Created by: drose (04Mar01)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "piecewiseCurve.h"
16 
17 #include "config_parametrics.h"
18 #include "hermiteCurve.h"
19 
20 #include "datagram.h"
21 #include "datagramIterator.h"
22 #include "bamWriter.h"
23 #include "bamReader.h"
24 
25 TypeHandle CubicCurveseg::_type_handle;
26 
27 ////////////////////////////////////////////////////////////////////
28 // Function: CubicCurveseg::Constructor
29 // Access: Public
30 // Description:
31 ////////////////////////////////////////////////////////////////////
32 CubicCurveseg::
33 CubicCurveseg() {
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: CubicCurveseg::Constructor
38 // Access: Public
39 // Description: Creates the curveseg given the four basis vectors
40 // (the columns of the matrix) explicitly.
41 ////////////////////////////////////////////////////////////////////
42 CubicCurveseg::
43 CubicCurveseg(const LMatrix4 &basis) {
44  Bx = basis.get_col(0);
45  By = basis.get_col(1);
46  Bz = basis.get_col(2);
47  Bw = basis.get_col(3);
48  rational = true;
49 }
50 
51 
52 ////////////////////////////////////////////////////////////////////
53 // Function: CubicCurveseg::Constructor
54 // Access: Public
55 // Description: Creates the curveseg as a Bezier segment.
56 ////////////////////////////////////////////////////////////////////
57 CubicCurveseg::
58 CubicCurveseg(const BezierSeg &seg) {
59  bezier_basis(seg);
60 }
61 
62 
63 ////////////////////////////////////////////////////////////////////
64 // Function: CubicCurveseg::Constructor
65 // Access: Public
66 // Description: Creates the curveseg as a NURBS segment. See
67 // nurbs_basis for a description of the parameters.
68 ////////////////////////////////////////////////////////////////////
69 CubicCurveseg::
70 CubicCurveseg(int order, const PN_stdfloat knots[], const LVecBase4 cvs[]) {
71  nurbs_basis(order, knots, cvs);
72 }
73 
74 ////////////////////////////////////////////////////////////////////
75 // Function: CubicCurveseg::Destructor
76 // Access: Protected
77 // Description:
78 ////////////////////////////////////////////////////////////////////
79 CubicCurveseg::
80 ~CubicCurveseg() {
81 }
82 
83 
84 
85 ////////////////////////////////////////////////////////////////////
86 // Function: CubicCurveseg::get_point
87 // Access: Published, Virtual
88 // Description: Computes the surface point at a given parametric
89 // point t.
90 ////////////////////////////////////////////////////////////////////
91 bool CubicCurveseg::
92 get_point(PN_stdfloat t, LVecBase3 &point) const {
93  PN_stdfloat t_sqrd = t*t;
94  evaluate_point(LVecBase4(t*t_sqrd, t_sqrd, t, 1.0f), point);
95  return true;
96 }
97 
98 ////////////////////////////////////////////////////////////////////
99 // Function: CubicCurveseg::get_tangent
100 // Access: Published, Virtual
101 // Description: Computes the surface tangent at a given parametric
102 // point t.
103 ////////////////////////////////////////////////////////////////////
104 bool CubicCurveseg::
105 get_tangent(PN_stdfloat t, LVecBase3 &tangent) const {
106  evaluate_vector(LVecBase4(3.0f*t*t, 2.0f*t, 1.0f, 0.0f), tangent);
107  return true;
108 }
109 
110 ////////////////////////////////////////////////////////////////////
111 // Function: CubicCurveseg::get_pt
112 // Access: Published, Virtual
113 // Description: Simultaneously computes the point and the tangent at
114 // the given parametric point.
115 ////////////////////////////////////////////////////////////////////
116 bool CubicCurveseg::
117 get_pt(PN_stdfloat t, LVecBase3 &point, LVecBase3 &tangent) const {
118  PN_stdfloat t_sqrd=t*t;
119  evaluate_point(LVecBase4(t*t_sqrd, t_sqrd, t, 1.0f), point);
120  evaluate_vector(LVecBase4(3.0f*t_sqrd, /*2.0f*t*/t+t, 1.0f, 0.0f), tangent);
121  return true;
122 }
123 
124 ////////////////////////////////////////////////////////////////////
125 // Function: CubicCurveseg::get_2ndtangent
126 // Access: Published, Virtual
127 // Description: Computes the surface 2nd-order tangent at a given
128 // parametric point t.
129 ////////////////////////////////////////////////////////////////////
130 bool CubicCurveseg::
131 get_2ndtangent(PN_stdfloat t, LVecBase3 &tangent2) const {
132  evaluate_vector(LVecBase4(6.0f*t, 2.0f, 0.0f, 0.0f), tangent2);
133  return true;
134 }
135 
136 
137 ////////////////////////////////////////////////////////////////////
138 // Function: CubicCurveseg::hermite_basis
139 // Access: Public
140 // Description: Defines the curve segment as a Hermite. This only
141 // sets up the basis vectors, so the curve will be
142 // computed correctly; it does not retain the CV's.
143 ////////////////////////////////////////////////////////////////////
144 void CubicCurveseg::
146  const HermiteCurveCV &cv1,
147  PN_stdfloat tlength) {
148  static LMatrix4
149  Mh( 2.0f, -3.0f, 0.0f, 1.0f,
150  -2.0f, 3.0f, 0.0f, 0.0f,
151  1.0f, -2.0f, 1.0f, 0.0f,
152  1.0f, -1.0f, 0.0f, 0.0f);
153 
154  LVecBase4 Gx(cv0._p[0], cv1._p[0],
155  cv0._out[0]*tlength, cv1._in[0]*tlength);
156  LVecBase4 Gy(cv0._p[1], cv1._p[1],
157  cv0._out[1]*tlength, cv1._in[1]*tlength);
158  LVecBase4 Gz(cv0._p[2], cv1._p[2],
159  cv0._out[2]*tlength, cv1._in[2]*tlength);
160 
161  Bx = Gx * Mh;
162  By = Gy * Mh;
163  Bz = Gz * Mh;
164  rational = false;
165 }
166 
167 ////////////////////////////////////////////////////////////////////
168 // Function: CubicCurveseg::bezier_basis
169 // Access: Public
170 // Description: Defines the curve segment as a Bezier. This only
171 // sets up the basis vectors, so the curve will be
172 // computed correctly; it does not retain the CV's.
173 ////////////////////////////////////////////////////////////////////
174 void CubicCurveseg::
175 bezier_basis(const BezierSeg &seg) {
176  static LMatrix4
177  Mb(-1.0f, 3.0f, -3.0f, 1.0f,
178  3.0f, -6.0f, 3.0f, 0.0f,
179  -3.0f, 3.0f, 0.0f, 0.0f,
180  1.0f, 0.0f, 0.0f, 0.0f);
181 
182  LVecBase4 Gx(seg._v[0][0], seg._v[1][0], seg._v[2][0], seg._v[3][0]);
183  LVecBase4 Gy(seg._v[0][1], seg._v[1][1], seg._v[2][1], seg._v[3][1]);
184  LVecBase4 Gz(seg._v[0][2], seg._v[1][2], seg._v[2][2], seg._v[3][2]);
185 
186  Bx = Gx * Mb;
187  By = Gy * Mb;
188  Bz = Gz * Mb;
189  rational = false;
190 }
191 
192 static LVecBase4
193 nurbs_blending_function(int order, int i, int j,
194  const PN_stdfloat knots[]) {
195  // This is doubly recursive. Ick.
196  LVecBase4 r;
197 
198  if (j==1) {
199  if (i==order-1 && knots[i] < knots[i+1]) {
200  r.set(0.0f, 0.0f, 0.0f, 1.0f);
201  } else {
202  r.set(0.0f, 0.0f, 0.0f, 0.0f);
203  }
204 
205  } else {
206  LVecBase4 bi0 = nurbs_blending_function(order, i, j-1, knots);
207  LVecBase4 bi1 = nurbs_blending_function(order, i+1, j-1, knots);
208 
209  PN_stdfloat d0 = knots[i+j-1] - knots[i];
210  PN_stdfloat d1 = knots[i+j] - knots[i+1];
211 
212  // First term. Division by zero is defined to equal zero.
213  if (d0 != 0.0f) {
214  if (d1 != 0.0f) {
215  r = bi0 / d0 - bi1 / d1;
216  } else {
217  r = bi0 / d0;
218  }
219 
220  } else if (d1 != 0.0f) {
221  r = - bi1 / d1;
222 
223  } else {
224  r.set(0.0f, 0.0f, 0.0f, 0.0f);
225  }
226 
227  // scale by t.
228  r[0] = r[1];
229  r[1] = r[2];
230  r[2] = r[3];
231  r[3] = 0.0f;
232 
233  // Second term.
234  if (d0 != 0.0f) {
235  if (d1 != 0.0f) {
236  r += bi0 * (- knots[i] / d0) + bi1 * (knots[i+j] / d1);
237  } else {
238  r += bi0 * (- knots[i] / d0);
239  }
240 
241  } else if (d1 != 0.0f) {
242  r += bi1 * (knots[i+j] / d1);
243  }
244  }
245 
246  return r;
247 }
248 
249 void
250 compute_nurbs_basis(int order,
251  const PN_stdfloat knots_in[],
252  LMatrix4 &basis) {
253  int i;
254 
255  // Scale the supplied knots to the range 0..1.
256  PN_stdfloat knots[8];
257  PN_stdfloat mink = knots_in[order-1];
258  PN_stdfloat maxk = knots_in[order];
259 
260  if (mink==maxk) {
261  // Huh. What were you thinking? This is a trivial NURBS.
262  parametrics_cat->warning()
263  << "Trivial NURBS curve specified." << endl;
264  memset((void *)&basis, 0, sizeof(LMatrix4));
265  return;
266  }
267 
268  for (i = 0; i<2*order; i++) {
269  knots[i] = (knots_in[i] - mink) / (maxk-mink);
270  }
271 
272 
273  LVecBase4 b[4];
274  for (i = 0; i<order; i++) {
275  b[i] = nurbs_blending_function(order, i, order, knots);
276  }
277 
278  for (i = 0; i<order; i++) {
279  basis.set_row(i, b[i]);
280  }
281 
282  for (i=order; i<4; i++) {
283  basis.set_row(i, LVecBase4::zero());
284  }
285 }
286 
287 
288 
289 ////////////////////////////////////////////////////////////////////
290 // Function: CubicCurveseg::nurbs_basis
291 // Access: Public
292 // Description: Defines the curve segment as a NURBS. Order is one
293 // more than the degree, and must be 1, 2, 3, or 4;
294 // knots is an array of order*2 values, and cvs is an
295 // array of order values.
296 ////////////////////////////////////////////////////////////////////
297 void CubicCurveseg::
298 nurbs_basis(int order, const PN_stdfloat knots[], const LVecBase4 cvs[]) {
299  assert(order>=1 && order<=4);
300 
301  LMatrix4 B;
302  compute_nurbs_basis(order, knots, B);
303 
304  // Create a local copy of our CV's, so we can zero out the unused
305  // elements.
306  LVecBase4 c[4];
307  for (int i = 0; i < 4; i++) {
308  c[i] = (i<order) ? cvs[i] : LVecBase4(0.0f, 0.0f, 0.0f, 0.0f);
309  }
310 
311  Bx = LVecBase4(c[0][0], c[1][0], c[2][0], c[3][0]) * B;
312  By = LVecBase4(c[0][1], c[1][1], c[2][1], c[3][1]) * B;
313  Bz = LVecBase4(c[0][2], c[1][2], c[2][2], c[3][2]) * B;
314  Bw = LVecBase4(c[0][3], c[1][3], c[2][3], c[3][3]) * B;
315 
316  rational = true;
317 }
318 
319 ////////////////////////////////////////////////////////////////////
320 // Function: CubicCurveseg::get_bezier_seg
321 // Access: Public, Virtual
322 // Description: Fills the BezierSeg structure with a description of
323 // the curve segment as a Bezier, if possible, but does
324 // not change the _t member of the structure. Returns
325 // true if successful, false otherwise.
326 ////////////////////////////////////////////////////////////////////
327 bool CubicCurveseg::
329  static LMatrix4
330  Mbi(0.0f, 0.0f, 0.0f, 1.0f,
331  0.0f, 0.0f, 1.0f/3.0f, 1.0f,
332  0.0f, 1.0f/3.0f, 2.0f/3.0f, 1.0f,
333  1.0f, 1.0f, 1.0f, 1.0f);
334 
335  LVecBase4 Gx = Bx * Mbi;
336  LVecBase4 Gy = By * Mbi;
337  LVecBase4 Gz = Bz * Mbi;
338 
339  if (rational) {
340  LVecBase4 Gw = Bw * Mbi;
341  seg._v[0].set(Gx[0]/Gw[0], Gy[0]/Gw[0], Gz[0]/Gw[0]);
342  seg._v[1].set(Gx[1]/Gw[1], Gy[1]/Gw[1], Gz[1]/Gw[1]);
343  seg._v[2].set(Gx[2]/Gw[2], Gy[2]/Gw[2], Gz[2]/Gw[2]);
344  seg._v[3].set(Gx[3]/Gw[3], Gy[3]/Gw[3], Gz[3]/Gw[3]);
345  } else {
346  seg._v[0].set(Gx[0], Gy[0], Gz[0]);
347  seg._v[1].set(Gx[1], Gy[1], Gz[1]);
348  seg._v[2].set(Gx[2], Gy[2], Gz[2]);
349  seg._v[3].set(Gx[3], Gy[3], Gz[3]);
350  }
351 
352  return true;
353 }
354 
355 // We need this operator since Performer didn't supply it.
356 inline LVecBase4
357 col_mult(const LMatrix4 &M, const LVecBase4 &v) {
358  return LVecBase4(M(0,0)*v[0] + M(0,1)*v[1] + M(0,2)*v[2] + M(0,3)*v[3],
359  M(1,0)*v[0] + M(1,1)*v[1] + M(1,2)*v[2] + M(1,3)*v[3],
360  M(2,0)*v[0] + M(2,1)*v[1] + M(2,2)*v[2] + M(2,3)*v[3],
361  M(3,0)*v[0] + M(3,1)*v[1] + M(3,2)*v[2] + M(3,3)*v[3]);
362 }
363 
364 ////////////////////////////////////////////////////////////////////
365 // Function: compute_seg_col
366 // Description: Interprets the parameters for a particular column of
367 // compute_seg. Builds the indicated column of T
368 // and P.
369 ////////////////////////////////////////////////////////////////////
370 static bool
371 compute_seg_col(int c,
372  int rtype, PN_stdfloat t, const LVecBase4 &v,
373  const LMatrix4 &B,
374  const LMatrix4 &Bi,
375  const LMatrix4 &G,
376  const LMatrix4 &GB,
377  LMatrix4 &T, LMatrix4 &P) {
378  bool keep_orig = ((rtype & RT_KEEP_ORIG) != 0);
379 
380  if (parametrics_cat.is_debug()) {
381  parametrics_cat.debug()
382  << "Computing col " << c << " type " << (rtype & RT_BASE_TYPE)
383  << " at " << t << " keep_orig = " << keep_orig
384  << " v = " << v << "\n";
385  }
386 
387  switch (rtype & RT_BASE_TYPE) {
388  // RT_point defines the point on the curve at t. This is the vector
389  // [ t^3 t^2 t^1 t^0 ].
390  PN_stdfloat t_sqrd,t_cubed;
391 
392  case RT_POINT:
393  t_sqrd = t*t;
394  t_cubed = t_sqrd*t;
395  T.set_col(c, LVecBase4(t_cubed, t_sqrd, t, 1.0f));
396  if (keep_orig) {
397  LVecBase4 vec(t_cubed, t_sqrd, t, 1.0f);
398  LVecBase4 ov = col_mult(GB, vec);
399  if (parametrics_cat.is_debug()) {
400  parametrics_cat.debug()
401  << "orig point = " << ov << "\n";
402  }
403  P.set_col(c, ov);
404  } else {
405  P.set_col(c, v);
406  }
407  break;
408 
409  // RT_tangent defines the tangent to the curve at t. This is
410  // the vector [ 3t^2 2t 1 0 ].
411  case RT_TANGENT:
412  t_sqrd = t*t;
413  T.set_col(c, LVecBase4(3.0f*t_sqrd, t+t, 1.0f, 0.0f));
414  if (keep_orig) {
415  LVecBase4 vec(3.0f*t_sqrd, /*2.0f*t*/t+t, 1.0f, 0.0f);
416  LVecBase4 ov = col_mult(GB, vec);
417  if (parametrics_cat.is_debug()) {
418  parametrics_cat.debug()
419  << "Matrix is:\n";
420  GB.write(parametrics_cat.debug(false), 2);
421  parametrics_cat.debug(false)
422  << "vector is " << vec << "\n"
423  << "orig tangent = " << ov << "\n";
424  }
425  P.set_col(c, ov);
426  } else {
427  P.set_col(c, v);
428  }
429  break;
430 
431  // RT_cv defines the cth control point. This is the cth column
432  // vector from Bi.
433  case RT_CV:
434  T.set_col(c, Bi.get_col(c));
435  if (keep_orig) {
436  if (parametrics_cat.is_debug()) {
437  parametrics_cat.debug()
438  << "orig CV = " << G.get_col(c) << "\n";
439  }
440  P.set_col(c, G.get_col(c));
441  } else {
442  P.set_col(c, v);
443  }
444  break;
445 
446  default:
447  cerr << "Invalid rebuild type in compute_seg\n";
448  return false;
449  }
450 
451  return true;
452 }
453 
454 ////////////////////////////////////////////////////////////////////
455 // Function: CubicCurveseg::compute_seg
456 // Access: Public, Static
457 // Description: Given a set of four properties of a curve segment
458 // (e.g. four points, four tangent values, four control
459 // points, or any combination), and a basis matrix,
460 // computes the corresponding geometry matrix that
461 // (together with the basis matrix) represents the curve
462 // that satisfies the four properties.
463 //
464 // The basis matrix is passed in as B, and its inverse
465 // must be precomputed and passed in as Bi.
466 //
467 // The result is returned in the matrix G, each column
468 // of which represents the cth control vertex. If any
469 // of the four properties has RT_KEEP_ORIG set (see
470 // below), G's input value is used to define the
471 // original shape of the curve; otherwise, G's input
472 // value is ignored.
473 //
474 // Each property is defined by an rtype, which may be
475 // any of RT_POINT, RT_TANGENT, or RT_CV, and may or may
476 // not be or'ed with RT_KEEP_ORIG. The meanings of the
477 // types are as follows:
478 //
479 // RT_POINT defines a specific point which the curve
480 // segment must pass through. t is in the range [0,1]
481 // and represents the parametric value at which the
482 // curve segment will intersect the given point. If
483 // RT_KEEP_ORIG is not set, v defines the point;
484 // otherwise, v is ignored and the original curve at
485 // point t defines the point.
486 //
487 // RT_TANGENT defines a specific tangent value which the
488 // curve segment must have at point t. As with
489 // RT_POINT, if RT_KEEP_ORIG is not set, v defines the
490 // tangent; otherwise, v is ignored and the original
491 // curve defines the tangent.
492 //
493 // RT_CV defines a specific control vertex which the
494 // curve segment must have. In this case, t is ignored.
495 // The position within the argument list determines
496 // which control vertex is applicable; e.g. rtype0 =
497 // RT_CV defines control vertex 0, and rtype2 = RT_CV
498 // defines control vertex 2. If RT_KEEP_ORIG is not
499 // set, v defines the new control vertex; otherwise, the
500 // control vertex is taken from G.
501 //
502 // The return value is true if all the parameters are
503 // sensible, or false if there is some error.
504 ////////////////////////////////////////////////////////////////////
505 bool CubicCurveseg::
506 compute_seg(int rtype0, PN_stdfloat t0, const LVecBase4 &v0,
507  int rtype1, PN_stdfloat t1, const LVecBase4 &v1,
508  int rtype2, PN_stdfloat t2, const LVecBase4 &v2,
509  int rtype3, PN_stdfloat t3, const LVecBase4 &v3,
510  const LMatrix4 &B,
511  const LMatrix4 &Bi,
512  LMatrix4 &G) {
513 
514  // We can define a cubic curve segment given four arbitrary
515  // properties of the segment: any point along the curve, any tangent
516  // along the curve, any control point. Given any four such
517  // properties, a single cubic curve segment is defined.
518 
519  // For a given cubic curve segment so defined, and given a basis
520  // matrix B, we can define the four control vertices that represent
521  // the segment with the basis matrix. That is, we can define the
522  // matrix G such that G * B * tc, where tc is [ t^3 t^2 t^1 t^0 ]
523  // for t in [ 0..1 ], represents the point on the curve segment
524  // corresponding to t.
525 
526  // First, we build a matrix T, such that each of the four columns of
527  // T contains the vector that would compute the corresponding
528  // property. We also build a corresponding matrix P, such that each
529  // of its columns contains the vector that is the solution of the
530  // corresponding column in T.
531 
532  LMatrix4 T, P, GB;
533 
534  // GB is G * B, but we only need to compute this if any of the
535  // columns wants the value from the original G.
536  if ((rtype0 | rtype1 | rtype2 | rtype3) & RT_KEEP_ORIG) {
537  GB = G * B;
538  }
539 
540  if (! (compute_seg_col(0, rtype0, t0, v0, B, Bi, G, GB, T, P) &&
541  compute_seg_col(1, rtype1, t1, v1, B, Bi, G, GB, T, P) &&
542  compute_seg_col(2, rtype2, t2, v2, B, Bi, G, GB, T, P) &&
543  compute_seg_col(3, rtype3, t3, v3, B, Bi, G, GB, T, P))) {
544  return false;
545  }
546 
547  LMatrix4 Ti;
548  Ti = invert(T);
549 
550  // Now we have T and P such that P represents the solution of T,
551  // when T is applied to the geometry and basis matrices. That is,
552  // each column of P represents the solution computed by the
553  // corresponding column of T. P = G * B * T.
554 
555  // We simply solve for G and get G = P * T^(-1) * B^(-1).
556 
557  G = P * Ti * Bi;
558 
559  return true;
560 }
561 
562 ////////////////////////////////////////////////////////////////////
563 // Function: CubicCurveseg::register_with_factory
564 // Access: Public, Static
565 // Description: Initializes the factory for reading these things from
566 // Bam files.
567 ////////////////////////////////////////////////////////////////////
568 void CubicCurveseg::
570  BamReader::get_factory()->register_factory(get_class_type(), make_CubicCurveseg);
571 }
572 
573 ////////////////////////////////////////////////////////////////////
574 // Function: CubicCurveseg::make_CubicCurveseg
575 // Access: Protected
576 // Description: Factory method to generate an object of this type.
577 ////////////////////////////////////////////////////////////////////
578 TypedWritable *CubicCurveseg::
579 make_CubicCurveseg(const FactoryParams &params) {
580  CubicCurveseg *me = new CubicCurveseg;
581  DatagramIterator scan;
582  BamReader *manager;
583 
584  parse_params(params, scan, manager);
585  me->fillin(scan, manager);
586  return me;
587 }
588 
589 ////////////////////////////////////////////////////////////////////
590 // Function: CubicCurveseg::write_datagram
591 // Access: Protected, Virtual
592 // Description: Function to write the important information in
593 // the particular object to a Datagram
594 ////////////////////////////////////////////////////////////////////
595 void CubicCurveseg::
596 write_datagram(BamWriter *manager, Datagram &me) {
597  ParametricCurve::write_datagram(manager, me);
598 
599  Bx.write_datagram(me);
600  By.write_datagram(me);
601  Bz.write_datagram(me);
602  Bw.write_datagram(me);
603  me.add_bool(rational);
604 }
605 
606 ////////////////////////////////////////////////////////////////////
607 // Function: CubicCurveseg::fillin
608 // Access: Protected
609 // Description: Function that reads out of the datagram (or asks
610 // manager to read) all of the data that is needed to
611 // re-create this object and stores it in the appropiate
612 // place
613 ////////////////////////////////////////////////////////////////////
614 void CubicCurveseg::
615 fillin(DatagramIterator &scan, BamReader *manager) {
616  ParametricCurve::fillin(scan, manager);
617 
618  Bx.read_datagram(scan);
619  By.read_datagram(scan);
620  Bz.read_datagram(scan);
621  Bw.read_datagram(scan);
622  rational = scan.get_bool();
623 }
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
bool get_bool()
Extracts a boolean value.
virtual bool get_point(PN_stdfloat t, LVecBase3 &point) const
Computes the surface point at a given parametric point t.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
void hermite_basis(const HermiteCurveCV &cv0, const HermiteCurveCV &cv1, PN_stdfloat tlength=1.0f)
Defines the curve segment as a Hermite.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
void bezier_basis(const BezierSeg &seg)
Defines the curve segment as a Bezier.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
virtual bool get_2ndtangent(PN_stdfloat t, LVecBase3 &tangent2) const
Computes the surface 2nd-order tangent at a given parametric point t.
A CubicCurveseg is any curve that can be completely described by four 4-valued basis vectors...
Definition: cubicCurveseg.h:58
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:118
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
void read_datagram(DatagramIterator &source)
Reads the vector from the Datagram using get_stdfloat().
Definition: lvecBase4.h:1458
virtual bool get_bezier_seg(BezierSeg &seg) const
Fills the BezierSeg structure with a description of the curve segment as a Bezier, if possible, but does not change the _t member of the structure.
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
void set_col(int col, const LVecBase4f &v)
Replaces the indicated column of the matrix.
Definition: lmatrix.h:1204
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
static bool compute_seg(int rtype0, PN_stdfloat t0, const LVecBase4 &v0, int rtype1, PN_stdfloat t1, const LVecBase4 &v1, int rtype2, PN_stdfloat t2, const LVecBase4 &v2, int rtype3, PN_stdfloat t3, const LVecBase4 &v3, const LMatrix4 &B, const LMatrix4 &Bi, LMatrix4 &G)
Given a set of four properties of a curve segment (e.g.
void write_datagram(Datagram &destination) const
Writes the vector to the Datagram using add_stdfloat().
Definition: lvecBase4.h:1438
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
A single CV of a Hermite curve.
Definition: hermiteCurve.h:52
LVecBase4f get_col(int col) const
Retrieves the indicated column of the matrix as a 4-component vector.
Definition: lmatrix.h:1294
static void register_with_read_factory()
Initializes the factory for reading these things from Bam files.
void nurbs_basis(int order, const PN_stdfloat knots[], const LVecBase4 cvs[])
Defines the curve segment as a NURBS.
void set_row(int row, const LVecBase4f &v)
Replaces the indicated row of the matrix.
Definition: lmatrix.h:1187
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
virtual bool get_pt(PN_stdfloat t, LVecBase3 &point, LVecBase3 &tangent) const
Simultaneously computes the point and the tangent at the given parametric point.
virtual bool get_tangent(PN_stdfloat t, LVecBase3 &tangent) const
Computes the surface tangent at a given parametric point t.
static const LVecBase4f & zero()
Returns a zero-length vector.
Definition: lvecBase4.h:493