kmQuaternion *sls_trackball_calc_quat(kmQuaternion *out, float trackball_radius,
                                      float trackball_speed, kmVec2 const *p1,
                                      kmVec2 const *p2) {
  //sls_log_info("p1 %f %f, p2 %f %f", p1->x, p1->y, p2->x, p2->y);

  kmVec3 axis;
  kmVec3 _p1, _p2, dir;
  float phi;
  float t;
  float epsilon = 0.001;
  if (sls_vec2_near(p1, p2, epsilon)) {
    // zero rotation
    kmQuaternionIdentity(out);
    return out;
  }

  _p1 = (kmVec3){p1->x, p1->y, sls_tb_project_to_sphere(trackball_radius, p1)};
  _p2 = (kmVec3){p2->x, p2->y, sls_tb_project_to_sphere(trackball_radius, p2)};

  kmVec3Subtract(&dir, &_p1, &_p2);

  kmVec3Cross(&axis, &_p2, &_p1);

  t = kmVec3Length(&dir) / (2.0f * trackball_radius);
  t = fminf(fmaxf(-1.f, t), 1.f);
  phi = 2.0f * asinf(t) * trackball_speed;
  kmQuaternion tmp_a, tmp_b;
  kmQuaternionRotationAxisAngle(&tmp_a, &axis, phi);

  tmp_b = *out;

  return kmQuaternionMultiply(out, &tmp_a, &tmp_b);
  ;
}
slsTrackball *sls_trackball_init(slsTrackball *self, float radius,
                                 float rotation_speed) {
  self->radius = radius;
  self->rotation_speed = rotation_speed;
  kmQuaternionIdentity(&self->rotation);

  kmMat4Identity(&self->rotation_mat);

  return self;
}
Exemple #3
0
/*
 * Returns a Quaternion representing the angle between two vectors
 */
kmQuaternion* kmQuaternionBetweenVec3(kmQuaternion* pOut, const kmVec3* u, const kmVec3* v) {
    kmVec3 w;
    kmScalar len;
    kmQuaternion q;

    if(kmVec3AreEqual(u, v)) {
        kmQuaternionIdentity(pOut);
        return pOut;
    }

    len = sqrtf(kmVec3LengthSq(u) * kmVec3LengthSq(v));
    kmVec3Cross(&w, u, v);

    kmQuaternionFill(&q, w.x, w.y, w.z, kmVec3Dot(u, v) + len);
    return kmQuaternionNormalize(pOut, &q);
}
lite3d_scene_node *lite3d_scene_node_init(lite3d_scene_node *node)
{
    SDL_assert(node);
    memset(node, 0, sizeof (lite3d_scene_node));
    lite3d_list_link_init(&node->nodeLink);
    kmMat4Identity(&node->localView);
    kmMat4Identity(&node->worldView);
    kmMat3Identity(&node->normalModel);
    kmQuaternionIdentity(&node->rotation);
    kmVec3Fill(&node->position, 0, 0, 0);
    kmVec3Fill(&node->scale, 1.0f, 1.0f, 1.0f);
    node->recalc = LITE3D_TRUE;
    node->invalidated = LITE3D_TRUE;
    node->rotationCentered = LITE3D_TRUE;
    node->isCamera = LITE3D_FALSE;
    node->renderable = LITE3D_TRUE;
    node->enabled = LITE3D_TRUE;
    node->visible = LITE3D_TRUE;
    node->frustumTest = LITE3D_TRUE;
    lite3d_list_init(&node->childNodes);

    return node;
}
Exemple #5
0
kmQuaternion* kmQuaternionRotationBetweenVec3(kmQuaternion* pOut, const kmVec3* vec1, const kmVec3* vec2, const kmVec3* fallback) {

	kmVec3 v1, v2;
    kmScalar a;

	kmVec3Assign(&v1, vec1);
	kmVec3Assign(&v2, vec2);

	kmVec3Normalize(&v1, &v1);
	kmVec3Normalize(&v2, &v2);

	a = kmVec3Dot(&v1, &v2);

	if (a >= 1.0) {
		kmQuaternionIdentity(pOut);
		return pOut;
	}

	if (a < (1e-6f - 1.0f))	{
		if (fabs(kmVec3LengthSq(fallback)) < kmEpsilon) {
            kmQuaternionRotationAxisAngle(pOut, fallback, kmPI);
		} else {
			kmVec3 axis;
			kmVec3 X;
			X.x = 1.0;
			X.y = 0.0;
			X.z = 0.0;


			kmVec3Cross(&axis, &X, vec1);

			/*If axis is zero*/
			if (fabs(kmVec3LengthSq(&axis)) < kmEpsilon) {
				kmVec3 Y;
				Y.x = 0.0;
				Y.y = 1.0;
				Y.z = 0.0;

				kmVec3Cross(&axis, &Y, vec1);
			}

			kmVec3Normalize(&axis, &axis);

            kmQuaternionRotationAxisAngle(pOut, &axis, kmPI);
		}
	} else {
		kmScalar s = sqrtf((1+a) * 2);
		kmScalar invs = 1 / s;

		kmVec3 c;
		kmVec3Cross(&c, &v1, &v2);

		pOut->x = c.x * invs;
		pOut->y = c.y * invs;
        pOut->z = c.z * invs;
        pOut->w = s * 0.5f;

		kmQuaternionNormalize(pOut, pOut);
	}

	return pOut;

}