[HOME][CONTENTS][DOWNLOAD][PREV][NEXT]


3D IMAGE RENDERING

A Wavefront Obj Viewer.  The following two figures are results of a wavefront obj viewer.  It shows how to use a Tcl command, oglm, to load a wavefront obj file into an oglm object in memory and to render it with the oglm commands including normal calculation and scale change.  It demonstrates a general architecure of scriptive GUI for viewing a 3D object. 

 
#
# Copyright(c) 1999-2001, Chengye Mao, email: chengye.geo@yahoo.com
#
# oglm.demo - To render a 3D object created from a wavefront obj file
#     using oglm command. A suite of oglm functions include create
#     cget, configure, delete, draw, info, material, normal, reverse
#     smooth and save for editing and manipulating an 3D object. 
#     The orginal "TclTk" object was created using Breeze Designer
#     v2.0 written by Neville Richards (http://www.imagos.fl.net.au).
#     The original head object was created by Lisa T. Casler
#     (http://www.mochamadness.com/lisa/bryce/goodies.html).
#     Both objects were edited with oglm functions to add material 
#     attributes and to recalculate normals.

#     This demo provides additional Tcl procedures to view an oglm
#     object with a GLW widget.  These procedures can also be used to 
#     render other 3D object written in OpenGL scripts. 
#
# Bindings of key press:
#     Escape destroy the demo
#     c      glDisable GL_CULL_FACE
#     C      glEnable GL_CULL_FACE 
#     w     glPolygonMode GL_FRONT_AND_BACK GL_LINE
#     W      glPolygonMode GL_FRONT_AND_BACK GL_FILL
#     s      scale down the object
#     S      scale up the object
#     z      decrease looking point z 
#     Z      increase looking point z 
#     x      decrease looking point x 
#     X      increase looking point x 
#     y      decrease looking point y
#     Y      increase looking point y
#     Left   move the object left 
#     Right  move the object right
#     Up     move the object up
#     Down   move the object down
#     Next   move the object far
#     Prior  move the object close
#     f      decrease the field of view
#     F      increase the field of view 
#
# Binding of mouse motion with the left-button pressed:
#     view rotation (x and y)
#
# Binding of mouse motion with the left-button pressed:
#     view rotation (x and z)
#
# Procedures:
#     oglm.demo      - entry point of the demo
#     oglm.bind      - bind a GLW widget to an oglm object
#     oglm.drawlist  - compile an OpenGL list object
#     oglm.reshape   - geometrical configure a GLW widget
#     oglm.display   - display a GLW widget
#     oglm.button    - handle mouse button press
#     oglm.motion    - handle mouse motion
#     oglm.keypress  - handle key press
#

proc oglm.demo {} {
    set i 0; set w .oglm-$i
    while {[winfo exists $w]} {
        incr i
        set w .oglm-$i
    }
    toplevel $w
    pack [frame $w.f] -side top -fill x

    set mbtn $w.f.mbtn
    set menu $mbtn.menu
    menubutton $mbtn -menu $menu -text "Object  "
    menu $menu -tearoff true -bd 1
    foreach obj {{head head} {tcltk tcltk}} {
        $menu add command -label "[lindex $obj 0]           " \
             -command "oglm.load $w.glw {$obj}"
    }
    pack $mbtn -side left
    pack [glw $w.glw] -side top -expand 1 -fill both
    bind $w.glw <Destroy> "destroy $w"
    oglm.load $w.glw $obj
}
proc oglm.load {w objDef} {
    global gimgHome
    set oglmObj [lindex $objDef 0]
    set objFile $gimgHome/data/[lindex $objDef 1]
    _busyIcon
    if {[lsearch [oglm info] $oglmObj] < 0} {
        oglm create $oglmObj -file $objFile.obj
    }
    _busyIcon
    oglm.bind $w $oglmObj
}
proc oglm.bind {w obj} {
    global _oglm
    set _oglm($w,obj) $obj
    set old [glw current $w]
    catch {
        GLfloat x0 0.0
        GLfloat y0 0.0
        GLfloat z0 -3
        GLfloat lx 0
        GLfloat ly 0
        GLfloat lz 2.0
        GLfloat anglex 40.0
        GLfloat anglez 0.0
        GLfloat angley 30.0
        GLfloat fov 60.0
        GLfloat sz 1.5
        GLint moving
        GLint startz 
        GLint startx
        GLint starty
        GLint drawlist [glGenLists 1]
    } 

    glEnable GL_LIGHTING
    glEnable GL_LIGHT0
    glLightModel GL_LIGHT_MODEL_TWO_SIDE GL_TRUE
    glEnable GL_DEPTH_TEST
    glEnable GL_CULL_FACE

    glMaterial GL_FRONT_AND_BACK GL_AMBIENT "0.2 0.2 0.2 1.0"
    glMaterial GL_FRONT_AND_BACK GL_DIFFUSE "0.8 0.8 0.8 1.0"
    glMaterial GL_FRONT_AND_BACK GL_SPECULAR "0.0 0.0 0.0 1.0"
    glMaterial GL_FRONT_AND_BACK GL_SHININESS 65.0

    oglm config $_oglm($w,obj) -zoom [glv sz]
    oglm.drawlist $w

    bind $w <Configure>     "oglm.reshape $w"
    bind $w <Expose>        "oglm.display $w"
    bind $w <ButtonPress-1> "oglm.button $w LEFT_DOWN %x %y"
    bind $w <ButtonPress-3> "oglm.button $w RIGHT_DOWN %x %y"
    bind $w <ButtonRelease> "oglm.button $w BUTTON_UP %x %y"
    bind $w <Motion>        "oglm.motion $w %x %y"
    bind $w <KeyPress>      "oglm.keypress $w %k %K"
    bind $w <Enter>         "focus $w"

    oglm.reshape $w
    oglm.display $w
    focus $w
    glw current $old
    return $w
}
proc oglm.drawlist w {
    global _oglm
    set old [glw current $w]
    glNewList drawlist GL_COMPILE
        oglm draw $_oglm($w,obj)
    glEndList
    glw current $old
}
proc oglm.reshape w {
    set old [glw current $w]
    set width [$w cget -width]
    set height [$w cget -height]
    glViewport 0 0 $width $height
    glMatrixMode GL_PROJECTION
    glLoadIdentity
    gluPerspective fov [expr $width/double($height)] 1.0 128.0
    glw current $old
}
proc oglm.display w {
    global _oglm
    set old [glw current $w]
    glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
    glMatrixMode GL_MODELVIEW
    glLoadIdentity

    glPushMatrix
    glTranslate x0 y0 z0
    gluLookAt lx ly lz 0 0 0 0 1 0 
    glRotate anglex 1 0 0
    glRotate angley 0 1 0
    glRotate anglez 0 0 1
    glCallList drawlist
    glPopMatrix

    glw draw $w
    glw current $old
}
proc oglm.button {w state x y} {
    set old [glw current $w]
    if {$state == "LEFT_DOWN"} {
        glset moving 1
        glset startx $y
        glset starty $x
    } 
    if {$state == "RIGHT_DOWN"} {
        glset moving 2
        glset startx $y
        glset startz $x
    }
    if {$state == "BUTTON_UP"} {
        glset moving 0
    }
    glw current $old
}
proc oglm.motion {w x y} {
    set old [glw current $w]
    set op [glv moving]
    if {$op > 0} {
        glset anglex [expr [glv anglex] + 0.5 * ($y - [glv startx])]
        glset startx $y
        if {$op == 1} {
            glset angley [expr [glv angley] + 0.5 * ($x - [glv starty])]
            glset starty $x
        } else {
            glset anglez [expr [glv anglez] + 0.5 * ($x - [glv startz])]
            glset startz $x
        }
        oglm.display $w
    }
    glw current $old
}
proc oglm.keypress {w keycode keysym} {
    global _oglm
    set old [glw current $w] 
    switch $keysym {
        "Escape" { destroy $w }
        "c"      { glDisable GL_CULL_FACE }
        "C"      { glEnable GL_CULL_FACE } 
        "w"      { glPolygonMode GL_FRONT_AND_BACK GL_LINE }
        "W"      { glPolygonMode GL_FRONT_AND_BACK GL_FILL }
        "s"      { glset sz [expr [glv sz]*0.95] 
                   oglm config $_oglm($w,obj) -zoom [glv sz]
                   oglm.drawlist $w}
        "S"      { glset sz [expr [glv sz]*1.05]
                   oglm config $_oglm($w,obj) -zoom [glv sz]
                   oglm.drawlist $w}
        "z"      { glset lz  [expr [glv lz]-0.02] }
        "Z"      { glset lz  [expr [glv lz]+0.02] }
        "x"      { glset lx  [expr [glv lx]-0.02] }
        "X"      { glset lx  [expr [glv lx]+0.02] }
        "y"      { glset ly  [expr [glv ly]-0.02] }
        "Y"      { glset ly  [expr [glv ly]+0.02] }
        "Left"   { glset x0  [expr [glv x0]-0.01] }
        "Right"  { glset x0  [expr [glv x0]+0.01] }
        "Up"     { glset y0  [expr [glv y0]+0.01] }
        "Down"   { glset y0  [expr [glv y0]-0.01] }
        "Next"   { glset z0  [expr [glv z0]+0.01] }
        "Prior"  { glset z0  [expr [glv z0]-0.01] }
        "f"      { glset fov [expr [glv fov] * 0.95]}
        "F"      { glset fov [expr [glv fov] * 1.05]} 
    }
    catch {
        glw current $old
        oglm.reshape $w
        oglm.display $w
    }
}
 

[HOME][CONTENTS][DOWNLOAD] 1