changed: gcc8 base update
[opensg.git] / Source / System / NodeCores / Drawables / Nurbs / Internal / OSGBezierTensorSurface.cpp
blobf319626f85fedb9806b8901726a0c82c5c757ad5
1 /*---------------------------------------------------------------------------*\
2 * OpenSG NURBS Library *
3 * *
4 * *
5 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
6 * *
7 * http://cg.cs.uni-bonn.de/ *
8 * *
9 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
38 #ifdef WIN32
39 # pragma warning (disable : 985)
40 #endif
41 #include "OSGBezierTensorSurface.h"
43 OSG_USING_NAMESPACE
45 #ifdef _DEBUG
46 #ifdef WIN32
47 #undef THIS_FILE
48 static char THIS_FILE[] = __FILE__;
49 #endif
50 #endif
53 //setup functions
54 int BezierTensorSurface::setControlPointMatrix(const DCTPVec4dmatrix& cps)
56 DCTPVec4dmatrix::size_type u_size = cps.size();
57 if(u_size < 2)
58 return -1; //invalid, at least two row of points are required
59 DCTPVec4dvector::size_type v_size = cps[0].size();
60 if(v_size < 2)
61 return -1; //invalid size, at least two columns are needed
63 for(DCTPVec4dvector::size_type i = 1; i < u_size; ++i)
64 if(cps[i].size() != v_size)
65 return -1; //the size of columns're not equal!
67 control_points = cps;
68 return 0;
71 //some REAL functionality
72 Vec3d BezierTensorSurface::computewdeCasteljau(Vec2d uv, int & /*error*/)
74 const unsigned int cui_u = UInt32(control_points.size());
75 const unsigned int cui_v = UInt32(control_points[0].size()) - 1;
77 Vec4d *pcl_u = new Vec4d[cui_u];
78 Vec4d *pcl_v = new Vec4d[cui_v];
79 unsigned int ui_i;
80 unsigned int ui_j;
81 unsigned int ui_k;
82 const double cd_tu = uv[0];
83 const double cd_tu2 = 1.0 - cd_tu;
84 const double cd_tv = uv[1];
85 const double cd_tv2 = 1.0 - cd_tv;
86 const unsigned int cui_u1 = cui_u - 1;
87 const unsigned int cui_v1 = cui_v - 1;
88 Vec3d cl_ret;
90 // std::cerr << uv << std::endl;
92 for(ui_i = 0; ui_i < cui_u; ++ui_i)
94 for(ui_j = 0; ui_j < cui_v; ++ui_j)
96 const unsigned int cui_j1 = ui_j + 1;
98 pcl_v[ui_j] = control_points[ui_i][ui_j] * cd_tv2 + control_points[ui_i][cui_j1] * cd_tv;
99 // std::cerr << pd_vx[ ui_j ] << " " << pd_vy[ ui_j ] << " " << pd_vz[ ui_j ] << std::endl;
102 for(ui_k = 0; ui_k < cui_v1; ++ui_k)
104 const unsigned int cui_vk = cui_v1 - ui_k;
106 for(ui_j = 0; ui_j < cui_vk; ++ui_j)
108 const unsigned int cui_j1 = ui_j + 1;
110 pcl_v[ui_j] *= cd_tv2;
111 pcl_v[ui_j] += pcl_v[cui_j1] * cd_tv;
115 pcl_u[ui_i] = pcl_v[0];
116 // std::cerr << pd_ux[ ui_i ] << " " << pd_uy[ ui_i ] << " " << pd_uz[ ui_i ] << std::endl;
119 /* for( ui_i = 0; ui_i < cui_u; ++ui_i )
121 const unsigned int cui_i1 = ui_i + 1;
125 for(ui_k = 0; ui_k < cui_u1; ++ui_k)
127 const unsigned int cui_uk = cui_u1 - ui_k;
129 for(ui_i = 0; ui_i < cui_uk; ++ui_i)
131 const unsigned int cui_i1 = ui_i + 1;
133 pcl_u[ui_i] *= cd_tu2;
134 pcl_u[ui_i] += pcl_u[cui_i1] * cd_tu;
138 cl_ret[0] = pcl_u[0][0] / pcl_u[0][3];
139 cl_ret[1] = pcl_u[0][1] / pcl_u[0][3];
140 cl_ret[2] = pcl_u[0][2] / pcl_u[0][3];
142 delete[] pcl_u;
143 delete[] pcl_v;
145 // std::cerr << cl_ret << std::endl << std::endl;
147 return cl_ret;
149 // NOTE: Old code was far too slow, because of memory allocation...
151 //FIXME: verification before goin' into computation!!
152 //FIXME: there are a lot of unverified error reports!!
153 /* Vec3dmatrix::size_type n = control_points.size() - 1;
154 Vec3dvector::size_type m = control_points[ 0 ].size() - 1;
156 if ( n <= m ) { //less expensive: first by u0 we get a (m+1) element vector
157 Vec3dvector Q( m + 1 ); //temp to store computed values at u0
158 for( Vec3dvector::size_type j = 0; j <= m; ++j ) {
159 Vec3dvector row( n + 1 ); //temp to store current row o' da control_points
160 for( Vec2dvector::size_type k = 0; k <= n; ++k ) row[ k ] = control_points[ k ][ j ]; //copied jth row
161 BezierCurve3D curve_of_row;
162 curve_of_row.setControlPointVector( row );
163 Q[ j ] = curve_of_row.computewdeCasteljau( uv[0], error );
164 } //OK - in Q now we have the points on the surface at u0 (uv.u )
165 BezierCurve3D column_at_u0;
166 column_at_u0.setControlPointVector( Q );
167 return column_at_u0.computewdeCasteljau( uv[1], error );
169 else {
170 Vec3dvector Q( n + 1 );
171 for( Vec3dvector::size_type j = 0; j <= n; ++j ) {
172 Vec3dvector column( m + 1 ); //temp to current column o' da control_points
173 column = control_points[ j ];
174 BezierCurve3D curve_of_column;
175 curve_of_column.setControlPointVector( column );
176 Q[ j ] = curve_of_column.computewdeCasteljau( uv[1], error );
177 } //OK - in Q now we have the points on the surfave at v0 (uv.v)
178 BezierCurve3D row_at_v0;
179 row_at_v0.setControlPointVector( Q );
180 return row_at_v0.computewdeCasteljau( uv[0], error );
184 Vec3d BezierTensorSurface::computeLinearApproximation(Vec2d uv, int &error)
186 //FIXME: verification before goin' into computation!!
187 DCTPVec4dmatrix::size_type n = control_points.size() - 1;
188 DCTPVec4dvector::size_type m = control_points[0].size() - 1;
189 Vec4d rat_res(0.0, 0.0, 0.0, 0.0);
190 Vec3d result(0.0, 0.0, 0.0);
192 if(n < 1 || m < 1) //too few points, at least 2 needed
194 error = -1;
195 return result;
197 rat_res = (control_points[0][0] * (1 - uv[0]) + control_points[n][0] * uv[0]) * (1 - uv[1]);
198 rat_res += (control_points[0][m] * (1 - uv[0]) + control_points[n][m] * uv[0]) * uv[1];
200 result[0] = rat_res[0] / rat_res[3];
201 result[1] = rat_res[1] / rat_res[3];
202 result[2] = rat_res[2] / rat_res[3];
204 return (result);
207 // subdivide surface at midpoint into 4 bezier surfaces
208 int BezierTensorSurface::midPointSubDivision(beziersurfacematrix &newbeziers)
210 int error;
211 unsigned int i;
212 newbeziers.resize(2);
213 newbeziers[0].resize(2);
214 newbeziers[1].resize(2); // we return exactly 4 new bezier tensorsurfaces
217 //FIXME: verification before goin' into computation!!
218 //FIXME: there are a lot of unverified error reports!!
219 DCTPVec4dmatrix::size_type n = control_points.size() - 1;
220 DCTPVec4dvector::size_type m = control_points[0].size() - 1;
221 bezier3dmatrix horizdiv(n + 1);
222 bezier3dmatrix vertdivleft(m + 1);
223 bezier3dmatrix vertdivright(m + 1);
225 // std::cerr << "n: " << n << " m: " << m << std::endl;
226 //FIXME: does the order u->v or v->u really not matter? e.g. for speed if for nothing else
227 for(i = 0; i <= n; i++)
229 horizdiv[i].resize(2);
230 horizdiv[i][0].setControlPointVector(control_points[i]);
231 error = horizdiv[i][0].midPointSubDivision(horizdiv[i][1]);
232 if(error)
233 return error;
236 for(i = 0; i <= m; i++)
238 DCTPVec4dvector tempvecleft(n + 1);
239 DCTPVec4dvector tempvecright(n + 1);
241 for(DCTPdvector::size_type j = 0; j <= n; j++)
243 tempvecleft[j] = horizdiv[j][0].getControlPointVector()[i];
244 tempvecright[j] = horizdiv[j][1].getControlPointVector()[i];
245 } // j
247 vertdivleft[i].resize(2);
248 vertdivleft[i][0].setControlPointVector(tempvecleft);
249 error = vertdivleft[i][0].midPointSubDivision(vertdivleft[i][1]);
250 if(error)
251 return error;
252 vertdivright[i].resize(2);
253 vertdivright[i][0].setControlPointVector(tempvecright);
254 error = vertdivright[i][0].midPointSubDivision(vertdivright[i][1]);
255 if(error)
256 return error;
257 } // i
259 DCTPVec4dmatrix cps(n + 1);
261 for(i = 0; i <= n; i++)
262 cps[i].resize(m + 1);
264 for(i = 0; i <= n; i++)
266 for(DCTPVec4dmatrix::size_type j = 0; j <= m; j++)
268 cps[i][j] = vertdivleft[j][0].getControlPointVector()[i];
272 newbeziers[0][0].setControlPointMatrix(cps);
274 for(i = 0; i <= n; i++)
276 for(DCTPVec4dmatrix::size_type j = 0; j <= m; j++)
278 cps[i][j] = vertdivleft[j][1].getControlPointVector()[i];
282 newbeziers[1][0].setControlPointMatrix(cps);
284 for(i = 0; i <= n; i++)
286 for(DCTPVec4dmatrix::size_type j = 0; j <= m; j++)
288 cps[i][j] = vertdivright[j][0].getControlPointVector()[i];
292 newbeziers[0][1].setControlPointMatrix(cps);
294 for(i = 0; i <= n; i++)
296 for(DCTPVec4dmatrix::size_type j = 0; j <= m; j++)
298 cps[i][j] = vertdivright[j][1].getControlPointVector()[i];
302 newbeziers[1][1].setControlPointMatrix(cps);
305 return 0;
308 // subdivide surface at midpoint into 4 bezier surfaces
309 int BezierTensorSurface::midPointSubDivision(beziersurfacevector &newbeziers)
311 int error;
313 newbeziers.resize(3); // we return exactly 3 new bezier tensorsurfaces
315 error = midPointSubDivisionU(newbeziers[1]); // first in u because this is slower
316 if(error)
317 return error;
318 error = midPointSubDivisionV(newbeziers[0]);
319 if(error)
320 return error;
321 return newbeziers[1].midPointSubDivisionV(newbeziers[2]);
324 // subdivide surface at midpoint into 2 bezier surfaces
325 int BezierTensorSurface::midPointSubDivisionU(BezierTensorSurface &newsurface)
327 // This function is time critical so optimize at the cost of readabiltity...
328 DCTPVec4dmatrix::size_type n = control_points.size();
329 DCTPVec4dvector::size_type m = control_points[0].size();
331 if( (n < 2) || (m < 2) )
333 return -1; //too few points, at least 2 needed to split curve
336 DCTPVec4dvector::size_type i, k;
337 DCTPVec4dmatrix::size_type j;
339 newsurface.control_points.clear(); // very imporatant for performance (no copying around of obsolte stuff!)
340 newsurface.control_points.resize(n);
342 for(j = 0; j < n; ++j)
344 DCTPVec4dvector &cp2 = newsurface.control_points[j];
346 cp2.resize(m);
349 DCTPVec4dmatrix &cp1 = control_points;
350 DCTPVec4dmatrix &cp2 = newsurface.control_points;
352 --n;
354 for(j = 0; j < m; ++j)
356 for(k = 0; k < n; ++k)
358 cp2[n - k][j] = cp1[n][j];
360 for(i = n; i > k; --i)
362 cp1[i][j] += cp1[i - 1][j];
363 cp1[i][j] *= 0.5;
367 cp2[0][j] = cp1[n][j];
370 return 0;
373 // subdivide surface at midpoint into 2 bezier surfaces
374 int BezierTensorSurface::midPointSubDivisionV(BezierTensorSurface &newsurface)
376 // This function is time critical so optimize at the cost of readabiltity...
377 DCTPVec4dmatrix::size_type n = control_points.size();
378 DCTPVec4dvector::size_type m = control_points[0].size();
380 if( (n < 2) || (m < 2) )
382 return -1; //too few points, at least 2 needed to split curve
385 DCTPVec4dvector::size_type i, k;
386 DCTPVec4dmatrix::size_type j;
388 newsurface.control_points.clear(); // very imporatant for performance (no copying around of obsolte stuff!)
389 newsurface.control_points.resize(n);
390 --m;
392 for(j = 0; j < n; ++j)
394 DCTPVec4dvector &cp1 = control_points[j];
395 DCTPVec4dvector &cp2 = newsurface.control_points[j];
397 cp2.resize(m + 1);
399 for(k = 0; k < m; ++k)
401 cp2[m - k] = cp1[m];
403 for(i = m; i > k; --i)
405 cp1[i] += cp1[i - 1];
406 cp1[i] *= 0.5;
410 cp2[0] = cp1[m];
413 return 0;