예제 #1
0
BOOL boundingBoxCollide(struct BoundingBox a, struct BoundingBox b)
{
    struct Vector a1 = a.direction = vectorNormalize(a.direction);
    struct Vector a2 = a.up = vectorNormalize(a.up);
    struct Vector a3 = vectorCross(a1, a2);
    struct Vector b1 = b.direction = vectorNormalize(b.direction);
    struct Vector b2 = b.up = vectorNormalize(b.up);
    struct Vector b3 = vectorCross(b1, b2);

    if(boundingBoxSeparationTest(a1, a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(a2, a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(a3, a, b)>0) return FALSE;

    if(boundingBoxSeparationTest(b1, a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(b2, a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(b3, a, b)>0) return FALSE;

    if(boundingBoxSeparationTest(vectorCross(a1, b1), a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(vectorCross(a1, b2), a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(vectorCross(a1, b3), a, b)>0) return FALSE;

    if(boundingBoxSeparationTest(vectorCross(a2, b1), a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(vectorCross(a2, b2), a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(vectorCross(a2, b3), a, b)>0) return FALSE;

    if(boundingBoxSeparationTest(vectorCross(a3, b1), a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(vectorCross(a3, b2), a, b)>0) return FALSE;
    if(boundingBoxSeparationTest(vectorCross(a3, b3), a, b)>0) return FALSE;

    return TRUE;
}
예제 #2
0
void chaser_update (Dynarr entities)
{
    Entity
    active;
    int
    i = 0,
    j = 0;
    Chaser
    chaser;
    struct target_info
        * target;
    VECTOR3
    direction,
    distance;
    while ((active = *(Entity *)dynarr_at (entities, i++)))
    {
        chaser = component_getData (entity_getAs (active, "chaser"));
        direction = vectorCreate (0, 0, 0);
        j = 0;
        while ((target = *(struct target_info **)dynarr_at (chaser->targets, j++)))
        {
            distance = position_distanceBetween (active, target->target);
            distance = vectorNormalize (&distance);
            distance = vectorMultiplyByScalar (&distance, target->weight);
            direction = vectorAdd (&direction, &distance);
        }
        direction = vectorNormalize (&direction);
        // direction is NaN; can't use
        if (direction.x != direction.x || direction.z != direction.z)
            continue;
        position_face (active, &direction);
        walking_start (active);
    }
}
예제 #3
0
struct BoundingBox boundingBoxInterpolate(const struct BoundingBox *a, const struct BoundingBox *b)
{
    struct BoundingBox bb;
    bb.position = vectorTimes( vectorAdd(a->position, b->position), 0.5 );
    bb.direction = vectorNormalize(vectorAdd(a->direction, b->direction));
    bb.up = vectorNormalize(vectorAdd(a->up, b->up));
    bb.halfSize = vectorTimes( vectorAdd(a->halfSize, b->halfSize), 0.5 );
    return bb;
}
예제 #4
0
static void position_updateAxesFromOrientation (POSITION pdata)
{
	QUAT
		r;
	if (pdata == NULL || pdata->dirty == false)
		return;
	r = pdata->orientation;
	/* FIXME?: wait, why are the side and front vectors transposed here? I
	 * guess it doesn't really matter, but...
	 *  - xph 2011-03-10
	 */
	// these values constitute a 3x3 rotation matrix. opengl offsets are commented on each value. see the camera component for how these are used to create the cameraview matrix.
	pdata->view.side.x =		// [0]
		1 -
		2 * r.y * r.y -
		2 * r.z * r.z;
	pdata->view.side.y =		// [4]
		2 * r.x * r.y -
		2 * r.w * r.z;
	pdata->view.side.z =		// [8]
		2 * r.x * r.z +
		2 * r.w * r.y;
	pdata->view.up.x =			// [1]
		2 * r.x * r.y +
		2 * r.w * r.z;
	pdata->view.up.y =			// [5]
		1 -
		2 * r.x * r.x -
		2 * r.z * r.z;
	pdata->view.up.z =			// [9]
		2 * r.y * r.z -
		2 * r.w * r.x;
	pdata->view.front.x =		// [2]
		2 * r.x * r.z -
		2 * r.w * r.y;
	pdata->view.front.y =		// [6]
		2 * r.y * r.z +
		2 * r.w * r.x;
	pdata->view.front.z =		// [10]
		1 -
		2 * r.x * r.x -
		2 * r.y * r.y;
	pdata->move.front = vectorCross (&pdata->view.side, &pdata->move.up);
	pdata->move.front = vectorNormalize (&pdata->move.front);
	pdata->move.side = vectorCross (&pdata->move.up, &pdata->view.front);
	pdata->move.side = vectorNormalize (&pdata->move.side);
	pdata->move.up = vectorCreate (0, 1, 0);
	pdata->orientation = quat_normalize (&pdata->orientation);
	pdata->dirty = false;
}
예제 #5
0
double vectorPointPlaneDistance(struct Vector point1, struct Vector point2, struct Vector normal)
{
    normal = vectorNormalize(normal);
    double d1 = vectorDot(normal, point1);
    double d2 = vectorDot(normal, point2);
    return fabs(d1-d2);
}
예제 #6
0
void Mesh::createVertexnormals(void) {
  int i, j, ii;
  bool connect;
  float normal[3];
  for (i = 0; i < vertexcount; i++) {
    bool found = false;
    vectorSet(normal, 0, 0, 0);
    for (j = 0; j < polygoncount; j++) {
      connect = false;
      class Polygon *polygon = &polygons[j];
      for (ii = 0; ii < polygon->vertexcount; ii++) {
        if (polygons[j].vertices[ii] == &(vertices[i])) {
          connect = true;
        }
      }
      if (connect) {
        vectorAdd(normal, polygon->planenormal);
        found = true;
      }
    }
    if (found) {
      vectorNormalize(vertices[i].normal, normal);
    }
  }
  for (j = 0; j < polygoncount; j++) {
    class Polygon *polygon = &polygons[j];
    if (!polygon->realsmooth)
      polygon->smooth = true;
  }
}
예제 #7
0
bool line_polyHit (const LINE3 * const line, int points, const VECTOR3 * const poly, float * tAtIntersection)
{
	VECTOR3
		u, v,
		plane,
		hit;
	LINE3
		transLine;
	float
		t;
	u = vectorSubtract (&poly[1], &poly[0]);
	v = vectorSubtract (&poly[2], &poly[0]);
	plane = vectorCross (&u, &v);
	plane = vectorNormalize (&plane);

	// see note in the line_triHit function
	transLine.origin = vectorSubtract (&line->origin, &poly[0]);
	transLine.dir = line->dir;
	if (!line_planeHit (&transLine, &plane, &t))
		return false;
	hit = vectorCreate
	(
		line->origin.x + line->dir.x * t,
		line->origin.y + line->dir.y * t,
		line->origin.z + line->dir.z * t
	);
	if (pointInPoly (&hit, points, poly))
	{
		if (tAtIntersection)
			*tAtIntersection = t;
		return true;
	}
	return false;
}
template <typename T> float MagneticSensorLsm303::heading(vector<T> from)
{
    vector<int32_t> temp_m = {magnetometer.x, magnetometer.y, magnetometer.z};

    ///< subtract offset (average of min and max) from magnetometer readings
    temp_m.x -= ((int32_t)magnetometer_min.x + magnetometer_max.x) / 2;
    temp_m.y -= ((int32_t)magnetometer_min.y + magnetometer_max.y) / 2;
    temp_m.z -= ((int32_t)magnetometer_min.z + magnetometer_max.z) / 2;

    ///< compute E and N
    vector<float> E;
    vector<float> N;
    vectorCross(&temp_m, &accelerometer, &E);
    vectorNormalize(&E);
    vectorCross(&accelerometer, &E, &N);
    vectorNormalize(&N);

    ///< compute heading
    float heading = atan2(vectorDot(&E, &from), vectorDot(&N, &from)) * 180 / M_PI;
    if (heading < 0) heading += 360;
    return heading;
}
예제 #9
0
_C3DTQuaternion quaternionFromAxisAngle(C3DTVector v) {

    v = vectorNormalize(v);

    _C3DTQuaternion	q;
    float sinHalfAngle = sinf(v.cartesian.w / 2.0f);

    q.cartesian.x = v.cartesian.x * sinHalfAngle;
    q.cartesian.y = v.cartesian.y * sinHalfAngle;
    q.cartesian.z = v.cartesian.z * sinHalfAngle;
    q.cartesian.w = cosf(v.cartesian.w / 2.0f);

    return q;
}
예제 #10
0
// Compute p1,p2,p3 face normal into pOut
point Actor::computeFaceNormal (point *p1, point *p2, point *p3, point *pOut)
{
    // Uses p2 as a new origin for p1,p3
    point a;
    vectorOffset(p3, p2, &a);
    point b;
    vectorOffset(p1, p2, &b);
    // Compute the cross product a X b to get the face normal
    point pn;
    vectorGetNormal(&a, &b, &pn);
    // Return a normalized vector
    vectorNormalize(&pn, pOut);
    
    return *pOut;
}
Plane::Plane(GzCoord aVertexList[]){
	GzCoord temp1, temp2;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 3; j++){
			vertexList[i][j] = aVertexList[i][j];
		}
	}

	vectorConstruct(vertexList[0], vertexList[1], temp1);
	vectorConstruct(vertexList[0], vertexList[2], temp2);
	vectorCrossProduct(temp1, temp2, normal);
	vectorNormalize(normal);

	distance = vectorDotProduct(normal, vertexList[0]);
}
예제 #12
0
void Mesh::createPlanes(void) {
  int i;
  for (i = 0; i < polygoncount; i++) {
    class Polygon *polygon = &this->polygons[i];
    if (polygon->vertexcount >= 3) {
      float v1[3], v2[3];
      vectorSub(v1, polygon->vertices[1]->position,
                polygon->vertices[0]->position);
      vectorSub(v2, polygon->vertices[2]->position,
                polygon->vertices[0]->position);
      vectorCross(polygon->planenormal, v1, v2);
      vectorNormalize(polygon->planenormal);

      polygon->planedistance =
          -vectorDot(polygon->vertices[0]->position, polygon->planenormal);
    }
  }
}
예제 #13
0
// Define the view frustum for culling
C3DTFrustum viewFrustum(const C3DTMatrix projection, const C3DTMatrix model)
{
    C3DTMatrix	clip;
    C3DTFrustum	r;

    clip = matrixMultiply(projection, model);

    // Right plane
    r.planes[0].cartesian.x = clip.flts[3] - clip.flts[0];
    r.planes[0].cartesian.y = clip.flts[7] - clip.flts[4];
    r.planes[0].cartesian.z = clip.flts[11] - clip.flts[8];
    r.planes[0].cartesian.w = clip.flts[15] - clip.flts[12];
    r.planes[0] = vectorNormalize(r.planes[0]);

    // Left plane
    r.planes[1].cartesian.x = clip.flts[3] + clip.flts[0];
    r.planes[1].cartesian.y = clip.flts[7] + clip.flts[4];
    r.planes[1].cartesian.z = clip.flts[11] + clip.flts[8];
    r.planes[1].cartesian.w = clip.flts[15] + clip.flts[12];
    r.planes[1] = vectorNormalize(r.planes[1]);

    // Bottom plane
    r.planes[2].cartesian.x = clip.flts[3] + clip.flts[1];
    r.planes[2].cartesian.y = clip.flts[7] + clip.flts[5];
    r.planes[2].cartesian.z = clip.flts[11] + clip.flts[9];
    r.planes[2].cartesian.w = clip.flts[15] + clip.flts[13];
    r.planes[2] = vectorNormalize(r.planes[2]);

    // Top plane
    r.planes[3].cartesian.x = clip.flts[3] - clip.flts[1];
    r.planes[3].cartesian.y = clip.flts[7] - clip.flts[5];
    r.planes[3].cartesian.z = clip.flts[11] - clip.flts[9];
    r.planes[3].cartesian.w = clip.flts[15] - clip.flts[13];
    r.planes[3] = vectorNormalize(r.planes[3]);

    // Far plane
    r.planes[4].cartesian.x = clip.flts[3] - clip.flts[2];
    r.planes[4].cartesian.y = clip.flts[7] - clip.flts[6];
    r.planes[4].cartesian.z = clip.flts[11] - clip.flts[10];
    r.planes[4].cartesian.w = clip.flts[15] - clip.flts[14];
    r.planes[4] = vectorNormalize(r.planes[4]);

    // Near plane
    r.planes[5].cartesian.x = clip.flts[3] + clip.flts[2];
    r.planes[5].cartesian.y = clip.flts[7] + clip.flts[6];
    r.planes[5].cartesian.z = clip.flts[11] + clip.flts[10];
    r.planes[5].cartesian.w = clip.flts[15] + clip.flts[14];
    r.planes[5] = vectorNormalize(r.planes[5]);

    return r;
}
예제 #14
0
파일: texture.c 프로젝트: xaphiriron/beyond
void textureDrawLine (TEXTURE t, VECTOR3 start, VECTOR3 end)
{
	VECTOR3
		diff = vectorSubtract (&end, &start),
		norm = vectorNormalize (&diff),
		current = start;
	/* i'm using i/max as a counter since due to floating point rounding error
	 * it's not feasible to use vector_cmp (&current, &end), which is the only
	 * other way i can think of to check for when the line is actually done
	 *  - xph 2011 08 27
	 */
	int
		i = 0,
		max = vectorMagnitude (&diff) + 1;
	/* if start is out of bounds skip ahead until it isn't (if it isn't), and
	 * if it goes out of bounds again then it's not coming back. this is
	 * important if start is out of bounds but end isn't (or if they're both
	 * oob but they cross the image edge at some point); the start of the line
	 * won't be drawn but stopping after the first oob coordiante would be
	 * wrong
	 * (there's a better way to do this: if either value is oob, calculate the
	 * intersection of the line w/ the screen edges and jump to that point
	 * without needing to loop)
	 *  - xph 2011 08 27
	 */
	while (textureOOB (t, current) && i < max)
	{
		current = vectorAdd (&current, &norm);
		i++;
	}
	while (i < max)
	{
		if (textureOOB (t, current))
			break;
		textureDrawPixel (t, current);
		current = vectorAdd (&current, &norm);
		i++;
	}
}
예제 #15
0
struct Vector vectorRotate(double angle, struct Vector axis, struct Vector v)
{
    if(vectorLength(axis) < EPSILON) // axis is zero
    {
        return v;
    }
    double c=cos(angle);
    double s=sin(angle);
    struct Vector result;
    axis = vectorNormalize(axis);
    result.x =  (axis.x*axis.x*(1-c)+c       )*v.x +
                (axis.x*axis.y*(1-c)-axis.z*s)*v.y +
                (axis.x*axis.z*(1-c)+axis.y*s)*v.z;

    result.y =  (axis.y*axis.x*(1-c)+axis.z*s)*v.x +
                (axis.y*axis.y*(1-c)+c       )*v.y +
                (axis.y*axis.z*(1-c)-axis.x*s)*v.z;

    result.z =  (axis.z*axis.x*(1-c)-axis.y*s)*v.x +
                (axis.z*axis.y*(1-c)+axis.x*s)*v.y +
                (axis.z*axis.z*(1-c)+c       )*v.z;
    return result;

}
예제 #16
0
// Normal of 2 vectors (0 centered)
inline C3DTVector vectorNormal(const C3DTVector a, const C3DTVector b)
{
    return vectorNormalize(vectorCrossProduct(a, b));
}
예제 #17
0
// Returns the cos() of the angle between 2 vectors
inline float vectorAngleCos(const C3DTVector a, const C3DTVector b)
{
    return vectorDotProduct(vectorNormalize(a), vectorNormalize(b));
}
예제 #18
0
// Normal of 2 vectors (centered on a 3rd point)
inline C3DTVector vectorNormalTri(const C3DTVector a, const C3DTVector b, const C3DTVector c)
{
    return vectorNormalize(vectorCrossProductTri(a, b, c));
}
예제 #19
0
bool handleCollision(Contact *contact) {
  Object *source = contact->object1;
  Object *target = contact->object2;
  float *normal = contact->normal;
  float *contactpoint = contact->position;

  float sourcevelocity[3], targetvelocity[3];
  float sourcecontactpoint[3], targetcontactpoint[3];

  vectorSub(sourcecontactpoint, contactpoint, source->position);
  source->getVelocity(sourcevelocity, sourcecontactpoint);

  if (target == NULL) {
    vectorSet(targetcontactpoint, 0, 0, 0);
    vectorSet(targetvelocity, 0, 0, 0);
  } else {
    vectorSub(targetcontactpoint, contactpoint, target->position);
    target->getVelocity(targetvelocity, targetcontactpoint);
  }

  float deltavelocity[3];
  vectorSub(deltavelocity, sourcevelocity, targetvelocity);
  float dot = vectorDot(deltavelocity, normal);

  // if (fabs(dot) < EPSILON) return false;
  // if (dot > -1.0e-5 && dot < 1.0e-5) return false;
  // if (dot >= 0) return false;
  if (dot > -1.0e-5)
    return false;

  float invmass1;
  invmass1 = source->invmass;

  float invmass2;
  if (target == NULL)
    invmass2 = 0;
  else
    invmass2 = target->invmass;

  float t1;
  if (source->invmomentofinertia == 0) {
    t1 = 0;
  } else {
    float v1[3];
    vectorCross(v1, sourcecontactpoint, normal);
    vectorScale(v1, source->invmomentofinertia);
    float w1[3];
    vectorCross(w1, v1, sourcecontactpoint);
    t1 = vectorDot(normal, w1);
  }

  float t2;
  if (target == NULL || target->invmomentofinertia == 0) {
    t2 = 0;
  } else {
    float v1[3];
    vectorCross(v1, targetcontactpoint, normal);
    vectorScale(v1, target->invmomentofinertia);
    float w1[3];
    vectorCross(w1, v1, targetcontactpoint);
    t2 = vectorDot(normal, w1);
  }

  float denominator = invmass1 + invmass2 + t1 + t2;

  float e = 1.0 - COLLISIONFRICTION;

  float impulsesize = (1 + e) * dot / denominator;

  // printf("%f\n", impulsesize);

  float impulse[3];
  vectorScale(impulse, normal, impulsesize);

  float friction[3];
  vectorScale(friction, normal, vectorDot(deltavelocity, normal));
  vectorAdd(friction, deltavelocity);
  vectorNormalize(friction);
  float frictionsize = 10 * KINETICFRICTION * dot / denominator;
  float maxfrictionsize = 0.1 * vectorLength(deltavelocity);
  if (frictionsize < -maxfrictionsize)
    frictionsize = -maxfrictionsize;
  vectorScale(friction, -frictionsize);
  vectorAdd(impulse, friction);

  if (target != NULL) {
    target->addImpulse(impulse, targetcontactpoint);
    target->calculateStateVariables();
  }

  float speed;
  float speed2[3];

  if (target != NULL && source != NULL) {
    // float kvel[3];
    // source->getVelocity(kvel);
    float k = vectorLength(sourcevelocity) * 0.1;
    // if (k > 1) k = 1;
    speed = -impulsesize * target->invmass * k;
    vectorScale(speed2, impulse, target->invmass * k);
    /*float kvel[3];
        source->getVelocity(kvel);
        float k = 0;//vectorDot(speed2, kvel);
        if (k < EPSILON) k = 0;
        speed *= k;
        vectorScale(speed2, k);
        if (k > 0) */ target->hitForce(speed, speed2, source);
  }

  vectorScale(impulse, -1);
  source->addImpulse(impulse, sourcecontactpoint);
  source->calculateStateVariables();

  // vectorScale(speed, source->invmass);
  if (target != NULL && source != NULL) {
    // float kvel[3];
    // target->getVelocity(kvel);
    float k = vectorLength(targetvelocity) * 0.1;
    // if (k > 1) k = 1;
    speed = -impulsesize * source->invmass * k;
    vectorScale(speed2, impulse, source->invmass * k);
    /*float kvel[3];
        target->getVelocity(kvel);
        float k = 0;//vectorDot(speed2, kvel);
        if (k < EPSILON) k = 0;
        speed *= k;
        vectorScale(speed2, k);
        if (k > 0) */ source->hitForce(speed, speed2, target);
  }

  return true;
}
예제 #20
0
bool checkSphereMeshCollision(float *sphereposition, float r, Mesh *mesh,
                              float *normal, float *contactpoint) {
  float linenormal[3];
  float pointnormal[3];
  float maxdist = 0;
  bool planecollision = false;
  bool linecollision = false;
  bool pointcollision = false;

  int i, j;

  for (i = 0; i < mesh->polygoncount; i++) {
    class Polygon *polygon = &mesh->polygons[i];

    float dist = distanceFromPlane(sphereposition, polygon->planenormal,
                                   polygon->planedistance);
    if (dist < r && dist > -r) {
      bool directcollision = true;
      for (j = 0; j < polygon->vertexcount; j++) {
        float *p1 = polygon->vertices[j]->position;
        float *p2 = polygon->vertices[(j + 1) % polygon->vertexcount]->position;
        float *p3 = polygon->vertices[(j + 2) % polygon->vertexcount]->position;
        float v1[3], v2[3];
        vectorSub(v1, p2, p1);

        // Collision for polygon surface
        vectorSub(v2, p3, p2);
        float t1[3];
        vectorProject(t1, v2, v1);
        float norm[3];
        vectorSub(norm, v2, t1);
        vectorNormalize(norm);

        // Collision for polygon edges
        float newpoint[3];
        vectorSub(newpoint, sphereposition, p1);
        float dist2 = vectorDot(newpoint, norm);
        if (dist2 < 0) {
          directcollision = false;
          float projloc = vectorDot(newpoint, v1) / vectorDot(v1, v1);
          if (projloc >= 0 && projloc <= 1) {
            float proj[3];
            vectorScale(proj, v1, projloc);
            float projorth[3];
            vectorSub(projorth, newpoint, proj);
            float l2 = vectorDot(projorth, projorth);
            if (l2 < r * r) {
              vectorNormalize(linenormal, projorth);
              if (dist < 0)
                vectorScale(linenormal, -1);
              linecollision = true;
            }
          }
        }

        // Collision for polygon vertices
        float pointdiff[3];
        vectorSub(pointdiff, sphereposition, p1);
        float l3 = vectorDot(pointdiff, pointdiff);
        if (l3 < r * r) {
          vectorScale(pointnormal, pointdiff, 1.0 / sqrt(l3));
          if (dist < 0)
            vectorScale(pointnormal, -1);
          pointcollision = true;
        }
      }
      if (directcollision) {
        if (dist > maxdist || !planecollision) {
          vectorCopy(normal, polygon->planenormal);
          maxdist = dist;
          planecollision = true;
        }
      }
    }
  }

  if (planecollision) {
    vectorScale(contactpoint, normal, -r);
    vectorAdd(contactpoint, sphereposition);
  } else if (linecollision) {
    vectorScale(contactpoint, linenormal, -r);
    vectorAdd(contactpoint, sphereposition);
    vectorCopy(normal, linenormal);
  } else if (pointcollision) {
    vectorScale(contactpoint, pointnormal, -r);
    vectorAdd(contactpoint, sphereposition);
    vectorCopy(normal, pointnormal);
  } else {
    return false;
  }

  return true;
}
예제 #21
0
bool handleLink(ObjectLink *link) {
  if (!link->enabled)
    return false;

  Object *source = link->object1;
  Object *target = link->object2;

  float normal[3];
  float contactpoint1[3], contactpoint2[3];
  source->transformPoint(contactpoint1, link->point1);
  target->transformPoint(contactpoint2, link->point2);

  float diff[3];
  vectorSub(diff, contactpoint1, contactpoint2);
  vectorNormalize(normal, diff);

  float strength = vectorDot(diff, diff);

  if (strength < 1.0e-5)
    return false;

  float sourcevelocity[3], targetvelocity[3];
  float sourcecontactpoint[3], targetcontactpoint[3];

  vectorSub(sourcecontactpoint, contactpoint1, source->position);
  source->getVelocity(sourcevelocity, sourcecontactpoint);

  vectorSub(targetcontactpoint, contactpoint2, target->position);
  target->getVelocity(targetvelocity, targetcontactpoint);

  float deltavelocity[3];
  vectorSub(deltavelocity, sourcevelocity, targetvelocity);
  float dot = vectorDot(deltavelocity, normal);

  // if (fabs(dot) < EPSILON) return false;
  // if (dot > -1.0e-5 && dot < 1.0e-5) return false;
  // if (dot >= 0) return false;
  // if (dot > -1.0e-5) return false;

  float invmass1 = source->invmass;
  float invmass2 = target->invmass;

  float t1;
  if (source->invmomentofinertia == 0) {
    t1 = 0;
  } else {
    float v1[3];
    vectorCross(v1, sourcecontactpoint, normal);
    vectorScale(v1, source->invmomentofinertia);
    float w1[3];
    vectorCross(w1, v1, sourcecontactpoint);
    t1 = vectorDot(normal, w1);
  }

  float t2;
  if (target->invmomentofinertia == 0) {
    t2 = 0;
  } else {
    float v1[3];
    vectorCross(v1, targetcontactpoint, normal);
    vectorScale(v1, target->invmomentofinertia);
    float w1[3];
    vectorCross(w1, v1, targetcontactpoint);
    t2 = vectorDot(normal, w1);
  }

  float denominator = invmass1 + invmass2 + t1 + t2;

  float impulsesize = (dot + strength * 100) / denominator;

  // printf("%f\n", impulsesize);

  float impulse[3];
  vectorScale(impulse, normal, impulsesize);

  target->addImpulse(impulse, targetcontactpoint);
  target->calculateStateVariables();

  vectorScale(impulse, -1);
  source->addImpulse(impulse, sourcecontactpoint);
  source->calculateStateVariables();

  return true;
}
예제 #22
0
void boundingBoxCollisionPoint(struct Vector* normal, struct Vector* point, struct BoundingBox ai, struct BoundingBox bi, struct BoundingBox af, struct BoundingBox bf)
{
    int i;
    int separartingAxesNum = 0;
    int lastSeparartingAxis = 0;
    struct BoundingBox a;
    struct BoundingBox b;
    double distance, minDistance;
    i=1000;
    while(separartingAxesNum != 1 && i-->0)
    {
        separartingAxesNum = 0;
        a = boundingBoxInterpolate(&ai, &af);
        b = boundingBoxInterpolate(&bi, &bf);

        struct Vector a1 = a.direction = vectorNormalize(a.direction);
        struct Vector a2 = a.up = vectorNormalize(a.up);
        struct Vector a3 = vectorCross(a1, a2);
        struct Vector b1 = b.direction = vectorNormalize(b.direction);
        struct Vector b2 = b.up = vectorNormalize(b.up);
        struct Vector b3 = vectorCross(b1, b2);

        if(boundingBoxSeparationTest(a1, a, b)>0) {separartingAxesNum++; lastSeparartingAxis=0;}
        if(boundingBoxSeparationTest(a2, a, b)>0) {separartingAxesNum++; lastSeparartingAxis=1;}
        if(boundingBoxSeparationTest(a3, a, b)>0) {separartingAxesNum++; lastSeparartingAxis=2;}

        if(boundingBoxSeparationTest(b1, a, b)>0) {separartingAxesNum++; lastSeparartingAxis=3;}
        if(boundingBoxSeparationTest(b2, a, b)>0) {separartingAxesNum++; lastSeparartingAxis=4;}
        if(boundingBoxSeparationTest(b3, a, b)>0) {separartingAxesNum++; lastSeparartingAxis=5;}

        if(boundingBoxSeparationTest(vectorCross(a1, b1), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=6;}
        if(boundingBoxSeparationTest(vectorCross(a1, b2), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=7;}
        if(boundingBoxSeparationTest(vectorCross(a1, b3), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=8;}

        if(boundingBoxSeparationTest(vectorCross(a2, b1), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=9;}
        if(boundingBoxSeparationTest(vectorCross(a2, b2), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=10;}
        if(boundingBoxSeparationTest(vectorCross(a2, b3), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=11;}

        if(boundingBoxSeparationTest(vectorCross(a3, b1), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=12;}
        if(boundingBoxSeparationTest(vectorCross(a3, b2), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=13;}
        if(boundingBoxSeparationTest(vectorCross(a3, b3), a, b)>0) {separartingAxesNum++; lastSeparartingAxis=14;}

        if(separartingAxesNum>1) // is not colliding yet
        {
            ai = a;
            bi = b;
        }
        if(separartingAxesNum<1) // is already colliding
        {
            af = a;
            bf = b;
        }
    }

    if(lastSeparartingAxis<6) // face-vertex
    {
        struct Vector center;
        int pointId = 0;
        struct Vector verticles[6];
        if(lastSeparartingAxis<3) // b-vertex collide with a-face
        {
            boundingBoxGetVerticles(verticles, &b);
            center = a.position;
        }
        else // a-vertex collide with b-face
        {
            boundingBoxGetVerticles(verticles, &a);
            center = b.position;
        }

        switch(lastSeparartingAxis)
        {
            case 0:
                *normal = a.direction;
                distance = a.halfSize.x;
                break;
            case 1:
                *normal = a.up;
                distance = a.halfSize.y;
                break;
            case 2:
                *normal = vectorCross(a.direction, a.up);
                distance = a.halfSize.z;
                break;
            case 3:
                *normal = b.direction;
                distance = b.halfSize.x;
                break;
            case 4:
                *normal = b.up;
                distance = b.halfSize.y;
                break;
            case 5:
                *normal = vectorCross(b.direction, b.up);;
                distance = b.halfSize.z;
                break;
            default:
                *normal = vectorZero();
                distance = 0;
        }

        minDistance = -1;
        for(i=0;i<6;i++)
        {
            distance = vectorPointPlaneDistance(verticles[i], center, *normal);
            if(minDistance < 0 || distance < minDistance)
            {
                minDistance = distance;
                pointId = i;
            }

        }

        *point = verticles[pointId];
    }
    else // edge-edge
    {
        struct Vector a1 = a.direction = vectorNormalize(a.direction);
        struct Vector a2 = a.up = vectorNormalize(a.up);
        struct Vector a3 = vectorNormalize( vectorCross(a1, a2) );
        struct Vector b1 = b.direction = vectorNormalize(b.direction);
        struct Vector b2 = b.up = vectorNormalize(b.up);
        struct Vector b3 = vectorNormalize(vectorCross(b1, b2));

        struct Vector halfEdgeA, halfEdgeB;
        struct Vector halfOffsetA[4];
        struct Vector halfOffsetB[4];
        for(i=0;i<4;i++)
        {switch(lastSeparartingAxis)
        {
                case 6: case 7: case 8:
                    halfEdgeA = vectorTimes(a1, a.halfSize.x);
                    halfOffsetA[i] = vectorAdd( vectorTimes(a1, 0),
                                  vectorAdd( vectorTimes(a2, a.halfSize.y * (1-2*(i%2)) ),
                                             vectorTimes(a3, a.halfSize.z * (i>=2 ? -1 : 1) )));
                    break;
                case 9: case 10: case 11:
                    halfEdgeA = vectorTimes(a2, a.halfSize.y);
                    halfOffsetA[i] = vectorAdd( vectorTimes(a1, a.halfSize.x * (1-2*(i%2))),
                                  vectorAdd( vectorTimes(a2, 0),
                                             vectorTimes(a3, a.halfSize.z * (i>=2 ? -1 : 1))));
                    break;
                case 12: case 13: case 14:
                    halfEdgeA = vectorTimes(a3, a.halfSize.z);
                    halfOffsetA[i] = vectorAdd( vectorTimes(a1, a.halfSize.x * (1-2*(i%2))),
                                  vectorAdd( vectorTimes(a2, a.halfSize.y * (i>=2 ? -1 : 1)),
                                             vectorTimes(a3, 0)));
                    break;
            }
            switch(lastSeparartingAxis)
            {
                case 6: case 9: case 12:
                    halfEdgeB = vectorTimes(b1, b.halfSize.x);
                    halfOffsetB[i] = vectorAdd( vectorTimes(b1, 0),
                                  vectorAdd( vectorTimes(b2, b.halfSize.y * (1-2*(i%2))),
                                             vectorTimes(b3, b.halfSize.z * (i>=2 ? -1 : 1))));
                    break;
                case 7: case 10: case 13:
                    halfEdgeB = vectorTimes(b2, b.halfSize.y);
                    halfOffsetB[i] = vectorAdd( vectorTimes(b1, b.halfSize.x * (1-2*(i%2))),
                                  vectorAdd( vectorTimes(b2, 0),
                                             vectorTimes(b3, b.halfSize.z * (i>=2 ? -1 : 1))));
                    break;
                case 8: case 11: case 14:
                    halfEdgeB = vectorTimes(b3, b.halfSize.z);
                    halfOffsetB[i] = vectorAdd( vectorTimes(b1, b.halfSize.x * (1-2*(i%2))),
                                  vectorAdd( vectorTimes(b2, b.halfSize.y * (i>=2 ? -1 : 1)),
                                             vectorTimes(b3, 0)));
                    break;
            }
        }
        *normal = vectorNormalize( vectorCross(halfEdgeA, halfEdgeB) );

        int edgeAi, edgeBi;
        int edgeA, edgeB;
        minDistance = -1;
        for(edgeAi = 0; edgeAi<4; edgeAi++)
            for(edgeBi = 0; edgeBi<4; edgeBi++)
            {
                distance = vectorDot(*normal, vectorAdd(a.position, halfOffsetA[edgeAi])) - vectorDot(*normal, vectorAdd(b.position, halfOffsetB[edgeBi]));
                distance = fabs(distance);
                if(minDistance == -1 || distance < minDistance)
                {
                    minDistance = distance;
                    edgeA = edgeAi;
                    edgeB = edgeBi;
                }

            }

        struct Vector pointEdgeA = vectorAdd(a.position, halfOffsetA[edgeA]);
        struct Vector pointEdgeB = vectorAdd(b.position, halfOffsetB[edgeB]);

        struct Vector rayVector = vectorNormalize(halfEdgeA);
        struct Vector rayPoint = pointEdgeA;
        struct Vector planePoint = pointEdgeB;
        struct Vector planeNormal = vectorNormalize(vectorCross(vectorNormalize(halfEdgeB), *normal));
        // ray - plane intersection
        double cosAlpha = vectorDot(rayVector, planeNormal);
        double distance = vectorPointPlaneDistance(rayPoint, planePoint, planeNormal);
        struct Vector pointA = vectorAdd(rayPoint, vectorTimes(rayVector, cosAlpha*distance)) ;

        rayVector = vectorNormalize(halfEdgeB);
        rayPoint = pointEdgeB;
        planePoint = pointEdgeA;
        planeNormal = vectorNormalize(vectorCross(vectorNormalize(halfEdgeA), *normal));
        // ray - plane intersection
        cosAlpha = vectorDot(rayVector, planeNormal);
        distance = vectorPointPlaneDistance(rayPoint, planePoint, planeNormal);
        struct Vector pointB = vectorAdd(rayPoint, vectorTimes(rayVector, cosAlpha*distance)) ;
        *point = vectorTimes(vectorAdd(pointA, pointB),0.5);
    }

    /* normal should point in direction from A to B*/

    double smallValue = 0.001;
    if(vectorLength(vectorSub(vectorAdd(*point,vectorTimes(*normal, smallValue)), a.position))
            <
       vectorLength(vectorSub(vectorAdd(*point,vectorZero()), a.position))) /*  |point + normal - A| < |point-A| */
            *normal = vectorTimes(*normal, -1.0);
    *normal = vectorNormalize(*normal);

}
예제 #23
0
Vertex::Vertex(float x, float y, float z) {
  vectorSet(position, x, y, z);
  vectorSet(normal, x, y, z);
  vectorNormalize(normal);
}