4 Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
6 This file is part of libc3.
8 libc3 is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 libc3 is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with libc3. If not, see <http://www.gnu.org/licenses/>.
23 #include "c3arcball.h"
26 /**************************************** c3arcball_init_mat4() ****/
27 /* Takes as argument a c3mat4 to use instead of the internal rot */
39 /**************************************** c3arcball_init_center() ****/
40 /* A constructor that accepts the screen center and arcball radius*/
43 c3arcball_init_center(
49 c3arcball_set_params(a, center, radius);
53 /************************************** c3arcball_set_params() ****/
65 /*************************************** c3arcball_init() **********/
71 a->center = c3vec2f( 0.0, 0.0 );
73 a->q_now = c3quat_identity();
75 a->rot = identity3D();
76 a->q_increment = c3quat_identity();
77 a->rot_increment = identity3D();
78 a->is_mouse_down = false;
79 a->is_spinning = false;
81 a->zero_increment = true;
84 /*********************************** c3arcball_mouse_to_sphere() ****/
87 c3arcball_mouse_to_sphere(
92 c3vec2 v2 = c3vec2_divf(c3vec2_sub(p, a->center), a->radius);
93 c3vec3 v3 = c3vec3f( v2.n[0], v2.n[1], 0.0 );
95 mag = c3vec2_dot(v2, v2);
98 v3 = c3vec3_normalize(v3);
100 v3.n[VZ] = (c3f) sqrt( 1.0 - mag );
102 /* Now we add constraints - X takes precedence over Y */
103 if ( a->constraint_x ) {
104 v3 = c3arcball_constrain_vector( v3, c3vec3f( 1.0, 0.0, 0.0 ));
105 } else if ( a->constraint_y ) {
106 v3 = c3arcball_constrain_vector( v3, c3vec3f( 0.0, 1.0, 0.0 ));
113 /************************************ c3arcball_constrain_vector() ****/
116 c3arcball_constrain_vector(
120 // return (vector - (vector * axis) * axis).normalize();
124 /************************************ c3arcball_mouse_down() **********/
127 c3arcball_mouse_down(
132 a->down_pt = c3vec2f( (c3f)x, (c3f) y );
133 a->is_mouse_down = true;
135 a->q_increment = c3quat_identity();
136 a->rot_increment = identity3D();
137 a->zero_increment = true;
141 /************************************ c3arcball_mouse_up() **********/
147 a->q_now = c3quat_mul(a->q_drag, a->q_now);
148 a->is_mouse_down = false;
152 /********************************** c3arcball_mouse_motion() **********/
155 c3arcball_mouse_motion(
163 /* Set the X constraint if CONTROL key is pressed, Y if ALT key */
164 c3arcball_set_constraints(a, ctrl != 0, alt != 0 );
166 c3vec2 new_pt = c3vec2f( (c3f)x, (c3f) y );
167 c3vec3 v0 = c3arcball_mouse_to_sphere(a, a->down_pt );
168 c3vec3 v1 = c3arcball_mouse_to_sphere(a, new_pt );
170 c3vec3 cross = c3vec3_cross(v0, v1);
172 a->q_drag = c3quat_vec3(cross, c3vec3_dot(v0, v1));
174 // *rot_ptr = (q_drag * q_now).to_mat4();
175 c3mat4 temp = c3quat_to_mat4(a->q_drag);
176 *a->rot_ptr = c3mat4_mul(a->rot_ptr, &temp);
180 /* We keep a copy of the current incremental rotation (= q_drag) */
181 a->q_increment = a->q_drag;
182 a->rot_increment = c3quat_to_mat4(a->q_increment);
184 c3arcball_set_constraints(a, false, false);
186 if (a->q_increment.s < .999999) {
187 a->is_spinning = true;
188 a->zero_increment = false;
190 a->is_spinning = false;
191 a->zero_increment = true;
196 /********************************** c3arcball_mouse_motion() **********/
199 c3arcball_mouse_motion(
204 mouse_motion(x, y, 0, 0, 0);
208 /***************************** c3arcball_set_constraints() **********/
211 c3arcball_set_constraints(
216 a->constraint_x = _constraint_x;
217 a->constraint_y = _constraint_y;
220 /***************************** c3arcball_idle() *********************/
226 if (a->is_mouse_down) {
227 a->is_spinning = false;
228 a->zero_increment = true;
231 if (a->damp_factor < 1.0f)
232 c3quat_scale_angle(&a->q_increment, 1.0f - a->damp_factor);
234 a->rot_increment = c3quat_to_mat4(a->q_increment);
236 if (a->q_increment.s >= .999999f) {
237 a->is_spinning = false;
238 a->zero_increment = true;
243 /************************ c3arcball_set_damping() *********************/
246 c3arcball_set_damping(