static void _control_camera(Game* G, float delta_time) { if(G->num_points == 1) { Vec2 curr = G->points[0].pos; Vec2 delta = vec2_sub(curr, G->prev_single); /* L-R rotation */ Quaternion q = quat_from_axis_anglef(0, 1, 0, delta_time*delta.x*0.2f); G->camera.orientation = quat_multiply(G->camera.orientation, q); /* U-D rotation */ q = quat_from_axis_anglef(1, 0, 0, delta_time*delta.y*0.2f); G->camera.orientation = quat_multiply(q, G->camera.orientation); G->prev_single = curr; } else if(G->num_points == 2) { float camera_speed = 0.1f; Vec3 look = quat_get_z_axis(G->camera.orientation); Vec3 right = quat_get_x_axis(G->camera.orientation); Vec2 avg = vec2_add(G->points[0].pos, G->points[1].pos); Vec2 delta; avg = vec2_mul_scalar(avg, 0.5f); delta = vec2_sub(avg, G->prev_double); look = vec3_mul_scalar(look, -delta.y*camera_speed); right = vec3_mul_scalar(right, delta.x*camera_speed); G->camera.position = vec3_add(G->camera.position, look); G->camera.position = vec3_add(G->camera.position, right); G->prev_double = avg; } }
static void camOrbit(int dx, int dy) { const double radius = 200; double dist; Vec3 v = cam_position; Quaternion o = cam_orientation; Quaternion q, q2; /* We invert the transformation because we are transforming the camera * and not the scene. */ q = quat_conjugate(quat_trackball(dx, dy, radius)); /* The quaternion q gives us an intrinsic transformation, close to unity. * To make it extrinsic, we compute q2 = o * q * ~o */ q2 = quat_multiply(o, quat_multiply(q, quat_conjugate(o))); q2 = quat_normalize(q2); /* As round-off errors accumulate, the distance between the camera and the * target would normally fluctuate. We take steps to prevent that here. */ dist = vec3_length(v); v = quat_transform(q2, v); v = vec3_normalize(v); v = vec3_scale(v, dist); cam_position = v; cam_orientation = quat_multiply(q2, cam_orientation); }
void position_rotateOnMouseInput (Entity e, const struct input_event * ie) { POSITION pdata = NULL; QUAT q; float mag, newPitch; int sq, xrel, yrel; if (ie->event->type != SDL_MOUSEMOTION) return; pdata = component_getData (entity_getAs (e, "position")); if (pdata == NULL) return; xrel = ie->event->motion.xrel; yrel = ie->event->motion.yrel; sq = xrel * xrel + yrel * yrel; if (sq > 2500) { mag = 50.0 / sqrt (sq); xrel *= mag; yrel *= mag; return; } // we manually recalculate the one orientation axis value (front y component) we care about right here, instead of updating every single one newPitch = (pdata->orientation.y * pdata->orientation.z + pdata->orientation.w * pdata->orientation.x) * 180.0; newPitch += yrel * pdata->sensitivity; //printf ("front: %7.3f, %7.3f, %7.3f\n", pdata->view.front.x, pdata->view.front.y, pdata->view.front.z); //printf ("pitch: %7.3f\n", newPitch); if (newPitch < 90.0 && newPitch > -90.0) { // pitch relative to the object's axes q = quat_eulerToQuat ( yrel * pdata->sensitivity, 0, 0 ); pdata->orientation = quat_multiply (&q, &pdata->orientation); } // (roll would also be relative to the world axis, if it's ever added) // heading relative to the world's axes q = quat_eulerToQuat ( 0, xrel * pdata->sensitivity, 0 ); pdata->orientation = quat_multiply (&pdata->orientation, &q); pdata->dirty = true; entity_speak (e, "orientationUpdate", NULL); //printf ("view quat: %7.2f, %7.2f, %7.2f, %7.2f\n", cdata->viewQuat.w, cdata->viewQuat.x, cdata->viewQuat.y, cdata->viewQuat.z); }
void position_face (Entity e, const VECTOR3 * face) { POSITION pos = component_getData (entity_getAs (e, "position")); float faceRot = atan2 (face->z, face->x), currentRot = position_getHeading (e), faceAngle; QUAT q; if (!pos) return; faceAngle = (faceRot - currentRot); faceAngle = faceAngle * (180.0 / M_PI); //printf ("face angle used: %f\n", faceAngle); q = quat_eulerToQuat (0, faceAngle, 0); //printf ("rotation: (%f; %f) %.2f, %.2f, %.2f, %.2f\n", faceRot, currentRot, q.x, q.y, q.z, q.w); pos->orientation = quat_multiply (&pos->orientation, &q); pos->dirty = true; entity_speak (e, "orientationUpdate", NULL); }
void jedi_processInput_RotationSpeed(double speed[3], uint32_t gyro_time) { // if (!global_quat) // jedi_initQuat(); if (fabs(speed[0]) > GYRO_THRESHOLD) speed[0] *= 0.07 * gyro_time / 10000.0; else speed[0] = 0.0; if (fabs(speed[1]) > GYRO_THRESHOLD) speed[1] *= 0.07 * gyro_time / 10000.0; else speed[1] = 0.0; if (fabs(speed[2]) > GYRO_THRESHOLD) speed[2] *= 0.07 * gyro_time / 10000.0; else speed[2] = 0.0; quat *local = quat_fromAngles(speed); global_quat = *quat_normalize(quat_multiply(&global_quat, local)); free(local); // fprintf(stderr, "global_quat %3.2f %3.2f %3.2f %3.2f\n", global_quat.W, // global_quat.X, global_quat.Y, global_quat.Z); }