# Lesson22.tcl
#
# NeHe's GL_ARB_multitexture & Bump Mapping Tutorial
#
# This Code Was Created by Jens Schneider (WizardSoft) 2000
# Lesson22 to the series of OpenGL tutorials by NeHe-Production
#
# This Code is loosely based upon Lesson06 by Jeff Molofee.
# contact me at: schneide@pool.informatik.rwth-aachen.de
#
# Basecode Was Created By Jeff Molofee 2000
# If You've Found This Code Useful, Please Let Me Know.
# Visit My Site At nehe.gamedev.net
#
# Modified for Tcl3D by Paul Obermeier 2006/08/16
# See www.tcl3d.org for the Tcl3D extension.
package require Img
package require tcl3d
set MAX_EMBOSS 0.008 ; # Maximum Emboss-Translate. Increase To Get Higher Immersion
# At A Cost Of Lower Quality (More Artifacts Will Occur!)
# Here Comes The ARB-Multitexture Support.
# There Are (Optimally) 6 New Commands To The OpenGL Set:
# glMultiTexCoordifARB i=1..4 : Sets Texture-Coordinates For Texel-Pipeline #i
# glActiveTextureARB : Sets Active Texel-Pipeline
# glClientActiveTextureARB : Sets Active Texel-Pipeline For The Pointer-Array-Commands
#
# There Are Even More For The Various Formats Of glMultiTexCoordi{f,fv,d,i},
# But We Don't Need Them.
# Font to be used in the Tk listbox.
set listFont {-family {Courier} -size 10}
# Determine the directory of this script.
set gDemo(scriptDir) [file dirname [info script]]
# Display mode.
set fullScreen false
# Window size.
set gDemo(winWidth) 640
set gDemo(winHeight) 480
set xrot 0.0 ; # X Rotation
set yrot 0.0 ; # Y Rotation
set xspeed 0.1 ; # X Rotation Speed
set yspeed 0.0 ; # Y Rotation Speed
set z -5.0 ; # Depth Into The Screen
set LightAmbient { 0.2 0.2 0.2 } ; # Ambient Light is 20% white
set LightDiffuse { 1.0 1.0 1.0 } ; # Diffuse Light is white
set LightPosition { 0.0 0.0 2.0 } ; # Position is somewhat in front of screen
set __ARB_ENABLE 1 ; # Used To Disable ARB Extensions Entirely
set multitextureSupported 0 ; # Flag Indicating Whether Multitexturing Is Supported
set useMultitexture 1 ; # Use It If It Is Supported?
set maxTexelUnits 1 ; # Number Of Texel-Pipelines. This Is At Least 1.
set emboss 0 ; # Emboss Only, No Basetexture?
set bumps 1 ; # Do Bumpmapping?
set filter 1 ; # Which Filter To Use
set texture [tcl3dVector GLuint 3] ; # Storage For 3 Textures
set bump [tcl3dVector GLuint 3] ; # Our Bumpmappings
set invbump [tcl3dVector GLuint 3] ; # Inverted Bumpmaps
set glLogo [tcl3dVector GLuint 1] ; # Handle For OpenGL-Logo
set multiLogo [tcl3dVector GLuint 1] ; # Handle For Multitexture-Enabled-Logo
set Gray { 0.5 0.5 0.5 1.0 }
# Data Contains The Faces For The Cube In Format 2xTexCoord, 3xVertex;
# Note That The Tesselation Of The Cube Is Only Absolute Minimum.
# Face ordering: Front, Back, Top, Bottom, Right, Left.
set data [list \
0.0 0.0 -1.0 -1.0 1.0 \
1.0 0.0 1.0 -1.0 1.0 \
1.0 1.0 1.0 1.0 1.0 \
0.0 1.0 -1.0 1.0 1.0 \
1.0 0.0 -1.0 -1.0 -1.0 \
1.0 1.0 -1.0 1.0 -1.0 \
0.0 1.0 1.0 1.0 -1.0 \
0.0 0.0 1.0 -1.0 -1.0 \
0.0 1.0 -1.0 1.0 -1.0 \
0.0 0.0 -1.0 1.0 1.0 \
1.0 0.0 1.0 1.0 1.0 \
1.0 1.0 1.0 1.0 -1.0 \
1.0 1.0 -1.0 -1.0 -1.0 \
0.0 1.0 1.0 -1.0 -1.0 \
0.0 0.0 1.0 -1.0 1.0 \
1.0 0.0 -1.0 -1.0 1.0 \
1.0 0.0 1.0 -1.0 -1.0 \
1.0 1.0 1.0 1.0 -1.0 \
0.0 1.0 1.0 1.0 1.0 \
0.0 0.0 1.0 -1.0 1.0 \
0.0 0.0 -1.0 -1.0 -1.0 \
1.0 0.0 -1.0 -1.0 1.0 \
1.0 1.0 -1.0 1.0 1.0 \
0.0 1.0 -1.0 1.0 -1.0 \
]
# 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 SetFullScreenMode { win } {
set sh [winfo screenheight $win]
set sw [winfo screenwidth $win]
wm minsize $win $sw $sh
wm maxsize $win $sw $sh
set fmtStr [format "%dx%d+0+0" $sw $sh]
wm geometry $win $fmtStr
wm overrideredirect $win 1
focus -force $win
}
proc SetWindowMode { win w h } {
set sh [winfo screenheight $win]
set sw [winfo screenwidth $win]
wm minsize $win 10 10
wm maxsize $win $sw $sh
set fmtStr [format "%dx%d+0+25" $w $h]
wm geometry $win $fmtStr
wm overrideredirect $win 0
focus -force $win
}
# Toggle between windowing and fullscreen mode.
proc ToggleWindowMode {} {
if { $::fullScreen } {
SetFullScreenMode .
set ::fullScreen false
} else {
SetWindowMode . $::gDemo(winWidth) $::gDemo(winHeight)
set ::fullScreen true
}
}
proc ToggleEmboss {} {
set ::emboss [expr 1 - $::emboss]
.fr.toglwin postredisplay
}
proc ToggleMultitexture {} {
set ::useMultitexture [expr (1 - $::useMultitexture) && $::multitextureSupported]
.fr.toglwin postredisplay
}
proc ToggleBumps {} {
set ::bumps [expr 1 - $::bumps]
.fr.toglwin postredisplay
}
proc ToggleFilter {} {
incr ::filter
if { $::filter > 2 } {
set ::filter 0
}
.fr.toglwin postredisplay
}
proc SetXSpeed { val } {
set ::xspeed [expr $::xspeed + $val]
}
proc SetYSpeed { val } {
set ::yspeed [expr $::yspeed + $val]
}
proc SetDepth { val } {
set ::z [expr $::z + $val]
}
# initMultitexture Checks At Run-Time If Multitexturing Is Supported
proc initMultitexture { toglwin } {
if { [tcl3dOglHaveExtension $toglwin "GL_ARB_multitexture"] && \
$::__ARB_ENABLE && \
[tcl3dOglHaveExtension $toglwin "GL_EXT_texture_env_combine"] } {
set ::maxTexelUnits [tcl3dOglGetMaxTextureUnits]
puts "GL_ARB_multitexture extension found ($::maxTexelUnits texel units)"
return 1
}
puts "GL_ARB_multitexture extension not found"
set ::useMultitexture 0 ; # We Can't Use It If It Isn't Supported!
return 0
}
proc initLights {} {
glLightfv GL_LIGHT1 GL_AMBIENT $::LightAmbient ; # Load Light-Parameters Into GL_LIGHT1
glLightfv GL_LIGHT1 GL_DIFFUSE $::LightDiffuse
glLightfv GL_LIGHT1 GL_POSITION $::LightPosition
glEnable GL_LIGHT1
}
proc LoadImage { imgName numChans } {
if { $numChans != 3 && $numChans != 4 } {
error "Error: Only 3 or 4 channels allowed ($numChans supplied)"
}
set texName [file join $::gDemo(scriptDir) "Data" $imgName]
set retVal [catch {set phImg [image create photo -file $texName]} err1]
if { $retVal != 0 } {
error "Error reading image $texName ($err1)"
} else {
set w [image width $phImg]
set h [image height $phImg]
set texImg [tcl3dVectorFromPhoto $phImg $numChans]
image delete $phImg
}
return [list $texImg $w $h]
}
# Load Bitmaps And Convert To Textures
proc LoadGLTextures {} {
# Load The Tile-Bitmap For Base-Texture
set imgInfo [LoadImage "Base.bmp" 3]
set imgData [lindex $imgInfo 0]
set imgWidth [lindex $imgInfo 1]
set imgHeight [lindex $imgInfo 2]
glGenTextures 3 $::texture ; # Create Three Textures
# Create Nearest Filtered Texture
glBindTexture GL_TEXTURE_2D [$::texture get 0]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_NEAREST
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_NEAREST
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGB8 $imgWidth $imgHeight 0 GL_RGB GL_UNSIGNED_BYTE $imgData
# Create Linear Filtered Texture
glBindTexture GL_TEXTURE_2D [$::texture get 1]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGB8 $imgWidth $imgHeight 0 GL_RGB GL_UNSIGNED_BYTE $imgData
# Create MipMapped Texture
glBindTexture GL_TEXTURE_2D [$::texture get 2]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR_MIPMAP_NEAREST
gluBuild2DMipmaps GL_TEXTURE_2D $::GL_RGB8 $imgWidth $imgHeight GL_RGB GL_UNSIGNED_BYTE $imgData
# Delete the image data vector.
$imgData delete
# Load The Bumpmaps
set imgInfo [LoadImage "Bump.bmp" 3]
set imgData [lindex $imgInfo 0]
set imgWidth [lindex $imgInfo 1]
set imgHeight [lindex $imgInfo 2]
glPixelTransferf GL_RED_SCALE 0.5 ; # Scale RGB By 50%, So That We Have Only
glPixelTransferf GL_GREEN_SCALE 0.5 ; # Half Intenstity
glPixelTransferf GL_BLUE_SCALE 0.5
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S $::GL_CLAMP ; # No Wrapping, Please!
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_T $::GL_CLAMP
glTexParameterfv GL_TEXTURE_2D GL_TEXTURE_BORDER_COLOR $::Gray
glGenTextures 3 $::bump ; # Create Three Textures
# Create Nearest Filtered Texture
glBindTexture GL_TEXTURE_2D [$::bump get 0]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_NEAREST
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_NEAREST
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGB8 $imgWidth $imgHeight 0 GL_RGB GL_UNSIGNED_BYTE $imgData
# Create Linear Filtered Texture
glBindTexture GL_TEXTURE_2D [$::bump get 1]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGB8 $imgWidth $imgHeight 0 GL_RGB GL_UNSIGNED_BYTE $imgData
# Create MipMapped Texture
glBindTexture GL_TEXTURE_2D [$::bump get 2]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR_MIPMAP_NEAREST
gluBuild2DMipmaps GL_TEXTURE_2D $::GL_RGB8 $imgWidth $imgHeight GL_RGB GL_UNSIGNED_BYTE $imgData
tcl3dVectorManip $imgData $imgWidth $imgHeight 3 -1 255 ; # Invert The Bumpmap
glGenTextures 3 $::invbump ; # Create Three Textures
# Create Nearest Filtered Texture
glBindTexture GL_TEXTURE_2D [$::invbump get 0]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_NEAREST
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_NEAREST
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGB8 $imgWidth $imgHeight 0 GL_RGB GL_UNSIGNED_BYTE $imgData
# Create Linear Filtered Texture
glBindTexture GL_TEXTURE_2D [$::invbump get 1]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGB8 $imgWidth $imgHeight 0 GL_RGB GL_UNSIGNED_BYTE $imgData
# Create MipMapped Texture
glBindTexture GL_TEXTURE_2D [$::invbump get 2]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR_MIPMAP_NEAREST
gluBuild2DMipmaps GL_TEXTURE_2D $::GL_RGB8 $imgWidth $imgHeight GL_RGB GL_UNSIGNED_BYTE $imgData
glPixelTransferf GL_RED_SCALE 1.0 ; # Scale RGB Back To 100% Again
glPixelTransferf GL_GREEN_SCALE 1.0
glPixelTransferf GL_BLUE_SCALE 1.0
# Delete the image data vector.
$imgData delete
# Load The Logo-Bitmaps
set imgInfo [LoadImage "OpenGL_Alpha.bmp" 3]
set imgData [lindex $imgInfo 0]
set imgWidth [lindex $imgInfo 1]
set imgHeight [lindex $imgInfo 2]
set alphaImg [tcl3dVector GLubyte [expr $imgWidth * $imgHeight * 4]] ; # Create Memory For RGBA8-Texture
tcl3dVectorCopyChannel $imgData $alphaImg 0 3 $imgWidth $imgHeight 3 4 ; # Pick Only Red Value As Alpha
$imgData delete
set imgInfo [LoadImage "OpenGL.bmp" 3]
set imgData [lindex $imgInfo 0]
tcl3dVectorCopyChannel $imgData $alphaImg 0 0 $imgWidth $imgHeight 3 4 ; # Red
tcl3dVectorCopyChannel $imgData $alphaImg 1 1 $imgWidth $imgHeight 3 4 ; # Green
tcl3dVectorCopyChannel $imgData $alphaImg 2 2 $imgWidth $imgHeight 3 4 ; # Blue
$imgData delete
glGenTextures 1 $::glLogo ; # Create One Texture
# Create Linear Filtered RGBA8-Texture
glBindTexture GL_TEXTURE_2D [$::glLogo get 0]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGBA8 $imgWidth $imgHeight 0 GL_RGBA GL_UNSIGNED_BYTE $alphaImg
$alphaImg delete
# Load The "Extension Enabled"-Logo
set imgInfo [LoadImage "Multi_On_Alpha.bmp" 3]
set imgData [lindex $imgInfo 0]
set imgWidth [lindex $imgInfo 1]
set imgHeight [lindex $imgInfo 2]
set alphaImg [tcl3dVector GLubyte [expr $imgWidth * $imgHeight * 4]]
tcl3dVectorCopyChannel $imgData $alphaImg 0 3 $imgWidth $imgHeight 3 4 ; # Pick Only Red Value As Alpha
$imgData delete
set imgInfo [LoadImage "Multi_On.bmp" 3]
set imgData [lindex $imgInfo 0]
tcl3dVectorCopyChannel $imgData $alphaImg 0 0 $imgWidth $imgHeight 3 4 ; # Red
tcl3dVectorCopyChannel $imgData $alphaImg 1 1 $imgWidth $imgHeight 3 4 ; # Green
tcl3dVectorCopyChannel $imgData $alphaImg 2 2 $imgWidth $imgHeight 3 4 ; # Blue
$imgData delete
glGenTextures 1 $::multiLogo ; # Create One Texture
# Create Linear Filtered RGBA8-Texture
glBindTexture GL_TEXTURE_2D [$::multiLogo get 0]
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_LINEAR
glTexImage2D GL_TEXTURE_2D 0 $::GL_RGBA8 $imgWidth $imgHeight 0 GL_RGBA GL_UNSIGNED_BYTE $alphaImg
$alphaImg delete
}
# Resize And Initialize The GL Window
proc ReshapeCallback { toglwin { w -1 } { h -1 } } {
set w [$toglwin width]
set h [$toglwin height]
glViewport 0 0 $w $h ; # Reset The Current Viewport
glMatrixMode GL_PROJECTION ; # Select The Projection Matrix
glLoadIdentity ; # Reset The Projection Matrix
# Calculate The Aspect Ratio Of The Window
gluPerspective 45.0 [expr double($w)/double($h)] 0.1 100.0
glMatrixMode GL_MODELVIEW ; # Select The Modelview Matrix
glLoadIdentity ; # Reset The Modelview Matrix
set ::gDemo(winWidth) $w
set ::gDemo(winHeight) $h
}
proc doCube {} {
global data
glBegin GL_QUADS
# Front Face
glNormal3f 0.0 0.0 1.0
for { set i 0 } { $i < 4 } { incr i } {
set ind [expr 5 * $i]
glTexCoord2f [lindex $data $ind] [lindex $data [expr $ind+1]]
glVertex3f [lindex $data [expr $ind+2]] [lindex $data [expr $ind+3]] [lindex $data [expr $ind+4]]
}
# Back Face
glNormal3f 0.0 0.0 -1.0
for { set i 4 } { $i < 8 } { incr i } {
set ind [expr 5 * $i]
glTexCoord2f [lindex $data $ind] [lindex $data [expr $ind+1]]
glVertex3f [lindex $data [expr $ind+2]] [lindex $data [expr $ind+3]] [lindex $data [expr $ind+4]]
}
# Top Face
glNormal3f 0.0 1.0 0.0
for { set i 8 } { $i < 12 } { incr i } {
set ind [expr 5 * $i]
glTexCoord2f [lindex $data $ind] [lindex $data [expr $ind+1]]
glVertex3f [lindex $data [expr $ind+2]] [lindex $data [expr $ind+3]] [lindex $data [expr $ind+4]]
}
# Bottom Face
glNormal3f 0.0 -1.0 0.0
for { set i 12 } { $i < 16 } { incr i } {
set ind [expr 5 * $i]
glTexCoord2f [lindex $data $ind] [lindex $data [expr $ind+1]]
glVertex3f [lindex $data [expr $ind+2]] [lindex $data [expr $ind+3]] [lindex $data [expr $ind+4]]
}
# Right face
glNormal3f 1.0 0.0 0.0
for { set i 16 } { $i < 20 } { incr i } {
set ind [expr 5 * $i]
glTexCoord2f [lindex $data $ind] [lindex $data [expr $ind+1]]
glVertex3f [lindex $data [expr $ind+2]] [lindex $data [expr $ind+3]] [lindex $data [expr $ind+4]]
}
# Left Face
glNormal3f -1.0 0.0 0.0
for { set i 20 } { $i < 24 } { incr i } {
set ind [expr 5 * $i]
glTexCoord2f [lindex $data $ind] [lindex $data [expr $ind+1]]
glVertex3f [lindex $data [expr $ind+2]] [lindex $data [expr $ind+3]] [lindex $data [expr $ind+4]]
}
glEnd
}
# All Setup For OpenGL Goes Here
proc CreateCallback { toglwin } {
set ::multitextureSupported [initMultitexture $toglwin]
LoadGLTextures ; # Jump To Texture Loading Routine
glEnable GL_TEXTURE_2D ; # Enable Texture Mapping
glShadeModel GL_SMOOTH ; # Enable Smooth Shading
glClearColor 0.0 0.0 0.0 0.5 ; # Black Background
glClearDepth 1.0 ; # Depth Buffer Setup
glEnable GL_DEPTH_TEST ; # Enables Depth Testing
glDepthFunc GL_LEQUAL ; # The Type Of Depth Testing To Do
glHint GL_PERSPECTIVE_CORRECTION_HINT GL_NICEST ; # Really Nice Perspective Calculations
initLights ; # Initialize OpenGL Light
}
# Okay, Here Comes The Important Stuff:
#
# On http://www.nvidia.com/marketing/Developer/DevRel.nsf/TechnicalDemosFrame?OpenPage
# You Can Find A Demo Called GL_BUMP That Is A Little Bit More Complicated.
# GL_BUMP: Copyright Diego Tártara, 1999.
# - diego_tartara@ciudad.com.ar -
#
# The Idea Behind GL_BUMP Is, That You Compute The Texture-Coordinate Offset As Follows:
# 0) All Coordinates Either In Object Or In World Space.
# 1) Calculate Vertex v From Actual Position (The Vertex You're At) To The Lightposition
# 2) Normalize v
# 3) Project This v Into Tangent Space.
# Tangent Space Is The Plane "Touching" The Object In Our Current Position On It.
# Typically, If You're Working With Flat Surfaces, This Is The Surface Itself.
# 4) Offset s,t-Texture-Coordinates By The Projected v's x And y-Component.
#
# * This Would Be Called Once Per Vertex In Our Geometry, If Done Correctly.
# * This Might Lead To Incoherencies In Our Texture Coordinates, But Is Ok As Long As You Did Not
# * Wrap The Bumpmap.
#
# Basically, We Do It The Same Way With Some Exceptions:
# ad 0) We'll Work In Object Space All Time. This Has The Advantage That We'll Only
# Have To Transform The Lightposition From Frame To Frame. This Position Obviously
# Has To Be Transformed Using The Inversion Of The Modelview Matrix. This Is, However,
# A Considerable Drawback, If You Don't Know How Your Modelview Matrix Was Built, Since
# Inverting A Matrix Is Costly And Complicated.
# ad 1) Do It Exactly That Way.
# ad 2) Do It Exactly That Way.
# ad 3) To Project The Lightvector Into Tangent Space, We'll Support The Setup-Routine
# With Two Directions: One Of Increasing s-Texture-Coordinate Axis, The Other In
# Increasing t-Texture-Coordinate Axis. The Projection Simply Is (Assumed Both
# texCoord Vectors And The Lightvector Are Normalized) The Dotproduct Between The
# Respective texCoord Vector And The Lightvector.
# ad 4) The Offset Is Computed By Taking The Result Of Step 3 And Multiplying The Two
# Numbers With MAX_EMBOSS, A Constant That Specifies How Much Quality We're Willing To
# Trade For Stronger Bump-Effects. Just Temper A Little Bit With MAX_EMBOSS!
#
# WHY THIS IS COOL:
# * Have A Look!
# * Very Cheap To Implement (About One Squareroot And A Couple Of MULs)!
# * Can Even Be Further Optimized!
# * SetUpBump Doesn't Disturb glBegin()/glEnd()
# * THIS DOES ALWAYS WORK - Not Only With XY-Tangent Spaces!!
#
# DRAWBACKS:
# * Must Know "Structure" Of Modelview-Matrix Or Invert It. Possible To Do The Whole Thing
# * In World Space, But This Involves One Transformation For Each Vertex!
#
proc SetUpBumps { n c l s t } {
set v [tcl3dVector GLfloat 3] ; # Vertex From Current Position To Light
set cv [tcl3dVectorFromList GLfloat $c]
# Calculate v From Current Vector c To Lightposition And Normalize v
tcl3dVec3fSubtract $l $cv $v
tcl3dVec3fNormalize $v
# Project v Such That We Get Two Values Along Each Texture-Coordinat Axis.
set retList $c
lset retList 0 [expr ([lindex $s 0]*[$v get 0] + [lindex $s 1]*[$v get 1] + [lindex $s 2]*[$v get 2])*$::MAX_EMBOSS]
lset retList 1 [expr ([lindex $t 0]*[$v get 0] + [lindex $t 1]*[$v get 1] + [lindex $t 2]*[$v get 2])*$::MAX_EMBOSS]
return $retList
}
# MUST CALL THIS LAST!!!, Billboards The Two Logos.
proc doLogo {} {
glDepthFunc GL_ALWAYS
glBlendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
glEnable GL_BLEND
glDisable GL_LIGHTING
glLoadIdentity
glBindTexture GL_TEXTURE_2D [$::glLogo get 0]
glBegin GL_QUADS
glTexCoord2f 0.0 0.0 ; glVertex3f 0.23 -0.4 -1.0
glTexCoord2f 1.0 0.0 ; glVertex3f 0.53 -0.4 -1.0
glTexCoord2f 1.0 1.0 ; glVertex3f 0.53 -0.25 -1.0
glTexCoord2f 0.0 1.0 ; glVertex3f 0.23 -0.25 -1.0
glEnd
if { $::useMultitexture } {
glBindTexture GL_TEXTURE_2D [$::multiLogo get 0]
glBegin GL_QUADS
glTexCoord2f 0.0 0.0 ; glVertex3f -0.53 -0.4 -1.0
glTexCoord2f 1.0 0.0 ; glVertex3f -0.33 -0.4 -1.0
glTexCoord2f 1.0 1.0 ; glVertex3f -0.33 -0.3 -1.0
glTexCoord2f 0.0 1.0 ; glVertex3f -0.53 -0.3 -1.0
glEnd
}
glDepthFunc GL_LEQUAL
}
proc doMesh1TexelUnits {} {
global data
#puts "doMesh1"
set c {0.0 0.0 0.0} ; # Holds Current Vertex
set n {0.0 0.0 0.0} ; # Normalized Normal Of Current Surface
set s {0.0 0.0 0.0} ; # s-Texture Coordinate Direction, Normalized
set t {0.0 0.0 0.0} ; # t-Texture Coordinate Direction, Normalized
set M [tcl3dVector GLfloat 16] ; # Holds The Modelview Matrix.
set Minv [tcl3dVector GLfloat 16] ; # Holds The Inverted Modelview Matrix To Do So.
# Clear Screen And Depth Buffer
glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
# Build Inverse Modelview Matrix First. This Substitutes One Push/Pop With One glLoadIdentity();
# Simply Build It By Doing All Transformations Negated And In Reverse Order.
glLoadIdentity
glRotatef [expr {-1.0 * $::yrot}] 0.0 1.0 0.0
glRotatef [expr {-1.0 * $::xrot}] 1.0 0.0 0.0
glTranslatef 0.0 0.0 [expr {-1.0 * $::z}]
glGetFloatv GL_MODELVIEW_MATRIX $M
glLoadIdentity
glTranslatef 0.0 0.0 $::z
glRotatef $::xrot 1.0 0.0 0.0
glRotatef $::yrot 0.0 1.0 0.0
# Transform The Lightposition Into Object Coordinates:
set l [tcl3dVectorFromList GLfloat $::LightPosition]
tcl3dMatfTranspose $M $Minv
tcl3dMatfTransformPoint $l $Minv $l
# PASS#1: Use Texture "Bump"
# No Blend
# No Lighting
# No Offset Texture-Coordinates
glBindTexture GL_TEXTURE_2D [$::bump get $::filter]
glDisable GL_BLEND
glDisable GL_LIGHTING
doCube
# PASS#2: Use Texture "Invbump"
# Blend GL_ONE To GL_ONE
# No Lighting
# Offset Texture Coordinates
glBindTexture GL_TEXTURE_2D [$::invbump get $::filter]
glBlendFunc GL_ONE GL_ONE
glDepthFunc GL_LEQUAL
glEnable GL_BLEND
glBegin GL_QUADS
# Front Face
set n { 0.0 0.0 1.0 }
set s { 1.0 0.0 0.0 }
set t { 0.0 1.0 0.0 }
for { set i 0 } { $i < 4 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glTexCoord2f [expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Back Face
set n { 0.0 0.0 -1.0 }
set s { -1.0 0.0 0.0 }
set t { 0.0 1.0 0.0 }
for { set i 4 } { $i < 8 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glTexCoord2f [expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Top Face
set n { 0.0 1.0 0.0 }
set s { 1.0 0.0 0.0 }
set t { 0.0 0.0 -1.0 }
for { set i 8 } { $i < 12 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glTexCoord2f [expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Bottom Face
set n { 0.0 -1.0 0.0 }
set s { -1.0 0.0 0.0 }
set t { 0.0 0.0 -1.0 }
for { set i 12 } { $i < 16 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glTexCoord2f [expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Right Face
set n { 1.0 0.0 0.0 }
set s { 0.0 0.0 -1.0 }
set t { 0.0 1.0 0.0 }
for { set i 16 } { $i < 20 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glTexCoord2f [expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Left Face
set n { -1.0 0.0 0.0 }
set s { 0.0 0.0 1.0 }
set t { 0.0 1.0 0.0 }
for { set i 20 } { $i < 24 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glTexCoord2f [expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
glEnd
# PASS#3: Use Texture "Base"
# Blend GL_DST_COLOR To GL_SRC_COLOR (Multiplies By 2)
# Lighting Enabled
# No Offset Texture-Coordinates
if { ! $::emboss } {
glTexEnvf GL_TEXTURE_ENV GL_TEXTURE_ENV_MODE $::GL_MODULATE
glBindTexture GL_TEXTURE_2D [$::texture get $::filter]
glBlendFunc GL_DST_COLOR GL_SRC_COLOR
glEnable GL_LIGHTING
doCube
}
set ::xrot [expr {$::xrot + $::xspeed}]
set ::yrot [expr {$::yrot + $::yspeed}]
if { $::xrot > 360.0 } { set ::xrot [expr {$::xrot - 360.0}] }
if { $::xrot < 0.0 } { set ::xrot [expr {$::xrot + 360.0}] }
if { $::yrot > 360.0 } { set ::yrot [expr {$::yrot - 360.0}] }
if { $::yrot < 0.0 } { set ::yrot [expr {$::yrot + 360.0}] }
# LAST PASS: Do The Logos
doLogo
}
proc doMesh2TexelUnits {} {
global data
#puts "doMesh2"
set c {0.0 0.0 0.0} ; # Holds Current Vertex
set n {0.0 0.0 0.0} ; # Normalized Normal Of Current Surface
set s {0.0 0.0 0.0} ; # s-Texture Coordinate Direction, Normalized
set t {0.0 0.0 0.0} ; # t-Texture Coordinate Direction, Normalized
set M [tcl3dVector GLfloat 16] ; # Holds The Modelview Matrix.
set Minv [tcl3dVector GLfloat 16] ; # Holds The Inverted Modelview Matrix To Do So.
# Clear Screen And Depth Buffer
glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
# Build Inverse Modelview Matrix First. This Substitutes One Push/Pop With One glLoadIdentity();
# Simply Build It By Doing All Transformations Negated And In Reverse Order.
glLoadIdentity
glRotatef [expr {-1.0 * $::yrot}] 0.0 1.0 0.0
glRotatef [expr {-1.0 * $::xrot}] 1.0 0.0 0.0
glTranslatef 0.0 0.0 [expr {-1.0 * $::z}]
glGetFloatv GL_MODELVIEW_MATRIX $M
glLoadIdentity
glTranslatef 0.0 0.0 $::z
glRotatef $::xrot 1.0 0.0 0.0
glRotatef $::yrot 0.0 1.0 0.0
# Transform The Lightposition Into Object Coordinates:
set l [tcl3dVectorFromList GLfloat $::LightPosition]
tcl3dMatfTranspose $M $Minv
tcl3dMatfTransformPoint $l $Minv $l
# PASS#1: Texel-Unit 0: Use Texture "Bump"
# No Blend
# No Lighting
# No Offset Texture-Coordinates
# Texture-Operation "Replace"
# Texel-Unit 1: Use Texture "Invbump"
# No Lighting
# Offset Texture Coordinates
# Texture-Operation "Replace"
# TEXTURE-UNIT #0
glActiveTextureARB GL_TEXTURE0_ARB
glEnable GL_TEXTURE_2D
glBindTexture GL_TEXTURE_2D [$::bump get $::filter]
glTexEnvf GL_TEXTURE_ENV GL_TEXTURE_ENV_MODE $::GL_COMBINE_EXT
glTexEnvf GL_TEXTURE_ENV GL_COMBINE_RGB_EXT $::GL_REPLACE
# TEXTURE-UNIT #1:
glActiveTextureARB GL_TEXTURE1_ARB
glEnable GL_TEXTURE_2D
glBindTexture GL_TEXTURE_2D [$::invbump get $::filter]
glTexEnvf GL_TEXTURE_ENV GL_TEXTURE_ENV_MODE $::GL_COMBINE_EXT
glTexEnvf GL_TEXTURE_ENV GL_COMBINE_RGB_EXT $::GL_ADD
# General Switches:
glDisable GL_BLEND
glDisable GL_LIGHTING
glBegin GL_QUADS
# Front Face
set n { 0.0 0.0 1.0 }
set s { 1.0 0.0 0.0 }
set t { 0.0 1.0 0.0 }
for { set i 0 } { $i < 4 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glMultiTexCoord2fARB GL_TEXTURE0_ARB \
[lindex $data $ind] [lindex $data [expr {$ind+1}]]
glMultiTexCoord2fARB GL_TEXTURE1_ARB \
[expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Back Face
set n { 0.0 0.0 -1.0 }
set s { -1.0 0.0 0.0 }
set t { 0.0 1.0 0.0 }
for { set i 4 } { $i < 8 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glMultiTexCoord2fARB GL_TEXTURE0_ARB \
[lindex $data $ind] [lindex $data [expr {$ind+1}]]
glMultiTexCoord2fARB GL_TEXTURE1_ARB \
[expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Top Face
set n { 0.0 1.0 0.0 }
set s { 1.0 0.0 0.0 }
set t { 0.0 0.0 -1.0 }
for { set i 8 } { $i < 12 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glMultiTexCoord2fARB GL_TEXTURE0_ARB \
[lindex $data $ind] [lindex $data [expr {$ind+1}]]
glMultiTexCoord2fARB GL_TEXTURE1_ARB \
[expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Bottom Face
set n { 0.0 -1.0 0.0 }
set s { -1.0 0.0 0.0 }
set t { 0.0 0.0 -1.0 }
for { set i 12 } { $i < 16 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glMultiTexCoord2fARB GL_TEXTURE0_ARB \
[lindex $data $ind] [lindex $data [expr {$ind+1}]]
glMultiTexCoord2fARB GL_TEXTURE1_ARB \
[expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Right Face
set n { 1.0 0.0 0.0 }
set s { 0.0 0.0 -1.0 }
set t { 0.0 1.0 0.0 }
for { set i 16 } { $i < 20 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glMultiTexCoord2fARB GL_TEXTURE0_ARB \
[lindex $data $ind] [lindex $data [expr {$ind+1}]]
glMultiTexCoord2fARB GL_TEXTURE1_ARB \
[expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
# Left Face
set n { -1.0 0.0 0.0 }
set s { 0.0 0.0 1.0 }
set t { 0.0 1.0 0.0 }
for { set i 20 } { $i < 24 } { incr i } {
set ind [expr 5 * $i]
lset c 0 [lindex $data [expr {$ind + 2}]]
lset c 1 [lindex $data [expr {$ind + 3}]]
lset c 2 [lindex $data [expr {$ind + 4}]]
set c [SetUpBumps $n $c $l $s $t]
glMultiTexCoord2fARB GL_TEXTURE0_ARB \
[lindex $data $ind] [lindex $data [expr {$ind+1}]]
glMultiTexCoord2fARB GL_TEXTURE1_ARB \
[expr {[lindex $data $ind] + [lindex $c 0]}] \
[expr {[lindex $data [expr {$ind+1}]] + [lindex $c 1]}]
glVertex3f [lindex $data [expr {$ind+2}]] \
[lindex $data [expr {$ind+3}]] \
[lindex $data [expr {$ind+4}]]
}
glEnd
# PASS#2 Use Texture "Base"
# Blend GL_DST_COLOR To GL_SRC_COLOR (Multiplies By 2)
# Lighting Enabled
# No Offset Texture-Coordinates
glActiveTextureARB GL_TEXTURE1_ARB
glDisable GL_TEXTURE_2D
glActiveTextureARB GL_TEXTURE0_ARB
if { ! $::emboss } {
glTexEnvf GL_TEXTURE_ENV GL_TEXTURE_ENV_MODE $::GL_MODULATE
glBindTexture GL_TEXTURE_2D [$::texture get $::filter]
glBlendFunc GL_DST_COLOR GL_SRC_COLOR
glEnable GL_BLEND
glEnable GL_LIGHTING
doCube
}
set ::xrot [expr {$::xrot + $::xspeed}]
set ::yrot [expr {$::yrot + $::yspeed}]
if { $::xrot > 360.0 } { set ::xrot [expr {$::xrot - 360.0}] }
if { $::xrot < 0.0 } { set ::xrot [expr {$::xrot + 360.0}] }
if { $::yrot > 360.0 } { set ::yrot [expr {$::yrot - 360.0}] }
if { $::yrot < 0.0 } { set ::yrot [expr {$::yrot + 360.0}] }
# LAST PASS: Do The Logos
doLogo
}
proc doMeshNoBumps {} {
#puts "doMeshNoBumps"
# Clear Screen And Depth Buffer
glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
glLoadIdentity ; # Reset The Current Modelview Matrix
glTranslatef 0.0 0.0 $::z
glRotatef $::xrot 1.0 0.0 0.0
glRotatef $::yrot 0.0 1.0 0.0
if { $::useMultitexture } {
glActiveTextureARB GL_TEXTURE1_ARB
glDisable GL_TEXTURE_2D
glActiveTextureARB GL_TEXTURE0_ARB
}
glDisable GL_BLEND
glBindTexture GL_TEXTURE_2D [$::texture get $::filter]
glBlendFunc GL_DST_COLOR GL_SRC_COLOR
glEnable GL_LIGHTING
doCube
set ::xrot [expr {$::xrot + $::xspeed}]
set ::yrot [expr {$::yrot + $::yspeed}]
if { $::xrot > 360.0 } { set ::xrot [expr {$::xrot - 360.0}] }
if { $::xrot < 0.0 } { set ::xrot [expr {$::xrot + 360.0}] }
if { $::yrot > 360.0 } { set ::yrot [expr {$::yrot - 360.0}] }
if { $::yrot < 0.0 } { set ::yrot [expr {$::yrot + 360.0}] }
# LAST PASS: Do The Logos
doLogo
}
proc Animate {} {
.fr.toglwin postredisplay
set ::animateId [tcl3dAfterIdle Animate]
}
proc StartAnimation {} {
if { ! [info exists ::animateId] } {
Animate
}
}
proc StopAnimation {} {
if { [info exists ::animateId] } {
after cancel $::animateId
unset ::animateId
}
}
# Here's Where We Do All The Drawing
proc DisplayCallback { toglwin } {
# 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]
if { $::bumps } {
if { $::useMultitexture && ($::maxTexelUnits > 1) } {
doMesh2TexelUnits
} else {
doMesh1TexelUnits
}
} else {
doMeshNoBumps
}
$toglwin swapbuffers
}
# Put all exit related code here.
proc ExitProg {} {
exit
}
# Create the OpenGL window and some Tk helper widgets.
proc CreateWindow {} {
frame .fr
pack .fr -expand 1 -fill both
# Create Our OpenGL Window
togl .fr.toglwin -width $::gDemo(winWidth) -height $::gDemo(winHeight) \
-double true -depth true -alpha true \
-createcommand CreateCallback \
-reshapecommand ReshapeCallback \
-displaycommand DisplayCallback
listbox .fr.usage -font $::listFont -height 10
label .fr.info
grid .fr.toglwin -row 0 -column 0 -sticky news
grid .fr.usage -row 1 -column 0 -sticky news
grid .fr.info -row 2 -column 0 -sticky news
grid rowconfigure .fr 0 -weight 1
grid columnconfigure .fr 0 -weight 1
wm title . "Tcl3D demo: NeHe's GL_ARB_multitexture & Bump Mapping Tutorial (Lesson 22)"
# Watch For ESC Key And Quit Messages
wm protocol . WM_DELETE_WINDOW "ExitProg"
bind . <Key-Escape> "ExitProg"
bind . <Key-F1> "ToggleWindowMode"
bind . <Key-e> "ToggleEmboss"
bind . <Key-m> "ToggleMultitexture"
bind . <Key-b> "ToggleBumps"
bind . <Key-f> "ToggleFilter"
bind . <Key-Up> "SetXSpeed -0.01"
bind . <Key-Down> "SetXSpeed 0.01"
bind . <Key-Left> "SetYSpeed -0.01"
bind . <Key-Right> "SetYSpeed 0.01"
bind . <Key-d> "SetDepth 0.05"
bind . <Key-i> "SetDepth -0.05"
bind .fr.toglwin <1> "StartAnimation"
bind .fr.toglwin <2> "StopAnimation"
bind .fr.toglwin <3> "StopAnimation"
bind .fr.toglwin <Control-Button-1> "StopAnimation"
.fr.usage insert end "Key-Escape Exit"
.fr.usage insert end "Key-F1 Toggle window mode"
.fr.usage insert end "Key-e Toggle emboss"
.fr.usage insert end "Key-m Toggle multitexturing"
.fr.usage insert end "Key-b Toggle bump maps"
.fr.usage insert end "Key-f Toggle filter"
.fr.usage insert end "Key-Up|Down Decrease|Increase x rotation speed"
.fr.usage insert end "Key-Left|Right Decrease|Increase y rotation speed"
.fr.usage insert end "Key-d|i Decrease|Increase distance"
.fr.usage insert end "Mouse-L|MR Start|Stop animation"
.fr.usage configure -state disabled
}
CreateWindow
PrintInfo [tcl3dOglGetInfoString]
if { [file tail [info script]] eq [file tail $::argv0] } {
# If started directly from tclsh or wish, then start animation.
update
StartAnimation
}
|