Clip.h (13784B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 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. 25 26 =========================================================================== 27 */ 28 29 #ifndef __CLIP_H__ 30 #define __CLIP_H__ 31 32 /* 33 =============================================================================== 34 35 Handles collision detection with the world and between physics objects. 36 37 =============================================================================== 38 */ 39 40 #define CLIPMODEL_ID_TO_JOINT_HANDLE( id ) ( ( id ) >= 0 ? INVALID_JOINT : ((jointHandle_t) ( -1 - id )) ) 41 #define JOINT_HANDLE_TO_CLIPMODEL_ID( id ) ( -1 - id ) 42 43 class idClip; 44 class idClipModel; 45 class idEntity; 46 47 //=============================================================== 48 // 49 // idClipModel 50 // 51 //=============================================================== 52 53 class idClipModel { 54 55 friend class idClip; 56 57 public: 58 idClipModel(); 59 explicit idClipModel( const char *name ); 60 explicit idClipModel( const idTraceModel &trm ); 61 explicit idClipModel( const idTraceModel &trm, bool persistantThroughSave ); 62 explicit idClipModel( const int renderModelHandle ); 63 explicit idClipModel( const idClipModel *model ); 64 ~idClipModel(); 65 66 bool LoadModel( const char *name ); 67 void LoadModel( const idTraceModel &trm, bool persistantThroughSave = true ); 68 void LoadModel( const int renderModelHandle ); 69 70 void Save( idSaveGame *savefile ) const; 71 void Restore( idRestoreGame *savefile ); 72 73 void Link( idClip &clp ); // must have been linked with an entity and id before 74 void Link( idClip &clp, idEntity *ent, int newId, const idVec3 &newOrigin, const idMat3 &newAxis, int renderModelHandle = -1 ); 75 void Unlink(); // unlink from sectors 76 void SetPosition( const idVec3 &newOrigin, const idMat3 &newAxis ); // unlinks the clip model 77 void Translate( const idVec3 &translation ); // unlinks the clip model 78 void Rotate( const idRotation &rotation ); // unlinks the clip model 79 void Enable(); // enable for clipping 80 void Disable(); // keep linked but disable for clipping 81 void SetMaterial( const idMaterial *m ); 82 const idMaterial * GetMaterial() const; 83 void SetContents( int newContents ); // override contents 84 int GetContents() const; 85 void SetEntity( idEntity *newEntity ); 86 idEntity * GetEntity() const; 87 void SetId( int newId ); 88 int GetId() const; 89 void SetOwner( idEntity *newOwner ); 90 idEntity * GetOwner() const; 91 const idBounds & GetBounds() const; 92 const idBounds & GetAbsBounds() const; 93 const idVec3 & GetOrigin() const; 94 const idMat3 & GetAxis() const; 95 bool IsTraceModel() const; // returns true if this is a trace model 96 bool IsRenderModel() const; // returns true if this is a render model 97 bool IsLinked() const; // returns true if the clip model is linked 98 bool IsEnabled() const; // returns true if enabled for collision detection 99 bool IsEqual( const idTraceModel &trm ) const; 100 cmHandle_t Handle() const; // returns handle used to collide vs this model 101 const idTraceModel * GetTraceModel() const; 102 void GetMassProperties( const float density, float &mass, idVec3 ¢erOfMass, idMat3 &inertiaTensor ) const; 103 104 static cmHandle_t CheckModel( const char *name ); 105 static void ClearTraceModelCache(); 106 static int TraceModelCacheSize(); 107 108 static void SaveTraceModels( idSaveGame *savefile ); 109 static void RestoreTraceModels( idRestoreGame *savefile ); 110 111 private: 112 bool enabled; // true if this clip model is used for clipping 113 idEntity * entity; // entity using this clip model 114 int id; // id for entities that use multiple clip models 115 idEntity * owner; // owner of the entity that owns this clip model 116 idVec3 origin; // origin of clip model 117 idMat3 axis; // orientation of clip model 118 idBounds bounds; // bounds 119 idBounds absBounds; // absolute bounds 120 const idMaterial * material; // material for trace models 121 int contents; // all contents ored together 122 cmHandle_t collisionModelHandle; // handle to collision model 123 int traceModelIndex; // trace model used for collision detection 124 int renderModelHandle; // render model def handle 125 126 struct clipLink_s * clipLinks; // links into sectors 127 int touchCount; 128 129 void Init(); // initialize 130 void Link_r( struct clipSector_s *node ); 131 132 static int AllocTraceModel( const idTraceModel &trm, bool persistantThroughSaves = true ); 133 static void FreeTraceModel( int traceModelIndex ); 134 static idTraceModel * GetCachedTraceModel( int traceModelIndex ); 135 static int GetTraceModelHashKey( const idTraceModel &trm ); 136 static struct trmCache_s * GetTraceModelEntry( int traceModelIndex ); 137 }; 138 139 140 ID_INLINE void idClipModel::Translate( const idVec3 &translation ) { 141 Unlink(); 142 origin += translation; 143 } 144 145 ID_INLINE void idClipModel::Rotate( const idRotation &rotation ) { 146 Unlink(); 147 origin *= rotation; 148 axis *= rotation.ToMat3(); 149 } 150 151 ID_INLINE void idClipModel::Enable() { 152 enabled = true; 153 } 154 155 ID_INLINE void idClipModel::Disable() { 156 enabled = false; 157 } 158 159 ID_INLINE void idClipModel::SetMaterial( const idMaterial *m ) { 160 material = m; 161 } 162 163 ID_INLINE const idMaterial * idClipModel::GetMaterial() const { 164 return material; 165 } 166 167 ID_INLINE void idClipModel::SetContents( int newContents ) { 168 contents = newContents; 169 } 170 171 ID_INLINE int idClipModel::GetContents() const { 172 return contents; 173 } 174 175 ID_INLINE void idClipModel::SetEntity( idEntity *newEntity ) { 176 entity = newEntity; 177 } 178 179 ID_INLINE idEntity *idClipModel::GetEntity() const { 180 return entity; 181 } 182 183 ID_INLINE void idClipModel::SetId( int newId ) { 184 id = newId; 185 } 186 187 ID_INLINE int idClipModel::GetId() const { 188 return id; 189 } 190 191 ID_INLINE void idClipModel::SetOwner( idEntity *newOwner ) { 192 owner = newOwner; 193 } 194 195 ID_INLINE idEntity *idClipModel::GetOwner() const { 196 return owner; 197 } 198 199 ID_INLINE const idBounds &idClipModel::GetBounds() const { 200 return bounds; 201 } 202 203 ID_INLINE const idBounds &idClipModel::GetAbsBounds() const { 204 return absBounds; 205 } 206 207 ID_INLINE const idVec3 &idClipModel::GetOrigin() const { 208 return origin; 209 } 210 211 ID_INLINE const idMat3 &idClipModel::GetAxis() const { 212 return axis; 213 } 214 215 ID_INLINE bool idClipModel::IsRenderModel() const { 216 return ( renderModelHandle != -1 ); 217 } 218 219 ID_INLINE bool idClipModel::IsTraceModel() const { 220 return ( traceModelIndex != -1 ); 221 } 222 223 ID_INLINE bool idClipModel::IsLinked() const { 224 return ( clipLinks != NULL ); 225 } 226 227 ID_INLINE bool idClipModel::IsEnabled() const { 228 return enabled; 229 } 230 231 ID_INLINE bool idClipModel::IsEqual( const idTraceModel &trm ) const { 232 return ( traceModelIndex != -1 && *GetCachedTraceModel( traceModelIndex ) == trm ); 233 } 234 235 ID_INLINE const idTraceModel *idClipModel::GetTraceModel() const { 236 if ( !IsTraceModel() ) { 237 return NULL; 238 } 239 return idClipModel::GetCachedTraceModel( traceModelIndex ); 240 } 241 242 243 //=============================================================== 244 // 245 // idClip 246 // 247 //=============================================================== 248 249 class idClip { 250 251 friend class idClipModel; 252 253 public: 254 idClip(); 255 256 void Init(); 257 void Shutdown(); 258 259 // clip versus the rest of the world 260 bool Translation( trace_t &results, const idVec3 &start, const idVec3 &end, 261 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ); 262 bool Rotation( trace_t &results, const idVec3 &start, const idRotation &rotation, 263 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ); 264 bool Motion( trace_t &results, const idVec3 &start, const idVec3 &end, const idRotation &rotation, 265 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ); 266 int Contacts( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth, 267 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ); 268 int Contents( const idVec3 &start, 269 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ); 270 271 // special case translations versus the rest of the world 272 bool TracePoint( trace_t &results, const idVec3 &start, const idVec3 &end, 273 int contentMask, const idEntity *passEntity ); 274 bool TraceBounds( trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds, 275 int contentMask, const idEntity *passEntity ); 276 277 // clip versus a specific model 278 void TranslationModel( trace_t &results, const idVec3 &start, const idVec3 &end, 279 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, 280 cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ); 281 void RotationModel( trace_t &results, const idVec3 &start, const idRotation &rotation, 282 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, 283 cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ); 284 int ContactsModel( contactInfo_t *contacts, const int maxContacts, const idVec3 &start, const idVec6 &dir, const float depth, 285 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, 286 cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ); 287 int ContentsModel( const idVec3 &start, 288 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, 289 cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ); 290 291 // clip versus all entities but not the world 292 void TranslationEntities( trace_t &results, const idVec3 &start, const idVec3 &end, 293 const idClipModel *mdl, const idMat3 &trmAxis, int contentMask, const idEntity *passEntity ); 294 295 // get a contact feature 296 bool GetModelContactFeature( const contactInfo_t &contact, const idClipModel *clipModel, idFixedWinding &winding ) const; 297 298 // get entities/clip models within or touching the given bounds 299 int EntitiesTouchingBounds( const idBounds &bounds, int contentMask, idEntity **entityList, int maxCount ) const; 300 int ClipModelsTouchingBounds( const idBounds &bounds, int contentMask, idClipModel **clipModelList, int maxCount ) const; 301 302 const idBounds & GetWorldBounds() const; 303 idClipModel * DefaultClipModel(); 304 305 // stats and debug drawing 306 void PrintStatistics(); 307 void DrawClipModels( const idVec3 &eye, const float radius, const idEntity *passEntity ); 308 bool DrawModelContactFeature( const contactInfo_t &contact, const idClipModel *clipModel, int lifetime ) const; 309 310 private: 311 int numClipSectors; 312 struct clipSector_s * clipSectors; 313 idBounds worldBounds; 314 idClipModel temporaryClipModel; 315 idClipModel defaultClipModel; 316 mutable int touchCount; 317 // statistics 318 int numTranslations; 319 int numRotations; 320 int numMotions; 321 int numRenderModelTraces; 322 int numContents; 323 int numContacts; 324 325 private: 326 struct clipSector_s * CreateClipSectors_r( const int depth, const idBounds &bounds, idVec3 &maxSector ); 327 void ClipModelsTouchingBounds_r( const struct clipSector_s *node, struct listParms_s &parms ) const; 328 const idTraceModel * TraceModelForClipModel( const idClipModel *mdl ) const; 329 int GetTraceClipModels( const idBounds &bounds, int contentMask, const idEntity *passEntity, idClipModel **clipModelList ) const; 330 void TraceRenderModel( trace_t &trace, const idVec3 &start, const idVec3 &end, const float radius, const idMat3 &axis, idClipModel *touch ) const; 331 }; 332 333 334 ID_INLINE bool idClip::TracePoint( trace_t &results, const idVec3 &start, const idVec3 &end, int contentMask, const idEntity *passEntity ) { 335 Translation( results, start, end, NULL, mat3_identity, contentMask, passEntity ); 336 return ( results.fraction < 1.0f ); 337 } 338 339 ID_INLINE bool idClip::TraceBounds( trace_t &results, const idVec3 &start, const idVec3 &end, const idBounds &bounds, int contentMask, const idEntity *passEntity ) { 340 temporaryClipModel.LoadModel( idTraceModel( bounds ) ); 341 Translation( results, start, end, &temporaryClipModel, mat3_identity, contentMask, passEntity ); 342 return ( results.fraction < 1.0f ); 343 } 344 345 ID_INLINE const idBounds & idClip::GetWorldBounds() const { 346 return worldBounds; 347 } 348 349 ID_INLINE idClipModel *idClip::DefaultClipModel() { 350 return &defaultClipModel; 351 } 352 353 #endif /* !__CLIP_H__ */