void Arcball::init() { center.set( 0.0, 0.0 ); radius = 1.0; q_now = quat_identity(); *rot_ptr = identity3D(); q_increment = quat_identity(); rot_increment = identity3D(); is_mouse_down = false; is_spinning = false; damp_factor = 0.0; zero_increment = true; }
void quat_from_axis_angle(const Vec3f axis, const float angle, Quat q) { if( ( fabs(axis[0]) < CUTE_EPSILON && fabs(axis[1]) < CUTE_EPSILON && fabs(axis[2]) < CUTE_EPSILON ) || fabs(angle) < CUTE_EPSILON ) { quat_identity(q); } double normed_axis[3] = {0}; double norm = sqrt( axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2] ); normed_axis[0] = axis[0] / norm; normed_axis[1] = axis[1] / norm; normed_axis[2] = axis[2] / norm; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wconversion" #pragma warning(push) #pragma warning(disable : 4244) q[0] = normed_axis[0] * sin(angle/2.0); q[1] = normed_axis[1] * sin(angle/2.0); q[2] = normed_axis[2] * sin(angle/2.0); q[3] = cos(angle/2.0); #pragma warning(pop) #pragma GCC diagnostic pop }
static void simulate_trackball(quat *q, GLfloat p1x, GLfloat p1y, GLfloat p2x, GLfloat p2y) { if (p1x == p2x && p1y == p2y) { quat_identity(q); } else { quat p1, p2, a, d; float p1z, p2z; float s, t; p1z = project_to_sphere(p1x, p1y); quat_assign(&p1, 0.0, p1x, p1y, p1z); p2z = project_to_sphere(p2x, p2y); quat_assign(&p2, 0.0, p2x, p2y, p2z); quat_mul(&a, &p1, &p2); a.w = 0.0; s = quat_norm(&a); quat_div_real(&a, &a, s); quat_sub(&d, &p1, &p2); t = quat_norm(&d) / (2.0 * R * ROOT_2_INV); if (t > 1.0) t = 1.0; quat_assign(q, cos(asin(t)), a.x * t, a.y * t, a.z * t); } }
void Arcball::mouse_down(int x, int y) { down_pt.set( (float)x, (float) y ); is_mouse_down = true; q_increment = quat_identity(); rot_increment = identity3D(); zero_increment = true; }
void quat_from_vec_pair(const Vec3f a, const Vec3f b, Quat q) { Vec4f axis; vec_cross(a,b,axis); float angle; vec_angle(a,b,&angle); if( (fabs(axis[0]) < CUTE_EPSILON && fabs(axis[1]) < CUTE_EPSILON && fabs(axis[2]) < CUTE_EPSILON) || fabs(angle) < CUTE_EPSILON ) { quat_identity(q); } quat_from_axis_angle(axis, angle, q); }
quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm) { quat_t q; anm_time_t tm0 = animation_time(node, tm, 0); struct anm_animation *anim0 = anm_get_active_animation(node, 0); struct anm_animation *anim1 = anm_get_active_animation(node, 1); if(!anim0) { return quat_identity(); } q = get_node_rotation(node, tm0, anim0); if(anim1) { anm_time_t tm1 = animation_time(node, tm, 1); quat_t q1 = get_node_rotation(node, tm1, anim1); q = quat_slerp(q, q1, node->cur_mix); } return q; }
void ARX_INTERFACE_ManageOpenedBook_Finish(const Vec2f & mousePos, Rectf rect, float scale) { RenderState baseState = render3D().depthTest(false).fog(false); Vec3f pos = Vec3f(0.f, 0.f, 2100.f); EERIE_LIGHT * light = lightHandleGet(torchLightHandle); EERIE_LIGHT tl = *light; light->pos = Vec3f(500.f, -1960.f, 1590.f); light->m_exists = true; light->rgb = Color3f(0.6f, 0.7f, 0.9f); light->intensity = 1.8f; light->fallstart = 4520.f; light->fallend = light->fallstart + 600.f; RecalcLight(light); Camera * oldcam = g_camera; g_culledDynamicLights[0] = light; g_culledDynamicLightsCount = 1; Vec2i tmpPos(0); GRenderer->SetAntialiasing(true); float wave = timeWaveSin(g_platformTime.frameStart(), PlatformDurationMsf(1256.6370614f)); float ptDelta = toMs(g_platformTime.lastFrameDuration()); Camera bookcam; bookcam.angle = Anglef(); bookcam.m_pos = Vec3f(0.f); bookcam.focal = 500.f; bookcam.cdepth = 2200.f; for(size_t i = 0; i < RUNE_COUNT; i++) { if(!gui::necklace.runes[i]) continue; EERIE_3DOBJ * rune = gui::necklace.runes[i]; Vec2i projectionCenter = Vec2i(rect.topLeft() + (Vec2f(285, 36) + Vec2f(tmpPos) * Vec2f(45, 64)) * scale); PrepareCamera(&bookcam, Rect(rect), projectionCenter); if(player.hasRune((Rune)i)) { Anglef angle; if(rune->angle.getYaw() != 0.f) { if(rune->angle.getYaw() > 300.f) { rune->angle.setYaw(300.f); } angle.setYaw(wave * rune->angle.getYaw() * (1.0f / 40)); } rune->angle.setYaw(rune->angle.getYaw() - ptDelta * 0.2f); if(rune->angle.getYaw() < 0.f) rune->angle.setYaw(0.f); // Now draw the rune TransformInfo t2(pos, glm::quat_cast(toRotationMatrix(angle))); DrawEERIEInter(rune, t2, NULL, false, 0.f); Rectf runeBox = UpdateBbox2d(*rune).toRect(); PopAllTriangleListOpaque(baseState); tmpPos.x++; if(tmpPos.x > 4) { tmpPos.x = 0; tmpPos.y++; } // TODO this is a workaround for vertexClipPositions being relative to viewport Vec2f mousePosInViewport = mousePos - rect.topLeft(); // Checks for Mouse floating over a rune... if(runeBox.contains(mousePosInViewport)) { bool r = false; for(size_t j = 0; j < rune->facelist.size(); j++) { float n = PtIn2DPolyProj(rune->vertexClipPositions, &rune->facelist[j], mousePosInViewport.x, mousePosInViewport.y); if(n != 0.f) { r = true; break; } } if(r) { TransformInfo t(pos, glm::quat_cast(toRotationMatrix(angle))); DrawEERIEInter(rune, t, NULL, false, 0.f); rune->angle.setYaw(rune->angle.getYaw() + ptDelta * 2.f); PopAllTriangleListOpaque(baseState.blendAdditive()); cursorSetInteraction(); if(eeMouseDown1()) { PlayerBookDrawRune((Rune)i); } } } TransformInfo t1(pos, quat_identity()); DrawEERIEInter(gui::necklace.lacet, t1, NULL, false, 0.f); PopAllTriangleListOpaque(baseState); } } *light = tl; PrepareCamera(oldcam, g_size); GRenderer->SetAntialiasing(false); }
quat::quat() { *this = quat_identity(); }
quat::quat( void ) { *this = quat_identity(); }
int32_t pivot_lookat(struct Pivot* pivot, const Vec3f target) { int32_t result = -1; Vec4f right_axis = RIGHT_AXIS; Vec4f up_axis = UP_AXIS; Vec4f forward_axis = FORWARD_AXIS; struct Pivot world_pivot; pivot_combine(pivot->parent, pivot, &world_pivot); Vec4f target_direction; vec_sub(target, world_pivot.position, target_direction); float dot_yaw = vec_dot(target_direction, forward_axis); Quat rotation = {0}; if( fabs(dot_yaw + 1.0f) < CUTE_EPSILON ) { // vector a and b point exactly in the opposite direction, // so it is a 180 degrees turn around the up-axis Quat rotation = {0}; quat_from_axis_angle(up_axis, PI, rotation); quat_mul(world_pivot.orientation, rotation, rotation); } else if( fabs(dot_yaw - (1.0f)) < CUTE_EPSILON ) { // vector a and b point exactly in the same direction // so we return the identity quaternion quat_copy(world_pivot.orientation, rotation); } else { // - I look at the target by turning the pivot orientation using only // yaw and pitch movement // - I always rotate the pivot from its initial orientation (up and forward // basis vectors like initialized above), so this does not incrementally // advance the orientation quat_identity(rotation); // - to find the amount of yaw I project the target_direction into the // up_axis plane, resulting in up_projection which is a vector that // points from the up_axis plane to the tip of the target_direction Vec4f up_projection = {0}; vec_mul1f(up_axis, vec_dot(target_direction, up_axis), up_projection); // - so then by subtracting the up_projection from the target_direction, // I get a vector lying in the up_axis plane, pointing towards the target Vec4f yaw_direction = {0}; vec_sub(target_direction, up_projection, yaw_direction); // - angle between yaw_direction and forward_axis is the amount of yaw we // need to point the forward_axis toward the target float yaw = 0.0f; vec_angle(yaw_direction, forward_axis, &yaw); log_assert( ! isnan(yaw), "vec_angle(%f %f %f, %f %f %f, %f);\n", yaw_direction[0], yaw_direction[1], yaw_direction[2], forward_axis[0], forward_axis[1], forward_axis[2], yaw ); // - I have to compute the cross product between yaw_direction and // forward_axis and use the resulting yaw_axis Vec4f yaw_axis = {0}; vec_cross(yaw_direction, forward_axis, yaw_axis); if( vec_nullp(yaw_axis) ) { vec_copy4f(up_axis, yaw_axis); } // - compute the yaw rotation Quat yaw_rotation = {0}; quat_from_axis_angle(yaw_axis, yaw, yaw_rotation); // - to compute, just as with the yaw, I want an axis that lies on the plane that // is spanned in this case by the right_axis, when the camera points toward the // target // - I could compute an axis, but I already have a direction vector that points // toward the target, the yaw_direction, I just have to normalize it to make it // an axis (and put the result in forward_axis, since it now is the forward_axis // of the yaw turned camera) Vec4f yaw_forward_axis = {0}; vec_normalize(yaw_direction, yaw_forward_axis); // - then use the new forward axis with the old target_direction to compute the angle // between those float pitch = 0.0f; vec_angle(target_direction, yaw_forward_axis, &pitch); log_assert( ! isnan(pitch), "vec_angle(%f %f %f, %f %f %f, %f);\n", target_direction[0], target_direction[1], target_direction[2], yaw_forward_axis[0], yaw_forward_axis[1], yaw_forward_axis[2], pitch ); // - and just as in the yaw case we compute an rotation pitch_axis Vec4f pitch_axis = {0}; vec_cross(target_direction, yaw_forward_axis, pitch_axis); if( vec_nullp(pitch_axis) ) { vec_copy4f(right_axis, pitch_axis); } // - and finally compute the pitch rotation and combine it with the yaw_rotation // in the same step Quat pitch_rotation; quat_from_axis_angle(pitch_axis, pitch, pitch_rotation); Quat yaw_pitch_rotation; quat_mul(yaw_rotation, pitch_rotation, yaw_pitch_rotation); Quat inverted_orientation = {0}; quat_invert(world_pivot.orientation, inverted_orientation); // - the int32_t I want to return indicates the cameras 'flip' status, that is, it is // one when the camera angle was pitched so much that it flipped over and its // up axis is now pointing downwards // - to find out if I am flipped over, I compute the flipped up_axis called // flip_axis and then use the dot product between the flip_axis and up_axis // to decide if I am flipped Vec4f flip_axis = {0}; vec_rotate(up_axis, inverted_orientation, flip_axis); vec_rotate(flip_axis, yaw_pitch_rotation, flip_axis); float dot_pitch = vec_dot(up_axis, flip_axis); Vec4f target_axis = {0}; vec_normalize(target_direction, target_axis); // - check if we are flipped and if we are, set result to 1 meaning we are flipped // - turn the camera around PI so that we can continue pitching, otherwise we just get // stuck when trying to flip the camera over if( dot_pitch < 0.0f ) { result = 1; quat_from_axis_angle(target_axis, PI, rotation); quat_mul(yaw_pitch_rotation, rotation, yaw_pitch_rotation); } quat_copy(yaw_pitch_rotation, rotation); } if( ! isnan(rotation[0]) && ! isnan(rotation[1]) && ! isnan(rotation[2]) && ! isnan(rotation[3]) ) { quat_copy(rotation, pivot->orientation); } pivot->eye_distance = vec_length(target_direction); return result; }
QuatP* qidentity(Quat q) { quat_identity(q); return q; }