Demo 2 of 3 in category QuickStartGuide
 |
# OpenSceneGraph Quick Start Guide
# http://www.skew-matrix.com/OSGQSG
#
# Lighting Example, Basic light and material control
#
# 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: OSG QuickStartGuide example Lighting"
wm protocol . WM_DELETE_WINDOW "ExitProg"
bind . <Key-Escape> "ExitProg"
bind . <Key-f> "SaveOsgToFile"
# Propagate key and mouse events to embedded OSG window.
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 CreateLightPoint {} {
osg::GeometryRef geom [osg::Geometry]
# Don't throw away single-vertex primitives.
osg::BoundingBox bbox -0.1 -0.1 -0.1 0.1 0.1 0.1
geom setInitialBound bbox
osg::Vec3Array v
geom setVertexArray v
v push [osg::Vec3 v1 0.0 0.0 0.0]
osg::Vec4Array c
geom setColorArray c
geom setColorBinding $::osg::Geometry_BIND_OVERALL
c push [osg::Vec4 c1 1.0 1.0 1.0 1.0]
geom addPrimitiveSet [osg::DrawArrays da $::GL_POINTS 0 1]
osg::Geode geode
geode addDrawable [geom get]
set state [geode getOrCreateStateSet]
$state setMode $::GL_LIGHTING \
[expr $::osg::StateAttribute_OFF | $::osg::StateAttribute_PROTECTED]
osg::Point pt
pt setSize 10.0
$state setAttribute pt osg::StateAttribute_ON
return geode
}
proc CreatePlane {} {
osg::GeometryRef geom [osg::Geometry]
osg::Vec3Array v
geom setVertexArray v
for { set y -10 } { $y <= 10 } { incr y } {
for { set x -10 } { $x <= 10 } { incr x } {
v push [osg::Vec3 v_${x}_${y} [expr {$x*0.5}] [expr {$y*0.5}] 0.0]
}
}
osg::Vec3Array n
geom setNormalArray n
geom setNormalBinding $::osg::Geometry_BIND_OVERALL
n push [osg::Vec3 n1 0.0 0.0 1.0]
osg::Vec4Array c
geom setColorArray c
geom setColorBinding $::osg::Geometry_BIND_OVERALL
c push [osg::Vec4 c1 1.0 1.0 1.0 1.0]
set len 21
set idx 0
set numStrips [expr {$len-1}]
set indices [tcl3dVector GLushort [expr {$len+$len}]]
while { $numStrips > 0 } {
set vert 0
while { $vert < $len } {
$indices set [expr {2*$vert+0}] [expr {$idx+$len}]
$indices set [expr {2*$vert+1}] $idx
incr vert
incr idx
}
osg::DrawElementsUShort strip_$numStrips $::osg::PrimitiveSet_QUAD_STRIP \
[expr {$len+$len}] $indices
geom addPrimitiveSet strip_$numStrips
incr numStrips -1
}
return [geom get]
}
proc CreateSceneGraph {} {
global gDemo
# Create the root node and set state for the entire subgraph.
osg::GroupRef root [osg::Group]
set state [root getOrCreateStateSet]
$state setMode $::GL_LIGHTING $::osg::StateAttribute_ON
$state setMode $::GL_LIGHT0 $::osg::StateAttribute_ON
$state setMode $::GL_LIGHT1 $::osg::StateAttribute_ON
osg::Matrix m
# Represent the two light sources with a shared point.
# Each light's position is 0,0,0 in object coordinates. The
# two parent MatrixTransforms translate the lights, and the
# shared point, to their actual positions.
osg::Geode lightPoint [CreateLightPoint]
osg::MatrixTransform mt0
m makeTranslate [osg::Vec3 t0 -3.0 2.0 5.0]
mt0 setMatrix m
# Create a mostly red light
osg::Light light0
light0 setLightNum 0
light0 setPosition [osg::Vec4 pos0 0.0 0.0 0.0 1.0]
light0 setDiffuse [osg::Vec4 dif0 1.0 0.5 0.5 1.0]
light0 setSpecular [osg::Vec4 spe0 1.0 0.8 0.8 1.0]
osg::LightSource ls0
root addChild mt0
mt0 addChild ls0
ls0 setLight light0
ls0 addChild lightPoint
osg::MatrixTransform mt1
m makeTranslate [osg::Vec3 t1 3.0 -2.0 3.0]
mt1 setMatrix m
# Create a mostly blue light
osg::Light light1
light1 setLightNum 1
light1 setPosition [osg::Vec4 pos1 0.0 0.0 0.0 1.0]
light1 setDiffuse [osg::Vec4 dif1 0.5 0.5 1.0 1.0]
light1 setSpecular [osg::Vec4 spe1 0.8 0.8 1.0 1.0]
osg::LightSource ls1
root addChild mt1
mt1 addChild ls1
ls1 setLight light1
ls1 addChild lightPoint
# Create a single instance of the lozenge geometry (read from disk).
# Multiply parent it to six MatrixTransform nodes, each with their
# own StateSet to change the material properties of the lozenge.
set osgFile [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data" "lozenge.osg"]]
osg::NodeRef lozenge [osgDB::readNodeFile $osgFile]
if { ! [lozenge valid] } {
error "Unable to load data file. Exiting."
}
osg::MatrixTransform mt2
m makeTranslate [osg::Vec3 t2 -1.0 -1.0 1.0]
mt2 setMatrix m
set state [mt2 getOrCreateStateSet]
osg::Material mat2
mat2 setDiffuse $::osg::Material_FRONT [osg::Vec4 dif2 0.0 0.0 0.0 1.0]
mat2 setSpecular $::osg::Material_FRONT [osg::Vec4 spe2 1.0 1.0 1.0 1.0]
mat2 setShininess $::osg::Material_FRONT 128.0
$state setAttribute mat2 osg::StateAttribute_ON
mt2 addChild [lozenge get]
root addChild mt2
osg::MatrixTransform mt3
m makeTranslate [osg::Vec3 t3 1.0 -1.0 1.0]
mt3 setMatrix m
set state [mt3 getOrCreateStateSet]
osg::Material mat3
# Just use the object's primary color for ambient and
# diffuse (uses the OpenGL color material feature).
mat3 setColorMode $::osg::Material_AMBIENT_AND_DIFFUSE
$state setAttribute mat3 osg::StateAttribute_ON
mt3 addChild [lozenge get]
root addChild mt3
osg::MatrixTransform mt4
m makeTranslate [osg::Vec3 t4 -1.0 0.0 1.0]
mt4 setMatrix m
set state [mt4 getOrCreateStateSet]
osg::Material mat4
mat4 setDiffuse $::osg::Material_FRONT [osg::Vec4 dif4 0.4 0.3 0.0 1.0]
mat4 setSpecular $::osg::Material_FRONT [osg::Vec4 spe4 0.8 0.8 0.1 1.0]
mat4 setShininess $::osg::Material_FRONT 20.0
$state setAttribute mat4 osg::StateAttribute_ON
mt4 addChild [lozenge get]
root addChild mt4
osg::MatrixTransform mt5
m makeTranslate [osg::Vec3 t5 1.0 0.0 1.0]
mt5 setMatrix m
set state [mt5 getOrCreateStateSet]
osg::Material mat5
mat5 setDiffuse $::osg::Material_FRONT [osg::Vec4 dif5 0.1 0.2 0.5 1.0]
mat5 setSpecular $::osg::Material_FRONT [osg::Vec4 spe5 0.9 0.9 1.0 1.0]
mat5 setShininess $::osg::Material_FRONT 10.0
$state setAttribute mat5 osg::StateAttribute_ON
mt5 addChild [lozenge get]
root addChild mt5
osg::MatrixTransform mt6
m makeTranslate [osg::Vec3 t6 -1.0 1.0 1.0]
mt6 setMatrix m
set state [mt6 getOrCreateStateSet]
osg::Material mat6
mat6 setDiffuse $::osg::Material_FRONT [osg::Vec4 dif6 0.2 0.9 0.9 1.0]
mat6 setSpecular $::osg::Material_FRONT [osg::Vec4 spe6 1.0 1.0 1.0 1.0]
mat6 setShininess $::osg::Material_FRONT 96.0
$state setAttribute mat6 osg::StateAttribute_ON
mt6 addChild [lozenge get]
root addChild mt6
osg::MatrixTransform mt7
m makeTranslate [osg::Vec3 t7 1.0 1.0 1.0]
mt7 setMatrix m
set state [mt7 getOrCreateStateSet]
osg::Material mat7
mat7 setDiffuse $::osg::Material_FRONT [osg::Vec4 dif7 1.0 1.0 1.0 1.0]
mat7 setSpecular $::osg::Material_FRONT [osg::Vec4 spe7 0.0 0.0 0.0 1.0]
$state setAttribute mat7 osg::StateAttribute_ON
mt7 addChild [lozenge get]
root addChild mt7
osg::Geode planeGeode
planeGeode addDrawable [CreatePlane]
set state [planeGeode getOrCreateStateSet]
osg::Material mat8
mat8 setDiffuse $::osg::Material_FRONT [osg::Vec4 dif8 0.6 0.5 0.2 1.0]
mat8 setSpecular $::osg::Material_FRONT [osg::Vec4 spe8 0.4 0.4 0.4 1.0]
mat8 setShininess $::osg::Material_FRONT 128.0
$state setAttribute mat8 osg::StateAttribute_ON
osg::CullFace cf
$state setAttributeAndModes cf
root addChild planeGeode
return [root get]
}
# Create the viewer and set its scene data to our scene
# graph created above.
osgViewer::ViewerRef viewer [osgViewer::Viewer]
viewer setSceneData [CreateSceneGraph]
if { [viewer getSceneData] eq "NULL" } {
error "No scene data available"
}
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
}
|
