/*! \brief intersect a ray with a sphere, only returns the first intersection point */ Intersection_t *Intersect_Sphere(Rayf_t *ray, Geo_Sphere_t *sphere) { /* values for the quadric equation */ float a = LengthSqV3f(ray->dir); float b = 2 * DotV3f(ray->dir, ray->orig); float c = LengthSqV3f(ray->orig) - Sqrf(sphere->radius); float D = Sqrf(b) - (4 * a * c); if (D >= 0) { float t1 = (-b - sqrtf(D)) / (2 * a), t2 = (-b + sqrtf(D)) / (2 * a); /* two candidate intersection parameters */ float t; /* the smallest positive candidate intersection parameter */ /* if only 1 is negative the ray starts inside the sphere * if both are negative the sphere is behind the ray * either way there's no intersection */ if (t1 <= EPSILON || t2 <= EPSILON) return NULL; else if (t1 <= EPSILON) t = t2; else if (t2 <= EPSILON) t = t1; else t = Minf(t1, t2); Intersection_t *intersection = NEW(Intersection_t); intersection->t = t; RayToPointf(ray, t, intersection->point); /* for a sphere centered at the origin the normal of a point is the vector from the point to the origin */ CopyV3f(intersection->point, intersection->norm); NormalizeV3f(intersection->norm); /* compute texture coordinates */ intersection->u = ((atan2(intersection->norm[1], intersection->norm[0]) / 3.142) + 1) / 2; intersection->v = (intersection->norm[2] + 1) / 2; return intersection; } return NULL; }
void Graphics::render(TrackData_t *track) { if (!initialized) { error->log(GRAPHICS, IMPORTANT, "Render function called without graphics initialization\n"); return; } if (track) { int i, j; /* load in the vertices */ Vec3f_t vert; GLUquadricObj *quadobj = gluNewQuadric(); Vec3f_t v; Segment_t *seg; int len; float ang; glColor3f(1,1,0); glBegin(GL_LINES); for (i = 0; i < track->nLanes; i++) { for (j = 0; j < track->lanes[i].nSegs; j++) { seg = &track->lanes[i].segs[j]; switch (track->lanes[i].segs[j].kind) { case LINE_SEGMENT: CopyV3f(track->verts[seg->start], vert); glVertex3f(vert[0], vert[1] + .01, vert[2]); CopyV3f(track->verts[seg->end], vert); glVertex3f(vert[0], vert[1] + .01, vert[2]); break; case ARC_SEGMENT: glEnd(); CopyV3f(track->verts[seg->center],v); glPushMatrix(); glTranslatef(v[0], v[1] + .01, v[2]); glRotatef(-90,1,0,0); SubV3f(v, track->verts[seg->start], v); len = LengthV3f(v); ang = seg->end > seg->start ? seg->angle : -seg->angle; gluPartialDisk(quadobj, len-.05, len, 40, 5, 0, ang); gluPartialDisk(quadobj, len-.05, len, 40, 5, 0, ang); glPopMatrix(); glBegin(GL_LINES); break; } } } glEnd(); gluDeleteQuadric(quadobj); /* draw finish line */ glDisable(GL_LIGHTING); glColor3f(1,0,1); glLineStipple(1, 0x0C0F); glLineWidth(4); glBegin(GL_LINES); glVertex3fv(track->verts[track->sects[0].edges[0].start]); glVertex3fv(track->verts[track->sects[0].edges[1].start]); glEnd(); glLineWidth(1); glDisable(GL_LINE_STIPPLE); glEnable(GL_LIGHTING); } }