okay, enough of my babbling and on with some code. basically the method
we are going to be doing is "projecting matrices".
it's pretty neat once you get the hang of it, (note: by now you should
know matrices by the front of your palm. if you don't i highly recommend
that you learn _EVERY_ thing you can about them. i took the path of just
jumping in for the eye candy and i wasted countless hours trying to get
an object to project properly onto a plane. please take my word.)
and another thing, in this paper i am not going to show you how to
*derive* the equation or how it was coined up. this is totally up to you
to find. to give you a tip, usually it has to do with scaling and finding
things that are equal to one another. once that main equation
is set up , it is just matter of solving for your variable. that's
about it, really no magic involved.
simplicity is the key to everything
void findplane(float
plane[4], float v0[3], float v1[3], float v2[3])
{
float vec0[3],
vec1[3];
/* need 2 vectors
to find cross product, consult my vectors paper if you are uneasy about
this part, just hopefully by the time you read this i will have added the
cross product ;) */
vec0[X] = v1[X]
- v0[X];
vec0[Y] = v1[Y]
- v0[Y];
vec0[Z] = v1[Z]
- v0[Z];
vec1[X] = v2[X]
- v0[X];
vec1[Y] = v2[Y]
- v0[Y];
vec1[Z] = v2[Z]
- v0[Z];
/* find cross
product to get A, B, and C of plane equation */
plane[A] = vec0[Y]
* vec1[Z] - vec0[Z] * vec1[Y];
plane[B] = -(vec0[X]
* vec1[Z] - vec0[Z] * vec1[X]);
plane[C] = vec0[X]
* vec1[Y] - vec0[Y] * vec1[X];
plane[D] = -(plane[A]
* v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
}
Well that pretty much sums up how to get the plane equation. the next step is finding what is the "new projection" going to be. remember you are going to "project" your new coordinates onto this plane. Once you have the projection part done, it is just a matter of offsetting your new shadow on the new plane, to get your cool shadows.
the next part is pretty logical,
once you have the plane which you are projecting on, it is time to find
the matrix to splatter your new shadows on.
note:
the word splatter was used. this was the best word i could think of to
mean what i was trying to say. This is one of this things that i move my
hands a lot in. Well i move my hands in everything i talk about. oh well
;)
Basically what
we are going to do is get _NEW_ _DATA_ from the light source and the "new
plane" which you have just found with the equation up top. You could also
call this plane a ground plane but it depends what you would consider the
ground.
This is probably
one of the more messier parts of the code but i will take you through it.
void
make_shadow_matrix(GLfloat shadow_matrix[4][4],
GLfloat groundplane[4],
GLfloat lightpos[4])
{
GLfloat dot;
/* find dot product between light position vector and ground plane normal
*/
dot = groundplane[X] * lightpos[X] +
groundplane[Y] * lightpos[Y] +
groundplane[Z] * lightpos[Z] +
groundplane[W] * lightpos[W];
shadow_matrix[0][0] = dot - lightpos[X] * groundplane[X];
shadow_matrix[1][0] = 0.f - lightpos[X] * groundplane[Y];
shadow_matrix[2][0] = 0.f - lightpos[X] * groundplane[Z];
shadow_matrix[3][0] = 0.f - lightpos[X] * groundplane[W];
shadow_matrix[X][1] = 0.f - lightpos[Y] * groundplane[X];
shadow_matrix[1][1] = dot - lightpos[Y] * groundplane[Y];
shadow_matrix[2][1] = 0.f - lightpos[Y] * groundplane[Z];
shadow_matrix[3][1] = 0.f - lightpos[Y] * groundplane[W];
shadow_matrix[X][2] = 0.f - lightpos[Z] * groundplane[X];
shadow_matrix[1][2] = 0.f - lightpos[Z] * groundplane[Y];
shadow_matrix[2][2] = dot - lightpos[Z] * groundplane[Z];
shadow_matrix[3][2] = 0.f - lightpos[Z] * groundplane[W];
shadow_matrix[X][3] = 0.f - lightpos[W] * groundplane[X];
shadow_matrix[1][3] = 0.f - lightpos[W] * groundplane[Y];
shadow_matrix[2][3] = 0.f - lightpos[W] * groundplane[Z];
shadow_matrix[3][3] = dot - lightpos[W] * groundplane[W];
}
Heheh. take a look at the vector paper. heh. j/k. You _SHOULD_ be able to understand this if you have a good knowledge of matrices. If you don't please step back and learn about them.
Well if you are confident
and think that you can hack and get this projection function, then go for
it. All you need is some paper, graphicing calculatior, a lot of coke and
a few sharp pencils and you might end up suprising your self.
It is a really good feeling.
Well now you have everything
you need to know to render shadows. All you are going to do is use the
shadow_matrix as your projector. Once you project to the new location,
draw your shadows. simple as that.
Well there is some stenciling
work to do, but then again, aren't you supposed to know opengl ;)
I have attached the source
code below, but if you are two lazy i have also put up the binary
on my site.
good luck,
akbar A.
source file: shadow.c