I'll see if i can find the sources later.
Edit: This seems to be it. I'm not sure if it's the latest version, but anyway:
import java.awt.*;
import java.awt.event.*;
import com.threed.jpct.*;
import com.threed.jpct.util.*;
import com.threed.jpct.procs.*;
import java.io.*;
import org.lwjgl.input.*;
public class ProjectiveDemo implements IPaintListener {
private KeyMapper keyMapper = null;
private FrameBuffer fb = null;
private World world = null;
private Object3D plane = null;
private Object3D ramp = null;
private Object3D cube = null;
private Object3D sphere = null;
private int fps = 0;
private long time = System.currentTimeMillis();
private Projector[] projectors = new Projector[3];
private MouseMapper mouse = null;
private float xAngle = 0;
private boolean doloop = true;
private boolean bloomy = false;
public ProjectiveDemo() {
Config.maxPolysVisible = 50000;
Config.glColorDepth = 24;
Config.glVertexArrays = true;
Config.glTriangleStrips = true;
Config.glFullscreen = false;
}
public void finishedPainting() {
if (System.currentTimeMillis() - time >= 1000) {
System.out.println(fps);
fps = 0;
time = System.currentTimeMillis();
}
fps++;
}
public void startPainting() {
}
private void initStuff() throws Exception {
fb = new FrameBuffer(800, 600, FrameBuffer.SAMPLINGMODE_NORMAL);
world = new World();
fb.enableRenderer(IRenderer.RENDERER_OPENGL, IRenderer.MODE_OPENGL);
fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);
keyMapper = new KeyMapper();
fb.setPaintListener(this);
plane = Primitives.getPlane(20, 15);
ramp = loadASC("city.asc", 1.5f);
sphere = Primitives.getSphere(30);
sphere.translate( -50, 10, 50);
cube = Primitives.getCube(20);
cube.translate(60, -20, 60);
plane.rotateX((float) Math.PI / 2f);
world.addObject(plane);
world.addObject(ramp);
world.addObject(sphere);
world.addObject(cube);
TextureManager tm = TextureManager.getInstance();
Texture red = loadTexture("textures/red_spot.gif");
Texture green = loadTexture("textures/sailing.png");
Texture blue = loadTexture("textures/blue_spot.gif");
Texture stones = loadTexture("textures/stones.jpg");
Texture t5 = loadTexture("textures/bumps.jpg");
tm.addTexture("red", red);
tm.addTexture("green", green);
tm.addTexture("blue", blue);
tm.addTexture("stones", stones);
tm.addTexture("bumps", t5);
TextureInfo objTexs = new TextureInfo(tm.getTextureID("bumps"));
objTexs.add(tm.getTextureID("red"), TextureInfo.MODE_ADD);
objTexs.add(tm.getTextureID("green"), TextureInfo.MODE_ADD);
objTexs.add(tm.getTextureID("blue"), TextureInfo.MODE_ADD);
TextureInfo planeTexs = new TextureInfo(tm.getTextureID("stones"));
planeTexs.add(tm.getTextureID("red"), TextureInfo.MODE_ADD);
planeTexs.add(tm.getTextureID("green"), TextureInfo.MODE_ADD);
planeTexs.add(tm.getTextureID("blue"), TextureInfo.MODE_ADD);
for (int i = 0; i < projectors.length; i++) {
projectors[i] = new Projector();
}
red.setProjector(projectors[0], false);
green.setProjector(projectors[1], false);
blue.setProjector(projectors[2], false);
plane.setTexture(planeTexs);
ramp.calcTextureWrapSpherical();
ramp.setTexture(objTexs);
cube.calcTextureWrapSpherical();
cube.setTexture(objTexs);
sphere.calcTextureWrapSpherical();
sphere.setTexture(objTexs);
Light light = new Light(world);
light.setPosition(new SimpleVector(0, -40, 0));
light.setIntensity(40, 45, 42);
world.setAmbientLight(20, 20, 20);
world.buildAllObjects();
mouse = new MouseMapper(fb);
mouse.hide();
}
private Texture loadTexture(String tex) throws Exception {
SimpleStream s = new SimpleStream(tex);
Texture t = new Texture(s.getStream());
s.close();
return t;
}
private Object3D loadASC(String asc, float scale) throws Exception {
SimpleStream s = new SimpleStream(asc);
Object3D o = Loader.loadASC(s.getStream(), scale, false);
s.close();
return o;
}
private void checkKeys() {
move();
KeyState ks = null;
while ((ks = keyMapper.poll()) != KeyState.NONE) {
if (ks.getKeyCode() == KeyEvent.VK_ESCAPE) {
doloop = false;
}
if (ks.getKeyCode() == KeyEvent.VK_B && ks.getState()) {
bloomy = !bloomy;
}
if (ks.getKeyCode() == KeyEvent.VK_SPACE && ks.getState()) {
TextureManager.getInstance().getTexture("green").setEnabled(
!TextureManager.getInstance().getTexture("green")
.isEnabled());
}
if (ks.getKeyCode() == KeyEvent.VK_UP) {
world.getCamera().moveCamera(Camera.CAMERA_MOVEIN, 5f);
}
if (ks.getKeyCode() == KeyEvent.VK_DOWN) {
world.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 5f);
}
if (ks.getKeyCode() == KeyEvent.VK_LEFT) {
world.getCamera().moveCamera(Camera.CAMERA_MOVELEFT, 5f);
}
if (ks.getKeyCode() == KeyEvent.VK_RIGHT) {
world.getCamera().moveCamera(Camera.CAMERA_MOVERIGHT, 5f);
}
if (ks.getKeyCode() == KeyEvent.VK_PAGE_UP) {
world.getCamera().moveCamera(Camera.CAMERA_MOVEUP, 5f);
}
if (ks.getKeyCode() == KeyEvent.VK_PAGE_DOWN) {
world.getCamera().moveCamera(Camera.CAMERA_MOVEDOWN, 5f);
}
}
}
private void move() {
Matrix rot = world.getCamera().getBack();
int dx = mouse.getDeltaX();
int dy = mouse.getDeltaY();
float ts = 0.2f;
float tsy = ts;
if (dx != 0) {
ts = Math.abs(dx) / -500f;
}
if (dy != 0) {
tsy = Math.abs(dy) / 500f;
}
if (dx < 0) {
rot.rotateAxis(rot.getYAxis(), ts);
}
if (dx > 0) {
rot.rotateAxis(rot.getYAxis(), -ts);
}
if (dy > 0 && xAngle < Math.PI / 4.2) {
rot.rotateX(tsy);
xAngle += tsy;
}
if (dy < 0 && xAngle > -Math.PI / 4.2) {
rot.rotateX( -tsy);
xAngle -= tsy;
}
}
private void doIt() throws Exception {
Camera cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 150);
cam.moveCamera(Camera.CAMERA_MOVEUP, 100);
cam.lookAt(plane.getTransformedCenter());
BloomGLProcessor bloom = new BloomGLProcessor();
fb.addPostProcessor(bloom);
for (int i = 0; i < projectors.length; i++) {
projectors[i].setPosition(plane.getTransformedCenter());
projectors[i].moveCamera(Camera.CAMERA_MOVEUP, 100);
projectors[i].setFOVLimits(0, 1);
projectors[i].setFOV(0.2f);
projectors[i].rotateCameraX((float) Math.PI / 2f);
}
float a = 0;
while (doloop && !org.lwjgl.opengl.Display.isCloseRequested()) {
checkKeys();
fb.clear(Color.BLACK);
a += 0.01f;
for (int i = 0; i < projectors.length; i++) {
SimpleVector lookAt = new SimpleVector(projectors[i].getPosition());
SimpleVector pivot = new SimpleVector(lookAt);
float offset = 10 + (5 * i);
pivot.y += offset;
lookAt.add(new SimpleVector(0, offset, 10));
lookAt = lookAt.calcSub(pivot);
if ((i & 1) == 1) {
lookAt.rotateY((float) a * (1f + 0.3f * i));
} else {
lookAt.rotateY((float) - a * (1f + 0.3f * i));
}
lookAt.add(pivot);
projectors[i].lookAt(lookAt);
}
world.renderScene(fb);
world.draw(fb);
if (bloomy) {
fb.runPostProcessors();
}
fb.update();
fb.displayGLOnly();
Thread.sleep(10);
}
fb.disableRenderer(IRenderer.RENDERER_OPENGL);
fb.dispose();
System.exit(0);
}
public static void main(String[] args) throws Exception {
Config.glVerbose = true;
ProjectiveDemo cd = new ProjectiveDemo();
cd.initStuff();
cd.doIt();
}
public class SimpleStream {
private InputStream stream;
public SimpleStream(String file) {
stream = this.getClass().getClassLoader().getResourceAsStream(file);
}
public InputStream getStream() {
return stream;
}
public void close() throws IOException {
stream.close();
}
}
class MouseMapper {
private boolean hidden = false;
private int height = 0;
public MouseMapper(FrameBuffer buffer) {
height = buffer.getOutputHeight();
init();
}
public void hide() {
if (!hidden) {
Mouse.setGrabbed(true);
hidden = true;
}
}
public void show() {
if (hidden) {
Mouse.setGrabbed(false);
hidden = false;
}
}
public boolean isVisible() {
return!hidden;
}
public void destroy() {
show();
if (Mouse.isCreated()) {
Mouse.destroy();
}
}
public boolean buttonDown(int button) {
return Mouse.isButtonDown(button);
}
public int getMouseX() {
return Mouse.getX();
}
public int getMouseY() {
return height - Mouse.getY();
}
public int getDeltaX() {
if (Mouse.isGrabbed()) {
return Mouse.getDX();
} else {
return 0;
}
}
public int getDeltaY() {
if (Mouse.isGrabbed()) {
return Mouse.getDY();
} else {
return 0;
}
}
private void init() {
try {
if (!Mouse.isCreated()) {
Mouse.create();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}