This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/physic/cm_test.c

216 lines
4.9 KiB
C

//=======================================================================
// Copyright XashXT Group 2007 ©
// cm_trace.c - combined tracing
//=======================================================================
#include "cm_local.h"
static float RayCastPlacement(const NewtonBody* body, const float* normal, int collisionID, void* userData, float intersetParam )
{
float *paramPtr;
paramPtr = (float *)userData;
paramPtr[0] = intersetParam;
return intersetParam;
}
// find floor for character placement
float CM_FindFloor( vec3_t p0, float maxDist )
{
vec3_t p1;
float floor_dist = 1.2f;
VectorCopy( p0, p1 );
p1[1] -= maxDist;
// shot a vertical ray from a high altitude and collected the intersection parameter.
NewtonWorldRayCast( gWorld, &p0[0], &p1[0], RayCastPlacement, &floor_dist, NULL );
// the intersection is the interpolated value
return p0[1] - maxDist * floor_dist;
}
/*
==================
CM_PointLeafnum_r
==================
*/
int CM_PointLeafnum_r( const vec3_t p, cnode_t *node )
{
cleaf_t *leaf;
// find which leaf the point is in
while( node->plane )
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p, node->plane->normal)) < node->plane->dist];
leaf = (cleaf_t *)node;
return leaf - cm.leafs;
}
int CM_PointLeafnum( const vec3_t p )
{
// map not loaded
if ( !cm.numnodes ) return 0;
return CM_PointLeafnum_r( p, cm.nodes );
}
/*
======================================================================
LEAF LISTING
======================================================================
*/
void CM_StoreLeafs( leaflist_t *ll, cnode_t *node )
{
cleaf_t *leaf = (cleaf_t *)node;
// store the lastLeaf even if the list is overflowed
if( leaf->cluster != -1 )
{
ll->lastleaf = leaf - cm.leafs;
}
if( ll->count >= ll->maxcount )
{
ll->overflowed = true;
return;
}
ll->list[ll->count++] = leaf - cm.leafs;
}
/*
=============
CM_BoxLeafnums
Fills in a list of all the leafs touched
=============
*/
void CM_BoxLeafnums_r( leaflist_t *ll, cnode_t *node )
{
cplane_t *plane;
int s;
while( 1 )
{
if( node->plane == NULL )
{
CM_StoreLeafs( ll, node );
return;
}
plane = node->plane;
s = BoxOnPlaneSide( ll->mins, ll->maxs, plane );
if( s == 1 )
{
node = node->children[0];
}
else if( s == 2 )
{
node = node->children[1];
}
else
{
// go down both
CM_BoxLeafnums_r( ll, node->children[0] );
node = node->children[1];
}
}
}
/*
==================
CM_BoxLeafnums
==================
*/
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastleaf )
{
leaflist_t ll;
cms.checkcount++;
VectorCopy( mins, ll.mins );
VectorCopy( maxs, ll.maxs );
ll.count = 0;
ll.maxcount = listsize;
ll.list = list;
ll.lastleaf = -1;
ll.overflowed = false;
CM_BoxLeafnums_r( &ll, cm.nodes );
if( lastleaf ) *lastleaf = ll.lastleaf;
return ll.count;
}
/*
==================
CM_PointContents
==================
*/
int CM_PointContents( const vec3_t p, cmodel_t *model )
{
int i, contents = 0;
cbrush_t *brush;
if( !cm.numnodes ) return 0; // map not loaded
// test if the point is inside each brush
if( model && model->type == mod_brush )
{
// submodels are effectively one leaf
for( i = 0, brush = cm.brushes + model->firstbrush; i < model->numbrushes; i++, brush++ )
if( brush->colbrushf && CM_CollisionPointInsideBrushFloat( p, brush->colbrushf ))
contents |= brush->colbrushf->contents;
}
else
{
cnode_t *node = cm.nodes;
cleaf_t *leaf;
// find which leaf the point is in
while( node->plane )
node = node->children[(node->plane->type < 3 ? p[node->plane->type] : DotProduct(p, node->plane->normal)) < node->plane->dist];
leaf = (cleaf_t *)node;
// now check the brushes in the leaf
for( i = 0; i < leaf->numleafbrushes; i++ )
{
brush = cm.brushes + leaf->firstleafbrush[i];
if( brush->colbrushf && CM_CollisionPointInsideBrushFloat( p, brush->colbrushf ))
contents |= brush->colbrushf->contents;
}
}
return contents;
}
/*
==================
CM_TransformedPointContents
Handles offseting and rotation of the end points for moving and
rotating entities
==================
*/
int CM_TransformedPointContents( const vec3_t p, cmodel_t *model, const vec3_t origin, const vec3_t angles )
{
vec3_t p_l;
vec3_t temp;
vec3_t forward, right, up;
// subtract origin offset
VectorSubtract( p, origin, p_l );
// rotate start and end into the models frame of reference
if(!VectorIsNull( angles ))
{
AngleVectors( angles, forward, right, up );
VectorCopy( p_l, temp );
p_l[0] = DotProduct( temp, forward );
p_l[1] = -DotProduct( temp, right );
p_l[2] = DotProduct( temp, up );
}
return CM_PointContents( p_l, model );
}