Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
93
Task/Draw-a-rotating-cube/Raku/draw-a-rotating-cube.raku
Normal file
93
Task/Draw-a-rotating-cube/Raku/draw-a-rotating-cube.raku
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use Terminal::Caca;
|
||||
given my $canvas = Terminal::Caca.new {
|
||||
.title('Rosetta Code - Rotating cube - Press any key to exit');
|
||||
|
||||
sub scale-and-translate($x, $y, $z) {
|
||||
$x * 5 / ( 5 + $z ) * 15 + 40,
|
||||
$y * 5 / ( 5 + $z ) * 7 + 15,
|
||||
$z;
|
||||
}
|
||||
|
||||
sub rotate3d-x( $x, $y, $z, $angle ) {
|
||||
my ($cosθ, $sinθ) = cis( $angle * π / 180.0 ).reals;
|
||||
$x,
|
||||
$y * $cosθ - $z * $sinθ,
|
||||
$y * $sinθ + $z * $cosθ;
|
||||
}
|
||||
|
||||
sub rotate3d-y( $x, $y, $z, $angle ) {
|
||||
my ($cosθ, $sinθ) = cis( $angle * π / 180.0 ).reals;
|
||||
$x * $cosθ - $z * $sinθ,
|
||||
$y,
|
||||
$x * $sinθ + $z * $cosθ;
|
||||
}
|
||||
|
||||
sub rotate3d-z( $x, $y, $z, $angle ) {
|
||||
my ($cosθ, $sinθ) = cis( $angle * π / 180.0 ).reals;
|
||||
$x * $cosθ - $y * $sinθ,
|
||||
$x * $cosθ + $y * $sinθ,
|
||||
$z;
|
||||
}
|
||||
|
||||
# Unit cube from polygon mesh, aligned to axes
|
||||
my @mesh =
|
||||
[ [1, 1, -1], [-1, -1, -1], [-1, 1, -1] ], # far face
|
||||
[ [1, 1, -1], [-1, -1, -1], [ 1, -1, -1] ],
|
||||
[ [1, 1, 1], [-1, -1, 1], [-1, 1, 1] ], # near face
|
||||
[ [1, 1, 1], [-1, -1, 1], [ 1, -1, 1] ];
|
||||
@mesh.push: [$_».rotate( 1)».Array] for @mesh[^4]; # positive and
|
||||
@mesh.push: [$_».rotate(-1)».Array] for @mesh[^4]; # negative rotations
|
||||
|
||||
# Rotate to correct orientation for task
|
||||
for ^@mesh X ^@mesh[0] -> ($i, $j) {
|
||||
@(@mesh[$i;$j]) = rotate3d-x |@mesh[$i;$j], 45;
|
||||
@(@mesh[$i;$j]) = rotate3d-z |@mesh[$i;$j], 40;
|
||||
}
|
||||
|
||||
my @colors = red, blue, green, cyan, magenta, yellow;
|
||||
|
||||
loop {
|
||||
for ^359 -> $angle {
|
||||
.color( white, white );
|
||||
.clear;
|
||||
|
||||
# Flatten 3D into 2D and rotate for all faces
|
||||
my @faces-z;
|
||||
my $c-index = 0;
|
||||
for @mesh -> @triangle {
|
||||
my @points;
|
||||
my $sum-z = 0;
|
||||
for @triangle -> @node {
|
||||
my ($px, $py, $z) = scale-and-translate |rotate3d-y |@node, $angle;
|
||||
@points.append: $px.Int, $py.Int;
|
||||
$sum-z += $z;
|
||||
}
|
||||
|
||||
@faces-z.push: %(
|
||||
color => @colors[$c-index++ div 2],
|
||||
points => @points,
|
||||
avg-z => $sum-z / +@points;
|
||||
);
|
||||
}
|
||||
|
||||
# Draw all faces
|
||||
# Sort by z to draw farthest first
|
||||
for @faces-z.sort( -*.<avg-z> ) -> %face {
|
||||
# Draw filled triangle
|
||||
.color( %face<color>, %face<color> );
|
||||
.fill-triangle( |%face<points> );
|
||||
# And frame
|
||||
.color( black, black );
|
||||
.thin-triangle( |%face<points> );
|
||||
}
|
||||
|
||||
.refresh;
|
||||
exit if .wait-for-event(key-press);
|
||||
}
|
||||
}
|
||||
|
||||
# Cleanup on scope exit
|
||||
LEAVE {
|
||||
.cleanup;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue