Skip to content

Instantly share code, notes, and snippets.

@jdolan
Last active December 29, 2015 18:39
Show Gist options
  • Save jdolan/7711821 to your computer and use it in GitHub Desktop.
Save jdolan/7711821 to your computer and use it in GitHub Desktop.
Projection shadows
/*
* @brief Applies any configuration and tag alignment, populating the model-view
* matrix for the entity in the process.
*/
static void R_SetMatrixForEntity(r_entity_t *e) {
vec_t *o = e->origin, *a = e->angles;
if (e->parent) {
vec3_t forward, tmp;
if (!IS_MESH_MODEL(e->model)) {
Com_Warn("Invalid model for linked entity\n");
return;
}
const r_entity_t *p = e->parent;
while (p->parent) {
p = p->parent;
}
AngleVectors(p->angles, forward, NULL, NULL);
VectorClear(e->origin);
VectorClear(e->angles);
R_ApplyMeshModelConfig(e);
Matrix4x4_CreateFromQuakeEntity(&e->matrix, o[0], o[1], o[2], a[0], a[1], a[2], e->scale);
R_ApplyMeshModelTag(e); // interpolate and concatenate the tag matrix
Matrix4x4_Invert_Simple(&e->inverse_matrix, &e->matrix);
Matrix4x4_Transform(&e->matrix, vec3_origin, e->origin);
Matrix4x4_Transform(&e->inverse_matrix, forward, tmp);
VectorAngles(tmp, e->angles);
e->angles[ROLL] = p->angles[ROLL];
Com_Print("%s %s\n", e->model->media.name, vtos(e->angles));
return;
}
if (IS_MESH_MODEL(e->model)) {
R_ApplyMeshModelConfig(e);
}
Matrix4x4_CreateFromQuakeEntity(&e->matrix, o[0], o[1], o[2], a[0], a[1], a[2], e->scale);
Matrix4x4_Invert_Simple(&e->inverse_matrix, &e->matrix);
}
/*
* @brief Applies translation, rotation, scale and projection for the entity.
* We borrow the standard projection matrix from SGI's cookbook, and adjust it
* for Quake's negative-distance planes:
*
* ftp://ftp.sgi.com/opengl/contrib/blythe/advanced99/notes/node192.html
*/
static void R_RotateForMeshShadow_default(const r_entity_t *e) {
vec4_t pos, normal, origin;
matrix4x4_t proj;
vec_t dot;
if (!e) {
glPopMatrix();
return;
}
// transform the lighting position into model space
R_TransformForEntity(e, e->lighting->pos, pos);
pos[3] = 1.0;
// along with the impacted plane that we will project onto
Matrix4x4_TransformPositivePlane(&e->inverse_matrix, e->lighting->plane.normal[0],
e->lighting->plane.normal[1], e->lighting->plane.normal[2], e->lighting->plane.dist,
normal);
// project the shadow origin onto the impacted plane in model space
dot = DotProduct(vec3_origin, normal) - normal[3];
VectorScale(normal, -dot, origin);
// now translate, rotate and scale for a generic shadow projection
glPushMatrix();
//glTranslatef(origin[0], origin[1], origin[2]); <-- COMMENT THIS OUT
glRotatef(-e->angles[ROLL], 1.0, 0.0, 0.0);
glRotatef(-e->angles[PITCH], 0.0, 1.0, 0.0);
glScalef(1.0, 1.0, 0.0);
// and sheer it, accounting for Quake's positive plane equation
normal[3] = -normal[3];
dot = DotProduct(pos, normal) + pos[3] * normal[3];
proj.m[0][0] = dot - pos[0] * normal[0];
proj.m[1][0] = 0.0 - pos[0] * normal[1];
proj.m[2][0] = 0.0 - pos[0] * normal[2];
proj.m[3][0] = 0.0 - pos[0] * normal[3] + origin[0]; // WHY NO WORKY?
proj.m[0][1] = 0.0 - pos[1] * normal[0];
proj.m[1][1] = dot - pos[1] * normal[1];
proj.m[2][1] = 0.0 - pos[1] * normal[2];
proj.m[3][1] = 0.0 - pos[1] * normal[3] + origin[1];
proj.m[0][2] = 0.0 - pos[2] * normal[0];
proj.m[1][2] = 0.0 - pos[2] * normal[1];
proj.m[2][2] = dot - pos[2] * normal[2];
proj.m[3][2] = 0.0 - pos[2] * normal[3] + origin[2];
proj.m[0][3] = 0.0 - pos[3] * normal[0];
proj.m[1][3] = 0.0 - pos[3] * normal[1];
proj.m[2][3] = 0.0 - pos[3] * normal[2];
proj.m[3][3] = dot - pos[3] * normal[3];
glMultMatrixf((GLfloat *) proj.m);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment