mirror of
https://github.com/id-Software/DOOM-3.git
synced 2026-03-19 16:39:27 +01:00
hello world
This commit is contained in:
424
neo/idlib/bv/Bounds.cpp
Normal file
424
neo/idlib/bv/Bounds.cpp
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
idBounds bounds_zero( vec3_zero, vec3_zero );
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::GetRadius
|
||||
============
|
||||
*/
|
||||
float idBounds::GetRadius( void ) const {
|
||||
int i;
|
||||
float total, b0, b1;
|
||||
|
||||
total = 0.0f;
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
b0 = (float)idMath::Fabs( b[0][i] );
|
||||
b1 = (float)idMath::Fabs( b[1][i] );
|
||||
if ( b0 > b1 ) {
|
||||
total += b0 * b0;
|
||||
} else {
|
||||
total += b1 * b1;
|
||||
}
|
||||
}
|
||||
return idMath::Sqrt( total );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::GetRadius
|
||||
============
|
||||
*/
|
||||
float idBounds::GetRadius( const idVec3 ¢er ) const {
|
||||
int i;
|
||||
float total, b0, b1;
|
||||
|
||||
total = 0.0f;
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
b0 = (float)idMath::Fabs( center[i] - b[0][i] );
|
||||
b1 = (float)idMath::Fabs( b[1][i] - center[i] );
|
||||
if ( b0 > b1 ) {
|
||||
total += b0 * b0;
|
||||
} else {
|
||||
total += b1 * b1;
|
||||
}
|
||||
}
|
||||
return idMath::Sqrt( total );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idBounds::PlaneDistance
|
||||
================
|
||||
*/
|
||||
float idBounds::PlaneDistance( const idPlane &plane ) const {
|
||||
idVec3 center;
|
||||
float d1, d2;
|
||||
|
||||
center = ( b[0] + b[1] ) * 0.5f;
|
||||
|
||||
d1 = plane.Distance( center );
|
||||
d2 = idMath::Fabs( ( b[1][0] - center[0] ) * plane.Normal()[0] ) +
|
||||
idMath::Fabs( ( b[1][1] - center[1] ) * plane.Normal()[1] ) +
|
||||
idMath::Fabs( ( b[1][2] - center[2] ) * plane.Normal()[2] );
|
||||
|
||||
if ( d1 - d2 > 0.0f ) {
|
||||
return d1 - d2;
|
||||
}
|
||||
if ( d1 + d2 < 0.0f ) {
|
||||
return d1 + d2;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idBounds::PlaneSide
|
||||
================
|
||||
*/
|
||||
int idBounds::PlaneSide( const idPlane &plane, const float epsilon ) const {
|
||||
idVec3 center;
|
||||
float d1, d2;
|
||||
|
||||
center = ( b[0] + b[1] ) * 0.5f;
|
||||
|
||||
d1 = plane.Distance( center );
|
||||
d2 = idMath::Fabs( ( b[1][0] - center[0] ) * plane.Normal()[0] ) +
|
||||
idMath::Fabs( ( b[1][1] - center[1] ) * plane.Normal()[1] ) +
|
||||
idMath::Fabs( ( b[1][2] - center[2] ) * plane.Normal()[2] );
|
||||
|
||||
if ( d1 - d2 > epsilon ) {
|
||||
return PLANESIDE_FRONT;
|
||||
}
|
||||
if ( d1 + d2 < -epsilon ) {
|
||||
return PLANESIDE_BACK;
|
||||
}
|
||||
return PLANESIDE_CROSS;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::LineIntersection
|
||||
|
||||
Returns true if the line intersects the bounds between the start and end point.
|
||||
============
|
||||
*/
|
||||
bool idBounds::LineIntersection( const idVec3 &start, const idVec3 &end ) const {
|
||||
float ld[3];
|
||||
idVec3 center = ( b[0] + b[1] ) * 0.5f;
|
||||
idVec3 extents = b[1] - center;
|
||||
idVec3 lineDir = 0.5f * ( end - start );
|
||||
idVec3 lineCenter = start + lineDir;
|
||||
idVec3 dir = lineCenter - center;
|
||||
|
||||
ld[0] = idMath::Fabs( lineDir[0] );
|
||||
if ( idMath::Fabs( dir[0] ) > extents[0] + ld[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ld[1] = idMath::Fabs( lineDir[1] );
|
||||
if ( idMath::Fabs( dir[1] ) > extents[1] + ld[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ld[2] = idMath::Fabs( lineDir[2] );
|
||||
if ( idMath::Fabs( dir[2] ) > extents[2] + ld[2] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 cross = lineDir.Cross( dir );
|
||||
|
||||
if ( idMath::Fabs( cross[0] ) > extents[1] * ld[2] + extents[2] * ld[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( idMath::Fabs( cross[1] ) > extents[0] * ld[2] + extents[2] * ld[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( idMath::Fabs( cross[2] ) > extents[0] * ld[1] + extents[1] * ld[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::RayIntersection
|
||||
|
||||
Returns true if the ray intersects the bounds.
|
||||
The ray can intersect the bounds in both directions from the start point.
|
||||
If start is inside the bounds it is considered an intersection with scale = 0
|
||||
============
|
||||
*/
|
||||
bool idBounds::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const {
|
||||
int i, ax0, ax1, ax2, side, inside;
|
||||
float f;
|
||||
idVec3 hit;
|
||||
|
||||
ax0 = -1;
|
||||
inside = 0;
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
if ( start[i] < b[0][i] ) {
|
||||
side = 0;
|
||||
}
|
||||
else if ( start[i] > b[1][i] ) {
|
||||
side = 1;
|
||||
}
|
||||
else {
|
||||
inside++;
|
||||
continue;
|
||||
}
|
||||
if ( dir[i] == 0.0f ) {
|
||||
continue;
|
||||
}
|
||||
f = ( start[i] - b[side][i] );
|
||||
if ( ax0 < 0 || idMath::Fabs( f ) > idMath::Fabs( scale * dir[i] ) ) {
|
||||
scale = - ( f / dir[i] );
|
||||
ax0 = i;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ax0 < 0 ) {
|
||||
scale = 0.0f;
|
||||
// return true if the start point is inside the bounds
|
||||
return ( inside == 3 );
|
||||
}
|
||||
|
||||
ax1 = (ax0+1)%3;
|
||||
ax2 = (ax0+2)%3;
|
||||
hit[ax1] = start[ax1] + scale * dir[ax1];
|
||||
hit[ax2] = start[ax2] + scale * dir[ax2];
|
||||
|
||||
return ( hit[ax1] >= b[0][ax1] && hit[ax1] <= b[1][ax1] &&
|
||||
hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::FromTransformedBounds
|
||||
============
|
||||
*/
|
||||
void idBounds::FromTransformedBounds( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis ) {
|
||||
int i;
|
||||
idVec3 center, extents, rotatedExtents;
|
||||
|
||||
center = (bounds[0] + bounds[1]) * 0.5f;
|
||||
extents = bounds[1] - center;
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
rotatedExtents[i] = idMath::Fabs( extents[0] * axis[0][i] ) +
|
||||
idMath::Fabs( extents[1] * axis[1][i] ) +
|
||||
idMath::Fabs( extents[2] * axis[2][i] );
|
||||
}
|
||||
|
||||
center = origin + center * axis;
|
||||
b[0] = center - rotatedExtents;
|
||||
b[1] = center + rotatedExtents;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::FromPoints
|
||||
|
||||
Most tight bounds for a point set.
|
||||
============
|
||||
*/
|
||||
void idBounds::FromPoints( const idVec3 *points, const int numPoints ) {
|
||||
SIMDProcessor->MinMax( b[0], b[1], points, numPoints );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::FromPointTranslation
|
||||
|
||||
Most tight bounds for the translational movement of the given point.
|
||||
============
|
||||
*/
|
||||
void idBounds::FromPointTranslation( const idVec3 &point, const idVec3 &translation ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
if ( translation[i] < 0.0f ) {
|
||||
b[0][i] = point[i] + translation[i];
|
||||
b[1][i] = point[i];
|
||||
}
|
||||
else {
|
||||
b[0][i] = point[i];
|
||||
b[1][i] = point[i] + translation[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::FromBoundsTranslation
|
||||
|
||||
Most tight bounds for the translational movement of the given bounds.
|
||||
============
|
||||
*/
|
||||
void idBounds::FromBoundsTranslation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idVec3 &translation ) {
|
||||
int i;
|
||||
|
||||
if ( axis.IsRotated() ) {
|
||||
FromTransformedBounds( bounds, origin, axis );
|
||||
}
|
||||
else {
|
||||
b[0] = bounds[0] + origin;
|
||||
b[1] = bounds[1] + origin;
|
||||
}
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
if ( translation[i] < 0.0f ) {
|
||||
b[0][i] += translation[i];
|
||||
}
|
||||
else {
|
||||
b[1][i] += translation[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
BoundsForPointRotation
|
||||
|
||||
only for rotations < 180 degrees
|
||||
================
|
||||
*/
|
||||
idBounds BoundsForPointRotation( const idVec3 &start, const idRotation &rotation ) {
|
||||
int i;
|
||||
float radiusSqr;
|
||||
idVec3 v1, v2;
|
||||
idVec3 origin, axis, end;
|
||||
idBounds bounds;
|
||||
|
||||
end = start * rotation;
|
||||
axis = rotation.GetVec();
|
||||
origin = rotation.GetOrigin() + axis * ( axis * ( start - rotation.GetOrigin() ) );
|
||||
radiusSqr = ( start - origin ).LengthSqr();
|
||||
v1 = ( start - origin ).Cross( axis );
|
||||
v2 = ( end - origin ).Cross( axis );
|
||||
|
||||
for ( i = 0; i < 3; i++ ) {
|
||||
// if the derivative changes sign along this axis during the rotation from start to end
|
||||
if ( ( v1[i] > 0.0f && v2[i] < 0.0f ) || ( v1[i] < 0.0f && v2[i] > 0.0f ) ) {
|
||||
if ( ( 0.5f * (start[i] + end[i]) - origin[i] ) > 0.0f ) {
|
||||
bounds[0][i] = Min( start[i], end[i] );
|
||||
bounds[1][i] = origin[i] + idMath::Sqrt( radiusSqr * ( 1.0f - axis[i] * axis[i] ) );
|
||||
}
|
||||
else {
|
||||
bounds[0][i] = origin[i] - idMath::Sqrt( radiusSqr * ( 1.0f - axis[i] * axis[i] ) );
|
||||
bounds[1][i] = Max( start[i], end[i] );
|
||||
}
|
||||
}
|
||||
else if ( start[i] > end[i] ) {
|
||||
bounds[0][i] = end[i];
|
||||
bounds[1][i] = start[i];
|
||||
}
|
||||
else {
|
||||
bounds[0][i] = start[i];
|
||||
bounds[1][i] = end[i];
|
||||
}
|
||||
}
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::FromPointRotation
|
||||
|
||||
Most tight bounds for the rotational movement of the given point.
|
||||
============
|
||||
*/
|
||||
void idBounds::FromPointRotation( const idVec3 &point, const idRotation &rotation ) {
|
||||
float radius;
|
||||
|
||||
if ( idMath::Fabs( rotation.GetAngle() ) < 180.0f ) {
|
||||
(*this) = BoundsForPointRotation( point, rotation );
|
||||
}
|
||||
else {
|
||||
|
||||
radius = ( point - rotation.GetOrigin() ).Length();
|
||||
|
||||
// FIXME: these bounds are usually way larger
|
||||
b[0].Set( -radius, -radius, -radius );
|
||||
b[1].Set( radius, radius, radius );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::FromBoundsRotation
|
||||
|
||||
Most tight bounds for the rotational movement of the given bounds.
|
||||
============
|
||||
*/
|
||||
void idBounds::FromBoundsRotation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idRotation &rotation ) {
|
||||
int i;
|
||||
float radius;
|
||||
idVec3 point;
|
||||
idBounds rBounds;
|
||||
|
||||
if ( idMath::Fabs( rotation.GetAngle() ) < 180.0f ) {
|
||||
|
||||
(*this) = BoundsForPointRotation( bounds[0] * axis + origin, rotation );
|
||||
for ( i = 1; i < 8; i++ ) {
|
||||
point[0] = bounds[(i^(i>>1))&1][0];
|
||||
point[1] = bounds[(i>>1)&1][1];
|
||||
point[2] = bounds[(i>>2)&1][2];
|
||||
(*this) += BoundsForPointRotation( point * axis + origin, rotation );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
point = (bounds[1] - bounds[0]) * 0.5f;
|
||||
radius = (bounds[1] - point).Length() + (point - rotation.GetOrigin()).Length();
|
||||
|
||||
// FIXME: these bounds are usually way larger
|
||||
b[0].Set( -radius, -radius, -radius );
|
||||
b[1].Set( radius, radius, radius );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBounds::ToPoints
|
||||
============
|
||||
*/
|
||||
void idBounds::ToPoints( idVec3 points[8] ) const {
|
||||
for ( int i = 0; i < 8; i++ ) {
|
||||
points[i][0] = b[(i^(i>>1))&1][0];
|
||||
points[i][1] = b[(i>>1)&1][1];
|
||||
points[i][2] = b[(i>>2)&1][2];
|
||||
}
|
||||
}
|
||||
409
neo/idlib/bv/Bounds.h
Normal file
409
neo/idlib/bv/Bounds.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __BV_BOUNDS_H__
|
||||
#define __BV_BOUNDS_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Axis Aligned Bounding Box
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idBounds {
|
||||
public:
|
||||
idBounds( void );
|
||||
explicit idBounds( const idVec3 &mins, const idVec3 &maxs );
|
||||
explicit idBounds( const idVec3 &point );
|
||||
|
||||
const idVec3 & operator[]( const int index ) const;
|
||||
idVec3 & operator[]( const int index );
|
||||
idBounds operator+( const idVec3 &t ) const; // returns translated bounds
|
||||
idBounds & operator+=( const idVec3 &t ); // translate the bounds
|
||||
idBounds operator*( const idMat3 &r ) const; // returns rotated bounds
|
||||
idBounds & operator*=( const idMat3 &r ); // rotate the bounds
|
||||
idBounds operator+( const idBounds &a ) const;
|
||||
idBounds & operator+=( const idBounds &a );
|
||||
idBounds operator-( const idBounds &a ) const;
|
||||
idBounds & operator-=( const idBounds &a );
|
||||
|
||||
bool Compare( const idBounds &a ) const; // exact compare, no epsilon
|
||||
bool Compare( const idBounds &a, const float epsilon ) const; // compare with epsilon
|
||||
bool operator==( const idBounds &a ) const; // exact compare, no epsilon
|
||||
bool operator!=( const idBounds &a ) const; // exact compare, no epsilon
|
||||
|
||||
void Clear( void ); // inside out bounds
|
||||
void Zero( void ); // single point at origin
|
||||
|
||||
idVec3 GetCenter( void ) const; // returns center of bounds
|
||||
float GetRadius( void ) const; // returns the radius relative to the bounds origin
|
||||
float GetRadius( const idVec3 ¢er ) const; // returns the radius relative to the given center
|
||||
float GetVolume( void ) const; // returns the volume of the bounds
|
||||
bool IsCleared( void ) const; // returns true if bounds are inside out
|
||||
|
||||
bool AddPoint( const idVec3 &v ); // add the point, returns true if the bounds expanded
|
||||
bool AddBounds( const idBounds &a ); // add the bounds, returns true if the bounds expanded
|
||||
idBounds Intersect( const idBounds &a ) const; // return intersection of this bounds with the given bounds
|
||||
idBounds & IntersectSelf( const idBounds &a ); // intersect this bounds with the given bounds
|
||||
idBounds Expand( const float d ) const; // return bounds expanded in all directions with the given value
|
||||
idBounds & ExpandSelf( const float d ); // expand bounds in all directions with the given value
|
||||
idBounds Translate( const idVec3 &translation ) const; // return translated bounds
|
||||
idBounds & TranslateSelf( const idVec3 &translation ); // translate this bounds
|
||||
idBounds Rotate( const idMat3 &rotation ) const; // return rotated bounds
|
||||
idBounds & RotateSelf( const idMat3 &rotation ); // rotate this bounds
|
||||
|
||||
float PlaneDistance( const idPlane &plane ) const;
|
||||
int PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
|
||||
|
||||
bool ContainsPoint( const idVec3 &p ) const; // includes touching
|
||||
bool IntersectsBounds( const idBounds &a ) const; // includes touching
|
||||
bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||||
// intersection point is start + dir * scale
|
||||
bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale ) const;
|
||||
|
||||
// most tight bounds for the given transformed bounds
|
||||
void FromTransformedBounds( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis );
|
||||
// most tight bounds for a point set
|
||||
void FromPoints( const idVec3 *points, const int numPoints );
|
||||
// most tight bounds for a translation
|
||||
void FromPointTranslation( const idVec3 &point, const idVec3 &translation );
|
||||
void FromBoundsTranslation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idVec3 &translation );
|
||||
// most tight bounds for a rotation
|
||||
void FromPointRotation( const idVec3 &point, const idRotation &rotation );
|
||||
void FromBoundsRotation( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis, const idRotation &rotation );
|
||||
|
||||
void ToPoints( idVec3 points[8] ) const;
|
||||
idSphere ToSphere( void ) const;
|
||||
|
||||
void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
|
||||
void AxisProjection( const idVec3 &origin, const idMat3 &axis, const idVec3 &dir, float &min, float &max ) const;
|
||||
|
||||
private:
|
||||
idVec3 b[2];
|
||||
};
|
||||
|
||||
extern idBounds bounds_zero;
|
||||
|
||||
ID_INLINE idBounds::idBounds( void ) {
|
||||
}
|
||||
|
||||
ID_INLINE idBounds::idBounds( const idVec3 &mins, const idVec3 &maxs ) {
|
||||
b[0] = mins;
|
||||
b[1] = maxs;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds::idBounds( const idVec3 &point ) {
|
||||
b[0] = point;
|
||||
b[1] = point;
|
||||
}
|
||||
|
||||
ID_INLINE const idVec3 &idBounds::operator[]( const int index ) const {
|
||||
return b[index];
|
||||
}
|
||||
|
||||
ID_INLINE idVec3 &idBounds::operator[]( const int index ) {
|
||||
return b[index];
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::operator+( const idVec3 &t ) const {
|
||||
return idBounds( b[0] + t, b[1] + t );
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::operator+=( const idVec3 &t ) {
|
||||
b[0] += t;
|
||||
b[1] += t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::operator*( const idMat3 &r ) const {
|
||||
idBounds bounds;
|
||||
bounds.FromTransformedBounds( *this, vec3_origin, r );
|
||||
return bounds;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::operator*=( const idMat3 &r ) {
|
||||
this->FromTransformedBounds( *this, vec3_origin, r );
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::operator+( const idBounds &a ) const {
|
||||
idBounds newBounds;
|
||||
newBounds = *this;
|
||||
newBounds.AddBounds( a );
|
||||
return newBounds;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::operator+=( const idBounds &a ) {
|
||||
idBounds::AddBounds( a );
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::operator-( const idBounds &a ) const {
|
||||
assert( b[1][0] - b[0][0] > a.b[1][0] - a.b[0][0] &&
|
||||
b[1][1] - b[0][1] > a.b[1][1] - a.b[0][1] &&
|
||||
b[1][2] - b[0][2] > a.b[1][2] - a.b[0][2] );
|
||||
return idBounds( idVec3( b[0][0] + a.b[1][0], b[0][1] + a.b[1][1], b[0][2] + a.b[1][2] ),
|
||||
idVec3( b[1][0] + a.b[0][0], b[1][1] + a.b[0][1], b[1][2] + a.b[0][2] ) );
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::operator-=( const idBounds &a ) {
|
||||
assert( b[1][0] - b[0][0] > a.b[1][0] - a.b[0][0] &&
|
||||
b[1][1] - b[0][1] > a.b[1][1] - a.b[0][1] &&
|
||||
b[1][2] - b[0][2] > a.b[1][2] - a.b[0][2] );
|
||||
b[0] += a.b[1];
|
||||
b[1] += a.b[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::Compare( const idBounds &a ) const {
|
||||
return ( b[0].Compare( a.b[0] ) && b[1].Compare( a.b[1] ) );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::Compare( const idBounds &a, const float epsilon ) const {
|
||||
return ( b[0].Compare( a.b[0], epsilon ) && b[1].Compare( a.b[1], epsilon ) );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::operator==( const idBounds &a ) const {
|
||||
return Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::operator!=( const idBounds &a ) const {
|
||||
return !Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE void idBounds::Clear( void ) {
|
||||
b[0][0] = b[0][1] = b[0][2] = idMath::INFINITY;
|
||||
b[1][0] = b[1][1] = b[1][2] = -idMath::INFINITY;
|
||||
}
|
||||
|
||||
ID_INLINE void idBounds::Zero( void ) {
|
||||
b[0][0] = b[0][1] = b[0][2] =
|
||||
b[1][0] = b[1][1] = b[1][2] = 0;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3 idBounds::GetCenter( void ) const {
|
||||
return idVec3( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
|
||||
}
|
||||
|
||||
ID_INLINE float idBounds::GetVolume( void ) const {
|
||||
if ( b[0][0] >= b[1][0] || b[0][1] >= b[1][1] || b[0][2] >= b[1][2] ) {
|
||||
return 0.0f;
|
||||
}
|
||||
return ( ( b[1][0] - b[0][0] ) * ( b[1][1] - b[0][1] ) * ( b[1][2] - b[0][2] ) );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::IsCleared( void ) const {
|
||||
return b[0][0] > b[1][0];
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::AddPoint( const idVec3 &v ) {
|
||||
bool expanded = false;
|
||||
if ( v[0] < b[0][0]) {
|
||||
b[0][0] = v[0];
|
||||
expanded = true;
|
||||
}
|
||||
if ( v[0] > b[1][0]) {
|
||||
b[1][0] = v[0];
|
||||
expanded = true;
|
||||
}
|
||||
if ( v[1] < b[0][1] ) {
|
||||
b[0][1] = v[1];
|
||||
expanded = true;
|
||||
}
|
||||
if ( v[1] > b[1][1]) {
|
||||
b[1][1] = v[1];
|
||||
expanded = true;
|
||||
}
|
||||
if ( v[2] < b[0][2] ) {
|
||||
b[0][2] = v[2];
|
||||
expanded = true;
|
||||
}
|
||||
if ( v[2] > b[1][2]) {
|
||||
b[1][2] = v[2];
|
||||
expanded = true;
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::AddBounds( const idBounds &a ) {
|
||||
bool expanded = false;
|
||||
if ( a.b[0][0] < b[0][0] ) {
|
||||
b[0][0] = a.b[0][0];
|
||||
expanded = true;
|
||||
}
|
||||
if ( a.b[0][1] < b[0][1] ) {
|
||||
b[0][1] = a.b[0][1];
|
||||
expanded = true;
|
||||
}
|
||||
if ( a.b[0][2] < b[0][2] ) {
|
||||
b[0][2] = a.b[0][2];
|
||||
expanded = true;
|
||||
}
|
||||
if ( a.b[1][0] > b[1][0] ) {
|
||||
b[1][0] = a.b[1][0];
|
||||
expanded = true;
|
||||
}
|
||||
if ( a.b[1][1] > b[1][1] ) {
|
||||
b[1][1] = a.b[1][1];
|
||||
expanded = true;
|
||||
}
|
||||
if ( a.b[1][2] > b[1][2] ) {
|
||||
b[1][2] = a.b[1][2];
|
||||
expanded = true;
|
||||
}
|
||||
return expanded;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::Intersect( const idBounds &a ) const {
|
||||
idBounds n;
|
||||
n.b[0][0] = ( a.b[0][0] > b[0][0] ) ? a.b[0][0] : b[0][0];
|
||||
n.b[0][1] = ( a.b[0][1] > b[0][1] ) ? a.b[0][1] : b[0][1];
|
||||
n.b[0][2] = ( a.b[0][2] > b[0][2] ) ? a.b[0][2] : b[0][2];
|
||||
n.b[1][0] = ( a.b[1][0] < b[1][0] ) ? a.b[1][0] : b[1][0];
|
||||
n.b[1][1] = ( a.b[1][1] < b[1][1] ) ? a.b[1][1] : b[1][1];
|
||||
n.b[1][2] = ( a.b[1][2] < b[1][2] ) ? a.b[1][2] : b[1][2];
|
||||
return n;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::IntersectSelf( const idBounds &a ) {
|
||||
if ( a.b[0][0] > b[0][0] ) {
|
||||
b[0][0] = a.b[0][0];
|
||||
}
|
||||
if ( a.b[0][1] > b[0][1] ) {
|
||||
b[0][1] = a.b[0][1];
|
||||
}
|
||||
if ( a.b[0][2] > b[0][2] ) {
|
||||
b[0][2] = a.b[0][2];
|
||||
}
|
||||
if ( a.b[1][0] < b[1][0] ) {
|
||||
b[1][0] = a.b[1][0];
|
||||
}
|
||||
if ( a.b[1][1] < b[1][1] ) {
|
||||
b[1][1] = a.b[1][1];
|
||||
}
|
||||
if ( a.b[1][2] < b[1][2] ) {
|
||||
b[1][2] = a.b[1][2];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::Expand( const float d ) const {
|
||||
return idBounds( idVec3( b[0][0] - d, b[0][1] - d, b[0][2] - d ),
|
||||
idVec3( b[1][0] + d, b[1][1] + d, b[1][2] + d ) );
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::ExpandSelf( const float d ) {
|
||||
b[0][0] -= d;
|
||||
b[0][1] -= d;
|
||||
b[0][2] -= d;
|
||||
b[1][0] += d;
|
||||
b[1][1] += d;
|
||||
b[1][2] += d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::Translate( const idVec3 &translation ) const {
|
||||
return idBounds( b[0] + translation, b[1] + translation );
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::TranslateSelf( const idVec3 &translation ) {
|
||||
b[0] += translation;
|
||||
b[1] += translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds idBounds::Rotate( const idMat3 &rotation ) const {
|
||||
idBounds bounds;
|
||||
bounds.FromTransformedBounds( *this, vec3_origin, rotation );
|
||||
return bounds;
|
||||
}
|
||||
|
||||
ID_INLINE idBounds &idBounds::RotateSelf( const idMat3 &rotation ) {
|
||||
FromTransformedBounds( *this, vec3_origin, rotation );
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::ContainsPoint( const idVec3 &p ) const {
|
||||
if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
|
||||
|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE bool idBounds::IntersectsBounds( const idBounds &a ) const {
|
||||
if ( a.b[1][0] < b[0][0] || a.b[1][1] < b[0][1] || a.b[1][2] < b[0][2]
|
||||
|| a.b[0][0] > b[1][0] || a.b[0][1] > b[1][1] || a.b[0][2] > b[1][2] ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE idSphere idBounds::ToSphere( void ) const {
|
||||
idSphere sphere;
|
||||
sphere.SetOrigin( ( b[0] + b[1] ) * 0.5f );
|
||||
sphere.SetRadius( ( b[1] - sphere.GetOrigin() ).Length() );
|
||||
return sphere;
|
||||
}
|
||||
|
||||
ID_INLINE void idBounds::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
|
||||
float d1, d2;
|
||||
idVec3 center, extents;
|
||||
|
||||
center = ( b[0] + b[1] ) * 0.5f;
|
||||
extents = b[1] - center;
|
||||
|
||||
d1 = dir * center;
|
||||
d2 = idMath::Fabs( extents[0] * dir[0] ) +
|
||||
idMath::Fabs( extents[1] * dir[1] ) +
|
||||
idMath::Fabs( extents[2] * dir[2] );
|
||||
|
||||
min = d1 - d2;
|
||||
max = d1 + d2;
|
||||
}
|
||||
|
||||
ID_INLINE void idBounds::AxisProjection( const idVec3 &origin, const idMat3 &axis, const idVec3 &dir, float &min, float &max ) const {
|
||||
float d1, d2;
|
||||
idVec3 center, extents;
|
||||
|
||||
center = ( b[0] + b[1] ) * 0.5f;
|
||||
extents = b[1] - center;
|
||||
center = origin + center * axis;
|
||||
|
||||
d1 = dir * center;
|
||||
d2 = idMath::Fabs( extents[0] * ( dir * axis[0] ) ) +
|
||||
idMath::Fabs( extents[1] * ( dir * axis[1] ) ) +
|
||||
idMath::Fabs( extents[2] * ( dir * axis[2] ) );
|
||||
|
||||
min = d1 - d2;
|
||||
max = d1 + d2;
|
||||
}
|
||||
|
||||
#endif /* !__BV_BOUNDS_H__ */
|
||||
849
neo/idlib/bv/Box.cpp
Normal file
849
neo/idlib/bv/Box.cpp
Normal file
@@ -0,0 +1,849 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
idBox box_zero( vec3_zero, vec3_zero, mat3_identity );
|
||||
|
||||
/*
|
||||
4---{4}---5
|
||||
+ /| /|
|
||||
Z {7} {8} {5} |
|
||||
- / | / {9}
|
||||
7--{6}----6 |
|
||||
| | | |
|
||||
{11} 0---|-{0}-1
|
||||
| / | / -
|
||||
| {3} {10} {1} Y
|
||||
|/ |/ +
|
||||
3---{2}---2
|
||||
|
||||
- X +
|
||||
|
||||
plane bits:
|
||||
0 = min x
|
||||
1 = max x
|
||||
2 = min y
|
||||
3 = max y
|
||||
4 = min z
|
||||
5 = max z
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
static int boxVertPlanes[8] = {
|
||||
( (1<<0) | (1<<2) | (1<<4) ),
|
||||
( (1<<1) | (1<<2) | (1<<4) ),
|
||||
( (1<<1) | (1<<3) | (1<<4) ),
|
||||
( (1<<0) | (1<<3) | (1<<4) ),
|
||||
( (1<<0) | (1<<2) | (1<<5) ),
|
||||
( (1<<1) | (1<<2) | (1<<5) ),
|
||||
( (1<<1) | (1<<3) | (1<<5) ),
|
||||
( (1<<0) | (1<<3) | (1<<5) )
|
||||
};
|
||||
|
||||
static int boxVertEdges[8][3] = {
|
||||
// bottom
|
||||
{ 3, 0, 8 },
|
||||
{ 0, 1, 9 },
|
||||
{ 1, 2, 10 },
|
||||
{ 2, 3, 11 },
|
||||
// top
|
||||
{ 7, 4, 8 },
|
||||
{ 4, 5, 9 },
|
||||
{ 5, 6, 10 },
|
||||
{ 6, 7, 11 }
|
||||
};
|
||||
|
||||
static int boxEdgePlanes[12][2] = {
|
||||
// bottom
|
||||
{ 4, 2 },
|
||||
{ 4, 1 },
|
||||
{ 4, 3 },
|
||||
{ 4, 0 },
|
||||
// top
|
||||
{ 5, 2 },
|
||||
{ 5, 1 },
|
||||
{ 5, 3 },
|
||||
{ 5, 0 },
|
||||
// sides
|
||||
{ 0, 2 },
|
||||
{ 2, 1 },
|
||||
{ 1, 3 },
|
||||
{ 3, 0 }
|
||||
};
|
||||
|
||||
static int boxEdgeVerts[12][2] = {
|
||||
// bottom
|
||||
{ 0, 1 },
|
||||
{ 1, 2 },
|
||||
{ 2, 3 },
|
||||
{ 3, 0 },
|
||||
// top
|
||||
{ 4, 5 },
|
||||
{ 5, 6 },
|
||||
{ 6, 7 },
|
||||
{ 7, 4 },
|
||||
// sides
|
||||
{ 0, 4 },
|
||||
{ 1, 5 },
|
||||
{ 2, 6 },
|
||||
{ 3, 7 }
|
||||
};
|
||||
*/
|
||||
|
||||
static int boxPlaneBitsSilVerts[64][7] = {
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 000000 = 0
|
||||
{ 4, 7, 4, 0, 3, 0, 0 }, // 000001 = 1
|
||||
{ 4, 5, 6, 2, 1, 0, 0 }, // 000010 = 2
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 000011 = 3
|
||||
{ 4, 4, 5, 1, 0, 0, 0 }, // 000100 = 4
|
||||
{ 6, 3, 7, 4, 5, 1, 0 }, // 000101 = 5
|
||||
{ 6, 4, 5, 6, 2, 1, 0 }, // 000110 = 6
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 000111 = 7
|
||||
{ 4, 6, 7, 3, 2, 0, 0 }, // 001000 = 8
|
||||
{ 6, 6, 7, 4, 0, 3, 2 }, // 001001 = 9
|
||||
{ 6, 5, 6, 7, 3, 2, 1 }, // 001010 = 10
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 001011 = 11
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 001100 = 12
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 001101 = 13
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 001110 = 14
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 001111 = 15
|
||||
{ 4, 0, 1, 2, 3, 0, 0 }, // 010000 = 16
|
||||
{ 6, 0, 1, 2, 3, 7, 4 }, // 010001 = 17
|
||||
{ 6, 3, 2, 6, 5, 1, 0 }, // 010010 = 18
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 010011 = 19
|
||||
{ 6, 1, 2, 3, 0, 4, 5 }, // 010100 = 20
|
||||
{ 6, 1, 2, 3, 7, 4, 5 }, // 010101 = 21
|
||||
{ 6, 2, 3, 0, 4, 5, 6 }, // 010110 = 22
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 010111 = 23
|
||||
{ 6, 0, 1, 2, 6, 7, 3 }, // 011000 = 24
|
||||
{ 6, 0, 1, 2, 6, 7, 4 }, // 011001 = 25
|
||||
{ 6, 0, 1, 5, 6, 7, 3 }, // 011010 = 26
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 011011 = 27
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 011100 = 28
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 011101 = 29
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 011110 = 30
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 011111 = 31
|
||||
{ 4, 7, 6, 5, 4, 0, 0 }, // 100000 = 32
|
||||
{ 6, 7, 6, 5, 4, 0, 3 }, // 100001 = 33
|
||||
{ 6, 5, 4, 7, 6, 2, 1 }, // 100010 = 34
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 100011 = 35
|
||||
{ 6, 4, 7, 6, 5, 1, 0 }, // 100100 = 36
|
||||
{ 6, 3, 7, 6, 5, 1, 0 }, // 100101 = 37
|
||||
{ 6, 4, 7, 6, 2, 1, 0 }, // 100110 = 38
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 100111 = 39
|
||||
{ 6, 6, 5, 4, 7, 3, 2 }, // 101000 = 40
|
||||
{ 6, 6, 5, 4, 0, 3, 2 }, // 101001 = 41
|
||||
{ 6, 5, 4, 7, 3, 2, 1 }, // 101010 = 42
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 101011 = 43
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 101100 = 44
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 101101 = 45
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 101110 = 46
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 101111 = 47
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110000 = 48
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110001 = 49
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110010 = 50
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110011 = 51
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110100 = 52
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110101 = 53
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110110 = 54
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 110111 = 55
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111000 = 56
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111001 = 57
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111010 = 58
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111011 = 59
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111100 = 60
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111101 = 61
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111110 = 62
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, // 111111 = 63
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::AddPoint
|
||||
============
|
||||
*/
|
||||
bool idBox::AddPoint( const idVec3 &v ) {
|
||||
idMat3 axis2;
|
||||
idBounds bounds1, bounds2;
|
||||
|
||||
if ( extents[0] < 0.0f ) {
|
||||
extents.Zero();
|
||||
center = v;
|
||||
axis.Identity();
|
||||
return true;
|
||||
}
|
||||
|
||||
bounds1[0][0] = bounds1[1][0] = center * axis[0];
|
||||
bounds1[0][1] = bounds1[1][1] = center * axis[1];
|
||||
bounds1[0][2] = bounds1[1][2] = center * axis[2];
|
||||
bounds1[0] -= extents;
|
||||
bounds1[1] += extents;
|
||||
if ( !bounds1.AddPoint( idVec3( v * axis[0], v * axis[1], v * axis[2] ) ) ) {
|
||||
// point is contained in the box
|
||||
return false;
|
||||
}
|
||||
|
||||
axis2[0] = v - center;
|
||||
axis2[0].Normalize();
|
||||
axis2[1] = axis[ Min3Index( axis2[0] * axis[0], axis2[0] * axis[1], axis2[0] * axis[2] ) ];
|
||||
axis2[1] = axis2[1] - ( axis2[1] * axis2[0] ) * axis2[0];
|
||||
axis2[1].Normalize();
|
||||
axis2[2].Cross( axis2[0], axis2[1] );
|
||||
|
||||
AxisProjection( axis2, bounds2 );
|
||||
bounds2.AddPoint( idVec3( v * axis2[0], v * axis2[1], v * axis2[2] ) );
|
||||
|
||||
// create new box based on the smallest bounds
|
||||
if ( bounds1.GetVolume() < bounds2.GetVolume() ) {
|
||||
center = ( bounds1[0] + bounds1[1] ) * 0.5f;
|
||||
extents = bounds1[1] - center;
|
||||
center *= axis;
|
||||
}
|
||||
else {
|
||||
center = ( bounds2[0] + bounds2[1] ) * 0.5f;
|
||||
extents = bounds2[1] - center;
|
||||
center *= axis2;
|
||||
axis = axis2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::AddBox
|
||||
============
|
||||
*/
|
||||
bool idBox::AddBox( const idBox &a ) {
|
||||
int i, besti;
|
||||
float v, bestv;
|
||||
idVec3 dir;
|
||||
idMat3 ax[4];
|
||||
idBounds bounds[4], b;
|
||||
|
||||
if ( a.extents[0] < 0.0f ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( extents[0] < 0.0f ) {
|
||||
center = a.center;
|
||||
extents = a.extents;
|
||||
axis = a.axis;
|
||||
return true;
|
||||
}
|
||||
|
||||
// test axis of this box
|
||||
ax[0] = axis;
|
||||
bounds[0][0][0] = bounds[0][1][0] = center * ax[0][0];
|
||||
bounds[0][0][1] = bounds[0][1][1] = center * ax[0][1];
|
||||
bounds[0][0][2] = bounds[0][1][2] = center * ax[0][2];
|
||||
bounds[0][0] -= extents;
|
||||
bounds[0][1] += extents;
|
||||
a.AxisProjection( ax[0], b );
|
||||
if ( !bounds[0].AddBounds( b ) ) {
|
||||
// the other box is contained in this box
|
||||
return false;
|
||||
}
|
||||
|
||||
// test axis of other box
|
||||
ax[1] = a.axis;
|
||||
bounds[1][0][0] = bounds[1][1][0] = a.center * ax[1][0];
|
||||
bounds[1][0][1] = bounds[1][1][1] = a.center * ax[1][1];
|
||||
bounds[1][0][2] = bounds[1][1][2] = a.center * ax[1][2];
|
||||
bounds[1][0] -= a.extents;
|
||||
bounds[1][1] += a.extents;
|
||||
AxisProjection( ax[1], b );
|
||||
if ( !bounds[1].AddBounds( b ) ) {
|
||||
// this box is contained in the other box
|
||||
center = a.center;
|
||||
extents = a.extents;
|
||||
axis = a.axis;
|
||||
return true;
|
||||
}
|
||||
|
||||
// test axes aligned with the vector between the box centers and one of the box axis
|
||||
dir = a.center - center;
|
||||
dir.Normalize();
|
||||
for ( i = 2; i < 4; i++ ) {
|
||||
ax[i][0] = dir;
|
||||
ax[i][1] = ax[i-2][ Min3Index( dir * ax[i-2][0], dir * ax[i-2][1], dir * ax[i-2][2] ) ];
|
||||
ax[i][1] = ax[i][1] - ( ax[i][1] * dir ) * dir;
|
||||
ax[i][1].Normalize();
|
||||
ax[i][2].Cross( dir, ax[i][1] );
|
||||
|
||||
AxisProjection( ax[i], bounds[i] );
|
||||
a.AxisProjection( ax[i], b );
|
||||
bounds[i].AddBounds( b );
|
||||
}
|
||||
|
||||
// get the bounds with the smallest volume
|
||||
bestv = idMath::INFINITY;
|
||||
besti = 0;
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
v = bounds[i].GetVolume();
|
||||
if ( v < bestv ) {
|
||||
bestv = v;
|
||||
besti = i;
|
||||
}
|
||||
}
|
||||
|
||||
// create a box from the smallest bounds axis pair
|
||||
center = ( bounds[besti][0] + bounds[besti][1] ) * 0.5f;
|
||||
extents = bounds[besti][1] - center;
|
||||
center *= ax[besti];
|
||||
axis = ax[besti];
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idBox::PlaneDistance
|
||||
================
|
||||
*/
|
||||
float idBox::PlaneDistance( const idPlane &plane ) const {
|
||||
float d1, d2;
|
||||
|
||||
d1 = plane.Distance( center );
|
||||
d2 = idMath::Fabs( extents[0] * plane.Normal()[0] ) +
|
||||
idMath::Fabs( extents[1] * plane.Normal()[1] ) +
|
||||
idMath::Fabs( extents[2] * plane.Normal()[2] );
|
||||
|
||||
if ( d1 - d2 > 0.0f ) {
|
||||
return d1 - d2;
|
||||
}
|
||||
if ( d1 + d2 < 0.0f ) {
|
||||
return d1 + d2;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idBox::PlaneSide
|
||||
================
|
||||
*/
|
||||
int idBox::PlaneSide( const idPlane &plane, const float epsilon ) const {
|
||||
float d1, d2;
|
||||
|
||||
d1 = plane.Distance( center );
|
||||
d2 = idMath::Fabs( extents[0] * plane.Normal()[0] ) +
|
||||
idMath::Fabs( extents[1] * plane.Normal()[1] ) +
|
||||
idMath::Fabs( extents[2] * plane.Normal()[2] );
|
||||
|
||||
if ( d1 - d2 > epsilon ) {
|
||||
return PLANESIDE_FRONT;
|
||||
}
|
||||
if ( d1 + d2 < -epsilon ) {
|
||||
return PLANESIDE_BACK;
|
||||
}
|
||||
return PLANESIDE_CROSS;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::IntersectsBox
|
||||
============
|
||||
*/
|
||||
bool idBox::IntersectsBox( const idBox &a ) const {
|
||||
idVec3 dir; // vector between centers
|
||||
float c[3][3]; // matrix c = axis.Transpose() * a.axis
|
||||
float ac[3][3]; // absolute values of c
|
||||
float axisdir[3]; // axis[i] * dir
|
||||
float d, e0, e1; // distance between centers and projected extents
|
||||
|
||||
dir = a.center - center;
|
||||
|
||||
// axis C0 + t * A0
|
||||
c[0][0] = axis[0] * a.axis[0];
|
||||
c[0][1] = axis[0] * a.axis[1];
|
||||
c[0][2] = axis[0] * a.axis[2];
|
||||
axisdir[0] = axis[0] * dir;
|
||||
ac[0][0] = idMath::Fabs( c[0][0] );
|
||||
ac[0][1] = idMath::Fabs( c[0][1] );
|
||||
ac[0][2] = idMath::Fabs( c[0][2] );
|
||||
|
||||
d = idMath::Fabs( axisdir[0] );
|
||||
e0 = extents[0];
|
||||
e1 = a.extents[0] * ac[0][0] + a.extents[1] * ac[0][1] + a.extents[2] * ac[0][2];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A1
|
||||
c[1][0] = axis[1] * a.axis[0];
|
||||
c[1][1] = axis[1] * a.axis[1];
|
||||
c[1][2] = axis[1] * a.axis[2];
|
||||
axisdir[1] = axis[1] * dir;
|
||||
ac[1][0] = idMath::Fabs( c[1][0] );
|
||||
ac[1][1] = idMath::Fabs( c[1][1] );
|
||||
ac[1][2] = idMath::Fabs( c[1][2] );
|
||||
|
||||
d = idMath::Fabs( axisdir[1] );
|
||||
e0 = extents[1];
|
||||
e1 = a.extents[0] * ac[1][0] + a.extents[1] * ac[1][1] + a.extents[2] * ac[1][2];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A2
|
||||
c[2][0] = axis[2] * a.axis[0];
|
||||
c[2][1] = axis[2] * a.axis[1];
|
||||
c[2][2] = axis[2] * a.axis[2];
|
||||
axisdir[2] = axis[2] * dir;
|
||||
ac[2][0] = idMath::Fabs( c[2][0] );
|
||||
ac[2][1] = idMath::Fabs( c[2][1] );
|
||||
ac[2][2] = idMath::Fabs( c[2][2] );
|
||||
|
||||
d = idMath::Fabs( axisdir[2] );
|
||||
e0 = extents[2];
|
||||
e1 = a.extents[0] * ac[2][0] + a.extents[1] * ac[2][1] + a.extents[2] * ac[2][2];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * B0
|
||||
d = idMath::Fabs( a.axis[0] * dir );
|
||||
e0 = extents[0] * ac[0][0] + extents[1] * ac[1][0] + extents[2] * ac[2][0];
|
||||
e1 = a.extents[0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * B1
|
||||
d = idMath::Fabs( a.axis[1] * dir );
|
||||
e0 = extents[0] * ac[0][1] + extents[1] * ac[1][1] + extents[2] * ac[2][1];
|
||||
e1 = a.extents[1];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * B2
|
||||
d = idMath::Fabs( a.axis[2] * dir );
|
||||
e0 = extents[0] * ac[0][2] + extents[1] * ac[1][2] + extents[2] * ac[2][2];
|
||||
e1 = a.extents[2];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A0xB0
|
||||
d = idMath::Fabs( axisdir[2] * c[1][0] - axisdir[1] * c[2][0] );
|
||||
e0 = extents[1] * ac[2][0] + extents[2] * ac[1][0];
|
||||
e1 = a.extents[1] * ac[0][2] + a.extents[2] * ac[0][1];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A0xB1
|
||||
d = idMath::Fabs( axisdir[2] * c[1][1] - axisdir[1] * c[2][1] );
|
||||
e0 = extents[1] * ac[2][1] + extents[2] * ac[1][1];
|
||||
e1 = a.extents[0] * ac[0][2] + a.extents[2] * ac[0][0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A0xB2
|
||||
d = idMath::Fabs( axisdir[2] * c[1][2] - axisdir[1] * c[2][2] );
|
||||
e0 = extents[1] * ac[2][2] + extents[2] * ac[1][2];
|
||||
e1 = a.extents[0] * ac[0][1] + a.extents[1] * ac[0][0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A1xB0
|
||||
d = idMath::Fabs( axisdir[0] * c[2][0] - axisdir[2] * c[0][0] );
|
||||
e0 = extents[0] * ac[2][0] + extents[2] * ac[0][0];
|
||||
e1 = a.extents[1] * ac[1][2] + a.extents[2] * ac[1][1];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A1xB1
|
||||
d = idMath::Fabs( axisdir[0] * c[2][1] - axisdir[2] * c[0][1] );
|
||||
e0 = extents[0] * ac[2][1] + extents[2] * ac[0][1];
|
||||
e1 = a.extents[0] * ac[1][2] + a.extents[2] * ac[1][0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A1xB2
|
||||
d = idMath::Fabs( axisdir[0] * c[2][2] - axisdir[2] * c[0][2] );
|
||||
e0 = extents[0] * ac[2][2] + extents[2] * ac[0][2];
|
||||
e1 = a.extents[0] * ac[1][1] + a.extents[1] * ac[1][0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A2xB0
|
||||
d = idMath::Fabs( axisdir[1] * c[0][0] - axisdir[0] * c[1][0] );
|
||||
e0 = extents[0] * ac[1][0] + extents[1] * ac[0][0];
|
||||
e1 = a.extents[1] * ac[2][2] + a.extents[2] * ac[2][1];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A2xB1
|
||||
d = idMath::Fabs( axisdir[1] * c[0][1] - axisdir[0] * c[1][1] );
|
||||
e0 = extents[0] * ac[1][1] + extents[1] * ac[0][1];
|
||||
e1 = a.extents[0] * ac[2][2] + a.extents[2] * ac[2][0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// axis C0 + t * A2xB2
|
||||
d = idMath::Fabs( axisdir[1] * c[0][2] - axisdir[0] * c[1][2] );
|
||||
e0 = extents[0] * ac[1][2] + extents[1] * ac[0][2];
|
||||
e1 = a.extents[0] * ac[2][1] + a.extents[1] * ac[2][0];
|
||||
if ( d > e0 + e1 ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::LineIntersection
|
||||
|
||||
Returns true if the line intersects the box between the start and end point.
|
||||
============
|
||||
*/
|
||||
bool idBox::LineIntersection( const idVec3 &start, const idVec3 &end ) const {
|
||||
float ld[3];
|
||||
idVec3 lineDir = 0.5f * ( end - start );
|
||||
idVec3 lineCenter = start + lineDir;
|
||||
idVec3 dir = lineCenter - center;
|
||||
|
||||
ld[0] = idMath::Fabs( lineDir * axis[0] );
|
||||
if ( idMath::Fabs( dir * axis[0] ) > extents[0] + ld[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ld[1] = idMath::Fabs( lineDir * axis[1] );
|
||||
if ( idMath::Fabs( dir * axis[1] ) > extents[1] + ld[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ld[2] = idMath::Fabs( lineDir * axis[2] );
|
||||
if ( idMath::Fabs( dir * axis[2] ) > extents[2] + ld[2] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 cross = lineDir.Cross( dir );
|
||||
|
||||
if ( idMath::Fabs( cross * axis[0] ) > extents[1] * ld[2] + extents[2] * ld[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( idMath::Fabs( cross * axis[1] ) > extents[0] * ld[2] + extents[2] * ld[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( idMath::Fabs( cross * axis[2] ) > extents[0] * ld[1] + extents[1] * ld[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
BoxPlaneClip
|
||||
============
|
||||
*/
|
||||
static bool BoxPlaneClip( const float denom, const float numer, float &scale0, float &scale1 ) {
|
||||
if ( denom > 0.0f ) {
|
||||
if ( numer > denom * scale1 ) {
|
||||
return false;
|
||||
}
|
||||
if ( numer > denom * scale0 ) {
|
||||
scale0 = numer / denom;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ( denom < 0.0f ) {
|
||||
if ( numer > denom * scale0 ) {
|
||||
return false;
|
||||
}
|
||||
if ( numer > denom * scale1 ) {
|
||||
scale1 = numer / denom;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return ( numer <= 0.0f );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::RayIntersection
|
||||
|
||||
Returns true if the ray intersects the box.
|
||||
The ray can intersect the box in both directions from the start point.
|
||||
If start is inside the box then scale1 < 0 and scale2 > 0.
|
||||
============
|
||||
*/
|
||||
bool idBox::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const {
|
||||
idVec3 localStart, localDir;
|
||||
|
||||
localStart = ( start - center ) * axis.Transpose();
|
||||
localDir = dir * axis.Transpose();
|
||||
|
||||
scale1 = -idMath::INFINITY;
|
||||
scale2 = idMath::INFINITY;
|
||||
return BoxPlaneClip( localDir.x, -localStart.x - extents[0], scale1, scale2 ) &&
|
||||
BoxPlaneClip( -localDir.x, localStart.x - extents[0], scale1, scale2 ) &&
|
||||
BoxPlaneClip( localDir.y, -localStart.y - extents[1], scale1, scale2 ) &&
|
||||
BoxPlaneClip( -localDir.y, localStart.y - extents[1], scale1, scale2 ) &&
|
||||
BoxPlaneClip( localDir.z, -localStart.z - extents[2], scale1, scale2 ) &&
|
||||
BoxPlaneClip( -localDir.z, localStart.z - extents[2], scale1, scale2 );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::FromPoints
|
||||
|
||||
Tight box for a collection of points.
|
||||
============
|
||||
*/
|
||||
void idBox::FromPoints( const idVec3 *points, const int numPoints ) {
|
||||
int i;
|
||||
float invNumPoints, sumXX, sumXY, sumXZ, sumYY, sumYZ, sumZZ;
|
||||
idVec3 dir;
|
||||
idBounds bounds;
|
||||
idMatX eigenVectors;
|
||||
idVecX eigenValues;
|
||||
|
||||
// compute mean of points
|
||||
center = points[0];
|
||||
for ( i = 1; i < numPoints; i++ ) {
|
||||
center += points[i];
|
||||
}
|
||||
invNumPoints = 1.0f / numPoints;
|
||||
center *= invNumPoints;
|
||||
|
||||
// compute covariances of points
|
||||
sumXX = 0.0f; sumXY = 0.0f; sumXZ = 0.0f;
|
||||
sumYY = 0.0f; sumYZ = 0.0f; sumZZ = 0.0f;
|
||||
for ( i = 0; i < numPoints; i++ ) {
|
||||
dir = points[i] - center;
|
||||
sumXX += dir.x * dir.x;
|
||||
sumXY += dir.x * dir.y;
|
||||
sumXZ += dir.x * dir.z;
|
||||
sumYY += dir.y * dir.y;
|
||||
sumYZ += dir.y * dir.z;
|
||||
sumZZ += dir.z * dir.z;
|
||||
}
|
||||
sumXX *= invNumPoints;
|
||||
sumXY *= invNumPoints;
|
||||
sumXZ *= invNumPoints;
|
||||
sumYY *= invNumPoints;
|
||||
sumYZ *= invNumPoints;
|
||||
sumZZ *= invNumPoints;
|
||||
|
||||
// compute eigenvectors for covariance matrix
|
||||
eigenValues.SetData( 3, VECX_ALLOCA( 3 ) );
|
||||
eigenVectors.SetData( 3, 3, MATX_ALLOCA( 3 * 3 ) );
|
||||
|
||||
eigenVectors[0][0] = sumXX;
|
||||
eigenVectors[0][1] = sumXY;
|
||||
eigenVectors[0][2] = sumXZ;
|
||||
eigenVectors[1][0] = sumXY;
|
||||
eigenVectors[1][1] = sumYY;
|
||||
eigenVectors[1][2] = sumYZ;
|
||||
eigenVectors[2][0] = sumXZ;
|
||||
eigenVectors[2][1] = sumYZ;
|
||||
eigenVectors[2][2] = sumZZ;
|
||||
eigenVectors.Eigen_SolveSymmetric( eigenValues );
|
||||
eigenVectors.Eigen_SortIncreasing( eigenValues );
|
||||
|
||||
axis[0][0] = eigenVectors[0][0];
|
||||
axis[0][1] = eigenVectors[0][1];
|
||||
axis[0][2] = eigenVectors[0][2];
|
||||
axis[1][0] = eigenVectors[1][0];
|
||||
axis[1][1] = eigenVectors[1][1];
|
||||
axis[1][2] = eigenVectors[1][2];
|
||||
axis[2][0] = eigenVectors[2][0];
|
||||
axis[2][1] = eigenVectors[2][1];
|
||||
axis[2][2] = eigenVectors[2][2];
|
||||
|
||||
extents[0] = eigenValues[0];
|
||||
extents[1] = eigenValues[0];
|
||||
extents[2] = eigenValues[0];
|
||||
|
||||
// refine by calculating the bounds of the points projected onto the axis and adjusting the center and extents
|
||||
bounds.Clear();
|
||||
for ( i = 0; i < numPoints; i++ ) {
|
||||
bounds.AddPoint( idVec3( points[i] * axis[0], points[i] * axis[1], points[i] * axis[2] ) );
|
||||
}
|
||||
center = ( bounds[0] + bounds[1] ) * 0.5f;
|
||||
extents = bounds[1] - center;
|
||||
center *= axis;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::FromPointTranslation
|
||||
|
||||
Most tight box for the translational movement of the given point.
|
||||
============
|
||||
*/
|
||||
void idBox::FromPointTranslation( const idVec3 &point, const idVec3 &translation ) {
|
||||
// FIXME: implement
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::FromBoxTranslation
|
||||
|
||||
Most tight box for the translational movement of the given box.
|
||||
============
|
||||
*/
|
||||
void idBox::FromBoxTranslation( const idBox &box, const idVec3 &translation ) {
|
||||
// FIXME: implement
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::FromPointRotation
|
||||
|
||||
Most tight bounds for the rotational movement of the given point.
|
||||
============
|
||||
*/
|
||||
void idBox::FromPointRotation( const idVec3 &point, const idRotation &rotation ) {
|
||||
// FIXME: implement
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::FromBoxRotation
|
||||
|
||||
Most tight box for the rotational movement of the given box.
|
||||
============
|
||||
*/
|
||||
void idBox::FromBoxRotation( const idBox &box, const idRotation &rotation ) {
|
||||
// FIXME: implement
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::ToPoints
|
||||
============
|
||||
*/
|
||||
void idBox::ToPoints( idVec3 points[8] ) const {
|
||||
idMat3 ax;
|
||||
idVec3 temp[4];
|
||||
|
||||
ax[0] = extents[0] * axis[0];
|
||||
ax[1] = extents[1] * axis[1];
|
||||
ax[2] = extents[2] * axis[2];
|
||||
temp[0] = center - ax[0];
|
||||
temp[1] = center + ax[0];
|
||||
temp[2] = ax[1] - ax[2];
|
||||
temp[3] = ax[1] + ax[2];
|
||||
points[0] = temp[0] - temp[3];
|
||||
points[1] = temp[1] - temp[3];
|
||||
points[2] = temp[1] + temp[2];
|
||||
points[3] = temp[0] + temp[2];
|
||||
points[4] = temp[0] - temp[2];
|
||||
points[5] = temp[1] - temp[2];
|
||||
points[6] = temp[1] + temp[3];
|
||||
points[7] = temp[0] + temp[3];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::GetProjectionSilhouetteVerts
|
||||
============
|
||||
*/
|
||||
int idBox::GetProjectionSilhouetteVerts( const idVec3 &projectionOrigin, idVec3 silVerts[6] ) const {
|
||||
float f;
|
||||
int i, planeBits, *index;
|
||||
idVec3 points[8], dir1, dir2;
|
||||
|
||||
ToPoints( points );
|
||||
|
||||
dir1 = points[0] - projectionOrigin;
|
||||
dir2 = points[6] - projectionOrigin;
|
||||
f = dir1 * axis[0];
|
||||
planeBits = FLOATSIGNBITNOTSET( f );
|
||||
f = dir2 * axis[0];
|
||||
planeBits |= FLOATSIGNBITSET( f ) << 1;
|
||||
f = dir1 * axis[1];
|
||||
planeBits |= FLOATSIGNBITNOTSET( f ) << 2;
|
||||
f = dir2 * axis[1];
|
||||
planeBits |= FLOATSIGNBITSET( f ) << 3;
|
||||
f = dir1 * axis[2];
|
||||
planeBits |= FLOATSIGNBITNOTSET( f ) << 4;
|
||||
f = dir2 * axis[2];
|
||||
planeBits |= FLOATSIGNBITSET( f ) << 5;
|
||||
|
||||
index = boxPlaneBitsSilVerts[planeBits];
|
||||
for ( i = 0; i < index[0]; i++ ) {
|
||||
silVerts[i] = points[index[i+1]];
|
||||
}
|
||||
|
||||
return index[0];
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idBox::GetParallelProjectionSilhouetteVerts
|
||||
============
|
||||
*/
|
||||
int idBox::GetParallelProjectionSilhouetteVerts( const idVec3 &projectionDir, idVec3 silVerts[6] ) const {
|
||||
float f;
|
||||
int i, planeBits, *index;
|
||||
idVec3 points[8];
|
||||
|
||||
ToPoints( points );
|
||||
|
||||
planeBits = 0;
|
||||
f = projectionDir * axis[0];
|
||||
if ( FLOATNOTZERO( f ) ) {
|
||||
planeBits = 1 << FLOATSIGNBITSET( f );
|
||||
}
|
||||
f = projectionDir * axis[1];
|
||||
if ( FLOATNOTZERO( f ) ) {
|
||||
planeBits |= 4 << FLOATSIGNBITSET( f );
|
||||
}
|
||||
f = projectionDir * axis[2];
|
||||
if ( FLOATNOTZERO( f ) ) {
|
||||
planeBits |= 16 << FLOATSIGNBITSET( f );
|
||||
}
|
||||
|
||||
index = boxPlaneBitsSilVerts[planeBits];
|
||||
for ( i = 0; i < index[0]; i++ ) {
|
||||
silVerts[i] = points[index[i+1]];
|
||||
}
|
||||
|
||||
return index[0];
|
||||
}
|
||||
297
neo/idlib/bv/Box.h
Normal file
297
neo/idlib/bv/Box.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __BV_BOX_H__
|
||||
#define __BV_BOX_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Oriented Bounding Box
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idBox {
|
||||
public:
|
||||
idBox( void );
|
||||
explicit idBox( const idVec3 ¢er, const idVec3 &extents, const idMat3 &axis );
|
||||
explicit idBox( const idVec3 &point );
|
||||
explicit idBox( const idBounds &bounds );
|
||||
explicit idBox( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis );
|
||||
|
||||
idBox operator+( const idVec3 &t ) const; // returns translated box
|
||||
idBox & operator+=( const idVec3 &t ); // translate the box
|
||||
idBox operator*( const idMat3 &r ) const; // returns rotated box
|
||||
idBox & operator*=( const idMat3 &r ); // rotate the box
|
||||
idBox operator+( const idBox &a ) const;
|
||||
idBox & operator+=( const idBox &a );
|
||||
idBox operator-( const idBox &a ) const;
|
||||
idBox & operator-=( const idBox &a );
|
||||
|
||||
bool Compare( const idBox &a ) const; // exact compare, no epsilon
|
||||
bool Compare( const idBox &a, const float epsilon ) const; // compare with epsilon
|
||||
bool operator==( const idBox &a ) const; // exact compare, no epsilon
|
||||
bool operator!=( const idBox &a ) const; // exact compare, no epsilon
|
||||
|
||||
void Clear( void ); // inside out box
|
||||
void Zero( void ); // single point at origin
|
||||
|
||||
const idVec3 & GetCenter( void ) const; // returns center of the box
|
||||
const idVec3 & GetExtents( void ) const; // returns extents of the box
|
||||
const idMat3 & GetAxis( void ) const; // returns the axis of the box
|
||||
float GetVolume( void ) const; // returns the volume of the box
|
||||
bool IsCleared( void ) const; // returns true if box are inside out
|
||||
|
||||
bool AddPoint( const idVec3 &v ); // add the point, returns true if the box expanded
|
||||
bool AddBox( const idBox &a ); // add the box, returns true if the box expanded
|
||||
idBox Expand( const float d ) const; // return box expanded in all directions with the given value
|
||||
idBox & ExpandSelf( const float d ); // expand box in all directions with the given value
|
||||
idBox Translate( const idVec3 &translation ) const; // return translated box
|
||||
idBox & TranslateSelf( const idVec3 &translation ); // translate this box
|
||||
idBox Rotate( const idMat3 &rotation ) const; // return rotated box
|
||||
idBox & RotateSelf( const idMat3 &rotation ); // rotate this box
|
||||
|
||||
float PlaneDistance( const idPlane &plane ) const;
|
||||
int PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
|
||||
|
||||
bool ContainsPoint( const idVec3 &p ) const; // includes touching
|
||||
bool IntersectsBox( const idBox &a ) const; // includes touching
|
||||
bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||||
// intersection points are (start + dir * scale1) and (start + dir * scale2)
|
||||
bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||||
|
||||
// tight box for a collection of points
|
||||
void FromPoints( const idVec3 *points, const int numPoints );
|
||||
// most tight box for a translation
|
||||
void FromPointTranslation( const idVec3 &point, const idVec3 &translation );
|
||||
void FromBoxTranslation( const idBox &box, const idVec3 &translation );
|
||||
// most tight box for a rotation
|
||||
void FromPointRotation( const idVec3 &point, const idRotation &rotation );
|
||||
void FromBoxRotation( const idBox &box, const idRotation &rotation );
|
||||
|
||||
void ToPoints( idVec3 points[8] ) const;
|
||||
idSphere ToSphere( void ) const;
|
||||
|
||||
// calculates the projection of this box onto the given axis
|
||||
void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
|
||||
void AxisProjection( const idMat3 &ax, idBounds &bounds ) const;
|
||||
|
||||
// calculates the silhouette of the box
|
||||
int GetProjectionSilhouetteVerts( const idVec3 &projectionOrigin, idVec3 silVerts[6] ) const;
|
||||
int GetParallelProjectionSilhouetteVerts( const idVec3 &projectionDir, idVec3 silVerts[6] ) const;
|
||||
|
||||
private:
|
||||
idVec3 center;
|
||||
idVec3 extents;
|
||||
idMat3 axis;
|
||||
};
|
||||
|
||||
extern idBox box_zero;
|
||||
|
||||
ID_INLINE idBox::idBox( void ) {
|
||||
}
|
||||
|
||||
ID_INLINE idBox::idBox( const idVec3 ¢er, const idVec3 &extents, const idMat3 &axis ) {
|
||||
this->center = center;
|
||||
this->extents = extents;
|
||||
this->axis = axis;
|
||||
}
|
||||
|
||||
ID_INLINE idBox::idBox( const idVec3 &point ) {
|
||||
this->center = point;
|
||||
this->extents.Zero();
|
||||
this->axis.Identity();
|
||||
}
|
||||
|
||||
ID_INLINE idBox::idBox( const idBounds &bounds ) {
|
||||
this->center = ( bounds[0] + bounds[1] ) * 0.5f;
|
||||
this->extents = bounds[1] - this->center;
|
||||
this->axis.Identity();
|
||||
}
|
||||
|
||||
ID_INLINE idBox::idBox( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis ) {
|
||||
this->center = ( bounds[0] + bounds[1] ) * 0.5f;
|
||||
this->extents = bounds[1] - this->center;
|
||||
this->center = origin + this->center * axis;
|
||||
this->axis = axis;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::operator+( const idVec3 &t ) const {
|
||||
return idBox( center + t, extents, axis );
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::operator+=( const idVec3 &t ) {
|
||||
center += t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::operator*( const idMat3 &r ) const {
|
||||
return idBox( center * r, extents, axis * r );
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::operator*=( const idMat3 &r ) {
|
||||
center *= r;
|
||||
axis *= r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::operator+( const idBox &a ) const {
|
||||
idBox newBox;
|
||||
newBox = *this;
|
||||
newBox.AddBox( a );
|
||||
return newBox;
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::operator+=( const idBox &a ) {
|
||||
idBox::AddBox( a );
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::operator-( const idBox &a ) const {
|
||||
return idBox( center, extents - a.extents, axis );
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::operator-=( const idBox &a ) {
|
||||
extents -= a.extents;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE bool idBox::Compare( const idBox &a ) const {
|
||||
return ( center.Compare( a.center ) && extents.Compare( a.extents ) && axis.Compare( a.axis ) );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBox::Compare( const idBox &a, const float epsilon ) const {
|
||||
return ( center.Compare( a.center, epsilon ) && extents.Compare( a.extents, epsilon ) && axis.Compare( a.axis, epsilon ) );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBox::operator==( const idBox &a ) const {
|
||||
return Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE bool idBox::operator!=( const idBox &a ) const {
|
||||
return !Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE void idBox::Clear( void ) {
|
||||
center.Zero();
|
||||
extents[0] = extents[1] = extents[2] = -idMath::INFINITY;
|
||||
axis.Identity();
|
||||
}
|
||||
|
||||
ID_INLINE void idBox::Zero( void ) {
|
||||
center.Zero();
|
||||
extents.Zero();
|
||||
axis.Identity();
|
||||
}
|
||||
|
||||
ID_INLINE const idVec3 &idBox::GetCenter( void ) const {
|
||||
return center;
|
||||
}
|
||||
|
||||
ID_INLINE const idVec3 &idBox::GetExtents( void ) const {
|
||||
return extents;
|
||||
}
|
||||
|
||||
ID_INLINE const idMat3 &idBox::GetAxis( void ) const {
|
||||
return axis;
|
||||
}
|
||||
|
||||
ID_INLINE float idBox::GetVolume( void ) const {
|
||||
return ( extents * 2.0f ).LengthSqr();
|
||||
}
|
||||
|
||||
ID_INLINE bool idBox::IsCleared( void ) const {
|
||||
return extents[0] < 0.0f;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::Expand( const float d ) const {
|
||||
return idBox( center, extents + idVec3( d, d, d ), axis );
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::ExpandSelf( const float d ) {
|
||||
extents[0] += d;
|
||||
extents[1] += d;
|
||||
extents[2] += d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::Translate( const idVec3 &translation ) const {
|
||||
return idBox( center + translation, extents, axis );
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::TranslateSelf( const idVec3 &translation ) {
|
||||
center += translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idBox idBox::Rotate( const idMat3 &rotation ) const {
|
||||
return idBox( center * rotation, extents, axis * rotation );
|
||||
}
|
||||
|
||||
ID_INLINE idBox &idBox::RotateSelf( const idMat3 &rotation ) {
|
||||
center *= rotation;
|
||||
axis *= rotation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE bool idBox::ContainsPoint( const idVec3 &p ) const {
|
||||
idVec3 lp = p - center;
|
||||
if ( idMath::Fabs( lp * axis[0] ) > extents[0] ||
|
||||
idMath::Fabs( lp * axis[1] ) > extents[1] ||
|
||||
idMath::Fabs( lp * axis[2] ) > extents[2] ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE idSphere idBox::ToSphere( void ) const {
|
||||
return idSphere( center, extents.Length() );
|
||||
}
|
||||
|
||||
ID_INLINE void idBox::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
|
||||
float d1 = dir * center;
|
||||
float d2 = idMath::Fabs( extents[0] * ( dir * axis[0] ) ) +
|
||||
idMath::Fabs( extents[1] * ( dir * axis[1] ) ) +
|
||||
idMath::Fabs( extents[2] * ( dir * axis[2] ) );
|
||||
min = d1 - d2;
|
||||
max = d1 + d2;
|
||||
}
|
||||
|
||||
ID_INLINE void idBox::AxisProjection( const idMat3 &ax, idBounds &bounds ) const {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
float d1 = ax[i] * center;
|
||||
float d2 = idMath::Fabs( extents[0] * ( ax[i] * axis[0] ) ) +
|
||||
idMath::Fabs( extents[1] * ( ax[i] * axis[1] ) ) +
|
||||
idMath::Fabs( extents[2] * ( ax[i] * axis[2] ) );
|
||||
bounds[0][i] = d1 - d2;
|
||||
bounds[1][i] = d1 + d2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !__BV_BOX_H__ */
|
||||
2843
neo/idlib/bv/Frustum.cpp
Normal file
2843
neo/idlib/bv/Frustum.cpp
Normal file
File diff suppressed because it is too large
Load Diff
265
neo/idlib/bv/Frustum.h
Normal file
265
neo/idlib/bv/Frustum.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __BV_FRUSTUM_H__
|
||||
#define __BV_FRUSTUM_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Orthogonal Frustum
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idFrustum {
|
||||
public:
|
||||
idFrustum( void );
|
||||
|
||||
void SetOrigin( const idVec3 &origin );
|
||||
void SetAxis( const idMat3 &axis );
|
||||
void SetSize( float dNear, float dFar, float dLeft, float dUp );
|
||||
void SetPyramid( float dNear, float dFar );
|
||||
void MoveNearDistance( float dNear );
|
||||
void MoveFarDistance( float dFar );
|
||||
|
||||
const idVec3 & GetOrigin( void ) const; // returns frustum origin
|
||||
const idMat3 & GetAxis( void ) const; // returns frustum orientation
|
||||
idVec3 GetCenter( void ) const; // returns center of frustum
|
||||
|
||||
bool IsValid( void ) const; // returns true if the frustum is valid
|
||||
float GetNearDistance( void ) const; // returns distance to near plane
|
||||
float GetFarDistance( void ) const; // returns distance to far plane
|
||||
float GetLeft( void ) const; // returns left vector length
|
||||
float GetUp( void ) const; // returns up vector length
|
||||
|
||||
idFrustum Expand( const float d ) const; // returns frustum expanded in all directions with the given value
|
||||
idFrustum & ExpandSelf( const float d ); // expands frustum in all directions with the given value
|
||||
idFrustum Translate( const idVec3 &translation ) const; // returns translated frustum
|
||||
idFrustum & TranslateSelf( const idVec3 &translation ); // translates frustum
|
||||
idFrustum Rotate( const idMat3 &rotation ) const; // returns rotated frustum
|
||||
idFrustum & RotateSelf( const idMat3 &rotation ); // rotates frustum
|
||||
|
||||
float PlaneDistance( const idPlane &plane ) const;
|
||||
int PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
|
||||
|
||||
// fast culling but might not cull everything outside the frustum
|
||||
bool CullPoint( const idVec3 &point ) const;
|
||||
bool CullBounds( const idBounds &bounds ) const;
|
||||
bool CullBox( const idBox &box ) const;
|
||||
bool CullSphere( const idSphere &sphere ) const;
|
||||
bool CullFrustum( const idFrustum &frustum ) const;
|
||||
bool CullWinding( const class idWinding &winding ) const;
|
||||
|
||||
// exact intersection tests
|
||||
bool ContainsPoint( const idVec3 &point ) const;
|
||||
bool IntersectsBounds( const idBounds &bounds ) const;
|
||||
bool IntersectsBox( const idBox &box ) const;
|
||||
bool IntersectsSphere( const idSphere &sphere ) const;
|
||||
bool IntersectsFrustum( const idFrustum &frustum ) const;
|
||||
bool IntersectsWinding( const idWinding &winding ) const;
|
||||
bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||||
bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||||
|
||||
// returns true if the projection origin is far enough away from the bounding volume to create a valid frustum
|
||||
bool FromProjection( const idBounds &bounds, const idVec3 &projectionOrigin, const float dFar );
|
||||
bool FromProjection( const idBox &box, const idVec3 &projectionOrigin, const float dFar );
|
||||
bool FromProjection( const idSphere &sphere, const idVec3 &projectionOrigin, const float dFar );
|
||||
|
||||
// moves the far plane so it extends just beyond the bounding volume
|
||||
bool ConstrainToBounds( const idBounds &bounds );
|
||||
bool ConstrainToBox( const idBox &box );
|
||||
bool ConstrainToSphere( const idSphere &sphere );
|
||||
bool ConstrainToFrustum( const idFrustum &frustum );
|
||||
|
||||
void ToPlanes( idPlane planes[6] ) const; // planes point outwards
|
||||
void ToPoints( idVec3 points[8] ) const; // 8 corners of the frustum
|
||||
|
||||
// calculates the projection of this frustum onto the given axis
|
||||
void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
|
||||
void AxisProjection( const idMat3 &ax, idBounds &bounds ) const;
|
||||
|
||||
// calculates the bounds for the projection in this frustum
|
||||
bool ProjectionBounds( const idBounds &bounds, idBounds &projectionBounds ) const;
|
||||
bool ProjectionBounds( const idBox &box, idBounds &projectionBounds ) const;
|
||||
bool ProjectionBounds( const idSphere &sphere, idBounds &projectionBounds ) const;
|
||||
bool ProjectionBounds( const idFrustum &frustum, idBounds &projectionBounds ) const;
|
||||
bool ProjectionBounds( const idWinding &winding, idBounds &projectionBounds ) const;
|
||||
|
||||
// calculates the bounds for the projection in this frustum of the given frustum clipped to the given box
|
||||
bool ClippedProjectionBounds( const idFrustum &frustum, const idBox &clipBox, idBounds &projectionBounds ) const;
|
||||
|
||||
private:
|
||||
idVec3 origin; // frustum origin
|
||||
idMat3 axis; // frustum orientation
|
||||
float dNear; // distance of near plane, dNear >= 0.0f
|
||||
float dFar; // distance of far plane, dFar > dNear
|
||||
float dLeft; // half the width at the far plane
|
||||
float dUp; // half the height at the far plane
|
||||
float invFar; // 1.0f / dFar
|
||||
|
||||
private:
|
||||
bool CullLocalBox( const idVec3 &localOrigin, const idVec3 &extents, const idMat3 &localAxis ) const;
|
||||
bool CullLocalFrustum( const idFrustum &localFrustum, const idVec3 indexPoints[8], const idVec3 cornerVecs[4] ) const;
|
||||
bool CullLocalWinding( const idVec3 *points, const int numPoints, int *pointCull ) const;
|
||||
bool BoundsCullLocalFrustum( const idBounds &bounds, const idFrustum &localFrustum, const idVec3 indexPoints[8], const idVec3 cornerVecs[4] ) const;
|
||||
bool LocalLineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||||
bool LocalRayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||||
bool LocalFrustumIntersectsFrustum( const idVec3 points[8], const bool testFirstSide ) const;
|
||||
bool LocalFrustumIntersectsBounds( const idVec3 points[8], const idBounds &bounds ) const;
|
||||
void ToClippedPoints( const float fractions[4], idVec3 points[8] ) const;
|
||||
void ToIndexPoints( idVec3 indexPoints[8] ) const;
|
||||
void ToIndexPointsAndCornerVecs( idVec3 indexPoints[8], idVec3 cornerVecs[4] ) const;
|
||||
void AxisProjection( const idVec3 indexPoints[8], const idVec3 cornerVecs[4], const idVec3 &dir, float &min, float &max ) const;
|
||||
void AddLocalLineToProjectionBoundsSetCull( const idVec3 &start, const idVec3 &end, int &startCull, int &endCull, idBounds &bounds ) const;
|
||||
void AddLocalLineToProjectionBoundsUseCull( const idVec3 &start, const idVec3 &end, int startCull, int endCull, idBounds &bounds ) const;
|
||||
bool AddLocalCapsToProjectionBounds( const idVec3 endPoints[4], const int endPointCull[4], const idVec3 &point, int pointCull, int pointClip, idBounds &projectionBounds ) const;
|
||||
bool BoundsRayIntersection( const idBounds &bounds, const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||||
void ClipFrustumToBox( const idBox &box, float clipFractions[4], int clipPlanes[4] ) const;
|
||||
bool ClipLine( const idVec3 localPoints[8], const idVec3 points[8], int startIndex, int endIndex, idVec3 &start, idVec3 &end, int &startClip, int &endClip ) const;
|
||||
};
|
||||
|
||||
|
||||
ID_INLINE idFrustum::idFrustum( void ) {
|
||||
dNear = dFar = 0.0f;
|
||||
}
|
||||
|
||||
ID_INLINE void idFrustum::SetOrigin( const idVec3 &origin ) {
|
||||
this->origin = origin;
|
||||
}
|
||||
|
||||
ID_INLINE void idFrustum::SetAxis( const idMat3 &axis ) {
|
||||
this->axis = axis;
|
||||
}
|
||||
|
||||
ID_INLINE void idFrustum::SetSize( float dNear, float dFar, float dLeft, float dUp ) {
|
||||
assert( dNear >= 0.0f && dFar > dNear && dLeft > 0.0f && dUp > 0.0f );
|
||||
this->dNear = dNear;
|
||||
this->dFar = dFar;
|
||||
this->dLeft = dLeft;
|
||||
this->dUp = dUp;
|
||||
this->invFar = 1.0f / dFar;
|
||||
}
|
||||
|
||||
ID_INLINE void idFrustum::SetPyramid( float dNear, float dFar ) {
|
||||
assert( dNear >= 0.0f && dFar > dNear );
|
||||
this->dNear = dNear;
|
||||
this->dFar = dFar;
|
||||
this->dLeft = dFar;
|
||||
this->dUp = dFar;
|
||||
this->invFar = 1.0f / dFar;
|
||||
}
|
||||
|
||||
ID_INLINE void idFrustum::MoveNearDistance( float dNear ) {
|
||||
assert( dNear >= 0.0f );
|
||||
this->dNear = dNear;
|
||||
}
|
||||
|
||||
ID_INLINE void idFrustum::MoveFarDistance( float dFar ) {
|
||||
assert( dFar > this->dNear );
|
||||
float scale = dFar / this->dFar;
|
||||
this->dFar = dFar;
|
||||
this->dLeft *= scale;
|
||||
this->dUp *= scale;
|
||||
this->invFar = 1.0f / dFar;
|
||||
}
|
||||
|
||||
ID_INLINE const idVec3 &idFrustum::GetOrigin( void ) const {
|
||||
return origin;
|
||||
}
|
||||
|
||||
ID_INLINE const idMat3 &idFrustum::GetAxis( void ) const {
|
||||
return axis;
|
||||
}
|
||||
|
||||
ID_INLINE idVec3 idFrustum::GetCenter( void ) const {
|
||||
return ( origin + axis[0] * ( ( dFar - dNear ) * 0.5f ) );
|
||||
}
|
||||
|
||||
ID_INLINE bool idFrustum::IsValid( void ) const {
|
||||
return ( dFar > dNear );
|
||||
}
|
||||
|
||||
ID_INLINE float idFrustum::GetNearDistance( void ) const {
|
||||
return dNear;
|
||||
}
|
||||
|
||||
ID_INLINE float idFrustum::GetFarDistance( void ) const {
|
||||
return dFar;
|
||||
}
|
||||
|
||||
ID_INLINE float idFrustum::GetLeft( void ) const {
|
||||
return dLeft;
|
||||
}
|
||||
|
||||
ID_INLINE float idFrustum::GetUp( void ) const {
|
||||
return dUp;
|
||||
}
|
||||
|
||||
ID_INLINE idFrustum idFrustum::Expand( const float d ) const {
|
||||
idFrustum f = *this;
|
||||
f.origin -= d * f.axis[0];
|
||||
f.dFar += 2.0f * d;
|
||||
f.dLeft = f.dFar * dLeft * invFar;
|
||||
f.dUp = f.dFar * dUp * invFar;
|
||||
f.invFar = 1.0f / dFar;
|
||||
return f;
|
||||
}
|
||||
|
||||
ID_INLINE idFrustum &idFrustum::ExpandSelf( const float d ) {
|
||||
origin -= d * axis[0];
|
||||
dFar += 2.0f * d;
|
||||
dLeft = dFar * dLeft * invFar;
|
||||
dUp = dFar * dUp * invFar;
|
||||
invFar = 1.0f / dFar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idFrustum idFrustum::Translate( const idVec3 &translation ) const {
|
||||
idFrustum f = *this;
|
||||
f.origin += translation;
|
||||
return f;
|
||||
}
|
||||
|
||||
ID_INLINE idFrustum &idFrustum::TranslateSelf( const idVec3 &translation ) {
|
||||
origin += translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idFrustum idFrustum::Rotate( const idMat3 &rotation ) const {
|
||||
idFrustum f = *this;
|
||||
f.axis *= rotation;
|
||||
return f;
|
||||
}
|
||||
|
||||
ID_INLINE idFrustum &idFrustum::RotateSelf( const idMat3 &rotation ) {
|
||||
axis *= rotation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif /* !__BV_FRUSTUM_H__ */
|
||||
143
neo/idlib/bv/Frustum_gcc.cpp
Normal file
143
neo/idlib/bv/Frustum_gcc.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
#include "../precompiled.h"
|
||||
|
||||
void BoxToPoints( const idVec3 ¢er, const idVec3 &extents, const idMat3 &axis, idVec3 points[8] );
|
||||
|
||||
/*
|
||||
============
|
||||
idFrustum::ProjectionBounds
|
||||
============
|
||||
*/
|
||||
bool idFrustum::ProjectionBounds( const idBox &box, idBounds &projectionBounds ) const {
|
||||
int i, p1, p2, pointCull[8], culled, outside;
|
||||
float scale1, scale2;
|
||||
idFrustum localFrustum;
|
||||
idVec3 points[8], localOrigin;
|
||||
idMat3 localAxis, localScaled;
|
||||
idBounds bounds( -box.GetExtents(), box.GetExtents() );
|
||||
|
||||
// if the frustum origin is inside the bounds
|
||||
if ( bounds.ContainsPoint( ( origin - box.GetCenter() ) * box.GetAxis().Transpose() ) ) {
|
||||
// bounds that cover the whole frustum
|
||||
float boxMin, boxMax, base;
|
||||
|
||||
base = origin * axis[0];
|
||||
box.AxisProjection( axis[0], boxMin, boxMax );
|
||||
|
||||
projectionBounds[0].x = boxMin - base;
|
||||
projectionBounds[1].x = boxMax - base;
|
||||
projectionBounds[0].y = projectionBounds[0].z = -1.0f;
|
||||
projectionBounds[1].y = projectionBounds[1].z = 1.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
projectionBounds.Clear();
|
||||
|
||||
// transform the bounds into the space of this frustum
|
||||
localOrigin = ( box.GetCenter() - origin ) * axis.Transpose();
|
||||
localAxis = box.GetAxis() * axis.Transpose();
|
||||
BoxToPoints( localOrigin, box.GetExtents(), localAxis, points );
|
||||
|
||||
// test outer four edges of the bounds
|
||||
culled = -1;
|
||||
outside = 0;
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
p1 = i;
|
||||
p2 = 4 + i;
|
||||
AddLocalLineToProjectionBoundsSetCull( points[p1], points[p2], pointCull[p1], pointCull[p2], projectionBounds );
|
||||
culled &= pointCull[p1] & pointCull[p2];
|
||||
outside |= pointCull[p1] | pointCull[p2];
|
||||
}
|
||||
|
||||
// if the bounds are completely outside this frustum
|
||||
if ( culled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the bounds are completely inside this frustum
|
||||
if ( !outside ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// test the remaining edges of the bounds
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
p1 = i;
|
||||
p2 = (i+1)&3;
|
||||
AddLocalLineToProjectionBoundsUseCull( points[p1], points[p2], pointCull[p1], pointCull[p2], projectionBounds );
|
||||
}
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
p1 = 4 + i;
|
||||
p2 = 4 + ((i+1)&3);
|
||||
AddLocalLineToProjectionBoundsUseCull( points[p1], points[p2], pointCull[p1], pointCull[p2], projectionBounds );
|
||||
}
|
||||
|
||||
// if the bounds extend beyond two or more boundaries of this frustum
|
||||
if ( outside != 1 && outside != 2 && outside != 4 && outside != 8 ) {
|
||||
|
||||
localOrigin = ( origin - box.GetCenter() ) * box.GetAxis().Transpose();
|
||||
localScaled = axis * box.GetAxis().Transpose();
|
||||
localScaled[0] *= dFar;
|
||||
localScaled[1] *= dLeft;
|
||||
localScaled[2] *= dUp;
|
||||
|
||||
// test the outer edges of this frustum for intersection with the bounds
|
||||
if ( (outside & 2) && (outside & 8) ) {
|
||||
BoundsRayIntersection( bounds, localOrigin, localScaled[0] - localScaled[1] - localScaled[2], scale1, scale2 );
|
||||
if ( scale1 <= scale2 && scale1 >= 0.0f ) {
|
||||
projectionBounds.AddPoint( idVec3( scale1 * dFar, -1.0f, -1.0f ) );
|
||||
projectionBounds.AddPoint( idVec3( scale2 * dFar, -1.0f, -1.0f ) );
|
||||
}
|
||||
}
|
||||
if ( (outside & 2) && (outside & 4) ) {
|
||||
BoundsRayIntersection( bounds, localOrigin, localScaled[0] - localScaled[1] + localScaled[2], scale1, scale2 );
|
||||
if ( scale1 <= scale2 && scale1 >= 0.0f ) {
|
||||
projectionBounds.AddPoint( idVec3( scale1 * dFar, -1.0f, 1.0f ) );
|
||||
projectionBounds.AddPoint( idVec3( scale2 * dFar, -1.0f, 1.0f ) );
|
||||
}
|
||||
}
|
||||
if ( (outside & 1) && (outside & 8) ) {
|
||||
BoundsRayIntersection( bounds, localOrigin, localScaled[0] + localScaled[1] - localScaled[2], scale1, scale2 );
|
||||
if ( scale1 <= scale2 && scale1 >= 0.0f ) {
|
||||
projectionBounds.AddPoint( idVec3( scale1 * dFar, 1.0f, -1.0f ) );
|
||||
projectionBounds.AddPoint( idVec3( scale2 * dFar, 1.0f, -1.0f ) );
|
||||
}
|
||||
}
|
||||
if ( (outside & 1) && (outside & 2) ) {
|
||||
BoundsRayIntersection( bounds, localOrigin, localScaled[0] + localScaled[1] + localScaled[2], scale1, scale2 );
|
||||
if ( scale1 <= scale2 && scale1 >= 0.0f ) {
|
||||
projectionBounds.AddPoint( idVec3( scale1 * dFar, 1.0f, 1.0f ) );
|
||||
projectionBounds.AddPoint( idVec3( scale2 * dFar, 1.0f, 1.0f ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
155
neo/idlib/bv/Sphere.cpp
Normal file
155
neo/idlib/bv/Sphere.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "../precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
|
||||
idSphere sphere_zero( vec3_zero, 0.0f );
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idSphere::PlaneDistance
|
||||
================
|
||||
*/
|
||||
float idSphere::PlaneDistance( const idPlane &plane ) const {
|
||||
float d;
|
||||
|
||||
d = plane.Distance( origin );
|
||||
if ( d > radius ) {
|
||||
return d - radius;
|
||||
}
|
||||
if ( d < -radius ) {
|
||||
return d + radius;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idSphere::PlaneSide
|
||||
================
|
||||
*/
|
||||
int idSphere::PlaneSide( const idPlane &plane, const float epsilon ) const {
|
||||
float d;
|
||||
|
||||
d = plane.Distance( origin );
|
||||
if ( d > radius + epsilon ) {
|
||||
return PLANESIDE_FRONT;
|
||||
}
|
||||
if ( d < -radius - epsilon ) {
|
||||
return PLANESIDE_BACK;
|
||||
}
|
||||
return PLANESIDE_CROSS;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idSphere::LineIntersection
|
||||
|
||||
Returns true if the line intersects the sphere between the start and end point.
|
||||
============
|
||||
*/
|
||||
bool idSphere::LineIntersection( const idVec3 &start, const idVec3 &end ) const {
|
||||
idVec3 r, s, e;
|
||||
float a;
|
||||
|
||||
s = start - origin;
|
||||
e = end - origin;
|
||||
r = e - s;
|
||||
a = -s * r;
|
||||
if ( a <= 0 ) {
|
||||
return ( s * s < radius * radius );
|
||||
}
|
||||
else if ( a >= r * r ) {
|
||||
return ( e * e < radius * radius );
|
||||
}
|
||||
else {
|
||||
r = s + ( a / ( r * r ) ) * r;
|
||||
return ( r * r < radius * radius );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idSphere::RayIntersection
|
||||
|
||||
Returns true if the ray intersects the sphere.
|
||||
The ray can intersect the sphere in both directions from the start point.
|
||||
If start is inside the sphere then scale1 < 0 and scale2 > 0.
|
||||
============
|
||||
*/
|
||||
bool idSphere::RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const {
|
||||
double a, b, c, d, sqrtd;
|
||||
idVec3 p;
|
||||
|
||||
p = start - origin;
|
||||
a = dir * dir;
|
||||
b = dir * p;
|
||||
c = p * p - radius * radius;
|
||||
d = b * b - c * a;
|
||||
|
||||
if ( d < 0.0f ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sqrtd = idMath::Sqrt( d );
|
||||
a = 1.0f / a;
|
||||
|
||||
scale1 = ( -b + sqrtd ) * a;
|
||||
scale2 = ( -b - sqrtd ) * a;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
idSphere::FromPoints
|
||||
|
||||
Tight sphere for a point set.
|
||||
============
|
||||
*/
|
||||
void idSphere::FromPoints( const idVec3 *points, const int numPoints ) {
|
||||
int i;
|
||||
float radiusSqr, dist;
|
||||
idVec3 mins, maxs;
|
||||
|
||||
SIMDProcessor->MinMax( mins, maxs, points, numPoints );
|
||||
|
||||
origin = ( mins + maxs ) * 0.5f;
|
||||
|
||||
radiusSqr = 0.0f;
|
||||
for ( i = 0; i < numPoints; i++ ) {
|
||||
dist = ( points[i] - origin ).LengthSqr();
|
||||
if ( dist > radiusSqr ) {
|
||||
radiusSqr = dist;
|
||||
}
|
||||
}
|
||||
radius = idMath::Sqrt( radiusSqr );
|
||||
}
|
||||
275
neo/idlib/bv/Sphere.h
Normal file
275
neo/idlib/bv/Sphere.h
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 GPL Source Code
|
||||
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
||||
|
||||
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
||||
|
||||
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __BV_SPHERE_H__
|
||||
#define __BV_SPHERE_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Sphere
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idSphere {
|
||||
public:
|
||||
idSphere( void );
|
||||
explicit idSphere( const idVec3 &point );
|
||||
explicit idSphere( const idVec3 &point, const float r );
|
||||
|
||||
float operator[]( const int index ) const;
|
||||
float & operator[]( const int index );
|
||||
idSphere operator+( const idVec3 &t ) const; // returns tranlated sphere
|
||||
idSphere & operator+=( const idVec3 &t ); // translate the sphere
|
||||
idSphere operator+( const idSphere &s ) const;
|
||||
idSphere & operator+=( const idSphere &s );
|
||||
|
||||
bool Compare( const idSphere &a ) const; // exact compare, no epsilon
|
||||
bool Compare( const idSphere &a, const float epsilon ) const; // compare with epsilon
|
||||
bool operator==( const idSphere &a ) const; // exact compare, no epsilon
|
||||
bool operator!=( const idSphere &a ) const; // exact compare, no epsilon
|
||||
|
||||
void Clear( void ); // inside out sphere
|
||||
void Zero( void ); // single point at origin
|
||||
void SetOrigin( const idVec3 &o ); // set origin of sphere
|
||||
void SetRadius( const float r ); // set square radius
|
||||
|
||||
const idVec3 & GetOrigin( void ) const; // returns origin of sphere
|
||||
float GetRadius( void ) const; // returns sphere radius
|
||||
bool IsCleared( void ) const; // returns true if sphere is inside out
|
||||
|
||||
bool AddPoint( const idVec3 &p ); // add the point, returns true if the sphere expanded
|
||||
bool AddSphere( const idSphere &s ); // add the sphere, returns true if the sphere expanded
|
||||
idSphere Expand( const float d ) const; // return bounds expanded in all directions with the given value
|
||||
idSphere & ExpandSelf( const float d ); // expand bounds in all directions with the given value
|
||||
idSphere Translate( const idVec3 &translation ) const;
|
||||
idSphere & TranslateSelf( const idVec3 &translation );
|
||||
|
||||
float PlaneDistance( const idPlane &plane ) const;
|
||||
int PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
|
||||
|
||||
bool ContainsPoint( const idVec3 &p ) const; // includes touching
|
||||
bool IntersectsSphere( const idSphere &s ) const; // includes touching
|
||||
bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||||
// intersection points are (start + dir * scale1) and (start + dir * scale2)
|
||||
bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||||
|
||||
// Tight sphere for a point set.
|
||||
void FromPoints( const idVec3 *points, const int numPoints );
|
||||
// Most tight sphere for a translation.
|
||||
void FromPointTranslation( const idVec3 &point, const idVec3 &translation );
|
||||
void FromSphereTranslation( const idSphere &sphere, const idVec3 &start, const idVec3 &translation );
|
||||
// Most tight sphere for a rotation.
|
||||
void FromPointRotation( const idVec3 &point, const idRotation &rotation );
|
||||
void FromSphereRotation( const idSphere &sphere, const idVec3 &start, const idRotation &rotation );
|
||||
|
||||
void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
|
||||
|
||||
private:
|
||||
idVec3 origin;
|
||||
float radius;
|
||||
};
|
||||
|
||||
extern idSphere sphere_zero;
|
||||
|
||||
ID_INLINE idSphere::idSphere( void ) {
|
||||
}
|
||||
|
||||
ID_INLINE idSphere::idSphere( const idVec3 &point ) {
|
||||
origin = point;
|
||||
radius = 0.0f;
|
||||
}
|
||||
|
||||
ID_INLINE idSphere::idSphere( const idVec3 &point, const float r ) {
|
||||
origin = point;
|
||||
radius = r;
|
||||
}
|
||||
|
||||
ID_INLINE float idSphere::operator[]( const int index ) const {
|
||||
return ((float *) &origin)[index];
|
||||
}
|
||||
|
||||
ID_INLINE float &idSphere::operator[]( const int index ) {
|
||||
return ((float *) &origin)[index];
|
||||
}
|
||||
|
||||
ID_INLINE idSphere idSphere::operator+( const idVec3 &t ) const {
|
||||
return idSphere( origin + t, radius );
|
||||
}
|
||||
|
||||
ID_INLINE idSphere &idSphere::operator+=( const idVec3 &t ) {
|
||||
origin += t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::Compare( const idSphere &a ) const {
|
||||
return ( origin.Compare( a.origin ) && radius == a.radius );
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::Compare( const idSphere &a, const float epsilon ) const {
|
||||
return ( origin.Compare( a.origin, epsilon ) && idMath::Fabs( radius - a.radius ) <= epsilon );
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::operator==( const idSphere &a ) const {
|
||||
return Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::operator!=( const idSphere &a ) const {
|
||||
return !Compare( a );
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::Clear( void ) {
|
||||
origin.Zero();
|
||||
radius = -1.0f;
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::Zero( void ) {
|
||||
origin.Zero();
|
||||
radius = 0.0f;
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::SetOrigin( const idVec3 &o ) {
|
||||
origin = o;
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::SetRadius( const float r ) {
|
||||
radius = r;
|
||||
}
|
||||
|
||||
ID_INLINE const idVec3 &idSphere::GetOrigin( void ) const {
|
||||
return origin;
|
||||
}
|
||||
|
||||
ID_INLINE float idSphere::GetRadius( void ) const {
|
||||
return radius;
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::IsCleared( void ) const {
|
||||
return ( radius < 0.0f );
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::AddPoint( const idVec3 &p ) {
|
||||
if ( radius < 0.0f ) {
|
||||
origin = p;
|
||||
radius = 0.0f;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
float r = ( p - origin ).LengthSqr();
|
||||
if ( r > radius * radius ) {
|
||||
r = idMath::Sqrt( r );
|
||||
origin += ( p - origin ) * 0.5f * (1.0f - radius / r );
|
||||
radius += 0.5f * ( r - radius );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::AddSphere( const idSphere &s ) {
|
||||
if ( radius < 0.0f ) {
|
||||
origin = s.origin;
|
||||
radius = s.radius;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
float r = ( s.origin - origin ).LengthSqr();
|
||||
if ( r > ( radius + s.radius ) * ( radius + s.radius ) ) {
|
||||
r = idMath::Sqrt( r );
|
||||
origin += ( s.origin - origin ) * 0.5f * (1.0f - radius / ( r + s.radius ) );
|
||||
radius += 0.5f * ( ( r + s.radius ) - radius );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ID_INLINE idSphere idSphere::Expand( const float d ) const {
|
||||
return idSphere( origin, radius + d );
|
||||
}
|
||||
|
||||
ID_INLINE idSphere &idSphere::ExpandSelf( const float d ) {
|
||||
radius += d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE idSphere idSphere::Translate( const idVec3 &translation ) const {
|
||||
return idSphere( origin + translation, radius );
|
||||
}
|
||||
|
||||
ID_INLINE idSphere &idSphere::TranslateSelf( const idVec3 &translation ) {
|
||||
origin += translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::ContainsPoint( const idVec3 &p ) const {
|
||||
if ( ( p - origin ).LengthSqr() > radius * radius ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE bool idSphere::IntersectsSphere( const idSphere &s ) const {
|
||||
float r = s.radius + radius;
|
||||
if ( ( s.origin - origin ).LengthSqr() > r * r ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::FromPointTranslation( const idVec3 &point, const idVec3 &translation ) {
|
||||
origin = point + 0.5f * translation;
|
||||
radius = idMath::Sqrt( 0.5f * translation.LengthSqr() );
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::FromSphereTranslation( const idSphere &sphere, const idVec3 &start, const idVec3 &translation ) {
|
||||
origin = start + sphere.origin + 0.5f * translation;
|
||||
radius = idMath::Sqrt( 0.5f * translation.LengthSqr() ) + sphere.radius;
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::FromPointRotation( const idVec3 &point, const idRotation &rotation ) {
|
||||
idVec3 end = rotation * point;
|
||||
origin = ( point + end ) * 0.5f;
|
||||
radius = idMath::Sqrt( 0.5f * ( end - point ).LengthSqr() );
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::FromSphereRotation( const idSphere &sphere, const idVec3 &start, const idRotation &rotation ) {
|
||||
idVec3 end = rotation * sphere.origin;
|
||||
origin = start + ( sphere.origin + end ) * 0.5f;
|
||||
radius = idMath::Sqrt( 0.5f * ( end - sphere.origin ).LengthSqr() ) + sphere.radius;
|
||||
}
|
||||
|
||||
ID_INLINE void idSphere::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
|
||||
float d;
|
||||
d = dir * origin;
|
||||
min = d - radius;
|
||||
max = d + radius;
|
||||
}
|
||||
|
||||
#endif /* !__BV_SPHERE_H__ */
|
||||
Reference in New Issue
Block a user