Skip to content

Instantly share code, notes, and snippets.

@KeyMaster-
Last active October 19, 2016 12:00
Show Gist options
  • Save KeyMaster-/a9aaf9f9ef53b6fab7beaa5b213a4b8a to your computer and use it in GitHub Desktop.
Save KeyMaster-/a9aaf9f9ef53b6fab7beaa5b213a4b8a to your computer and use it in GitHub Desktop.
A quick luxe program to demonstrate manual perspective projection of a rotating pyramid.
import luxe.GameConfig;
import luxe.Input;
import luxe.Vector;
class Main extends luxe.Game {
//--- The actual important stuff --
var verts:Array<Vector>; //Holds the '3D model' vertices, i.e. actual 3D coordinates
//The setup function, this runs once at the start of the game
override function ready() {
verts = [];
//4 bottom verts
//Replace this with the 3 bottom vertices of a triangle to form a tetrahedron (and also adjust what lines are drawn in update)
//Remember that positive z goes down the screen, so larger z is further down
verts.push(new Vector(0.5, 0.5, 0.5)); //right, far
verts.push(new Vector(0.5, 0.5, -0.5)); //right, near
verts.push(new Vector(-0.5, 0.5, -0.5)); //left, near
verts.push(new Vector(-0.5, 0.5, 0.5)); //left, far
//Top vert
verts.push(new Vector(0, -0.5, 0));
} //ready
//Our accumulated running time, for the rotation
var time:Float = 0;
override function update(delta:Float) {
time += delta;
var transformed = []; //Our vertices, transformed to screen space
for(i in 0...verts.length) {
var transformed_vert = verts[i].clone();
var angle = time * Math.PI;
//The 2D rotation matrix around the y-axis (i.e. along the x-z plane)
transformed_vert.x = Math.cos(angle) * verts[i].x - Math.sin(angle) * verts[i].z;
transformed_vert.z = Math.sin(angle) * verts[i].x + Math.cos(angle) * verts[i].z;
transformed_vert.z += 2; //Push the whole model away from our "camera" at 0,0, into the screen
//This is the perspective projection.
//Objects far away have a higher z coordinate, and thus get scaled towards the center of the projection (right now, that's the 0,0 point)
transformed_vert.x /= transformed_vert.z;
transformed_vert.y /= transformed_vert.z;
transformed_vert.multiplyScalar(Luxe.screen.w / 2); //Scale up the resulting projected position to be actually visible on screen. This value is kinda arbitrary
transformed_vert.add(Luxe.screen.mid); //Currently, our model is centered around 0,0. This moves it to the center of the screen.
transformed_vert.z = 0; //This is in screenspace, so there should be no z. (Necessary for my rendering, if you just pass x/y directly z doesn't matter)
transformed.push(transformed_vert);
}
//Draw the 4 base verts
draw_line(transformed[0], transformed[1]);
draw_line(transformed[1], transformed[2]);
draw_line(transformed[2], transformed[3]);
draw_line(transformed[3], transformed[0]);
//Draw the 4 lines to the peak
draw_line(transformed[0], transformed[4]);
draw_line(transformed[1], transformed[4]);
draw_line(transformed[2], transformed[4]);
draw_line(transformed[3], transformed[4]);
} //update
function draw_line(p0:Vector, p1:Vector) {
Luxe.draw.line({
p0:p0,
p1:p1,
immediate:true
});
}
//--- Luxe specific setup. ---
override function config(config:GameConfig) {
config.window.title = 'luxe game';
config.window.width = 960;
config.window.height = 640;
config.window.fullscreen = false;
return config;
} //config
override function onkeyup(event:KeyEvent) {
if(event.keycode == Key.escape) {
Luxe.shutdown();
}
} //onkeyup
} //Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment