VRML 2.0

Virtual Shadows
Copyright © 1999 Leonardo Boselli. All Rights Reserved.

This first part is included in the ShadowTest class (the Applet that controls the VRML world). It creates the Shadow object, sets all the parameters (Light, Transform and IndexedFaceSet) and then adds the shadow to the world.

package IT.uno.vrml.worlds;

import IT.uno.vrml.eai.*;
import IT.uno.vrml.eai.shd.*;

public class ShadowTest extends BasicWorld {

  public void run() {
    //...

    Shadow shd = new Shadow(this);
    shd.setLight(the_directional_light);
    shd.setTransform(the_incapsulating_transform);
    shd.setIndexedFaceSet(the_index_face_set,the_coordinate_index_array);
    shd.update();
    add(shd);

    //...
  }

  //...
}

This is the complete Shadow class. The constructor initializes the structure of the Shadow object. Then there are some methods that set all the required parameters. Finally, the update method modifies the shadow vertexes when the object changes location or shape. This is the most useful method and includes the calculations for all the transformations applied to the object and for the plane projection.

package IT.uno.vrml.eai.shd;

import IT.uno.vrml.eai.*;
import IT.uno.vrml.eai.utl.*;

public class Shadow extends Group {

  private Transform transform;
  private IndexedFaceSet body;
  private IndexedFaceSet faceSet;
  private Coordinate coord;
  private float[] origin = {0,0,0};
  private float[] orient = {0,1,0};
  private DirectionalLight light;

  public Shadow(World w) {
    super(w);
    Shape s = new Shape(w);
    faceSet = new IndexedFaceSet(w);
    coord = new Coordinate(w);
    faceSet.setCoord(coord);
    s.setGeometry(faceSet);
    Appearance a = new Appearance(w);
    Material m = new Material(w);
    m.setTransparency(0.5f);
    float[] c = {.2f,.2f,.2f};
    m.setDiffuseColor(c);
    a.setMaterial(m);
    s.setAppearance(a);
    addChildren(s);
  }

  public void setPlane(float[] org, float[] orn) {
    origin = org;
    orient = Vec.normalize(orn);
  }

  public void setLight(DirectionalLight l) {
    light = l;
  }

  public void setTransform(Transform t) {
    transform = t;
  }

  public void setIndexedFaceSet(IndexedFaceSet ifs, int[] ci) {
    body = ifs;
    faceSet.setCoordIndex(ci);
  }

  public void update() {
    float[][] point = body.getCoord().getPoint();
    float[][] shadow = new float[point.length][];
    float[] direct = light.getDirection();
    float den = Vec.scalar(direct,orient);
    float[] t = transform.getTranslation();
    float[] r = transform.getRotation();
    if(r[3] != 0) {
      float[] c = transform.getCenter();
      float rx = r[0];
      float ry = r[1];
      float rz = r[2];
      float ra = -r[3];
      float sina = (float)Math.sin(ra);
      float cosa = (float)Math.cos(ra);
      float mcosa = (float)(1-cosa);
      float rxymcosa = rx*ry*mcosa;
      float ryzmcosa = ry*rz*mcosa;
      float rxzmcosa = rx*rz*mcosa;
      float rxsina = rx*sina;
      float rysina = ry*sina;
      float rzsina = rz*sina;
      float rx2mcosacosa = rx*rx*mcosa+cosa;
      float ry2mcosacosa = ry*ry*mcosa+cosa;
      float rz2mcosacosa = rz*rz*mcosa+cosa;
      float rxymcosaprzsina = rxymcosa+rzsina;
      float rxzmcosamrysina = rxzmcosa-rysina;
      float ryzmcosaprxsina = ryzmcosa+rxsina;
      float rxymcosamrzsina = rxymcosa-rzsina;
      float rxzmcosaprysina = rxzmcosa+rysina;
      float ryzmcosamrxsina = ryzmcosa-rxsina;
      float t0c0 = t[0]+c[0];
      float t1c1 = t[1]+c[1];
      float t2c2 = t[2]+c[2];
      for(int n = 0; n < point.length; n++) {
        float x = point[n][0]-c[0];
        float y = point[n][1]-c[1];
        float z = point[n][2]-c[2];
        float[] pt = {
          rx2mcosacosa*x+rxymcosaprzsina*y+rxzmcosamrysina*z+t0c0,
          ry2mcosacosa*y+ryzmcosaprxsina*z+rxymcosamrzsina*x+t1c1,
          rz2mcosacosa*z+rxzmcosaprysina*x+ryzmcosamrxsina*y+t2c2
        };
        float k = Vec.scalar(Vec.subtract(pt,origin),orient)/den;
        shadow[n] = Vec.subtract(pt,Vec.scale(k,direct));
      }
    } else {
      for(int n = 0; n < point.length; n++) {
        float[] pt = {
          point[n][0]+t[0],
          point[n][1]+t[1],
          point[n][2]+t[2]
        };
        float k = Vec.scalar(Vec.subtract(pt,origin),orient)/den;
        shadow[n] = Vec.subtract(pt,Vec.scale(k,direct));
      }
    }
    coord.setPoint(shadow);
  }

}

More questions? Send a query to TETRACTYS Freeware.


TETRACTYS Freeware Main Page hosted by GeoCities Get your own Free Home Page