sim.portrayal3d.simple.LightPortrayal3D Maven / Gradle / Ivy
Show all versions of mason Show documentation
/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.portrayal3d.simple;
import sim.portrayal3d.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import sim.util.*;
import java.awt.*;
/** A simple Portrayal3D which provides ambient, directional, or point light to the scene. While this could be used
in a FieldPortrayal to represent its objects, it's more likely to be dropped directly into the Display3D itself. Your
light can be any color, and it will have infinite bounds -- it irradiates everything regardless of where it is -- meaning there's no such thing as a shadow. LightPortrayals aren't selectable: how can you catch a moonbeam in your hand?
- Ambient Light is light which seems to come from all around and has no direct source.
- Directional Light comes from a point light source located infinitely far away. Thus there is a direction in which the light is shining. The classic example: sunlight.
- Point Light comes from a point light source located at a finite position (like a light bulb). If you place a point light source in a field portrayal, the position you'd specified here will get scaled and translated just like any other object. Point light also has an attenuation -- a degree to which its strength drops off. The attenuation is calculated as an equation on the distance d that the object is from the light source: q^2 * d + l * d + c, where q is the quadratic attenuation, l is the linear attenuation and c is the constant attenuation. A good default is c=1,l=0,q=0.
In fact, the default objects provided in the simulator (such as SpherePortrayal3D) don't respond to light at all -- they
just display themselves with their given color as if there were a magical light source. To get them to respond
in a different fashion, you'll need to provide them with a different Appearance object, and set that Appearance's
ColoringAttributes and Material. Here's an example which makes a green sphere that's harshly lit only on the side where it receives light, else it's jet black.
import javax.media.j3d.*;
import javax.vecmath.*;
Color3f color = new Color3f(Color.green);
Appearance appearance = new Appearance();
appearance.setColoringAttributes(
new ColoringAttributes(color, ColoringAttributes.SHADE_GOURAUD));
Material m= new Material();
m.setAmbientColor(color);
m.setEmissiveColor(0f,0f,0f);
m.setDiffuseColor(color);
m.setSpecularColor(1f,1f,1f);
m.setShininess(128f);
appearance.setMaterial(m);
SpherePortrayal3D sphere = new SpherePortrayal3D(appearance, 1.0f);
*/
public class LightPortrayal3D extends SimplePortrayal3D
{
Light light;
Vector3f double3DToVector3f(Double3D d)
{
Vector3f v = new Vector3f();
v.x = (float)d.x; v.y = (float)d.y; v.z = (float)d.z;
return v;
}
/** Directional Light */
public LightPortrayal3D(Color color, Double3D direction)
{
light = new DirectionalLight(new Color3f(color),double3DToVector3f(direction));
light.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), Double.POSITIVE_INFINITY));
}
/** Ambient Light */
public LightPortrayal3D(Color color)
{
light = new AmbientLight(new Color3f(color));
light.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), Double.POSITIVE_INFINITY));
}
/** Point Light. If you don't know what to provide for attenutation, you can't go wrong with 1,0,0. */
public LightPortrayal3D(Color color, Double3D position,
float constantAttenuation, float linearAttenuation, float quadraticAttenuation)
{
PointLight p = new PointLight();
p.setAttenuation(constantAttenuation, linearAttenuation, quadraticAttenuation);
p.setPosition((float)position.x,(float)position.y,(float)position.z);
light = p;
light.setColor(new Color3f(color));
light.setInfluencingBounds(new BoundingSphere(new Point3d(0,0,0), Double.POSITIVE_INFINITY));
}
/** Provide your own Light! */
public LightPortrayal3D(Light light)
{
this.light = light;
}
public TransformGroup getModel(Object obj, TransformGroup j3dModel)
{
if(j3dModel==null)
{
j3dModel = new TransformGroup();
j3dModel.setCapability(Group.ALLOW_CHILDREN_READ);
Light l = (Light)(light.cloneTree(false));
clearPickableFlags(l); // make un-pickable. How do you catch a moonbeam in your hand?
j3dModel.addChild(l);
}
return j3dModel;
}
}