00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/bezier_patch.h"
00029 using namespace NLMISC;
00030
00031
00032 namespace NL3D {
00033
00034
00035
00036 void CBezierPatch::make(CVector vertices[4], CVector normals[4])
00037 {
00038 sint i;
00039 static sint starts[8]= {0,1, 1,2, 2,3, 3,0};
00040 static sint ends[8]= {1,0, 2,1, 3,2, 0,3};
00041
00042 for(i=0;i<4;i++)
00043 Vertices[i]= vertices[i];
00044
00045
00046 for(i=0;i<8;i++)
00047 {
00048 CVector tgt= Vertices[ends[i]] - Vertices[starts[i]];
00049 CVector I,J,K;
00050 J= normals[starts[i]];
00051 I= J^tgt;
00052 K= I^J;
00053 K.normalize();
00054
00055 Tangents[i]= Vertices[starts[i]] + K*tgt.norm()/3;
00056 }
00057
00058 makeInteriors();
00059 }
00060
00061 void CBezierPatch::makeInteriors()
00062 {
00063 CVector &a = Vertices[0];
00064 CVector &b = Vertices[1];
00065 CVector &c = Vertices[2];
00066 CVector &d = Vertices[3];
00067 Interiors[0] = Tangents[7] + Tangents[0] - a;
00068 Interiors[1] = Tangents[1] + Tangents[2] - b;
00069 Interiors[2] = Tangents[3] + Tangents[4] - c;
00070 Interiors[3] = Tangents[5] + Tangents[6] - d;
00071 }
00072
00073 void CBezierPatch::applyMatrix(const CMatrix &m)
00074 {
00075 sint i;
00076
00077 for(i=0;i<4;i++)
00078 Vertices[i]= m*Vertices[i];
00079 for(i=0;i<8;i++)
00080 Tangents[i]= m*Tangents[i];
00081 for(i=0;i<4;i++)
00082 Interiors[i]= m*Interiors[i];
00083 }
00084
00085
00086
00087 static inline void mulAdd(CVector &tgt, const CVector &src, float f)
00088 {
00089 tgt.x+= src.x*f;
00090 tgt.y+= src.y*f;
00091 tgt.z+= src.z*f;
00092 }
00093
00094
00095
00096 static inline void mulAddD(CVectorD &tgt, const CVector &src, double f)
00097 {
00098 tgt.x+= src.x*f;
00099 tgt.y+= src.y*f;
00100 tgt.z+= src.z*f;
00101 }
00102
00103
00104
00105 CVector CBezierPatch::eval(float ps, float pt) const
00106 {
00107 CVector p;
00108
00109 float ps2 = ps * ps;
00110 float ps1 = 1.0f - ps;
00111 float ps12 = ps1 * ps1;
00112 float s0 = ps12 * ps1;
00113 float s1 = 3.0f * ps * ps12;
00114 float s2 = 3.0f * ps2 * ps1;
00115 float s3 = ps2 * ps;
00116 float pt2 = pt * pt;
00117 float pt1 = 1.0f - pt;
00118 float pt12 = pt1 * pt1;
00119 float t0 = pt12 * pt1;
00120 float t1 = 3.0f * pt * pt12;
00121 float t2 = 3.0f * pt2 * pt1;
00122 float t3 = pt2 * pt;
00123
00124 p.set(0,0,0);
00125 mulAdd(p, Vertices[0] , s0 * t0);
00126 mulAdd(p, Tangents[7] , s1 * t0);
00127 mulAdd(p, Tangents[6] , s2 * t0);
00128 mulAdd(p, Vertices[3] , s3 * t0);
00129 mulAdd(p, Tangents[0] , s0 * t1);
00130 mulAdd(p, Interiors[0], s1 * t1);
00131 mulAdd(p, Interiors[3], s2 * t1);
00132 mulAdd(p, Tangents[5] , s3 * t1);
00133 mulAdd(p, Tangents[1] , s0 * t2);
00134 mulAdd(p, Interiors[1], s1 * t2);
00135 mulAdd(p, Interiors[2], s2 * t2);
00136 mulAdd(p, Tangents[4] , s3 * t2);
00137 mulAdd(p, Vertices[1] , s0 * t3);
00138 mulAdd(p, Tangents[2] , s1 * t3);
00139 mulAdd(p, Tangents[3] , s2 * t3);
00140 mulAdd(p, Vertices[2] , s3 * t3);
00141
00142 return p;
00143 }
00144
00145 CVectorD CBezierPatch::evalDouble(double ps, double pt) const
00146 {
00147 CVectorD p;
00148
00149 double ps2 = ps * ps;
00150 double ps1 = 1.0f - ps;
00151 double ps12 = ps1 * ps1;
00152 double s0 = ps12 * ps1;
00153 double s1 = 3.0f * ps * ps12;
00154 double s2 = 3.0f * ps2 * ps1;
00155 double s3 = ps2 * ps;
00156 double pt2 = pt * pt;
00157 double pt1 = 1.0f - pt;
00158 double pt12 = pt1 * pt1;
00159 double t0 = pt12 * pt1;
00160 double t1 = 3.0f * pt * pt12;
00161 double t2 = 3.0f * pt2 * pt1;
00162 double t3 = pt2 * pt;
00163
00164 p.set(0,0,0);
00165 mulAddD(p, Vertices[0] , s0 * t0);
00166 mulAddD(p, Tangents[7] , s1 * t0);
00167 mulAddD(p, Tangents[6] , s2 * t0);
00168 mulAddD(p, Vertices[3] , s3 * t0);
00169 mulAddD(p, Tangents[0] , s0 * t1);
00170 mulAddD(p, Interiors[0], s1 * t1);
00171 mulAddD(p, Interiors[3], s2 * t1);
00172 mulAddD(p, Tangents[5] , s3 * t1);
00173 mulAddD(p, Tangents[1] , s0 * t2);
00174 mulAddD(p, Interiors[1], s1 * t2);
00175 mulAddD(p, Interiors[2], s2 * t2);
00176 mulAddD(p, Tangents[4] , s3 * t2);
00177 mulAddD(p, Vertices[1] , s0 * t3);
00178 mulAddD(p, Tangents[2] , s1 * t3);
00179 mulAddD(p, Tangents[3] , s2 * t3);
00180 mulAddD(p, Vertices[2] , s3 * t3);
00181
00182 return p;
00183 }
00184
00185
00186
00187 CVector CBezierPatch::evalNormal(float ps, float pt) const
00188 {
00189 CVector tgtS, tgtT;
00190
00191 float s0,s1,s2,s3;
00192 float t0,t1,t2,t3;
00193 float ps2 = ps * ps;
00194 float ps1 = 1.0f - ps;
00195 float ps12 = ps1 * ps1;
00196 float pt2 = pt * pt;
00197 float pt1 = 1.0f - pt;
00198 float pt12 = pt1 * pt1;
00199
00200
00201
00202
00203 s0 = -3* ps12;
00204 s1 = 9*ps2 + 3 -12*ps;
00205 s2 =-9*ps2 + 6*ps ;
00206 s3 = 3* ps2;
00207
00208 t0 = pt12 * pt1;
00209 t1 = 3.0f * pt * pt12;
00210 t2 = 3.0f * pt2 * pt1;
00211 t3 = pt2 * pt;
00212
00213 tgtS.set(0,0,0);
00214 mulAdd(tgtS, Vertices[0] , s0 * t0);
00215 mulAdd(tgtS, Tangents[7] , s1 * t0);
00216 mulAdd(tgtS, Tangents[6] , s2 * t0);
00217 mulAdd(tgtS, Vertices[3] , s3 * t0);
00218 mulAdd(tgtS, Tangents[0] , s0 * t1);
00219 mulAdd(tgtS, Interiors[0], s1 * t1);
00220 mulAdd(tgtS, Interiors[3], s2 * t1);
00221 mulAdd(tgtS, Tangents[5] , s3 * t1);
00222 mulAdd(tgtS, Tangents[1] , s0 * t2);
00223 mulAdd(tgtS, Interiors[1], s1 * t2);
00224 mulAdd(tgtS, Interiors[2], s2 * t2);
00225 mulAdd(tgtS, Tangents[4] , s3 * t2);
00226 mulAdd(tgtS, Vertices[1] , s0 * t3);
00227 mulAdd(tgtS, Tangents[2] , s1 * t3);
00228 mulAdd(tgtS, Tangents[3] , s2 * t3);
00229 mulAdd(tgtS, Vertices[2] , s3 * t3);
00230
00231
00232
00233
00234 s0 = ps12 * ps1;
00235 s1 = 3.0f * ps * ps12;
00236 s2 = 3.0f * ps2 * ps1;
00237 s3 = ps2 * ps;
00238
00239 t0 = -3* pt12;
00240 t1 = 9*pt2 + 3 -12*pt;
00241 t2 =-9*pt2 + 6*pt ;
00242 t3 = 3* pt2;
00243
00244 tgtT.set(0,0,0);
00245 mulAdd(tgtT, Vertices[0] , s0 * t0);
00246 mulAdd(tgtT, Tangents[7] , s1 * t0);
00247 mulAdd(tgtT, Tangents[6] , s2 * t0);
00248 mulAdd(tgtT, Vertices[3] , s3 * t0);
00249 mulAdd(tgtT, Tangents[0] , s0 * t1);
00250 mulAdd(tgtT, Interiors[0], s1 * t1);
00251 mulAdd(tgtT, Interiors[3], s2 * t1);
00252 mulAdd(tgtT, Tangents[5] , s3 * t1);
00253 mulAdd(tgtT, Tangents[1] , s0 * t2);
00254 mulAdd(tgtT, Interiors[1], s1 * t2);
00255 mulAdd(tgtT, Interiors[2], s2 * t2);
00256 mulAdd(tgtT, Tangents[4] , s3 * t2);
00257 mulAdd(tgtT, Vertices[1] , s0 * t3);
00258 mulAdd(tgtT, Tangents[2] , s1 * t3);
00259 mulAdd(tgtT, Tangents[3] , s2 * t3);
00260 mulAdd(tgtT, Vertices[2] , s3 * t3);
00261
00262
00263
00264 CVector norm= tgtT^tgtS;
00265 norm.normalize();
00266 return norm;
00267 }
00268
00269
00270
00271 CVector CBezierPatch::evalTangentS(float ps, float pt) const
00272 {
00273 CVector tgtS;
00274
00275 float s0,s1,s2,s3;
00276 float t0,t1,t2,t3;
00277 float ps2 = ps * ps;
00278 float ps1 = 1.0f - ps;
00279 float ps12 = ps1 * ps1;
00280 float pt2 = pt * pt;
00281 float pt1 = 1.0f - pt;
00282 float pt12 = pt1 * pt1;
00283
00284
00285
00286
00287 s0 = -3* ps12;
00288 s1 = 9*ps2 + 3 -12*ps;
00289 s2 =-9*ps2 + 6*ps ;
00290 s3 = 3* ps2;
00291
00292 t0 = pt12 * pt1;
00293 t1 = 3.0f * pt * pt12;
00294 t2 = 3.0f * pt2 * pt1;
00295 t3 = pt2 * pt;
00296
00297 tgtS.set(0,0,0);
00298 mulAdd(tgtS, Vertices[0] , s0 * t0);
00299 mulAdd(tgtS, Tangents[7] , s1 * t0);
00300 mulAdd(tgtS, Tangents[6] , s2 * t0);
00301 mulAdd(tgtS, Vertices[3] , s3 * t0);
00302 mulAdd(tgtS, Tangents[0] , s0 * t1);
00303 mulAdd(tgtS, Interiors[0], s1 * t1);
00304 mulAdd(tgtS, Interiors[3], s2 * t1);
00305 mulAdd(tgtS, Tangents[5] , s3 * t1);
00306 mulAdd(tgtS, Tangents[1] , s0 * t2);
00307 mulAdd(tgtS, Interiors[1], s1 * t2);
00308 mulAdd(tgtS, Interiors[2], s2 * t2);
00309 mulAdd(tgtS, Tangents[4] , s3 * t2);
00310 mulAdd(tgtS, Vertices[1] , s0 * t3);
00311 mulAdd(tgtS, Tangents[2] , s1 * t3);
00312 mulAdd(tgtS, Tangents[3] , s2 * t3);
00313 mulAdd(tgtS, Vertices[2] , s3 * t3);
00314
00315
00316 return tgtS.normed();
00317 }
00318
00319
00320
00321 CVector CBezierPatch::evalTangentT(float ps, float pt) const
00322 {
00323 CVector tgtT;
00324
00325 float s0,s1,s2,s3;
00326 float t0,t1,t2,t3;
00327 float ps2 = ps * ps;
00328 float ps1 = 1.0f - ps;
00329 float ps12 = ps1 * ps1;
00330 float pt2 = pt * pt;
00331 float pt1 = 1.0f - pt;
00332 float pt12 = pt1 * pt1;
00333
00334
00335
00336
00337 s0 = ps12 * ps1;
00338 s1 = 3.0f * ps * ps12;
00339 s2 = 3.0f * ps2 * ps1;
00340 s3 = ps2 * ps;
00341
00342 t0 = -3* pt12;
00343 t1 = 9*pt2 + 3 -12*pt;
00344 t2 =-9*pt2 + 6*pt ;
00345 t3 = 3* pt2;
00346
00347 tgtT.set(0,0,0);
00348 mulAdd(tgtT, Vertices[0] , s0 * t0);
00349 mulAdd(tgtT, Tangents[7] , s1 * t0);
00350 mulAdd(tgtT, Tangents[6] , s2 * t0);
00351 mulAdd(tgtT, Vertices[3] , s3 * t0);
00352 mulAdd(tgtT, Tangents[0] , s0 * t1);
00353 mulAdd(tgtT, Interiors[0], s1 * t1);
00354 mulAdd(tgtT, Interiors[3], s2 * t1);
00355 mulAdd(tgtT, Tangents[5] , s3 * t1);
00356 mulAdd(tgtT, Tangents[1] , s0 * t2);
00357 mulAdd(tgtT, Interiors[1], s1 * t2);
00358 mulAdd(tgtT, Interiors[2], s2 * t2);
00359 mulAdd(tgtT, Tangents[4] , s3 * t2);
00360 mulAdd(tgtT, Vertices[1] , s0 * t3);
00361 mulAdd(tgtT, Tangents[2] , s1 * t3);
00362 mulAdd(tgtT, Tangents[3] , s2 * t3);
00363 mulAdd(tgtT, Vertices[2] , s3 * t3);
00364
00365
00366 return tgtT.normed();
00367 }
00368
00369
00370
00371 void CBezierPatch::CBezierCurve::subdivide(CBezierCurve &left, CBezierCurve &right, float t)
00372 {
00373 float t1= 1-t;
00374
00375
00376 left.P0= P0;
00377 right.P3= P3;
00378
00379 left.P1= t1*P0 + t*P1;
00380 right.P2= t1*P2 + t*P3;
00381 CVector middle12= t1*P1 + t*P2;
00382
00383 left.P2= t1*left.P1 + t*middle12;
00384 right.P1= t1*middle12 + t*right.P2;
00385
00386 left.P3= right.P0= t1*left.P2 + t*right.P1;
00387 }
00388
00389
00390
00391 void CBezierPatch::subdivideS(CBezierPatch &left, CBezierPatch &right, float s) const
00392 {
00393 CBezierCurve curveT[4];
00394 CBezierCurve curveTLeft[4];
00395 CBezierCurve curveTRight[4];
00396
00397
00398 curveT[0].set(Vertices[0], Tangents[7] , Tangents[6] , Vertices[3]);
00399 curveT[1].set(Tangents[0], Interiors[0], Interiors[3], Tangents[5]);
00400 curveT[2].set(Tangents[1], Interiors[1], Interiors[2], Tangents[4]);
00401 curveT[3].set(Vertices[1], Tangents[2] , Tangents[3] , Vertices[2]);
00402
00403
00404 for(sint i=0;i<4;i++)
00405 curveT[i].subdivide(curveTLeft[i], curveTRight[i], s);
00406
00407
00408
00409 curveTLeft[0].get(left.Vertices[0], left.Tangents[7] , left.Tangents[6] , left.Vertices[3]);
00410 curveTLeft[1].get(left.Tangents[0], left.Interiors[0], left.Interiors[3], left.Tangents[5]);
00411 curveTLeft[2].get(left.Tangents[1], left.Interiors[1], left.Interiors[2], left.Tangents[4]);
00412 curveTLeft[3].get(left.Vertices[1], left.Tangents[2] , left.Tangents[3] , left.Vertices[2]);
00413
00414 curveTRight[0].get(right.Vertices[0], right.Tangents[7] , right.Tangents[6] , right.Vertices[3]);
00415 curveTRight[1].get(right.Tangents[0], right.Interiors[0], right.Interiors[3], right.Tangents[5]);
00416 curveTRight[2].get(right.Tangents[1], right.Interiors[1], right.Interiors[2], right.Tangents[4]);
00417 curveTRight[3].get(right.Vertices[1], right.Tangents[2] , right.Tangents[3] , right.Vertices[2]);
00418 }
00419
00420
00421
00422 void CBezierPatch::subdivideT(CBezierPatch &top, CBezierPatch &bottom, float t) const
00423 {
00424 CBezierCurve curveS[4];
00425 CBezierCurve curveSTop[4];
00426 CBezierCurve curveSBottom[4];
00427
00428
00429 curveS[0].set(Vertices[0], Tangents[0] , Tangents[1] , Vertices[1]);
00430 curveS[1].set(Tangents[7], Interiors[0], Interiors[1], Tangents[2]);
00431 curveS[2].set(Tangents[6], Interiors[3], Interiors[2], Tangents[3]);
00432 curveS[3].set(Vertices[3], Tangents[5] , Tangents[4] , Vertices[2]);
00433
00434
00435 for(sint i=0;i<4;i++)
00436 curveS[i].subdivide(curveSTop[i], curveSBottom[i], t);
00437
00438
00439
00440 curveSTop[0].get(top.Vertices[0], top.Tangents[0] , top.Tangents[1] , top.Vertices[1]);
00441 curveSTop[1].get(top.Tangents[7], top.Interiors[0], top.Interiors[1], top.Tangents[2]);
00442 curveSTop[2].get(top.Tangents[6], top.Interiors[3], top.Interiors[2], top.Tangents[3]);
00443 curveSTop[3].get(top.Vertices[3], top.Tangents[5] , top.Tangents[4] , top.Vertices[2]);
00444
00445 curveSBottom[0].get(bottom.Vertices[0], bottom.Tangents[0] , bottom.Tangents[1] , bottom.Vertices[1]);
00446 curveSBottom[1].get(bottom.Tangents[7], bottom.Interiors[0], bottom.Interiors[1], bottom.Tangents[2]);
00447 curveSBottom[2].get(bottom.Tangents[6], bottom.Interiors[3], bottom.Interiors[2], bottom.Tangents[3]);
00448 curveSBottom[3].get(bottom.Vertices[3], bottom.Tangents[5] , bottom.Tangents[4] , bottom.Vertices[2]);
00449 }
00450
00451
00452
00453 }