## ## VMD camera flight plugin 1.0 ## by John Stone ## ## package provide camflyer 1.0 namespace eval ::CamFly:: { namespace export cameramode namespace export getcamera namespace export setcamera namespace export drawcamera namespace export lookatsel namespace export lookatpos namespace export orientcameratopos namespace export orientcameratosel namespace export circledemoflight set camdir {0 0 -2} set campos {0 0 2} set camup {0 1 0} } proc ::CamFly::center_of_mass { selection } { # some error checking if {[$selection num] <= 0} { error "center_of_mass: needs a selection with atoms" } # set the center of mass to 0 set com [veczero] # set the total mass to 0 set mass 0 # [$selection get {x y z}] returns the coordinates {x y z} # [$selection get {mass}] returns the masses # so the following says "for each pair of {coordinates} and masses, # do the computation ..." foreach coord [$selection get {x y z}] m [$selection get mass] { # sum of the masses set mass [expr $mass + $m] # sum up the product of mass and coordinate set com [vecadd $com [vecscale $m $coord]] } # and scale by the inverse of the number of atoms if {$mass == 0} { error "center_of_mass: total mass is zero" } # The "1.0" can't be "1", since otherwise integer division is done return [vecscale [expr 1.0/$mass] $com] } proc ::CamFly::cameramode { mode } { set identityvpts { {{1.000000 0.000000 0.000000 0.000000} {0.000000 1.000000 0.000000 0.000000} {0.000000 0.000000 1.000000 0.000000} {0.000000 0.000000 0.000000 1.000000}} {{1.000000 0.000000 0.000000 0.000000} {0.000000 1.000000 0.000000 0.000000} {0.000000 0.000000 1.000000 0.000000} {0.000000 0.000000 0.000000 1.000000}} {{1.000000 0.000000 0.000000 0.000000} {0.000000 1.000000 0.000000 0.000000} {0.000000 0.000000 1.000000 0.000000} {0.000000 0.000000 0.000000 1.000000}} {{1.000000 0.000000 0.000000 0.000000} {0.000000 1.000000 0.000000 0.000000} {0.000000 0.000000 1.000000 0.000000} {0.000000 0.000000 0.000000 1.000000}} } if { $mode } { molinfo top set {center_matrix rotate_matrix scale_matrix global_matrix} $identityvpts # set clipping planes in units of angstroms display nearclip set 1 display farclip set 1000 } else { # reset to defaults display nearclip set 0.5 display farclip set 10 display eyepos { 0 0 2} display eyedir { 0 0 -2} display eyeup { 0 1 0} display resetview } } proc ::CamFly::lookatpos { newpos } { variable campos variable camdir set dir [vecsub $newpos $campos] set len [veclength $dir] if { $len >= 0.0001 } { set camdir [vecscale [expr 1 / $len] $dir] } else { set camdir $dir } } proc ::CamFly::lookatsel { selection } { variable campos variable camdir set camlookpos [center_of_mass $selection] set dir [vecsub $camlookpos $campos] set len [veclength $dir] if { $len >= 0.0001 } { set camdir [vecscale [expr 1 / $len] $dir] } else { set camdir $dir } } proc ::CamFly::getcamera { } { variable camdir variable campos variable camup set campos [display get eyepos]; set camdir [display get eyedir]; set camup [display get eyeup]; } proc ::CamFly::setcamera { } { variable camdir variable campos variable camup display eyepos $campos display eyedir $camdir display eyeup $camup } proc ::CamFly::drawcamera { } { variable campos variable camdir variable camup draw color blue draw sphere $campos radius 0.25 draw color green draw line $campos [vecadd $campos $camdir] draw color red draw line $campos [vecadd $campos $camup] } proc ::CamFly::orientcameratopos { targetpos position drawnonly } { variable campos variable camdir variable camup set campos $position lookatpos $targetpos if { $drawnonly } { drawcamera } else { setcamera } } proc ::CamFly::orientcameratosel { selection position drawnonly } { variable campos variable camdir variable camup set campos $position lookatsel $selection if { $drawnonly } { drawcamera } else { setcamera } } proc ::CamFly::circledemoflight { centerpos radius drawnonly } { set maxsteps 1440.0 for {set i 0} { $i < $maxsteps} { incr i 1 } { puts "i: $i" set len [expr $i / $maxsteps] set ang [expr 3.14159 * ($i / (180.0))] set x [expr $len * $radius * sin($ang)] set y [expr $len * $radius * cos($ang)] set circlepos [list $x 0 $y] set newpos [vecadd $centerpos $circlepos] # puts "campos: $newpos" orientcameratopos $centerpos $newpos $drawnonly display update ui # sleep 1 } }