A Simple Shadow
The idea is based on a situation where we position a light source in origo.
The plane (P!,P2,P3) is described with the equation: Ax+By+Cz=D.
private void CalculatePlane() { double[] v1={floor[3]-floor[0], //x floor[4]-floor[1], //y floor[5]-floor[2]}; //z double[] v2={floor[6]-floor[0], //x floor[7]-floor[1], //y floor[8]-floor[2]}; //z // crossproduct: (ay*bz-az*by, az*bx-ax*bz, ax*by-ay*bx) A = v1[1] * v2[2] - v1[2] * v2[1]; B = v1[2] * v2[0] - v1[0] * v2[2]; C = v1[0] * v2[1] - v1[1] * v2[0]; // using a point on the floor to find D D = -(A * floor[0] + B * floor[1] + C * floor[2]); }
Based on this we render the scene with;
public void display(GLAutoDrawable drawable) { GL gl = drawable.getGL(); GLU glu=new GLU(); // Clear the drawing area gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT| GL.GL_ACCUM_BUFFER_BIT); gl.glLoadIdentity(); // watch this glu.gluLookAt(25.0,25.0,20.0, 0.0,0.0,-10.0, 0.0,0.0,1.0); //gl.glRotatef(view_rotx,1.0f,0.0f,0.0f); //gl.glRotatef(view_roty,0.0f,1.0f,0.0f); // draw axes gl.glBegin(GL.GL_LINES); gl.glVertex3d(0.0, 0.0, 0.0); gl.glVertex3d(20.0, 0.0, 0.0); gl.glVertex3d(0.0, 0.0, 0.0); gl.glVertex3d(0.0, 20.0, 0.0); gl.glVertex3d(0.0, 0.0, -20.0); gl.glVertex3d(0.0, 0.0, 0.0); gl.glEnd(); // draw the light as a sphere // set bulb material stdMaterials.setMaterial(gl,stdMaterials.MAT_YELLOW_PLASTIC,GL.GL_FRONT); GLUquadric q=glu.gluNewQuadric(); q=glu.gluNewQuadric(); glu.gluSphere(q,0.5f,20,20); glu.gluDeleteQuadric(q); // draw the floor //set floormaterial stdMaterials.setMaterial(gl,stdMaterials.MAT_GREEN_RUBBER,GL.GL_FRONT); gl.glBegin(GL.GL_POLYGON); gl.glNormal3d(0.0, 0.0, 1.0); for (int ix = 0; ix < 12; ix += 3) gl.glVertex3d(floor[ix], floor[ix + 1], floor[ix + 2] - 0.1); gl.glEnd(); // draw the form that casts the shadow gl.glRotatef(ZRotation, 0.0f, 0.0f, 1.0f); // set form material stdMaterials.setMaterial(gl,stdMaterials.MAT_RUBY,GL.GL_FRONT); DrawForm(gl); // since light is in origo double[] mpx = {D, 0.0f,0.0f,-A, 0.0f,D, 0.0f,-B, 0.0f,0.0f,D, -C, 0.0f,0.0f,0.0f,0.0f}; gl.glPushMatrix(); gl.glMultMatrixd(mpx,0); // set shadow material stdMaterials.setMaterial(gl,stdMaterials.MAT_BLACK_RUBBER,GL.GL_FRONT); // draw the shadow DrawForm(gl); gl.glPopMatrix(); // Flush all drawing operations to the graphics card gl.glFlush(); }
The form casting the shadow is rendered like this;
private void DrawForm(GL gl) { double[] triangle ={5.0,0.0,0.0, 0.0,5.0,0.0, 5.0,5.0,0.0}; int Radius = 7; GLU glu=new GLU(); GLUT glut=new GLUT(); GLUquadric glpQ=glu.gluNewQuadric(); gl.glTranslatef(0.0f,0.0f,ZElevation); switch (SelectedForm) { case 1:glu.gluSphere(glpQ,Radius/3.0f,20,20);break; case 2:theTorus.drawTorus(Radius, Radius/10.0f, 50, 50);break; case 3:glut.glutSolidTeapot(1.0);break; default: gl.glBegin(GL.GL_POLYGON); gl.glNormal3d(A, B, C); for (int ix = 0; ix < 9; ix += 3) gl.glVertex3d(triangle[ix], triangle[ix + 1], triangle[ix + 2]); gl.glEnd(); break; } gl.glTranslatef(0.0f,0.0f,-ZElevation); glu.gluDeleteQuadric(glpQ); }