convert line ends
[canaan.git] / prj / cam / src / physics / phmods.cpp
blob9bbe67ec76725ebcf7cbd2d09eaa84fce202490c
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/physics/phmods.cpp,v 1.22 1999/06/15 19:05:11 ccarollo Exp $
8 //
9 // Physics model lists
11 // Implementation is that all models are only on one list
12 // The moving list is just the head of the active list and we keep a pointer to the first
13 // stationary model on the active list.
16 #include <lg.h>
17 #include <phystyp2.h>
18 #include <allocapi.h>
20 #include <phcore.h>
21 #include <phmod.h>
22 #include <phmods.h>
23 #include <phprop.h>
24 #include <phmodsph.h>
25 #include <phmodbsp.h>
26 #include <phmodobb.h>
27 #include <objedit.h>
29 #include <iobjsys.h>
30 #include <appagg.h>
32 #include <mprintf.h>
34 // Must be last header
35 #include <dbmem.h>
37 ///////////////////////////////////////////////////////////////////////////////
39 void cPhysModels::Read(PhysReadWrite func, ulong /* partition */ )
41 int i;
42 int model_type;
43 int nMoving, nStationary, nInactive;
44 int nDeferred;
45 cPhysSphereModel *pCurSphereModel;
46 cPhysBSPModel *pCurBSPModel;
47 cPhysOBBModel *pCurOBBModel;
49 // m_nMovingModels = m_nStationaryModels = m_nInactiveModels = 0;
51 // Moving models
52 func(&nMoving, sizeof(int), 1);
53 for (i=0; i<nMoving; i++)
55 func(&model_type, sizeof(int), 1);
56 switch (model_type) {
57 case kPMT_Point:
58 case kPMT_Sphere:
59 case kPMT_SphereHat:
61 pCurSphereModel = new cPhysSphereModel(func);
63 AddToMoving(pCurSphereModel);
65 break;
67 case kPMT_BSP:
69 pCurBSPModel = new cPhysBSPModel(func);
70 AddToMoving(pCurBSPModel);
71 break;
73 case kPMT_OBB:
75 pCurOBBModel = new cPhysOBBModel(func);
76 AddToMoving(pCurOBBModel);
77 break;
79 default:
81 Error(1, "Invalid PhysModel type: %d\n", model_type);
82 break;
89 // Stationary models
90 func(&nStationary, sizeof(int), 1);
91 for (i=0; i<nStationary; i++) {
92 func(&model_type, sizeof(int), 1);
93 switch (model_type) {
94 case kPMT_Point:
95 case kPMT_Sphere:
96 case kPMT_SphereHat:
98 pCurSphereModel = new cPhysSphereModel(func);
99 AddToStationary(pCurSphereModel);
100 break;
102 case kPMT_BSP:
104 pCurBSPModel = new cPhysBSPModel(func);
105 AddToStationary(pCurBSPModel);
106 break;
108 case kPMT_OBB:
110 pCurOBBModel = new cPhysOBBModel(func);
111 AddToStationary(pCurOBBModel);
112 break;
114 default:
116 Error(1, "Invalid PhysModel type: %d\n", model_type);
117 break;
122 // Inactive models
123 func(&nInactive, sizeof(int), 1);
124 for (i=0; i<nInactive; i++) {
125 func(&model_type, sizeof(int), 1);
126 switch (model_type) {
127 case kPMT_Point:
128 case kPMT_Sphere:
129 case kPMT_SphereHat:
131 pCurSphereModel = new cPhysSphereModel(func);
132 AddToInactive(pCurSphereModel);
133 break;
135 case kPMT_BSP:
137 pCurBSPModel = new cPhysBSPModel(func);
138 AddToInactive(pCurBSPModel);
139 break;
141 case kPMT_OBB:
143 pCurOBBModel = new cPhysOBBModel(func);
144 AddToInactive(pCurOBBModel);
145 break;
147 default:
149 Error(1, "Invalid PhysModel type: %d\n", model_type);
150 break;
155 if (g_PhysVersion >= 23)
157 func(&nDeferred, sizeof(int), 1);
158 LGALLOC_PUSH_CREDIT();
159 m_deferredVelocityList.SetSize(nDeferred);
160 LGALLOC_POP_CREDIT();
161 for (i=0; i<nDeferred; i++)
162 func(&m_deferredVelocityList[i], sizeof(sDeferredVelocity), 1);
164 else
165 m_deferredVelocityList.SetSize(0);
169 void cPhysModels::Write(PhysReadWrite func, eObjPartition part)
171 cPhysModel *pCurModel;
172 int model_type;
173 int num_models;
174 int num_deferred;
176 AutoAppIPtr_(ObjectSystem,pObjSys);
178 // Moving models
180 // count the number of moving models we're actually saving
181 num_models = 0;
182 for (pCurModel = GetFirstMoving(); pCurModel != NULL; pCurModel = GetNextMoving(pCurModel))
184 if (pObjSys->IsObjSavePartition(pCurModel->GetObjID(),part))
185 num_models++;
189 func(&num_models, sizeof(int), 1);
190 for (pCurModel = GetFirstMoving(); pCurModel != NULL; pCurModel = GetNextMoving(pCurModel))
192 if (!pObjSys->IsObjSavePartition(pCurModel->GetObjID(),part))
193 continue;
195 // Write the model type so that it knows what's coming when reading
196 // @TODO: This needs to be fixed when/if we mix submodel types
197 model_type = (int)pCurModel->GetType(0);
198 func(&model_type, sizeof(int), 1);
199 // This will call the appropriate descendant's write function
200 pCurModel->Write(func);
204 // Stationary models
206 // count the number of stationary models we're actually saving
207 num_models = 0;
208 for (pCurModel = GetFirstStationary(); pCurModel != NULL; pCurModel = GetNextStationary(pCurModel))
210 if (pObjSys->IsObjSavePartition(pCurModel->GetObjID(),part))
211 num_models++;
214 func(&num_models, sizeof(int), 1);
215 for (pCurModel = GetFirstStationary(); pCurModel != NULL; pCurModel = GetNextStationary(pCurModel))
217 if (!pObjSys->IsObjSavePartition(pCurModel->GetObjID(),part))
218 continue;
220 model_type = (int)pCurModel->GetType(0);
221 func(&model_type, sizeof(int), 1);
222 pCurModel->Write(func);
226 // Inactive models
228 // count how many...
229 num_models = 0;
230 for (pCurModel = GetFirstInactive(); pCurModel != NULL; pCurModel = GetNextInactive(pCurModel))
232 if (pObjSys->IsObjSavePartition(pCurModel->GetObjID(),part))
233 num_models++;
236 func(&num_models, sizeof(int), 1);
238 for (pCurModel = GetFirstInactive(); pCurModel != NULL; pCurModel = GetNextInactive(pCurModel))
240 if (!pObjSys->IsObjSavePartition(pCurModel->GetObjID(),part))
241 continue;
243 model_type = (int)pCurModel->GetType(0);
244 func(&model_type, sizeof(int), 1);
245 pCurModel->Write(func);
248 num_deferred = m_deferredVelocityList.Size();
249 func(&num_deferred, sizeof(int), 1);
250 for (int i=0; i<num_deferred; i++)
251 func(&m_deferredVelocityList[i], sizeof(sDeferredVelocity), 1);
254 ///////////////////////////////////////////////////////////////////////////////
256 void cPhysModels::Remove(cPhysModel * pModel)
258 DecNum(pModel);
260 if (pModel->IsActive())
262 if (m_pFirstStationary == pModel)
263 m_pFirstStationary = m_pFirstStationary->GetNext();
264 m_activeList.Remove(pModel);
265 m_activeTable.Remove(pModel);
267 else
269 m_inactiveList.Remove(pModel);
270 m_inactiveTable.Remove(pModel);
274 ///////////////////////////////////////
276 void cPhysModels::DestroyAllInList(cPhysModelList * pList)
278 cPhysModel * pModel;
279 cPhysModel * pNextModel;
281 pModel = pList->GetFirst();
283 while (pModel)
285 #if 0
286 // if (pModel->IsHigh())
287 g_pHighModelProperty->Delete(pModel->GetObjID());
288 // else
289 g_pLowModelProperty->Delete(pModel->GetObjID());
290 #endif
292 pNextModel = pModel->GetNext();
293 pList->Remove(pModel);
294 delete pModel;
295 pModel = pNextModel;
299 ///////////////////////////////////////
301 void cPhysModels::DestroyAll()
303 m_activeTable.SetEmpty();
304 m_inactiveTable.SetEmpty();
305 DestroyAllInList(&m_activeList);
306 DestroyAllInList(&m_inactiveList);
307 m_nMovingModels = m_nStationaryModels = m_nInactiveModels = 0;
308 m_pFirstStationary = NULL;
311 ///////////////////////////////////////
313 void cPhysModels::AddToStationary(cPhysModel * pModel)
315 ConfigSpew("ModelState", ("Object %d becomes stationary\n", pModel->GetObjID()));
316 if (m_pFirstStationary == NULL)
317 m_pFirstStationary = pModel;
319 LGALLOC_PUSH_CREDIT();
320 m_activeList.Append(pModel);
321 LGALLOC_POP_CREDIT();
323 m_activeTable.Insert(pModel);
324 pModel->SetStationary(TRUE);
325 m_nStationaryModels++;
328 ///////////////////////////////////////
330 void cPhysModels::Deactivate(cPhysModel * pModel)
332 #ifdef DBG_ON
333 if (!pModel->IsActive())
334 Warning(("cPhysModels::Deactivate: model is not currently active\n"));
335 #endif
336 if (m_pFirstStationary == pModel)
337 m_pFirstStationary = m_pFirstStationary->GetNext();
338 m_activeList.Remove(pModel);
339 m_activeTable.Remove(pModel);
340 DecNum(pModel);
341 AddToInactive(pModel);
344 ///////////////////////////////////////
346 void cPhysModels::ActivateToMoving(cPhysModel * pModel)
348 #ifdef DBG_ON
349 if (pModel->IsActive())
350 Warning(("cPhysModels::ActivateToMoving: model is already active\n"));
351 #endif
352 m_inactiveList.Remove(pModel);
353 m_inactiveTable.Remove(pModel);
354 DecNum(pModel);
355 AddToMoving(pModel);
358 ///////////////////////////////////////
360 void cPhysModels::StopMoving(cPhysModel * pModel)
362 #ifdef DBG_ON
363 if (!(pModel->IsActive()))
364 Warning(("cPhysModels::StopMoving: model is not currently active\n"));
365 #endif
366 m_activeList.Remove(pModel);
367 m_activeTable.Remove(pModel);
368 DecNum(pModel);
369 AddToStationary(pModel);
372 ///////////////////////////////////////
374 void cPhysModels::StartMoving(cPhysModel * pModel)
376 #ifdef DBG_ON
377 if (!(pModel->IsActive()))
378 Warning(("cPhysModels::StartMoving: model is not currently active\n"));
379 #endif
380 if (m_pFirstStationary == pModel)
381 m_pFirstStationary = m_pFirstStationary->GetNext();
382 m_activeList.Remove(pModel);
383 m_activeTable.Remove(pModel);
384 DecNum(pModel);
385 AddToMoving(pModel);
388 ///////////////////////////////////////////////////////////////////////////////
390 void cPhysModels::AddDeferredVelocity(ObjID objID, const mxs_vector &velocity)
392 sDeferredVelocity defer;
394 defer.objID = objID;
395 defer.submod = -1;
396 defer.velocity = velocity;
398 LGALLOC_AUTO_CREDIT();
399 m_deferredVelocityList.Append(defer);
402 ////////////////////////////////////////
404 void cPhysModels::AddDeferredVelocity(ObjID objID, int subModId, const mxs_vector &velocity)
406 sDeferredVelocity defer;
408 defer.objID = objID;
409 defer.submod = subModId;
410 defer.velocity = velocity;
412 LGALLOC_AUTO_CREDIT();
413 m_deferredVelocityList.Append(defer);
416 ////////////////////////////////////////
418 void cPhysModels::ApplyDeferredVelocities()
420 cPhysModel *pModel;
421 mxs_vector velocity;
423 for (int i=0; i<m_deferredVelocityList.Size(); i++)
425 pModel = g_PhysModels.Get(m_deferredVelocityList[i].objID);
427 if (pModel == NULL)
429 Warning(("ApplyDeferredVelocities: %s has no physics model\n", ObjWarnName(m_deferredVelocityList[i].objID)));
430 continue;
433 mx_copy_vec(&velocity, &pModel->GetVelocity(m_deferredVelocityList[i].submod));
434 mx_addeq_vec(&velocity, &m_deferredVelocityList[i].velocity);
435 pModel->GetDynamics(m_deferredVelocityList[i].submod)->SetVelocity(velocity);
437 pModel->SetSleep(FALSE);
440 m_deferredVelocityList.SetSize(0);
443 ///////////////////////////////////////////////////////////////////////////////
445 #ifndef SHIP
447 void cPhysModels::SpewStats()
449 cPhysModel *pModel;
451 long total_size;
453 // Sum sizes of main structures
454 long contact_size = 0;
455 long external_size = 0;
456 long internal_size = 0;
458 int obb_count = 0;
459 int sphere_count = 0;
461 int model_count = 0;
463 pModel = m_activeList.GetFirst();
464 while (pModel)
466 switch (pModel->GetType(0))
468 case kPMT_Sphere:
469 case kPMT_Point:
470 case kPMT_SphereHat:
472 sphere_count++;
473 external_size += sizeof(cPhysSphereModel);
474 internal_size += ((cPhysSphereModel *)pModel)->InternalSize();
475 break;
477 case kPMT_OBB:
479 obb_count++;
480 external_size += sizeof(cPhysOBBModel);
481 internal_size += ((cPhysOBBModel *)pModel)->InternalSize();
482 break;
486 model_count++;
487 pModel = pModel->GetNext();
490 pModel = m_inactiveList.GetFirst();
491 while (pModel)
493 switch (pModel->GetType(0))
495 case kPMT_Sphere:
496 case kPMT_Point:
497 case kPMT_SphereHat:
499 sphere_count++;
500 external_size += sizeof(cPhysSphereModel);
501 internal_size += ((cPhysSphereModel *)pModel)->InternalSize();
502 break;
504 case kPMT_OBB:
506 obb_count++;
507 external_size += sizeof(cPhysOBBModel);
508 internal_size += ((cPhysOBBModel *)pModel)->InternalSize();
509 break;
513 model_count++;
514 pModel = pModel->GetNext();
517 // Total it up
518 total_size = external_size + internal_size;
520 mprintf(" Models: %d (%d sphere, %d obb)\n", model_count, sphere_count, obb_count);
521 mprintf(" external: %dk\n", external_size >> 10);
522 mprintf(" internal: %dk\n", internal_size >> 10);
523 mprintf("Total: %dk\n", total_size >> 10);
526 void cPhysModels::HackListRemove(cPhysModel *pModel)
528 if (pModel->IsActive())
530 if (m_pFirstStationary == pModel)
531 m_pFirstStationary = m_pFirstStationary->GetNext();
532 m_activeList.Remove(pModel);
534 else
535 m_inactiveList.Remove(pModel);
538 #endif
540 ///////////////////////////////////////////////////////////////////////////////