Skip to content

Instantly share code, notes, and snippets.

@jdolan
Last active March 7, 2021 23:53
Show Gist options
  • Save jdolan/7807812 to your computer and use it in GitHub Desktop.
Save jdolan/7807812 to your computer and use it in GitHub Desktop.
BSP surface unwinding for surface area calculation
/*
* @brief Unwinds the surface, iterating all non-collinear vertices.
*
* @return The next winding point, or NULL if the face is completely unwound.
*/
static const vec_t *R_UnwindBspSurface(const r_bsp_model_t *bsp, const r_bsp_surface_t *surf,
const vec_t *last) {
const int32_t *se = &bsp->surface_edges[surf->first_edge];
const vec_t *v0 = R_BSP_VERTEX(bsp, *se)->position;
if (!last)
return v0;
uint16_t i;
for (i = 0; i < surf->num_edges; i++) {
const vec_t *v = R_BSP_VERTEX(bsp, se[i])->position;
if (VectorCompare(last, v)) {
break;
}
}
while (i < surf->num_edges - 1) {
const vec_t *v1 = R_BSP_VERTEX(bsp, se[(i + 1) % surf->num_edges])->position;
const vec_t *v2 = R_BSP_VERTEX(bsp, se[(i + 2) % surf->num_edges])->position;
vec3_t delta1, delta2;
VectorSubtract(v1, v0, delta1);
VectorSubtract(v2, v0, delta1);
VectorNormalize(delta1);
VectorNormalize(delta2);
if (DotProduct(delta1, delta2) < 1.0 - SIDE_EPSILON) {
return v1;
}
i++;
}
return NULL;
}
/*
* @brief Resolves the surface bounding box and lightmap texture coordinates.
*/
static void R_SetupBspSurface(r_bsp_model_t *bsp, r_bsp_surface_t *surf) {
// ..
if (surf->texinfo->light) { // resolve surface area
const vec_t *v0 = R_UnwindBspSurface(bsp, surf, NULL);
const vec_t *v1 = R_UnwindBspSurface(bsp, surf, v0);
const vec_t *v2 = R_UnwindBspSurface(bsp, surf, v1);
while (v1 && v2) {
vec3_t delta1, delta2, cross;
VectorSubtract(v1, v0, delta1);
VectorSubtract(v2, v0, delta2);
CrossProduct(delta1, delta2, cross);
surf->area += 0.5 * VectorLength(cross);
v1 = R_UnwindBspSurface(bsp, surf, v2);
v2 = R_UnwindBspSurface(bsp, surf, v1);
}
}
// ..
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment