Demo 4 of 6 in category FopingTutorials
 |
# Tuto8.tcl: Draw a shape with fog.
#
# Original C++ code by Franclin Foping.
# See http://www.openscenegraph.org/projects/osg/wiki/Support/Tutorials
# for the original files.
#
# Modified for Tcl3D by Paul Obermeier 2009/03/20.
# See www.tcl3d.org for the Tcl3D extension.
package require tcl3d
if { ! [tcl3dHaveOsg] } {
tk_messageBox -icon error -type ok -title "Missing Tcl3D module" \
-message "Demo needs the tcl3dOSG module."
proc Cleanup {} {}
exit 1
return
}
# Font to be used in the Tk listbox.
set gDemo(listFont) {-family {Courier} -size 10}
# Window size.
set gDemo(winWidth) 640
set gDemo(winHeight) 480
# Determine the directory and filename of this script.
set gDemo(scriptFile) [info script]
set gDemo(scriptDir) [file dirname $gDemo(scriptFile)]
# Show errors occuring in the Togl callbacks.
proc bgerror { msg } {
puts "Error: $msg\n\n$::errorInfo"
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
}
}
# Idle callback to redisplay the scene.
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
}
}
proc CreateCallback { toglwin } {
}
proc ReshapeCallback { toglwin { w -1 } { h -1 } } {
set w [$toglwin width]
set h [$toglwin height]
# Propagate resize event to embedded OSG window.
tcl3dOsgWindowResize $toglwin [tcl3dOsgGetOsgWin] $w $h
}
proc DisplayCallback { toglwin } {
if { [viewer valid] } {
viewer frame
}
$toglwin swapbuffers
}
proc Cleanup {} {
uplevel #0 unset gDemo
viewer -delete
}
proc ExitProg {} {
exit
}
proc SaveOsgToFile {} {
global gDemo
set osgRoot [viewer getSceneData]
set outFile [format "%s.osgt" [file rootname $gDemo(scriptFile)]]
# Create a name on the file system, if running from within a Starpack.
set outFile [tcl3dGenExtName $outFile]
puts "Saving scenegraph to file $outFile"
if { ! [osgDB::writeNodeFile $osgRoot $outFile] } {
puts "Failed to write scenegraph to file $outFile"
}
}
proc CreateWidgets { osgwin } {
global gDemo
frame .fr
pack .fr -expand 1 -fill both
set toglwin .fr.toglwin
togl $toglwin -width $gDemo(winWidth) -height $gDemo(winHeight) \
-double true -depth true -alpha true \
-createcommand CreateCallback \
-reshapecommand ReshapeCallback \
-displaycommand DisplayCallback
listbox .fr.usage -font $::gDemo(listFont) -height 3
label .fr.info
grid $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: Foping's OSG tutorial #8 (Draw a shape with fog)"
wm protocol . WM_DELETE_WINDOW "ExitProg"
bind . <Key-Escape> "ExitProg"
bind . <Key-f> "SaveOsgToFile"
# Propagate key and mouse events down to OSG.
bind . <KeyPress> "tcl3dOsgKeyPress $toglwin $osgwin %N"
tcl3dOsgAddTrackballBindings $toglwin $osgwin
.fr.usage insert end "Key-Escape Exit"
.fr.usage insert end "Key-f Save SceneGraph to file"
.fr.usage insert end "Mouse Trackball"
.fr.usage configure -state disabled
}
#
# Start of tutorial specific code.
#
proc myQuad {} {
global gDemo
osg::Geode geode
osg::Geometry geometry
osg::Vec3Array vertices
vertices push [osg::Vec3 v1 3.0 0.0 0.0]
vertices push [osg::Vec3 v2 3.0 0.0 3.0]
vertices push [osg::Vec3 v3 0.0 0.0 3.0]
vertices push [osg::Vec3 v4 0.0 0.0 0.0]
geometry setVertexArray vertices
# All vertices are white this time (it's hard to see that we have two
# textures with all the colors...)
osg::Vec4Array colors
colors push [osg::Vec4 c1 1.0 1.0 1.0 1.0]
geometry setColorArray colors
geometry setColorBinding $::osg::Geometry_BIND_OVERALL
osg::Vec3Array normals
normals push [osg::Vec3 n1 0.0 -1.0 0.0]
geometry setNormalArray normals
geometry setNormalBinding $::osg::Geometry_BIND_OVERALL
# Load texture from file and map it to the triangle
set img1File [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data/Fieldstone.bmp"]]
set img1 [osgDB::readImageFile $img1File]
if { $img1 eq "NULL" } {
puts "Error reading texture \"$img1File\""
exit 1
}
osg::Texture2D texture1
texture1 setImage $img1
set stateSet [geode getOrCreateStateSet]
$stateSet setTextureAttributeAndModes 0 texture1 $::osg::StateAttribute_ON
# And do the same for the second "texture unit".
set img2File [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data/window04smash.bmp"]]
set img2 [osgDB::readImageFile $img2File]
if { $img2 eq "NULL" } {
puts "Error reading texture \"$img2File\""
exit 1
}
osg::Texture2D texture2
texture2 setImage $img2
$stateSet setTextureAttributeAndModes 1 texture2 $::osg::StateAttribute_ON
osg::Vec2Array texCoords
texCoords push [osg::Vec2 t1 0.0 0.0]
texCoords push [osg::Vec2 t2 0.0 1.0]
texCoords push [osg::Vec2 t3 1.0 1.0]
texCoords push [osg::Vec2 t4 1.0 0.0]
# Here, the two texture units (0 and 1) share the same texture coordinates.
geometry setTexCoordArray 0 texCoords
geometry setTexCoordArray 1 texCoords
# Back to the usual: setup a primitive set and add the geometry to the geode.
geometry addPrimitiveSet [osg::DrawArrays da $::osg::PrimitiveSet_QUADS 0 [vertices size]]
geode addDrawable geometry
return geode
}
# This is where we defined the fogging effect
proc setFogState {} {
osg::Fog fog ; # The fog object
fog setMode $::osg::Fog_LINEAR ; # Fog type
fog setColor [osg::Vec4 c1 0.8 0.8 0.8 0] ; # Fog color
# Start position of the fog - distance from the camera to the fog
fog setStart 120
# maximum distance - where the fog terminates.
fog setEnd 200
osg::StateSet fogState
fogState setAttributeAndModes fog $::osg::StateAttribute_ON
fogState setMode $::GL_FOG $::osg::StateAttribute_ON
return fogState
}
osgViewer::ViewerRef viewer [osgViewer::Viewer]
osg::Group root
osg::PositionAttitudeTransform objectPat
osg::PositionAttitudeTransform quadPat
osg::MatrixTransform terrainScaleMAT
osg::Matrix terrainScaleMatrix
terrainScaleMatrix makeScale 0.05 0.05 0.03
osg::Vec3d objectPosTrans -1 3 5
osg::Vec3d quadPos 5 0 5
osg::Vec3f terrainScale 0.5 0.5 0.5
# The geode of the capsule
osg::Geode myshapegeode
objectPat addChild myshapegeode
objectPat setPosition objectPosTrans
quadPat addChild [myQuad]
quadPat setPosition quadPos
myshapegeode addDrawable [osg::ShapeDrawable sd [osg::Capsule caps [osg::Vec3f] 1 2]]
# Getting the state set of the geode
set nodess [myshapegeode getOrCreateStateSet]
# Loading texture image object
set imgFile [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data/Fieldstone.bmp"]]
set img [osgDB::readImageFile $imgFile]
if { $img eq "NULL" } {
puts "Error reading texture \"$imgFile\""
exit 1
}
# Bind the image to a 2D texture object
osg::Texture2D tex
tex setImage $img
# Applying texture on the object
$nodess setTextureAttributeAndModes 0 tex $::osg::StateAttribute_ON
# Loading the terrain node
set osgFile [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data/Terrain2.3ds"]]
set terrainnode [osgDB::readNodeFile $osgFile]
terrainScaleMAT addChild $terrainnode
terrainScaleMAT setMatrix terrainScaleMatrix
# Adding the terrain node to the root node
root addChild quadPat
root addChild objectPat
root addChild terrainScaleMAT
# Adding the fog to the root node
root setStateSet [setFogState]
# run optimization over the scene graph
osgUtil::Optimizer optimizer
optimizer optimize root
viewer setSceneData root
viewer setCameraManipulator [osgGA::TrackballManipulator]
if { $argc >= 1 && [lindex $argv 0] eq "-viewer" } {
# Only use the standard OSG viewer window without any Tk widgets.
viewer setUpViewInWindow 50 50 500 400
viewer run
exit 0
}
# Use the OSG viewer inside a Togl widget.
set osgwin [viewer setUpViewerAsEmbeddedInWindow 50 50 500 400]
tcl3dOsgSetOsgWin $osgwin
viewer realize
CreateWidgets $osgwin
PrintInfo [tcl3dOsgGetInfoString]
if { [file tail [info script]] eq [file tail $::argv0] } {
# If started directly from tclsh or wish, then start animation.
update
StartAnimation
}
|
