/* ================= R_RecursiveHullCheck ================= */ static int R_RecursiveHullCheck( mnode_t *node, const vec3_t start, const vec3_t end ) { int side, r; float t1, t2; float frac; vec3_t mid; const vec_t *p1 = start, *p2 = end; cplane_t *plane; loc0: plane = node->plane; if( !plane ) return R_TraceAgainstLeaf( ( mleaf_t * )node ); if( plane->type < 3 ) { t1 = p1[plane->type] - plane->dist; t2 = p2[plane->type] - plane->dist; } else { t1 = DotProduct( plane->normal, p1 ) - plane->dist; t2 = DotProduct( plane->normal, p2 ) - plane->dist; } if( t1 >= -ON_EPSILON && t2 >= -ON_EPSILON ) { node = node->children[0]; goto loc0; } if( t1 < ON_EPSILON && t2 < ON_EPSILON ) { node = node->children[1]; goto loc0; } side = t1 < 0; frac = t1 / (t1 - t2); VectorLerp( p1, frac, p2, mid ); r = R_RecursiveHullCheck( node->children[side], p1, mid ); if( r ) return r; return R_RecursiveHullCheck( node->children[!side], mid, p2 ); }
/* * R_TraceLine */ static msurface_t *R_TransformedTraceLine( rtrace_t *tr, const vec3_t start, const vec3_t end, entity_t *test, int surfumask ) { model_t *model; r_traceframecount++; // for multi-check avoidance // fill in a default trace memset( tr, 0, sizeof( *tr ) ); trace_surface = NULL; trace_umask = surfumask; trace_fraction = 1; VectorCopy( end, trace_impact ); memset( &trace_plane, 0, sizeof( trace_plane ) ); ClearBounds( trace_absmins, trace_absmaxs ); AddPointToBounds( start, trace_absmins, trace_absmaxs ); AddPointToBounds( end, trace_absmins, trace_absmaxs ); model = test->model; if( model ) { if( model->type == mod_brush ) { mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata; vec3_t temp, start_l, end_l; mat3_t axis; bool rotated = !Matrix3_Compare( test->axis, axis_identity ); // transform VectorSubtract( start, test->origin, start_l ); VectorSubtract( end, test->origin, end_l ); if( rotated ) { VectorCopy( start_l, temp ); Matrix3_TransformVector( test->axis, temp, start_l ); VectorCopy( end_l, temp ); Matrix3_TransformVector( test->axis, temp, end_l ); } VectorCopy( start_l, trace_start ); VectorCopy( end_l, trace_end ); // world uses a recursive approach using BSP tree, submodels // just walk the list of surfaces linearly if( test->model == rsh.worldModel ) { R_RecursiveHullCheck( bmodel->nodes, start_l, end_l ); } else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) ) { R_TraceAgainstBmodel( bmodel ); } // transform back if( rotated && trace_fraction != 1 ) { Matrix3_Transpose( test->axis, axis ); VectorCopy( tr->plane.normal, temp ); Matrix3_TransformVector( axis, temp, trace_plane.normal ); } } } // calculate the impact plane, if any if( trace_fraction < 1 && trace_surface != NULL ) { VectorNormalize( trace_plane.normal ); trace_plane.dist = DotProduct( trace_plane.normal, trace_impact ); CategorizePlane( &trace_plane ); tr->shader = trace_surface->shader; tr->plane = trace_plane; tr->surfFlags = trace_surface->flags; tr->ent = R_ENT2NUM( test ); } tr->fraction = trace_fraction; VectorCopy( trace_impact, tr->endpos ); return trace_surface; }
/* ================= R_TraceLine ================= */ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int umask ) { ref_model_t *model; r_fragmentframecount++; // for multi-check avoidance // fill in a default trace Mem_Set( tr, 0, sizeof( trace_t )); trace_surface = NULL; trace_umask = umask; trace_fraction = 1; VectorCopy( end, trace_impact ); Mem_Set( &trace_plane, 0, sizeof( trace_plane )); ClearBounds( trace_absmins, trace_absmaxs ); AddPointToBounds( start, trace_absmins, trace_absmaxs ); AddPointToBounds( end, trace_absmins, trace_absmaxs ); model = test->model; if( model ) { if( model->type == mod_world || model->type == mod_brush ) { mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata; vec3_t temp, start_l, end_l, axis[3]; bool rotated = !Matrix3x3_Compare( test->axis, matrix3x3_identity ); // transform VectorSubtract( start, test->origin, start_l ); VectorSubtract( end, test->origin, end_l ); if( rotated ) { VectorCopy( start_l, temp ); Matrix3x3_Transform( test->axis, temp, start_l ); VectorCopy( end_l, temp ); Matrix3x3_Transform( test->axis, temp, end_l ); } VectorCopy( start_l, trace_start ); VectorCopy( end_l, trace_end ); // world uses a recursive approach using BSP tree, submodels // just walk the list of surfaces linearly if( test->model->type == mod_world ) R_RecursiveHullCheck( bmodel->nodes, start_l, end_l ); else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) ) R_TraceAgainstBmodel( bmodel ); // transform back if( rotated && trace_fraction != 1 ) { Matrix3x3_Transpose( axis, test->axis ); VectorCopy( tr->vecPlaneNormal, temp ); Matrix3x3_Transform( axis, temp, trace_plane.normal ); } } } // calculate the impact plane, if any if( trace_fraction < 1.0f ) { VectorNormalize( trace_plane.normal ); trace_plane.dist = DotProduct( trace_plane.normal, trace_impact ); CategorizePlane( &trace_plane ); tr->flPlaneDist = trace_plane.dist; VectorCopy( trace_plane.normal, tr->vecPlaneNormal ); tr->iContents = trace_surface->contents; tr->pHit = (edict_t *)test; } tr->flFraction = trace_fraction; VectorCopy( trace_impact, tr->vecEndPos ); return trace_surface; }