shell bypass 403
###################################################
#
# ArcBall.pm
#
# From Graphics Gems IV.
#
# This is an example of the controller class:
# the routines set_wh and mouse_moved are the standard routines.
#
# This needs a faster implementation (?)
package PDL::Graphics::TriD::QuaterController;
use base qw(PDL::Graphics::TriD::ButtonControl);
use fields qw /Inv Quat/;
sub new {
my($type,$win,$inv,$quat) = @_;
my $this = $type->SUPER::new($win);
$this->{Inv} = $inv;
$this->{Quat} = (defined($quat) ? $quat :
new PDL::Graphics::TriD::Quaternion(1,0,0,0));
$win->add_resizecommand(sub {$this->set_wh(@_)});
return $this;
}
sub xy2qua {
my($this,$x,$y) = @_;
$x -= $this->{W}/2; $y -= $this->{H}/2;
$x /= $this->{SC}; $y /= $this->{SC};
$y = -$y;
return $this->normxy2qua($x,$y);
}
sub mouse_moved {
my($this,$x0,$y0,$x1,$y1) = @_;
# Copy the size of the owning viewport to our size, in case it changed...
$this->{H} = $this->{Win}->{H};
$this->{W} = $this->{Win}->{W};
if($PDL::Graphics::TriD::verbose) {
print "QuaterController: mouse-moved: $this: $x0,$y0,$x1,$y1,$this->{W},$this->{H},$this->{SC}\n" if($PDL::Graphics::TriD::verbose);
if($PDL::Graphics::TriD::verbose > 1) {
print "\tthis is:\n";
foreach my $k(sort keys %$this) {
print "\t$k\t=>\t$this->{$k}\n";
}
}
}
# Convert both to quaternions.
my ($qua0,$qua1) = ($this->xy2qua($x0,$y0),$this->xy2qua($x1,$y1));
# print "ARCBALLQ: ",(join ', ',@$qua0)," ",(join ', ',@$qua1),"\n";
my $arc = $qua1->multiply($qua0->invert());
# my $arc = $qua0->invert()->multiply($qua1);
if($this->{Inv}) {
$arc->invert_rotation_this();
}
$this->{Quat}->set($arc->multiply($this->{Quat}));
# print "ARCBALLQ: ",(join ', ',@$arc)," ",(join ', ',@{$this->{Quat}}),"\n";
# $this->{Quat}->set($this->{Quat}->multiply($arc));
1; # signals a refresh
}
#
# Original ArcBall
#
package PDL::Graphics::TriD::ArcBall;
use base qw/PDL::Graphics::TriD::QuaterController/;
# x,y to unit quaternion on the sphere.
sub normxy2qua {
my($this,$x,$y) = @_;
my $dist = sqrt ($x ** 2 + $y ** 2);
if($dist > 1.0) {$x /= $dist; $y /= $dist; $dist = 1.0;}
my $z = sqrt(1-$dist**2);
return PDL::Graphics::TriD::Quaternion->new(0,$x,$y,$z);
}
# Tjl's version: a cone - more even change of
package PDL::Graphics::TriD::ArcCone;
use base qw/PDL::Graphics::TriD::QuaterController/;
# x,y to unit quaternion on the sphere.
sub normxy2qua {
my($this,$x,$y) = @_;
my $dist = sqrt ($x ** 2 + $y ** 2);
if($dist > 1.0) {$x /= $dist; $y /= $dist; $dist = 1.0;}
my $z = 1-$dist;
my $qua = PDL::Graphics::TriD::Quaternion->new(0,$x,$y,$z);
$qua->normalize_this();
return $qua;
}
# Tjl's version2: a bowl -- angle is proportional to displacement.
package PDL::Graphics::TriD::ArcBowl;
use base qw/PDL::Graphics::TriD::QuaterController/;
# x,y to unit quaternion on the sphere.
sub normxy2qua {
my($this,$x,$y) = @_;
my $dist = sqrt ($x ** 2 + $y ** 2);
if($dist > 1.0) {$x /= $dist; $y /= $dist; $dist = 1.0;}
my $z = cos($dist*3.142/2);
my $qua = PDL::Graphics::TriD::Quaternion->new(0,$x,$y,$z);
$qua->normalize_this();
return $qua;
}
1;