source: trunk/src/opengl/glu/nurbs/interface/bezierEval.cpp

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

* empty log message *

File size: 7.9 KB
Line 
1/* $Id: bezierEval.cpp,v 1.1 2000-02-09 08:48:59 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** $Date: 2000-02-09 08:48:59 $ $Revision: 1.1 $
36*/
37/*
38** $Header: /home/ktk/tmp/odin/2007/netlabs.cvs/odin32/src/opengl/glu/nurbs/interface/bezierEval.cpp,v 1.1 2000-02-09 08:48:59 jeroen Exp $
39*/
40
41#include <stdlib.h>
42#include <stdio.h>
43#include <assert.h>
44#include <math.h>
45#include "bezierEval.h"
46
47#define TOLERANCE 0.0001
48
49#ifndef MAX_ORDER
50#define MAX_ORDER 16
51#endif
52
53#ifndef MAX_DIMENSION
54#define MAX_DIMENSION 4
55#endif
56
57static void normalize(float vec[3]);
58static void crossProduct(float x[3], float y[3], float ret[3]);
59static void bezierCurveEvalfast(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[]);
60
61static float binomialCoefficients[8][8] = {
62 {1,0,0,0,0,0,0,0},
63 {1,1,0,0,0,0,0,0},
64 {1,2,1,0,0,0,0,0},
65 {1,3,3,1,0,0,0,0},
66 {1,4,6,4,1,0,0,0},
67 {1,5,10,10,5,1,0,0},
68 {1,6,15,20,15,6,1,0},
69 {1,7,21,35,35,21,7,1}
70};
71
72void bezierCurveEval(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[])
73{
74 float uprime = (u-u0)/(u1-u0);
75 float *ctlptr = ctlpoints;
76 float oneMinusX = 1.0-uprime;
77 float XPower = 1.0;
78
79 int i,k;
80 for(k=0; k<dimension; k++)
81 retpoint[k] = (*(ctlptr + k));
82
83 for(i=1; i<order; i++){
84 ctlptr += stride;
85 XPower *= uprime;
86 for(k=0; k<dimension; k++) {
87 retpoint[k] = retpoint[k]*oneMinusX + ctlptr[k]* binomialCoefficients[order-1][i] * XPower;
88 }
89 }
90}
91
92
93
94/*order = degree +1 >=1.
95 */
96void bezierCurveEvalfast(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retpoint[])
97{
98 float uprime = (u-u0)/(u1-u0);
99 float buf[MAX_ORDER][MAX_ORDER][MAX_DIMENSION];
100 float* ctlptr = ctlpoints;
101 int r, i,j;
102 for(i=0; i<order; i++) {
103 for(j=0; j<dimension; j++)
104 buf[0][i][j] = ctlptr[j];
105 ctlptr += stride;
106 }
107 for(r=1; r<order; r++){
108 for(i=0; i<order-r; i++) {
109 for(j=0; j<dimension; j++)
110 buf[r][i][j] = (1-uprime)*buf[r-1][i][j] + uprime*buf[r-1][i+1][j];
111 }
112 }
113
114 for(j=0; j<dimension; j++)
115 retpoint[j] = buf[order-1][0][j];
116}
117
118
119
120/*order = degree +1 >=1.
121 */
122void bezierCurveEvalDer(float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[])
123{
124 int i,k;
125 float width = u1-u0;
126 float *ctlptr = ctlpoints;
127
128 float buf[MAX_ORDER][MAX_DIMENSION];
129 if(order == 1){
130 for(k=0; k<dimension; k++)
131 retDer[k]=0;
132 }
133 for(i=0; i<order-1; i++){
134 for(k=0; k<dimension; k++) {
135 buf[i][k] = (ctlptr[stride+k] - ctlptr[k])*(order-1)/width;
136 }
137 ctlptr += stride;
138 }
139
140 bezierCurveEval(u0, u1, order-1, (float*) buf, MAX_DIMENSION, dimension, u, retDer);
141}
142
143void bezierCurveEvalDerGen(int der, float u0, float u1, int order, float *ctlpoints, int stride, int dimension, float u, float retDer[])
144{
145 int i,k,r;
146 float *ctlptr = ctlpoints;
147 float width=u1-u0;
148 float buf[MAX_ORDER][MAX_ORDER][MAX_DIMENSION];
149 if(der<0) der=0;
150 for(i=0; i<order; i++){
151 for(k=0; k<dimension; k++){
152 buf[0][i][k] = ctlptr[k];
153 }
154 ctlptr += stride;
155 }
156
157
158 for(r=1; r<=der; r++){
159 for(i=0; i<order-r; i++){
160 for(k=0; k<dimension; k++){
161 buf[r][i][k] = (buf[r-1][i+1][k] - buf[r-1][i][k])*(order-r)/width;
162 }
163 }
164 }
165
166 bezierCurveEval(u0, u1, order-der, (float *) (buf[der]), MAX_DIMENSION, dimension, u, retDer);
167}
168
169/*the Bezier bivarite polynomial is:
170 * sum[i:0,uorder-1][j:0,vorder-1] { ctlpoints[i*ustride+j*vstride] * B(i)*B(j)
171 * where B(i) and B(j) are basis functions
172 */
173void bezierSurfEvalDerGen(int uder, int vder, float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[])
174{
175 int i,j,k;
176 float newPoints[MAX_ORDER][MAX_DIMENSION];
177
178 for(i=0; i<uorder; i++){
179
180 bezierCurveEvalDerGen(vder, v0, v1, vorder, ctlpoints+ustride*i, vstride, dimension, v, newPoints[i]);
181
182 }
183
184 bezierCurveEvalDerGen(uder, u0, u1, uorder, (float *) newPoints, MAX_DIMENSION, dimension, u, ret);
185}
186
187
188/*division by w is performed*/
189void bezierSurfEval(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float ret[])
190{
191 bezierSurfEvalDerGen(0, 0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, ret);
192 if(dimension == 4) /*homogeneous*/{
193 ret[0] /= ret[3];
194 ret[1] /= ret[3];
195 ret[2] /= ret[3];
196 }
197}
198
199void bezierSurfEvalNormal(float u0, float u1, int uorder, float v0, float v1, int vorder, int dimension, float *ctlpoints, int ustride, int vstride, float u, float v, float retNormal[])
200{
201 float partialU[4];
202 float partialV[4];
203 assert(dimension>=3 && dimension <=4);
204 bezierSurfEvalDerGen(1,0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, partialU);
205 bezierSurfEvalDerGen(0,1, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, partialV);
206
207 if(dimension == 3){/*inhomogeneous*/
208 crossProduct(partialU, partialV, retNormal);
209
210 normalize(retNormal);
211
212 return;
213 }
214 else { /*homogeneous*/
215 float val[4]; /*the point coordinates (without derivative)*/
216 float newPartialU[MAX_DIMENSION];
217 float newPartialV[MAX_DIMENSION];
218 int i;
219 bezierSurfEvalDerGen(0,0, u0, u1, uorder, v0, v1, vorder, dimension, ctlpoints, ustride, vstride, u, v, val);
220
221 for(i=0; i<=2; i++){
222 newPartialU[i] = partialU[i] * val[3] - val[i] * partialU[3];
223 newPartialV[i] = partialV[i] * val[3] - val[i] * partialV[3];
224 }
225 crossProduct(newPartialU, newPartialV, retNormal);
226 normalize(retNormal);
227 }
228}
229
230/*if size is 0, then nothing is done*/
231static void normalize(float vec[3])
232{
233 float size = sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
234
235 if(size < TOLERANCE)
236 {
237#ifdef DEBUG
238 fprintf(stderr, "Warning: in oglBSpline.c normal is 0\n");
239#endif
240 return;
241 }
242 else {
243 vec[0] = vec[0]/size;
244 vec[1] = vec[1]/size;
245 vec[2] = vec[2]/size;
246 }
247}
248
249
250static void crossProduct(float x[3], float y[3], float ret[3])
251{
252 ret[0] = x[1]*y[2] - y[1]*x[2];
253 ret[1] = x[2]*y[0] - y[2]*x[0];
254 ret[2] = x[0]*y[1] - y[0]*x[1];
255
256}
257
Note: See TracBrowser for help on using the repository browser.