Beispiel #1
0
kmBool kmRay3IntersectTriangle(const kmRay3* ray, const kmVec3* v0, const kmVec3* v1, const kmVec3* v2, kmVec3* intersection, kmVec3* normal, kmScalar* distance) {
    kmVec3 e1, e2, pvec, tvec, qvec, dir;
    kmScalar det, inv_det, u, v, t;

    kmVec3Normalize(&dir, &ray->dir);

    kmVec3Subtract(&e1, v1, v0);
    kmVec3Subtract(&e2, v2, v0);

    kmVec3Cross(&pvec, &dir, &e2);
    det = kmVec3Dot(&e1, &pvec);

    /* Backfacing, discard. */
    if(det < kmEpsilon) {
        return KM_FALSE;
    }

    if(kmAlmostEqual(det, 0)) {
        return KM_FALSE;
    }

    inv_det = 1.0 / det;

    kmVec3Subtract(&tvec, &ray->start, v0);

    u = inv_det * kmVec3Dot(&tvec, &pvec);
    if(u < 0.0 || u > 1.0) {
        return KM_FALSE;
    }

    kmVec3Cross(&qvec, &tvec, &e1);
    v = inv_det * kmVec3Dot(&dir, &qvec);
    if(v < 0.0 || (u + v) > 1.0) {
        return KM_FALSE;
    }

    t = inv_det * kmVec3Dot(&e2, &qvec);
    if(t > kmEpsilon && (t*t) <= kmVec3LengthSq(&ray->dir)) {
        kmVec3 scaled;
        *distance = t; /* Distance */
        kmVec3Cross(normal, &e1, &e2); /* Surface normal of collision */
        kmVec3Normalize(normal, normal);
        kmVec3Normalize(&scaled, &dir);
        kmVec3Scale(&scaled, &scaled, *distance);
        kmVec3Add(intersection, &ray->start, &scaled);
        return KM_TRUE;
    }

    return KM_FALSE;
}
Beispiel #2
0
/**
 * Creates a plane from 3 points. The result is stored in pOut.
 * pOut is returned.
 */
kmPlane* const kmPlaneFromPoints(kmPlane* pOut, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3)
{
    /*
    v = (B − A) × (C − A)
    n = 1⁄|v| v
    Outa = nx
    Outb = ny
    Outc = nz
    Outd = −n⋅A
    */

    kmVec3 n, v1, v2;
    kmVec3Subtract(&v1, p2, p1); //Create the vectors for the 2 sides of the triangle
    kmVec3Subtract(&v2, p3, p1);
    kmVec3Cross(&n, &v1, &v2); //Use the cross product to get the normal

    kmVec3Normalize(&n, &n); //Normalize it and assign to pOut->m_N

    pOut->a = n.x;
    pOut->b = n.y;
    pOut->c = n.z;
    pOut->d = kmVec3Dot(kmVec3Scale(&n, &n, -1.0), p1);

    return pOut;
}
Beispiel #3
0
kmVec3* kmVec3ProjectOnToVec3(const kmVec3* pIn, const kmVec3* other, kmVec3* projection) {
    kmScalar scale = kmVec3Length(pIn) * kmVec3Dot(pIn, other);

    kmVec3Normalize(projection, other);
    kmVec3Scale(projection, projection, scale);
    return projection;
}
Beispiel #4
0
/**
 * Reflects a vector about a given surface normal. The surface normal is
 * assumed to be of unit length.
 */
kmVec3* kmVec3Reflect(kmVec3* pOut, const kmVec3* pIn, const kmVec3* normal) {
  kmVec3 tmp;
  kmVec3Scale(&tmp, normal, 2.0f * kmVec3Dot(pIn, normal));
  kmVec3Subtract(pOut, pIn, &tmp);

  return pOut;
}
Beispiel #5
0
kmVec3* kmPlaneGetIntersection(kmVec3* pOut, const kmPlane* p1, const kmPlane* p2, const kmPlane* p3) {
    kmVec3 n1, n2, n3, cross;
    kmVec3 r1, r2, r3;
    double denom = 0;
    
    kmVec3Fill(&n1, p1->a, p1->b, p1->c);
    kmVec3Fill(&n2, p2->a, p2->b, p2->c);
    kmVec3Fill(&n3, p3->a, p3->b, p3->c);
    
    kmVec3Cross(&cross, &n2, &n3);

    denom = kmVec3Dot(&n1, &cross);

    if (kmAlmostEqual(denom, 0.0)) {
        return NULL;
    }

    kmVec3Cross(&r1, &n2, &n3);
    kmVec3Cross(&r2, &n3, &n1);
    kmVec3Cross(&r3, &n1, &n2);

    kmVec3Scale(&r1, &r1, -p1->d);
    kmVec3Scale(&r2, &r2, p2->d);
    kmVec3Scale(&r3, &r3, p3->d);

    kmVec3Subtract(pOut, &r1, &r2);
    kmVec3Subtract(pOut, pOut, &r3);
    kmVec3Scale(pOut, pOut, 1.0 / denom);

    /*p = -d1 * ( n2.Cross ( n3 ) ) – d2 * ( n3.Cross ( n1 ) ) – d3 * ( n1.Cross ( n2 ) ) / denom;*/

    return pOut;
}
Beispiel #6
0
void kmVec3OrthoNormalize(kmVec3* normal, kmVec3* tangent) {
    kmVec3 proj;

    kmVec3Normalize(normal, normal);

    kmVec3Scale(&proj, normal, kmVec3Dot(tangent, normal));
    kmVec3Subtract(tangent, tangent, &proj);
    kmVec3Normalize(tangent, tangent);
}
Beispiel #7
0
kmVec3* kmVec3ProjectOnToPlane(kmVec3* pOut, const kmVec3* point, const struct kmPlane* plane) {
    kmVec3 N;
    kmVec3Fill(&N, plane->a, plane->b, plane->c);
    kmVec3Normalize(&N, &N);
    kmScalar distance = -kmVec3Dot(&N, point);
    kmVec3Scale(&N, &N, distance);
    kmVec3Add(pOut, point, &N);
    return pOut;
}
Beispiel #8
0
kmVec3* kmVec3Reflect(kmVec3* pOut, const kmVec3* v1, const kmVec3* normal) {
	const kmScalar d = 2 * kmVec3Dot(v1, normal);

    kmVec3Fill(pOut, 
               v1->x - d * normal->x, 
               v1->y - d * normal->y, 
               v1->z - d * normal->z);
    
    return pOut;
}
Beispiel #9
0
kmVec3* kmVec3ProjectOnToVec3(const kmVec3* w, const kmVec3* v,
                              kmVec3* projection) {
    kmVec3 unitW, unitV;
    kmVec3Normalize(&unitW, w);
    kmVec3Normalize(&unitV, v);

    kmScalar cos0 = kmVec3Dot(&unitW, &unitV);

    kmVec3Scale(projection, &unitV, kmVec3Length(w) * cos0);

    return projection;
}
Beispiel #10
0
/**
 * Builds a translation matrix in the same way as gluLookAt()
 * the resulting matrix is stored in pOut. pOut is returned.
 */
kmMat4* kmMat4LookAt(kmMat4* pOut, const kmVec3* pEye,
                     const kmVec3* pCenter, const kmVec3* pUp)
{
    kmVec3 f;
    kmVec3 s;
    kmVec3 u;

    kmVec3Subtract(&f, pCenter, pEye);
    kmVec3Normalize(&f, &f);

    kmVec3Cross(&s, &f, pUp);
    kmVec3Normalize(&s, &s);

    kmVec3Cross(&u, &s, &f);

    pOut->mat[0] = s.x;
    pOut->mat[1] = u.x;
    pOut->mat[2] = -f.x;
    pOut->mat[3] = 0.0;

    pOut->mat[4] = s.y;
    pOut->mat[5] = u.y;
    pOut->mat[6] = -f.y;
    pOut->mat[7] = 0.0;

    pOut->mat[8] = s.z;
    pOut->mat[9] = u.z;
    pOut->mat[10] = -f.z;
    pOut->mat[11] = 0.0;

    pOut->mat[12] = -kmVec3Dot(&s, pEye);
    pOut->mat[13] = -kmVec3Dot(&u, pEye);
    pOut->mat[14] = kmVec3Dot(&f, pEye);
    pOut->mat[15] = 1.0;

    return pOut;
}
Beispiel #11
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);
}
Beispiel #12
0
kmPlane* const kmPlaneFromPointNormal(kmPlane* pOut, const kmVec3* pPoint, const kmVec3* pNormal)
{
    /*
	Planea = Nx
	Planeb = Ny
	Planec = Nz
	Planed = −N⋅P
    */


    pOut->a = pNormal->x;
    pOut->b = pNormal->y;
    pOut->c = pNormal->z;
    pOut->d = -kmVec3Dot(pNormal, pPoint);

    return pOut;
}
Beispiel #13
0
static inline bool
_frustum_contains_sphere(
	ne_frustum *f,
	ne_bounding_sphere *s)
{
	float dist = 0.f;
	float rad = -s->radius;

	for (uint8_t i = 0; i < 6; ++i) {
		dist = kmVec3Dot(&f->planes[i].normal, &s->center)
			+ f->planes[i].distance;

		if (dist < rad)
			return false;
	}

	return true;
}
Beispiel #14
0
kmQuaternion* kmQuaternionExtractRotationAroundAxis(const kmQuaternion* pIn, const kmVec3* axis, kmQuaternion* pOut) {
    /**
        Given a quaternion, and an axis. This extracts the rotation around the axis into pOut as another quaternion.
        Uses the swing-twist decomposition.

        http://stackoverflow.com/questions/3684269/component-of-a-quaternion-rotation-around-an-axis/22401169?noredirect=1#comment34098058_22401169
    */

    kmVec3 ra;
    kmScalar d;

    kmVec3Fill(&ra, pIn->x, pIn->y, pIn->z);

    d = kmVec3Dot(&ra, axis);

    kmQuaternionFill(pOut, axis->x * d, axis->y * d, axis->z * d, pIn->w);
    kmQuaternionNormalize(pOut, pOut);
    return pOut;
}
Beispiel #15
0
/* Calculate view matrix */
static void dlCameraCalculateViewMatrix( dlCamera *object )
{
   kmVec3 tgtv, upvector;
   kmScalar dp;

   CALL("%p", object);

   kmVec3Subtract( &tgtv, &object->target, &object->translation );

   kmVec3Normalize( &tgtv, &tgtv );
   kmVec3Normalize( &upvector, &object->upVector );

   dp = kmVec3Dot( &tgtv, &upvector );
   if( dp == 1.f )
   {
      upvector.x += 0.5f;
   }

   kmMat4LookAt( &object->view, &object->translation, &object->target, &upvector );

   /* Frustum recalculation here */

   kmMat4Multiply( &object->matrix, &object->projection, &object->view );
}
Beispiel #16
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;

}