1 #ifndef ARCBALL_CAMERA_H
2 #define ARCBALL_CAMERA_H
9 #define ARCBALL_CAMERA_LEFT_HANDED_BIT 1
46 float delta_time_seconds,
49 float rotation_multiplier,
50 int screen_width,
int screen_height,
55 int delta_scroll_ticks,
70 #endif // ARCBALL_CAMERA_H
72 #ifdef ARCBALL_CAMERA_IMPLEMENTATION
86 float delta_time_seconds,
89 float rotation_multiplier,
90 int screen_width,
int screen_height,
95 int delta_scroll_ticks,
100 float up_len = sqrtf(up[0] * up[0] + up[1] * up[1] + up[2] * up[2]);
101 assert(fabsf(up_len - 1.0
f) < 0.000001
f);
103 float to_target[3] = {
108 float to_target_len = sqrtf(to_target[0] * to_target[0] + to_target[1] * to_target[1] + to_target[2] * to_target[2]);
115 float x0 = (float)(px_x0 - screen_width / 2);
116 float x1 = (float)(px_x1 - screen_width / 2);
117 float y0 = (float)((screen_height - px_y0 - 1) - screen_height / 2);
118 float y1 = (float)((screen_height - px_y1 - 1) - screen_height / 2);
119 float arcball_radius = (float)(screen_width > screen_height ? screen_width : screen_height);
122 float dist0 = sqrtf(
x0 *
x0 +
y0 *
y0);
123 float dist1 = sqrtf(
x1 *
x1 +
y1 *
y1);
126 if (dist0 > arcball_radius)
134 z0 = sqrtf(arcball_radius * arcball_radius -
x0 *
x0 -
y0 *
y0);
138 if (dist1 > arcball_radius)
141 x1 = (
x1 / dist1) * arcball_radius;
142 y1 = (
y1 / dist1) * arcball_radius;
143 dist1 = arcball_radius;
149 z1 = sqrtf(arcball_radius * arcball_radius -
x1 *
x1 -
y1 *
y1);
154 float to_eye_unorm[3] = {
159 float to_eye_len = sqrtf(to_eye_unorm[0] * to_eye_unorm[0] + to_eye_unorm[1] * to_eye_unorm[1] + to_eye_unorm[2] * to_eye_unorm[2]);
161 to_eye_unorm[0] / to_eye_len,
162 to_eye_unorm[1] / to_eye_len,
163 to_eye_unorm[2] / to_eye_len
167 -(to_eye[1] * up[2] - to_eye[2] * up[1]),
168 -(to_eye[2] * up[0] - to_eye[0] * up[2]),
169 -(to_eye[0] * up[1] - to_eye[1] * up[0])
174 across[0], across[1], across[2],
176 to_eye[0], to_eye[1], to_eye[2]
180 eye_m[0] *
x0 + eye_m[3] *
y0 + eye_m[6] * z0,
181 eye_m[1] *
x0 + eye_m[4] *
y0 + eye_m[7] * z0,
182 eye_m[2] *
x0 + eye_m[5] *
y0 + eye_m[8] * z0,
186 eye_m[0] *
x1 + eye_m[3] *
y1 + eye_m[6] * z1,
187 eye_m[1] *
x1 + eye_m[4] *
y1 + eye_m[7] * z1,
188 eye_m[2] *
x1 + eye_m[5] *
y1 + eye_m[8] * z1,
201 float qw, qx, qy, qz;
203 float norm_u_norm_v = sqrtf((
x0 *
x0 +
y0 *
y0 + z0 * z0) * (
x1 *
x1 +
y1 *
y1 + z1 * z1));
204 qw = norm_u_norm_v + (
x0 *
x1 +
y0 *
y1 + z0 * z1);
206 if (qw < 1.
e-6
f * norm_u_norm_v)
212 if (fabsf(
x0) > fabsf(z0))
228 qx =
y0 * z1 - z0 *
y1;
229 qy = z0 *
x1 -
x0 * z1;
233 float q_len = sqrtf(qx * qx + qy * qy + qz * qz + qw * qw);
249 qx = rotation_multiplier * qx;
250 qy = rotation_multiplier * qy;
251 qz = rotation_multiplier * qz;
252 qw = 1.0f + rotation_multiplier * (qw - 1.0f);
253 float q_len = sqrtf(qx * qx + qy * qy + qz * qz + qw * qw);
267 float theta_0 = acosf(
c);
269 float theta = theta_0 * rotation_multiplier;
276 float q2_len = sqrtf(qx2 * qx2 + qy2 * qy2 + qz2 * qz2 + qw2 * qw2);
283 qx = qx2 * sinf(theta);
284 qy = qy2 * sinf(theta);
285 qz = qz2 * sinf(theta);
286 qw = cosf(theta) + qw2 * sinf(theta);
291 float to_eye[3] = { eye[0] - target[0], eye[1] - target[1], eye[2] - target[2] };
295 (1.0f - 2.0f * qy * qy - 2.0f * qz * qz), 2.0
f * (qx * qy + qw * qz), 2.0f * (qx * qz - qw * qy),
296 2.0
f * (qx * qy - qw * qz), (1.0f - 2.0f * qx * qx - 2.0f * qz * qz), 2.0
f * (qy * qz + qw * qx),
297 2.0f * (qx * qz + qw * qy), 2.0
f * (qy * qz - qw * qx), (1.0f - 2.0f * qx * qx - 2.0f * qy * qy)
302 to_eye[0] * qmat[0] + to_eye[1] * qmat[1] + to_eye[2] * qmat[2],
303 to_eye[0] * qmat[3] + to_eye[1] * qmat[4] + to_eye[2] * qmat[5],
304 to_eye[0] * qmat[6] + to_eye[1] * qmat[7] + to_eye[2] * qmat[8]
309 up[0] * qmat[0] + up[1] * qmat[1] + up[2] * qmat[2],
310 up[0] * qmat[3] + up[1] * qmat[4] + up[2] * qmat[5],
311 up[0] * qmat[6] + up[1] * qmat[7] + up[2] * qmat[8]
314 float up2_len = sqrtf(up2[0] * up2[0] + up2[1] * up2[1] + up2[2] * up2[2]);
320 eye[0] = target[0] + to_eye2[0];
321 eye[1] = target[1] + to_eye2[1];
322 eye[2] = target[2] + to_eye2[2];
334 int dx = -(px_x0 - px_x1);
335 int dy = (px_y0 - px_y1);
337 float to_eye_unorm[3] = {
342 float to_eye_len = sqrtf(to_eye_unorm[0] * to_eye_unorm[0] + to_eye_unorm[1] * to_eye_unorm[1] + to_eye_unorm[2] * to_eye_unorm[2]);
344 to_eye_unorm[0] / to_eye_len,
345 to_eye_unorm[1] / to_eye_len,
346 to_eye_unorm[2] / to_eye_len
350 -(to_eye[1] * up[2] - to_eye[2] * up[1]),
351 -(to_eye[2] * up[0] - to_eye[0] * up[2]),
352 -(to_eye[0] * up[1] - to_eye[1] * up[0])
355 float pan_delta[3] = {
356 delta_time_seconds * pan_speed * (dx * across[0] + dy * up[0]),
357 delta_time_seconds * pan_speed * (dx * across[1] + dy * up[1]),
358 delta_time_seconds * pan_speed * (dx * across[2] + dy * up[2]),
361 eye[0] += pan_delta[0];
362 eye[1] += pan_delta[1];
363 eye[2] += pan_delta[2];
365 target[0] += pan_delta[0];
366 target[1] += pan_delta[1];
367 target[2] += pan_delta[2];
371 float zoom_dist = zoom_per_tick * delta_scroll_ticks;
374 float to_target[3] = {
380 float to_target_len = sqrtf(to_target[0] * to_target[0] + to_target[1] * to_target[1] + to_target[2] * to_target[2]);
385 if (zoom_dist >= to_target_len - 0.00001
f)
387 zoom_dist = to_target_len - 0.00001f;
393 to_target[0] / to_target_len,
394 to_target[1] / to_target_len,
395 to_target[2] / to_target_len,
398 float eye_zoom[3] = {
404 eye[0] += eye_zoom[0];
405 eye[1] += eye_zoom[1];
406 eye[2] += eye_zoom[2];
412 target[0] += eye_zoom[0];
413 target[1] += eye_zoom[1];
414 target[2] += eye_zoom[2];
430 float look_len = sqrtf(look[0] * look[0] + look[1] * look[1] + look[2] * look[2]);
431 float up_len = sqrtf(up[0] * up[0] + up[1] * up[1] + up[2] * up[2]);
433 assert(fabsf(look_len - 1.0
f) < 0.000001
f);
434 assert(fabsf(up_len - 1.0
f) < 0.000001
f);
437 float up_norm[3] = { up[0] / up_len, up[1] / up_len, up[2] / up_len };
440 float f[3] = { look[0] / look_len, look[1] / look_len, look[2] / look_len };
444 f[1] * up_norm[2] -
f[2] * up_norm[1],
445 f[2] * up_norm[0] -
f[0] * up_norm[2],
446 f[0] * up_norm[1] -
f[1] * up_norm[0]
448 float s_len = sqrtf(
s[0] *
s[0] +
s[1] *
s[1] +
s[2] *
s[2]);
455 s[1] *
f[2] -
s[2] *
f[1],
456 s[2] *
f[0] -
s[0] *
f[2],
457 s[0] *
f[1] -
s[1] *
f[0]
459 float u_len = sqrtf(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
476 s[0] * -eye[0] +
s[1] * -eye[1] +
s[2] * -eye[2],
477 u[0] * -eye[0] + u[1] * -eye[1] + u[2] * -eye[2],
478 f[0] * -eye[0] +
f[1] * -eye[1] +
f[2] * -eye[2]
502 #endif // __cplusplus
504 #endif // ARCBALL_CAMERA_IMPLEMENTATION