no display name and no $DISPLAY environment variable
while executing
"load /enadisk/commun/linux/local/ActiveTcl-8.6.11/lib/libtk8.6.so Tk"
("package ifneeded Tk 8.6.11" script)
invoked from within
"package require Tk"
(in namespace eval "::request" script line 9)
invoked from within
"namespace eval ::request $script"
("::try" body line 12)
OUTPUT BUFFER:
# cgTeapot.tcl
#
# Original files from: http://developer.nvidia.com/Cg
# This is the example called interfaces_ogl as included in the Cg Toolkit.
#
# Modified for Tcl3D by Paul Obermeier 2005/11/07
# See www.tcl3d.org for the Tcl3D extension.
package require Tk
package require tcl3d 0.5.0
if { [info procs tcl3dHaveCg] ne "" } {
if { ![tcl3dHaveCg] } {
tk_messageBox -icon error -type ok -title "Error" \
-message "You do not have Cg installed."
exit
}
}
set M_PI 3.141592
set TWOPI [expr 2.0*$M_PI]
set GROUNDWIDTH 20
set pWidth2 [expr $::GROUNDWIDTH / 2.0]
set nWidth2 [expr -1.0 * $pWidth2]
set g_quadVerts [tcl3dVectorFromArgs GLfloat \
$nWidth2 $nWidth2 0.0 \
$pWidth2 $nWidth2 0.0 \
$pWidth2 $pWidth2 0.0 \
$nWidth2 $pWidth2 0.0]
set g_quadNorms [tcl3dVectorFromArgs GLfloat 0 0 1 0 0 1 0 0 1 0 0 1]
set g_init 0
# Determine the directory of this script.
set g_scriptDir [file dirname [info script]]
# Show errors occuring in the Togl callbacks.
proc bgerror { msg } {
tk_messageBox -icon error -type ok -message "Error: $msg\n\n$::errorInfo"
ExitProg
}
# Print info message into widget a the bottom of the window.
proc PrintInfo { msg } {
if { [winfo exists .fr.info] } {
.fr.info configure -text $msg
}
}
proc DEG2RAD {x} {
return [expr $x*$::M_PI/180.0]
}
array set g_Properties {
teapot,ambient {.05 .05 .05}
teapot,diffuse {.8 .4 .1}
teapot,specular {.4 .2 .2}
teapot,exp 10.0
bright,ambient {.05 .05 .05}
bright,diffuse {1.9 1.9 1.9}
bright,specular {.1 .1 .1}
bright,exp 20.0
dark,ambient {.05 .05 .05}
dark,diffuse {.1 .1 .1}
dark,specular {.4 .4 .4}
dark,exp 40.0
}
array set g_Objs {
"0,r" 9
"0,target" {0 0 0}
"0,color" { 0.2 0.2 0.25 }
"0,enabled" 0
"0,name" "PointLight"
"0,rotateMode" 0
"1,r" 16
"1,target" {0 0 0}
"1,color" { 0.6 0.1 0.1 }
"1,enabled" 0
"1,name" "SpotLight"
"1,rotateMode" 0
"2,r" 45.
"2,target" {0 0 0}
"2,name" "Camera"
"2,rotateMode" 0
}
set g_Objs(0,theta) [DEG2RAD -20]
set g_Objs(0,phi) [DEG2RAD 60]
set g_Objs(1,theta) [DEG2RAD 40]
set g_Objs(1,phi) [DEG2RAD 40]
set g_Objs(2,theta) [DEG2RAD 30.]
set g_Objs(2,phi) [DEG2RAD 60.]
set Eye 2
set numLights 2
set numSelections [expr $numLights + 1]
set motionSelections { 2 0 1 }
set currentSelection 0
set g_WinWidth 300
set g_WinHeight 300
set numRotating 0
set drawLightsMode 1
set literalMode 1
set printMode 1
set moveMode 0
set zoomMode 0
set retargetMode 0
set vertexProfile $::CG_PROFILE_UNKNOWN
set fragmentProfile $::CG_PROFILE_UNKNOWN
proc ParseArgs { argc argv } {
set i 0
while { $i < $argc } {
if { 0 == [strcmp [lindex $argv $i] "-nv3x"] } {
set ::vertexProfile $::CG_PROFILE_VP30
set ::fragmentProfile $::CG_PROFILE_FP30
} elseif { 0 == [strcmp [lindex $argv $i] "-arb"] } {
set ::vertexProfile $::CG_PROFILE_ARBVP1
set ::fragmentProfile $::CG_PROFILE_ARBFP1
} elseif { 0 == [strcmp [lindex $argv $i] "-nv4x"] } {
set ::vertexProfile $::CG_PROFILE_VP30
set ::fragmentProfile $::CG_PROFILE_FP40
} elseif { 0 == [strcmp [lindex $argv $i] "-v"] } {
set ::printMode 1
} elseif { 0 == [strcmp [lindex $argv $i] "-l"] } {
set ::literalMode [expr ! $::literalMode]
} else {
return $i
}
incr i
}
return $i
}
# Main program; do basic GLUT and Cg setup, but leave most of the work
# to the display() function.
proc CreateWindow {} {
set compilerArgs [ParseArgs $::argc $::argv]
frame .fr
pack .fr -expand 1 -fill both
togl .fr.toglwin -width $::g_WinWidth -height $::g_WinHeight \
-rgba true -double true -depth true \
-createproc CreateCallback \
-reshapeproc ReshapeCallback \
-displayproc DisplayCallback
label .fr.info
grid .fr.toglwin -row 0 -column 0 -sticky news
grid .fr.info -row 1 -column 0 -sticky news
grid rowconfigure .fr 0 -weight 1
grid columnconfigure .fr 0 -weight 1
wm title . "Tcl3D demo: Teapot with Cg"
bind . "ExitProg"
bind . "RotateMode .fr.toglwin"
bind . "ToggleLight 0 ; .fr.toglwin postredisplay"
bind . "ToggleLight 1 ; .fr.toglwin postredisplay"
bind . "ToggleLightsMode .fr.toglwin"
bind . "Recenter .fr.toglwin"
bind . "CycleSelection .fr.toglwin"
bind .fr.toglwin { SetModes 0 0 1 ; MoveStart %W %x %y }
bind .fr.toglwin { SetModes 0 1 0 ; MoveStart %W %x %y }
bind .fr.toglwin { SetModes 1 0 0 ; MoveStart %W %x %y }
bind .fr.toglwin { SetModes 0 0 0 ; MoveEnd %W %x %y }
bind .fr.toglwin { MoveCont %W %x %y }
}
proc Cleanup {} {
$::g_quadVerts delete
$::g_quadNorms delete
if { [info exists ::g_quadric] } {
gluDeleteQuadric $::g_quadric
}
cgDestroyContext $::g_context
foreach var [info globals g_*] {
uplevel #0 unset $var
}
}
proc ExitProg {} {
exit
}
proc SetModes { move retarget zoom } {
set ::moveMode $move
set ::retargetMode $retarget
set ::zoomMode $zoom
}
proc MoveStart { W x y } {
set ::mouseX $x
set ::mouseY $y
}
proc MoveCont { W x y } {
Motion $W $x $y
}
proc MoveEnd { W x y } {
$W postredisplay
}
proc ToggleLight { which } {
set ::g_Objs($which,enabled) [expr ! $::g_Objs($which,enabled)]
set param [cgGetNamedStructParameter $::g_Objs($which,handle) "enabled"]
cgSetParameter1f $param $::g_Objs($which,enabled)
}
proc IdleFunc { toglwin } {
if { $::numRotating > 0 } {
$toglwin postredisplay
tcl3dAfterIdle "IdleFunc $toglwin"
}
}
proc BindPrograms { vert frag } {
cgGLEnableProfile $::vertexProfile
cgGLEnableProfile $::fragmentProfile
cgGLBindProgram $vert
cgGLBindProgram $frag
set param [cgGetNamedProgramParameter $vert CG_PROGRAM "ModelView"]
cgGLSetStateMatrixParameter $param \
CG_GL_MODELVIEW_MATRIX \
CG_GL_MATRIX_IDENTITY
set param [cgGetNamedProgramParameter $vert CG_PROGRAM "ModelViewIT"]
cgGLSetStateMatrixParameter $param \
CG_GL_MODELVIEW_MATRIX \
CG_GL_MATRIX_INVERSE_TRANSPOSE
set param [cgGetNamedProgramParameter $vert CG_PROGRAM "ModelViewProj"]
cgGLSetStateMatrixParameter $param \
CG_GL_MODELVIEW_PROJECTION_MATRIX \
CG_GL_MATRIX_IDENTITY
}
proc PolarToCartesian { r phi theta } {
return [list \
[expr $r*sin($phi)*sin($theta)] \
[expr $r*sin($phi)*cos($theta)] \
[expr $r*cos($phi)]]
}
proc TransformPointCart { p m } {
set ov0 [expr [$m get 0] * [lindex $p 0] + \
[$m get 4] * [lindex $p 1] + \
[$m get 8] * [lindex $p 2] + \
[$m get 12]]
set ov1 [expr [$m get 1] * [lindex $p 0] + \
[$m get 5] * [lindex $p 1] + \
[$m get 9] * [lindex $p 2] + \
[$m get 13]]
set ov2 [expr [$m get 2] * [lindex $p 0] + \
[$m get 6] * [lindex $p 1] + \
[$m get 10] * [lindex $p 2] + \
[$m get 14]]
set w [expr [$m get 3] * [lindex $p 0] + \
[$m get 7] * [lindex $p 1] + \
[$m get 11] * [lindex $p 2] + \
[$m get 15]]
if { $w != 1.0 } {
set ov0 [expr $ov0 / $w]
set ov1 [expr $ov1 / $w]
set ov2 [expr $ov2 / $w]
}
return [list $ov0 $ov1 $ov2]
}
proc TransformPointPolar {r phi theta m } {
set c [PolarToCartesian $r $phi $theta]
return [TransformPointCart $c $m]
}
proc glPuts { str } {
glListBase $::FontBase
set len [string length $str]
set sa [tcl3dVectorFromString GLubyte $str]
glCallLists $len GL_UNSIGNED_BYTE $sa
$sa delete
}
proc DrawLights {} {
if { ! [info exists ::g_quadric] } {
set ::g_quadric [gluNewQuadric]
gluQuadricOrientation $::g_quadric GLU_OUTSIDE
}
for { set i 0 } { $i < $::numLights } { incr i } {
glPushMatrix
set vec [PolarToCartesian $::g_Objs($i,r) $::g_Objs($i,phi) $::g_Objs($i,theta)]
glTranslatef [lindex $vec 0] [lindex $vec 1] [lindex $vec 2]
BindPrograms $::vertexProg $::lightProg
set param [cgGetNamedProgramParameter $::lightProg CG_PROGRAM "color"]
set vec $::g_Objs($i,color)
if { [lindex $::motionSelections $::currentSelection] != $i } {
lset vec 0 [expr [lindex $vec 0] * 0.2]
lset vec 1 [expr [lindex $vec 1] * 0.2]
lset vec 2 [expr [lindex $vec 2] * 0.2]
}
cgSetParameter3fv $param $vec
gluSphere $::g_quadric .2 5 5
glPopMatrix
}
}
proc DrawGround {} {
glPushMatrix
BindPrograms $::vertexProg $::groundProg
glVertexPointer 3 GL_FLOAT 0 $::g_quadVerts
glNormalPointer GL_FLOAT 0 $::g_quadNorms
glDrawArrays GL_QUADS 0 4
glPopMatrix
}
proc DrawText {} {
cgGLDisableProfile $::vertexProfile
cgGLDisableProfile $::fragmentProfile
glMatrixMode GL_PROJECTION
glLoadIdentity
glOrtho -1 1 -1 1 -1 1
glMatrixMode GL_MODELVIEW
glLoadIdentity
glDisable [expr $::GL_LIGHTING | $::GL_DEPTH_TEST]
glColor3f 1 1 1
glPushMatrix
glRasterPos2f -.98 -.98
set ind [lindex $::motionSelections $::currentSelection]
set buf [format "%s %s" $::g_Objs($ind,name) \
[expr { $::moveMode ? "(move)" : \
($::zoomMode ? "(zoom)" : \
($::retargetMode ? "(retarget)" : " ")) } ]]
glPuts $buf
glEnable [expr $::GL_LIGHTING | $::GL_DEPTH_TEST]
glPopMatrix
}
proc InitCgShader {} {
tcl3dCgResetError
# Basic Cg setup; register a callback function for any errors
# and create an initial context
set ::g_context [cgCreateContext]
set retVal [tcl3dCgGetError $::g_context]
if { $retVal ne "" } {
error "cgCreateContext: $retVal"
}
# initialize programs, etc.
InitPrograms
}
proc CreateCallback { toglwin } {
set ::FontBase [$toglwin loadbitmapfont "fixed"]
InitCgShader
}
proc ReshapeCallback { toglwin { w -1 } { h -1 } } {
set w [$toglwin width]
set h [$toglwin height]
glViewport 0 0 $w $h
set ::g_WinWidth $w
set ::g_WinHeight $h
}
proc DisplayCallback { toglwin } {
if { $::g_init == 0 } {
glEnable GL_DEPTH_TEST
glDisable GL_CULL_FACE
glEnableClientState GL_VERTEX_ARRAY
glEnableClientState GL_NORMAL_ARRAY
glClearColor .1 .1 .1 1.
set ::g_init 1
}
for { set i 0 } { $i < $::numSelections } { incr i } {
set ind [lindex $::motionSelections $i]
if { $::g_Objs($ind,rotateMode) } {
set ::g_Objs($ind,theta) [expr $::g_Objs($ind,theta) + 0.02]
}
}
glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
# Viewport command is not really needed, but has been inserted for
# Mac OSX. Presentation framework (Tk) does not send a reshape event,
# when switching from one demo to another.
glViewport 0 0 [$toglwin width] [$toglwin height]
glMatrixMode GL_PROJECTION
glPushMatrix
glLoadIdentity
gluPerspective 25 [expr double($::g_WinWidth)/double($::g_WinHeight)] .1 1000
glMatrixMode GL_MODELVIEW
glLoadIdentity
glPushMatrix
glLoadIdentity
set eyeCoords [PolarToCartesian $::g_Objs($::Eye,r) \
$::g_Objs($::Eye,phi) \
$::g_Objs($::Eye,theta)]
gluLookAt [lindex $eyeCoords 0] \
[lindex $eyeCoords 1] \
[lindex $eyeCoords 2] \
[lindex $::g_Objs($::Eye,target) 0] \
[lindex $::g_Objs($::Eye,target) 1] \
[lindex $::g_Objs($::Eye,target) 2] \
[expr -cos($::g_Objs($::Eye,phi))*sin($::g_Objs($::Eye,theta))] \
[expr -cos($::g_Objs($::Eye,phi))*cos($::g_Objs($::Eye,theta))] \
[expr sin($::g_Objs($::Eye,phi))]
# Compute eye space light positions
UpdateLights
if { $::drawLightsMode } {
DrawLights
}
# Draw teapot
glPushMatrix
BindPrograms $::vertexProg $::teapotProg
glutSolidTeapot 2.0
glPopMatrix
# Draw ground plane
DrawGround
glPopMatrix
glMatrixMode GL_PROJECTION
glPopMatrix
DrawText
glEnd
$toglwin swapbuffers
}
proc InitPrograms {} {
# Do one-time setup only once; setup Cg programs and textures
# and set up OpenGL state.
if { $::vertexProfile == $::CG_PROFILE_UNKNOWN || \
$::fragmentProfile == $::CG_PROFILE_UNKNOWN } {
set ::vertexProfile [cgGLGetLatestProfile CG_GL_VERTEX]
set ::fragmentProfile [cgGLGetLatestProfile CG_GL_FRAGMENT]
}
if { [tcl3dCgFindProfile $::vertexProfile] eq "" } {
error "Could not find Cg vertex profile $::vertexProfile"
}
if { [tcl3dCgFindProfile $::fragmentProfile] eq "" } {
error "Could not find Cg fragment profile $::fragmentProfile"
}
cgGLSetOptimalOptions $::vertexProfile
cgGLSetOptimalOptions $::fragmentProfile
LoadCgPrograms
if { $::printMode } {
puts [format "Warnings:\n%s\n" [cgGetLastListing $::g_context]]
}
}
proc CreateLightSource { prog lind } {
# Get handle to user-defined type
set lightType [cgGetNamedUserType $prog $::g_Objs($lind,name)]
# Create parameter of that type
set light [cgCreateParameter $::g_context $lightType]
if { $light == 0 } {
return 0
}
# Stash handles to position, target parameters
set ::g_Objs($lind,posHandle) [cgGetNamedStructParameter $light "Plight"]
set ::g_Objs($lind,targetHandle) [cgGetNamedStructParameter $light "target"]
set ::g_Objs($lind,handle) $light
# Set light color
set param [cgGetNamedStructParameter $light "Clight"]
if { $param == 0 } {
return 0
}
cgSetParameter3fv $param $::g_Objs($lind,color)
if { $::literalMode } {
cgSetParameterVariability $param CG_LITERAL
}
return 1
}
proc UpdateLights {} {
set modelViewMat [tcl3dVector GLfloat 16]
glGetFloatv GL_MODELVIEW_MATRIX $modelViewMat
# Compute eye-space coords of each light source's
# position and (if applicable) target
for { set i 0 } { $i < $::numLights } { incr i } {
set lightPosEye [TransformPointPolar $::g_Objs($i,r) $::g_Objs($i,phi) \
$::g_Objs($i,theta) $modelViewMat]
cgSetParameter3fv $::g_Objs($i,posHandle) $lightPosEye
if { $::g_Objs($i,targetHandle) != "NULL" } {
set lightTargetEye [TransformPointCart $::g_Objs($i,target) $modelViewMat]
cgSetParameter3fv $::g_Objs($i,targetHandle) $lightTargetEye
}
}
$modelViewMat delete
}
proc SetBlinnProperties { b p } {
cgSetParameter3fv [cgGetNamedStructParameter $b "ambient"] $::g_Properties($p,ambient)
cgSetParameter3fv [cgGetNamedStructParameter $b "diffuse"] $::g_Properties($p,diffuse)
cgSetParameter3fv [cgGetNamedStructParameter $b "specular"] $::g_Properties($p,specular)
cgSetParameter1f [cgGetNamedStructParameter $b "sexp"] $::g_Properties($p,exp)
if { $::literalMode } {
cgSetParameterVariability $b CG_LITERAL
}
}
proc GetFileName { fileName } {
return [tcl3dGetExtFile [file join $::g_scriptDir $fileName]]
}
proc LoadCgPrograms {} {
# Create & wire up up a handful of programs.
if { ! [cgIsContext $::g_context] } {
error "No context specified"
}
# The Cg source files used later in cgCreateProgramFromFile include other Cg
# files. If running from inside a Starpack, we have to copy these files to
# the file system. That's what the next lines are for. They do nothing, if
# this script is directly run from tclsh or wish.
tcl3dGetExtFile [file join $::g_scriptDir "blend.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "blinn.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "checker.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "common.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "light.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "material.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "pointlight.cg"]
tcl3dGetExtFile [file join $::g_scriptDir "spotlight.cg"]
# First, create programs that don't make use
# of shared instances, and thus can be compiled
# immediately.
# Create vertex program. This is the vertex program
# used with all of the fragment shaders.
set ::vertexProg [cgCreateProgramFromFile $::g_context CG_SOURCE \
[GetFileName "vertex.cg"] \
$::vertexProfile "main" "NULL"]
tcl3dCgPrintProgramInfo $::vertexProg "vertex.cg"
cgGLLoadProgram $::vertexProg
# Create constant shader, used for light source visualization
set ::lightProg [cgCreateProgramFromFile $::g_context CG_SOURCE \
[GetFileName "constant.cg"] \
$::fragmentProfile "main" "NULL"]
tcl3dCgPrintProgramInfo $::lightProg "constant.cg"
cgGLLoadProgram $::lightProg
# Next, create shared instances and the programs that use them.
# Turn on manual compilation so the runtime won't try to compile
# incomplete programs.
cgSetAutoCompile $::g_context CG_COMPILE_MANUAL
# Create teapot fragment program
set ::teapotProg [cgCreateProgramFromFile $::g_context CG_SOURCE \
[GetFileName "materialmain.cg"] \
$::fragmentProfile "main" "NULL"]
# Create metal material for teapot.
set metal [cgCreateParameter $::g_context \
[cgGetNamedUserType $::teapotProg "Blinn"]]
SetBlinnProperties $metal "teapot"
# Connect material parameter of teapot program to metal material
set param [cgGetNamedProgramParameter $::teapotProg CG_PROGRAM "material"]
cgConnectParameter $metal $param
# Create ground fragment program
set ::groundProg [cgCreateProgramFromFile $::g_context CG_SOURCE \
[GetFileName "materialmain.cg"] \
$::fragmentProfile "main" "NULL"]
# Create checker material
set checker [cgCreateParameter $::g_context \
[cgGetNamedUserType $::teapotProg "CheckerBlinn"]]
set param [cgGetNamedStructParameter $checker "csize"]
cgSetParameter1f $param 1.0
if { $::literalMode } {
cgSetParameterVariability $param CG_LITERAL
}
set param [cgGetNamedStructParameter $checker "mats"]
SetBlinnProperties [cgGetArrayParameter $param 0] "bright"
SetBlinnProperties [cgGetArrayParameter $param 1] "dark"
# Associate checker material with material parameter of ground program
cgConnectParameter $checker [cgGetNamedProgramParameter \
$::groundProg CG_PROGRAM "material"]
# Next, create shared light sources
# Get type handles from any program that includes the
# appropriate type definition.
set lArray [cgCreateParameterArray $::g_context \
[cgGetNamedUserType $::teapotProg "Light"] $::numLights]
for { set i 0 } { $i < $::numLights } { incr i } {
# We pass teapotProg here, but could pass any program (compiled or uncompiled) whose
# source defines the types.
if { [CreateLightSource $::teapotProg $i] == 0 } {
error "Cannot create light source"
}
cgConnectParameter $::g_Objs($i,handle) [cgGetArrayParameter $lArray $i]
}
# Connect the light source array to each material.
cgConnectParameter $lArray [cgGetNamedProgramParameter $::teapotProg CG_PROGRAM "lights"]
cgConnectParameter $lArray [cgGetNamedProgramParameter $::groundProg CG_PROGRAM "lights"]
# Set the 'enabled' member variable of each light source
ToggleLight 0
ToggleLight 1
# Finally, compile and load the programs
cgCompileProgram $::teapotProg
tcl3dCgPrintProgramInfo $::teapotProg "materialmain.cg"
cgGLLoadProgram $::teapotProg
cgCompileProgram $::groundProg
tcl3dCgPrintProgramInfo $::groundProg "materialmain.cg"
cgGLLoadProgram $::groundProg
}
proc Motion { toglwin x y } {
set curInd [lindex $::motionSelections $::currentSelection]
if { $::moveMode } {
set dtheta [expr double($::mouseX - $x)*$::TWOPI/$::g_WinWidth]
set dphi [expr double($y - $::mouseY)*$::TWOPI/$::g_WinHeight]
if { $curInd == $::Eye } {
set ::g_Objs($curInd,theta) [expr $::g_Objs($curInd,theta) - $dtheta]
set ::g_Objs($curInd,phi) [expr $::g_Objs($curInd,phi) - $dphi]
} else {
set ::g_Objs($curInd,theta) [expr $::g_Objs($curInd,theta) + $dtheta]
set ::g_Objs($curInd,phi) [expr $::g_Objs($curInd,phi) + $dphi]
}
if { $::g_Objs($curInd,theta) < [expr -1.0 * $::TWOPI] } {
set ::g_Objs($curInd,theta) [expr $::g_Objs($curInd,theta) + $::TWOPI]
} elseif { $::g_Objs($curInd,theta) > $::TWOPI } {
set ::g_Objs($curInd,theta) [expr $::g_Objs($curInd,theta) - $::TWOPI]
}
if { $::g_Objs($curInd,phi) > $::M_PI } {
set ::g_Objs($curInd,phi) $::M_PI
} elseif { $::g_Objs($curInd,phi) < 0.0 } {
set ::g_Objs($curInd,phi) 0.0
}
}
if { $::zoomMode } {
set ::g_Objs($curInd,r) [expr $::g_Objs($curInd,r) + 0.25* ($y-$::mouseY)]
if { $::g_Objs($curInd,r) < 0.0 } {
set ::g_Objs($curInd,r) 0.0
}
}
if { $::retargetMode } {
if { $curInd == $::Eye } {
lset ::g_Objs($curInd,target) 0 \
[expr [lindex $::g_Objs($curInd,target) 0] - 0.1 * ($::mouseX - $x)]
lset ::g_Objs($curInd,target) 1 \
[expr [lindex $::g_Objs($curInd,target) 1] + 0.1 * ($::mouseY - $y)]
} else {
lset ::g_Objs($curInd,target) 0 \
[expr [lindex $::g_Objs($curInd,target) 0] + 0.1 * ($::mouseX - $x)]
lset ::g_Objs($curInd,target) 1 \
[expr [lindex $::g_Objs($curInd,target) 1] - 0.1 * ($::mouseY - $y)]
}
}
set ::mouseX $x
set ::mouseY $y
$toglwin postredisplay
}
proc RotateMode { toglwin } {
set curInd [lindex $::motionSelections $::currentSelection]
set ::g_Objs($curInd,rotateMode) [expr ! $::g_Objs($curInd,rotateMode)]
if { $::g_Objs($curInd,rotateMode) } {
incr ::numRotating
} else {
incr ::numRotating -1
}
if { $::numRotating } {
tcl3dAfterIdle "IdleFunc $toglwin"
}
$toglwin postredisplay
}
proc ToggleLightsMode { toglwin } {
set ::drawLightsMode [expr ! $::drawLightsMode]
$toglwin postredisplay
}
proc CycleSelection { toglwin } {
set ::currentSelection [expr ($::currentSelection +1) % $::numSelections]
$toglwin postredisplay
}
proc Recenter { toglwin } {
set ind [lindex $::motionSelections $::currentSelection]
set ::g_Objs($ind,target) {0 0 0}
$toglwin postredisplay
}
CreateWindow
PrintInfo [format "Running on %s with a %s (OpenGL %s, Tcl %s)" \
$tcl_platform(os) [glGetString GL_RENDERER] \
[glGetString GL_VERSION] [info patchlevel]]