src/bezier.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *            bezier.cc
00003  *
00004  *  Sat Nov 12 10:20:06 2005
00005  *  Copyright  2005  Joe Venzon
00006  *  joe@venzon.net
00007  ****************************************************************************/
00008 
00009 /*
00010  *  This program 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 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023  */
00024  
00025 #include "bezier.h"
00026 
00027 BEZIER::BEZIER()
00028 {
00029         int x,y;
00030         
00031         for (x = 0; x < 4; x++)
00032         {
00033                 for (y = 0; y < 4; y++)
00034                 {
00035                         points[x][y].zero();
00036                 }
00037         }
00038 }
00039 
00040 BEZIER::~BEZIER()
00041 {
00042         
00043 }
00044 
00045 void BEZIER::SetFromCorners(VERTEX fl, VERTEX fr, VERTEX bl, VERTEX br)
00046 {
00047         VERTEX temp;
00048         
00049         center = fl + fr + bl + br;
00050         center.Scale(0.25);
00051         radius = 0;
00052         if ((fl - center).len() > radius)
00053                 radius = (fl - center).len();
00054         if ((fr - center).len() > radius)
00055                 radius = (fr - center).len();
00056         if ((bl - center).len() > radius)
00057                 radius = (bl - center).len();
00058         if ((br - center).len() > radius)
00059                 radius = (br - center).len();
00060         
00061         //assign corners
00062         points[0][0] = fl;
00063         points[0][3] = fr;
00064         points[3][3] = br;
00065         points[3][0] = bl;
00066         
00067         //calculate intermediate front and back points
00068         
00069         temp = fr - fl;
00070         points[0][1] = fl + temp.normalize().ScaleR(temp.len()/3.0);
00071         points[0][2] = fl + temp.normalize().ScaleR(2.0*temp.len()/3.0);
00072         
00073         temp = br - bl;
00074         points[3][1] = bl + temp.normalize().ScaleR(temp.len()/3.0);
00075         points[3][2] = bl + temp.normalize().ScaleR(2.0*temp.len()/3.0);
00076         
00077         
00078         //calculate intermediate left and right points  
00079         int i;
00080         for (i = 0; i < 4; i++)
00081         {
00082                 temp = points[3][i] - points[0][i];
00083                 points[1][i] = points[0][i] + temp.normalize().ScaleR(temp.len()/3.0);
00084                 points[2][i] = points[0][i] + temp.normalize().ScaleR(2.0*temp.len()/3.0);
00085         }
00086 }
00087 
00088 void BEZIER::Visualize(bool wireframe, bool fill, VERTEX color)
00089 {
00090         if (!fill && !wireframe)
00091                 return;
00092         
00093         glPushAttrib(GL_ALL_ATTRIB_BITS);
00094         
00095         glDisable(GL_LIGHTING);
00096         glDisable(GL_TEXTURE_2D);
00097         
00098         if (fill)
00099         {
00100                 glColor4f(1,1,1,1);
00101                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00102                 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00103                 glDisable(GL_DEPTH_TEST);
00104                 glEnable(GL_BLEND);
00105                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
00106                 float trans = 0.25;
00107                 glColor4f(1,1,1,trans);
00108                 DrawSurf(SURFDRAW_VIS, trans);
00109                 glEnable(GL_DEPTH_TEST);
00110         }
00111         
00112         if (wireframe)
00113         {
00114                 glDisable(GL_DEPTH_TEST);
00115                 glLineWidth(1.0);
00116                 glEnable(GL_BLEND);
00117                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
00118                 //glColor4f(.5,.6,.5,0.1);
00119                 glColor4f(color.x, color.y, color.z,0.1);
00120                 DrawControlPoints();
00121                 
00122                 glEnable(GL_DEPTH_TEST);
00123                 glDisable(GL_BLEND);
00124                 glLineWidth(2.0);
00125                 glColor4f(color.x, color.y, color.z,1);
00126                 DrawControlPoints();
00127         }
00128         
00129         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00130         glPopAttrib();
00131 }
00132 
00133 void BEZIER::DrawSurf(int div, float trans)
00134 {
00135         int x, y;
00136         
00137         float px, py, pxo, pyo, col;
00138         
00139         //VERTEX temp[4];
00140         VERTEX normal;
00141         
00142         if (div < 1)
00143                 div = 1;
00144         
00145         glBegin(GL_TRIANGLES);
00146         
00147         for (x = 0; x < div; x++)
00148         {
00149                 for (y = 0; y < div; y++)
00150                 {
00151                         //if (x < div - 1 && y < div - 1)
00152                         {
00153                                 px = (float) x / (float) div;
00154                                 py = (float) y / (float) div;
00155                                 pxo = (float) (x+1) / (float) div;
00156                                 pyo = (float) (y+1) / (float) div;
00157                                 
00158                                 normal = (SurfCoord(pxo, pyo) - SurfCoord(px, py)).cross(SurfCoord(pxo, py) - SurfCoord(px, py));
00159                                 normal = normal.normalize();
00160                                 col = normal.y;
00161                                 col = col * col;
00162                                 glColor4f(col,col,col, trans);
00163                                 
00164                                 glVertex3fv(SurfCoord(pxo, py).v3());
00165                                 glVertex3fv(SurfCoord(px, py).v3());
00166                                 glVertex3fv(SurfCoord(px, pyo).v3());
00167                                 
00168                                 normal = (SurfCoord(px, pyo) - SurfCoord(px, py)).cross(SurfCoord(pxo, pyo) - SurfCoord(px, py));
00169                                 normal = normal.normalize();
00170                                 col = normal.y;
00171                                 col = col * col;
00172                                 glColor4f(col,col,col, trans);
00173                                 
00174                                 glVertex3fv(SurfCoord(px, pyo).v3());
00175                                 glVertex3fv(SurfCoord(pxo, pyo).v3());
00176                                 glVertex3fv(SurfCoord(pxo, py).v3());
00177                         }
00178                 }
00179         }
00180 
00181         glEnd();
00182 }
00183 
00184 void BEZIER::DrawControlPoints()
00185 {
00186         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00187 
00188         //glColor4f(1,0,0,1);
00189         
00190         /*int x, y;
00191         glPointSize(5.0);
00192         glBegin(GL_POINTS);
00193         
00194         for (x = 0; x < 4; x++)
00195         {
00196                 for (y = 0; y < 4; y++)
00197                 {
00198                         glVertex3fv(points[x][y].v3());
00199                 }
00200         }
00201 
00202         glEnd();*/
00203         
00204         //glColor4f(0,1,0,1);
00205         
00206         glBegin(GL_QUADS);
00207         
00208         glVertex3fv(points[0][0].v3());
00209         glVertex3fv(points[3][0].v3());
00210         glVertex3fv(points[3][3].v3());
00211         glVertex3fv(points[0][3].v3());
00212 
00213         glEnd();
00214         
00215         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00216 }
00217 
00218 void BEZIER::Attach(BEZIER & other)
00219 {
00220         int x;
00221         
00222         //move the other patch to the location of this patch
00223         /*for (x = 0; x < 4; x++)
00224                 points[0][x] = other.points[3][x];*/
00225         
00226         //move the other patch to the location of this patch and force its
00227         // intermediate points into a nice grid layout
00228         other.SetFromCorners(other.points[0][0], other.points[0][3], points[0][0], points[0][3]);
00229         
00230         VERTEX slope;
00231         
00232         for (x = 0; x < 4; x++)
00233         {
00234                 //slope points in the forward direction
00235                 slope = (other.points[0][x] - points[3][x]).normalize();
00236                 
00237                 float otherlen = (other.points[0][x] - other.points[3][x]).len();
00238                 float mylen = (points[0][x] - points[3][x]).len();
00239                 
00240                 float meanlen = (otherlen + mylen)/2.0;
00241                 float leglen = meanlen / 3.0;
00242                 
00243                 other.points[2][x] = other.points[3][x] + slope.ScaleR(leglen);
00244                 points[1][x] = points[0][x] + slope.ScaleR(-leglen);
00245         }
00246 }
00247 
00248 VERTEX BEZIER::Bernstein(float u, VERTEX *p)
00249 {
00250         VERTEX  a, b, c, d, r;
00251 
00252         a = p[0].ScaleR(pow(u,3));
00253         b = p[1].ScaleR(3*pow(u,2)*(1-u));
00254         c = p[2].ScaleR(3*u*pow((1-u),2));
00255         d = p[3].ScaleR(pow((1-u),3));
00256 
00257         //r = pointAdd(pointAdd(a, b), pointAdd(c, d));
00258         r = a+b+c+d;
00259 
00260         return r;
00261 }
00262 
00263 VERTEX BEZIER::SurfCoord(float px, float py)
00264 {
00265         VERTEX temp[4];
00266         VERTEX temp2[4];
00267         int i, j;
00268 
00269         /*if (px == 0.0 && py == 0.0)
00270                 return points[3][3];
00271         if (px == 1.0 && py == 1.0)
00272                 return points[0][0];
00273         if (px == 1.0 && py == 0.0)
00274                 return points[0][3];
00275         if (px == 0.0 && py == 1.0)
00276                 return points[3][0];*/
00277         
00278         //get splines along x axis
00279         for (j = 0; j < 4; j++)
00280         {
00281                 for (i = 0; i < 4; i++)
00282                         temp2[i] = points[j][i];
00283                 temp[j] = Bernstein(px, temp2);
00284         }
00285         
00286         return Bernstein(py, temp);
00287 }
00288 
00289 VERTEX BEZIER::SurfNorm(float px, float py)
00290 {
00291         VERTEX temp[4];
00292         VERTEX temp2[4];
00293         VERTEX tempx[4];
00294         int i, j;
00295 
00296         //get splines along x axis
00297         for (j = 0; j < 4; j++)
00298         {
00299                 for (i = 0; i < 4; i++)
00300                         temp2[i] = points[j][i];
00301                 temp[j] = Bernstein(px, temp2);
00302         }
00303         
00304         //get splines along y axis
00305         for (j = 0; j < 4; j++)
00306         {
00307                 for (i = 0; i < 4; i++)
00308                         temp2[i] = points[i][j];
00309                 tempx[j] = Bernstein(py, temp2);
00310         }
00311         
00312         //return BernsteinTangent(py, temp);
00313         return BernsteinTangent(px, tempx).cross(BernsteinTangent(py, temp)).normalize().InvertR();
00314 }
00315 
00316 VERTEX BEZIER::BernsteinTangent(float u, VERTEX *p)
00317 {
00318         VERTEX  a, b, c, r;
00319 
00320         a = (p[1]-p[0]).ScaleR(3*pow(u,2));
00321         b = (p[2]-p[1]).ScaleR(3*2*u*(1-u));
00322         c = (p[3]-p[2]).ScaleR(3*pow((1-u),2));
00323 
00324         //r = pointAdd(pointAdd(a, b), pointAdd(c, d));
00325         r = a+b+c;
00326 
00327         return r;
00328 }
00329 
00330 void BEZIER::GetTri(int div, int num, VERTEX outtri[3])
00331 {
00332         int firsttri = num % 2;
00333         
00334         int x = (num/2) % div;
00335         int y = (num/2) / div;
00336 
00337         if (firsttri == 0)
00338         {               
00339                 float px = (float) x / (float) div;
00340                 float py = (float) y / (float) div;
00341                 float pxo = (float) (x+1) / (float) div;
00342                 float pyo = (float) (y+1) / (float) div;
00343         
00344                 /*glVertex3fv(SurfCoord(px, py).v3());
00345                 glVertex3fv(SurfCoord(pxo, py).v3());
00346                 glVertex3fv(SurfCoord(pxo, pyo).v3());*/
00347                 
00348                 outtri[0] = SurfCoord(px, py);
00349                 outtri[1] = SurfCoord(pxo, py);
00350                 outtri[2] = SurfCoord(px, pyo);
00351         }
00352         else
00353         {
00354                 float px = (float) x / (float) div;
00355                 float py = (float) y / (float) div;
00356                 float pxo = (float) (x+1) / (float) div;
00357                 float pyo = (float) (y+1) / (float) div;
00358                 
00359                 /*glVertex3fv(SurfCoord(px, py).v3());
00360                 glVertex3fv(SurfCoord(pxo, pyo).v3());
00361                 glVertex3fv(SurfCoord(px, pyo).v3());*/
00362                 
00363                 outtri[0] = SurfCoord(pxo, pyo);
00364                 outtri[1] = SurfCoord(px, pyo);
00365                 outtri[2] = SurfCoord(pxo, py);
00366         }
00367 }
00368 
00369 bool BEZIER::CollideSubDiv(VERTEX origin, VERTEX direction, VERTEX &outtri)
00370 {
00371         int i;
00372         
00373         VERTEX curtri[3];
00374         
00375         int retval = 0;
00376         
00377         float t, u, v;
00378         
00379         int x, y;
00380         
00381         for (i = 0; i < NumTris(COLLISION_DIVS) && !retval; i++)
00382         {       
00383                 GetTri(COLLISION_DIVS, i, curtri);
00384                 
00385                 retval = INTERSECT_FUNCTION(origin.v3(), direction.v3(),
00386                         curtri[0].v3(), curtri[1].v3(), curtri[2].v3(), 
00387                         &t, &u, &v);
00388                 
00389                 if (retval)
00390                 {
00391                         if (i % 2 == 0)
00392                         {
00393                                 u = 1.0 - u;
00394                                 v = 1.0 - v;
00395                         }
00396                         
00397                         u = 1.0 - u;
00398                         v = 1.0 - v;
00399                         
00400                         x = (i/2) % COLLISION_DIVS;
00401                         y = (i/2) / COLLISION_DIVS;
00402                         u += (float) x;
00403                         v += (float) y;
00404                         u = u / (float) COLLISION_DIVS;
00405                         v = v / (float) COLLISION_DIVS;
00406                         
00407                         //u = 1.0 - u;
00408                         //v = 1.0 - v;
00409                         
00410                         //cout << u << "," << v << endl;
00411                         outtri = SurfCoord(u, v);
00412                         //outtri = curtri[0].ScaleR(1-u-v) + curtri[1].ScaleR(u) + curtri[2].ScaleR(v);
00413                         return true;
00414                 }
00415         }
00416         
00417         outtri = origin;
00418         return false;
00419 }
00420 
00421 bool BEZIER::CollideNewton(VERTEX origin, VERTEX direction, VERTEX &outtri)
00422 {
00423         int i;
00424         
00425         VERTEX curtri[3];
00426         VERTEX coltri[3];
00427         
00428         int retval = 0;
00429         bool collided = false;
00430         
00431         float su, sv, tu, tv;
00432         su = sv = tu = tv = 0;
00433         
00434         float t, u, v;
00435         
00436         int x, y;
00437         int j;
00438         
00439         for (i = 0; i < NumTris(1) && !retval; i++)
00440         {       
00441                 GetTri(COLLISION_DIVS, i, curtri);
00442                 
00443                 retval = INTERSECT_FUNCTION(origin.v3(), direction.v3(),
00444                         curtri[0].v3(), curtri[1].v3(), curtri[2].v3(), 
00445                         &t, &u, &v);
00446                 
00447                 if (retval)
00448                 {
00449                         for (j = 0; j < 3; j++)
00450                                 coltri[j] = curtri[j];
00451                         tu = u;
00452                         tv = v;
00453                         
00454                         if (i % 2 == 0)
00455                         {
00456                                 u = 1.0 - u;
00457                                 v = 1.0 - v;
00458                         }
00459                         
00460                         u = 1.0 - u;
00461                         v = 1.0 - v;
00462                         
00463                         x = (i/2) % COLLISION_DIVS;
00464                         y = (i/2) / COLLISION_DIVS;
00465                         u += (float) x;
00466                         v += (float) y;
00467                         u = u / (float) COLLISION_DIVS;
00468                         v = v / (float) COLLISION_DIVS;
00469                         
00470                         //u = 1.0 - u;
00471                         //v = 1.0 - v;
00472                         
00473                         //cout << u << "," << v << endl;
00474                         outtri = SurfCoord(u, v);
00475                         su = u;
00476                         sv = v;
00477                         //return true;
00478                         collided = true;
00479                 }
00480         }
00481         
00482         if (collided)
00483         {
00484                 bool loop = true;
00485                 bool verbose = false;
00486                 VERTEX normal;
00487                 VERTEX approx;
00488                 VERTEX actual;
00489                 VERTEX guess = outtri;
00490                 VERTEX correct;
00491                 MATRIX3 proj;
00492                 
00493                 float error, lasterror;
00494                 
00495                 approx = curtri[0].ScaleR(1-tu-tv) + curtri[1].ScaleR(tu) + curtri[2].ScaleR(tv);
00496                 
00497                 float spanu = (points[0][3] - points[0][0]).len();
00498                 float spanv = (points[3][0] - points[0][0]).len();
00499                 
00500                 //error = (approx - outtri).len();
00501                 //error is the distance from direction vector to actual position
00502                 VERTEX dirnorm = direction.normalize();
00503                 VERTEX errorvec;
00504                 
00505                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00506                 error = errorvec.len();
00507                 lasterror = error;
00508                 
00509                 if (verbose)
00510                         cout << error << endl;
00511                 
00512                 float uit = (error / spanu)/2.0;
00513                 float vit = (error / spanv)/2.0;
00514                 float nu, nv;
00515                 
00516                 float biasv, biasu;
00517                 biasu = biasv = 1.0;
00518                 
00519                 float erroru, errorv;
00520                 
00521                 nu = su + uit;
00522                 nv = sv + vit;
00523                 if (nu > 1.0)
00524                         nu = 1.0;
00525                 if (nv > 1.0)
00526                         nv = 1.0;
00527                 guess = SurfCoord(nu,sv);
00528                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00529                 error = errorvec.len();
00530                 erroru = error - lasterror;
00531                 if (error > lasterror)
00532                         biasu = -1.0;
00533                 if (verbose) cout << error << endl;
00534                 guess = SurfCoord(su,nv);
00535                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00536                 error = errorvec.len();
00537                 errorv = error - lasterror;
00538                 if (error > lasterror)
00539                         biasv = -1.0;
00540                 if (verbose) cout << error << endl;
00541                         
00542                 biasu *= erroru/(erroru+errorv);
00543                 biasv *= errorv/(erroru+errorv);
00544                 
00545                 VERTEX lastguess = guess;
00546                 
00547                 nu = su;
00548                 nv = sv;
00549                 
00550                 float ou, ov;
00551                 ou = nu;
00552                 ov = nv;
00553                 
00554                 VERTEX tempguess;
00555                 
00556                 int n;
00557                 for (n = 0; (n < 20) && loop; n++)
00558                 {
00559                         lastguess = guess;
00560                         ou = nu;
00561                         ov = nv;
00562                         
00563                         nu += biasu * (error / spanu)/1.0;
00564                         nv += biasv * (error / spanv)/1.0;
00565                         
00566                         tempguess = SurfCoord(nu, ov);
00567                         if (((tempguess - origin) - dirnorm.ScaleR((tempguess - origin).dot(dirnorm))).len() > lasterror)
00568                         {
00569                                 biasu = 0.0;
00570                                 nu = ou;
00571                         }
00572                         tempguess = SurfCoord(ou, nv);
00573                         if (((tempguess - origin) - dirnorm.ScaleR((tempguess - origin).dot(dirnorm))).len() > lasterror)
00574                         {
00575                                 biasv = 0.0;
00576                                 nv = ov;
00577                         }
00578                         
00579                         guess = SurfCoord(nu, nv);
00580                         
00581                         lasterror = error;
00582                         errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00583                         error = errorvec.len();
00584                         if (verbose) cout << n << ": " << error << endl;
00585                         
00586                         if (lasterror <= error || biasu == 0.0 && biasv == 0.0)
00587                                 loop = false;
00588                 }
00589                 
00590                 /*int n;
00591                 for (n = 0; (n < 1) && loop; n++)
00592                 {
00593                         cout << n << ": " << error << endl;
00594                         
00595                         actual = SurfCoord(su, sv);
00596                         normal = SurfNorm(su, sv);
00597                         proj.ProjectionMatrix(normal.normalize());
00598                         correct = approx - actual;
00599                         guess = proj.Multiply(correct);
00600                         
00601                         lasterror = error;
00602                         errorvec = dirnorm.ScaleR((outtri - origin).dot(dirnorm));
00603                         error = errorvec.len();
00604                 }*/
00605                 
00606                 /*approx.DebugPrint();
00607                 actual.DebugPrint();
00608                 normal.DebugPrint();
00609                 //proj.DebugPrint();
00610                 guess.DebugPrint();
00611                 guess = guess + actual;
00612                 guess.DebugPrint();*/
00613                 //cout << n << ": " << (guess - outtri).len() << endl;
00614                 if (verbose) cout << endl;
00615                 
00616                 outtri = lastguess;     
00617                 
00618                 return true;
00619         }
00620         
00621         outtri = origin;
00622         return false;
00623 }
00624 
00625 void BEZIER::CopyFrom(BEZIER &other)
00626 {
00627         int x, y;
00628         
00629         for (x = 0; x < 4; x++)
00630         {
00631                 for (y = 0; y < 4; y++)
00632                 {
00633                         points[x][y] = other.points[x][y];
00634                 }
00635         }
00636 }
00637 
00638 bool BEZIER::ReadFrom(ifstream &openfile)
00639 {
00640         int x, y;
00641         
00642         if (!openfile)
00643                 return false;
00644         
00645         for (x = 0; x < 4; x++)
00646         {
00647                 for (y = 0; y < 4; y++)
00648                 {
00649                         openfile >> points[x][y].x;
00650                         openfile >> points[x][y].y;
00651                         openfile >> points[x][y].z;
00652                 }
00653         }
00654         
00655         return true;
00656 }
00657 
00658 bool BEZIER::WriteTo(ofstream &openfile)
00659 {
00660         int x, y;
00661         
00662         for (x = 0; x < 4; x++)
00663         {
00664                 for (y = 0; y < 4; y++)
00665                 {
00666                         openfile << points[x][y].x << " ";
00667                         openfile << points[x][y].y << " ";
00668                         openfile << points[x][y].z << endl;
00669                 }
00670         }
00671         
00672         return true;
00673 }
00674 
00675 bool BEZIER::CollideSingleQuad(VERTEX origin, VERTEX direction, VERTEX &outtri)
00676 {
00677         bool col = false;
00678         
00679         float t, u, v;
00680         
00681         col = INTERSECT_QUAD_FUNCTION(origin, direction,
00682                 points[0][0], points[0][3], points[3][3], points[3][0],
00683                 t, u, v);
00684         
00685         if (col)
00686         {
00687                 /*if (i % 2 == 0)
00688                 {
00689                         u = 1.0 - u;
00690                         v = 1.0 - v;
00691                 }
00692                 
00693                 u = 1.0 - u;
00694                 v = 1.0 - v;
00695                 
00696                 x = (i/2) % COLLISION_DIVS;
00697                 y = (i/2) / COLLISION_DIVS;
00698                 u += (float) x;
00699                 v += (float) y;
00700                 u = u / (float) COLLISION_DIVS;
00701                 v = v / (float) COLLISION_DIVS;*/
00702                 
00703                 u = 1.0 - u;
00704                 v = 1.0 - v;
00705                 
00706                 //cout << u << "," << v << endl;
00707                 outtri = SurfCoord(u, v);
00708                 //outtri = curtri[0].ScaleR(1-u-v) + curtri[1].ScaleR(u) + curtri[2].ScaleR(v);
00709                 return true;
00710         }
00711         
00712         outtri = origin;
00713         return false;
00714 }
00715 
00716 bool BEZIER::CollideQuadNewton(VERTEX origin, VERTEX direction, VERTEX &outtri)
00717 {
00718         bool col = false;
00719         
00720         float t, u, v;
00721         
00722         col = INTERSECT_QUAD_FUNCTION(origin, direction,
00723                 points[0][0], points[0][3], points[3][3], points[3][0],
00724                 t, u, v);
00725         
00726         if (col)
00727         {
00728                 /*if (i % 2 == 0)
00729                 {
00730                         u = 1.0 - u;
00731                         v = 1.0 - v;
00732                 }
00733                 
00734                 u = 1.0 - u;
00735                 v = 1.0 - v;
00736                 
00737                 x = (i/2) % COLLISION_DIVS;
00738                 y = (i/2) / COLLISION_DIVS;
00739                 u += (float) x;
00740                 v += (float) y;
00741                 u = u / (float) COLLISION_DIVS;
00742                 v = v / (float) COLLISION_DIVS;*/
00743                 
00744                 u = 1.0 - u;
00745                 v = 1.0 - v;
00746                 
00747                 //cout << u << "," << v << endl;
00748                 outtri = SurfCoord(u, v);
00749                 float su = u;
00750                 float sv = v;
00751                 //outtri = curtri[0].ScaleR(1-u-v) + curtri[1].ScaleR(u) + curtri[2].ScaleR(v);
00752                 
00753                 bool loop = true;
00754                 bool verbose = true;
00755                 VERTEX normal;
00756                 VERTEX approx;
00757                 VERTEX actual;
00758                 VERTEX guess = outtri;
00759                 VERTEX correct;
00760                 MATRIX3 proj;
00761                 
00762                 float error, lasterror;
00763                 
00764                 float spanu = (points[0][3] - points[0][0]).len();
00765                 float spanv = (points[3][0] - points[0][0]).len();
00766                 
00767                 //error = (approx - outtri).len();
00768                 //error is the distance from direction vector to actual position
00769                 VERTEX dirnorm = direction.normalize();
00770                 VERTEX errorvec;
00771                 
00772                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00773                 error = errorvec.len();
00774                 lasterror = error;
00775                 
00776                 if (verbose)
00777                         cout << error << endl;
00778                 
00779                 float uit = (error / spanu)/2.0;
00780                 float vit = (error / spanv)/2.0;
00781                 float nu, nv;
00782                 
00783                 float biasv, biasu;
00784                 biasu = biasv = 1.0;
00785                 
00786                 float erroru, errorv;
00787                 
00788                 nu = su + uit;
00789                 nv = sv + vit;
00790                 if (nu > 1.0)
00791                         nu = 1.0;
00792                 if (nv > 1.0)
00793                         nv = 1.0;
00794                 guess = SurfCoord(nu,sv);
00795                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00796                 error = errorvec.len();
00797                 erroru = error - lasterror;
00798                 if (error > lasterror)
00799                         biasu = -1.0;
00800                 if (verbose) cout << error << endl;
00801                 guess = SurfCoord(su,nv);
00802                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00803                 error = errorvec.len();
00804                 errorv = error - lasterror;
00805                 if (error > lasterror)
00806                         biasv = -1.0;
00807                 if (verbose) cout << error << endl;
00808                         
00809                 biasu *= erroru/(erroru+errorv);
00810                 biasv *= errorv/(erroru+errorv);
00811                 
00812                 VERTEX lastguess = guess;
00813                 
00814                 nu = su;
00815                 nv = sv;
00816                 
00817                 float ou, ov;
00818                 ou = nu;
00819                 ov = nv;
00820                 
00821                 VERTEX tempguess;
00822                 
00823                 int n;
00824                 for (n = 0; (n < 5) && loop; n++)
00825                 {
00826                         lastguess = guess;
00827                         ou = nu;
00828                         ov = nv;
00829                         
00830                         nu += biasu * (error / spanu)/1.0;
00831                         nv += biasv * (error / spanv)/1.0;
00832                         
00833                         tempguess = SurfCoord(nu, ov);
00834                         if (((tempguess - origin) - dirnorm.ScaleR((tempguess - origin).dot(dirnorm))).len() > lasterror)
00835                         {
00836                                 biasu = 0.0;
00837                                 nu = ou;
00838                         }
00839                         tempguess = SurfCoord(ou, nv);
00840                         if (((tempguess - origin) - dirnorm.ScaleR((tempguess - origin).dot(dirnorm))).len() > lasterror)
00841                         {
00842                                 biasv = 0.0;
00843                                 nv = ov;
00844                         }
00845                         
00846                         guess = SurfCoord(nu, nv);
00847                         
00848                         lasterror = error;
00849                         errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00850                         error = errorvec.len();
00851                         if (verbose) cout << n << ": " << error << endl;
00852                         
00853                         if (lasterror <= error || biasu == 0.0 && biasv == 0.0)
00854                                 loop = false;
00855                 }
00856                 
00857                 /*int n;
00858                 for (n = 0; (n < 1) && loop; n++)
00859                 {
00860                         cout << n << ": " << error << endl;
00861                         
00862                         actual = SurfCoord(su, sv);
00863                         normal = SurfNorm(su, sv);
00864                         proj.ProjectionMatrix(normal.normalize());
00865                         correct = approx - actual;
00866                         guess = proj.Multiply(correct);
00867                         
00868                         lasterror = error;
00869                         errorvec = dirnorm.ScaleR((outtri - origin).dot(dirnorm));
00870                         error = errorvec.len();
00871                 }*/
00872                 
00873                 /*approx.DebugPrint();
00874                 actual.DebugPrint();
00875                 normal.DebugPrint();
00876                 //proj.DebugPrint();
00877                 guess.DebugPrint();
00878                 guess = guess + actual;
00879                 guess.DebugPrint();*/
00880                 //cout << n << ": " << (guess - outtri).len() << endl;
00881                 if (verbose) cout << endl;
00882                 
00883                 outtri = lastguess;     
00884                 
00885                 return true;
00886         }
00887         
00888         outtri = origin;
00889         return false;   
00890 }
00891 
00892 bool BEZIER::CollideSubDivQuad(VERTEX origin, VERTEX direction, VERTEX &outtri)
00893 {
00894         bool col = false;
00895         
00896         const bool verbose = false;
00897         
00898         const bool projhack = true;
00899         
00900         if (projhack)
00901                 origin.y = 1;
00902         
00903         float t, u, v;
00904         
00905         float su = 0;
00906         float sv = 0;
00907         
00908         float umin = 0;
00909         float umax = 1;
00910         float vmin = 0;
00911         float vmax = 1;
00912         
00913         /*VERTEX ul = points[0][0];
00914         VERTEX ur = points[0][3];
00915         VERTEX br = points[3][3];
00916         VERTEX bl = points[3][0];*/
00917         
00918         VERTEX ul = points[3][3];
00919         VERTEX ur = points[3][0];
00920         VERTEX br = points[0][0];
00921         VERTEX bl = points[0][3];
00922         
00923         int subdivnum = 0;
00924 
00925         int i;
00926         for (i = 0; i < COLLISION_QUAD_DIVS; i++)
00927         {       
00928                 //speedup for i == 0
00929                 if (i != 0)
00930                 {
00931                         ul = SurfCoord(umin, vmin);
00932                         ur = SurfCoord(umax, vmin);
00933                         br = SurfCoord(umax, vmax);
00934                         bl = SurfCoord(umin, vmax);
00935                 }
00936                 
00937                 if (projhack)
00938                 {
00939                         ul.y = ur.y = br.y = bl.y = 0;
00940                 }
00941                 
00942                 //u = v = 0.0;
00943 
00944                 col = INTERSECT_QUAD_FUNCTION(origin, direction,
00945                         ul, ur, br, bl,
00946                         t, u, v);
00947                 
00948                 if (col)
00949                 {
00950                         //correct UV
00951                         //u = 1.0 - u;
00952                         //v = 1.0 - v;
00953                         
00954                         //expand quad UV to surface UV
00955                         su = u * (umax - umin) + umin;
00956                         sv = v * (vmax - vmin) + vmin;
00957                         
00958                         //calculate error
00959                         if (verbose)
00960                         {
00961                                 VERTEX guess = SurfCoord(su, sv);
00962                                 VERTEX dirnorm = direction.normalize();
00963                                 VERTEX errorvec;
00964                                 
00965                                 errorvec = (guess - origin) - dirnorm.ScaleR((guess - origin).dot(dirnorm));
00966                                 
00967                                 cout << i << ": " << errorvec.len() << endl;
00968                         }
00969                         
00970                         //evaluate which quadrant was hit
00971                         if (v <= 0.5)
00972                         {
00973                                 //top side
00974                                 vmax = 0.5*(vmax-vmin)+vmin;
00975                                 subdivnum = 0;
00976                         }
00977                         else
00978                         {
00979                                 //bottom side
00980                                 vmin = 0.5*(vmax-vmin)+vmin;
00981                                 subdivnum = 2;
00982                         }
00983                         
00984                         if (u <= 0.5)
00985                         {
00986                                 //left side
00987                                 umax = 0.5*(umax-umin) + umin;
00988                         }
00989                         else
00990                         {
00991                                 //right side
00992                                 umin = 0.5*(umax-umin) + umin;
00993                                 subdivnum++;
00994                         }
00995                         
00996                         //outtri = SurfCoord(u, v);
00997                 }
00998                 else
00999                 {
01000                         if (verbose)
01001                                 cout << i << ": nocol " << origin.x << endl;
01002                         
01003                         if ((i == 0) && QUAD_DIV_FAST_DISCARD)
01004                         //if (QUAD_DIV_FAST_DISCARD)
01005                         {
01006                                 outtri = origin;
01007                                 return false;
01008                         }
01009                         else
01010                         {
01011                                 //need to try again with a different subdiv
01012                                 
01013                                 //undo previous changes to uv rect
01014                                 float umin0 = umin;
01015                                 float umax0 = umax;
01016                                 float vmin0 = vmin;
01017                                 float vmax0 = vmax;
01018                                 
01019                                 if (subdivnum < 2)
01020                                         vmax0 = (vmax-vmin)*2.0 + vmin;
01021                                 else
01022                                         vmin0 = vmax - (vmax-vmin)*2.0;
01023                                 
01024                                 if (subdivnum % 2 == 0)
01025                                         umax0 = (umax-umin)*2.0 + umin;
01026                                 else
01027                                         umin0 = umax - (umax-umin)*2.0;
01028                                 
01029                                 if (verbose)
01030                                 {
01031                                         cout << endl << "Guessed wrong on " << subdivnum << endl;
01032                                         cout << umin << ", " << umax << " : " << vmin << ", " << vmax << endl;
01033                                         cout << umin0 << ", " << umax0 << " : " << vmin0 << ", " << vmax0 << endl;
01034                                 }
01035                                 
01036                                 if (verbose)
01037                                 {
01038                                         cout << "!" << subdivnum << endl;
01039                                         ul.DebugPrint();
01040                                         ur.DebugPrint();
01041                                         br.DebugPrint();
01042                                         bl.DebugPrint();
01043                                         cout << endl;
01044                                 }
01045                                 
01046                                 //try other rects
01047                                 int s;
01048                                 bool scol = false;
01049                                 int curnum = 0;
01050                                 for (s = 1; s < 4 && !scol; s++)
01051                                 {
01052                                         curnum = (4 + subdivnum - s) % 4;
01053                                         
01054                                         vmin = vmin0;
01055                                         vmax = vmax0;
01056                                         umin = umin0;
01057                                         umax = umin0;
01058                                         
01059                                         if (curnum < 2)
01060                                                 vmax = 0.5*(vmax0-vmin0)+vmin0;
01061                                         else
01062                                                 vmin = 0.5*(vmax0-vmin0)+vmin0;
01063                                         
01064                                         if (curnum % 2 == 0)
01065                                                 umax = 0.5*(umax0-umin0) + umin0;
01066                                         else
01067                                                 umin = 0.5*(umax0-umin0) + umin0;
01068                                         
01069                                         if (verbose)
01070                                         {
01071                                                 cout << curnum << endl;
01072                                                 cout << umin0 << ", " << umax0 << " : " << vmin0 << ", " << vmax0 << endl;
01073                                                 cout << umin << ", " << umax << " : " << vmin << ", " << vmax << endl;
01074                                         }
01075 
01076                                         ul = SurfCoord(umin, vmin);
01077                                         ur = SurfCoord(umax, vmin);
01078                                         br = SurfCoord(umax, vmax);
01079                                         bl = SurfCoord(umin, vmax);
01080                                         
01081                                         if (projhack)
01082                                         {
01083                                                 ul.y = ur.y = br.y = bl.y = 0;
01084                                         }
01085                                         
01086                                         if (verbose)
01087                                         {
01088                                                 ul.DebugPrint();
01089                                                 ur.DebugPrint();
01090                                                 br.DebugPrint();
01091                                                 bl.DebugPrint();
01092                                                 cout << endl;
01093                                         }
01094                         
01095                                         scol = INTERSECT_QUAD_FUNCTION(origin, direction,
01096                                                 ul, ur, br, bl,
01097                                                 t, u, v);
01098                                         
01099                                         if (scol)
01100                                         {
01101                                                 //rejoice!
01102                                                 su = u * (umax - umin) + umin;
01103                                                 sv = v * (vmax - vmin) + vmin;
01104                                                 
01105                                                 //evaluate which quadrant was hit
01106                                                 if (v <= 0.5)
01107                                                 {
01108                                                         //top side
01109                                                         vmax = 0.5*(vmax-vmin)+vmin;
01110                                                         subdivnum = 0;
01111                                                 }
01112                                                 else
01113                                                 {
01114                                                         //bottom side
01115                                                         vmin = 0.5*(vmax-vmin)+vmin;
01116                                                         subdivnum = 2;
01117                                                 }
01118                                                 
01119                                                 if (u <= 0.5)
01120                                                 {
01121                                                         //left side
01122                                                         umax = 0.5*(umax-umin) + umin;
01123                                                 }
01124                                                 else
01125                                                 {
01126                                                         //right side
01127                                                         umin = 0.5*(umax-umin) + umin;
01128                                                         subdivnum++;
01129                                                 }
01130                                         }
01131                                 }
01132                                 
01133                                 if (verbose)
01134                                 {
01135                                         if (!scol)
01136                                         {
01137                                                 cout << "Never found poper quad. " << origin.x << endl;
01138                                                 //origin.DebugPrint();
01139                                                 //direction.DebugPrint();
01140                                                 //cout << endl;
01141                                         }
01142                                         //else
01143                                                 //cout << "Found proper quad after " << s-1 << " trie(s). " << origin.x << endl;
01144                                 }
01145                                 
01146                                 if (!scol)
01147                                 {
01148                                         //cry
01149                                         
01150                                         //outtri = origin;
01151                                         //return false;
01152                                 }
01153                         }
01154                         
01155                         /*if (i != 0)
01156                         {
01157                                 loop = false;
01158                                 u = oldu;
01159                                 v = oldv;
01160                         }*/
01161                 }
01162         }
01163         
01164         if (verbose)
01165                 cout << endl;
01166         
01167         /*col = INTERSECT_QUAD_FUNCTION(origin, direction,
01168                 points[0][0], points[0][3], points[3][3], points[3][0],
01169                 t, u, v);
01170         
01171         if (col)
01172         {       
01173                 u = 1.0 - u;
01174                 v = 1.0 - v;
01175                 
01176                 //cout << u << "," << v << endl;
01177                 outtri = SurfCoord(u, v);
01178                 return true;
01179         }*/
01180         
01181         if (col || QUAD_DIV_FAST_DISCARD)
01182         //if (col)
01183         {
01184                 if (!col)
01185                         cout << "blip " << su << "," << sv << ": " << u << "," << v << endl;
01186                 outtri = SurfCoord(su, sv);
01187                 return true;
01188         }
01189         else
01190         {
01191                 outtri = origin;
01192                 return false;
01193         }       
01194 }
01195 
01196 bool BEZIER::CollideSubDivQuadSimple(VERTEX origin, VERTEX direction, VERTEX &outtri)
01197 {
01198         VERTEX normal;
01199         return CollideSubDivQuadSimpleNorm(origin, direction, outtri, normal);
01200 }
01201 
01202 bool BEZIER::CollideSubDivQuadSimpleNorm(VERTEX origin, VERTEX direction, VERTEX &outtri, VERTEX & normal)
01203 {
01204         bool col = false;
01205         
01206         const bool verbose = false;
01207         //const bool verbose = true;
01208         
01209         const bool projhack = false;
01210         
01211         if (projhack)
01212                 origin.y = 1;
01213         
01214         float t, u, v;
01215         
01216         float su = 0;
01217         float sv = 0;
01218         
01219         float umin = 0;
01220         float umax = 1;
01221         float vmin = 0;
01222         float vmax = 1;
01223         
01224         //const float fuzziness = 0.13;
01225         
01226         /*VERTEX ul = points[0][0];
01227         VERTEX ur = points[0][3];
01228         VERTEX br = points[3][3];
01229         VERTEX bl = points[3][0];*/
01230         
01231         VERTEX ul = points[3][3];
01232         VERTEX ur = points[3][0];
01233         VERTEX br = points[0][0];
01234         VERTEX bl = points[0][3];
01235         
01236         //int subdivnum = 0;
01237 
01238         bool loop = true;
01239         
01240         float areacut = 0.5;
01241 
01242         int i;
01243         for (i = 0; i < COLLISION_QUAD_DIVS && loop; i++)
01244         {
01245                 float tu[2];
01246                 float tv[2];
01247                 
01248                 //speedup for i == 0
01249                 //if (i != 0)
01250                 {
01251                         tu[0] = umin;
01252                         if (tu[0] < 0)
01253                                 tu[0] = 0;
01254                         tu[1] = umax;
01255                         if (tu[1] > 1)
01256                                 tu[1] = 1;
01257                         
01258                         tv[0] = vmin;
01259                         if (tv[0] < 0)
01260                                 tv[0] = 0;
01261                         tv[1] = vmax;
01262                         
01263                         if (tv[1] > 1)
01264                                 tv[1] = 1;
01265                         
01266                         ul = SurfCoord(tu[0], tv[0]);
01267                         ur = SurfCoord(tu[1], tv[0]);
01268                         br = SurfCoord(tu[1], tv[1]);
01269                         bl = SurfCoord(tu[0], tv[1]);
01270                         
01271                         /*umin = u[0];
01272                         umax = v[1];
01273                         vmin = v[0];
01274                         vmax = v[1];*/
01275                         
01276                         /*ul = SurfCoord(umin, vmin);
01277                         ur = SurfCoord(umax, vmin);
01278                         br = SurfCoord(umax, vmax);
01279                         bl = SurfCoord(umin, vmax);*/
01280                 }
01281                 
01282                 if (projhack)
01283                 {
01284                         ul.y = ur.y = br.y = bl.y = 0;
01285                 }
01286                 
01287                 //u = v = 0.0;
01288 
01289                 col = INTERSECT_QUAD_FUNCTION(origin, direction,
01290                         ul, ur, br, bl,
01291                         t, u, v);
01292                 
01293                 if (col)
01294                 {
01295                         //expand quad UV to surface UV
01296                         //su = u * (umax - umin) + umin;
01297                         //sv = v * (vmax - vmin) + vmin;
01298                         
01299                         su = u * (tu[1] - tu[0]) + tu[0];
01300                         sv = v * (tv[1] - tv[0]) + tv[0];
01301                         
01302                         //place max and min according to area hit
01303                         vmax = sv + (0.5*areacut)*(vmax-vmin);
01304                         vmin = sv - (0.5*areacut)*(vmax-vmin);
01305                         umax = su + (0.5*areacut)*(umax-umin);
01306                         umin = su - (0.5*areacut)*(umax-umin);
01307                         
01308                         /*//evaluate which quadrant was hit
01309                         if (v <= 0.5)
01310                         {
01311                                 //top side
01312                                 vmax = (0.5+fuzziness)*(vmax-vmin)+vmin;
01313                                 //vmax = (0.5+fuzziness)*(vmax-vmin)+vmin-fuzziness*0.5;
01314                                 //vmin -= fuzziness*0.5;
01315                                 subdivnum = 0;
01316                         }
01317                         else
01318                         {
01319                                 //bottom side
01320                                 vmin = (0.5-fuzziness)*(vmax-vmin)+vmin;
01321                                 subdivnum = 2;
01322                         }
01323                         
01324                         if (u <= 0.5)
01325                         {
01326                                 //left side
01327                                 umax = (0.5+fuzziness)*(umax-umin) + umin;
01328                         }
01329                         else
01330                         {
01331                                 //right side
01332                                 umin = (0.5-fuzziness)*(umax-umin) + umin;
01333                                 subdivnum++;
01334                         }*/
01335                 }
01336                 else
01337                 {
01338                         if ((i == 0) &&