Demo MultiTextures

Demo 9 of 14 in category OsgHelp

Previous demo: poThumbs/Light.jpgLight
Next demo: poThumbs/Shapes.jpgShapes
MultiTextures.jpg
# MultiTextures.tcl
#
# Original C++ code by Peter Wraae Marino and Michael Bach Jensen.
# See www.osghelp.com for the original files.
#
# Modified for Tcl3D by Paul Obermeier 2010/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: OsgHelp tutorial MultiTextures"

    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 CreateQuad { vPos } {
    # create drawable geometry object
    osg::Geometry geo

    # add 4 vertices creating a quad
    osg::Vec3Array verts
    set v1 [osg::Vec3]
    set v2 [osg::Vec3]
    set v3 [osg::Vec3]
    set v4 [osg::Vec3]
    $v1 set 0 0 0
    $v2 set 1 0 0
    $v3 set 1 0 1
    $v4 set 0 0 1
    verts push [$vPos add $v1]
    verts push [$vPos add $v2]
    verts push [$vPos add $v3]
    verts push [$vPos add $v4]

    geo setVertexArray verts

    # create a primitive set
    osg::DrawElementsUInt primitiveSet $::osg::PrimitiveSet_QUADS 0
    primitiveSet push 3
    primitiveSet push 2
    primitiveSet push 1
    primitiveSet push 0
    geo addPrimitiveSet primitiveSet

    # create an arraw for texture coordinates
    osg::Vec2Array texCoords
    texCoords push [osg::Vec2 t1 0.0 0.0]
    texCoords push [osg::Vec2 t2 1.0 0.0]
    texCoords push [osg::Vec2 t3 1.0 1.0]
    texCoords push [osg::Vec2 t4 0.0 1.0]
    geo setTexCoordArray 0 texCoords
    geo setTexCoordArray 1 texCoords

    # create geometry node that will contain all our drawables
    osg::Geode geode
    geode addDrawable geo

    return geode
}

proc CreateScene {} {
    global gDemo

    osg::Group group

    # load texture of a pencil (contains alpha)
    osg::Texture2D texPencil
    set pencilFile [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data/pencil.tga"]]
    texPencil setImage [osgDB::readImageFile $pencilFile]

    # load texture of cracks (no alpha)
    osg::Texture2D texCracks
    set cracksFile [tcl3dGetExtFile [file join $gDemo(scriptDir) "Data/cracks.tga"]]
    texCracks setImage [osgDB::readImageFile $cracksFile]

    # create quad on left side
    set geode0 [CreateQuad [osg::Vec3 v0 -0.5 0 0]]
    group addChild $geode0
    set stateSet0 [$geode0 getOrCreateStateSet]
    $stateSet0 setMode $::GL_LIGHTING $::osg::StateAttribute_OFF
    $stateSet0 setMode $::GL_BLEND $::osg::StateAttribute_ON
    $stateSet0 setTextureAttributeAndModes 0 texPencil $::osg::StateAttribute_ON
    $stateSet0 setTextureAttributeAndModes 1 texCracks $::osg::StateAttribute_ON

    # add combiner, setup so it multiplies texture0 with texture1
    osg::TexEnvCombine texEnv0
    texEnv0 setCombine_RGB  $::osg::TexEnvCombine_MODULATE
    texEnv0 setSource0_RGB  $::osg::TexEnvCombine_TEXTURE0
    texEnv0 setOperand0_RGB $::osg::TexEnvCombine_SRC_COLOR
    texEnv0 setSource1_RGB  $::osg::TexEnvCombine_TEXTURE1
    texEnv0 setOperand1_RGB $::osg::TexEnvCombine_SRC_COLOR
    $stateSet0 setTextureAttribute 1 texEnv0

    # create quad on right side
    set geode1 [CreateQuad [osg::Vec3 v1 0.5 0 0]]
    group addChild $geode1
    set stateSet1 [$geode1 getOrCreateStateSet]
    $stateSet1 setMode $::GL_LIGHTING $::osg::StateAttribute_OFF
    $stateSet1 setMode $::GL_BLEND $::osg::StateAttribute_ON
    $stateSet1 setTextureAttributeAndModes 0 texPencil $::osg::StateAttribute_ON
    $stateSet1 setTextureAttributeAndModes 1 texCracks $::osg::StateAttribute_ON

    # add combiner, setup so we draw texture1 (cracks)
    # and invert the alpha in texture0 (pencil) 
    osg::TexEnvCombine texEnv1
    texEnv1 setCombine_RGB    $::osg::TexEnvCombine_REPLACE
    texEnv1 setSource0_RGB    $::osg::TexEnvCombine_TEXTURE1
    texEnv1 setOperand0_RGB   $::osg::TexEnvCombine_SRC_COLOR
    texEnv1 setCombine_Alpha  $::osg::TexEnvCombine_MODULATE
    texEnv1 setSource1_Alpha  $::osg::TexEnvCombine_TEXTURE0
    texEnv1 setOperand1_Alpha $::osg::TexEnvCombine_ONE_MINUS_SRC_ALPHA
    $stateSet1 setTextureAttribute 1 texEnv1

    return group
}

# We have the geometry ready. Now create the viewer and the Tk widgets.
osgViewer::ViewerRef viewer [osgViewer::Viewer]

# set the scene-graph data the viewer will render
viewer setSceneData [CreateScene]

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
}

Top of page