the elusive shadow
by: akbar A.(syedali011@earthlink.net)
May 7, 2000
shadows;
there in are life everywhere, they are often casted onto a arbitrary (not always) planes from some sort of light source. i think i summed it pretty well for this paper.
see my initial plan in this paper was to make it like a book, beat around the bush for a while, propose all the shadow algorithms (alan watt is damn good at this, i think that is what he is famous for  ;)
and then tell you what are the benefits and fallbacks of choosing each diffrent shadowing model.
well i would just like to tell you that i have completely changed mind. first off i have not implemented all the shadow algorithms so i could not give you first hand experience on how they work out in practice etc..
i also want you to know that all. err. _MOST_ of the algorithms which people talk about or write programs about are not _NEW_ . These algorithms have been sitting on the shelves in manilla folders up in sgi's offices just waiting for someone to take the courage and actually code up these computer resources hogs(times use to be in the hours for simple z-buffering ).
Well it turned out a few years later, that these algorithms where really not slow at all. What took a few hours now was able to be proceed in a fraction of a second. Thus was born the technology age. A time where the algorithms matched the processors capabilities.
 

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
if it is not simple, then it will be a failure. akbar A.

that's all a shadow really is, in its simplest form. now all you have to do is figure out how to get that pink stuff to render onto your planes.
Well there are a few things which are given in your problem(get cool shadows in the application). Now, with this in mind we are going to have to create a matrix to project the new location of the shadow. It sounds complicated but i assure you it's not. First we are going to have to be able to calculate the plane equation. Well since we have the points of the plane it just a matter of plugging it into the equation. Just check your old high school calculus book and you will see it in there.
Here is how you go about finding the plane equation with the points. remember we are working in 3d space so each point has 3 slots, or components to go on the virtual coordinate plane.

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