Add some comments to OpenGL code

This commit is contained in:
Alessandro Ranellucci 2013-07-01 12:23:44 +02:00
parent 8ec3ec6bda
commit 63ba894260

View File

@ -15,6 +15,8 @@ __PACKAGE__->mk_accessors( qw(quat dirty init mview_init
mesh_center mesh_size mesh_center mesh_size
verts norms initpos) ); verts norms initpos) );
use constant TRACKBALLSIZE => 0.8;
sub new { sub new {
my ($class, $parent, $mesh) = @_; my ($class, $parent, $mesh) = @_;
my $self = $class->SUPER::new($parent); my $self = $class->SUPER::new($parent);
@ -71,6 +73,7 @@ sub new {
return $self; return $self;
} }
# Given an axis and angle, compute quaternion.
sub axis_to_quat { sub axis_to_quat {
my ($ax, $phi) = @_; my ($ax, $phi) = @_;
@ -81,13 +84,16 @@ sub axis_to_quat {
return @q; return @q;
} }
# Project a point on the virtual trackball.
# If it is inside the sphere, map it to the sphere, if it outside map it
# to a hyperbola.
sub project_to_sphere { sub project_to_sphere {
my ($r, $x, $y) = @_; my ($r, $x, $y) = @_;
my $d = sqrt($x * $x + $y * $y); my $d = sqrt($x * $x + $y * $y);
if ($d < $r * 0.70710678118654752440) { if ($d < $r * 0.70710678118654752440) { # Inside sphere
return sqrt($r * $r - $d * $d); return sqrt($r * $r - $d * $d);
} else { } else { # On hyperbola
my $t = $r / 1.41421356237309504880; my $t = $r / 1.41421356237309504880;
return $t * $t / $d; return $t * $t / $d;
} }
@ -101,20 +107,34 @@ sub cross {
@$v1[0] * @$v2[1] - @$v1[1] * @$v2[0]); @$v1[0] * @$v2[1] - @$v1[1] * @$v2[0]);
} }
# Simulate a track-ball. Project the points onto the virtual trackball,
# then figure out the axis of rotation, which is the cross product of
# P1 P2 and O P1 (O is the center of the ball, 0,0,0) Note: This is a
# deformed trackball-- is a trackball in the center, but is deformed
# into a hyperbolic sheet of rotation away from the center.
# It is assumed that the arguments to this routine are in the range
# (-1.0 ... 1.0).
sub trackball { sub trackball {
my ($p1x, $p1y, $p2x, $p2y, $r) = @_; my ($p1x, $p1y, $p2x, $p2y) = @_;
if ($p1x == $p2x && $p1y == $p2y) { if ($p1x == $p2x && $p1y == $p2y) {
return (0.0, 0.0, 0.0, 1.0); # zero rotation
return (0.0, 0.0, 0.0, 1.0);
} }
my @p1 = ($p1x, $p1y, project_to_sphere($r, $p1x, $p1y)); # First, figure out z-coordinates for projection of P1 and P2 to
my @p2 = ($p2x, $p2y, project_to_sphere($r, $p2x, $p2y)); # deformed sphere
my @p1 = ($p1x, $p1y, project_to_sphere(TRACKBALLSIZE, $p1x, $p1y));
my @p2 = ($p2x, $p2y, project_to_sphere(TRACKBALLSIZE, $p2x, $p2y));
# axis of rotation (cross product of P1 and P2)
my @a = cross(\@p2, \@p1); my @a = cross(\@p2, \@p1);
# Figure out how much to rotate around that axis.
my @d = map { $_ * $_ } (map { $p1[$_] - $p2[$_] } 0 .. $#p1); my @d = map { $_ * $_ } (map { $p1[$_] - $p2[$_] } 0 .. $#p1);
my $t = sqrt(reduce { $a + $b } @d) / (2.0 * $r); my $t = sqrt(reduce { $a + $b } @d) / (2.0 * TRACKBALLSIZE);
# Avoid problems with out-of-control values...
$t = 1.0 if ($t > 1.0); $t = 1.0 if ($t > 1.0);
$t = -1.0 if ($t < -1.0); $t = -1.0 if ($t < -1.0);
my $phi = 2.0 * asin($t); my $phi = 2.0 * asin($t);
@ -122,6 +142,7 @@ sub trackball {
return axis_to_quat(\@a, $phi); return axis_to_quat(\@a, $phi);
} }
# Build a rotation matrix, given a quaternion rotation.
sub quat_to_rotmatrix { sub quat_to_rotmatrix {
my ($q) = @_; my ($q) = @_;
@ -172,7 +193,7 @@ sub handle_rotation {
1 - $orig->y / ($size->height / 2), #/ 1 - $orig->y / ($size->height / 2), #/
$new->x / ($size->width / 2) - 1, $new->x / ($size->width / 2) - 1,
1 - $new->y / ($size->height / 2), #/ 1 - $new->y / ($size->height / 2), #/
0.8); );
$self->quat(mulquats($self->quat, \@quat)); $self->quat(mulquats($self->quat, \@quat));
$self->initpos($new); $self->initpos($new);
$self->Refresh; $self->Refresh;