Hello,
Recently I have found strange behavior.
I have a class that allows me to create simple Rays. It uses VertexController to change ray dimensions which gives me possibility to reuse objects. I use it for laser or ship fumes effects.
Now I have other objects displayed as billboards - planets, stars etc.
I have noticed recently, that scaled billboard is displayed sometimes over the ray despite fact that ray is much closer to camera.
There are screensots of simple app where ray is from [-20,0,-3] to [0,-20,-3] and box of size (2,2) is located at [-150,-150,-40]:

The billboard does not have scale applied.

A scale is applied ( box.setScale(6); ).
Here is an example application:
//Test.java
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.World;
public class Test extends JFrame implements Runnable
{
private static final long serialVersionUID = 811111147457394977L;
private World world;
private FrameBuffer buffer;
private Canvas myCanvas;
private boolean alive = true;
private boolean initialized = false;
private Ray ray;
private Object3D box;
public static void main(String[] args)
{
new Test();
}
public Test()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
init();
pack();
setVisible(true);
}
public void init()
{
world = new World();
ray = new Ray();
ray.initialize(new SimpleVector(-20, 0, -3), new SimpleVector(0, -20,
-3), 0.5, Color.YELLOW, Object3D.TRANSPARENCY_MODE_DEFAULT);
box = Primitives.getBox(2, 2);
box.setBillboarding(true);
box.setAdditionalColor(Color.WHITE);
box.setLighting(Object3D.LIGHTING_NO_LIGHTS);
box.setTransparency(0);
box.setTransparencyMode(Object3D.TRANSPARENCY_MODE_ADD);
box.setTransparency(255);
box.setScale(6);
box.build();
box.compile();
box.translate(-150, -150, -40);
world.addObject(ray);
world.addObject(box);
Camera camera = world.getCamera();
camera.setPosition(0, 0, 0);
camera.lookAt(box.getTransformedCenter());
world.setAmbientLight(100, 100, 100);
buffer = new FrameBuffer(640, 480, FrameBuffer.SAMPLINGMODE_GL_AA_4X);
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
myCanvas = buffer.enableGLCanvasRenderer();
add(myCanvas, BorderLayout.CENTER);
initialized = true;
new Thread(this).start();
}
@Override
public void run()
{
while (alive)
{
this.repaint();
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
alive = false;
}
@Override
public void paint(Graphics g)
{
if (!initialized)
return;
buffer.clear();
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
myCanvas.repaint();
}
}
//Ray.java
public class Ray extends Object3D
{
private static final long serialVersionUID = -1684665440334869826L;
private static final SimpleVector YVEC = new SimpleVector(0, 1, 0);
private static final SimpleVector ZVEC = new SimpleVector(0, 0, 1);
private static int HF1 = 0;
private static int HF2 = 1;
private static int HT1 = 2;
private static int HT2 = 3;
private static int VF1 = 4;
private static int VF2 = 5;
private static int VT1 = 6;
private static int VT2 = 7;
private static SimpleVector[] VERTEXES = new SimpleVector[] {
new SimpleVector(-1.5, -1.5, -1), new SimpleVector(-0.5, -0.5, -1),
new SimpleVector(1.5, 1.5, -1), new SimpleVector(0.5, 0.5, -1),
new SimpleVector(-1, -1, -1.5), new SimpleVector(-0.5, -0.5, -0.5),
new SimpleVector(1.5, 1.5, 1.5), new SimpleVector(0.5, 0.5, 0.5) };
private SimpleVector[] vertexes = new SimpleVector[VERTEXES.length];
public Ray()
{
super(4);
for (int i = 0; i < VERTEXES.length; ++i)
vertexes[i] = new SimpleVector(VERTEXES[i]);
addTriangle(VERTEXES[HF1], 1, 1, VERTEXES[HT1], 1, 0, VERTEXES[HT2], 0,
0);
addTriangle(VERTEXES[HT2], 0, 0, VERTEXES[HF2], 0, 1, VERTEXES[HF1], 1,
1);
addTriangle(VERTEXES[VF1], 1, 1, VERTEXES[VT1], 1, 0, VERTEXES[VT2], 0,
0);
addTriangle(VERTEXES[VT2], 0, 0, VERTEXES[VF2], 0, 1, VERTEXES[VF1], 1,
1);
setCulling(Object3D.CULLING_DISABLED);
setLighting(Object3D.LIGHTING_NO_LIGHTS);
setTransparency(0);
build();
getMesh().setVertexController(new RayVertexController(),
IVertexController.PRESERVE_SOURCE_MESH);
}
public void initialize(SimpleVector from, SimpleVector to, double scale, Color color,
int transparencyMode)
{
setVertexes(from, to, (float) scale);
setAdditionalColor(color);
setTransparencyMode(transparencyMode);
getMesh().applyVertexController();
setCenter(SimpleVector.ORIGIN);
setOrigin(SimpleVector.ORIGIN);
getRotationMatrix().setIdentity();
setRotationPivot(SimpleVector.ORIGIN);
}
private void setVertexes(SimpleVector from, SimpleVector to, float scale)
{
scale /= 2;
SimpleVector diff = to.calcSub(from);
SimpleVector ya = SimpleVectorUtil.mul(
diff.calcCross(YVEC).normalize(), scale);
SimpleVector za = SimpleVectorUtil.mul(
diff.calcCross(ZVEC).normalize(), scale);
vertexes[HF1].set(from.x - ya.x, from.y - ya.y, from.z - ya.z);
vertexes[HF2].set(from.x + ya.x, from.y + ya.y, from.z + ya.z);
vertexes[HT1].set(to.x - ya.x, to.y - ya.y, to.z - ya.z);
vertexes[HT2].set(to.x + ya.x, to.y + ya.y, to.z + ya.z);
vertexes[VF1].set(from.x - za.x, from.y - za.y, from.z - za.z);
vertexes[VF2].set(from.x + za.x, from.y + za.y, from.z + za.z);
vertexes[VT1].set(to.x - za.x, to.y - za.y, to.z - za.z);
vertexes[VT2].set(to.x + za.x, to.y + za.y, to.z + za.z);
}
public SimpleVector convertVertex(SimpleVector vertex)
{
for (int i = 0; i < VERTEXES.length; ++i)
if (VERTEXES[i].equals(vertex))
return vertexes[i];
return vertex;
}
class RayVertexController extends GenericVertexController
{
private static final long serialVersionUID = -3596694596175935772L;
@Override
public void apply()
{
SimpleVector[] src = getSourceMesh();
SimpleVector[] dst = getDestinationMesh();
for (int i = 0; i < src.length; ++i)
{
dst[i].set(convertVertex(src[i]));
}
}
}
}
//SimpleVectorUtil.java
public class SimpleVectorUtil
{
public static SimpleVector mul(SimpleVector vec, float mul)
{
vec.x *= mul;
vec.y *= mul;
vec.z *= mul;
return vec;
}
public static SimpleVector calcMul(SimpleVector vec, float mul)
{
return mul(new SimpleVector(vec), mul);
}
}
Is it a bug, or perhaps I have to set some additional parameters to have that working correctly?
Thanks,
Wojtek