Example #1
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);
}
Example #2
0
/* Check if the ray and sphere intersect */
bool intersectRaySphere(ray *r, sphere *s){
	/* A = d.d, the vector dot product of the direction */
	float A = vectorDot(&r->dir, &r->dir); 
	
	/* We need a vector representing the distance between the start of 
	 * the ray and the position of the circle.
	 * This is the term (p0 - c) 
	 */
	vector dist = vectorSub(&r->start, &s->pos);
	
	/* 2d.(p0 - c) */  
	float B = 2 * vectorDot(&r->dir, &dist);
	
	/* (p0 - c).(p0 - c) - r^2 */
	float C = vectorDot(&dist, &dist) - (s->radius * s->radius);
	
	/* Solving the discriminant */
	float discr = B * B - 4 * A * C;
	
	/* If the discriminant is negative, there are no real roots.
	 * Return false in that case as the ray misses the sphere.
	 * Return true in all other cases (can be one or two intersections)
	 */
	if(discr < 0)
		return false;
	else
		return true;
}
Example #3
0
float MeshShape::calculateMomentOfInertia(float *rotationvector) {
  if (vectorDot(rotationvector, rotationvector) < EPSILON)
    return 0;
  int i;
  float j = 0;
  for (i = 0; i < mesh->vertexcount; i++) {
    float proj[3];
    vectorProject(proj, mesh->vertices[i].position, rotationvector);
    vectorSub(proj, mesh->vertices[i].position, proj);
    // float r = vectorLength(proj);
    float r2 = vectorDot(proj, proj);
    j += r2;
  }
  return j / i;
}
Vector Biot_Savart_SingleLineSeg(LineSeg seg,Vector fieldpoint)
{

    Vector result,r,Seg_Cross_r;
    Vector SegMidPoint,SegVector,SegDirection;
    Vector BDirection;
    double SegLength,x,z,constval;
    double Bmag;


    SegMidPoint=linesegCenter(seg);
    SegLength=linesegLength(seg);
    SegVector=linesegVector(seg);
    SegDirection=vectorUnitVector(SegVector);


    r=linesegVector(linesegGenerate(SegMidPoint,fieldpoint));
    Seg_Cross_r=vectorCross(SegVector,r);
    BDirection=vectorUnitVector(Seg_Cross_r);
    z=vectorMagnitude(Seg_Cross_r)/SegLength;
    constval=mu_0/(4*M_PI*z);
    x=vectorDot(SegDirection,r);
    if(z == 0)
    {
	Bmag=0;
    }
    else
    {
	Bmag=constval*((SegLength-2*x)/sqrt((SegLength-2*x)*(SegLength-2*x)+4*z*z)+(SegLength+2*x)/sqrt((SegLength+2*x)*(SegLength+2*x)+4*z*z));
    }
    //printf("Bmag %g\n",Bmag);
    result=vectorScale(BDirection,Bmag);
    //printf("result.x,result.y,result.z %g,%g,%g\n",result.x,result.y,result.z);
    return result;
}
void MagneticSensorLsm303::vectorNormalize(vector<float> *a)
{
  float mag = sqrt(vectorDot(a, a));
  a->x /= mag;
  a->y /= mag;
  a->z /= mag;
}
Example #6
0
/* Returns Positive on separation - gives distance*/
double boundingBoxSeparationTest(struct Vector L, struct BoundingBox a, struct BoundingBox b)
{
    double R = fabs(vectorDot(L, vectorSub(a.position, b.position)));
    double R0 = a.halfSize.x*fabs(vectorDot(L, a.direction)) +
                a.halfSize.y*fabs(vectorDot(L, a.up)) +
                a.halfSize.z*fabs(vectorDot(L, vectorCross(a.up, a.direction)));
    double R1 = b.halfSize.x*fabs(vectorDot(L, b.direction)) +
                b.halfSize.y*fabs(vectorDot(L, b.up)) +
                b.halfSize.z*fabs(vectorDot(L, vectorCross(b.up, b.direction)));
    return R - (R0 + R1);
}
Example #7
0
/* Check if a ray collides with a sphere */
bool collideRaySphere(ray *r, sphere *s, double *t)
{

        /* Ray/Sphere intersection
		 *
         * collideRaySpere(ray,sphere)
         *      Vector distance = ray.start - sphere.position
         *      B = distance dot ray.direction
         *      C = distance dot distance - sphere.radius^2
         *	Discriminant = B^2 - C
         *	Discriminant < 0 --> no collision
         *	Otherwise select closest solution
         */

        vector dist = vectorSub(&r->start, &s->pos);
        double B = vectorDot(&dist, &r->dir);

        double D = B * B - vectorDot(&dist, &dist) + s->size * s->size;

        /* Discriminant less than 0 ? */
        if (D < 0.0f)
                return FALSE;

        double t0 = -B - sqrtf(D);
        double t1 = -B + sqrtf(D);

        bool retvalue = FALSE;

        if ((t0 > 0.1f) && (t0 < *t)) {
                *t = t0;
                retvalue = TRUE;
        }
        if ((t1 > 0.1f) && (t1 < *t)) {
                *t = t1;
                retvalue = TRUE;
        }

        return retvalue;
}
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;
}
Example #9
0
/* Not really the best or most accurate way, but it works... */
double AutoExposure(scene *myScene)
{
#define ACCUMULATION_SIZE 256
        double exposure = -1.0f;
        double accumulationfactor = (double)max(myScene->width, myScene->height);
        double projectionDistance = 0.0f;

        if ((myScene->persp.type == CONIC) && myScene->persp.FOV > 0.0f && myScene->persp.FOV < 189.0f) {
                projectionDistance = 0.5f * myScene->width / tanf ((double)(PIOVER180) * 0.5f * myScene->persp.FOV);
        }

        accumulationfactor = accumulationfactor / ACCUMULATION_SIZE;
        colour mediumPoint = {0.0f, 0.0f, 0.0f};
        const double mediumPointWeight = 1.0f / (ACCUMULATION_SIZE*ACCUMULATION_SIZE);
        int x,y;
        for (y = 0; y < ACCUMULATION_SIZE; ++y) {
                for (x = 0 ; x < ACCUMULATION_SIZE; ++x) {

                        if (myScene->persp.type == ORTHOGONAL || projectionDistance == 0.0f) {

                                ray viewRay = { {(double)x*accumulationfactor, (double)y * accumulationfactor, -10000.0f}, { 0.0f, 0.0f, 1.0f}};
                                colour currentColor = raytrace(&viewRay, myScene);
                                colour tmp = colourMul(&currentColor, &currentColor);
                                tmp = colourCoefMul(mediumPointWeight, &tmp);
                                mediumPoint = colourAdd(&mediumPoint,&tmp);
                        } else {
                                vector dir = {((double)(x)*accumulationfactor - 0.5f * myScene->width) / projectionDistance,
                                              ((double)(y)*accumulationfactor - 0.5f * myScene->height) / projectionDistance,
                                              1.0f
                                             };
                                double norm = vectorDot(&dir,&dir);
                                if (norm == 0.0f)
                                        break;
                                dir = vectorScale(invsqrtf(norm), &dir);
                                ray viewRay = { {0.5f * myScene->width,  0.5f * myScene->height, 0.0f}, {dir.x, dir.y, dir.z} };
                                colour currentColor = raytrace(&viewRay, myScene);
                                colour tmp = colourMul(&currentColor, &currentColor);
                                tmp = colourCoefMul(mediumPointWeight, &tmp);
                                mediumPoint = colourAdd(&mediumPoint,&tmp);
                        }
                }
        }

        double mediumLuminance = sqrtf(0.2126f * mediumPoint.red + 0.715160f * mediumPoint.green + 0.072169f * mediumPoint.blue);
        if (mediumLuminance > 0.001f) {
                // put the medium luminance to an intermediate gray value
                exposure = logf(0.6f) / mediumLuminance;
        }
        return exposure;
}
Example #10
0
bool tracePlane(tracehit *result, float *origin, float *ray,
                class Polygon *polygon) {
  float *normal = polygon->planenormal;
  float D = polygon->planedistance;
  float denominator = vectorDot(normal, ray);
  if (denominator == 0) {
    if (vectorDot(normal, origin) > 0)
      result->t = 1000000;
    else
      result->t = -1000000;
    result->polygon = polygon;
    return true;
  }

  float t = -(vectorDot(normal, origin) + D) / denominator;

  result->t = t;
  result->polygon = polygon;

  // if (t < 0 || t > 1) return false;

  return true;
}
Example #11
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);
    }
  }
}
Example #12
0
bool checkEdgeMeshCollision(float *p1, float *p2, Mesh *mesh, float *normal,
                            float *contactpoint) {
  float ray[3];
  vectorSub(ray, p2, p1);

  // UNUSED//float maxdist = 0;
  // UNUSED//bool collision = false;

  int i, j;

  tracehit hits[MAXPOLYGONS];
  int hitcount = 0;

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

    if (tracePlane(&hits[hitcount], p1, ray, polygon)) {
      hitcount++;
    }
  }

  if (hitcount < 2)
    return false;

  for (i = 1; i < hitcount; i++) {
    for (j = i; j > 0; j--) {
      if (hits[j].t < hits[j - 1].t) {
        float tempt = hits[j].t;
        hits[j].t = hits[j - 1].t;
        hits[j - 1].t = tempt;
        class Polygon *tempp = hits[j].polygon;
        hits[j].polygon = hits[j - 1].polygon;
        hits[j - 1].polygon = tempp;
      } else
        break;
    }
  }

  int negative = -1, positive = -1;

  for (i = 0; i < hitcount; i++) {
    // UNUSED//float t = hits[i].t;
    class Polygon *polygon = hits[i].polygon;

    float dot = vectorDot(ray, polygon->planenormal);

    if (dot > 0 && positive == -1)
      positive = i;
    if (dot < 0)
      negative = i;

    if (dot < 0 && positive != -1)
      return false;
  }

  if (negative == -1 || positive == -1)
    return false;

  /*for (i = 0; i < hitcount; i++){
      float t = hits[i].t;
      class Polygon *polygon = hits[i].polygon;

      float dot = vectorDot(ray, polygon->planenormal);

      printf("%f ", dot);
  }
  printf("\n");*/

  if (hits[negative].t < 0 || hits[positive].t > 1)
    return false;

  Edge *edge2 = findSharingEdge(hits[negative].polygon, hits[positive].polygon);

  // fflush(stdout);
  float cp1[3], cp2[3];
  vectorScale(cp1, ray, hits[negative].t);
  vectorAdd(cp1, p1);
  vectorScale(cp2, ray, hits[positive].t);
  vectorAdd(cp2, p1);

  if (edge2 != NULL) {

    /*float ev1[3];
    vectorSub(ev1, edge2->v2->position, edge2->v1->position);
    vectorCross(normal, ev1, ray);
    vectorScale(normal, vectorDot(normal, hits[positive].polygon->planenormal));
    vectorNormalize(normal);

    float at = (hits[negative].t + hits[positive].t) / 2;
    vectorScale(contactpoint, ray, at);
    vectorAdd(contactpoint, p1);*/

    float dot1 = fabs(vectorDot(ray, hits[negative].polygon->planenormal));
    float dot2 = fabs(vectorDot(ray, hits[positive].polygon->planenormal));

    if (dot1 > dot2) {
      // vectorScale(contactpoint, ray, hits[negative].t);
      // vectorAdd(contactpoint, p1);
      vectorCopy(contactpoint, cp1);
      vectorCopy(normal, hits[positive].polygon->planenormal);
    } else {
      // vectorScale(contactpoint, ray, hits[positive].t);
      // vectorAdd(contactpoint, p1);
      vectorCopy(contactpoint, cp2);
      vectorCopy(normal, hits[negative].polygon->planenormal);
    }
  } else {
    Polygon *polygon = findNearestPolygon(hits[negative].polygon, cp1);
    if (polygon != NULL) {
      /*vectorCopy(contactpoint, cp1);
      vectorAdd(contactpoint, cp2);
      vectorScale(contactpoint, 0.5);*/
      float at = (hits[negative].t + hits[positive].t) / 2;
      vectorScale(contactpoint, ray, at);
      vectorAdd(contactpoint, p1);

      vectorCopy(normal, polygon->planenormal);
    } else {
      return false;
    }
  }

  // shotsound->play();
  return true;
}
Example #13
0
/***************************************
 *         Conjugate Gradient          *
 *   This function will do the CG      *
 *  algorithm without preconditioning. *
 *    For optimiziation you must not   *
 *        change the algorithm.        *
 ***************************************
 r(0)    = b - Ax(0)
 p(0)    = r(0)
 rho(0)    =  <r(0),r(0)>                
 ***************************************
 for k=0,1,2,...,n-1
   q(k)      = A * p(k)                 
   dot_pq    = <p(k),q(k)>             
   alpha     = rho(k) / dot_pq
   x(k+1)    = x(k) + alpha*p(k)      
   r(k+1)    = r(k) - alpha*q(k)     
   check convergence ||r(k+1)||_2 < eps  
	 rho(k+1)  = <r(k+1), r(k+1)>         
   beta      = rho(k+1) / rho(k)
   p(k+1)    = r(k+1) + beta*p(k)      
***************************************/
void cg(const int n, const int nnz, const int maxNNZ, const floatType* data, const int* indices, const int* length, const floatType* b, floatType* x, struct SolverConfig* sc){

	floatType* r, *p, *q;
	floatType alpha, beta, rho, rho_old, dot_pq, bnrm2;
	int iter;
 	double timeMatvec_s;
 	double timeMatvec=0;
	int i;
	floatType temp;
	
	/* allocate memory */
	r = (floatType*)malloc(n * sizeof(floatType));
	p = (floatType*)malloc(n * sizeof(floatType));
	q = (floatType*)malloc(n * sizeof(floatType));
	
#pragma acc data copyin(data[0:n*maxNNZ], indices[0:n*maxNNZ], length[0:n], n, nnz, maxNNZ, b[0:n]) copy(x[0:n]) create(alpha, beta, r[0:n], p[0:n], q[0:n], i, temp) //eigentlich auch copy(x[0:n]) aber error: not found on device???
{
	DBGMAT("Start matrix A = ", n, nnz, maxNNZ, data, indices, length)
	DBGVEC("b = ", b, n);
	DBGVEC("x = ", x, n);

	/* r(0)    = b - Ax(0) */
	timeMatvec_s = getWTime();
	matvec(n, nnz, maxNNZ, data, indices, length, x, r);
//hier inline ausprobieren
/*int i, j, k;
#pragma acc parallel loop present(data, indices, length, x)
	for (i = 0; i < n; i++) {
		r[i] = 0;
		for (j = 0; j < length[i]; j++) {
			k = j * n + i;
			r[i] += data[k] * x[indices[k]];
		}
	}*/
	timeMatvec += getWTime() - timeMatvec_s;
	xpay(b, -1.0, n, r);
	DBGVEC("r = b - Ax = ", r, n);
	

	/* Calculate initial residuum */
	nrm2(r, n, &bnrm2);
	bnrm2 = 1.0 /bnrm2;

	/* p(0)    = r(0) */
	memcpy(p, r, n*sizeof(floatType));
	DBGVEC("p = r = ", p, n);

	/* rho(0)    =  <r(0),r(0)> */
	vectorDot(r, r, n, &rho);
	printf("rho_0=%e\n", rho);

	for(iter = 0; iter < sc->maxIter; iter++){
		DBGMSG("=============== Iteration %d ======================\n", iter);
		/* q(k)      = A * p(k) */
		timeMatvec_s = getWTime();
		matvec(n, nnz, maxNNZ, data, indices, length, p, q);
		timeMatvec += getWTime() - timeMatvec_s;
		DBGVEC("q = A * p= ", q, n);

		/* dot_pq    = <p(k),q(k)> */
		vectorDot(p, q, n, &dot_pq);
		DBGSCA("dot_pq = <p, q> = ", dot_pq);

		/* alpha     = rho(k) / dot_pq */
		alpha = rho / dot_pq;
		DBGSCA("alpha = rho / dot_pq = ", alpha);

		/* x(k+1)    = x(k) + alpha*p(k) */
		axpy(alpha, p, n, x);
#pragma acc update host(x[0:n])
		DBGVEC("x = x + alpha * p= ", x, n);

		/* r(k+1)    = r(k) - alpha*q(k) */
		axpy(-alpha, q, n, r);
		DBGVEC("r = r - alpha * q= ", r, n);


		rho_old = rho;
		DBGSCA("rho_old = rho = ", rho_old);


		/* rho(k+1)  = <r(k+1), r(k+1)> */
		vectorDot(r, r, n, &rho);
		DBGSCA("rho = <r, r> = ", rho);

		/* Normalize the residual with initial one */
		sc->residual= sqrt(rho) * bnrm2;


   	
		/* Check convergence ||r(k+1)||_2 < eps
		 * If the residual is smaller than the CG
		 * tolerance specified in the CG_TOLERANCE
		 * environment variable our solution vector
		 * is good enough and we can stop the 
		 * algorithm. */
		printf("res_%d=%e\n", iter+1, sc->residual);
		if(sc->residual <= sc->tolerance)
			break;


		/* beta      = rho(k+1) / rho(k) */
		beta = rho / rho_old;
		DBGSCA("beta = rho / rho_old= ", beta);

		/* p(k+1)    = r(k+1) + beta*p(k) */
		xpay(r, beta, n, p);
		DBGVEC("p = r + beta * p> = ", p, n);

	}

	/* Store the number of iterations and the 
	 * time for the sparse matrix vector
	 * product which is the most expensive 
	 * function in the whole CG algorithm. */
	sc->iter = iter;
	sc->timeMatvec = timeMatvec;

	/* Clean up */
	free(r);
	free(p);
	free(q);
}//ende data region
}
Example #14
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);

}
/**
 * Solves a linear least squares problem to obtain a N degree polynomial that fits
 * the specified input data as nearly as possible.
 *
 * Returns true if a solution is found, false otherwise.
 *
 * The input consists of two vectors of data points X and Y with indices 0..m-1
 * along with a weight vector W of the same size.
 *
 * The output is a vector B with indices 0..n that describes a polynomial
 * that fits the data, such the sum of W[i] * W[i] * abs(Y[i] - (B[0] + B[1] X[i]
 * + B[2] X[i]^2 ... B[n] X[i]^n)) for all i between 0 and m-1 is minimized.
 *
 * Accordingly, the weight vector W should be initialized by the caller with the
 * reciprocal square root of the variance of the error in each input data point.
 * In other words, an ideal choice for W would be W[i] = 1 / var(Y[i]) = 1 / stddev(Y[i]).
 * The weights express the relative importance of each data point.  If the weights are
 * all 1, then the data points are considered to be of equal importance when fitting
 * the polynomial.  It is a good idea to choose weights that diminish the importance
 * of data points that may have higher than usual error margins.
 *
 * Errors among data points are assumed to be independent.  W is represented here
 * as a vector although in the literature it is typically taken to be a diagonal matrix.
 *
 * That is to say, the function that generated the input data can be approximated
 * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
 *
 * The coefficient of determination (R^2) is also returned to describe the goodness
 * of fit of the model for the given data.  It is a value between 0 and 1, where 1
 * indicates perfect correspondence.
 *
 * This function first expands the X vector to a m by n matrix A such that
 * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n, then
 * multiplies it by w[i]./
 *
 * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
 * and an m by n upper triangular matrix R.  Because R is upper triangular (lower
 * part is all zeroes), we can simplify the decomposition into an m by n matrix
 * Q1 and a n by n matrix R1 such that A = Q1 R1.
 *
 * Finally we solve the system of linear equations given by R1 B = (Qtranspose W Y)
 * to find B.
 *
 * For efficiency, we lay out A and Q column-wise in memory because we frequently
 * operate on the column vectors.  Conversely, we lay out R row-wise.
 *
 * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
 * http://en.wikipedia.org/wiki/Gram-Schmidt
 */
static bool solveLeastSquares(const float* x, const float* y,
        const float* w, uint32_t m, uint32_t n, float* outB, float* outDet) {
#if DEBUG_STRATEGY
    ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
            vectorToString(x, m).c_str(), vectorToString(y, m).c_str(),
            vectorToString(w, m).c_str());
#endif

    // Expand the X vector to a matrix A, pre-multiplied by the weights.
    float a[n][m]; // column-major order
    for (uint32_t h = 0; h < m; h++) {
        a[0][h] = w[h];
        for (uint32_t i = 1; i < n; i++) {
            a[i][h] = a[i - 1][h] * x[h];
        }
    }
#if DEBUG_STRATEGY
    ALOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str());
#endif

    // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
    float q[n][m]; // orthonormal basis, column-major order
    float r[n][n]; // upper triangular matrix, row-major order
    for (uint32_t j = 0; j < n; j++) {
        for (uint32_t h = 0; h < m; h++) {
            q[j][h] = a[j][h];
        }
        for (uint32_t i = 0; i < j; i++) {
            float dot = vectorDot(&q[j][0], &q[i][0], m);
            for (uint32_t h = 0; h < m; h++) {
                q[j][h] -= dot * q[i][h];
            }
        }

        float norm = vectorNorm(&q[j][0], m);
        if (norm < 0.000001f) {
            // vectors are linearly dependent or zero so no solution
#if DEBUG_STRATEGY
            ALOGD("  - no solution, norm=%f", norm);
#endif
            return false;
        }

        float invNorm = 1.0f / norm;
        for (uint32_t h = 0; h < m; h++) {
            q[j][h] *= invNorm;
        }
        for (uint32_t i = 0; i < n; i++) {
            r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
        }
    }
#if DEBUG_STRATEGY
    ALOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).c_str());
    ALOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).c_str());

    // calculate QR, if we factored A correctly then QR should equal A
    float qr[n][m];
    for (uint32_t h = 0; h < m; h++) {
        for (uint32_t i = 0; i < n; i++) {
            qr[i][h] = 0;
            for (uint32_t j = 0; j < n; j++) {
                qr[i][h] += q[j][h] * r[j][i];
            }
        }
    }
    ALOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).c_str());
#endif

    // Solve R B = Qt W Y to find B.  This is easy because R is upper triangular.
    // We just work from bottom-right to top-left calculating B's coefficients.
    float wy[m];
    for (uint32_t h = 0; h < m; h++) {
        wy[h] = y[h] * w[h];
    }
    for (uint32_t i = n; i != 0; ) {
        i--;
        outB[i] = vectorDot(&q[i][0], wy, m);
        for (uint32_t j = n - 1; j > i; j--) {
            outB[i] -= r[i][j] * outB[j];
        }
        outB[i] /= r[i][i];
    }
#if DEBUG_STRATEGY
    ALOGD("  - b=%s", vectorToString(outB, n).c_str());
#endif

    // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
    // SSerr is the residual sum of squares (variance of the error),
    // and SStot is the total sum of squares (variance of the data) where each
    // has been weighted.
    float ymean = 0;
    for (uint32_t h = 0; h < m; h++) {
        ymean += y[h];
    }
    ymean /= m;

    float sserr = 0;
    float sstot = 0;
    for (uint32_t h = 0; h < m; h++) {
        float err = y[h] - outB[0];
        float term = 1;
        for (uint32_t i = 1; i < n; i++) {
            term *= x[h];
            err -= term * outB[i];
        }
        sserr += w[h] * w[h] * err * err;
        float var = y[h] - ymean;
        sstot += w[h] * w[h] * var * var;
    }
    *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
#if DEBUG_STRATEGY
    ALOGD("  - sserr=%f", sserr);
    ALOGD("  - sstot=%f", sstot);
    ALOGD("  - det=%f", *outDet);
#endif
    return true;
}
Example #16
0
void *renderThread(void *arg)
{

        int x,y;
        thread_info *tinfo = (thread_info *)arg;

        /* Calculate which part to render based on thread id */
        int limits[]={(tinfo->thread_num*sectionsize),(tinfo->thread_num*sectionsize)+sectionsize};

        /* Autoexposure */
        double exposure = AutoExposure(myScene);

        double projectionDistance = 0.0f;
        if ((myScene->persp.type == CONIC) && myScene->persp.FOV > 0.0f && myScene->persp.FOV < 189.0f) {
                projectionDistance = 0.5f * myScene->width / tanf((double)(PIOVER180) * 0.5f * myScene->persp.FOV);
        }


        for (y = limits[0]; y < limits[1]; ++y) {
                for (x = 0; x < myScene->width; ++x) {
                        colour output = {0.0f, 0.0f, 0.0f};
                        double fragmentx, fragmenty;

                        /* Antialiasing */
                        for (fragmentx = x; fragmentx < x + 1.0f; fragmentx += 0.5f) {
                                for (fragmenty = y; fragmenty < y + 1.0f; fragmenty += 0.5f) {
                                        double sampleRatio=0.25f;
                                        colour temp = {0.0f, 0.0f, 0.0f};
                                        double totalWeight = 0.0f;

                                        if (myScene->persp.type == ORTHOGONAL || projectionDistance == 0.0f) {
                                                ray viewRay = { {fragmentx, fragmenty, -10000.0f},{ 0.0f, 0.0f, 1.0f}};
                                                int i;
                                                for (i = 0; i < myScene->complexity; ++i) {
                                                        colour result = raytrace(&viewRay, myScene);
                                                        totalWeight += 1.0f;
                                                        temp = colourAdd(&temp,&result);
                                                }
                                                temp = colourCoefMul((1.0f/totalWeight), &temp);
                                        } else {
                                                vector dir = {(fragmentx - 0.5f * myScene->width) / projectionDistance,
                                                              (fragmenty - 0.5f * myScene->height) / projectionDistance,
                                                              1.0f
                                                             };

                                                double norm = vectorDot(&dir,&dir);
                                                if (norm == 0.0f)
                                                        break;

                                                dir = vectorScale(invsqrtf(norm),&dir);

                                                vector start = {0.5f * myScene->width,  0.5f * myScene->height, 0.0f};

                                                vector tmp = vectorScale(myScene->persp.clearPoint,&dir);
                                                vector observed = vectorAdd(&start,&tmp);

                                                int i;
                                                for (i = 0; i < myScene->complexity; ++i) {
                                                        ray viewRay = { {start.x, start.y, start.z}, {dir.x, dir.y, dir.z} };

                                                        if (myScene->persp.dispersion != 0.0f) {
                                                                vector disturbance;
                                                                disturbance.x = (myScene->persp.dispersion / RAND_MAX) * (1.0f * rand());
                                                                disturbance.y = (myScene->persp.dispersion / RAND_MAX) * (1.0f * rand());
                                                                disturbance.z = 0.0f;

                                                                viewRay.start = vectorAdd(&viewRay.start, &disturbance);
                                                                viewRay.dir = vectorSub(&observed, &viewRay.start);
                                                                norm = vectorDot(&viewRay.dir,&viewRay.dir);

                                                                if (norm == 0.0f)
                                                                        break;

                                                                viewRay.dir = vectorScale(invsqrtf(norm),&viewRay.dir);
                                                        }
                                                        colour result = raytrace(&viewRay, myScene);
                                                        totalWeight += 1.0f;
                                                        temp = colourAdd(&temp,&result);
                                                }
                                                temp = colourCoefMul((1.0f/totalWeight), &temp);
                                        }

                                        temp.blue = (1.0f - expf(temp.blue * exposure));
                                        temp.red =  (1.0f - expf(temp.red * exposure));
                                        temp.green = (1.0f - expf(temp.green * exposure));

                                        colour adjusted = colourCoefMul(sampleRatio, &temp);
                                        output = colourAdd(&output, &adjusted);
                                }
                        }

                        /* gamma correction */
                        double invgamma = 0.45f; //Fixed value from sRGB standard
                        output.blue = powf(output.blue, invgamma);
                        output.red = powf(output.red, invgamma);
                        output.green = powf(output.green, invgamma);

                        img[(x+y*myScene->width)*3+2] = (unsigned char)min(output.red*255.0f, 255.0f);
                        img[(x+y*myScene->width)*3+1] = (unsigned char)min(output.green*255.0f, 255.0f);
                        img[(x+y*myScene->width)*3+0] = (unsigned char)min(output.blue*255.0f,255.0f);
                }
        }
        pthread_exit((void *) arg);
}
Example #17
0
colour raytrace(ray *viewRay, scene *myScene)
{
        colour output = {0.0f, 0.0f, 0.0f};
        double coef = 1.0f;
        int level = 0;
	
        do {
                vector hitpoint,n;
                int currentSphere = -1;
                int currentTriangle = -1;
                material currentMat;
                double t = 20000.0f;
                double temp;
                vector n1;

                unsigned int i;
                for (i = 0; i < myScene->numSpheres; ++i) {
                        if (collideRaySphere(viewRay, &myScene->spheres[i], &t)) {
                                currentSphere = i;
                        }
                }

                for (i = 0; i < myScene->numTriangles; ++i) {
                        if (collideRayTriangle(viewRay, &myScene->triangles[i], &t, &n1)) {
                                currentTriangle = i;
                                currentSphere = -1;
                        }
                }

                if (currentSphere != -1) {
                        vector scaled = vectorScale(t, &viewRay->dir);
                        hitpoint = vectorAdd(&viewRay->start, &scaled);
                        n = vectorSub(&hitpoint, &myScene->spheres[currentSphere].pos);
                        temp = vectorDot(&n,&n);
                        if (temp == 0.0f) break;
                        temp = invsqrtf(temp);
                        n = vectorScale(temp, &n);
                        currentMat = myScene->materials[myScene->spheres[currentSphere].material];
                } else if (currentTriangle != -1) {
                        vector scaled = vectorScale(t, &viewRay->dir);
                        hitpoint = vectorAdd(&viewRay->start, &scaled);
                        n=n1;
                        temp = vectorDot(&n,&n);
                        if (temp == 0.0f) break;
                        temp = invsqrtf(temp);
                        n = vectorScale(temp, &n);
                        currentMat = myScene->materials[myScene->triangles[currentTriangle].material];
                } else {
                        /* No hit - add background */
                       	colour test = {0.05,0.05,0.35};
                        colour tmp = colourCoefMul(coef, &test);
                        output = colourAdd(&output,&tmp);
                        break;
                }

                /* Bump mapping using Perlin noise */
                if (currentMat.bump != 0.0) {

                        double noiseCoefx = noise(0.1 * hitpoint.x, 0.1 * hitpoint.y, 0.1 * hitpoint.z, myNoise);
                        double noiseCoefy = noise(0.1 * hitpoint.y, 0.1 * hitpoint.z, 0.1 * hitpoint.x, myNoise);
                        double noiseCoefz = noise(0.1 * hitpoint.z, 0.1 * hitpoint.x, 0.1 * hitpoint.y, myNoise);


                        n.x = (1.0f - currentMat.bump ) * n.x + currentMat.bump * noiseCoefx;
                        n.y = (1.0f - currentMat.bump ) * n.y + currentMat.bump * noiseCoefy;
                        n.z = (1.0f - currentMat.bump ) * n.z + currentMat.bump * noiseCoefz;

                        temp = vectorDot(&n, &n);
                        if (temp == 0.0f) {
                                break;
                        }
                        temp = invsqrtf(temp);
                        n = vectorScale(temp, &n);
                }

                bool inside;

                if (vectorDot(&n,&viewRay->dir) > 0.0f) {
                        n = vectorScale(-1.0f,&n);
                        inside = TRUE;
                } else {
                        inside = FALSE;
                }

                if (!inside) {

                        ray lightRay;
                        lightRay.start = hitpoint;

                        /* Find the value of the light at this point */
                        unsigned int j;
                        for (j = 0; j < myScene->numLights; ++j) {
                                light currentLight = myScene->lights[j];
                                lightRay.dir = vectorSub(&currentLight.pos,&hitpoint);

                                double lightprojection = vectorDot(&lightRay.dir,&n);

                                if ( lightprojection <= 0.0f ) continue;

                                double lightdist = vectorDot(&lightRay.dir,&lightRay.dir);
                                double temp = lightdist;

                                if ( temp == 0.0f ) continue;
                                temp = invsqrtf(temp);
                                lightRay.dir = vectorScale(temp,&lightRay.dir);
                                lightprojection = temp * lightprojection;

                                /* Calculate the shadows */
                                bool inshadow = FALSE;
                                double t = lightdist;

                                unsigned int k;

                                for (k = 0; k < myScene->numSpheres; ++k) {
                                        if (collideRaySphere(&lightRay, &myScene->spheres[k], &t)) {
                                                inshadow = TRUE;
                                                break;
                                        }

                                }

                                for (k = 0; k < myScene->numTriangles; ++k) {
                                        if (collideRayTriangle(&lightRay, &myScene->triangles[k], &t, &n1)) {
                                                inshadow = TRUE;
                                                break;
                                        }
                                }


                                if (!inshadow) {
                                        /* Diffuse refraction using Lambert */
                                        double lambert = vectorDot(&lightRay.dir, &n) * coef;
                                        double noiseCoef = 0.0f;
                                        int level = 0;
                                        switch (currentMat.MatType) {

                                        case TURBULENCE:
                                                for (level = 1; level < 10; level++) {
                                                        noiseCoef += (1.0f / level )
                                                                     * fabsf(noise(level * 0.05 * hitpoint.x,
                                                                                   level * 0.05 * hitpoint.y,
                                                                                   level * 0.05 * hitpoint.z,
                                                                                   myNoise));
                                                }
                                                colour diff1 = colourCoefMul(noiseCoef,&currentMat.diffuse);
                                                colour diff2 = colourCoefMul((1.0f - noiseCoef), &currentMat.mdiffuse);
                                                colour temp1 = colourAdd(&diff1, &diff2);
                                                output = colourAdd(&output, &temp1);
                                                break;

                                        case MARBLE:
                                                for (level = 1; level < 10; level ++) {
                                                        noiseCoef +=  (1.0f / level)
                                                                      * fabsf(noise(level * 0.05 * hitpoint.x,
                                                                                    level * 0.05 * hitpoint.y,
                                                                                    level * 0.05 * hitpoint.z,
                                                                                    myNoise));
                                                }
                                                noiseCoef = 0.5f * sinf( (hitpoint.x + hitpoint.y) * 0.05f + noiseCoef) + 0.5f;
                                                colour diff3 = colourCoefMul(noiseCoef,&currentMat.diffuse);
                                                colour diff4 = colourCoefMul((1.0f - noiseCoef), &currentMat.mdiffuse);
                                                colour tmp1 = colourAdd(&diff3, &diff4);

                                                colour lamint = colourCoefMul(lambert, &currentLight.intensity);
                                                colour lamint_scaled = colourCoefMul(coef, &lamint);

                                                colour temp2 = colourMul(&lamint_scaled, &tmp1);
                                                output = colourAdd(&output, &temp2);
                                                break;

                                                /* Basically Gouraud */
                                        default:

                                                output.red += lambert * currentLight.intensity.red * currentMat.diffuse.red;
                                                output.green += lambert * currentLight.intensity.green * currentMat.diffuse.green;
                                                output.blue += lambert * currentLight.intensity.blue * currentMat.diffuse.blue;
                                                break;
                                        }

                                        /* Blinn */
                                        double viewprojection = vectorDot(&viewRay->dir, &n);
                                        vector blinnDir = vectorSub(&lightRay.dir, &viewRay->dir);
                                        double temp = vectorDot(&blinnDir, &blinnDir);
                                        if (temp != 0.0f ) {
                                                double blinn = invsqrtf(temp) * max(lightprojection - viewprojection , 0.0f);
                                                blinn = coef * powf(blinn, currentMat.power);
                                                colour tmp_1 = colourCoefMul(blinn, &currentMat.specular);
                                                colour tmp_2 = colourMul(&tmp_1, &currentLight.intensity);
                                                output = colourAdd(&output, &tmp_2);
                                        }

                                }
                        }
                        /* Iterate over the reflection */

                        coef *= currentMat.reflection;
                        double reflect = 2.0f * vectorDot(&viewRay->dir, &n);
                        viewRay->start = hitpoint;

                        vector tmp = vectorScale(reflect, &n);
                        viewRay->dir = vectorSub(&viewRay->dir, &tmp);
                }
                level++;
                /* Limit iteration depth to 10 */
        } while ((coef > 0.0f) && (level < 10));
        return output;
}
Example #18
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;
}
Example #19
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;
}
Example #20
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;
}