
# Set up the test environment, if it does not already exist. Delete any
# canvas3d items that may be left over from a previous test script.
if {[info commands .win] == ""} {
    source [file join [file dirname [info script]] interactive.tcl]
}

i_test polygon-1.1 {
Create a square on the z=0 plane with the center at (0,0,0) and each
edge 1 unit in length. The square should appear blue because of the
-color option.
} {
.win delete all
.win configure -width 600 -height 400

.win create polygon {1 1 0    1 -1 0    -1 -1 0    -1 1 0} -tags P1
.win itemconfigure P1 -color blue

.win configure -cameralocation {0 0 4}
.win configure -cameracenter {0 0 0}
.win configure -cameraup {0 1 0}
}

i_test polygon-1.2 {
Create another square the same size as the first, this one on the z=-1
plane. The center of this square is at (.5, .5, -1).
} {
.win create polygon {1 1 0    1 -1 0    -1 -1 0    -1 1 0} -tags P2
.win transform P2 {move .5 .5 -1}
.win itemconfigure P2 -color green
}

i_test polygon-1.3 {
Set the color of the first polygon to (0, 0, 1, 0.5) and the second to
(0, 1, 0, 0.5). The polygons should remain opaque, as the -enablealpha
switch is not set to true.
} {
.win itemconfigure P1 -color {0 0 1 0.5}
.win itemconfigure P2 -color {0 1 0 0.5}
}

i_test polygon-1.4 {
Turn on -enablealpha. The polygons should become semi-translucent.
} {
.win configure -enablealpha yes
}

i_test polygon-1.5 {
Turn off -enablealpha. The polygons should become opaque again.
} {
.win configure -enablealpha 0
}

i_test polygon-1.6 {
Turn on lighting. The light source, located at (5, 0, 5), emits diffuse
white light only.

Because -horizon is set to false, light angles are calculated based on the
location of the light source. So the front polygon should appear slightly
darker than the one behind it.
} {
.win create light {5 0 5     0 0 0} -tags L1
.win itemconfigure L1 -ambient black -specular black -diffuse white
}

i_test polygon-1.7 {
Set -horizon to true. Now both polygons should be exactly the same shade of
grey.
} {
.win itemconfigure L1 -horizon true
}

i_test polygon-1.8 {
Set the -diffuse option of the polygons to blue and green respectively.
Things should look similar to the they did when we set the colors to blue
and green without any light sources. The rendered colors will be darker,
because of the angle between the light source and the surface normals.
} {
.win itemconfigure P1 -diffuse blue
.win itemconfigure P2 -diffuse green
}

i_test polygon-1.9 {
Set the -diffuse option of the first polygon to (0, 0, 1, 0.5) and the
second to (0, 1, 0, 0.5). Also set -enablealpha to true.

Again, things should look similar to when the translucency was introduced
using the -color option.
} {
.win configure -enablealpha 1
.win itemconfigure P1 -diffuse {0 0 1 0.5}
.win itemconfigure P2 -diffuse {0 1 0 0.5}
}

i_test polygon-1.10 {
Move the back (green) polygon so that it makes a right angle with the
first, like two sides of an adjacent cube.
} {
.win transform P2 {move -0.5 -0.5 1   rotate 90 up  move -1 0 -1}
}

i_test polygon-1.11-1 {
Rotate the model 15 degrees around it's natural center.
} {
.win transform P1||P2 {move 0 0 1   rotate -15 up  move 0 0 -1}
}
i_test polygon-1.11-2 {
Rotate the model 15 degrees around it's natural center.
} {
.win transform P1||P2 {move 0 0 1   rotate -15 up  move 0 0 -1}
}
i_test polygon-1.11-3 {
Rotate the model 15 degrees around it's natural center.
} {
.win transform P1||P2 {move 0 0 1   rotate -15 up  move 0 0 -1}
}
i_test polygon-1.11-4 {
Rotate the model 15 degrees around it's natural center.
} {
.win transform P1||P2 {move 0 0 1   rotate -15 up  move 0 0 -1}
}
i_test polygon-1.11-5 {
Rotate the model 15 degrees around it's natural center.
} {
.win transform P1||P2 {move 0 0 1   rotate -15 up  move 0 0 -1}
}
i_test polygon-1.11-6 {
Rotate the model 15 degrees around it's natural center.
} {
.win transform P1||P2 {move 0 0 1   rotate -15 up  move 0 0 -1}
}

i_test polygon-1.12 {
Approximate a sphere using 512 triangles. It should appear quite jagged.
} {

proc midpoint {v1 v2} {
    return [list \
        [expr ([lindex $v1 0] + [lindex $v2 0]) / 2.0] \
        [expr ([lindex $v1 1] + [lindex $v2 1]) / 2.0] \
        [expr ([lindex $v1 2] + [lindex $v2 2]) / 2.0] \
    ]
}

proc normalize {v} {
    set x [lindex $v 0]
    set y [lindex $v 1]
    set z [lindex $v 2]
    set mag [expr sqrt($x*$x + $y*$y + $z*$z)]
    return [list [expr $x / $mag] [expr $y / $mag] [expr $z / $mag]]
}

set XPLUS  {1 0 0}
set XMINUS {-1 0 0}
set YPLUS  {0 1 0}
set YMINUS {0 -1 0}
set ZPLUS  {0 0 1}
set ZMINUS {0 0 -1}

set triangles [list \
    [concat $XPLUS $YPLUS $ZPLUS] \
    [concat $XPLUS $YPLUS $ZMINUS] \
    [concat $XPLUS $YMINUS $ZPLUS] \
    [concat $XPLUS $YMINUS $ZMINUS] \
    [concat $XMINUS $YPLUS $ZPLUS] \
    [concat $XMINUS $YPLUS $ZMINUS] \
    [concat $XMINUS $YMINUS $ZPLUS] \
    [concat $XMINUS $YMINUS $ZMINUS] \
]

for {set i 0} {$i < 3} {incr i} {
    set newtriangles [list]
    foreach t $triangles {
        set v1 [lrange $t 0 2]
        set v2 [lrange $t 3 5]
        set v3 [lrange $t 6 8]

        set v12 [normalize [midpoint $v1 $v2]]
        set v23 [normalize [midpoint $v2 $v3]]
        set v31 [normalize [midpoint $v3 $v1]]

        lappend newtriangles [concat $v1 $v12 $v31]
        lappend newtriangles [concat $v2 $v12 $v23]
        lappend newtriangles [concat $v3 $v31 $v23]
        lappend newtriangles [concat $v12 $v23 $v31]
    }
    set triangles $newtriangles
}

.win delete all
.win create polygon $triangles -tags SPHERE
.win create light {200 200 200 0 0 0} -tags LIGHT
.win configure -cameralocation {0 0 3} -cameracenter {0 0 0} -cameraup {0 1 0}
}

i_test polygon-1.13 {
Turn on the -smooth option for the sphere approximation. It should look
pretty spherical now.
} {
.win itemconfigure SPHERE -smooth 1
}

i_test polygon-1.14 {
Just for fun, transform the sphere into an egg shape.
} {
.win transform SPHERE {scale 1.5 1 1 rotate -30 0 0 1}
}

i_test polygon-1.15 {
Set the diffuse reflection coefficients of the sphere to {0.8 0.2 0.2 1.0}.
The sphere should appear red.
} {
.win itemconfigure SPHERE -diffuse {0.8 0.2 0.2 1.0}
}

i_test polygon-1.16 {
Set the specular reflection coefficients of the sphere to {1.0 1.0 1.0 1.0}
and the shininess to 100.0. The sphere should appear shiny.
} {
.win itemconfigure SPHERE -specular white -shininess 100.0
}
i_test polygon-1.17 {
Set the -outline options of the sphere to true. The sphere should appear as
a "spiderweb" outline.
} {
.win itemconfigure SPHERE -style outline
}
i_test polygon-1.18 {
Set the -color options of the sphere to purple. The sphere should appear as
a purple "spiderweb" outline.
} {
.win itemconfigure SPHERE -color purple
}

i_test polygon-1.19 {
Clear the widget. Create a few nonsensical polygons to make sure they do
not cause a crash. There should be a single triangular face visible.
} {
.win delete all
.win create polygon {0 0 0 0 0 0 0 0 0}
.win create polygon {0 0 0 1 1 1 2 2 2}
.win create polygon {0 0 0 0 0 0 0 0 0} {0 0 0 1 1 0 1 -1 0}
.win configure -cameralocation {0 0 4}
.win configure -cameracenter {0 0 0}
.win configure -cameraup {0 1 0}
}

