phys.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/phys.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 2/21/02 4:01p $*
  29. * *
  30. * $Revision:: 79 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "phys.h"
  36. #include "colmathaabox.h"
  37. #include "rendobj.h"
  38. #include "rinfo.h"
  39. #include "assetmgr.h"
  40. #include "ww3d.h"
  41. #include "wwdebug.h"
  42. #include "pscene.h"
  43. #include "cullsys.h"
  44. #include "chunkio.h"
  45. #include "saveload.h"
  46. #include "persistfactory.h"
  47. #include "physcoltest.h"
  48. #include "lightenvironment.h"
  49. #include "umbrasupport.h"
  50. #if (UMBRASUPPORT)
  51. #include <umbra.hpp>
  52. #endif
  53. #include "dx8wrapper.h"
  54. #include "dx8vertexbuffer.h"
  55. #include "dx8indexbuffer.h"
  56. const float DEBUG_RENDER_DIST2 = (50.0f*50.0f);
  57. const float SUN_CHECK_DISTANCE = 50.0f; //If a ray this long doesn't intersect, you can see the sun...
  58. /*
  59. ** create_render_obj_from_filename
  60. */
  61. RenderObjClass * create_render_obj_from_filename( const char * filename )
  62. {
  63. StringClass render_obj_name(filename,true);
  64. if ( ::strchr( filename, '\\' ) != 0 ) {
  65. render_obj_name = ::strrchr( filename, '\\' ) + 1;
  66. }
  67. render_obj_name.Erase( render_obj_name.Get_Length() - 4, 4 );
  68. RenderObjClass *model = WW3DAssetManager::Get_Instance()->Create_Render_Obj( render_obj_name );
  69. if ( model == NULL ) {
  70. WWDEBUG_SAY(("Failed to create %s from %s\n", (const char *)render_obj_name, filename));
  71. }
  72. return model;
  73. }
  74. /***********************************************************************************************
  75. **
  76. ** PhysClass Implementation
  77. **
  78. ***********************************************************************************************/
  79. /*
  80. ** Chunk ID's used by PhysClass
  81. */
  82. enum
  83. {
  84. PHYS_CHUNK_VARIABLES = 0x00660055,
  85. PHYS_CHUNK_MODEL,
  86. PHYS_VARIABLE_CULLABLE_PTR = 0x00,
  87. PHYS_VARIABLE_WIDGETUSER_PTR,
  88. PHYS_VARIABLE_EDITABLE_PTR,
  89. PHYS_VARIABLE_FLAGS,
  90. PHYS_VARIABLE_NAME,
  91. PHYS_VARIABLE_OBSERVER,
  92. PHYS_VARIABLE_DEFID,
  93. PHYS_VARIABLE_INSTANCEID,
  94. };
  95. PhysClass::PhysClass(void) :
  96. Flags(DEFAULT_FLAGS),
  97. Model(NULL),
  98. Observer(NULL),
  99. Definition(NULL),
  100. InstanceID(0),
  101. VisObjectID(0),
  102. LastVisibleFrame(0), // JANI TEMP TEST
  103. SunStatusLastUpdated(0),
  104. StaticLightingCache(NULL)
  105. #if (UMBRASUPPORT)
  106. ,UmbraObject(NULL)
  107. #endif
  108. {
  109. #if (UMBRASUPPORT)
  110. UmbraObject = new Umbra::Object(UmbraSupport::Peek_Dummy_Sphere());
  111. UmbraObject->setUserPointer(this);
  112. UmbraSupport::Install_Umbra_Object(this);
  113. #endif
  114. }
  115. PhysClass::~PhysClass(void)
  116. {
  117. if (Model) {
  118. Model->Release_Ref();
  119. Model = NULL;
  120. }
  121. if (StaticLightingCache) {
  122. delete StaticLightingCache;
  123. }
  124. #if (UMBRASUPPORT)
  125. if (UmbraObject) {
  126. UmbraSupport::Remove_Umbra_Object(this);
  127. UmbraObject->release();
  128. UmbraObject = NULL;
  129. }
  130. #endif
  131. }
  132. void PhysClass::Init(const PhysDefClass & def)
  133. {
  134. Definition = &def;
  135. Flags = DEFAULT_FLAGS;
  136. if (!def.ModelName.Is_Empty()) {
  137. RenderObjClass * model = NULL;
  138. if (::strchr(def.ModelName, '.') != NULL) {
  139. model = ::create_render_obj_from_filename(def.ModelName);
  140. } else {
  141. model = WW3DAssetManager::Get_Instance()->Create_Render_Obj(def.ModelName);
  142. }
  143. if ( model == NULL ) {
  144. WWDEBUG_SAY(( "*** FATAL ERROR : Failed to create model %s\n", def.ModelName ));
  145. }
  146. Set_Model(model);
  147. REF_PTR_RELEASE(model);
  148. }
  149. }
  150. void PhysClass::Set_Model(RenderObjClass * model)
  151. {
  152. PhysicsSceneClass * the_scene = PhysicsSceneClass::Get_Instance();
  153. bool in_scene = the_scene->Contains(this);
  154. if (Model) {
  155. // If we had an old model, copy the transform
  156. if ( model ) {
  157. model->Set_Transform( Model->Get_Transform() );
  158. }
  159. if (in_scene) Model->Notify_Removed(the_scene);
  160. Model->Release_Ref();
  161. }
  162. Model = model;
  163. if (Model) {
  164. Model->Add_Ref();
  165. if (in_scene) Model->Notify_Added(the_scene);
  166. }
  167. if ((Definition != NULL) && (Definition->IsPreLit)) {
  168. Enable_Is_Pre_Lit(true);
  169. }
  170. Invalidate_Static_Lighting_Cache ();
  171. }
  172. void PhysClass::Set_Model_By_Name(const char * model_type_name)
  173. {
  174. RenderObjClass * model = WW3DAssetManager::Get_Instance()->Create_Render_Obj(model_type_name);
  175. if ( model == NULL ) {
  176. WWDEBUG_SAY(( "%s failed to load\n", model_type_name ));
  177. }
  178. WWASSERT(model); // As above, PhysClasses cannot survive without a model...
  179. Set_Model(model);
  180. if (model) {
  181. model->Release_Ref();
  182. }
  183. }
  184. RenderObjClass * PhysClass::Get_Model(void)
  185. {
  186. if (Model) Model->Add_Ref();
  187. return Model;
  188. }
  189. void PhysClass::Set_Name(const char * name)
  190. {
  191. Name=name;
  192. }
  193. const char * PhysClass::Get_Name(void)
  194. {
  195. return Name;
  196. }
  197. void PhysClass::Get_Shadow_Blob_Box(AABoxClass * set_obj_space_box)
  198. {
  199. WWASSERT(set_obj_space_box != NULL);
  200. if (set_obj_space_box != NULL) {
  201. Model->Get_Obj_Space_Bounding_Box(*set_obj_space_box);
  202. set_obj_space_box->Extent *= 0.75f;
  203. }
  204. }
  205. void PhysClass::Render(RenderInfoClass & rinfo)
  206. {
  207. Push_Effects(rinfo);
  208. if (Model) {
  209. Model->Render(rinfo);
  210. }
  211. Pop_Effects(rinfo);
  212. }
  213. void PhysClass::Vis_Render(SpecialRenderInfoClass & rinfo)
  214. {
  215. if (Model) {
  216. Model->Special_Render(rinfo);
  217. }
  218. }
  219. void PhysClass::Invalidate_Static_Lighting_Cache(void)
  220. {
  221. Set_Flag(STATIC_LIGHTING_DIRTY,true);
  222. }
  223. LightEnvironmentClass * PhysClass::Get_Static_Lighting_Environment(void)
  224. {
  225. if (Is_Pre_Lit()) {
  226. /*
  227. ** This object doesn't need a lighting cache, make sure it doesn't have one
  228. */
  229. if (StaticLightingCache != NULL) {
  230. WWDEBUG_SAY(("Pre-Lit object %s has a lighting cache!\r\n",Model->Get_Name()));
  231. delete StaticLightingCache;
  232. StaticLightingCache = NULL;
  233. }
  234. } else if (Get_Flag(STATIC_LIGHTING_DIRTY)) {
  235. /*
  236. ** First, ensure that we have an allocated lighting cache
  237. */
  238. if (StaticLightingCache == NULL) {
  239. StaticLightingCache = new LightEnvironmentClass;
  240. }
  241. /*
  242. ** Next, update our sunlight status
  243. */
  244. Update_Sun_Status();
  245. /*
  246. ** Finally, ask the physics scene to re-compute our lighting cache
  247. */
  248. PhysicsSceneClass::Get_Instance()->Compute_Static_Lighting( StaticLightingCache,
  249. Model->Get_Bounding_Sphere().Center,
  250. Get_Flag(IS_IN_THE_SUN),
  251. Get_Vis_Object_ID() );
  252. Set_Flag(STATIC_LIGHTING_DIRTY,false);
  253. }
  254. /*
  255. ** Return our lighting cache to the caller
  256. */
  257. return StaticLightingCache;
  258. }
  259. void PhysClass::Update_Sun_Status(void)
  260. {
  261. // Update sun status only four times per second
  262. unsigned current_time=WW3D::Get_Sync_Time();
  263. if ((current_time-SunStatusLastUpdated)<250) return;
  264. SunStatusLastUpdated=current_time;
  265. PhysicsSceneClass * scene = PhysicsSceneClass::Get_Instance();
  266. Vector3 sunlight;
  267. scene->Get_Sun_Light_Vector(&sunlight);
  268. Vector3 center = Model->Get_Bounding_Sphere().Center;
  269. #pragma message ("(gth) Need a collision group for sun-rays")
  270. CastResultStruct sunresult;
  271. LineSegClass sunray(center,center - sunlight * SUN_CHECK_DISTANCE);
  272. PhysRayCollisionTestClass sunraytest(sunray,&sunresult,0,COLLISION_TYPE_PROJECTILE);
  273. sunraytest.CheckStaticObjs = true;
  274. sunraytest.CheckDynamicObjs = false;
  275. Inc_Ignore_Counter();
  276. scene->Cast_Ray(sunraytest);
  277. // if the ray hits a static object which is casting a projected shadow, ignore that object
  278. // and check again.
  279. if ( (sunresult.Fraction < 1.0f) &&
  280. (sunraytest.CollidedPhysObj != NULL) )
  281. {
  282. PhysClass * obj = sunraytest.CollidedPhysObj;
  283. if (obj->Is_Casting_Shadow()) {
  284. obj->Inc_Ignore_Counter();
  285. sunresult.Reset();
  286. scene->Cast_Ray(sunraytest);
  287. obj->Dec_Ignore_Counter();
  288. }
  289. }
  290. Dec_Ignore_Counter();
  291. Enable_Is_In_The_Sun(sunresult.Fraction == 1.0f);
  292. }
  293. void PhysClass::Push_Effects(RenderInfoClass & rinfo)
  294. {
  295. if (!MaterialEffectsOnMe.Is_Empty()) {
  296. RefMaterialEffectListIterator iterator(&MaterialEffectsOnMe);
  297. for ( ; !iterator.Is_Done() ; iterator.Next()) {
  298. iterator.Peek_Obj()->Render_Push(rinfo,this);
  299. }
  300. }
  301. #if 0
  302. if (!ProjectionsOnMe.Is_Empty()) {
  303. ShaderClass shader = ShaderClass::_PresetOpaqueShader;
  304. VertexMaterialClass * vmtl = VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_NODIFFUSE);
  305. DX8Wrapper::Set_Shader(shader);
  306. DX8Wrapper::Set_Material(vmtl);
  307. Matrix4 view,proj;
  308. Matrix4 identity(true);
  309. DX8Wrapper::Get_Transform(D3DTS_VIEW,view);
  310. DX8Wrapper::Get_Transform(D3DTS_PROJECTION,proj);
  311. DX8Wrapper::Set_Transform(D3DTS_WORLD,identity);
  312. DX8Wrapper::Set_Transform(D3DTS_VIEW,identity);
  313. DX8Wrapper::Set_Transform(D3DTS_PROJECTION,identity);
  314. TexProjListIterator iterator(&ProjectionsOnMe);
  315. for ( ; !iterator.Is_Done() ; iterator.Next()) {
  316. TextureClass * tex = iterator.Peek_Obj()->Peek_Material_Pass()->Peek_Texture(0);
  317. if (tex != NULL) {
  318. DX8Wrapper::Set_Texture(0,tex);
  319. DynamicVBAccessClass vbaccess(BUFFER_TYPE_DYNAMIC_DX8,4);
  320. {
  321. DynamicVBAccessClass::WriteLockClass lock(&vbaccess);
  322. VertexFormatXYZNDUV2 * verts = lock.Get_Formatted_Vertex_Array();
  323. verts[0].x = -1.0f;
  324. verts[0].y = 0.8f;
  325. verts[0].z = 0.0;
  326. verts[0].u1 = 0.0f;
  327. verts[0].v1 = 0.0f;
  328. verts[0].diffuse = 0xFFFFFFFF;
  329. verts[1].x = -1.0f;
  330. verts[1].y = 0.3f;
  331. verts[1].z = 0.0;
  332. verts[1].u1 = 0.0f;
  333. verts[1].v1 = 1.0f;
  334. verts[1].diffuse = 0xFFFFFFFF;
  335. verts[2].x = -0.5f;
  336. verts[2].y = 0.3f;
  337. verts[2].z = 0.0;
  338. verts[2].u1 = 1.0f;
  339. verts[2].v1 = 1.0f;
  340. verts[2].diffuse = 0xFFFFFFFF;
  341. verts[3].x = -0.5f;
  342. verts[3].y = 0.8f;
  343. verts[3].z = 0.0;
  344. verts[3].u1 = 1.0f;
  345. verts[3].v1 = 0.0f;
  346. verts[3].diffuse = 0xFFFFFFFF;
  347. }
  348. DynamicIBAccessClass ibaccess(BUFFER_TYPE_DYNAMIC_DX8,2*3);
  349. {
  350. DynamicIBAccessClass::WriteLockClass lock(&ibaccess);
  351. unsigned short * indices = lock.Get_Index_Array();
  352. indices[0] = 0;
  353. indices[1] = 1;
  354. indices[2] = 2;
  355. indices[3] = 0;
  356. indices[4] = 2;
  357. indices[5] = 3;
  358. }
  359. DX8Wrapper::Set_Vertex_Buffer(vbaccess);
  360. DX8Wrapper::Set_Index_Buffer(ibaccess,0);
  361. DX8Wrapper::Draw_Triangles(0,2,0,4);
  362. }
  363. }
  364. DX8Wrapper::Set_Transform(D3DTS_VIEW,view);
  365. DX8Wrapper::Set_Transform(D3DTS_PROJECTION,proj);
  366. REF_PTR_RELEASE(vmtl);
  367. }
  368. #endif
  369. }
  370. void PhysClass::Pop_Effects(RenderInfoClass & rinfo)
  371. {
  372. if (!MaterialEffectsOnMe.Is_Empty()) {
  373. RefMaterialEffectListIterator iterator(&MaterialEffectsOnMe);
  374. while (!iterator.Is_Done()) {
  375. MaterialEffectClass * effect = iterator.Peek_Obj();
  376. effect->Render_Pop(rinfo);
  377. if (effect->Is_Auto_Remove_Enabled()) {
  378. iterator.Remove_Current_Object();
  379. } else {
  380. iterator.Next();
  381. }
  382. }
  383. }
  384. }
  385. bool PhysClass::Save (ChunkSaveClass &csave)
  386. {
  387. CullableClass * cullable_ptr = (CullableClass *)this;
  388. WidgetUserClass * widgetuser_ptr = (WidgetUserClass *)this;
  389. EditableClass * editable_ptr = (EditableClass *)this;
  390. csave.Begin_Chunk(PHYS_CHUNK_VARIABLES);
  391. // (gth) not saving observer pointers any more!
  392. WRITE_MICRO_CHUNK(csave,PHYS_VARIABLE_CULLABLE_PTR,cullable_ptr);
  393. WRITE_MICRO_CHUNK(csave,PHYS_VARIABLE_WIDGETUSER_PTR,widgetuser_ptr);
  394. WRITE_MICRO_CHUNK(csave,PHYS_VARIABLE_EDITABLE_PTR,editable_ptr);
  395. WRITE_MICRO_CHUNK(csave,PHYS_VARIABLE_FLAGS,Flags);
  396. WRITE_MICRO_CHUNK(csave,PHYS_VARIABLE_INSTANCEID,InstanceID);
  397. if (Name.Get_Length() > 0) {
  398. csave.Begin_Micro_Chunk(PHYS_VARIABLE_NAME);
  399. WWASSERT(Name.Get_Length()+1 < 255);
  400. csave.Write(Name,Name.Get_Length() + 1);
  401. csave.End_Micro_Chunk();
  402. }
  403. if (Definition != NULL) {
  404. int defid = Definition->Get_ID();
  405. WRITE_MICRO_CHUNK(csave,PHYS_VARIABLE_DEFID,defid);
  406. }
  407. csave.End_Chunk();
  408. csave.Begin_Chunk(PHYS_CHUNK_MODEL);
  409. csave.Begin_Chunk(Model->Get_Factory().Chunk_ID());
  410. Model->Get_Factory().Save(csave,Model);
  411. csave.End_Chunk();
  412. csave.End_Chunk();
  413. return true;
  414. }
  415. bool PhysClass::Load (ChunkLoadClass &cload)
  416. {
  417. PersistFactoryClass * factory = NULL;
  418. CullableClass * cullable_ptr = NULL;
  419. WidgetUserClass * widgetuser_ptr = NULL;
  420. EditableClass * editable_ptr = NULL;
  421. int defid = -1;
  422. char tmpstring[256];
  423. tmpstring[0] = 0;
  424. RenderObjClass * render_model = NULL;
  425. while (cload.Open_Chunk()) {
  426. switch(cload.Cur_Chunk_ID())
  427. {
  428. case PHYS_CHUNK_VARIABLES:
  429. while (cload.Open_Micro_Chunk()) {
  430. switch(cload.Cur_Micro_Chunk_ID()) {
  431. // (gth) not saving observer pointers any more!
  432. READ_MICRO_CHUNK(cload,PHYS_VARIABLE_CULLABLE_PTR,cullable_ptr);
  433. READ_MICRO_CHUNK(cload,PHYS_VARIABLE_WIDGETUSER_PTR,widgetuser_ptr);
  434. READ_MICRO_CHUNK(cload,PHYS_VARIABLE_EDITABLE_PTR,editable_ptr);
  435. READ_MICRO_CHUNK(cload,PHYS_VARIABLE_FLAGS,Flags);
  436. READ_MICRO_CHUNK(cload,PHYS_VARIABLE_DEFID,defid);
  437. READ_MICRO_CHUNK(cload,PHYS_VARIABLE_INSTANCEID,InstanceID);
  438. case PHYS_VARIABLE_NAME:
  439. cload.Read(tmpstring,cload.Cur_Micro_Chunk_Length());
  440. break;
  441. }
  442. cload.Close_Micro_Chunk();
  443. }
  444. break;
  445. case PHYS_CHUNK_MODEL:
  446. cload.Open_Chunk();
  447. factory = SaveLoadSystemClass::Find_Persist_Factory(cload.Cur_Chunk_ID());
  448. WWASSERT(factory != NULL);
  449. if (factory != NULL) {
  450. render_model = (RenderObjClass *)factory->Load(cload);
  451. SET_REF_OWNER(render_model);
  452. }
  453. cload.Close_Chunk();
  454. break;
  455. default:
  456. WWDEBUG_SAY(("Unhandled Chunk: 0x%X File: %s Line: %d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  457. break;
  458. }
  459. if (cullable_ptr != NULL) {
  460. SaveLoadSystemClass::Register_Pointer(cullable_ptr,(CullableClass *)this);
  461. }
  462. cload.Close_Chunk();
  463. }
  464. /*
  465. ** Set our name
  466. */
  467. if (strlen(tmpstring) > 0) {
  468. Set_Name(tmpstring);
  469. }
  470. /*
  471. ** Set our definition pointer
  472. */
  473. if (defid != -1) {
  474. Definition = (PhysDefClass *)_TheDefinitionMgr.Find_Definition(defid);
  475. } else {
  476. Definition = NULL;
  477. }
  478. /*
  479. ** Only install the model after our definition is installed
  480. */
  481. Set_Model(render_model);
  482. REF_PTR_RELEASE(render_model);
  483. /*
  484. ** Ask that our Observer pointer is re-mapped
  485. */
  486. if (Observer != NULL) {
  487. REQUEST_POINTER_REMAP((void**)&Observer);
  488. }
  489. /*
  490. ** Register all of the multiple-inheritance versions of our this pointer
  491. */
  492. if (cullable_ptr != NULL) {
  493. SaveLoadSystemClass::Register_Pointer(cullable_ptr,(CullableClass *)this);
  494. }
  495. if (widgetuser_ptr != NULL) {
  496. SaveLoadSystemClass::Register_Pointer(widgetuser_ptr,(WidgetUserClass *)this);
  497. }
  498. if (editable_ptr != NULL) {
  499. SaveLoadSystemClass::Register_Pointer(editable_ptr,(EditableClass *)this);
  500. }
  501. /*
  502. ** Mark our static lighting cache dirty
  503. */
  504. Invalidate_Static_Lighting_Cache();
  505. /*
  506. ** Update our Umbra object
  507. */
  508. #if (UMBRASUPPORT)
  509. UmbraSupport::Update_Umbra_Object(this);
  510. #endif
  511. return true;
  512. }
  513. #ifdef WWDEBUG
  514. void PhysClass::Add_Debug_Point(const Vector3 & p,const Vector3 & color)
  515. {
  516. if (Is_Debug_Display_Enabled()) {
  517. PhysicsSceneClass::Get_Instance()->Add_Debug_Point(p,color);
  518. }
  519. }
  520. #endif
  521. #ifdef WWDEBUG
  522. void PhysClass::Add_Debug_Vector(const Vector3 & p,const Vector3 & v,const Vector3 & color)
  523. {
  524. if (Is_Debug_Display_Enabled() && (v.Length2() > 0.0f)) {
  525. PhysicsSceneClass::Get_Instance()->Add_Debug_Vector(p,v,color);
  526. }
  527. }
  528. #endif
  529. #ifdef WWDEBUG
  530. void PhysClass::Add_Debug_AABox(const AABoxClass & box,const Vector3 & color,float opacity)
  531. {
  532. if (Is_Debug_Display_Enabled()) {
  533. PhysicsSceneClass::Get_Instance()->Add_Debug_AABox(box,color,opacity);
  534. }
  535. }
  536. #endif
  537. #ifdef WWDEBUG
  538. void PhysClass::Add_Debug_OBBox(const OBBoxClass & box,const Vector3 & color,float opacity)
  539. {
  540. if (Is_Debug_Display_Enabled()) {
  541. PhysicsSceneClass::Get_Instance()->Add_Debug_OBBox(box,color,opacity);
  542. }
  543. }
  544. #endif
  545. #ifdef WWDEBUG
  546. void PhysClass::Add_Debug_Axes(const Matrix3D & transform,const Vector3 & color)
  547. {
  548. if (Is_Debug_Display_Enabled()) {
  549. PhysicsSceneClass::Get_Instance()->Add_Debug_Axes(transform,color);
  550. }
  551. }
  552. #endif
  553. bool PhysClass::Is_Debug_Display_Enabled(void) const
  554. {
  555. PhysicsSceneClass * the_scene = PhysicsSceneClass::Get_Instance();
  556. Vector3 pos;
  557. Get_Position(&pos);
  558. float dist = (pos - the_scene->Get_Last_Camera_Position()).Length2();
  559. if (dist > DEBUG_RENDER_DIST2) {
  560. return false;
  561. }
  562. if (the_scene) {
  563. return (((Flags & DEBUGDISPLAY) == DEBUGDISPLAY) || the_scene->Is_Debug_Display_Enabled());
  564. } else {
  565. return ((Flags & DEBUGDISPLAY) == DEBUGDISPLAY);
  566. }
  567. }
  568. bool PhysClass::Expire(void)
  569. {
  570. ExpirationReactionType result = EXPIRATION_APPROVED;
  571. if (Observer != NULL) {
  572. result = Observer->Object_Expired(this);
  573. }
  574. if (result == EXPIRATION_APPROVED) {
  575. PhysicsSceneClass::Get_Instance()->Delayed_Remove_Object(this);
  576. return true;
  577. } else {
  578. return false;
  579. }
  580. }
  581. //
  582. // TSS added this... not efficient to use if you are also
  583. // setting position
  584. //
  585. void PhysClass::Set_Facing(float new_facing)
  586. {
  587. Vector3 pos;
  588. Get_Position(&pos);
  589. Matrix3D tm(1);
  590. tm.Translate(pos);
  591. tm.Rotate_Z(new_facing);
  592. Set_Transform(tm);
  593. }
  594. bool PhysClass::Do_Any_Effects_Suppress_Shadows(void)
  595. {
  596. RefMaterialEffectListIterator iterator(&MaterialEffectsOnMe);
  597. for ( ; !iterator.Is_Done() ; iterator.Next()) {
  598. if (iterator.Peek_Obj()->Are_Shadows_Suppressed()) {
  599. return true;
  600. }
  601. }
  602. return false;
  603. }
  604. /***********************************************************************************************
  605. **
  606. ** PhysDefClass Implementation
  607. ** This holds the description for a PhysClass. Since PhysClass's aren't concrete, this
  608. ** definition class isn't either and thus has no persist factory (required by PersistClass)
  609. ** or create method (required by DefinitionClass)
  610. **
  611. ***********************************************************************************************/
  612. enum
  613. {
  614. PHYSDEF_CHUNK_DEFINITION = 0x055ffe07, // parent class data.
  615. PHYSDEF_CHUNK_VARIABLES, // simple variables
  616. PHYSDEF_VARIABLE_FLAGS = 0x00,
  617. PHYSDEF_VARIABLE_MODELNAME,
  618. PHYSDEF_VARIABLE_ISPRELIT,
  619. };
  620. PhysDefClass::PhysDefClass(void) :
  621. ModelName ("NULL"),
  622. IsPreLit(false)
  623. {
  624. FILENAME_PARAM(PhysDefClass,ModelName, "Westwood 3D Files", ".w3d");
  625. }
  626. bool PhysDefClass::Is_Valid_Config (StringClass &message)
  627. {
  628. bool retval = true;
  629. if (ModelName.Is_Empty ()) {
  630. message += "ModelName is invalid!\n";
  631. retval = false;
  632. }
  633. return retval;
  634. }
  635. bool PhysDefClass::Save(ChunkSaveClass &csave)
  636. {
  637. csave.Begin_Chunk(PHYSDEF_CHUNK_DEFINITION);
  638. DefinitionClass::Save(csave);
  639. csave.End_Chunk();
  640. csave.Begin_Chunk(PHYSDEF_CHUNK_VARIABLES);
  641. WRITE_MICRO_CHUNK_WWSTRING(csave,PHYSDEF_VARIABLE_MODELNAME,ModelName);
  642. WRITE_MICRO_CHUNK(csave,PHYSDEF_VARIABLE_ISPRELIT,IsPreLit);
  643. csave.End_Chunk();
  644. return true;
  645. }
  646. bool PhysDefClass::Load(ChunkLoadClass &cload)
  647. {
  648. while (cload.Open_Chunk()) {
  649. switch(cload.Cur_Chunk_ID()) {
  650. case PHYSDEF_CHUNK_DEFINITION:
  651. DefinitionClass::Load(cload);
  652. break;
  653. case PHYSDEF_CHUNK_VARIABLES:
  654. WWASSERT(cload.Cur_Chunk_ID() == PHYSDEF_CHUNK_VARIABLES);
  655. while (cload.Open_Micro_Chunk()) {
  656. switch(cload.Cur_Micro_Chunk_ID()) {
  657. OBSOLETE_MICRO_CHUNK(PHYSDEF_VARIABLE_FLAGS);
  658. READ_MICRO_CHUNK_WWSTRING(cload,PHYSDEF_VARIABLE_MODELNAME,ModelName);
  659. READ_MICRO_CHUNK(cload,PHYSDEF_VARIABLE_ISPRELIT,IsPreLit);
  660. }
  661. cload.Close_Micro_Chunk();
  662. }
  663. break;
  664. }
  665. cload.Close_Chunk();
  666. }
  667. return true;
  668. }
  669. bool PhysDefClass::Is_Type(const char * type_name)
  670. {
  671. if (stricmp(type_name,PhysDefClass::Get_Type_Name()) == 0) {
  672. return true;
  673. } else {
  674. return false;
  675. }
  676. }