Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
133
Task/Draw-a-rotating-cube/Tcl/draw-a-rotating-cube.tcl
Normal file
133
Task/Draw-a-rotating-cube/Tcl/draw-a-rotating-cube.tcl
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# matrix operation support:
|
||||
package require math::linearalgebra
|
||||
namespace import ::math::linearalgebra::matmul
|
||||
namespace import ::math::linearalgebra::crossproduct
|
||||
namespace import ::math::linearalgebra::dotproduct
|
||||
namespace import ::math::linearalgebra::sub
|
||||
|
||||
# returns a cube as a list of faces,
|
||||
# where each face is a list of (3space) points
|
||||
proc make_cube {{radius 1}} {
|
||||
set dirs {
|
||||
A { 1 1 1}
|
||||
B { 1 1 -1}
|
||||
C { 1 -1 -1}
|
||||
D { 1 -1 1}
|
||||
E {-1 1 1}
|
||||
F {-1 1 -1}
|
||||
G {-1 -1 -1}
|
||||
H {-1 -1 1}
|
||||
}
|
||||
set faces {
|
||||
{A B C D}
|
||||
{D C G H}
|
||||
{H G F E}
|
||||
{E F B A}
|
||||
{A D H E}
|
||||
{C B F G}
|
||||
}
|
||||
lmap fa $faces {
|
||||
lmap dir $fa {
|
||||
lmap x [dict get $dirs $dir] {
|
||||
expr {1.0 * $x * $radius}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# a matrix constructor
|
||||
proc Matrix {m} {
|
||||
tailcall lmap row $m {
|
||||
lmap e $row {
|
||||
expr 1.0*($e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc identity {} {
|
||||
Matrix {
|
||||
{1 0 0}
|
||||
{0 1 0}
|
||||
{0 0 1}
|
||||
}
|
||||
}
|
||||
|
||||
# some matrices useful for animation:
|
||||
proc rotateZ {theta} {
|
||||
Matrix {
|
||||
{ cos($theta) -sin($theta) 0 }
|
||||
{ sin($theta) cos($theta) 0 }
|
||||
{ 0 0 1 }
|
||||
}
|
||||
}
|
||||
proc rotateY {theta} {
|
||||
Matrix {
|
||||
{ sin($theta) 0 cos($theta) }
|
||||
{ 0 1 0 }
|
||||
{ cos($theta) 0 -sin($theta) }
|
||||
}
|
||||
}
|
||||
proc rotateX {theta} {
|
||||
Matrix {
|
||||
{ 1 0 0 }
|
||||
{ 0 cos($theta) -sin($theta) }
|
||||
{ 0 sin($theta) cos($theta) }
|
||||
}
|
||||
}
|
||||
|
||||
proc camera {flen} {
|
||||
Matrix {
|
||||
{ $flen 0 0 }
|
||||
{ 0 $flen 0 }
|
||||
{ 0 0 0 }
|
||||
}
|
||||
}
|
||||
|
||||
proc render {canvas object} {
|
||||
|
||||
set W [winfo width $canvas]
|
||||
set H [winfo height $canvas]
|
||||
|
||||
set fl 1.0
|
||||
set t [expr {[clock microseconds] / 1000000.0}]
|
||||
|
||||
set transform [identity]
|
||||
set transform [matmul $transform [rotateX [expr {atan(1)}]]]
|
||||
set transform [matmul $transform [rotateZ [expr {atan(1)}]]]
|
||||
|
||||
set transform [matmul $transform [rotateY $t]]
|
||||
set transform [matmul $transform [camera $fl]]
|
||||
|
||||
foreach face $object {
|
||||
# do transformations into screen space:
|
||||
set points [lmap p $face { matmul $p $transform }]
|
||||
# calculate a normal
|
||||
set o [lindex $points 0]
|
||||
set v1 [sub [lindex $points 1] $o]
|
||||
set v2 [sub [lindex $points 2] $o]
|
||||
set normal [crossproduct $v1 $v2]
|
||||
|
||||
set cosi [dotproduct $normal {0 0 -1.0}]
|
||||
if {$cosi <= 0} { ;# rear-facing!
|
||||
continue
|
||||
}
|
||||
|
||||
set points [lmap p $points {
|
||||
lassign $p x y
|
||||
list [expr {$x + $W/2}] [expr {$y + $H/2}]
|
||||
}]
|
||||
set points [concat {*}$points]
|
||||
$canvas create poly $points -outline black -fill red
|
||||
}
|
||||
}
|
||||
|
||||
package require Tk
|
||||
pack [canvas .c] -expand yes -fill both
|
||||
|
||||
proc tick {} {
|
||||
.c delete all
|
||||
render .c $::world
|
||||
after 50 tick
|
||||
}
|
||||
set ::world [make_cube 100]
|
||||
tick
|
||||
Loading…
Add table
Add a link
Reference in a new issue