37 #include "../idlib/precompiled.h"
51 #define CM_PL_RANGE_EPSILON 1e-4f
53 #define ROTATION_AXIS_EPSILON (CM_CLIP_EPSILON*0.25f)
68 proj = axis * ( point * axis );
70 v2 = axis.
Cross( v1 );
75 t = tanHalfAngle * tanHalfAngle;
76 d = 1.0f / ( 1.0f +
t );
77 s = 2.0f * tanHalfAngle * d;
80 point = v1 * c - v2 * s + proj + origin;
97 t = tanHalfAngle * tanHalfAngle;
98 d = 1.0f / ( 1.0f +
t );
99 s = 2.0f * tanHalfAngle * d;
100 c = ( 1.0f -
t ) * d;
103 proj = axis * ( start * axis );
105 v2 = axis.
Cross( v1 );
106 start = v1 * c - v2 * s + proj + origin;
109 proj = axis * ( end * axis );
111 v2 = axis.
Cross( v1 );
112 end = v1 * c - v2 * s + proj + origin;
127 idVec3 at, bt, dir, dir1, dir2;
132 if ( tanHalfAngle != 0.0
f ) {
138 if ( dir1 * dir1 > dir2 * dir2 ) {
144 if ( tw->
angle < 0.0f ) {
153 if ( ( d1 > 0.0
f && d2 > 0.0
f ) || ( d1 < 0.0
f && d2 < 0.0
f ) ) {
162 if ( ( d1 > 0.0
f && d2 > 0.0
f ) || ( d1 < 0.0
f && d2 < 0.0
f ) ) {
167 dir1 = (vd - vc).Cross( dir );
174 collisionPoint = at + ( d1 / (d1 - d2) ) * ( bt - at );
177 collisionNormal.
Cross( bt-at, vd-vc );
191 const float minTan,
float &tanHalfAngle ) {
192 double v0,
v1,
v2,
a,
b,
c, d, sqrtd,
q, frac1, frac2;
292 tanHalfAngle = tw->
maxTan;
300 v0 = pl2[0] * pl1[4] + pl2[4] * pl1[0];
301 v1 = pl2[1] * pl1[2] - pl2[2] * pl1[1] + pl2[5] * pl1[3] - pl2[3] * pl1[5];
302 v2 = pl2[1] * pl1[5] + pl2[2] * pl1[3] + pl2[5] * pl1[1] + pl2[3] * pl1[2];
311 frac1 = -c / ( 2.0f *
b );
330 if ( tw->
angle < 0.0f ) {
336 if ( frac1 >= minTan && frac1 < tanHalfAngle ) {
337 tanHalfAngle = frac1;
339 if ( frac2 >= minTan && frac2 < tanHalfAngle ) {
340 tanHalfAngle = frac2;
343 if ( tw->
angle < 0.0f ) {
344 tanHalfAngle = -tanHalfAngle;
361 float &tanHalfAngle,
float &dir ) {
362 double v0,
v1,
v2,
a,
b,
c, d, sqrtd,
q, frac1, frac2;
397 v0 = pl2[0] * pl1[4] + pl2[4] * pl1[0];
398 v1 = pl2[1] * pl1[2] - pl2[2] * pl1[1] + pl2[5] * pl1[3] - pl2[3] * pl1[5];
399 v2 = pl2[1] * pl1[5] + pl2[2] * pl1[3] + pl2[5] * pl1[1] + pl2[3] * pl1[2];
403 if ( tw->
angle > 0.0f ) {
431 frac1 = -c / ( 2.0f *
b );
450 if ( tw->
angle < 0.0f ) {
455 if ( frac1 < 0.0
f && frac2 < 0.0
f ) {
459 if ( frac1 > frac2 ) {
460 tanHalfAngle = frac1;
463 tanHalfAngle = frac2;
466 if ( tw->
angle < 0.0f ) {
467 tanHalfAngle = -tanHalfAngle;
480 float f1, f2, startTan, dir, tanHalfAngle;
483 idVec3 collisionPoint, collisionNormal, origin, epsDir;
506 for ( i = 0; i < poly->
numEdges; i++ ) {
524 for ( j = 0; j < 3; j++ ) {
525 if ( v1->
p[j] > v2->
p[j] ) {
526 bounds[0][
j] = v2->
p[
j];
527 bounds[1][
j] = v1->
p[
j];
530 bounds[0][
j] = v1->
p[
j];
531 bounds[1][
j] = v2->
p[
j];
550 if ( ( f1 < 0.0f && f2 > 0.0
f ) || ( f1 > 0.0f && f2 < 0.0f ) ) {
567 tanHalfAngle = startTan;
585 tanHalfAngle, collisionPoint, collisionNormal ) ) {
612 if ( tw->
maxTan == 0.0f ) {
626 const float angle,
const float minTan,
float &tanHalfAngle ) {
627 double v0,
v1,
v2,
a,
b,
c, d, sqrtd,
q, frac1, frac2;
664 tanHalfAngle = tw->
maxTan;
671 v0 = normal[2] * p[2] + d;
672 v1 = normal[0] * p[1] - normal[1] * p[0];
673 v2 = normal[0] * p[0] + normal[1] * p[1];
682 frac1 = -c / ( 2.0f *
b );
701 if ( angle < 0.0
f ) {
707 if ( frac1 >= minTan && frac1 < tanHalfAngle ) {
708 tanHalfAngle = frac1;
710 if ( frac2 >= minTan && frac2 < tanHalfAngle ) {
711 tanHalfAngle = frac2;
714 if ( angle < 0.0
f ) {
715 tanHalfAngle = -tanHalfAngle;
731 const float angle,
float &tanHalfAngle,
float &dir ) {
733 double v1,
v2,
a,
b,
c, d, sqrtd,
q, frac1, frac2;
765 v1 = normal[0] * p[1] - normal[1] * p[0];
766 v2 = normal[0] * p[0] + normal[1] * p[1];
769 if ( angle < 0.0
f ) {
787 frac1 = -c / ( 2.0f *
b );
806 if ( angle < 0.0
f ) {
811 if ( frac1 < 0.0
f && frac2 < 0.0
f ) {
815 if ( frac1 > frac2 ) {
816 tanHalfAngle = frac1;
819 tanHalfAngle = frac2;
822 if ( angle < 0.0
f ) {
823 tanHalfAngle = -tanHalfAngle;
835 const idPlane &plane,
const float angle,
const idVec3 &origin,
836 float &tanHalfAngle,
idVec3 &collisionPoint,
idVec3 &endDir ) {
837 float d, dir, startTan;
847 vec = point - origin;
848 if ( d * d > vec * vec ) {
853 startDir = ( point - origin ).Cross( tw->
axis );
854 if ( angle < 0.0
f ) {
855 startDir = -startDir;
858 if ( startDir * epsPlane.
Normal() >= 0.0f ) {
865 endDir = ( endPoint - origin ).Cross( tw->
axis );
866 if ( angle < 0.0
f ) {
870 if ( endDir * epsPlane.
Normal() > 0.0f ) {
895 tanHalfAngle = startTan;
907 collisionPoint = point;
908 if ( tanHalfAngle != 0.0
f ) {
912 endDir = ( collisionPoint - origin ).Cross( tw->
axis );
913 if ( angle < 0.0
f ) {
927 idVec3 endDir, collisionPoint;
947 tanHalfAngle, collisionPoint, endDir ) ) {
953 pl.
FromRay( collisionPoint, endDir );
954 for ( i = 0; i < poly->
numEdges; i++ ) {
955 if ( poly->
edges[i] < 0 ) {
987 idVec3 dir, endp, endDir, collisionPoint;
1002 dir = v->
p - rotationOrigin;
1013 tanHalfAngle, collisionPoint, endDir ) ) {
1019 pl.
FromRay( collisionPoint, endDir );
1020 for ( i = 0; i < trmpoly->
numEdges; i++ ) {
1021 edgeNum = trmpoly->
edges[
i];
1022 edge = tw->
edges + abs(edgeNum);
1023 if ( edgeNum < 0 ) {
1055 int i,
j, k, edgeNum;
1116 for ( i = 0; i < tw->
numVerts; i++ ) {
1123 for ( i = 0; i < p->
numEdges; i++ ) {
1144 for ( i = 0; i < tw->
numVerts; i++ ) {
1152 for ( i = 1; i <= tw->
numEdges; i++ ) {
1160 for ( i = 0; i < p->
numEdges; i++ ) {
1174 for ( k = 0; k < 2; k++ ) {
1192 for ( j = 0; j < tw->
numPolys; j++ ) {
1202 return ( tw->
maxTan == 0.0f );
1217 radiusSqr = ( start - origin ).LengthSqr();
1218 v1 = ( start - origin ).Cross( axis );
1219 v2 = ( end - origin ).Cross( axis );
1221 for ( i = 0; i < 3; i++ ) {
1223 if ( ( v1[i] > 0.0
f && v2[i] < 0.0
f ) || ( v1[
i] < 0.0f && v2[
i] > 0.0f ) ) {
1224 if ( ( 0.5
f * (start[i] + end[i]) - origin[
i] ) > 0.0
f ) {
1225 bounds[0][
i] =
Min( start[i], end[i] );
1226 bounds[1][
i] = origin[
i] +
idMath::Sqrt( radiusSqr * ( 1.0
f - axis[i] * axis[i] ) );
1229 bounds[0][
i] = origin[
i] -
idMath::Sqrt( radiusSqr * ( 1.0
f - axis[i] * axis[i] ) );
1230 bounds[1][
i] =
Max( start[i], end[i] );
1233 else if ( start[i] > end[i] ) {
1234 bounds[0][
i] = end[
i];
1235 bounds[1][
i] = start[
i];
1238 bounds[0][
i] = start[
i];
1239 bounds[1][
i] = end[
i];
1253 const float startAngle,
const float endAngle,
const idVec3 &
start,
1257 float d, maxErr, initialTan;
1258 bool model_rotated, trm_rotated;
1259 idVec3 dir, dir1, dir2, tmp, vr, vup, org, at, bt;
1260 idMat3 invModelAxis, endAxis, tmpAxis;
1269 common->
Printf(
"idCollisionModelManagerLocal::Rotation180: invalid model handle\n");
1273 common->
Printf(
"idCollisionModelManagerLocal::Rotation180: invalid model\n");
1288 tw.
angle = endAngle - startAngle;
1292 tw.
start = start - modelOrigin;
1297 tw.
origin = rorg - modelOrigin;
1311 if ( model_rotated ) {
1313 tw.
axis *= invModelAxis;
1314 tw.
origin *= invModelAxis;
1325 tw.
matrix[0][1] = -vup[0];
1326 tw.
matrix[1][1] = -vup[1];
1327 tw.
matrix[2][1] = -vup[2];
1333 if ( !trm || ( trm->
bounds[1][0] - trm->
bounds[0][0] <= 0.0f &&
1337 if ( model_rotated ) {
1339 tw.
start *= invModelAxis;
1343 if ( startAngle != 0.0
f ) {
1375 *results = tw.
trace;
1377 if ( tw.
maxTan == initialTan ) {
1383 endRotation.
Set( rorg, axis, startAngle + (endAngle-startAngle) * results->
fraction );
1389 if ( model_rotated ) {
1390 results->
c.
normal *= modelAxis;
1391 results->
c.
point *= modelAxis;
1393 results->
c.
point += modelOrigin;
1407 if ( trm_rotated ) {
1408 for ( i = 0; i < tw.
numVerts; i++ ) {
1413 for ( i = 0; i < tw.
numVerts; i++ ) {
1417 if ( model_rotated ) {
1418 for ( i = 0; i < tw.
numVerts; i++ ) {
1422 for ( i = 0; i < tw.
numVerts; i++ ) {
1426 if ( startAngle != 0.0
f ) {
1427 for ( i = 0; i < tw.
numVerts; i++ ) {
1431 for ( i = 0; i < tw.
numVerts; i++ ) {
1437 if ( trm_rotated ) {
1443 if ( model_rotated ) {
1445 tw.
start *= invModelAxis;
1449 if ( startAngle != 0.0
f ) {
1469 for ( edge = tw.
edges + 1, i = 1; i <= tw.
numEdges; i++, edge++ ) {
1492 if ( trm_rotated & model_rotated ) {
1493 tmpAxis = trmAxis * invModelAxis;
1494 for ( poly = tw.
polys, i = 0; i < tw.
numPolys; i++, poly++ ) {
1495 poly->
plane *= tmpAxis;
1497 }
else if ( trm_rotated ) {
1498 for ( poly = tw.
polys, i = 0; i < tw.
numPolys; i++, poly++ ) {
1499 poly->
plane *= trmAxis;
1501 }
else if ( model_rotated ) {
1502 for ( poly = tw.
polys, i = 0; i < tw.
numPolys; i++, poly++ ) {
1503 poly->
plane *= invModelAxis;
1508 for ( poly = tw.
polys, i = 0; i < tw.
numPolys; i++, poly++ ) {
1514 for ( j = 0; j < poly->
numEdges; j++ ) {
1524 for ( i = 0; i < 3; i++ ) {
1541 for ( poly = tw.
polys, i = 0; i < tw.
numPolys; i++, poly++ ) {
1547 for ( j = 0; j < poly->
numEdges; j++ ) {
1548 edgeNum = poly->
edges[
j];
1549 edge = tw.
edges + abs(edgeNum);
1550 if ( !(edge->
bitNum & 2) ) {
1570 for ( i = 0; i < tw.
numVerts; i++ ) {
1585 *results = tw.
trace;
1587 if ( tw.
maxTan == initialTan ) {
1593 endRotation.
Set( rorg, axis, startAngle + (endAngle-startAngle) * results->
fraction );
1599 if ( model_rotated ) {
1600 results->
c.
normal *= modelAxis;
1601 results->
c.
point *= modelAxis;
1603 results->
c.
point += modelOrigin;
1614 static int entered = 0;
1621 float maxa, stepa,
a, lasta;
1626 memset( results, 0,
sizeof( *results ) );
1629 if ( rotation.
GetAngle() == 0.0f ) {
1635 bool startsolid =
false;
1650 if ( rotation.
GetAngle() >= 360.0f ) {
1653 }
else if ( rotation.
GetAngle() <= -360.0f ) {
1658 stepa = rotation.
GetAngle() * 0.5f;
1660 for ( lasta = 0.0
f, a = stepa; fabs( a ) < fabs( maxa ) + 1.0f; lasta =
a, a += stepa ) {
1662 idCollisionModelManagerLocal::Rotation180( results, rotation.
GetOrigin(), rotation.
GetVec(), lasta,
a,
start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis );
1674 idCollisionModelManagerLocal::Rotation180( results, rotation.
GetOrigin(), rotation.
GetVec(), 0.0f, rotation.
GetAngle(),
start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis );
GLdouble GLdouble GLdouble GLdouble q
void SetupTrm(cm_traceWork_t *tw, const idTraceModel *trm)
void RotateTrmEdgeThroughPolygon(cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmEdge_t *trmEdge)
bool RotateTrmThroughPolygon(cm_traceWork_t *tw, cm_polygon_t *p)
bool AddBounds(const idBounds &a)
assert(prefInfo.fullscreenBtn)
void Rotation180(trace_t *results, const idVec3 &rorg, const idVec3 &axis, const float startAngle, const float endAngle, const idVec3 &start, const idTraceModel *trm, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis)
const idVec3 & Normal(void) const
ID_INLINE T Max(T x, T y)
idMat3 Transpose(void) const
float Distance(const idVec3 &v) const
idPluecker polygonEdgePlueckerCache[CM_MAX_POLYGON_EDGES]
idCVar cm_debugCollision("cm_debugCollision","0", CVAR_GAME|CVAR_BOOL,"debug the collision detection")
static float Sqrt(float x)
const idMaterial * material
int ContentsTrm(trace_t *results, const idVec3 &start, const idTraceModel *trm, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
void SetNormal(const idVec3 &normal)
idVec3 Cross(const idVec3 &a) const
bool IsRotated(void) const
void FromLine(const idVec3 &start, const idVec3 &end)
idRotation modelVertexRotation
GLfloat GLfloat GLfloat v2
float GetAngle(void) const
#define FLOATSIGNBITSET(f)
void SetDist(const float dist)
void BoundsForRotation(const idVec3 &origin, const idVec3 &axis, const idVec3 &start, const idVec3 &end, idBounds &bounds)
void Rotation(trace_t *results, const idVec3 &start, const idRotation &rotation, const idTraceModel *trm, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
cm_trmEdge_t edges[MAX_TRACEMODEL_EDGES+1]
static float Fabs(float f)
#define INTSIGNBITNOTSET(i)
float PlaneDistance(const idPlane &plane) const
void TraceThroughModel(cm_traceWork_t *tw)
#define ROTATION_AXIS_EPSILON
void CM_RotateEdge(idVec3 &start, idVec3 &end, const idVec3 &origin, const idVec3 &axis, const float tanHalfAngle)
#define CIRCLE_APPROXIMATION_LENGTH
float PermutedInnerProduct(const idPluecker &a) const
int RotatePointThroughPlane(const cm_traceWork_t *tw, const idVec3 &point, const idPlane &plane, const float angle, const float minTan, float &tanHalfAngle)
void CM_RotatePoint(idVec3 &point, const idVec3 &origin, const idVec3 &axis, const float tanHalfAngle)
void RotateTrmVertexThroughPolygon(cm_traceWork_t *tw, cm_polygon_t *poly, cm_trmVertex_t *v, int vertexNum)
void FromRay(const idVec3 &start, const idVec3 &dir)
GLubyte GLubyte GLubyte a
virtual void Printf(const char *fmt,...) id_attribute((format(printf
void Set(const idVec3 &rotationOrigin, const idVec3 &rotationVec, const float rotationAngle)
int EdgeFurthestFromEdge(cm_traceWork_t *tw, const idPluecker &pl1, const idVec3 &vc, const idVec3 &vd, float &tanHalfAngle, float &dir)
const idVec3 & GetVec(void) const
idVec3 polygonRotationOriginCache[CM_MAX_POLYGON_EDGES]
void RotateVertexThroughTrmPolygon(cm_traceWork_t *tw, cm_trmPolygon_t *trmpoly, cm_polygon_t *poly, cm_vertex_t *v, idVec3 &rotationOrigin)
const idMat3 & ToMat3(void) const
bool IntersectsBounds(const idBounds &a) const
int Contents(const idVec3 &start, const idTraceModel *trm, const idMat3 &trmAxis, int contentMask, cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis)
int edges[MAX_TRACEMODEL_POLYEDGES]
const idVec3 & GetOrigin(void) const
char * va(const char *fmt,...)
cm_trmPolygon_t polys[MAX_TRACEMODEL_POLYS]
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
int CollisionBetweenEdgeBounds(cm_traceWork_t *tw, const idVec3 &va, const idVec3 &vb, const idVec3 &vc, const idVec3 &vd, float tanHalfAngle, idVec3 &collisionPoint, idVec3 &collisionNormal)
int RotatePointThroughEpsilonPlane(const cm_traceWork_t *tw, const idVec3 &point, const idVec3 &endPoint, const idPlane &plane, const float angle, const idVec3 &origin, float &tanHalfAngle, idVec3 &collisionPoint, idVec3 &endDir)
int RotateEdgeThroughEdge(cm_traceWork_t *tw, const idPluecker &pl1, const idVec3 &vc, const idVec3 &vd, const float minTan, float &tanHalfAngle)
int PointFurthestFromPlane(const cm_traceWork_t *tw, const idVec3 &point, const idPlane &plane, const float angle, float &tanHalfAngle, float &dir)
#define CM_PL_RANGE_EPSILON
bool ContainsPoint(const idVec3 &p) const
ID_INLINE T Min(T x, T y)
void NormalVectors(idVec3 &left, idVec3 &down) const
void RotatePoint(idVec3 &point) const
cm_trmVertex_t vertices[MAX_TRACEMODEL_VERTS]
float maxDistFromHeartPlane1
void FitThroughPoint(const idVec3 &p)