bool BEZIER::Collide(VERTEX origin, VERTEX direction, VERTEX &outtri) { int i; VERTEX curtri[3]; int retval = 0; float t, u, v; int x, y; for (i = 0; i < NumTris(COLLISION_DIVS) && !retval; i++) { GetTri(COLLISION_DIVS, i, curtri); retval = INTERSECT_FUNCTION(origin.v3(), direction.v3(), curtri[0].v3(), curtri[1].v3(), curtri[2].v3(), &t, &u, &v); if (retval) { if (i % 2 == 0) { u = 1.0 - u; v = 1.0 - v; } u = 1.0 - u; v = 1.0 - v; x = (i/2) % COLLISION_DIVS; y = (i/2) / COLLISION_DIVS; u += (float) x; v += (float) y; u = u / (float) COLLISION_DIVS; v = v / (float) COLLISION_DIVS; //u = 1.0 - u; //v = 1.0 - v; //cout << u << "," << v << endl; outtri = SurfCoord(u, v); return true; } } outtri = origin; return false; }
void BEZIER::GetTri(int div, int num, VERTEX outtri[3]) { int firsttri = num % 2; int x = (num/2) % div; int y = (num/2) / div; if (firsttri == 0) { float px = (float) x / (float) div; float py = (float) y / (float) div; float pxo = (float) (x+1) / (float) div; float pyo = (float) (y+1) / (float) div; /*glVertex3fv(SurfCoord(px, py).v3()); glVertex3fv(SurfCoord(pxo, py).v3()); glVertex3fv(SurfCoord(pxo, pyo).v3());*/ outtri[0] = SurfCoord(px, py); outtri[1] = SurfCoord(pxo, py); outtri[2] = SurfCoord(px, pyo); } else { float px = (float) x / (float) div; float py = (float) y / (float) div; float pxo = (float) (x+1) / (float) div; float pyo = (float) (y+1) / (float) div; /*glVertex3fv(SurfCoord(px, py).v3()); glVertex3fv(SurfCoord(pxo, pyo).v3()); glVertex3fv(SurfCoord(px, pyo).v3());*/ outtri[0] = SurfCoord(pxo, pyo); outtri[1] = SurfCoord(px, pyo); outtri[2] = SurfCoord(pxo, py); } }
bool Bezier::CollideSubDivQuadSimpleNorm(const Vec3 & origin, const Vec3 & direction, Vec3 &outtri, Vec3 & normal) const { bool col = false; const int COLLISION_QUAD_DIVS = 6; const float areacut = 0.5; float t, u, v; float su = 0; float sv = 0; float umin = 0; float umax = 1; float vmin = 0; float vmax = 1; Vec3 ul = points[3][3]; Vec3 ur = points[3][0]; Vec3 br = points[0][0]; Vec3 bl = points[0][3]; for (int i = 0; i < COLLISION_QUAD_DIVS; i++) { float tu[2]; float tv[2]; //speedup for i == 0 //if (i != 0) { tu[0] = umin; if (tu[0] < 0) tu[0] = 0; tu[1] = umax; if (tu[1] > 1) tu[1] = 1; tv[0] = vmin; if (tv[0] < 0) tv[0] = 0; tv[1] = vmax; if (tv[1] > 1) tv[1] = 1; ul = SurfCoord(tu[0], tv[0]); ur = SurfCoord(tu[1], tv[0]); br = SurfCoord(tu[1], tv[1]); bl = SurfCoord(tu[0], tv[1]); } col = IntersectQuadrilateralF(origin, direction, ul, ur, br, bl, t, u, v); if (col) { //expand quad UV to surface UV //su = u * (umax - umin) + umin; //sv = v * (vmax - vmin) + vmin; su = u * (tu[1] - tu[0]) + tu[0]; sv = v * (tv[1] - tv[0]) + tv[0]; //place max and min according to area hit vmax = sv + (0.5*areacut)*(vmax - vmin); vmin = sv - (0.5*areacut)*(vmax - vmin); umax = su + (0.5*areacut)*(umax - umin); umin = su - (0.5*areacut)*(umax - umin); } else { outtri = origin; return false; } } outtri = SurfCoord(su, sv); normal = SurfNorm(su, sv); return true; }
void Bezier::Attach(Bezier & other, bool reverse) { /*if (!reverse) { //move the other patch to the location of this patch and force its // intermediate points into a nice grid layout other.SetFromCorners(other.points[0][0], other.points[0][3], points[0][0], points[0][3]); for (int x = 0; x < 4; x++) { //slope points in the forward direction Vec3 slope = other.points[0][x] - points[3][x]; if (slope.Magnitude() > 0.0001) slope = slope.Normalize(); float otherlen = (other.points[0][x] - other.points[3][x]).Magnitude(); float mylen = (points[0][x] - points[3][x]).Magnitude(); float meanlen = (otherlen + mylen)/2.0; float leglen = meanlen / 3.0; if (slope.Magnitude() > 0.0001) { other.points[2][x] = other.points[3][x] + slope*leglen; points[1][x] = points[0][x] + slope*(-leglen); } else { other.points[2][x] = other.points[3][x]; points[1][x] = points[0][x]; } } }*/ //CheckForProblems(); //store the pointer to next patch next_patch = &other; //calculate the track radius at the connection of this patch and next patch Vec3 a = SurfCoord(0.5,0.0); Vec3 b = SurfCoord(0.5,1.0); Vec3 c = other.SurfCoord(0.5,1.0); if (reverse) { a = SurfCoord(0.5,1.0); b = SurfCoord(0.5,0.0); c = other.SurfCoord(0.5,0.0); //Reverse(); } //racing_line = a; Vec3 d1 = a - b; Vec3 d2 = c - b; float diff = d2.Magnitude() - d1.Magnitude(); double dd = ((d1.Magnitude() < 0.0001) || (d2.Magnitude() < 0.0001)) ? 0.0 : d1.Normalize().dot(d2.Normalize()); float angle = acos((dd>=1.0L)?1.0L:(dd<=-1.0L)?-1.0L:dd); float d1d2mag = d1.Magnitude() + d2.Magnitude(); float alpha = (d1d2mag < 0.0001) ? 0.0f : (M_PI * diff + 2.0 * d1.Magnitude() * angle) / d1d2mag / 2.0; if (fabs(alpha - M_PI/2.0) < 0.001) track_radius = 10000.0; else track_radius = d1.Magnitude() / 2.0 / cos(alpha); if (d1.Magnitude() < 0.0001) track_curvature = 0.0; else track_curvature = 2.0 * cos(alpha) / d1.Magnitude(); //determine it's a left or right turn at the connection Vec3 d = d1.cross(d2); if (fabs(d[0]) < 0.1 && fabs(d[1]) < 0.1 && fabs(d[2]) < 0.1) { turn = 0; //straight ahead } else if (d[1] > 0.0) turn = -1; //left turn ahead else turn = 1; //right turn ahead //calculate distance from start of the road if (other.next_patch == NULL || reverse) other.dist_from_start = dist_from_start + d1.Magnitude(); length = d1.Magnitude(); }
bool BEZIER::CollideSubDivQuadSimpleNorm(const MATHVECTOR<float,3> & origin, const MATHVECTOR<float,3> & direction, MATHVECTOR<float,3> &outtri, MATHVECTOR<float,3> & normal) const { bool col = false; const int COLLISION_QUAD_DIVS = 6; const bool QUAD_DIV_FAST_DISCARD = true; float t, u, v; float su = 0; float sv = 0; float umin = 0; float umax = 1; float vmin = 0; float vmax = 1; //const float fuzziness = 0.13; MATHVECTOR<float,3> ul = points[3][3]; MATHVECTOR<float,3> ur = points[3][0]; MATHVECTOR<float,3> br = points[0][0]; MATHVECTOR<float,3> bl = points[0][3]; //int subdivnum = 0; bool loop = true; float areacut = 0.5; for (int i = 0; i < COLLISION_QUAD_DIVS && loop; i++) { float tu[2]; float tv[2]; //speedup for i == 0 //if (i != 0) { tu[0] = umin; if (tu[0] < 0) tu[0] = 0; tu[1] = umax; if (tu[1] > 1) tu[1] = 1; tv[0] = vmin; if (tv[0] < 0) tv[0] = 0; tv[1] = vmax; if (tv[1] > 1) tv[1] = 1; ul = SurfCoord(tu[0], tv[0]); ur = SurfCoord(tu[1], tv[0]); br = SurfCoord(tu[1], tv[1]); bl = SurfCoord(tu[0], tv[1]); } //u = v = 0.0; col = IntersectQuadrilateralF(origin, direction, ul, ur, br, bl, t, u, v); if (col) { //expand quad UV to surface UV //su = u * (umax - umin) + umin; //sv = v * (vmax - vmin) + vmin; su = u * (tu[1] - tu[0]) + tu[0]; sv = v * (tv[1] - tv[0]) + tv[0]; //place max and min according to area hit vmax = sv + (0.5*areacut)*(vmax-vmin); vmin = sv - (0.5*areacut)*(vmax-vmin); umax = su + (0.5*areacut)*(umax-umin); umin = su - (0.5*areacut)*(umax-umin); } else { if ((i == 0) && QUAD_DIV_FAST_DISCARD) //if (QUAD_DIV_FAST_DISCARD) { outtri = origin; return false; } else { /*if (verbose) { cout << "<" << i << ": nocol " << su << "," << sv << ">" << endl; cout << "<" << umin << "," << umax << ";" << vmin << "," << vmax << ">" << endl; ul.DebugPrint(); ur.DebugPrint(); bl.DebugPrint(); br.DebugPrint(); cout << endl; }*/ loop = false; } } } if (col)// || QUAD_DIV_FAST_DISCARD) //if (col) { /*if (!col) cout << "blip " << su << "," << sv << ": " << u << "," << v << endl;*/ outtri = SurfCoord(su, sv); normal = SurfNorm(su, sv); //if (verbose) //cout << "<" << i << ">" << endl; return true; } else { outtri = origin; return false; } }
void BEZIER::DrawSurf(int div, float trans) { int x, y; float px, py, pxo, pyo, col; //VERTEX temp[4]; VERTEX normal; if (div < 1) div = 1; glBegin(GL_TRIANGLES); for (x = 0; x < div; x++) { for (y = 0; y < div; y++) { //if (x < div - 1 && y < div - 1) { px = (float) x / (float) div; py = (float) y / (float) div; pxo = (float) (x+1) / (float) div; pyo = (float) (y+1) / (float) div; normal = (SurfCoord(pxo, pyo) - SurfCoord(px, py)).cross(SurfCoord(pxo, py) - SurfCoord(px, py)); normal = normal.normalize(); col = normal.y; col = col * col; glColor4f(col,col,col, trans); glVertex3fv(SurfCoord(pxo, py).v3()); glVertex3fv(SurfCoord(px, py).v3()); glVertex3fv(SurfCoord(px, pyo).v3()); normal = (SurfCoord(px, pyo) - SurfCoord(px, py)).cross(SurfCoord(pxo, pyo) - SurfCoord(px, py)); normal = normal.normalize(); col = normal.y; col = col * col; glColor4f(col,col,col, trans); glVertex3fv(SurfCoord(px, pyo).v3()); glVertex3fv(SurfCoord(pxo, pyo).v3()); glVertex3fv(SurfCoord(pxo, py).v3()); } } } glEnd(); }