# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

bezier_patch.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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         // For all tangents.
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                 // Yes, we store tangents as position, not vectors...
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         // Compute tangentS
00201         //=================
00202         // s/ds.
00203         s0 = -3* ps12;
00204         s1 = 9*ps2 + 3 -12*ps;
00205         s2 =-9*ps2 + 6*ps ;
00206         s3 = 3* ps2;
00207         // t/dt.
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         // Compute tangentT
00232         //=================
00233         // s/ds.
00234         s0 = ps12 * ps1;
00235         s1 = 3.0f * ps * ps12;
00236         s2 = 3.0f * ps2 * ps1;
00237         s3 = ps2 * ps;
00238         // t/dt.
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         // Return the normal.
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         // Compute tangentS
00285         //=================
00286         // s/ds.
00287         s0 = -3* ps12;
00288         s1 = 9*ps2 + 3 -12*ps;
00289         s2 =-9*ps2 + 6*ps ;
00290         s3 = 3* ps2;
00291         // t/dt.
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         // Return the tgt normalized
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         // Compute tangentT
00335         //=================
00336         // s/ds.
00337         s0 = ps12 * ps1;
00338         s1 = 3.0f * ps * ps12;
00339         s2 = 3.0f * ps2 * ps1;
00340         s3 = ps2 * ps;
00341         // t/dt.
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         // Return the tgt normalized
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         // Subdivide the 2 curves.
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         // Setup horizontal curves.
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         // Subdivide curves.
00404         for(sint i=0;i<4;i++)
00405                 curveT[i].subdivide(curveTLeft[i], curveTRight[i], s);
00406 
00407         // Setup bezier patchs.
00408         // left.
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         // right.
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         // Setup vertical curves.
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         // Subdivide curves.
00435         for(sint i=0;i<4;i++)
00436                 curveS[i].subdivide(curveSTop[i], curveSBottom[i], t);
00437 
00438         // Setup bezier patchs.
00439         // top.
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         // bottom.
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 } // NL3D