Digital Elevation Model. The following are two DEM objects: the left one was rendered with a GLW widget and the right one was rendered with a glw image displayed with a canvas widget. The attached source code highlights a architecture of a molular GUI implementation for scriptive OpenGL rendering with both a GLW widget and a glw image. It shows how to use a Tcl command, glload, to load an image file into a data array. It also shows how to use Tcl commands glexSolidDem and glexWireDem to render a DEM data set in solid and wire modes respectively. # # Copyright(c) 1999-2001, Chengye Mao, email: chengye.geo@yahoo.com # # dem - To render a 3D digital elevation model (DEM) with a GLW # widget/image. The DEM data set is a subset of Grand # Canyon DEM downloaded from USGS's website http://www.usgs.gov. # Key bindings are provided as a simple API for object rotation, # translation, zoom in/out of the 3D rendering. # # Two entries, dem.create and demcanv.create are provided to # render the DEM view in a GLW widget or a canvas-hosted glw # image respectively. # # The commands glexSolidDem and glexWireDem are used to calculate # normals and colors for each vertex in triangle fans defined by # 3x3 vertex subarrays tiled over the DEM grid. These two commands # are Tcl commands written in "C". A vertex's normal is defined # at a plane calculated from four neighboring vertices including # itself with a least-square-error method. Colors are interpolated # with blue for the minimum elevation, green for the middle and red # for the maximum. # # Many script lines look like "C" codes required for the same # rendering except for the key bindings which change the # parameters of the rendering states and are much simpler in # Tcl scripts. # # Variables of a GLW widget/image can be created with # commands such as GLint, GLfloat, GLdouble and etc. Variables # created by these commands have a scope defined by the command # glw current pathname, which returns the pathname of the # previous GLW widget/image. The created variables are valid # during the lifetime of a GLW widget/image unless they are # deleted with the command gldel. Variables associated with a GLW # widget/image are freed when the GLW widget/image is # destroyed or deleted. # # A command glload is used to read a DEM image into a variable # dem. glload can be used to read a binary data stream of # specified data type into a GLW variable. When an image file # of black/white or RGB is loaded with glload, the image's rows # and columns need to be specified separately. # # See the glw document for details of glw commands. # # Key bindings: # w display the view in a wire grid # W display the view in a solid surface # s z scale decreases # S z scale increases # z zoom out the view # Z zoom in the view # f field of view decreases # F field of view increases # left view moves left # right view moves right # up view moves up # down view moves down # Q/q stop or start rotation # # Binding of mouse motion with the left-button pressed: # view rotation # # Procedures: # dem.init - initialize # dem.gen - generate DEM in a OpenGL list # dem.reshape - configurate a GLW widget # dem.display - display a GLW widget # dem.button - handle mouse button # dem.motion - handle mouse motion # dem.keypress - handle key press # dem.rotate - rotate the DEM object by z # dem.create - entry to ceatte the rendering widget # # Procedures to wrap a GLW image into a hosting widget: # dem.img - create a GLW image for rendering # dem.img.config - configurate a GLW image with its hosting widget # dem.img.keypress - handle key press in a hosting widget # dem.img.bind - binding a hosting widget to dem proccedures # demcanv.create - entry to create a canvas-hosted GLW image # proc dem.init w {
GLint rows 160
GLint moving
# Set up simple lighting model
# Enable material properties for lighting
dem.gen $w glw current $old
proc dem.gen {w {mode Solid}} {
proc dem.reshape {w width height} {
proc dem.display w {
glColor 1 1 1
glEnable GL_DEPTH_TEST
glPushMatrix
glw draw
proc dem.button {w state x y} {
if {$state == "BUTTON_UP"} {
proc dem.motion {w x y} {
proc dem.keypress {w keycode keysym} {
switch $keysym {
proc dem.rotate w {
proc dem.queue w {
proc dem.create w {
bind $w <Expose>
"dem.display $w"
dem.display $w
proc dem.img img {
dem.reshape $img 180 90
proc dem.img.config {w img wwd wht} {
proc dem.img.keypress {w img k K} {
proc dem.img.bind {w img} {
proc demcanv.create canv {
|