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
}
}
|