OUTPUT BUFFER:
# Copyright: 2006-2010 Paul Obermeier (obermeier@tcl3d.org) # # See the file "Tcl3D_License.txt" for information on # usage and redistribution of this file, and for a # DISCLAIMER OF ALL WARRANTIES. # # Module: Tcl3D -> tcl3dOde # Filename: odeJoints.tcl # # Author: Paul Obermeier # # Description: Tcl3D Ode example: Connected bodies with joints # Based on PyODE Tutorial 2 By Matthias Baas. package require Tk package require tcl3d 0.5.0 set clk [tcl3dNewSwatch] set timer [tcl3dNewSwatch] if { [info procs tcl3dHaveOde] ne "" } { if { ![tcl3dHaveOde] } { tk_messageBox -icon error -type ok -title "Error" \ -message "You do not have ODE installed." exit } } # Show errors occuring in the Togl callbacks. proc bgerror { msg } { tk_messageBox -icon error -type ok -message "Error: $msg\n\n$::errorInfo" exit } # Print info message into widget a the bottom of the window. proc PrintInfo { msg } { if { [winfo exists .fr.info] } { .fr.info configure -text $msg } } proc Cleanup {} { .fr.toglwin delete $::l1 $::l2 $::c1 $::c2 } # Put all exit related code here. proc ExitProg {} { exit } proc coord { x y } { return [list [expr 320+170*$x] [expr 400-170*$y]] } proc circle { id x y r } { foreach { cx cy } [coord $x $y] break; .fr.toglwin coords $id \ [expr $cx-$r] [expr $cy-$r] \ [expr $cx+$r] [expr $cy+$r] } proc line { id x1 y1 x2 y2 } { foreach { cx1 cy1 } [coord $x1 $y1] break; foreach { cx2 cy2 } [coord $x2 $y2] break; .fr.toglwin coords $id $cx1 $cy1 $cx2 $cy2 } proc StartAnimation {} { global world if { [info exists ::animateId] } { return } set x1 1 set y1 2 set z1 0 set x2 2 set y2 2 set z2 0 # Create a world object set world [dWorldCreate] dWorldSetGravity $world 0 -9.81 0 # Create two bodies set body1 [dBodyCreate $world] set body2 [dBodyCreate $world] set M [new_dMass] dMassSetSphere $M 2500 0.05 dBodySetMass $body1 $M dBodySetPosition $body1 $x1 $y1 $z1 dBodySetMass $body2 $M dBodySetPosition $body2 $x2 $y2 $z2 set grp [dJointGroupCreate 0] # Connect body1 with the static environment set j1 [dJointCreateBall $world $grp] dJointAttach $j1 $body1 "NULL" dJointSetBallAnchor $j1 0 2 0 # Connect body2 with body1 set j2 [dJointCreateBall $world $grp] dJointAttach $j2 $body1 $body2 dJointSetBallAnchor $j2 1 2 0 set fps 50 set ::dt [expr 1.0 / $fps] tcl3dResetSwatch $::clk tcl3dResetSwatch $::timer tcl3dStartSwatch $::clk tcl3dStartSwatch $::timer set ::curFrame 1 animate $body1 $body2 } proc StopAnimation {} { if { [info exists ::animateId] } { after cancel $::animateId unset ::animateId } } proc animate { body1 body2 } { .fr.timing configure -text [format "Time: %6.1f sec (Frame %d)" \ [tcl3dLookupSwatch $::clk] $::curFrame] tcl3dResetSwatch $::timer set pos [dBodyGetPosition $body1] set x1 [dReal_getitem $pos 0] set y1 [dReal_getitem $pos 1] set z1 [dReal_getitem $pos 2] set pos [dBodyGetPosition $body2] set x2 [dReal_getitem $pos 0] set y2 [dReal_getitem $pos 1] set z2 [dReal_getitem $pos 2] line $::l1 0 2 $x1 $y1 line $::l2 $x1 $y1 $x2 $y2 circle $::c1 $x1 $y1 20 circle $::c2 $x2 $y2 20 dWorldStep $::world $::dt while { [tcl3dLookupSwatch $::timer] < $::dt } { update idletasks } incr ::curFrame set ::animateId [tcl3dAfterIdle "animate $body1 $body2"] } # Master frame. Needed to integrate demo into Tcl3D Starpack presentation. frame .fr pack .fr -expand 1 -fill both canvas .fr.toglwin -width 640 -height 480 -bg white label .fr.timing -background green label .fr.info grid .fr.toglwin -row 0 -column 0 -sticky news grid .fr.timing -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 # Watch For ESC Key And Quit Messages wm protocol . WM_DELETE_WINDOW "ExitProg" bind .