Skip to content

Commit

Permalink
ray4: Eliminate large goto statement
Browse files Browse the repository at this point in the history
  • Loading branch information
hollasch committed Nov 13, 2024
1 parent 22aa29c commit bc97368
Showing 1 changed file with 64 additions and 66 deletions.
130 changes: 64 additions & 66 deletions ray4/src/r4_trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,104 +92,102 @@ void RayTrace (

double NdotD = 0; // Normal dot ray direction

if (!(nearattr->flags & (AT_DIFFUSE | AT_SPECULAR)))
goto REFTRAN;
if (nearattr->flags & (AT_DIFFUSE | AT_SPECULAR)) {

// If we're looking at the object from `behind' (or inside), then flip the normal vector.
// If we're looking at the object from `behind' (or inside), then flip the normal vector.

NdotD = dot(nearnormal, ray.direction);
NdotD = dot(nearnormal, ray.direction);

if (NdotD > 0.0) {
nearnormal = -nearnormal;
NdotD = -NdotD;
}
if (NdotD > 0.0) {
nearnormal = -nearnormal;
NdotD = -NdotD;
}

// To avoid surface acne, move the intersection point just outside the object surface to prevent
// that same surface from erroneously shadowing itself.
// To avoid surface acne, move the intersection point just outside the object surface to
// prevent that same surface from erroneously shadowing itself.

Point4 intr_out = nearintr + (1e-10 * nearnormal); // Intersection Outside The Surface
Point4 intr_out = nearintr + (1e-10 * nearnormal); // Intersection Outside The Surface

// Add illumation to the point from all visible lights.
// Add illumation to the point from all visible lights.

for (auto *light = lightlist; light; light=light->next) {
Vector4 ldir; // Light Direction
double mindist; // Nearest Object Distance
for (auto *light = lightlist; light; light=light->next) {
Vector4 ldir; // Light Direction
double mindist; // Nearest Object Distance

if (light->type == LightType::Directional) {
ldir = light->direction;
mindist = -1.0;
} else {
double norm; // Vector Norm
if (light->type == LightType::Directional) {
ldir = light->direction;
mindist = -1.0;
} else {
double norm; // Vector Norm

ldir = light->position - intr_out;
ldir = light->position - intr_out;

// Normalize the light-direction vector. If the (point) light source is VERY close to
// the intersection point, then just set the light-direction vector to the surface
// normal.
// Normalize the light-direction vector. If the (point) light source is VERY close
// to the intersection point, then just set the light-direction vector to the
// surface normal.

mindist = norm = ldir.norm();
if (norm < epsilon)
ldir = nearnormal;
else
ldir /= norm;
}
mindist = norm = ldir.norm();
if (norm < epsilon)
ldir = nearnormal;
else
ldir /= norm;
}

// Determine if the light is obscurred by any other object. If the light is obscurred by a
// transparent object, then ignore refraction, but color the light we're receiving based on
// the object's transparent color.
// Determine if the light is obscurred by any other object. If the light is obscurred by
// a transparent object, then ignore refraction, but color the light we're receiving
// based on the object's transparent color.

auto lcolor = light->color; // Light Color
auto lcolor = light->color; // Light Color

for (optr=objlist; optr; optr=optr->next) {
double minsave=mindist; // Nearest Object Distance (saved)
for (optr=objlist; optr; optr=optr->next) {
double minsave=mindist; // Nearest Object Distance (saved)

if ((*optr->intersect)(optr, Ray4(intr_out, ldir), &mindist, nullptr, nullptr)) {
if (!(optr->attr->flags & AT_TRANSPAR))
break;
if ((*optr->intersect)(optr, Ray4(intr_out, ldir), &mindist, nullptr, nullptr)) {
if (!(optr->attr->flags & AT_TRANSPAR))
break;

lcolor *= optr->attr->Kt;
mindist = minsave;
lcolor *= optr->attr->Kt;
mindist = minsave;
}
}
}

// If an opaque object shadows us, then skip this light source. Also, if the maximum amount
// of light transmitted through transparent objects is less than 1/256, then this light
// source can add nothing significant, so skip it.
// If an opaque object shadows us, then skip this light source. Also, if the maximum
// amount of light transmitted through transparent objects is less than 1/256, then this
// light source can add nothing significant, so skip it.

if ((optr) || ((lcolor.r + lcolor.g + lcolor.b) < 0.001))
continue;
if ((optr) || ((lcolor.r + lcolor.g + lcolor.b) < 0.001))
continue;

// If surface normal is turned from light, skip this light.
// If surface normal is turned from light, skip this light.

double ftemp = dot(nearnormal, ldir); // Scratch Real Value
if (ftemp <= 0.0)
continue;
double ftemp = dot(nearnormal, ldir); // Scratch Real Value
if (ftemp <= 0.0)
continue;

// Add the diffuse component of the light.
// Add the diffuse component of the light.

color += ftemp * nearattr->Kd * lcolor;
color += ftemp * nearattr->Kd * lcolor;

// If this object has no specular reflection, do next light.
// If this object has no specular reflection, do next light.

if (!(nearattr->flags & AT_SPECULAR)) continue;
if (!(nearattr->flags & AT_SPECULAR)) continue;

// Calculate the light reflection vector.
// Calculate the light reflection vector.

ftemp *= 2.0;
Vector4 Refl = -ldir + (ftemp * nearnormal); // Reflection Vector
ftemp *= 2.0;
Vector4 Refl = -ldir + (ftemp * nearnormal); // Reflection Vector

// Calculate the cosine of the sight & reflection vectors, raised to the Phong power, for
// the specular reflection.
// Calculate the cosine of the sight & reflection vectors, raised to the Phong power,
// for the specular reflection.

ftemp = dot(-ray.direction, Refl);
if (ftemp > 0.0) {
ftemp = pow (ftemp, nearattr->shine);
color += ftemp * nearattr->Ks * lcolor;
ftemp = dot(-ray.direction, Refl);
if (ftemp > 0.0) {
ftemp = pow (ftemp, nearattr->shine);
color += ftemp * nearattr->Ks * lcolor;
}
}
}

REFTRAN:

// If we're at the mamximum raytrace depth now, don't go any deeper.

if (maxdepth && (level == maxdepth))
Expand Down

0 comments on commit bc97368

Please sign in to comment.