source: trunk/src/opengl/glu/nurbs/internals/arctess.cpp

Last change on this file was 2689, checked in by jeroen, 26 years ago

* empty log message *

File size: 17.7 KB
Line 
1/* $Id: arctess.cpp,v 1.1 2000-02-09 08:50:20 jeroen Exp $ */
2/*
3** License Applicability. Except to the extent portions of this file are
4** made subject to an alternative license as permitted in the SGI Free
5** Software License B, Version 1.0 (the "License"), the contents of this
6** file are subject only to the provisions of the License. You may not use
7** this file except in compliance with the License. You may obtain a copy
8** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
9** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
10**
11** http://oss.sgi.com/projects/FreeB
12**
13** Note that, as provided in the License, the Software is distributed on an
14** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
15** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
16** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
17** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
18**
19** Original Code. The Original Code is: OpenGL Sample Implementation,
20** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
21** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
22** Copyright in any portions created by third parties is as indicated
23** elsewhere herein. All Rights Reserved.
24**
25** Additional Notice Provisions: The application programming interfaces
26** established by SGI in conjunction with the Original Code are The
27** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
28** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
29** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
30** Window System(R) (Version 1.3), released October 19, 1998. This software
31** was created using the OpenGL(R) version 1.2.1 Sample Implementation
32** published by SGI, but has not been independently verified as being
33** compliant with the OpenGL(R) version 1.2.1 Specification.
34*/
35
36/*
37 * arctessellator.c++
38 *
39 * $Date: 2000-02-09 08:50:20 $ $Revision: 1.1 $
40 * $Header: /home/ktk/tmp/odin/2007/netlabs.cvs/odin32/src/opengl/glu/nurbs/internals/arctess.cpp,v 1.1 2000-02-09 08:50:20 jeroen Exp $
41 */
42
43/*#include <stdlib.h>*/
44#include "glimports.h"
45#include "mystdio.h"
46#include "myassert.h"
47#include "arctess.h"
48#include "bufpool.h"
49#include "simplemath.h"
50#include "bezierarc.h"
51#include "trimvertex.h"
52#include "trimvertpool.h"
53
54#define NOELIMINATION
55
56#define steps_function(large, small, rate) (max(1, 1+ (int) ((large-small)/rate)));
57
58/*-----------------------------------------------------------------------------
59 * ArcTessellator - construct an ArcTessellator
60 *-----------------------------------------------------------------------------
61 */
62
63ArcTessellator::ArcTessellator( TrimVertexPool& t, Pool& p )
64 : trimvertexpool(t), pwlarcpool(p)
65{
66}
67
68/*-----------------------------------------------------------------------------
69 * ~ArcTessellator - destroy an ArcTessellator
70 *-----------------------------------------------------------------------------
71 */
72
73ArcTessellator::~ArcTessellator( void )
74{
75}
76
77/*-----------------------------------------------------------------------------
78 * bezier - construct a bezier arc and attach it to an Arc
79 *-----------------------------------------------------------------------------
80 */
81
82void
83ArcTessellator::bezier( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2 )
84{
85 assert( arc != 0 );
86 assert( ! arc->isTessellated() );
87
88#ifndef NDEBUG
89 switch( arc->getside() ) {
90 case arc_left:
91 assert( s1 == s2 );
92 assert( t2 < t1 );
93 break;
94 case arc_right:
95 assert( s1 == s2 );
96 assert( t1 < t2 );
97 break;
98 case arc_top:
99 assert( t1 == t2 );
100 assert( s2 < s1 );
101 break;
102 case arc_bottom:
103 assert( t1 == t2 );
104 assert( s1 < s2 );
105 break;
106 case arc_none:
107 (void) abort();
108 break;
109 }
110#endif
111
112 TrimVertex *p = trimvertexpool.get(2);
113 arc->pwlArc = new(pwlarcpool) PwlArc( 2, p );
114 p[0].param[0] = s1;
115 p[0].param[1] = t1;
116 p[1].param[0] = s2;
117 p[1].param[1] = t2;
118 assert( (s1 == s2) || (t1 == t2) );
119 arc->setbezier();
120}
121
122
123/*-----------------------------------------------------------------------------
124 * pwl_left - construct a left boundary pwl arc and attach it to an arc
125 *-----------------------------------------------------------------------------
126 */
127
128void
129ArcTessellator::pwl_left( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate )
130{
131 assert( t2 < t1 );
132
133/* if(rate <= 0.06) rate = 0.06;*/
134/* int nsteps = 1 + (int) ((t1 - t2) / rate ); */
135 int nsteps = steps_function(t1, t2, rate);
136
137
138 REAL stepsize = (t1 - t2) / (REAL) nsteps;
139
140 TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
141 int i;
142 for( i = nsteps; i > 0; i-- ) {
143 newvert[i].param[0] = s;
144 newvert[i].param[1] = t2;
145 t2 += stepsize;
146 }
147 newvert[i].param[0] = s;
148 newvert[i].param[1] = t1;
149
150 arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_left );
151}
152
153/*-----------------------------------------------------------------------------
154 * pwl_right - construct a right boundary pwl arc and attach it to an arc
155 *-----------------------------------------------------------------------------
156 */
157
158void
159ArcTessellator::pwl_right( Arc *arc, REAL s, REAL t1, REAL t2, REAL rate )
160{
161 assert( t1 < t2 );
162
163/* if(rate <= 0.06) rate = 0.06;*/
164
165/* int nsteps = 1 + (int) ((t2 - t1) / rate ); */
166 int nsteps = steps_function(t2,t1,rate);
167 REAL stepsize = (t2 - t1) / (REAL) nsteps;
168
169 TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
170 int i;
171 for( i = 0; i < nsteps; i++ ) {
172 newvert[i].param[0] = s;
173 newvert[i].param[1] = t1;
174 t1 += stepsize;
175 }
176 newvert[i].param[0] = s;
177 newvert[i].param[1] = t2;
178
179 arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_right );
180}
181
182
183/*-----------------------------------------------------------------------------
184 * pwl_top - construct a top boundary pwl arc and attach it to an arc
185 *-----------------------------------------------------------------------------
186 */
187
188void
189ArcTessellator::pwl_top( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate )
190{
191 assert( s2 < s1 );
192
193/* if(rate <= 0.06) rate = 0.06;*/
194
195/* int nsteps = 1 + (int) ((s1 - s2) / rate ); */
196 int nsteps = steps_function(s1,s2,rate);
197 REAL stepsize = (s1 - s2) / (REAL) nsteps;
198
199 TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
200 int i;
201 for( i = nsteps; i > 0; i-- ) {
202 newvert[i].param[0] = s2;
203 newvert[i].param[1] = t;
204 s2 += stepsize;
205 }
206 newvert[i].param[0] = s1;
207 newvert[i].param[1] = t;
208
209 arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_top );
210}
211
212/*-----------------------------------------------------------------------------
213 * pwl_bottom - construct a bottom boundary pwl arc and attach it to an arc
214 *-----------------------------------------------------------------------------
215 */
216
217void
218ArcTessellator::pwl_bottom( Arc *arc, REAL t, REAL s1, REAL s2, REAL rate )
219{
220 assert( s1 < s2 );
221
222/* if(rate <= 0.06) rate = 0.06;*/
223
224/* int nsteps = 1 + (int) ((s2 - s1) / rate ); */
225 int nsteps = steps_function(s2,s1,rate);
226 REAL stepsize = (s2 - s1) / (REAL) nsteps;
227
228 TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
229 int i;
230 for( i = 0; i < nsteps; i++ ) {
231 newvert[i].param[0] = s1;
232 newvert[i].param[1] = t;
233 s1 += stepsize;
234 }
235 newvert[i].param[0] = s2;
236 newvert[i].param[1] = t;
237
238 arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom );
239}
240
241/*-----------------------------------------------------------------------------
242 * pwl - construct a pwl arc and attach it to an arc
243 *-----------------------------------------------------------------------------
244 */
245
246void
247ArcTessellator::pwl( Arc *arc, REAL s1, REAL s2, REAL t1, REAL t2, REAL rate )
248{
249
250/* if(rate <= 0.06) rate = 0.06;*/
251
252 int snsteps = 1 + (int) (abs(s2 - s1) / rate );
253 int tnsteps = 1 + (int) (abs(t2 - t1) / rate );
254 int nsteps = max(1,max( snsteps, tnsteps ));
255
256 REAL sstepsize = (s2 - s1) / (REAL) nsteps;
257 REAL tstepsize = (t2 - t1) / (REAL) nsteps;
258 TrimVertex *newvert = trimvertexpool.get( nsteps+1 );
259 long i;
260 for( i = 0; i < nsteps; i++ ) {
261 newvert[i].param[0] = s1;
262 newvert[i].param[1] = t1;
263 s1 += sstepsize;
264 t1 += tstepsize;
265 }
266 newvert[i].param[0] = s2;
267 newvert[i].param[1] = t2;
268
269 /* arc->makeSide( new(pwlarcpool) PwlArc( nsteps+1, newvert ), arc_bottom ); */
270 arc->pwlArc = new(pwlarcpool) PwlArc( nsteps+1, newvert );
271
272 arc->clearbezier();
273 arc->clearside( );
274}
275
276
277/*-----------------------------------------------------------------------------
278 * tessellateLinear - constuct a linear pwl arc and attach it to an Arc
279 *-----------------------------------------------------------------------------
280 */
281
282void
283ArcTessellator::tessellateLinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational )
284{
285 assert( arc->pwlArc == NULL );
286 REAL s1, s2, t1, t2;
287
288 //we don't need to scale by arc_stepsize if the trim curve
289 //is piecewise linear. Reason: In pwl_right, pwl_left, pwl_top, pwl_left,
290 //and pwl, the nsteps is computed by deltaU (or V) /stepsize.
291 //The quantity deltaU/arc_stepsize doesn't have any meaning. And
292 //it causes problems: see bug 517641
293 REAL stepsize = geo_stepsize; /* * arc_stepsize*/;
294
295 BezierArc *b = arc->bezierArc;
296
297 if( isrational ) {
298 s1 = b->cpts[0] / b->cpts[2];
299 t1 = b->cpts[1] / b->cpts[2];
300 s2 = b->cpts[b->stride+0] / b->cpts[b->stride+2];
301 t2 = b->cpts[b->stride+1] / b->cpts[b->stride+2];
302 } else {
303 s1 = b->cpts[0];
304 t1 = b->cpts[1];
305 s2 = b->cpts[b->stride+0];
306 t2 = b->cpts[b->stride+1];
307 }
308 if( s1 == s2 )
309 if( t1 < t2 )
310 pwl_right( arc, s1, t1, t2, stepsize );
311 else
312 pwl_left( arc, s1, t1, t2, stepsize );
313 else if( t1 == t2 )
314 if( s1 < s2 )
315 pwl_bottom( arc, t1, s1, s2, stepsize );
316 else
317 pwl_top( arc, t1, s1, s2, stepsize );
318 else
319 pwl( arc, s1, s2, t1, t2, stepsize );
320}
321
322/*-----------------------------------------------------------------------------
323 * tessellateNonlinear - constuct a nonlinear pwl arc and attach it to an Arc
324 *-----------------------------------------------------------------------------
325 */
326
327void
328ArcTessellator::tessellateNonlinear( Arc *arc, REAL geo_stepsize, REAL arc_stepsize, int isrational )
329{
330 assert( arc->pwlArc == NULL );
331
332 REAL stepsize = geo_stepsize * arc_stepsize;
333
334 BezierArc *bezierArc = arc->bezierArc;
335
336 REAL size; //bounding box size of the curve in UV
337 {
338 int i,j;
339 REAL min_u, min_v, max_u,max_v;
340 min_u = max_u = bezierArc->cpts[0];
341 min_v = max_v = bezierArc->cpts[1];
342 for(i=1, j=2; i<bezierArc->order; i++, j+= bezierArc->stride)
343 {
344 if(bezierArc->cpts[j] < min_u)
345 min_u = bezierArc->cpts[j];
346 if(bezierArc->cpts[j] > max_u)
347 max_u = bezierArc->cpts[j];
348 if(bezierArc->cpts[j+1] < min_v)
349 min_v = bezierArc->cpts[j+1];
350 if(bezierArc->cpts[j+1] > max_v)
351 max_v = bezierArc->cpts[j+1];
352 }
353
354 size = max_u - min_u;
355 if(size < max_v - min_v)
356 size = max_v - min_v;
357 }
358
359 /*int nsteps = 1 + (int) (1.0/stepsize);*/
360
361 int nsteps = (int) (size/stepsize);
362 if(nsteps <=0)
363 nsteps=1;
364
365 TrimVertex *vert = trimvertexpool.get( nsteps+1 );
366 REAL dp = 1.0/nsteps;
367
368
369 arc->pwlArc = new(pwlarcpool) PwlArc();
370 arc->pwlArc->pts = vert;
371
372 if( isrational ) {
373 REAL pow_u[MAXORDER], pow_v[MAXORDER], pow_w[MAXORDER];
374 trim_power_coeffs( bezierArc, pow_u, 0 );
375 trim_power_coeffs( bezierArc, pow_v, 1 );
376 trim_power_coeffs( bezierArc, pow_w, 2 );
377
378 /* compute first point exactly */
379 REAL *b = bezierArc->cpts;
380 vert->param[0] = b[0]/b[2];
381 vert->param[1] = b[1]/b[2];
382
383 /* strength reduction on p = dp * step would introduce error */
384 int step;
385 int ocanremove = 0;
386 register long order = bezierArc->order;
387 for( step=1, ++vert; step<nsteps; step++, vert++ ) {
388 register REAL p = dp * step;
389 register REAL u = pow_u[0];
390 register REAL v = pow_v[0];
391 register REAL w = pow_w[0];
392 for( register int i = 1; i < order; i++ ) {
393 u = u * p + pow_u[i];
394 v = v * p + pow_v[i];
395 w = w * p + pow_w[i];
396 }
397 vert->param[0] = u/w;
398 vert->param[1] = v/w;
399#ifndef NOELIMINATION
400 REAL ds = abs(vert[0].param[0] - vert[-1].param[0]);
401 REAL dt = abs(vert[0].param[1] - vert[-1].param[1]);
402 int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0;
403 REAL ods=0.0, odt=0.0;
404
405 if( ocanremove && canremove ) {
406 REAL nds = ds + ods;
407 REAL ndt = dt + odt;
408 if( nds<geo_stepsize && ndt<geo_stepsize ) {
409 // remove previous point
410 --vert;
411 vert[0].param[0] = vert[1].param[0];
412 vert[0].param[1] = vert[1].param[1];
413 ods = nds;
414 odt = ndt;
415 ocanremove = 1;
416 } else {
417 ocanremove = canremove;
418 ods = ds;
419 odt = dt;
420 }
421 } else {
422 ocanremove = canremove;
423 ods = ds;
424 odt = dt;
425 }
426#endif
427 }
428
429 /* compute last point exactly */
430 b += (order - 1) * bezierArc->stride;
431 vert->param[0] = b[0]/b[2];
432 vert->param[1] = b[1]/b[2];
433
434 } else {
435 REAL pow_u[MAXORDER], pow_v[MAXORDER];
436 trim_power_coeffs( bezierArc, pow_u, 0 );
437 trim_power_coeffs( bezierArc, pow_v, 1 );
438
439 /* compute first point exactly */
440 REAL *b = bezierArc->cpts;
441 vert->param[0] = b[0];
442 vert->param[1] = b[1];
443
444 /* strength reduction on p = dp * step would introduce error */
445 int step;
446 int ocanremove = 0;
447 register long order = bezierArc->order;
448 for( step=1, ++vert; step<nsteps; step++, vert++ ) {
449 register REAL p = dp * step;
450 register REAL u = pow_u[0];
451 register REAL v = pow_v[0];
452 for( register int i = 1; i < bezierArc->order; i++ ) {
453 u = u * p + pow_u[i];
454 v = v * p + pow_v[i];
455 }
456 vert->param[0] = u;
457 vert->param[1] = v;
458#ifndef NOELIMINATION
459 REAL ds = abs(vert[0].param[0] - vert[-1].param[0]);
460 REAL dt = abs(vert[0].param[1] - vert[-1].param[1]);
461 int canremove = (ds<geo_stepsize && dt<geo_stepsize) ? 1 : 0;
462 REAL ods=0.0, odt=0.0;
463
464 if( ocanremove && canremove ) {
465 REAL nds = ds + ods;
466 REAL ndt = dt + odt;
467 if( nds<geo_stepsize && ndt<geo_stepsize ) {
468 // remove previous point
469 --vert;
470 vert[0].param[0] = vert[1].param[0];
471 vert[0].param[1] = vert[1].param[1];
472 ods = nds;
473 odt = ndt;
474 ocanremove = 1;
475 } else {
476 ocanremove = canremove;
477 ods = ds;
478 odt = dt;
479 }
480 } else {
481 ocanremove = canremove;
482 ods = ds;
483 odt = dt;
484 }
485#endif
486 }
487
488 /* compute last point exactly */
489 b += (order - 1) * bezierArc->stride;
490 vert->param[0] = b[0];
491 vert->param[1] = b[1];
492 }
493 arc->pwlArc->npts = vert - arc->pwlArc->pts + 1;
494/*
495 for( TrimVertex *vt=pwlArc->pts; vt != vert-1; vt++ ) {
496 if( tooclose( vt[0].param[0], vt[1].param[0] ) )
497 vt[1].param[0] = vt[0].param[0];
498 if( tooclose( vt[0].param[1], vt[1].param[1] ) )
499 vt[1].param[1] = vt[0].param[1];
500 }
501*/
502}
503
504const REAL ArcTessellator::gl_Bernstein[][MAXORDER][MAXORDER] = {
505 {
506 {1, 0, 0, 0, 0, 0, 0, 0 },
507 {0, 0, 0, 0, 0, 0, 0, 0 },
508 {0, 0, 0, 0, 0, 0, 0, 0 },
509 {0, 0, 0, 0, 0, 0, 0, 0 },
510 {0, 0, 0, 0, 0, 0, 0, 0 },
511 {0, 0, 0, 0, 0, 0, 0, 0 },
512 {0, 0, 0, 0, 0, 0, 0, 0 },
513 {0, 0, 0, 0, 0, 0, 0, 0 }
514 },
515 {
516 {-1, 1, 0, 0, 0, 0, 0, 0 },
517 {1, 0, 0, 0, 0, 0, 0, 0 },
518 {0, 0, 0, 0, 0, 0, 0, 0 },
519 {0, 0, 0, 0, 0, 0, 0, 0 },
520 {0, 0, 0, 0, 0, 0, 0, 0 },
521 {0, 0, 0, 0, 0, 0, 0, 0 },
522 {0, 0, 0, 0, 0, 0, 0, 0 },
523 {0, 0, 0, 0, 0, 0, 0, 0 }
524 },
525 {
526 {1, -2, 1, 0, 0, 0, 0, 0 },
527 {-2, 2, 0, 0, 0, 0, 0, 0 },
528 {1, 0, 0, 0, 0, 0, 0, 0 },
529 {0, 0, 0, 0, 0, 0, 0, 0 },
530 {0, 0, 0, 0, 0, 0, 0, 0 },
531 {0, 0, 0, 0, 0, 0, 0, 0 },
532 {0, 0, 0, 0, 0, 0, 0, 0 },
533 {0, 0, 0, 0, 0, 0, 0, 0 }
534 },
535 {
536 {-1, 3, -3, 1, 0, 0, 0, 0 },
537 {3, -6, 3, 0, 0, 0, 0, 0 },
538 {-3, 3, 0, 0, 0, 0, 0, 0 },
539 {1, 0, 0, 0, 0, 0, 0, 0 },
540 {0, 0, 0, 0, 0, 0, 0, 0 },
541 {0, 0, 0, 0, 0, 0, 0, 0 },
542 {0, 0, 0, 0, 0, 0, 0, 0 },
543 {0, 0, 0, 0, 0, 0, 0, 0 }
544 },
545 {
546 {1, -4, 6, -4, 1, 0, 0, 0 },
547 {-4, 12, -12, 4, 0, 0, 0, 0 },
548 {6, -12, 6, 0, 0, 0, 0, 0 },
549 {-4, 4, 0, 0, 0, 0, 0, 0 },
550 {1, 0, 0, 0, 0, 0, 0, 0 },
551 {0, 0, 0, 0, 0, 0, 0, 0 },
552 {0, 0, 0, 0, 0, 0, 0, 0 },
553 {0, 0, 0, 0, 0, 0, 0, 0 }
554 },
555 {
556 {-1, 5, -10, 10, -5, 1, 0, 0 },
557 {5, -20, 30, -20, 5, 0, 0, 0 },
558 {-10, 30, -30, 10, 0, 0, 0, 0 },
559 {10, -20, 10, 0, 0, 0, 0, 0 },
560 {-5, 5, 0, 0, 0, 0, 0, 0 },
561 {1, 0, 0, 0, 0, 0, 0, 0 },
562 {0, 0, 0, 0, 0, 0, 0, 0 },
563 {0, 0, 0, 0, 0, 0, 0, 0 }
564 },
565 {
566 {1, -6, 15, -20, 15, -6, 1, 0 },
567 {-6, 30, -60, 60, -30, 6, 0, 0 },
568 {15, -60, 90, -60, 15, 0, 0, 0 },
569 {-20, 60, -60, 20, 0, 0, 0, 0 },
570 {15, -30, 15, 0, 0, 0, 0, 0 },
571 {-6, 6, 0, 0, 0, 0, 0, 0 },
572 {1, 0, 0, 0, 0, 0, 0, 0 },
573 {0, 0, 0, 0, 0, 0, 0, 0 }
574 },
575 {
576 {-1, 7, -21, 35, -35, 21, -7, 1 },
577 {7, -42, 105, -140, 105, -42, 7, 0 },
578 {-21, 105, -210, 210, -105, 21, 0, 0 },
579 {35, -140, 210, -140, 35, 0, 0, 0 },
580 {-35, 105, -105, 35, 0, 0, 0, 0 },
581 {21, -42, 21, 0, 0, 0, 0, 0 },
582 {-7, 7, 0, 0, 0, 0, 0, 0 },
583 {1, 0, 0, 0, 0, 0, 0, 0 }
584 }};
585
586
587/*-----------------------------------------------------------------------------
588 * trim_power_coeffs - compute power basis coefficients from bezier coeffients
589 *-----------------------------------------------------------------------------
590 */
591void
592ArcTessellator::trim_power_coeffs( BezierArc *bez_arc, REAL *p, int coord )
593{
594 register int stride = bez_arc->stride;
595 register int order = bez_arc->order;
596 register REAL *base = bez_arc->cpts + coord;
597
598 REAL const (*mat)[MAXORDER][MAXORDER] = &gl_Bernstein[order-1];
599 REAL const (*lrow)[MAXORDER] = &(*mat)[order];
600
601 /* WIN32 didn't like the following line within the for-loop */
602 REAL const (*row)[MAXORDER] = &(*mat)[0];
603 for( ; row != lrow; row++ ) {
604 register REAL s = 0.0;
605 register REAL *point = base;
606 register REAL const *mlast = *row + order;
607 for( REAL const *m = *row; m != mlast; m++, point += stride )
608 s += *(m) * (*point);
609 *(p++) = s;
610 }
611}
Note: See TracBrowser for help on using the repository browser.