Esempio n. 1
0
/*
** All the three given vectors span only a 2D space, and this finds
** the normal to that plane.  Simply sums up all the pair-wise
** cross-products to get a good estimate.  Trick is getting the cross
** products to line up before summing.
*/
void
nullspace1(double ret[3],
           const double r0[3], const double r1[3], const double r2[3]) {
  double crs[3];

  /* ret = r0 x r1 */
  VEC_CROSS(ret, r0, r1);
  /* crs = r1 x r2 */
  VEC_CROSS(crs, r1, r2);
  /* ret += crs or ret -= crs; whichever makes ret longer */
  if (VEC_DOT(ret, crs) > 0) {
    VEC_ADD(ret, crs);
  } else {
    VEC_SUB(ret, crs);
  }
  /* crs = r0 x r2 */
  VEC_CROSS(crs, r0, r2);
  /* ret += crs or ret -= crs; whichever makes ret longer */
  if (VEC_DOT(ret, crs) > 0) {
    VEC_ADD(ret, crs);
  } else {
    VEC_SUB(ret, crs);
  }

  return;
}
Esempio n. 2
0
BOOL IsPolyInsideSurface(CTempSurface *pSurface, CPrePoly *pPoly)
{
	DWORD i, j;
	CEditPoly *pEditPoly;
	CPrePlane edgePlane;
	PVector vTemp, testPt;
	
	pEditPoly = pSurface->m_pPoly;
	for(i=0; i < pEditPoly->NumVerts(); i++)
	{
		VEC_SUB(vTemp, pEditPoly->NextPt(i), pEditPoly->Pt(i));
		VEC_CROSS(edgePlane.m_Normal, vTemp, pEditPoly->Normal());
		edgePlane.m_Normal.Norm();
		edgePlane.m_Dist = VEC_DOT(edgePlane.m_Normal, pEditPoly->Pt(i));

		for(j=0; j < pPoly->NumVerts(); j++)
		{
			testPt = pPoly->Pt(j);

			if(DIST_TO_PLANE(testPt, edgePlane) < -0.1f)
			{
				return FALSE;
			}
		}
	}

	return TRUE;
}
Esempio n. 3
0
inline bool d3d_ClipSprite(SpriteInstance *pInstance, HPOLY hPoly, 
	T **ppPoints, uint32 *pnPoints, T *pOut)
{
	LTPlane thePlane;
	float dot, d1, d2;
	SPolyVertex *pPrevPoint, *pCurPoint, *pEndPoint;
	LTVector vecTo;
	T *pVerts;
	uint32 nVerts;
	WorldPoly *pPoly;

	if(g_have_world == false)
		return false;
	
	// Get the correct poly.
	pPoly = world_bsp_client->GetPolyFromHPoly(hPoly);
	if(!pPoly)
		return false;

	// First see if the viewer is on the frontside of the poly.
	dot = pPoly->GetPlane()->DistTo(g_ViewParams.m_Pos);
	if(dot <= 0.01f)
		return false;

	pVerts = *ppPoints;
	nVerts = *pnPoints;
	
	// Clip on each edge plane.	
	pEndPoint = &pPoly->GetVertices()[pPoly->GetNumVertices()];
	pPrevPoint = pEndPoint - 1;
	for(pCurPoint=pPoly->GetVertices(); pCurPoint != pEndPoint; )
	{
		VEC_SUB(vecTo, pCurPoint->m_Vertex->m_Vec, pPrevPoint->m_Vertex->m_Vec);
		VEC_CROSS(thePlane.m_Normal, vecTo, pPoly->GetPlane()->m_Normal);
		VEC_NORM(thePlane.m_Normal);
		thePlane.m_Dist = VEC_DOT(thePlane.m_Normal, pCurPoint->m_Vertex->m_Vec);

		#define CLIPTEST PLANETEST
		#define DOCLIP DOPLANECLIP
		#include "polyclip.h"
		#undef CLIPTEST
		#undef DOCLIP

		pPrevPoint = pCurPoint;
		++pCurPoint;
	}

	*ppPoints = pVerts;
	*pnPoints = nVerts;
	return true;
}
Esempio n. 4
0
/*****************************************
 * Read nappe characterization in a file *
 *****************************************/
GEO *
file_geo_nappe (BYTE Type, FILE *File)
{
  GEO_NAPPE  *Geo;
  PNT        *Pnt, *PntA, *PntB, *PntC, *PntD;
  FCT        *Fct;
  VECTOR     U, V;
  REAL       Real;
  INDEX      Index;

  INIT_MEM (Geo, 1, GEO_NAPPE);
  Geo->Type = Type;
  GET_INDEX (Geo->NbrPnt);
  INIT_MEM (Geo->TabPnt, Geo->NbrPnt, PNT);
  GET_INDEX (Geo->NbrFct);
  INIT_MEM (Geo->TabFct, Geo->NbrFct, FCT);
  Geo->Min.x = Geo->Min.y = Geo->Min.z =  INFINITY;
  Geo->Max.x = Geo->Max.y = Geo->Max.z = -INFINITY;

  for (Index = 0, Pnt = Geo->TabPnt; Index < Geo->NbrPnt; Index++, Pnt++) {
    GET_VECTOR (Pnt->Point);
    VEC_MIN (Geo->Min, Pnt->Point);
    VEC_MAX (Geo->Max, Pnt->Point);
  }

  for (Index = 0, Fct = Geo->TabFct; Index < Geo->NbrFct; Index++, Fct++) {
    if (fscanf (File, " ( %d %d %d %d )", &Fct->i, &Fct->j, &Fct->k, &Fct->l) < 4)
      return (FALSE);
    Fct->NumFct = Index;
    PntA = Geo->TabPnt + Fct->i; 
    PntB = Geo->TabPnt + Fct->j;
    PntC = Geo->TabPnt + Fct->k;
    PntD = Geo->TabPnt + Fct->l;
    VEC_SUB (U, PntC->Point, PntA->Point);
    VEC_SUB (V, PntD->Point, PntB->Point);
    VEC_CROSS (Fct->Normal, U, V);
    VEC_UNIT (Fct->Normal, Real);
    VEC_INC (PntA->Normal, Fct->Normal);
    VEC_INC (PntB->Normal, Fct->Normal);
    VEC_INC (PntC->Normal, Fct->Normal);
    VEC_INC (PntD->Normal, Fct->Normal);
  }

  for (Index = 0, Pnt = Geo->TabPnt; Index < Geo->NbrPnt; Index++, Pnt++)
    VEC_UNIT (Pnt->Normal, Real);

  return ((GEO *) Geo);
}
Esempio n. 5
0
/*
** All vectors are in the same 1D space, we have to find two
** mutually vectors perpendicular to that span
*/
void
nullspace2(double reta[3], double retb[3],
           const double r0[3], const double r1[3], const double r2[3]) {
  double sqr[3], sum[3];
  int idx;

  VEC_COPY(sum, r0);
  if (VEC_DOT(sum, r1) > 0) {
    VEC_ADD(sum, r1);
  } else {
    VEC_SUB(sum, r1);
  }
  if (VEC_DOT(sum, r2) > 0) {
    VEC_ADD(sum, r2);
  } else {
    VEC_SUB(sum, r2);
  }
  /* find largest component, to get most stable expression for a
     perpendicular vector */
  sqr[0] = sum[0]*sum[0];
  sqr[1] = sum[1]*sum[1];
  sqr[2] = sum[2]*sum[2];
  idx = 0;
  if (sqr[0] < sqr[1])
    idx = 1;
  if (sqr[idx] < sqr[2])
    idx = 2;
  /* reta will be perpendicular to sum */
  if (0 == idx) {
    VEC_SET(reta, sum[1] - sum[2], -sum[0], sum[0]);
  } else if (1 == idx) {
    VEC_SET(reta, -sum[1], sum[0] - sum[2], sum[1]);
  } else {
    VEC_SET(reta, -sum[2], sum[2], sum[0] - sum[1]);
  }
  /* and now retb will be perpendicular to both reta and sum */
  VEC_CROSS(retb, reta, sum);
  return;
}
Esempio n. 6
0
int
evals_evecs(double eval[3], double evec[9],
            const double _M00, const double _M01, const double _M02,
            const double _M11, const double _M12,
            const double _M22) {
  double r0[3], r1[3], r2[3], crs[3], len, dot;

  double mean, norm, rnorm, Q, R, QQQ, D, theta,
    M00, M01, M02, M11, M12, M22;
  double epsilon = 1.0E-12;
  int roots;

  /* copy the given matrix elements */
  M00 = _M00;
  M01 = _M01;
  M02 = _M02;
  M11 = _M11;
  M12 = _M12;
  M22 = _M22;

  /*
  ** subtract out the eigenvalue mean (will add back to evals later);
  ** helps with numerical stability
  */
  mean = (M00 + M11 + M22)/3.0;
  M00 -= mean;
  M11 -= mean;
  M22 -= mean;

  /*
  ** divide out L2 norm of eigenvalues (will multiply back later);
  ** this too seems to help with stability
  */
  norm = sqrt(M00*M00 + 2*M01*M01 + 2*M02*M02 +
              M11*M11 + 2*M12*M12 +
              M22*M22);
  rnorm = norm ? 1.0/norm : 1.0;
  M00 *= rnorm;
  M01 *= rnorm;
  M02 *= rnorm;
  M11 *= rnorm;
  M12 *= rnorm;
  M22 *= rnorm;

  /* this code is a mix of prior Teem code and ideas from Eberly's
     "Eigensystems for 3 x 3 Symmetric Matrices (Revisited)" */
  Q = (M01*M01 + M02*M02 + M12*M12 - M00*M11 - M00*M22 - M11*M22)/3.0;
  QQQ = Q*Q*Q;
  R = (M00*M11*M22 + M02*(2*M01*M12 - M02*M11)
       - M00*M12*M12 - M01*M01*M22)/2.0;
  D = QQQ - R*R;
  if (D > epsilon) {
    /* three distinct roots- this is the most common case */
    double mm, ss, cc;
    theta = atan2(sqrt(D), R)/3.0;
    mm = sqrt(Q);
    ss = sin(theta);
    cc = cos(theta);
    eval[0] = 2*mm*cc;
    eval[1] = mm*(-cc + sqrt(3.0)*ss);
    eval[2] = mm*(-cc - sqrt(3.0)*ss);
    roots = ROOT_THREE;
    /* else D is near enough to zero */
  } else if (R < -epsilon || epsilon < R) {
    double U;
    /* one double root and one single root */
    U = airCbrt(R); /* cube root function */
    if (U > 0) {
      eval[0] = 2*U;
      eval[1] = -U;
      eval[2] = -U;
    } else {
      eval[0] = -U;
      eval[1] = -U;
      eval[2] = 2*U;
    }
    roots = ROOT_SINGLE_DOUBLE;
  } else {
    /* a triple root! */
    eval[0] = eval[1] = eval[2] = 0.0;
    roots = ROOT_TRIPLE;
  }

  /* r0, r1, r2 are the vectors we manipulate to
     find the nullspaces of M - lambda*I */
  VEC_SET(r0, 0.0, M01, M02);
  VEC_SET(r1, M01, 0.0, M12);
  VEC_SET(r2, M02, M12, 0.0);
  if (ROOT_THREE == roots) {
    r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0];
    nullspace1(evec+0, r0, r1, r2);
    r0[0] = M00 - eval[1]; r1[1] = M11 - eval[1]; r2[2] = M22 - eval[1];
    nullspace1(evec+3, r0, r1, r2);
    r0[0] = M00 - eval[2]; r1[1] = M11 - eval[2]; r2[2] = M22 - eval[2];
    nullspace1(evec+6, r0, r1, r2);
  } else if (ROOT_SINGLE_DOUBLE == roots) {
    if (eval[1] == eval[2]) {
      /* one big (eval[0]) , two small (eval[1,2]) */
      r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0];
      nullspace1(evec+0, r0, r1, r2);
      r0[0] = M00 - eval[1]; r1[1] = M11 - eval[1]; r2[2] = M22 - eval[1];
      nullspace2(evec+3, evec+6, r0, r1, r2);
    }
    else {
      /* two big (eval[0,1]), one small (eval[2]) */
      r0[0] = M00 - eval[0]; r1[1] = M11 - eval[0]; r2[2] = M22 - eval[0];
      nullspace2(evec+0, evec+3, r0, r1, r2);
      r0[0] = M00 - eval[2]; r1[1] = M11 - eval[2]; r2[2] = M22 - eval[2];
      nullspace1(evec+6, r0, r1, r2);
    }
  } else {
    /* ROOT_TRIPLE == roots; use any basis for eigenvectors */
    VEC_SET(evec+0, 1, 0, 0);
    VEC_SET(evec+3, 0, 1, 0);
    VEC_SET(evec+6, 0, 0, 1);
  }
  /* we always make sure its really orthonormal; keeping fixed the
     eigenvector associated with the largest-magnitude eigenvalue */
  if (ABS(eval[0]) > ABS(eval[2])) {
    /* normalize evec+0 but don't move it */
    VEC_NORM(evec+0, len);
    dot = VEC_DOT(evec+0, evec+3); VEC_SCL_SUB(evec+3, dot, evec+0);
    VEC_NORM(evec+3, len);
    dot = VEC_DOT(evec+0, evec+6); VEC_SCL_SUB(evec+6, dot, evec+0);
    dot = VEC_DOT(evec+3, evec+6); VEC_SCL_SUB(evec+6, dot, evec+3);
    VEC_NORM(evec+6, len);
  } else {
    /* normalize evec+6 but don't move it */
    VEC_NORM(evec+6, len);
    dot = VEC_DOT(evec+6, evec+3); VEC_SCL_SUB(evec+3, dot, evec+6);
    VEC_NORM(evec+3, len);
    dot = VEC_DOT(evec+3, evec+0); VEC_SCL_SUB(evec+0, dot, evec+3);
    dot = VEC_DOT(evec+6, evec+0); VEC_SCL_SUB(evec+0, dot, evec+6);
    VEC_NORM(evec+0, len);
  }

  /* to be nice, make it right-handed */
  VEC_CROSS(crs, evec+0, evec+3);
  if (0 > VEC_DOT(crs, evec+6)) {
    VEC_SCL(evec+6, -1);
  }

  /* multiply back by eigenvalue L2 norm */
  eval[0] /= rnorm;
  eval[1] /= rnorm;
  eval[2] /= rnorm;

  /* add back in the eigenvalue mean */
  eval[0] += mean;
  eval[1] += mean;
  eval[2] += mean;

  return roots;
}
Esempio n. 7
0
void SoccerBall::Update( )
{
	DVector vVel, vAccel, vAccelAdd, vPos, vForward, vCross, vTemp, vTemp2;
	CollisionInfo collInfo;
	float fVelMag, fDistTraveled, fTime, fRotAmount, fExp;
	DRotation rRot;

	g_pServerDE->GetObjectPos( m_hObject, &vPos );
	g_pServerDE->GetVelocity( m_hObject, &vVel );
	fVelMag = VEC_MAG( vVel );
	fTime = g_pServerDE->GetTime( );

	// Remove the ball if it's been sitting around for a while.
	if( fTime > m_fRespawnTime )
	{
		g_pServerDE->RemoveObject( m_hObject );
		return;
	}

	// Update the on ground info
	g_pServerDE->GetStandingOn( m_hObject, &collInfo );
	m_bOnGround = ( collInfo.m_hObject ) ? DTRUE : DFALSE;
	if( m_bOnGround )
	{
		m_fLastTimeOnGround = fTime;
	}

	// Get how far we've traveled.
	VEC_SUB( vForward, vPos, m_vLastPos );
	fDistTraveled = VEC_MAG( vForward );
	VEC_COPY( m_vLastPos, vPos );

	// Rotate the ball
	if( fDistTraveled > 0.0f )
	{
		VEC_MULSCALAR( vForward, vForward, 1.0f / fDistTraveled );

		if( m_bOnGround )
		{
			VEC_COPY( m_vLastNormal, collInfo.m_Plane.m_Normal );
			VEC_CROSS( vCross, vForward, m_vLastNormal );
			fRotAmount = VEC_MAG( vCross ) * fDistTraveled / m_fRadius;
		}
		else
		{
			VEC_CROSS( vCross, vForward, m_vLastNormal );
			fRotAmount = VEC_MAG( vCross ) * fDistTraveled / m_fRadius;
		}

		if( fRotAmount > 0.0f )
		{
			VEC_NORM( vCross );
			g_pServerDE->GetObjectRotation( m_hObject, &rRot );
			g_pServerDE->RotateAroundAxis( &rRot, &vCross, fRotAmount );
			g_pServerDE->SetObjectRotation( m_hObject, &rRot );
		}
	}

	// Adjust the velocity and accel
	if( fVelMag < MINBALLVEL )
	{
		VEC_INIT( vVel );
		g_pServerDE->SetVelocity( m_hObject, &vVel );
	}
	else if( fVelMag > MAXBALLVEL )
	{
		VEC_MULSCALAR( vVel, vVel, MAXBALLVEL / fVelMag );				
		g_pServerDE->SetVelocity( m_hObject, &vVel );
	}
	else
	{
		// new velocity is given by:		v = ( a / k ) + ( v_0 - a / k ) * exp( -k * t )
		g_pServerDE->GetAcceleration( m_hObject, &vAccel );
		fExp = ( float )exp( -BALLDRAG * g_pServerDE->GetFrameTime( ));
		VEC_DIVSCALAR( vTemp, vAccel, BALLDRAG );
		VEC_SUB( vTemp2, vVel, vTemp );
		VEC_MULSCALAR( vTemp2, vTemp2, fExp );
		VEC_ADD( vVel, vTemp2, vTemp );
		g_pServerDE->SetVelocity( m_hObject, &vVel );
	}

	// Make sure we're rolling if we're on a slope.  This counteracts the way the
	// engine stops objects on slopes.
	if( m_bOnGround )
	{
		if( collInfo.m_Plane.m_Normal.y < 0.9f && fabs( vVel.y ) < 50.0f )
		{
			g_pServerDE->GetGlobalForce( &vAccelAdd );
			vAccel.y += vAccelAdd.y * 0.5f;
			g_pServerDE->SetAcceleration( m_hObject, &vAccel );
		}
	}

	// Play a bounce sound if enough time has elapsed
	if( m_bBounced )
	{
		if( fTime > m_fLastBounceTime + TIMEBETWEENBOUNCESOUNDS )
		{
			// Play a bounce sound...
			PlaySoundFromPos( &vPos, "Sounds_ao\\events\\soccerball.wav", 750, SOUNDPRIORITY_MISC_MEDIUM );
		}

		m_bBounced = DFALSE;
	}

	g_pServerDE->SetNextUpdate( m_hObject, 0.001f );
}
int gim_triangle_triangle_overlap(
							GIM_TRIANGLE_DATA *tri1,
							GIM_TRIANGLE_DATA *tri2)
{
    vec3f _distances;
    char out_of_face;
    CLASSIFY_TRIPOINTS_BY_FACE(tri1->m_vertices[0],tri1->m_vertices[1],tri1->m_vertices[2],tri2->m_planes.m_planes[0],out_of_face);
    if(out_of_face==1) return 0;

    CLASSIFY_TRIPOINTS_BY_FACE(tri2->m_vertices[0],tri2->m_vertices[1],tri2->m_vertices[2],tri1->m_planes.m_planes[0],out_of_face);
    if(out_of_face==1) return 0;


    float du0=0,du1=0,du2=0,dv0=0,dv1=0,dv2=0;
    float D[3];
    float isect1[2], isect2[2];
    float du0du1=0,du0du2=0,dv0dv1=0,dv0dv2=0;
    short index;
    float vp0,vp1,vp2;
    float up0,up1,up2;
    float bb,cc,max;

    /* compute direction of intersection line */
    VEC_CROSS(D,tri1->m_planes.m_planes[0],tri2->m_planes.m_planes[0]);

    /* compute and index to the largest component of D */
    max=(float)FABS(D[0]);
    index=0;
    bb=(float)FABS(D[1]);
    cc=(float)FABS(D[2]);
    if(bb>max) max=bb,index=1;
    if(cc>max) max=cc,index=2;

     /* this is the simplified projection onto L*/
     vp0= tri1->m_vertices[0][index];
     vp1= tri1->m_vertices[1][index];
     vp2= tri1->m_vertices[2][index];

     up0= tri2->m_vertices[0][index];
     up1= tri2->m_vertices[1][index];
     up2= tri2->m_vertices[2][index];

    /* compute interval for triangle 1 */
    float a,b,c,x0,x1;
    NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1);

    /* compute interval for triangle 2 */
    float d,e,f,y0,y1;
    NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1);

    float xx,yy,xxyy,tmp;
    xx=x0*x1;
    yy=y0*y1;
    xxyy=xx*yy;

    tmp=a*xxyy;
    isect1[0]=tmp+b*x1*yy;
    isect1[1]=tmp+c*x0*yy;

    tmp=d*xxyy;
    isect2[0]=tmp+e*xx*y1;
    isect2[1]=tmp+f*xx*y0;

    SORT(isect1[0],isect1[1]);
    SORT(isect2[0],isect2[1]);

    if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
    return 1;
}