MouseEngineLoop Actionscript
Table of contents | Previous document | Download MouseEngineLoop.as | SWF!T Homepage RCSfile: MouseEngineLoop.as,v Revision: 1.4 Date: 2003/01/29 16:40:19
Copyright 2003 Orgdot AS. All Rights Reserved. http://dev.swfit.com
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Generates several mouse xy values with delays and bounce. See MouseEngineInit for further information.
author Olaf Havnes
version Revision: 1.4 Date: 2003/01/29 16:40:19
since SWFIT1.0
NB Split this file in two - we don't need the camera all the time?
The old mouse position
old_x = x;
The real mouse x position
x = _x;
The change since last frame
c_x = x - old_x;
The delayed mouse x position
dl_x = (dl_x * dl + x) / (dl + 1);
The undelayed but clipped mouse x position
cl_x = x;
if (x < x_min) cl_x = x_min;
else if (x > x_max) cl_x = x_max;
The delayed and clipped mouse x position
dc_x = (dc_x * dl + cl_x) / (dl + 1);
The rubber mouse x uses the clipped and undelayed x
vx += ac * (cl_x - rb_x) - fr * vx;
rb_x += vx;
Store in _level0.
/:mouse_x = x;
/:mouse_int_x = int (x);
/:change_mouse_x = c_x;
/:change_mouse_int_x = int (c_x);
/:delay_mouse_x = dl_x;
/:delay_mouse_int_x = int (dl_x);
/:clip_mouse_x = cl_x;
/:clip_mouse_int_x = int (cl_x);
/:delay_clip_mouse_x = dc_x;
/:delay_clip_mouse_int_x = int (dc_x);
/:rubber_mouse_x = rb_x;
/:rubber_mouse_int_x = int (rb_x);
Repeat for y.
The old mouse position
old_y = y;
The real mouse y position
y = _y;
The change since last frame
c_y = y - old_y;
The delayed mouse y position
dl_y = (dl_y * dl + y) / (dl + 1);
The undelayed but clipped mouse y position
cl_y = y;
if (y < y_min) cl_y = y_min;
else if (y > y_max) cl_y = y_max;
The delayed and clipped mouse y position
dc_y = (dc_y * dl + cl_y) / (dl + 1);
The rubber mouse y uses the clipped and undelayed y
vy += ac * (cl_y - rb_y) - fr * vy;
rb_y += vy;
Store in _level0.
/:mouse_y = y;
/:mouse_int_y = int (y);
/:change_mouse_y = c_y;
/:change_mouse_int_y = int (c_y);
/:delay_mouse_y = dl_y;
/:delay_mouse_int_y = int (dl_y);
/:clip_mouse_y = cl_y;
/:clip_mouse_int_y = int (cl_y);
/:delay_clip_mouse_y = dc_y;
/:delay_clip_mouse_int_y = int (dc_y);
/:rubber_mouse_y = rb_y;
/:rubber_mouse_int_y = int (rb_y);
The camera model uses the delayed-clipped mouse values, producing values between - 1 and 1 for camera-position, reversing the sign for the y-values (+ is now up).
cam_x = dc_x / cw_2 + xwa;
cam_y = - dc_y / ch_2 + ywa;
pre-compute
cam_x2 = cam_x * cam_x;
cam_y2 = cam_y * cam_y;
cam_z2 = cam_len_sq - cam_x2 - cam_y2;
Iterate just once through Newton's method. I doubt anybody is able to move the
mouse quick enough to produce a significant error on this value, especially since
the camera uses the delayed mouse values.
cam_z = (cam_z + cam_z2 / cam_z) / 2;
Store in _level0.
/:camera_x = cam_x;
/:camera_y = cam_y;
/:camera_z = cam_z;
When we move the camera back plane, we might think of it as
a) rotate the "horizon unit line HUV" in the XZ plane around the Y-axis
b) rotate the "verizon unit line VUV " around the horizon line, so that
VUV is perpendicular to both HUV and the camera back plane
We look at HUV first. Rotating HUV in the XZ-plane:
HUV = (xh, 0, zh) and |HUV| = 1 gives us: zh * zh + xh * xh = 1
C.HUV = 0 gives us: xh * cam_x + zh * cam_z = 0
==> zh = - xh * cam_x / cam_z , and
==> xh * xh * (1 + cam_x * cam_x / cam_z * cam_z ) = 1
xh = (xh + cam_z2 / ((cam_z2 + cam_x2) * xh)) / 2;
zh = - xh * cam_x / cam_z;
yh = 0;
Then we look at VUV, remembering that:
VUV.HUV = 0, C.VUV = 0 and |VUV| = 1
See EOF for notes.
eq_0 = xh * cam_z - zh * cam_x;
eq_1 = yh * cam_z - zh * cam_y;
eq_2 = xh * cam_y - yh * cam_x;
eq_02 = eq_0 * eq_0;
One Newton iteration will do for the square root:
yv = ( yv + eq_02 / ((eq_02 + eq_1 * eq_1 + eq_2 * eq_2) * yv) ) / 2;
zv = - yv * eq_2 / eq_0;
xv = - yv * eq_1 / eq_0;
We get values for the camera roll from the mouse position on the screen.
The further out the mouse is, the more roll, the closer to one centered axis,
the less roll. We use the sign to adjust for quadrant.
cr = cr_2 * (cam_x2 + cam_y2) * cam_x * cam_y;
Store in _level0.
/:camera_roll = cr;
Look up a trig value:
cr_mult = int (cr * /:DEG_MULT);
if (cr_mult < 0) cr_mult += /:NUM_DEG;
cr_mult_cos = eval ("/:COS_" add cr_mult);
cr_mult_sin = eval ("/:SIN_" add cr_mult);
Then we return to the two vectors HUV and VUV from above. The two vectors in
the rotated crosshair can be represented as a sum of HUV and VUV:
huv_r = cos (R) * HUV + sin (R) * VUV, and
vuv_r = cos (R) * VUV - sin (R) * VUV:
Store in _level0.
/:huv_x = xh * cr_mult_cos + xv * cr_mult_sin;
/:huv_y = yh * cr_mult_cos + yv * cr_mult_sin;
/:huv_z = zh * cr_mult_cos + zv * cr_mult_sin;
/:vuv_x = xv * cr_mult_cos - xh * cr_mult_sin;
/:vuv_y = yv * cr_mult_cos - yh * cr_mult_sin;
/:vuv_z = zv * cr_mult_cos - zh * cr_mult_sin;
|
|