00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00062 points[0][0] = fl;
00063 points[0][3] = fr;
00064 points[3][3] = br;
00065 points[3][0] = bl;
00066
00067
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
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
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
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
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
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
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
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
00223
00224
00225
00226
00227
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
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
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
00270
00271
00272
00273
00274
00275
00276
00277
00278
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
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
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
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
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
00345
00346
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
00360
00361
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
00408
00409
00410
00411 outtri = SurfCoord(u, v);
00412
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
00471
00472
00473
00474 outtri = SurfCoord(u, v);
00475 su = u;
00476 sv = v;
00477
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
00501
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
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
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
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 u = 1.0 - u;
00704 v = 1.0 - v;
00705
00706
00707 outtri = SurfCoord(u, v);
00708
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
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 u = 1.0 - u;
00745 v = 1.0 - v;
00746
00747
00748 outtri = SurfCoord(u, v);
00749 float su = u;
00750 float sv = v;
00751
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
00768
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
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
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
00914
00915
00916
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
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
00943
00944 col = INTERSECT_QUAD_FUNCTION(origin, direction,
00945 ul, ur, br, bl,
00946 t, u, v);
00947
00948 if (col)
00949 {
00950
00951
00952
00953
00954
00955 su = u * (umax - umin) + umin;
00956 sv = v * (vmax - vmin) + vmin;
00957
00958
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
00971 if (v <= 0.5)
00972 {
00973
00974 vmax = 0.5*(vmax-vmin)+vmin;
00975 subdivnum = 0;
00976 }
00977 else
00978 {
00979
00980 vmin = 0.5*(vmax-vmin)+vmin;
00981 subdivnum = 2;
00982 }
00983
00984 if (u <= 0.5)
00985 {
00986
00987 umax = 0.5*(umax-umin) + umin;
00988 }
00989 else
00990 {
00991
00992 umin = 0.5*(umax-umin) + umin;
00993 subdivnum++;
00994 }
00995
00996
00997 }
00998 else
00999 {
01000 if (verbose)
01001 cout << i << ": nocol " << origin.x << endl;
01002
01003 if ((i == 0) && QUAD_DIV_FAST_DISCARD)
01004
01005 {
01006 outtri = origin;
01007 return false;
01008 }
01009 else
01010 {
01011
01012
01013
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
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
01102 su = u * (umax - umin) + umin;
01103 sv = v * (vmax - vmin) + vmin;
01104
01105
01106 if (v <= 0.5)
01107 {
01108
01109 vmax = 0.5*(vmax-vmin)+vmin;
01110 subdivnum = 0;
01111 }
01112 else
01113 {
01114
01115 vmin = 0.5*(vmax-vmin)+vmin;
01116 subdivnum = 2;
01117 }
01118
01119 if (u <= 0.5)
01120 {
01121
01122 umax = 0.5*(umax-umin) + umin;
01123 }
01124 else
01125 {
01126
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
01139
01140
01141 }
01142
01143
01144 }
01145
01146 if (!scol)
01147 {
01148
01149
01150
01151
01152 }
01153 }
01154
01155
01156
01157
01158
01159
01160
01161 }
01162 }
01163
01164 if (verbose)
01165 cout << endl;
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181 if (col || QUAD_DIV_FAST_DISCARD)
01182
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
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
01225
01226
01227
01228
01229
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
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
01249
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
01272
01273
01274
01275
01276
01277
01278
01279
01280 }
01281
01282 if (projhack)
01283 {
01284 ul.y = ur.y = br.y = bl.y = 0;
01285 }
01286
01287
01288
01289 col = INTERSECT_QUAD_FUNCTION(origin, direction,
01290 ul, ur, br, bl,
01291 t, u, v);
01292
01293 if (col)
01294 {
01295
01296
01297
01298
01299 su = u * (tu[1] - tu[0]) + tu[0];
01300 sv = v * (tv[1] - tv[0]) + tv[0];
01301
01302
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
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 }
01336 else
01337 {
01338 if ((i == 0) &&