Simuliertes 3D-Objekt, mit Canvas und JavaScript realisiert
Immer weniger Surfer können Java-Applets anzeigen, dafür wurde der Support der Browser für Canvas immer besser. So als Versuch habe ich mein erstes Applet mit Canvas und JavaScript neu implementiert.
Wenn Sie mit der Maus über das Objekt fahren, dreht es sich um seinen Mittelpunkt. Auf dem Tablet funktioniert das nicht, und deshalb gibt es jetzt eine bessere Version.
Das Objekt wird nicht etwa durch WebGL dargestellt, sondern verwendet den "Painters Algorithm". Dabei werden weiter entfernte Flächen zuerst gezeichnet, und dann alle anderen auf der Z-Achse bis zum Betrachter darüber.
Der Code sieht vereinfacht so aus:
// Ecken definieren
var points = [ { x: 1, y: 1, z: 1 }, { x: 1, y: 1, z:-1 },
{ x:-1, y: 1, z:-1 }, { x:-1, y: 1, z: 1 },
{ x: 1, y:-1, z: 1 }, { x: 1, y:-1, z:-1 },
{ x:-1, y:-1, z:-1 }, { x:-1, y:-1, z: 1 } ] ;
// Flächen definieren
var surfaces = [ { p0: 3, p1: 2, p2: 6, p3: 7, color: "#FF0000" },
{ p0: 0, p1: 6, p2: 5, p3: 3, color: "#0000FF" },
{ p0: 0, p1: 1, p2: 5, p3: 4, color: "#FF0000" },
{ p0: 0, p1: 4, p2: 7, p3: 3, color: "#FFFFFF" } ] ;
// Hilfsvariablen
var canvas, ctx, sinalpha, cosalpha, sinbeta, cosbeta ;
// X-Koordinate der Projektion berechnen
function px( point )
{
return (cosalpha * point.x - sinalpha * point.y) * 100 + 200 ;
}
// Y-Koordinate der Projektion berechnen
function py( point )
{
return (cosbeta * point.z - sinbeta * (cosalpha * point.y + sinalpha * point.x)) * 100 + 200 ;
}
// Eine Fläche zeichnen
function drawsurface( s )
{
ctx.beginPath() ;
ctx.moveTo( px(points[s.p0]), py(points[s.p0]) ) ;
ctx.lineTo( px(points[s.p1]), py(points[s.p1]) ) ;
ctx.lineTo( px(points[s.p2]), py(points[s.p2]) ) ;
ctx.lineTo( px(points[s.p3]), py(points[s.p3]) ) ;
ctx.closePath() ;
ctx.fillStyle = s.color ;
ctx.fill() ;
}
// Körper zeichnen. alpha und beta sind die Drehwinkel
function draw( alpha, beta )
{
// Hilfsvariablen berechnen
sinalpha = Math.sin( alpha ) ;
cosalpha = Math.cos( alpha ) ;
sinbeta = Math.sin( beta ) ;
cosbeta = Math.cos( beta ) ;
// Hintergrund löschen
ctx.clearRect( 0, 0, canvas.width, canvas.height ) ;
// Bodenfläche zuerst zeichnen wenn der Körper nach vorne gekippt ist
if( beta <= 0 )
drawsurface( surfaces[3] ) ;
// Reihenfolge der Flächen wenn der Körper nach rechts gedreht ist
if( alpha >= 0 )
{
drawsurface( surfaces[0] ) ;
drawsurface( surfaces[1] ) ;
drawsurface( surfaces[2] ) ;
}
else
{
drawsurface( surfaces[2] ) ;
drawsurface( surfaces[1] ) ;
drawsurface( surfaces[0] ) ;
}
// Bodenfläche zuletzt zeichnen wenn der Körper nach hinten gekippt ist
if( beta > 0 )
drawsurface( surfaces[3] ) ;
}
Die Mittelfläche war übrigens nicht so geplant, sondern entstand durch einen Zählfehler bei der Applet-Version. Was dabei herauskam, gefiehl mir aber besser als meine ursprüngliche Idee ;-)