2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/physics/phmods.cpp,v 1.22 1999/06/15 19:05:11 ccarollo Exp $
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.
34 // Must be last header
37 ///////////////////////////////////////////////////////////////////////////////
39 void cPhysModels::Read(PhysReadWrite func
, ulong
/* partition */ )
43 int nMoving
, nStationary
, nInactive
;
45 cPhysSphereModel
*pCurSphereModel
;
46 cPhysBSPModel
*pCurBSPModel
;
47 cPhysOBBModel
*pCurOBBModel
;
49 // m_nMovingModels = m_nStationaryModels = m_nInactiveModels = 0;
52 func(&nMoving
, sizeof(int), 1);
53 for (i
=0; i
<nMoving
; i
++)
55 func(&model_type
, sizeof(int), 1);
61 pCurSphereModel
= new cPhysSphereModel(func
);
63 AddToMoving(pCurSphereModel
);
69 pCurBSPModel
= new cPhysBSPModel(func
);
70 AddToMoving(pCurBSPModel
);
75 pCurOBBModel
= new cPhysOBBModel(func
);
76 AddToMoving(pCurOBBModel
);
81 Error(1, "Invalid PhysModel type: %d\n", model_type
);
90 func(&nStationary
, sizeof(int), 1);
91 for (i
=0; i
<nStationary
; i
++) {
92 func(&model_type
, sizeof(int), 1);
98 pCurSphereModel
= new cPhysSphereModel(func
);
99 AddToStationary(pCurSphereModel
);
104 pCurBSPModel
= new cPhysBSPModel(func
);
105 AddToStationary(pCurBSPModel
);
110 pCurOBBModel
= new cPhysOBBModel(func
);
111 AddToStationary(pCurOBBModel
);
116 Error(1, "Invalid PhysModel type: %d\n", model_type
);
123 func(&nInactive
, sizeof(int), 1);
124 for (i
=0; i
<nInactive
; i
++) {
125 func(&model_type
, sizeof(int), 1);
126 switch (model_type
) {
131 pCurSphereModel
= new cPhysSphereModel(func
);
132 AddToInactive(pCurSphereModel
);
137 pCurBSPModel
= new cPhysBSPModel(func
);
138 AddToInactive(pCurBSPModel
);
143 pCurOBBModel
= new cPhysOBBModel(func
);
144 AddToInactive(pCurOBBModel
);
149 Error(1, "Invalid PhysModel type: %d\n", model_type
);
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);
165 m_deferredVelocityList
.SetSize(0);
169 void cPhysModels::Write(PhysReadWrite func
, eObjPartition part
)
171 cPhysModel
*pCurModel
;
176 AutoAppIPtr_(ObjectSystem
,pObjSys
);
180 // count the number of moving models we're actually saving
182 for (pCurModel
= GetFirstMoving(); pCurModel
!= NULL
; pCurModel
= GetNextMoving(pCurModel
))
184 if (pObjSys
->IsObjSavePartition(pCurModel
->GetObjID(),part
))
189 func(&num_models
, sizeof(int), 1);
190 for (pCurModel
= GetFirstMoving(); pCurModel
!= NULL
; pCurModel
= GetNextMoving(pCurModel
))
192 if (!pObjSys
->IsObjSavePartition(pCurModel
->GetObjID(),part
))
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
);
206 // count the number of stationary models we're actually saving
208 for (pCurModel
= GetFirstStationary(); pCurModel
!= NULL
; pCurModel
= GetNextStationary(pCurModel
))
210 if (pObjSys
->IsObjSavePartition(pCurModel
->GetObjID(),part
))
214 func(&num_models
, sizeof(int), 1);
215 for (pCurModel
= GetFirstStationary(); pCurModel
!= NULL
; pCurModel
= GetNextStationary(pCurModel
))
217 if (!pObjSys
->IsObjSavePartition(pCurModel
->GetObjID(),part
))
220 model_type
= (int)pCurModel
->GetType(0);
221 func(&model_type
, sizeof(int), 1);
222 pCurModel
->Write(func
);
230 for (pCurModel
= GetFirstInactive(); pCurModel
!= NULL
; pCurModel
= GetNextInactive(pCurModel
))
232 if (pObjSys
->IsObjSavePartition(pCurModel
->GetObjID(),part
))
236 func(&num_models
, sizeof(int), 1);
238 for (pCurModel
= GetFirstInactive(); pCurModel
!= NULL
; pCurModel
= GetNextInactive(pCurModel
))
240 if (!pObjSys
->IsObjSavePartition(pCurModel
->GetObjID(),part
))
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
)
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
);
269 m_inactiveList
.Remove(pModel
);
270 m_inactiveTable
.Remove(pModel
);
274 ///////////////////////////////////////
276 void cPhysModels::DestroyAllInList(cPhysModelList
* pList
)
279 cPhysModel
* pNextModel
;
281 pModel
= pList
->GetFirst();
286 // if (pModel->IsHigh())
287 g_pHighModelProperty
->Delete(pModel
->GetObjID());
289 g_pLowModelProperty
->Delete(pModel
->GetObjID());
292 pNextModel
= pModel
->GetNext();
293 pList
->Remove(pModel
);
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
)
333 if (!pModel
->IsActive())
334 Warning(("cPhysModels::Deactivate: model is not currently active\n"));
336 if (m_pFirstStationary
== pModel
)
337 m_pFirstStationary
= m_pFirstStationary
->GetNext();
338 m_activeList
.Remove(pModel
);
339 m_activeTable
.Remove(pModel
);
341 AddToInactive(pModel
);
344 ///////////////////////////////////////
346 void cPhysModels::ActivateToMoving(cPhysModel
* pModel
)
349 if (pModel
->IsActive())
350 Warning(("cPhysModels::ActivateToMoving: model is already active\n"));
352 m_inactiveList
.Remove(pModel
);
353 m_inactiveTable
.Remove(pModel
);
358 ///////////////////////////////////////
360 void cPhysModels::StopMoving(cPhysModel
* pModel
)
363 if (!(pModel
->IsActive()))
364 Warning(("cPhysModels::StopMoving: model is not currently active\n"));
366 m_activeList
.Remove(pModel
);
367 m_activeTable
.Remove(pModel
);
369 AddToStationary(pModel
);
372 ///////////////////////////////////////
374 void cPhysModels::StartMoving(cPhysModel
* pModel
)
377 if (!(pModel
->IsActive()))
378 Warning(("cPhysModels::StartMoving: model is not currently active\n"));
380 if (m_pFirstStationary
== pModel
)
381 m_pFirstStationary
= m_pFirstStationary
->GetNext();
382 m_activeList
.Remove(pModel
);
383 m_activeTable
.Remove(pModel
);
388 ///////////////////////////////////////////////////////////////////////////////
390 void cPhysModels::AddDeferredVelocity(ObjID objID
, const mxs_vector
&velocity
)
392 sDeferredVelocity defer
;
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
;
409 defer
.submod
= subModId
;
410 defer
.velocity
= velocity
;
412 LGALLOC_AUTO_CREDIT();
413 m_deferredVelocityList
.Append(defer
);
416 ////////////////////////////////////////
418 void cPhysModels::ApplyDeferredVelocities()
423 for (int i
=0; i
<m_deferredVelocityList
.Size(); i
++)
425 pModel
= g_PhysModels
.Get(m_deferredVelocityList
[i
].objID
);
429 Warning(("ApplyDeferredVelocities: %s has no physics model\n", ObjWarnName(m_deferredVelocityList
[i
].objID
)));
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 ///////////////////////////////////////////////////////////////////////////////
447 void cPhysModels::SpewStats()
453 // Sum sizes of main structures
454 long contact_size
= 0;
455 long external_size
= 0;
456 long internal_size
= 0;
459 int sphere_count
= 0;
463 pModel
= m_activeList
.GetFirst();
466 switch (pModel
->GetType(0))
473 external_size
+= sizeof(cPhysSphereModel
);
474 internal_size
+= ((cPhysSphereModel
*)pModel
)->InternalSize();
480 external_size
+= sizeof(cPhysOBBModel
);
481 internal_size
+= ((cPhysOBBModel
*)pModel
)->InternalSize();
487 pModel
= pModel
->GetNext();
490 pModel
= m_inactiveList
.GetFirst();
493 switch (pModel
->GetType(0))
500 external_size
+= sizeof(cPhysSphereModel
);
501 internal_size
+= ((cPhysSphereModel
*)pModel
)->InternalSize();
507 external_size
+= sizeof(cPhysOBBModel
);
508 internal_size
+= ((cPhysOBBModel
*)pModel
)->InternalSize();
514 pModel
= pModel
->GetNext();
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
);
535 m_inactiveList
.Remove(pModel
);
540 ///////////////////////////////////////////////////////////////////////////////