_Tecate and Interactive 3-D_
by Peter Kochevar


Listing One

clone moo WorldViewer
add moo {
   behavior {
      bootstrap {remoteHost shape} {
      # Alert a running session on remoteHost that we want to play
         if {$remoteHost != [gethost]} {
            send $remoteHost:[getself] enter "[gethost] {$shape}"
         } else {
            addstate shape $shape
         }
      }

      enter {host shape} {
      # Register the given host as a player, and let everyone else know
         set hostlist [getstate hosts]

         foreach i $hostlist {
            send [lindex $i 0]:[getself] newPlayer "$host {$shape}"
         }

         send [getsender] startUp "{[lappend hostlist "[gethost] {[getstate shape]}"]}"

         send [getself] newPlayer "$host {$shape}"
      }

      newPlayer {host shape} {
      # Add the given host as a new player
         set hostlist [getstate hosts]
         addstate hosts [lappend hostlist "$host {$shape}"]

         puts "([gethost]) newPlayer: creating object $host"
         clone $host Entity
         add $host "appearance {$shape}"

         set position [get [getstate camera] state position]
         set orientation [get [getstate camera] state orientation]
         send $host:[getself] updateState "[gethost] [getstate room] {$position} {$orientation}"
      }

      startUp {hosts} {

      # Initialize play
         addstate hosts $hosts

         foreach i $hosts {
            set host [lindex $i 0]
            set shape [lindex $i 1]
            puts "([gethost]) startUp: creating object $host"
            clone $host Entity
            add $host "appearance {$shape}"
         }

         send [getself] broadcast {}
      }

      move {} {
      # Move self if flying
         inherited move {}

         send [getself] broadcast {}
      }

      requestUpdates {} {
      # Request an update from every other player
         foreach i [getstate hosts] {
            set host [lindex $i 0]
            send $host:[getself] updateMe
         }
      }

      updateMe {} {
      # Sender wishes to receive update of state
         set position [get [getstate camera] state position]
         set orientation [get [getstate camera] state orientation]

         send [getsender] updateState "[gethost] [getstate room] {$position} {$orientation}"
      }

      broadcast {} {
      # Broadcast current position and orientation to everyone else
         set position [get [getstate camera] state position]
         set orientation [get [getstate camera] state orientation]

         foreach i [getstate hosts] {
            set host [lindex $i 0]
            send $host:[getself] updateState "[gethost] [getstate room] {$position} {$orientation}"
         }
      }

      updateState {host room position orientation} {
      # Update the position and orientation of the player on the given host
         if {$room == [getstate room]} {
            set transform [mconcat [mtranslate $position] "$orientation"]
            add [getstate scene] "subobject {$host {$transform}}"
         } elseif {[lsearch [inquire [getstate scene] subobject] $host] != -1} {
            remove [getstate scene] "subobject {$host}"

         }
      }
   }
}


Listing Two

clone Room Entity
add Room {
   state {
      scene ""
      window ""
      realized 0
   }
   behavior {
      init {scene window size color} {
      # Initialize the room
         addstate scene $scene
         addstate window $window
         addstate size $size

         add [getself] "appearance {
            shape {box [getstate size]}
            diffusecolor {$color}
         }"
      }

      inLimits {x y z} {
      # Check if given point is inside or outside the room
         set width [lindex [getstate size] 0]
         set height [lindex [getstate size] 1]
         set depth [lindex [getstate size] 2]

         set min $width
         if {$height < $min} {set min $height}
         if {$depth < $min} {set min $depth}
         set pad [expr 0.05*$min]

         if {$pad < $x && $x < [expr $width - $pad]} {
            if {$pad < $y && $y < [expr $height - $pad]} {
               if {$pad < $z && $z < [expr $depth - $pad]} {
                  return 1
               }
            }
         }
         return 0
      }

      realize {target position up} {
      # Display the room and its contents
         addstate realized 1
         add [getstate scene] "subobject {[getself] {[midentity]}}"


         set x [expr 0.5*[lindex [getstate size] 0]]
         set y [lindex [getstate size] 1]
         set z [expr 0.5*[lindex [getstate size] 2]]
         
         send [getstate window]-light(2) setView "{$x [expr 0.5*$y] 0.0} {$x $y $z} {0 1 0}"
         send [getstate window]-light(3) setView "{$x [expr 0.5*$y] [expr $z+$z]} {$x 0.0 $z} {0 1 0}"

         set camera [get [getstate window] state camera]
         send $camera setView "{$target} {$position} {$up}"
         add [getstate window] "state {defaultPos {$position} defaultTar {$target}}"

         send [getstate window] setRoom "[getself]"
         send [getself] callback realize
      }

      unrealize {} {
      # Disable the room's display
         addstate realized 0
         remove [getstate scene] "subobject {[getself]}"
         send [getself] callback unrealize
      }



Listing Three

clone Bridge Entity
add Bridge {
   state {
      portals {}
   }
   behavior {
      init {color room0 target0 position0 up0 room1 target1 position1 up1} {
         clone [getself]-0 Portal
         send [getself]-0 init "[getself] $room0 {$target0} {$position0} {$up0} {$color}"
         clone [getself]-1 Portal
         send [getself]-1 init "[getself] $room1 {$target1} {$position1} {$up1} {$color}"

         addstate portals "[getself]-0 [getself]-1"
         add [getself] "subobject {[getself]-0 [getself]-1}"
      }

      crossBridge {portal} {
         set i [lsearch [getstate portals] $portal]
         if {$i == -1} {
            puts "([getself]:oppositePortal) Unrecognized portal '$portal'"
         } else {
            set i [expr 1 - $i]
            set portal [lindex [getstate portals] $i]
            set position [get $portal state position]
            set target [get $portal state normal]
            set position [vadd $position [vscale 1.1 $target]]
            set target [vadd $position $target]
            send [get $portal state room] realize "{$target} {$position} {0 1 0}"

         }
      }
   }
}


Listing Four

clone Portal Entity
add Portal {
   state {
      bridge   ""
      room    ""
      position ""
      normal   ""
      auto     0
   }
   behavior {
      init {bridge room target position up color} {
         addstate bridge $bridge
         addstate room $room
         addstate position $position
         addstate color $color

         add [getself] "appearance {
            shape {cylinder 0.2 1}
            diffusecolor {$color}
         }"
         set zvec [vnormalize [vadd $target [vscale -1.0 $position]]]
         addstate normal $zvec
         set xvec [vnormalize [vcross $zvec $up]]
         set yvec [vcross $xvec $zvec]
         set orientation [mtranspose "$xvec 0 $yvec 0 $zvec 0 0 0 0 1"]
         add $room "subobject {[getself] {[mconcat [mtranslate $position] $orientation]}}"
         
         send $room register "[getself] realize enableProximity"
         send $room register "[getself] unrealize disableProximity"
         set window [get $room state window]
         send $window register "[getself] Pick-Button-1 beginTractor"
      }

      enableProximity {} {
         set room [getstate room]
         set window [get $room state window]
         send $window register "[getself] move proximity"
      }

      disableProximity {} {
         set room [getstate room]
         set window [get $room state window]
         send $window unregister "[getself] move proximity"
      }

      proximity {} {

         set room [getstate room]
         set window [get $room state window]
         set camera [get $window state camera]
         set cameraPos [get $camera state position]
         set pos [getstate position]

         set d [vlength [vadd $pos [vscale -1.0 $cameraPos]]]
         if {$d < 1.0} {
            if {[getstate auto]} {
               addstate auto 0
               send SystemClock unregister "[getself] tractor"
            }
            send [getself] wormhole
         }
      }

      wormhole {} {
         set room [getstate room]
         send $room unrealize

         set bridge [getstate bridge]
         send $bridge crossBridge "[getself]"

         send [get $room state window] broadcast {}
         send [get $room state window] requestUpdates
      }

      beginTractor {} {
         addstate auto 1

         send SystemClock register "[getself] tractor"
      }

      tractor {} {
         set room [getstate room]
         set window [get $room state window]
         set camera [get $window state camera]
         set cameraPos [get $camera state position]
         set pos [getstate position]

         set disp [vadd $pos [vscale -1.0 $cameraPos]]
         set pos [vadd $cameraPos [vscale 0.1 $disp]]

         set zvec [get $camera state zvec]

         send $camera setView "{[vadd $zvec $pos]} {$pos} {0 1 0}"
         send [getself] proximity

         send $window broadcast {}
         send $window callback move
      }
   }
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Listing Five

clone scene Entity
send moo init {scene}

clone a Room
send a init {scene moo {30 10 40} {.3 .4 .6}}

clone b Room
send b init {scene moo {20 10 18} {.4 .6 .5}}

clone c Room
send c init {scene moo {15 8 10} {.6 .6 .4}}

clone abBridge Bridge
send abBridge init {{.6 .3 .5} a {5 5 30} {5 5 35} {0 1 0} b {10 5 10} {10 5 15} {0 1 0}}

clone acBridge Bridge
send acBridge init {{.1 .7 .2} a {20 3 20} {20 3 30} {0 1 0} c {5 4 2} {5 4 7} {0 1 0}}

clone bcBridge Bridge
send bcBridge init {{.1 .3 .7} b {4 6 10} {4 6 15} {0 1 0} c {10 4 2} {10 4 7} {0 1 0}}

send a realize {{9 5 14} {5 5 5} {0 1 0}}
send moo bootstrap "$bootstrapHost {$shape}"


