I've hit what may be a lighting bug, and I wonder if someone could try to confirm my results on their system please.
The testcase is based on one of Florin's performance tests, and displays a number of cubes.
Each cube is in its own TransformGroup. Each TransformGroup has a yellow point light added to it. The PointLight is scoped to only affect that TransformGroup.
There are additionally a single ambient light and a single directional light each with default (universal) scope.
Each cube should therefore lit by exactly 3 lights (1 ambient, 1 directional, 1 point). The trouble is on my system, that only some of the cubes are lit by their point lights. See the attached JPEG for details.
Can anyone say if they get the same problem - I'm trying to work out if this is a general Java3D issue, or an issue with my machine/video card.
Thanks !
Rob --
Rob Nugent Sun Microsystems, Southampton, UK
[EMAIL PROTECTED]
Tel: +44 (0) 1489 585503 Fax: +44 (0) 1489 881363
<<inline: test.jpg>>
/* * $Id: $ * c. 2002 publity AG */
import java.awt.BorderLayout;
import java.awt.Color;
import java.util.Enumeration;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.Transform3D;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Appearance;
import javax.media.j3d.Material;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.PointLight;
import javax.media.j3d.Alpha;
import javax.media.j3d.Behavior;
import javax.media.j3d.WakeupCondition;
import javax.media.j3d.WakeupOnElapsedFrames;
import javax.media.j3d.Shape3D;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Geometry;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.vecmath.Vector3f;
import javax.vecmath.Point3d;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.timer.J3DTimer;
/**
*
* @author fherinean
* @version $Revision: $
*/
public class LTest extends JFrame
{
private JLabel label = new JLabel("FPS: ");
private Appearance app = null;
private QuadArray geom = null;
// box size
float size = 0.1f;
Point3f lower = new Point3f(-size, -size, -size);
Point3f upper = new Point3f(size, size, size);
// normals for a simple box
float[] normals = {
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f,
-1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
};
// box coords
float[] coords = {
lower.x, lower.y, upper.z, upper.x, lower.y, upper.z, upper.x, upper.y,
upper.z, lower.x, upper.y, upper.z,
upper.x, lower.y, upper.z, upper.x, lower.y, lower.z, upper.x, upper.y,
lower.z, upper.x, upper.y, upper.z,
upper.x, lower.y, lower.z, lower.x, lower.y, lower.z, lower.x, upper.y,
lower.z, upper.x, upper.y, lower.z,
lower.x, lower.y, lower.z, lower.x, lower.y, upper.z, lower.x, upper.y,
upper.z, lower.x, upper.y, lower.z,
lower.x, lower.y, lower.z, upper.x, lower.y, lower.z, upper.x, lower.y,
upper.z, lower.x, lower.y, upper.z,
upper.x, upper.y, lower.z, lower.x, upper.y, lower.z, lower.x, upper.y,
upper.z, upper.x, upper.y, upper.z,
};
public LTest()
{
super();
// create canvas & universe
Canvas3D c3d = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SimpleUniverse universe = new SimpleUniverse(c3d);
universe.addBranchGraph(createBranchBroup());
// show the window
getContentPane().add(c3d, BorderLayout.CENTER);
getContentPane().add(label, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
setVisible(true);
}
private BranchGroup createBranchBroup()
{
BranchGroup objRoot = new BranchGroup();
FPSCounter counter = new FPSCounter(6 * 6);
for (int k = 0; k < 6; k++)
{
for (int l = 0; l < 6; l++)
{
Vector3f position = new Vector3f(-1.0f + k * 0.05f, -0.9f + 0.38f * l,
-3.5f - (k * 0.3f));
TransformGroup objSpin = new TransformGroup();
objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objSpin.setCapabilityIsFrequent(TransformGroup.ALLOW_TRANSFORM_WRITE);
objSpin.addChild(new Shape3D(getGeometry(1, 0.4f, 0.0f),
getAppearance()));
counter.addTarget(objSpin, position);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),
Double.POSITIVE_INFINITY);
PointLight pl = new PointLight();
pl.setCapability(PointLight.ALLOW_STATE_WRITE);
pl.setColor(new Color3f(1.0f,1.0f,0.0f));
Point3f pos = new Point3f(1.25f,0.0f, 0.0f);
pl.setPosition(pos);
pl.setAttenuation(0.0f,0.0f,0.015f);
pl.setInfluencingBounds(bounds);
objSpin.addChild(pl);
pl.addScope(objSpin);
objRoot.addChild(objSpin);
}
}
objRoot.addChild(counter);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 1000.0);
Color3f ambientColor = new Color3f(0.3f, 0.3f, 0.3f);
AmbientLight ambientLightNode = new AmbientLight(ambientColor);
ambientLightNode.setInfluencingBounds(bounds);
objRoot.addChild(ambientLightNode);
//Skapa en direktionell ljusk�alla
Color3f light1Color = new Color3f(0.1f, 0.1f, 0.1f);
Vector3f light1Direction = new Vector3f(0.0f, 0.0f, -1.0f);
DirectionalLight light1 = new DirectionalLight();
light1.setInfluencingBounds(bounds);
light1.setDirection(light1Direction);
light1.setColor(light1Color);
objRoot.addChild(light1);
//objRoot.compile();
return objRoot;
}
private Appearance getAppearance()
{
if (app == null)
{
app = new Appearance();
Color3f ambient = new Color3f(Color.LIGHT_GRAY);
Color3f emissive = new Color3f(Color.BLACK);
Color3f diffuse = new Color3f(Color.LIGHT_GRAY);
Color3f specular = new Color3f(Color.WHITE);
Material material = new Material(ambient, emissive, diffuse, specular, 10);
app.setMaterial(material);
}
return app;
}
private Geometry getGeometry(int count, float dx, float dy)
{
if (geom == null)
{
Point3f coord = new Point3f();
Vector3f norm = new Vector3f();
geom = new QuadArray(24 * count,
QuadArray.COORDINATES | QuadArray.NORMALS);
int d = 0;
for (int i = 0; i < count; i++)
{
Transform3D trans = new Transform3D();
trans.setTranslation(new Vector3f(dx * i, dy * i, 0));
int d1 = 0;
for (int j = 0; j < 24; j++)
{
coord.set(coords[d1], coords[d1 + 1], coords[d1 + 2]);
trans.transform(coord);
geom.setCoordinate(d, coord);
norm.set(normals[d1], normals[d1 + 1], normals[d1 + 2]);
geom.setNormal(d++, norm);
d1 += 3;
}
}
}
return geom;
}
public static void main(String[] args)
{
new LTest();
}
public class FPSCounter
extends Behavior
{
private int nFrames;
private long startTime;
private final WakeupCondition w;
private int count = 0;
private Transform3D transform = new Transform3D();
private Alpha alpha = new Alpha(-1, 8000);
private Vector3f[] posArray;
private TransformGroup[] tgArray;
private int size = 0;
public FPSCounter(int size)
{
nFrames = 200;
this.size = size;
tgArray = new TransformGroup[size];
posArray = new Vector3f[size];
w = new WakeupOnElapsedFrames(0);
}
public void initialize()
{
count = 0;
setSchedulingBounds(new BoundingSphere(new Point3d(), 1000));
startTime = J3DTimer.getValue();
wakeupOn(w);
}
public void processStimulus(Enumeration criteria)
{
count++;
if (count == nFrames)
{
long time = J3DTimer.getValue();
label.setText("FPS: " + (1000000000.0f * nFrames / (time -
startTime)));
startTime = time;
count = 0;
}
transform.rotX(alpha.value() * Math.PI * 2);
for (int i = 0; i < size; i++)
{
transform.setTranslation(posArray[i]);
tgArray[i].setTransform(transform);
}
wakeupOn(w);
}
public void addTarget(TransformGroup tg, Vector3f position)
{
tgArray[count] = tg;
posArray[count++] = position;
}
}
}
