Utility.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464
  1. /*
  2. ** Copyright (C) 1996, 1997 Microsoft Corporation. All Rights Reserved.
  3. **
  4. ** File: utility.h
  5. **
  6. ** Author:
  7. **
  8. ** Description:
  9. ** Header file for the utility library. Basically a set of commonly
  10. ** used functions.
  11. **
  12. ** History:
  13. */
  14. #ifndef utl_h
  15. #define utl_h
  16. /*
  17. ** Disable some stupid warning messages that we really don't need and
  18. ** shouldn't be there (actually, set them to level 4 so I can still see
  19. ** them if I want to).
  20. */
  21. #define _exposed
  22. #include "CRC.h"
  23. class UTL;
  24. class List_utl;
  25. class Link_utl;
  26. class Lock_utl;
  27. template<class T, class Sink = NullFunc> class Slist_utl;
  28. template<class T, class Sink = NullFunc> class Slink_utl;
  29. template<class T> class Mlist_utl;
  30. template<class T> class Mlink_utl;
  31. struct FPOINT
  32. {
  33. float x;
  34. float y;
  35. };
  36. class Rotation;
  37. // These constants correspond to the maximum length of a file name or a
  38. // player name. They should correspond to the maximum lengths in the SQL
  39. // database (for Name and FileName custom data types). Longer names are
  40. // handled via truncation. DB versions do not include the NULL terminator
  41. const int c_cbFileNameDB = 12; // keep in sync with
  42. const int c_cbDescriptionDB = 200;
  43. const int c_cbNameDB = 24;
  44. const int c_cbLocAbrevDB = 8;
  45. const int c_cbFileName = c_cbFileNameDB + 1;
  46. const int c_cbDescription = c_cbDescriptionDB + 1;
  47. const int c_cbName = c_cbNameDB + 1;
  48. const int c_cbLocAbrev = c_cbLocAbrevDB + 1;
  49. const int c_cbCDKey = 32 + 1; // TODO: fill in the correct length
  50. const int c_cbPassportName = 256 + 1;
  51. class _exposed List_utl
  52. {
  53. public:
  54. /*
  55. ** Return the number of links in *this.
  56. */
  57. inline int n(void) const
  58. {
  59. return m_n;
  60. }
  61. protected:
  62. List_utl(void);
  63. inline ~List_utl(void)
  64. {
  65. }
  66. /*
  67. ** Set the first link of *this to f.
  68. */
  69. void first(Link_utl* f);
  70. /*
  71. ** Return the current first link in *this.
  72. */
  73. inline Link_utl* first(void) const
  74. {
  75. return m_first;
  76. }
  77. /*
  78. ** Set the last link of *this to l.
  79. */
  80. void last(Link_utl* l);
  81. /*
  82. ** Return the current last link in *this.
  83. */
  84. inline Link_utl* last(void) const
  85. {
  86. return m_last;
  87. }
  88. /*
  89. ** Return's the index'th element (index >= 0),
  90. ** or the list.n() + index'th element (index < 0).
  91. ** (note, list[-1] == list.last())
  92. */
  93. Link_utl* operator [] (int index) const;
  94. private:
  95. Link_utl* m_first;
  96. Link_utl* m_last;
  97. int m_n;
  98. friend class Link_utl;
  99. };
  100. class _exposed Link_utl
  101. {
  102. public:
  103. /*
  104. ** Remove *this from whatever list it is attached to & return true,
  105. ** do nothing & return false if not attached.
  106. */
  107. bool unlink(void);
  108. protected:
  109. Link_utl(void);
  110. ~Link_utl(void)
  111. {
  112. }
  113. /*
  114. ** Return the pointer to whatever list *this is attached to.
  115. */
  116. inline List_utl* list(void) const
  117. {
  118. return m_list;
  119. }
  120. /*
  121. ** Insert l immediately after *this & return true.
  122. ** Do nothing & return false if *this is not part of a list.
  123. */
  124. bool next(Link_utl* l);
  125. /*
  126. ** Return the next element in the list.
  127. */
  128. inline Link_utl* next(void) const
  129. {
  130. return m_next;
  131. }
  132. /*
  133. ** Insert l immediately before *this & return true.
  134. ** Do nothing & return false if *this is not part of a list.
  135. */
  136. bool txen(Link_utl* l);
  137. /*
  138. ** Return the previous element in the list.
  139. */
  140. inline Link_utl* txen(void) const
  141. {
  142. return m_txen;
  143. }
  144. protected:
  145. List_utl* m_list;
  146. Link_utl* m_next;
  147. Link_utl* m_txen;
  148. friend List_utl;
  149. };
  150. class _exposed Lock_utl
  151. {
  152. public:
  153. Lock_utl(void);
  154. ~Lock_utl(void);
  155. /*
  156. ** Lock or unlock the list. Lock/unlock pairs can be nested.
  157. ** We are technically lying about the const attribute but that
  158. ** seems fair since neither lock nor unlock actually modify the
  159. ** contents of the thing that is locked.
  160. */
  161. void lock(void) const;
  162. void unlock(void) const;
  163. private:
  164. HANDLE m_lockedS;
  165. DWORD m_locking_threadID;
  166. int m_locks;
  167. };
  168. /*
  169. ** Templated list of T, single thread safe.
  170. */
  171. template<class T, class Sink> class Slist_utl : public List_utl
  172. {
  173. protected:
  174. Sink sink;
  175. public:
  176. Slist_utl()
  177. {};
  178. Slist_utl(const Sink& _sink)
  179. : sink(_sink) {}
  180. inline ~Slist_utl(void)
  181. {
  182. purge();
  183. }
  184. /*
  185. ** Clear the list.
  186. ** If deleteF is true, all links are deleted.
  187. ** If deleteF is false, they are simply unlinked.
  188. **
  189. ** Note: when a list's destructor is called, purge(true) is called.
  190. */
  191. void purge(bool deleteF = true);
  192. /*
  193. ** Create a new Slink which contains a copy of t and
  194. ** make it the first element of the list. Returns false
  195. ** iff unable to allocate a new link.
  196. */
  197. bool first(const T& t);
  198. bool last(const T& t);
  199. /*
  200. ** These are equivalent to the List_utl versions.
  201. */
  202. inline void first(Slink_utl<T, Sink>* l)
  203. {
  204. List_utl::first(l);
  205. sink();
  206. }
  207. inline Slink_utl<T, Sink>* first(void) const
  208. {
  209. return (Slink_utl<T, Sink>*)List_utl::first();
  210. }
  211. inline void last(Slink_utl<T, Sink>* l)
  212. {
  213. List_utl::last(l);
  214. sink();
  215. }
  216. inline Slink_utl<T, Sink>* last(void) const
  217. {
  218. return (Slink_utl<T, Sink>*)List_utl::last();
  219. }
  220. inline Slink_utl<T, Sink>* find(const T& e) const
  221. {
  222. Slink_utl<T, Sink>* l;
  223. for (l = first(); ((l != NULL) && (l->data() != e)); l = l->next())
  224. {
  225. //Intentionally empty
  226. }
  227. return l;
  228. }
  229. inline Slink_utl<T, Sink>* operator [](int index) const
  230. {
  231. return (Slink_utl<T, Sink>*)List_utl::operator [](index);
  232. }
  233. friend class Slink_utl<T, Sink>;
  234. };
  235. /*
  236. ** Templated list element of T, single thread safe. Each element
  237. ** contains a copy of T, not a pointer to T.
  238. */
  239. template<class T, class Sink> class Slink_utl : public Link_utl
  240. {
  241. public:
  242. /*
  243. ** Use the default constructor for the data member.
  244. */
  245. inline Slink_utl(void)
  246. {
  247. }
  248. /*
  249. ** Use the copy constructor from t for the data member.
  250. */
  251. inline Slink_utl(const T& t)
  252. :
  253. m_data(t)
  254. {
  255. }
  256. inline ~Slink_utl(void)
  257. {
  258. if (list())
  259. unlink();
  260. }
  261. /*
  262. ** Return/set the data member of the link.
  263. */
  264. inline const T& data(void) const
  265. {
  266. return m_data;
  267. }
  268. inline T& data(void)
  269. {
  270. return m_data;
  271. }
  272. inline void data(const T& t)
  273. {
  274. m_data = t;
  275. list()->sink();
  276. }
  277. /*
  278. ** Create a new Slink which contains a copy of t,
  279. ** insert it after or before *this, and return true.
  280. ** Do nothing and return false if *this is not attached to a list.
  281. */
  282. bool next(const T& t);
  283. bool txen(const T& t);
  284. /*
  285. ** These are equivalent to the List_utl versions.
  286. */
  287. inline Slist_utl<T, Sink>* list(void) const
  288. {
  289. return (Slist_utl<T, Sink>*)Link_utl::list();
  290. }
  291. inline bool next(Slink_utl<T, Sink>* l)
  292. {
  293. return Link_utl::next(l);
  294. }
  295. inline Slink_utl<T, Sink>* next(void) const
  296. {
  297. return (Slink_utl<T, Sink>*)Link_utl::next();
  298. }
  299. inline bool txen(Slink_utl<T, Sink>* l)
  300. {
  301. return Link_utl::txen(l);
  302. }
  303. inline Slink_utl<T, Sink>* txen(void) const
  304. {
  305. return (Slink_utl<T, Sink>*)Link_utl::txen();
  306. }
  307. __forceinline bool unlink(void)
  308. {
  309. Slist_utl<T, Sink>* plist = list();
  310. bool result = Link_utl::unlink();
  311. plist->sink();
  312. return result;
  313. }
  314. private:
  315. T m_data;
  316. };
  317. /*
  318. ** Templated list of T, multi-thread safe (if locked/unlocked properly).
  319. */
  320. template<class T> class Mlist_utl : public List_utl, public Lock_utl
  321. {
  322. public:
  323. inline Mlist_utl(void)
  324. {
  325. }
  326. inline ~Mlist_utl(void)
  327. {
  328. purge();
  329. }
  330. /*
  331. ** Clear the list.
  332. */
  333. void purge(bool deleteF = true); //locked/unlocked
  334. /*
  335. ** Create a new Slink which contains a copy of t and
  336. ** make it the first element of the list. Returns false
  337. ** if unable to allocate a new link.
  338. */
  339. bool first(const T& t); //locked/unlocked
  340. bool last(const T& t); //locked/unlocked
  341. /*
  342. ** These are equivalent to the List_utl versions.
  343. */
  344. void first(Mlink_utl<T>* l); //locked/unlocked
  345. Mlink_utl<T>* first(void) const;
  346. void last(Mlink_utl<T>* l); //locked/unlocked
  347. Mlink_utl<T>* last(void) const;
  348. inline Mlink_utl<T>* find(const T& e) const
  349. {
  350. lock();
  351. Mlink_utl<T>* l;
  352. for (l = first(); ((l != NULL) && (l->data() != e)); l = l->next())
  353. {
  354. //Intentionally empty
  355. }
  356. unlock();
  357. return l;
  358. }
  359. Mlink_utl<T>* operator [](int) const;
  360. friend class Mlink_utl<T>;
  361. };
  362. /*
  363. ** Templated list element of T, multi-thread safe. Each element
  364. ** contains a copy of T, not a pointer to T.
  365. */
  366. template<class T> class Mlink_utl : public Link_utl
  367. {
  368. public:
  369. /*
  370. ** Use the default constructor for the data member.
  371. */
  372. inline Mlink_utl(void)
  373. {
  374. }
  375. /*
  376. ** Use the copy constructor from t for the data member.
  377. */
  378. inline Mlink_utl(const T& t)
  379. :
  380. m_data(t)
  381. {
  382. }
  383. inline ~Mlink_utl(void)
  384. {
  385. if (list())
  386. unlink();
  387. }
  388. /*
  389. ** Return the data member of the link.
  390. */
  391. inline const T& data(void) const
  392. {
  393. return m_data;
  394. }
  395. inline T& data(void)
  396. {
  397. return m_data;
  398. }
  399. inline void data(const T& t)
  400. {
  401. m_data = t;
  402. }
  403. /*
  404. ** Create a new Mlink which contains a copy of t,
  405. ** insert it after or before *this, and return true.
  406. ** Do nothing and return false if *this is not attached to a list.
  407. */
  408. bool next(const T& t);
  409. bool txen(const T& t);
  410. /*
  411. ** These are equivalent to the List_utl versions.
  412. */
  413. inline Mlist_utl<T>* list(void) const
  414. {
  415. return (Mlist_utl<T>*)Link_utl::list();
  416. }
  417. inline bool next(Mlink_utl<T>* l)
  418. {
  419. return Link_utl::next(l);
  420. }
  421. inline Mlink_utl<T>* next(void) const
  422. {
  423. return (Mlink_utl<T>*)Link_utl::next();
  424. }
  425. inline bool txen(Mlink_utl<T>* l)
  426. {
  427. return Link_utl::txen(l);
  428. }
  429. inline Mlink_utl<T>* txen(void) const
  430. {
  431. return (Mlink_utl<T>*)Link_utl::txen();
  432. }
  433. private:
  434. T m_data;
  435. };
  436. class Rotation
  437. {
  438. public:
  439. Rotation(void);
  440. Rotation(float x, float y, float z, float a)
  441. :
  442. m_axis(x, y, z),
  443. m_angle(a)
  444. {
  445. }
  446. Rotation(const Vector& xyz, float a)
  447. :
  448. m_axis(xyz),
  449. m_angle(a)
  450. {
  451. }
  452. Rotation(const Rotation&);
  453. void reset(void);
  454. void set(const Vector& axis,
  455. float angle);
  456. Rotation& operator = (const Rotation&);
  457. inline float x(void) const
  458. {
  459. return m_axis.x;
  460. }
  461. inline float y(void) const
  462. {
  463. return m_axis.y;
  464. }
  465. inline float z(void) const
  466. {
  467. return m_axis.z;
  468. }
  469. inline float angle(void) const
  470. {
  471. return m_angle;
  472. }
  473. inline const Vector& axis(void) const
  474. {
  475. return m_axis;
  476. }
  477. void axis(const Vector& v);
  478. void angle(float r);
  479. void x(float t);
  480. void y(float t);
  481. void z(float t);
  482. private:
  483. Vector m_axis;
  484. float m_angle;
  485. };
  486. const int c_cbFrameName = 20;
  487. class FrameDataUTL
  488. {
  489. public:
  490. char szName[c_cbFrameName];
  491. Vector position;
  492. Vector forward;
  493. friend bool operator!=(const FrameDataUTL& fd1, const FrameDataUTL& fd2)
  494. {
  495. return false;
  496. }
  497. };
  498. typedef Slist_utl<FrameDataUTL> FrameList;
  499. typedef Slink_utl<FrameDataUTL> FrameLink;
  500. const int c_nAxes = 3;
  501. const int c_maxHitTests = 100;
  502. const int c_minNodeSize = 5;
  503. const int c_minRootSize = 10;
  504. class Interval;
  505. class BoundingBox;
  506. class Endpoint;
  507. class HitTest;
  508. class KDnode;
  509. class KDroot;
  510. class CollisionEntry;
  511. class CollisionQueue;
  512. class Interval
  513. {
  514. public:
  515. float values[2]; //lo & hi endpoints.
  516. };
  517. class BoundingBox
  518. {
  519. public:
  520. Interval axes[c_nAxes];
  521. };
  522. class Endpoint
  523. {
  524. public:
  525. float value;
  526. HitTest* pHitTest;
  527. bool highF;
  528. //Bubble-sort based algorith: use when the list is mostly sorted
  529. static void shortSort(Endpoint** lo,
  530. Endpoint** hi);
  531. //Quick-sort based algorithm: the alternative to shortSort
  532. static void longSort(Endpoint** lo,
  533. Endpoint** hi);
  534. };
  535. class Transform44
  536. {
  537. public:
  538. inline Transform44(void)
  539. :
  540. m_position(Vector::GetZero()),
  541. m_orientation(Orientation::GetIdentity()),
  542. m_modifiedF(true)
  543. {
  544. }
  545. inline const Vector& GetPosition(void) const
  546. {
  547. return m_position;
  548. }
  549. inline void SetPosition(const Vector& xyz)
  550. {
  551. assert(xyz.Length() < 100000);
  552. m_position = xyz;
  553. m_modifiedF = true;
  554. }
  555. inline const Orientation& GetOrientation(void) const
  556. {
  557. return m_orientation;
  558. }
  559. inline void SetOrientation(const Orientation& o)
  560. {
  561. m_orientation = o;
  562. m_modifiedF = true;
  563. }
  564. inline const Matrix& GetMatrix(void)
  565. {
  566. if (m_modifiedF)
  567. {
  568. m_modifiedF = false;
  569. //m_matrix.SetTranslate(m_position);
  570. //m_matrix.SetOrientation(m_orientation);
  571. }
  572. return m_matrix;
  573. }
  574. private:
  575. Matrix m_matrix;
  576. Vector m_position;
  577. Orientation m_orientation;
  578. bool m_modifiedF;
  579. };
  580. typedef char HitTestShape;
  581. //These do not depend on orientation
  582. const HitTestShape c_htsPoint = -4;
  583. const HitTestShape c_htsSphere = -3;
  584. //And these do, but there is a "closed" form solution for whether a point is inside
  585. const HitTestShape c_htsEllipse = -2;
  586. const HitTestShape c_htsCone = -1;
  587. //but not for this ... the hts is actually the number of distinct
  588. //convex hulls within the hit test
  589. const HitTestShape c_htsConvexHullMin = 0;
  590. const HitTestShape c_htsConvexHullMax = 127;
  591. typedef void* HitTestID;
  592. HitTestID const c_htidStaticObject = (HitTestID)(0xffffffff);
  593. class MultiHullBase
  594. {
  595. public:
  596. MultiHullBase(const Vector& ellipseEquation,
  597. float originalRadius)
  598. :
  599. m_ellipseEquation(ellipseEquation),
  600. m_originalRadius(originalRadius)
  601. {
  602. }
  603. const Vector& GetFrameOffset(const char* pszFrameName) const
  604. {
  605. const FrameDataUTL* pfd = GetFrame(pszFrameName);
  606. return pfd ? pfd->position : Vector::GetZero();
  607. }
  608. const Vector& GetFrameForward(const char* pszFrameName) const
  609. {
  610. static const Vector z(0.0f, 0.0f, 1.0f);
  611. const FrameDataUTL* pfd = GetFrame(pszFrameName);
  612. return pfd ? pfd->forward : z;
  613. }
  614. const FrameDataUTL* GetFrame(const char* pszFrameName) const
  615. {
  616. for (FrameLink* pfl = m_frames.first();
  617. (pfl != NULL);
  618. pfl = pfl->next())
  619. {
  620. const FrameDataUTL& fd = pfl->data();
  621. if (strcmp(pszFrameName, fd.szName) == 0)
  622. {
  623. return &fd;
  624. }
  625. }
  626. return NULL;
  627. }
  628. const float GetOriginalRadius(void) const
  629. {
  630. return m_originalRadius;
  631. }
  632. const Vector& GetEllipseEquation(void) const
  633. {
  634. return m_ellipseEquation;
  635. }
  636. protected:
  637. FrameList m_frames;
  638. float m_originalRadius;
  639. Vector m_ellipseEquation;
  640. };
  641. class HitTest : public Transform44
  642. {
  643. public:
  644. static MultiHullBase* Load(const char* pszFileName);
  645. static HitTest* Create(const char* pszFileName,
  646. IObject* data,
  647. bool staticF,
  648. HitTestShape htsDefault = c_htsSphere);
  649. HitTest(IObject* data,
  650. float radius,
  651. bool staticF,
  652. HitTestShape shape)
  653. :
  654. m_cRefs(1),
  655. m_id(NULL),
  656. m_data(data),
  657. m_radius(radius),
  658. m_shape(shape),
  659. m_shapeTrue(shape),
  660. m_noHit(NULL),
  661. m_pvUseTrueShapeSelf(NULL),
  662. m_pvUseTrueShapeOther(NULL),
  663. m_deadF(true),
  664. m_deletedF(false),
  665. m_staticF(staticF),
  666. m_velocity(Vector::GetZero()),
  667. m_timeStart(0),
  668. m_timeStop(0),
  669. m_pkdrRoot(NULL)
  670. {
  671. assert (data);
  672. data->AddRef();
  673. m_endpoints[0][0].highF =
  674. m_endpoints[1][0].highF =
  675. m_endpoints[2][0].highF = false;
  676. m_endpoints[0][1].highF =
  677. m_endpoints[1][1].highF =
  678. m_endpoints[2][1].highF = true;
  679. m_endpoints[0][0].pHitTest = m_endpoints[0][1].pHitTest =
  680. m_endpoints[1][0].pHitTest = m_endpoints[1][1].pHitTest =
  681. m_endpoints[2][0].pHitTest = m_endpoints[2][1].pHitTest = this;
  682. //No addref on m_data ... this hit test is part of m_data
  683. }
  684. ~HitTest(void)
  685. {
  686. assert (m_data);
  687. m_data->Release();
  688. }
  689. ULONG __stdcall AddRef(void)
  690. {
  691. return ++m_cRefs;
  692. }
  693. ULONG __stdcall Release(void)
  694. {
  695. ULONG cRefs = --m_cRefs;
  696. if (cRefs == 0)
  697. delete this;
  698. return cRefs;
  699. }
  700. void SetStaticF(bool staticF)
  701. {
  702. m_staticF = staticF;
  703. }
  704. void SetBB(Time start, Time stop, float dt);
  705. void SetStopPosition(void)
  706. {
  707. m_stopPosition = GetPosition();
  708. if (m_tStop > 0.0f)
  709. m_stopPosition += m_tStop * m_velocity;
  710. assert (m_stopPosition.LengthSquared() >= 0.0f);
  711. assert (m_stopPosition.LengthSquared() < 1.0e12f);
  712. }
  713. void Move(float t)
  714. {
  715. if (!m_staticF)
  716. {
  717. SetPosition(GetPosition() + m_velocity * t);
  718. if (m_tStart <= t)
  719. m_tStart = 0.0f;
  720. else
  721. m_tStart -= t;
  722. m_tStop -= t;
  723. assert (GetPosition() * GetPosition() >= 0.0f);
  724. }
  725. }
  726. void AdjustTimes(float t)
  727. {
  728. if (!m_staticF)
  729. {
  730. if (m_tStart <= t)
  731. m_tStart = 0.0f;
  732. else
  733. m_tStart -= t;
  734. m_tStop -= t;
  735. }
  736. }
  737. void Move(void)
  738. {
  739. if (!m_staticF)
  740. SetPosition(m_stopPosition);
  741. }
  742. virtual void UpdateStaticBB(void)
  743. {
  744. UpdateStaticBB(m_radius);
  745. }
  746. void UpdateStaticBB(float r)
  747. {
  748. assert (m_staticF);
  749. //let's assume were using the xy & z axes.
  750. assert (c_nAxes == 3);
  751. for (int i = 0; (i < c_nAxes); i++)
  752. {
  753. float v = GetPosition()[i];
  754. m_boundingBox.axes[i].values[0] = v - r;
  755. m_boundingBox.axes[i].values[1] = v + r;
  756. m_endpoints[i][0].value = m_boundingBox.axes[i].values[0];
  757. m_endpoints[i][1].value = m_boundingBox.axes[i].values[1];
  758. }
  759. }
  760. void UpdateBB(void);
  761. void Collide(HitTest* pHitTest,
  762. CollisionQueue* pQueue);
  763. HitTestShape GetShape(void) const
  764. {
  765. return m_shape;
  766. }
  767. HitTestShape GetTrueShape(void) const
  768. {
  769. return m_shapeTrue;
  770. }
  771. virtual void SetShape(HitTestShape shape)
  772. {
  773. //Never upgrade to anything more complex than our true shape
  774. if (shape <= m_shapeTrue)
  775. m_shape = shape;
  776. }
  777. virtual const Vector* GetEllipseEquation(void) const
  778. {
  779. return NULL;
  780. }
  781. float GetRadius(void) const
  782. {
  783. return m_radius;
  784. }
  785. virtual void SetRadius(float r)
  786. {
  787. m_radius = r;
  788. }
  789. virtual float GetScale(void) const
  790. {
  791. return 1.0f;
  792. }
  793. bool GetDeadF(void) const
  794. {
  795. return m_deadF;
  796. }
  797. void SetDeadF(bool d)
  798. {
  799. m_deadF = d;
  800. }
  801. bool GetDeletedF(void) const
  802. {
  803. return m_deletedF;
  804. }
  805. void SetDeletedF(bool d)
  806. {
  807. m_deletedF = d;
  808. }
  809. IObject* GetData(void) const
  810. {
  811. return m_data;
  812. }
  813. HitTest* GetLastTest(void) const
  814. {
  815. return m_lastTest;
  816. }
  817. void SetLastTest(HitTest* ht)
  818. {
  819. m_lastTest = ht;
  820. }
  821. const Vector& GetVelocity(void) const
  822. {
  823. return m_velocity;
  824. }
  825. void SetVelocity(const Vector& v)
  826. {
  827. assert (v * v >= 0.0f);
  828. assert (v.LengthSquared() < (100000.0f * 100000.0f));
  829. m_velocity = v;
  830. }
  831. HitTestID GetID(void) const
  832. {
  833. return m_id;
  834. }
  835. void SetID(HitTestID id)
  836. {
  837. m_id = id;
  838. }
  839. HitTest* GetNoHit(void) const
  840. {
  841. return m_noHit;
  842. }
  843. void SetUseTrueShapeSelf(void* pvUseTrueShapeSelf)
  844. {
  845. m_pvUseTrueShapeSelf = pvUseTrueShapeSelf;
  846. }
  847. void SetUseTrueShapeOther(void* pvUseTrueShapeOther)
  848. {
  849. m_pvUseTrueShapeOther = pvUseTrueShapeOther;
  850. }
  851. void SetNoHit(HitTest* ht)
  852. {
  853. m_noHit = ht;
  854. }
  855. void SetTimeStart(Time t)
  856. {
  857. m_timeStart = t;
  858. }
  859. void SetTimeStop(Time t)
  860. {
  861. m_timeStop = t;
  862. }
  863. static bool HullCollide(float* tCollision,
  864. float tMax,
  865. HitTest* phtHullA,
  866. HitTestShape* phtsA,
  867. HitTest* phtHullB,
  868. HitTestShape* phtsB,
  869. const Vector& dP,
  870. const Vector& dV); //Sense for velocity is reversed from position
  871. static bool IntervalCollide(float tStart,
  872. float tStop,
  873. float maxDeltaT,
  874. HitTest* phtHullA,
  875. HitTestShape htsA,
  876. HitTest* phtHullB,
  877. HitTestShape htsB,
  878. const Vector& dP,
  879. const Vector& dV, //Sense for velocity is reversed from position
  880. const Orientation& orientationA,
  881. float* tCollision);
  882. Vector GetMinExtreme(HitTestShape hts,
  883. const Vector& position,
  884. const Orientation& orientation,
  885. const Vector& direction);
  886. //position is assumed to be 0, 0, 0; orientation is the identity
  887. Vector GetMaxExtreme(HitTestShape hts,
  888. const Vector& direction);
  889. virtual Vector GetCenter(HitTestShape hts) const
  890. {
  891. assert (false); //Should never be called for anything except convex hulls
  892. return Vector::GetZero();
  893. }
  894. void SetKDRoot(KDroot* pkdr)
  895. {
  896. m_pkdrRoot = pkdr;
  897. }
  898. KDroot* GetKDRoot(void) const
  899. {
  900. return m_pkdrRoot;
  901. }
  902. virtual const Vector GetFrameOffset(const char* pszFrameName) const
  903. {
  904. return Vector::GetZero();
  905. }
  906. virtual const Vector& GetFrameForward(const char* pszFrameName) const
  907. {
  908. static const Vector z(0.0f, 0.0f, 1.0f);
  909. return z;
  910. }
  911. virtual const FrameDataUTL* GetFrame(const char* pszFrameName) const
  912. {
  913. return NULL;
  914. }
  915. float GetTstop(void) const
  916. {
  917. return m_tStop;
  918. }
  919. protected:
  920. ULONG m_cRefs;
  921. IObject* m_data;
  922. void* m_pvUseTrueShapeSelf; //if m_useTrueShapeSelf != NULL and m_useTrueShapeSelf == pht->m_useTrueShapeOther
  923. void* m_pvUseTrueShapeOther; //then always use the true shape for purposes of collision detection & not the given shape
  924. KDroot* m_pkdrRoot;
  925. HitTest* m_noHit;
  926. HitTestID m_id;
  927. BoundingBox m_boundingBox;
  928. Vector m_stopPosition;
  929. Vector m_velocity;
  930. float m_radius;
  931. float m_tStart;
  932. float m_tStop;
  933. Time m_timeStart;
  934. Time m_timeStop;
  935. Endpoint m_endpoints[c_nAxes][2];
  936. HitTest* m_lastTest;
  937. HitTestShape m_shape;
  938. HitTestShape m_shapeTrue;
  939. bool m_deletedF;
  940. bool m_deadF;
  941. bool m_activeF;
  942. bool m_staticF;
  943. friend class KDnode;
  944. friend class KDroot;
  945. };
  946. typedef Slist_utl<HitTest*> HitTestList;
  947. typedef Slink_utl<HitTest*> HitTestLink;
  948. class KDnode
  949. {
  950. public:
  951. KDnode(KDnode* parent);
  952. ~KDnode(void);
  953. void reset(bool highF);
  954. void pivot(void);
  955. void test(HitTest* pHitTest,
  956. CollisionQueue* pQueue) const;
  957. protected:
  958. int m_pivotAxis;
  959. float m_pivotValue;
  960. KDnode* m_parent;
  961. KDnode* m_children[2];
  962. void allocHitTestsEndpoints(int n);
  963. int m_nHitTests;
  964. int m_maxHitTests;
  965. HitTest** m_ppHitTests;
  966. Endpoint** m_ppEndpoints[c_nAxes];
  967. };
  968. class KDroot : public KDnode
  969. {
  970. public:
  971. KDroot(bool bStatic);
  972. ~KDroot(void);
  973. void addHitTest(HitTest* pHitTest);
  974. void deleteHitTest(HitTest* pHitTest);
  975. void flush(void);
  976. void update(void);
  977. private:
  978. int m_nAdded;
  979. int m_nDeleted;
  980. bool m_bStatic;
  981. };
  982. class CollisionEntry
  983. {
  984. public:
  985. float m_tCollision;
  986. HitTest* m_pHitTest1;
  987. HitTest* m_pHitTest2;
  988. HitTestShape m_hts1;
  989. HitTestShape m_hts2;
  990. //Bubble-sort based algorith: use when the list is mostly sorted
  991. static void shortSort(CollisionEntry* lo,
  992. CollisionEntry* hi);
  993. //Quick-sort based algorithm: the alternative to shortSort
  994. static void longSort(CollisionEntry* lo,
  995. CollisionEntry* hi);
  996. };
  997. class CollisionQueue
  998. {
  999. public:
  1000. CollisionQueue(void);
  1001. CollisionQueue(int m_maxCollisions,
  1002. CollisionEntry* pCollisions);
  1003. ~CollisionQueue(void);
  1004. inline int n(void) const
  1005. {
  1006. return m_nCollisions;
  1007. }
  1008. inline CollisionEntry& operator [] (int i)
  1009. {
  1010. return m_pCollisions[i];
  1011. }
  1012. void sort(int start);
  1013. void flush(int start,
  1014. HitTest* pHitTest1,
  1015. HitTest* pHitTest2);
  1016. void purge(void);
  1017. void addCollision(float tCollision,
  1018. HitTest* pHitTest1,
  1019. HitTestShape hts1,
  1020. HitTest* pHitTest2,
  1021. HitTestShape hts2);
  1022. private:
  1023. int m_nCollisions;
  1024. CollisionEntry* m_pCollisions;
  1025. int m_maxCollisions;
  1026. bool m_fDelete;
  1027. };
  1028. class UTL
  1029. {
  1030. public:
  1031. //Get an artwork file, downloading if needed
  1032. // S_OK ... file exists and has a non-zero length
  1033. // S_FALSE ... file exists, but has a length of zero
  1034. // E_FAIL ... file does not exist.
  1035. static void SetArtPath(const char* szArtwork);
  1036. static HRESULT getFile( const char* name,
  1037. const char* extension,
  1038. OUT char* artwork,
  1039. bool downloadF,
  1040. bool createF);
  1041. // Writes a blob to disk; returns true iff successful
  1042. static bool SaveFile( const char * szFilename,
  1043. const void *pData,
  1044. unsigned cLen,
  1045. OUT char * szErrorMsg,
  1046. bool bCreateAsTemp);
  1047. static bool AppendFile(const char * szFileName, const void * data, unsigned bytes);
  1048. static int SearchAndReplace(char * szDest, const char * szSource, const char * szNewWord, const char * szOldWord);
  1049. static void SetUrlRoot(const char * szUrlRoot);
  1050. //Like the stock strdup() except uses new [] and handles NULL
  1051. static char* strdup(const char* s);
  1052. //set allocated on demand strings, file names or names
  1053. static void putFileName(char* name, const char* newVal);
  1054. static void putName(char* name, const char* newVal);
  1055. static const char* artworkPath(void)
  1056. {
  1057. return s_artworkPath;
  1058. }
  1059. static LONG GetPathFromReg(IN HKEY hkey,
  1060. IN const char * szSubKey,
  1061. OUT char * szPath);
  1062. // converts char * of hex to int. Assumes uppercase for 'A' to 'F'.
  1063. static int hextoi(const char * pHex);
  1064. private:
  1065. static char s_artworkPath[MAX_PATH];
  1066. static char s_szUrlRoot[MAX_PATH];
  1067. };
  1068. class BytePercentage
  1069. {
  1070. public:
  1071. enum
  1072. {
  1073. Divisor = 240 //Use 240 since it has so many nice factors (2, 3, 4, 5, 10, etc.)
  1074. };
  1075. BytePercentage(void)
  1076. {
  1077. }
  1078. BytePercentage(const BytePercentage& p)
  1079. :
  1080. m_percentage(p.m_percentage)
  1081. {
  1082. }
  1083. BytePercentage(float f)
  1084. :
  1085. m_percentage((unsigned char)(f * (float)Divisor + 0.5f))
  1086. {
  1087. assert ((f * (float)Divisor + 0.5f) >= 0.0f);
  1088. assert ((f * (float)Divisor + 0.5f) < (float)(Divisor + 1));
  1089. }
  1090. unsigned char GetChar(void) const
  1091. {
  1092. return m_percentage;
  1093. }
  1094. void SetChar(unsigned char p)
  1095. {
  1096. m_percentage = p;
  1097. }
  1098. BytePercentage& operator = (float f)
  1099. {
  1100. assert ((f * (float)Divisor + 0.5f) >= 0.0f);
  1101. assert ((f * (float)Divisor + 0.5f) < (float)(Divisor + 1));
  1102. m_percentage = (unsigned char)(f * (float)Divisor + 0.5f);
  1103. return *this;
  1104. }
  1105. operator float (void) const
  1106. {
  1107. return ((float)m_percentage) / ((float)Divisor);
  1108. }
  1109. private:
  1110. unsigned char m_percentage;
  1111. };
  1112. extern const Rotation c_rotationZero;
  1113. #include "utility.hxx"
  1114. #undef _exposed
  1115. // safe strcpy
  1116. static char * Strcpy(char * szDst, const char * szSrc)
  1117. {
  1118. assert(szDst);
  1119. return lstrcpyA(szDst, szSrc ? szSrc : "");
  1120. }
  1121. // safe strncpy
  1122. static char * Strncpy(char * szDst, const char * szSrc, size_t cb)
  1123. {
  1124. assert(szDst);
  1125. return strncpy(szDst, szSrc ? szSrc : "", cb);
  1126. }
  1127. // safe strcmp
  1128. static int Strcmp(const char * szDst, const char * szSrc)
  1129. {
  1130. return lstrcmpA(szDst ? szDst : "", szSrc ? szSrc : "");
  1131. }
  1132. #define IMPLIES(x, y) (!(x) || (y))
  1133. #define IFF(x, y) (!!(x) == !!(y))
  1134. #include "listwrappers.h"
  1135. // Class for temporary dll function use
  1136. template <class Func> // signature of function to get, so that Proc can be used without casting
  1137. class CTempFuncDll
  1138. {
  1139. public:
  1140. CTempFuncDll(LPSTR szDLL, LPSTR szFunc)
  1141. {
  1142. hmod = LoadLibrary(szDLL);
  1143. pfunc = (Func) ((hmod) ? GetProcAddress(hmod, szFunc) : 0);
  1144. }
  1145. ~CTempFuncDll()
  1146. {
  1147. FreeLibrary(hmod);
  1148. }
  1149. Func Call()
  1150. {
  1151. assert(pfunc);
  1152. assert(!IsBadCodePtr((FARPROC)pfunc));
  1153. return pfunc;
  1154. }
  1155. private:
  1156. HMODULE hmod;
  1157. Func pfunc;
  1158. };
  1159. class CTempTimer_OptimizedOut // timers do nothing in optimized builds
  1160. {
  1161. public:
  1162. CTempTimer_OptimizedOut(const char * szName, float dtWarning) {}
  1163. void Start() {}
  1164. bool Stop(const char* format = NULL, ...) {return false;}
  1165. DWORD LastInterval() {return 0;}
  1166. };
  1167. class CTimer
  1168. {
  1169. public:
  1170. CTimer(const char * szName, float dtWarning) :
  1171. m_szname(szName),
  1172. m_time(0),
  1173. m_dtWarning((DWORD)(1000.0f * dtWarning)),
  1174. m_dtimemax(0),
  1175. m_dtTotal(0)
  1176. {
  1177. }
  1178. void Start()
  1179. {
  1180. m_time = Time::Now();
  1181. }
  1182. bool Stop(const char* format = NULL, ...) // returns whether this previous interval was a new record
  1183. {
  1184. m_dtimelast = Time::Now().clock() - m_time.clock();
  1185. m_dtTotal += m_dtimelast;
  1186. bool fExtra = false;
  1187. bool fRecord = false;
  1188. if (m_dtimelast > m_dtimemax)
  1189. {
  1190. debugf("Timer: %fs spent %s, %fs total (longest so far)\n", (float) m_dtimelast / 1000.f, m_szname, (float)m_dtTotal / 1000.f);
  1191. m_dtimemax = m_dtimelast;
  1192. fRecord = true;
  1193. fExtra = true;
  1194. }
  1195. else if (m_dtimelast >= m_dtWarning)
  1196. {
  1197. debugf("Timer: %fs spent %s, %fs total\n", (float) m_dtimelast / 1000.0f, m_szname, (float)m_dtTotal / 1000.f);
  1198. fExtra = true;
  1199. }
  1200. if (fExtra && format)
  1201. {
  1202. const size_t size = 256;
  1203. char bfr[size];
  1204. va_list vl;
  1205. va_start(vl, format);
  1206. _vsnprintf(bfr, size, format, vl);
  1207. va_end(vl);
  1208. debugf("^--%s\n", bfr);
  1209. }
  1210. return fRecord;
  1211. }
  1212. DWORD LastInterval() // in seconds
  1213. {
  1214. return m_dtimelast;
  1215. }
  1216. private:
  1217. const char * m_szname;
  1218. Time m_time;
  1219. DWORD m_dtimelast;
  1220. DWORD m_dtimemax;
  1221. DWORD m_dtWarning;
  1222. DWORD m_dtTotal;
  1223. };
  1224. #ifdef NDEBUG
  1225. #define CTempTimer CTempTimer_OptimizedOut
  1226. #else
  1227. #define CTempTimer CTimer
  1228. #endif
  1229. #endif