1 /*---------------------------------------------------------------------------*\
2 * OpenSG NURBS Library *
5 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
7 * http://cg.cs.uni-bonn.de/ *
9 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 # pragma warning (disable : 985)
41 #include "OSGBezierTensorSurface.h"
48 static char THIS_FILE
[] = __FILE__
;
54 int BezierTensorSurface::setControlPointMatrix(const DCTPVec4dmatrix
& cps
)
56 DCTPVec4dmatrix::size_type u_size
= cps
.size();
58 return -1; //invalid, at least two row of points are required
59 DCTPVec4dvector::size_type v_size
= cps
[0].size();
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!
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
];
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;
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];
145 // std::cerr << cl_ret << std::endl << std::endl;
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 );
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
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];
207 // subdivide surface at midpoint into 4 bezier surfaces
208 int BezierTensorSurface::midPointSubDivision(beziersurfacematrix
&newbeziers
)
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]);
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
];
247 vertdivleft
[i
].resize(2);
248 vertdivleft
[i
][0].setControlPointVector(tempvecleft
);
249 error
= vertdivleft
[i
][0].midPointSubDivision(vertdivleft
[i
][1]);
252 vertdivright
[i
].resize(2);
253 vertdivright
[i
][0].setControlPointVector(tempvecright
);
254 error
= vertdivright
[i
][0].midPointSubDivision(vertdivright
[i
][1]);
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
);
308 // subdivide surface at midpoint into 4 bezier surfaces
309 int BezierTensorSurface::midPointSubDivision(beziersurfacevector
&newbeziers
)
313 newbeziers
.resize(3); // we return exactly 3 new bezier tensorsurfaces
315 error
= midPointSubDivisionU(newbeziers
[1]); // first in u because this is slower
318 error
= midPointSubDivisionV(newbeziers
[0]);
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
];
349 DCTPVec4dmatrix
&cp1
= control_points
;
350 DCTPVec4dmatrix
&cp2
= newsurface
.control_points
;
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
];
367 cp2
[0][j
] = cp1
[n
][j
];
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
);
392 for(j
= 0; j
< n
; ++j
)
394 DCTPVec4dvector
&cp1
= control_points
[j
];
395 DCTPVec4dvector
&cp2
= newsurface
.control_points
[j
];
399 for(k
= 0; k
< m
; ++k
)
403 for(i
= m
; i
> k
; --i
)
405 cp1
[i
] += cp1
[i
- 1];