W3DViewDoc.cpp 84 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114
  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. // W3DViewDoc.cpp : implementation of the CW3DViewDoc class
  19. //
  20. #include "stdafx.h"
  21. #include "w3dview.h"
  22. #include "w3dviewdoc.h"
  23. #include "ffactory.h"
  24. #include "globals.h"
  25. #include "viewerassetmgr.h"
  26. #include "globals.h"
  27. #include "rendobj.h"
  28. #include "graphicview.h"
  29. #include "datatreeview.h"
  30. #include "mainfrm.h"
  31. #include "distlod.h"
  32. #include "light.h"
  33. #include "camera.h"
  34. #include "w3d_file.h"
  35. #include "wwfile.h"
  36. #include "bmp2d.h"
  37. #include "part_emt.h"
  38. #include "part_ldr.h"
  39. #include "utils.h"
  40. #include "w3derr.h"
  41. #include "chunkio.h"
  42. #include "assetinfo.h"
  43. #include "meshmdl.h"
  44. #include "agg_def.h"
  45. #include "hlod.h"
  46. #include "restrictedfiledialog.h"
  47. #include "viewerscene.h"
  48. #include "ini.h"
  49. #include "ww3d.h"
  50. #include "emitterinstancelist.h"
  51. #include "mesh.h"
  52. #include "screencursor.h"
  53. #include "sphereobj.h"
  54. #include "ringobj.h"
  55. #include "textfile.h"
  56. #include "hmorphanim.h"
  57. #include "mmsystem.h"
  58. #include "soundrobj.h"
  59. #include "dazzle.h"
  60. #ifdef _DEBUG
  61. #define new DEBUG_NEW
  62. #undef THIS_FILE
  63. static char THIS_FILE[] = __FILE__;
  64. #endif
  65. /////////////////////////////////////////////////////////////////////////////
  66. // CW3DViewDoc
  67. IMPLEMENT_DYNCREATE(CW3DViewDoc, CDocument)
  68. BEGIN_MESSAGE_MAP(CW3DViewDoc, CDocument)
  69. //{{AFX_MSG_MAP(CW3DViewDoc)
  70. // NOTE - the ClassWizard will add and remove mapping macros here.
  71. // DO NOT EDIT what you see in these blocks of generated code!
  72. //}}AFX_MSG_MAP
  73. END_MESSAGE_MAP()
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CW3DViewDoc construction/destruction
  76. ///////////////////////////////////////////////////////////////
  77. //
  78. // CW3DViewDoc
  79. //
  80. CW3DViewDoc::CW3DViewDoc (void)
  81. : m_pCScene (NULL),
  82. m_pC2DScene (NULL),
  83. m_pCursorScene (NULL),
  84. m_pCBackObjectScene (NULL),
  85. m_pDazzleLayer (NULL),
  86. m_pCBackObjectCamera (NULL),
  87. m_pCBackgroundObject (NULL),
  88. m_pC2DCamera (NULL),
  89. m_pCSceneLight (NULL),
  90. m_pCRenderObj (NULL),
  91. m_pCAnimation (NULL),
  92. m_pCAnimCombo (NULL),
  93. m_pCBackgroundBMP (NULL),
  94. m_CurrentFrame (0),
  95. m_bAnimBlend (TRUE),
  96. m_bAnimateCamera (false),
  97. m_bAutoCameraReset (true),
  98. m_bOneTimeReset (true),
  99. m_pCursor (NULL),
  100. m_backgroundColor (0.5F, 0.5F, 0.5F),
  101. m_ManualFOV (false),
  102. m_ManualClipPlanes (false),
  103. m_IsInitialized (false),
  104. m_bFogEnabled(false),
  105. m_nChannelQnBytes(2),
  106. m_bCompress_channel_Q(false)
  107. {
  108. // Read the camera animation settings from the registry
  109. m_bAnimateCamera = ((BOOL)theApp.GetProfileInt ("Config", "AnimateCamera", 0)) == TRUE;
  110. m_bAutoCameraReset = ((BOOL)theApp.GetProfileInt ("Config", "ResetCamera", 1)) == TRUE;
  111. return ;
  112. }
  113. ///////////////////////////////////////////////////////////////
  114. //
  115. // ~CW3DViewDoc
  116. //
  117. ///////////////////////////////////////////////////////////////
  118. CW3DViewDoc::~CW3DViewDoc (void)
  119. {
  120. CleanupResources ();
  121. MEMBER_RELEASE (m_pCursor);
  122. return ;
  123. }
  124. ///////////////////////////////////////////////////////////////
  125. //
  126. // CleanupResources
  127. //
  128. ///////////////////////////////////////////////////////////////
  129. void
  130. CW3DViewDoc::CleanupResources (void)
  131. {
  132. if (m_pC2DScene)
  133. {
  134. if (m_pCBackgroundBMP)
  135. {
  136. // Remove the background BMP from the scene
  137. m_pCBackgroundBMP->Remove ();
  138. }
  139. // Release the 2D scene we allocated to display background BMPs
  140. m_pC2DScene->Release_Ref ();
  141. m_pC2DScene = NULL;
  142. }
  143. if (m_pCBackObjectScene)
  144. {
  145. if (m_pCBackgroundObject)
  146. {
  147. // Remove the background BMP from the scene
  148. m_pCBackgroundObject->Remove ();
  149. }
  150. // Release the scene we allocated to display background objects
  151. m_pCBackObjectScene->Release_Ref ();
  152. m_pCBackObjectScene = NULL;
  153. }
  154. if (m_pCursor != NULL) {
  155. m_pCursor->Remove ();
  156. }
  157. MEMBER_RELEASE (m_pCursorScene);
  158. if (m_pCScene)
  159. {
  160. if (m_pCRenderObj)
  161. {
  162. // Remove the currently displayed object from the scene
  163. Remove_Object_From_Scene (m_pCRenderObj);
  164. }
  165. if (m_pCSceneLight)
  166. {
  167. // Remove the light from the scene
  168. Remove_Object_From_Scene (m_pCSceneLight);
  169. }
  170. // Get rid of the lined up objects.
  171. m_pCScene->Clear_Lineup();
  172. // Release the scene object we allocated earlier
  173. m_pCScene->Release_Ref ();
  174. m_pCScene = NULL;
  175. }
  176. // Was there a dazzle layer?
  177. if (m_pDazzleLayer) {
  178. delete m_pDazzleLayer;
  179. m_pDazzleLayer = NULL;
  180. }
  181. // Was there a valid scene object?
  182. if (m_pCBackObjectScene)
  183. {
  184. // Free the scene object
  185. m_pCBackObjectScene->Release_Ref ();
  186. m_pCBackObjectScene = NULL;
  187. }
  188. // Was there a valid 2D camera?
  189. if (m_pC2DCamera)
  190. {
  191. // Free the camera object
  192. m_pC2DCamera->Release_Ref ();
  193. m_pC2DCamera = NULL;
  194. }
  195. // Was there a valid background camera?
  196. if (m_pCBackObjectCamera)
  197. {
  198. // Free the camera object
  199. m_pCBackObjectCamera->Release_Ref ();
  200. m_pCBackObjectCamera = NULL;
  201. }
  202. // Was there a valid background BMP?
  203. if (m_pCBackgroundBMP)
  204. {
  205. m_pCBackgroundBMP->Release_Ref ();
  206. m_pCBackgroundBMP = NULL;
  207. }
  208. // Was there a valid scene light?
  209. if (m_pCSceneLight)
  210. {
  211. m_pCSceneLight->Release_Ref ();
  212. m_pCSceneLight = NULL;
  213. }
  214. // Was there a valid display object?
  215. if (m_pCRenderObj)
  216. {
  217. // Free the currently displayed object
  218. SAFE_DELETE (m_pCAnimCombo);
  219. MEMBER_RELEASE (m_pCAnimation);
  220. MEMBER_RELEASE (m_pCRenderObj);
  221. }
  222. return ;
  223. }
  224. ///////////////////////////////////////////////////////////////
  225. //
  226. // OnNewDocument
  227. //
  228. ///////////////////////////////////////////////////////////////
  229. BOOL
  230. CW3DViewDoc::OnNewDocument (void)
  231. {
  232. if (!CDocument::OnNewDocument())
  233. return FALSE;
  234. _TheAssetMgr->Start_Tracking_Textures ();
  235. m_LoadList.Delete_All ();
  236. m_bOneTimeReset = true;
  237. if (m_pCScene && m_pCRenderObj)
  238. {
  239. // Remove the currently displayed object from the scene
  240. Remove_Object_From_Scene (m_pCRenderObj);
  241. }
  242. if (m_pCScene)
  243. {
  244. // Remove all objects from the lineup.
  245. m_pCScene->Clear_Lineup();
  246. // Update the fog color.
  247. m_pCScene->Set_Fog_Color(m_backgroundColor);
  248. }
  249. if (m_pCRenderObj)
  250. {
  251. // Free the currently displayed object
  252. SAFE_DELETE (m_pCAnimCombo);
  253. MEMBER_RELEASE (m_pCAnimation);
  254. MEMBER_RELEASE (m_pCRenderObj);
  255. }
  256. CDataTreeView *pCDataTreeView = GetDataTreeView ();
  257. if (pCDataTreeView)
  258. {
  259. // Delete everything from the tree
  260. pCDataTreeView->GetTreeCtrl ().DeleteAllItems ();
  261. // Recreate the root nodes
  262. pCDataTreeView->CreateRootNodes ();
  263. }
  264. // Remove everything from the scene and the asset manager
  265. CleanupResources ();
  266. //WW3DAssetManager::Get_Instance ()->Release_All_Textures ();
  267. WW3DAssetManager::Get_Instance ()->Free_Assets ();
  268. WW3DAssetManager::Get_Instance ()->Load_Procedural_Textures();
  269. return TRUE;
  270. }
  271. /////////////////////////////////////////////////////////////////////////////
  272. //
  273. // CW3DViewDoc
  274. //
  275. /////////////////////////////////////////////////////////////////////////////
  276. void
  277. CW3DViewDoc::Serialize(CArchive& ar)
  278. {
  279. if (ar.IsStoring())
  280. {
  281. // TODO: add storing code here
  282. }
  283. else
  284. {
  285. // TODO: add loading code here
  286. }
  287. return ;
  288. }
  289. /////////////////////////////////////////////////////////////////////////////
  290. // CW3DViewDoc diagnostics
  291. #ifdef _DEBUG
  292. void CW3DViewDoc::AssertValid() const
  293. {
  294. CDocument::AssertValid();
  295. }
  296. void CW3DViewDoc::Dump(CDumpContext& dc) const
  297. {
  298. CDocument::Dump(dc);
  299. }
  300. #endif //_DEBUG
  301. ///////////////////////////////////////////////////////////////
  302. //
  303. // InitScene
  304. //
  305. ///////////////////////////////////////////////////////////////
  306. void
  307. CW3DViewDoc::InitScene (void)
  308. {
  309. if (m_pCScene == NULL) {
  310. //
  311. // Make sure the emitters don't remove themselves from the scene
  312. // when they are finished emitting...
  313. //
  314. ParticleEmitterClass::Set_Default_Remove_On_Complete (false);
  315. m_pCScene = new ViewerSceneClass;
  316. ASSERT (m_pCScene);
  317. if (m_pCScene != NULL) {
  318. // Set some default ambient lighting
  319. m_pCScene->Set_Ambient_Light (Vector3 (0.5F, 0.5F, 0.5F));
  320. // Set up the correct fog color.
  321. m_pCScene->Set_Fog_Color(GetBackgroundColor());
  322. // Create a new scene light
  323. m_pCSceneLight = new LightClass;
  324. ASSERT (m_pCSceneLight);
  325. if (m_pCSceneLight != NULL) {
  326. // Create some default light settings
  327. m_pCSceneLight->Set_Position (Vector3 (0, 5000, 3000));
  328. m_pCSceneLight->Set_Intensity (1.0F);
  329. m_pCSceneLight->Set_Force_Visible(true);
  330. m_pCSceneLight->Set_Flag (LightClass::NEAR_ATTENUATION, false);
  331. m_pCSceneLight->Set_Far_Attenuation_Range (1000000, 1000000);
  332. m_pCSceneLight->Set_Ambient(Vector3(0,0,0));
  333. m_pCSceneLight->Set_Diffuse (Vector3(1, 1, 1));
  334. m_pCSceneLight->Set_Specular (Vector3(1, 1, 1));
  335. // Add this light to the scene
  336. m_pCScene->Add_Render_Object (m_pCSceneLight);
  337. }
  338. }
  339. // Instantiate a new 2D scene
  340. m_pC2DScene = new SimpleSceneClass;
  341. ASSERT (m_pC2DScene);
  342. // Instantiate a new 2D cursor scene
  343. m_pCursorScene = new SimpleSceneClass;
  344. ASSERT (m_pCursorScene);
  345. Create_Cursor ();
  346. m_pCursorScene->Add_Render_Object (m_pCursor);
  347. m_pCBackObjectScene = new SimpleSceneClass;
  348. // Were we successful in instantiating the scene object?
  349. ASSERT (m_pCBackObjectScene);
  350. if (m_pCBackObjectScene) {
  351. // Set the default ambient light for the background object
  352. m_pCBackObjectScene->Set_Ambient_Light (Vector3 (0.5F, 0.5F, 0.5F));
  353. }
  354. // Create a new instance of the camera class to use
  355. // when rendering the background object
  356. m_pCBackObjectCamera = new CameraClass ();
  357. // Were we successful in creating the new instance?
  358. ASSERT (m_pCBackObjectCamera);
  359. if (m_pCBackObjectCamera) {
  360. // Set the default values for the new camera
  361. m_pCBackObjectCamera->Set_View_Plane (Vector2 (-1.00F, -1.00F), Vector2 (1.00F, 1.00F));
  362. m_pCBackObjectCamera->Set_Position (Vector3 (0.00F, 0.00F, 0.00F));
  363. m_pCBackObjectCamera->Set_Clip_Planes (0.1F, 10.0F);
  364. }
  365. // Create a new instance of the camera class to use
  366. // when rendering the background BMP
  367. m_pC2DCamera = new CameraClass ();
  368. // Were we successful in creating the new instance?
  369. ASSERT (m_pC2DCamera);
  370. if (m_pC2DCamera) {
  371. // Set the default values for the new camera
  372. m_pC2DCamera->Set_View_Plane (Vector2 (-1.00F, -1.00F), Vector2 (1.00F, 1.00F));
  373. m_pC2DCamera->Set_Position (Vector3 (0.00F, 0.00F, 1.00F));
  374. m_pC2DCamera->Set_Clip_Planes (0.1F, 10.0F);
  375. }
  376. //
  377. // Read the texture paths from the registry
  378. //
  379. CString path1 = theApp.GetProfileString ("Config", "TexturePath1", "");
  380. CString path2 = theApp.GetProfileString ("Config", "TexturePath2", "");
  381. Set_Texture_Path1 (path1);
  382. Set_Texture_Path2 (path2);
  383. // Construct a dazzle layer object
  384. m_pDazzleLayer = new DazzleLayerClass();
  385. DazzleRenderObjClass::Set_Current_Dazzle_Layer(m_pDazzleLayer);
  386. // Enable fog if appropriate.
  387. if (IsFogEnabled()) {
  388. m_pCScene->Set_Fog_Enable(true);
  389. }
  390. }
  391. Load_Camera_Settings ();
  392. m_IsInitialized = true;
  393. return ;
  394. }
  395. ///////////////////////////////////////////////////////////////
  396. //
  397. // OnOpenDocument
  398. //
  399. ///////////////////////////////////////////////////////////////
  400. BOOL
  401. CW3DViewDoc::OnOpenDocument (LPCTSTR lpszPathName)
  402. {
  403. if (!CDocument::OnOpenDocument(lpszPathName))
  404. return FALSE;
  405. //
  406. // Don't allow repaints while the load is going on
  407. //
  408. CGraphicView *current_view = ::Get_Graphic_View ();
  409. if (current_view != NULL) {
  410. current_view->Allow_Update (false);
  411. }
  412. //
  413. // Load the assets from this file into application
  414. //
  415. LoadAssetsFromFile (lpszPathName);
  416. //
  417. // Re-load the data list to include all new assets
  418. //
  419. CDataTreeView *data_view = GetDataTreeView ();
  420. if (data_view != NULL) {
  421. data_view->LoadAssetsIntoTree ();
  422. }
  423. //
  424. // Turn repainting back on...
  425. //
  426. if (current_view != NULL) {
  427. current_view->Allow_Update (true);
  428. }
  429. return TRUE;
  430. }
  431. ///////////////////////////////////////////////////////////////
  432. //
  433. // LoadAssetsFromFile
  434. //
  435. ///////////////////////////////////////////////////////////////
  436. void
  437. CW3DViewDoc::LoadAssetsFromFile (LPCTSTR lpszPathName)
  438. {
  439. if (m_pCScene == NULL) {
  440. InitScene ();
  441. }
  442. //
  443. // Remember the last path we opened
  444. //
  445. m_LastPath = ::Strip_Filename_From_Path (lpszPathName);
  446. //
  447. // Add this path to the load list
  448. //
  449. m_LoadList.Add (lpszPathName);
  450. //
  451. // Don't allow repaints while the load is going on
  452. //
  453. CGraphicView *current_view = ::Get_Graphic_View ();
  454. if (current_view != NULL) {
  455. current_view->Allow_Update (false);
  456. }
  457. //
  458. // HACK HACK -- Force the current directory to be the directory
  459. // the file is located in.
  460. //
  461. if (::strrchr (lpszPathName, '\\')) {
  462. CString stringTemp = lpszPathName;
  463. stringTemp = stringTemp.Left ((long)::strrchr (lpszPathName, '\\') - (long)lpszPathName);
  464. ::SetCurrentDirectory (stringTemp);
  465. _TheSimpleFileFactory->Append_Sub_Directory(stringTemp);
  466. }
  467. LPCTSTR extension = ::strrchr (lpszPathName, '.');
  468. if (::lstrcmpi (extension, ".tga") == 0 || ::lstrcmpi (extension, ".dds") == 0) {
  469. // Load the texture file into the asset manager
  470. TextureClass *ptexture = WW3DAssetManager::Get_Instance()->Get_Texture (::Get_Filename_From_Path (lpszPathName));
  471. if (ptexture != NULL) {
  472. ptexture->Release_Ref();
  473. }
  474. } else {
  475. WW3DAssetManager::Get_Instance()->Load_3D_Assets (::Get_Filename_From_Path (lpszPathName));
  476. }
  477. //
  478. // Turn repainting back on...
  479. //
  480. if (current_view != NULL) {
  481. current_view->Allow_Update (true);
  482. }
  483. return ;
  484. }
  485. ///////////////////////////////////////////////////////////////
  486. //
  487. // Reload_Displayed_Object
  488. //
  489. ///////////////////////////////////////////////////////////////
  490. void
  491. CW3DViewDoc::Reload_Displayed_Object (void)
  492. {
  493. GetDataTreeView ()->Display_Asset ();
  494. //SAFE_ADD_REF (m_pCRenderObj);
  495. //DisplayObject (m_pCRenderObj, false, false);
  496. //SAFE_RELEASE_REF (m_pCRenderObj);
  497. return ;
  498. }
  499. ///////////////////////////////////////////////////////////////
  500. //
  501. // Display_Emitter
  502. //
  503. ///////////////////////////////////////////////////////////////
  504. void
  505. CW3DViewDoc::Display_Emitter
  506. (
  507. ParticleEmitterClass *pemitter,
  508. bool use_global_reset_flag,
  509. bool allow_reset
  510. )
  511. {
  512. ASSERT (m_pCScene);
  513. // Data OK?
  514. if (m_pCScene != NULL) {
  515. // Lose the animation
  516. SAFE_DELETE (m_pCAnimCombo);
  517. MEMBER_RELEASE (m_pCAnimation);
  518. if (m_pCRenderObj != NULL) {
  519. // Remove this object from the scene
  520. Remove_Object_From_Scene (m_pCRenderObj);
  521. m_pCRenderObj->Release_Ref ();
  522. m_pCRenderObj = NULL;
  523. }
  524. m_pCScene->Clear_Lineup();
  525. // Do we have a new emitter to display?
  526. if (pemitter != NULL) {
  527. // Add the emitter to the scene
  528. pemitter->Set_Transform (Matrix3D (1));
  529. MEMBER_ADD (m_pCRenderObj, pemitter);
  530. m_pCScene->Add_Render_Object (m_pCRenderObj);
  531. pemitter->Start ();
  532. CGraphicView *pCGraphicView = GetGraphicView ();
  533. if (pCGraphicView) {
  534. // Try to find a good view for the emitter
  535. if ((use_global_reset_flag && m_bAutoCameraReset) ||
  536. ((use_global_reset_flag == false) && allow_reset) ||
  537. m_bOneTimeReset) {
  538. pCGraphicView->Reset_Camera_To_Display_Emitter (*pemitter);
  539. m_bOneTimeReset = false;
  540. }
  541. }
  542. }
  543. }
  544. return ;
  545. }
  546. ///////////////////////////////////////////////////////////////
  547. //
  548. // DisplayObject
  549. //
  550. ///////////////////////////////////////////////////////////////
  551. void
  552. CW3DViewDoc::DisplayObject
  553. (
  554. RenderObjClass *pCModel,
  555. bool use_global_reset_flag,
  556. bool allow_reset,
  557. bool add_ghost
  558. )
  559. {
  560. ASSERT (m_pCScene);
  561. // Data OK?
  562. if (m_pCScene)
  563. {
  564. // Lose the animation
  565. SAFE_DELETE (m_pCAnimCombo);
  566. MEMBER_RELEASE (m_pCAnimation);
  567. // Do we have an old object to remove from the scene?
  568. if (add_ghost == false) {
  569. if (m_pCRenderObj)
  570. {
  571. // Remove this object from the scene
  572. Remove_Object_From_Scene (m_pCRenderObj);
  573. m_pCRenderObj->Release_Ref ();
  574. m_pCRenderObj = NULL;
  575. }
  576. }
  577. m_pCScene->Clear_Lineup();
  578. // Do we have a new object to display?
  579. if (pCModel && (add_ghost == false))
  580. {
  581. // Reset the animation for this object
  582. pCModel->Set_Animation ();
  583. m_pCRenderObj = pCModel;
  584. m_pCRenderObj->Add_Ref ();
  585. m_pCRenderObj->Set_Transform (Matrix3D (1));
  586. // Add this object to the scene
  587. if (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_BITMAP2D) {
  588. m_pC2DScene->Add_Render_Object (m_pCRenderObj);
  589. } else {
  590. m_pCScene->Add_Render_Object (m_pCRenderObj);
  591. }
  592. // Reset the current lod to be the lowest possible LOD...
  593. if ((m_pCScene->Are_LODs_Switching ()) &&
  594. (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_HLOD)) {
  595. ((HLodClass *)m_pCRenderObj)->Set_LOD_Level (0);
  596. }
  597. CGraphicView *pCGraphicView = GetGraphicView ();
  598. if (pCGraphicView)
  599. {
  600. // Reset the camera to so the user can see
  601. // the whole object
  602. if ((use_global_reset_flag && m_bAutoCameraReset) ||
  603. ((use_global_reset_flag == false) && allow_reset) ||
  604. m_bOneTimeReset) {
  605. pCGraphicView->Reset_Camera_To_Display_Object (*m_pCRenderObj);
  606. m_bOneTimeReset = false;
  607. }
  608. }
  609. }
  610. else if (pCModel) {
  611. // Reset the animation for this object
  612. pCModel->Set_Animation ();
  613. RenderObjClass *m_pCRenderObj;
  614. m_pCRenderObj = pCModel;
  615. m_pCRenderObj->Add_Ref ();
  616. m_pCRenderObj->Set_Transform (Matrix3D (1));
  617. // Add this object to the scene
  618. if (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_BITMAP2D) {
  619. m_pC2DScene->Add_Render_Object (m_pCRenderObj);
  620. } else {
  621. m_pCScene->Clear_Lineup();
  622. m_pCScene->Add_Render_Object (m_pCRenderObj);
  623. }
  624. // Reset the current lod to be the lowest possible LOD...
  625. if ((m_pCScene->Are_LODs_Switching ()) &&
  626. (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_HLOD)) {
  627. ((HLodClass *)m_pCRenderObj)->Set_LOD_Level (0);
  628. }
  629. CGraphicView *pCGraphicView = GetGraphicView ();
  630. if (pCGraphicView)
  631. {
  632. // Reset the camera to so the user can see
  633. // the whole object
  634. if ((use_global_reset_flag && m_bAutoCameraReset) ||
  635. ((use_global_reset_flag == false) && allow_reset) ||
  636. m_bOneTimeReset) {
  637. pCGraphicView->Reset_Camera_To_Display_Object (*m_pCRenderObj);
  638. m_bOneTimeReset = false;
  639. }
  640. }
  641. }
  642. }
  643. return ;
  644. }
  645. ///////////////////////////////////////////////////////////////
  646. //
  647. // ResetAnimation
  648. //
  649. ///////////////////////////////////////////////////////////////
  650. void
  651. CW3DViewDoc::ResetAnimation (void)
  652. {
  653. if (m_pCAnimation != NULL) {
  654. //
  655. // Reset the frame counter
  656. //
  657. m_CurrentFrame = 0;
  658. m_animTime = 0.00F;
  659. float frame_rate = m_pCAnimation->Get_Frame_Rate ();
  660. float anim_speed = ::Get_Graphic_View ()->GetAnimationSpeed ();
  661. //
  662. // Update the status bar on the main window
  663. //
  664. ((CMainFrame *)::AfxGetMainWnd ())->UpdateFrameCount ( 0,
  665. m_pCAnimation->Get_Num_Frames () - 1,
  666. frame_rate * anim_speed);
  667. }
  668. return ;
  669. }
  670. ///////////////////////////////////////////////////////////////
  671. //
  672. // StepAnimation
  673. //
  674. ///////////////////////////////////////////////////////////////
  675. void
  676. CW3DViewDoc::StepAnimation (int iFrameInc)
  677. {
  678. if (m_pCRenderObj && m_pCAnimation) {
  679. int iTotalFrames = m_pCAnimation->Get_Num_Frames ();
  680. // Increment the frame
  681. m_CurrentFrame += iFrameInc;
  682. //
  683. // Wrap the animation
  684. //
  685. if (m_CurrentFrame >= iTotalFrames) {
  686. m_CurrentFrame = 0;
  687. m_animTime = 0.00F;
  688. }
  689. else if (m_CurrentFrame < 0) {
  690. m_CurrentFrame = iTotalFrames-1;
  691. }
  692. //
  693. // Update the status bar on the main window
  694. //
  695. float frame_rate = m_pCAnimation->Get_Frame_Rate ();
  696. float anim_speed = ::Get_Graphic_View ()->GetAnimationSpeed ();
  697. ((CMainFrame *)::AfxGetMainWnd ())->UpdateFrameCount (m_CurrentFrame, iTotalFrames - 1, frame_rate * anim_speed);
  698. //
  699. // Update the animation frame
  700. //
  701. if (m_pCAnimCombo) {
  702. for (int i = 0; i < m_pCAnimCombo->Get_Num_Anims(); i++)
  703. {
  704. m_pCAnimCombo->Set_Frame(i, m_CurrentFrame);
  705. }
  706. m_pCRenderObj->Set_Animation (m_pCAnimCombo);
  707. } else {
  708. m_pCRenderObj->Set_Animation (m_pCAnimation, m_CurrentFrame);
  709. }
  710. Update_Camera ();
  711. }
  712. return ;
  713. }
  714. ///////////////////////////////////////////////////////////////
  715. //
  716. // PlayAnimation
  717. //
  718. ///////////////////////////////////////////////////////////////
  719. void
  720. CW3DViewDoc::PlayAnimation
  721. (
  722. RenderObjClass *pCModel,
  723. LPCTSTR pszAnimationName,
  724. bool use_global_reset_flag,
  725. bool allow_reset
  726. )
  727. {
  728. ASSERT (m_pCScene);
  729. ASSERT (pCModel);
  730. ASSERT (pszAnimationName);
  731. // Data OK?
  732. if (m_pCScene &&
  733. pCModel &&
  734. pszAnimationName)
  735. {
  736. // Display this hierarchy on the screen
  737. DisplayObject (pCModel);
  738. // Get an instance of the animation object
  739. SAFE_DELETE (m_pCAnimCombo);
  740. MEMBER_RELEASE (m_pCAnimation);
  741. m_pCAnimation = WW3DAssetManager::Get_Instance()->Get_HAnim (pszAnimationName);
  742. ASSERT (m_pCAnimation);
  743. // Reset the frame counter
  744. m_CurrentFrame = 0;
  745. m_animTime = 0.00F;
  746. if (m_pCRenderObj)
  747. {
  748. // Update the animation frame
  749. m_pCRenderObj->Set_Animation (m_pCAnimation, 0);
  750. CGraphicView *pCGraphicView = GetGraphicView ();
  751. if (pCGraphicView)
  752. {
  753. // Reset the camera to so the user can see
  754. // the whole object
  755. if ((use_global_reset_flag && m_bAutoCameraReset) ||
  756. ((use_global_reset_flag == false) && allow_reset) ||
  757. m_bOneTimeReset) {
  758. pCGraphicView->Reset_Camera_To_Display_Object (*m_pCRenderObj);
  759. m_bOneTimeReset = false;
  760. }
  761. AfxGetMainWnd ()->PostMessage (WM_COMMAND, MAKELPARAM (IDM_ANI_START, 0));
  762. }
  763. }
  764. Update_Camera ();
  765. Play_Animation_Sound ();
  766. }
  767. return ;
  768. }
  769. ///////////////////////////////////////////////////////////////
  770. //
  771. // Play_Animation_Sound
  772. //
  773. ///////////////////////////////////////////////////////////////
  774. void
  775. CW3DViewDoc::Play_Animation_Sound (void)
  776. {
  777. if (m_pCAnimation != NULL) {
  778. CString animation_name = m_pCAnimation->Get_Name ();
  779. //
  780. // Play a sound with the animation
  781. //
  782. const char *separator = ::strchr (animation_name , '.');
  783. if (separator != NULL) {
  784. CString sound_filename = separator + 1;
  785. sound_filename += ".wav";
  786. ::PlaySound (NULL, NULL, SND_PURGE);
  787. ::PlaySound (sound_filename, NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
  788. }
  789. }
  790. return ;
  791. }
  792. ///////////////////////////////////////////////////////////////
  793. //
  794. // PlayAnimation
  795. //
  796. ///////////////////////////////////////////////////////////////
  797. void
  798. CW3DViewDoc::PlayAnimation
  799. (
  800. RenderObjClass *pCModel,
  801. HAnimComboClass *pCAnimCombo,
  802. bool use_global_reset_flag,
  803. bool allow_reset
  804. )
  805. {
  806. ASSERT (m_pCScene);
  807. ASSERT (pCModel);
  808. ASSERT (pCAnimCombo);
  809. // Data OK?
  810. if (m_pCScene &&
  811. pCModel &&
  812. pCAnimCombo)
  813. {
  814. // Display this hierarchy on the screen
  815. DisplayObject (pCModel);
  816. // Get an instance of the animation object
  817. SAFE_DELETE (m_pCAnimCombo);
  818. MEMBER_RELEASE (m_pCAnimation);
  819. m_pCAnimCombo = pCAnimCombo;
  820. m_pCAnimation = m_pCAnimCombo->Get_Motion(0); // ref added by get_motion
  821. ASSERT (m_pCAnimation);
  822. // It will be assumed that every animation in the m_pCAnimCombo
  823. // has the same number of frames and has the same framerate as
  824. // the first animation in the combo (m_pCAnimation).
  825. // Reset the frame counter
  826. m_CurrentFrame = 0;
  827. m_animTime = 0.00F;
  828. if (m_pCRenderObj)
  829. {
  830. // Update the animation frame
  831. for (int i = 0; i < m_pCAnimCombo->Get_Num_Anims(); i++)
  832. m_pCAnimCombo->Set_Frame(i, 0.0f);
  833. m_pCRenderObj->Set_Animation(m_pCAnimCombo);
  834. CGraphicView *pCGraphicView = GetGraphicView ();
  835. if (pCGraphicView)
  836. {
  837. // Reset the camera to so the user can see
  838. // the whole object
  839. if ((use_global_reset_flag && m_bAutoCameraReset) ||
  840. ((use_global_reset_flag == false) && allow_reset) ||
  841. m_bOneTimeReset) {
  842. pCGraphicView->Reset_Camera_To_Display_Object (*m_pCRenderObj);
  843. m_bOneTimeReset = false;
  844. }
  845. AfxGetMainWnd ()->PostMessage (WM_COMMAND, MAKELPARAM (IDM_ANI_START, 0));
  846. }
  847. }
  848. Update_Camera ();
  849. Play_Animation_Sound ();
  850. }
  851. return ;
  852. }
  853. ////////////////////////////////////////////////////////////////////////////
  854. //
  855. // Get_Camera_Transform
  856. //
  857. ////////////////////////////////////////////////////////////////////////////
  858. bool
  859. Get_Camera_Transform (RenderObjClass *render_obj, Matrix3D &tm)
  860. {
  861. bool retval = false;
  862. if (render_obj != NULL) {
  863. for (int index = 0; (index < render_obj->Get_Num_Sub_Objects ()) && !retval; index ++) {
  864. RenderObjClass *psub_obj = render_obj->Get_Sub_Object (index);
  865. if (psub_obj != NULL) {
  866. retval = Get_Camera_Transform (psub_obj, tm);
  867. }
  868. MEMBER_RELEASE (psub_obj);
  869. }
  870. if (!retval) {
  871. int index = render_obj->Get_Bone_Index ("CAMERA");
  872. if (index > 0) {
  873. tm = render_obj->Get_Bone_Transform (index);
  874. retval = true;
  875. }
  876. }
  877. }
  878. return retval;
  879. }
  880. ///////////////////////////////////////////////////////////////
  881. //
  882. // Update_Camera
  883. //
  884. ///////////////////////////////////////////////////////////////
  885. void
  886. CW3DViewDoc::Update_Camera (void)
  887. {
  888. // Should we update the camera's position as well?
  889. if (m_bAnimateCamera && m_pCRenderObj != NULL) {
  890. Matrix3D transform (1);
  891. if (Get_Camera_Transform (m_pCRenderObj, transform)) {
  892. // Convert the bone's transform into a camera transform
  893. //Matrix3D transform = m_pCRenderObj->Get_Bone_Transform (index);
  894. Matrix3D cam_transform (Vector3 (0, -1, 0), Vector3 (0, 0, 1), Vector3 (-1, 0, 0), Vector3 (0, 0, 0));
  895. Matrix3D new_transform = transform * cam_transform;
  896. // Pass the new transform onto the camera
  897. CameraClass *pcamera = GetGraphicView()->GetCamera ();
  898. pcamera->Set_Transform (new_transform);
  899. }
  900. }
  901. return ;
  902. }
  903. ///////////////////////////////////////////////////////////////
  904. //
  905. // UpdateFrame
  906. //
  907. ///////////////////////////////////////////////////////////////
  908. void
  909. CW3DViewDoc::UpdateFrame (float relativeTimeSlice)
  910. {
  911. if (m_pCRenderObj && m_pCAnimation) {
  912. int total_frames = m_pCAnimation->Get_Num_Frames ();
  913. float frame_rate = m_pCAnimation->Get_Frame_Rate ();
  914. float loop_time = ((float)(total_frames-1)) / frame_rate;
  915. //
  916. // Update the total elapsed animation time
  917. //
  918. m_animTime += relativeTimeSlice;
  919. if (m_animTime > loop_time) {
  920. m_animTime -= loop_time;
  921. }
  922. // Adjust the current frame counter
  923. m_CurrentFrame = (frame_rate * m_animTime);
  924. //
  925. // Update the status bar on the main window
  926. //
  927. float anim_speed = ::Get_Graphic_View ()->GetAnimationSpeed ();
  928. ((CMainFrame *)::AfxGetMainWnd ())->UpdateFrameCount (m_CurrentFrame, total_frames - 1, frame_rate * anim_speed);
  929. if (m_pCAnimCombo) {
  930. //
  931. // Update the animation frame for all anims in the combo.
  932. //
  933. for (int i = 0; i < m_pCAnimCombo->Get_Num_Anims(); i++) {
  934. m_pCAnimCombo->Set_Frame(i, m_CurrentFrame);
  935. }
  936. m_pCRenderObj->Set_Animation (m_pCAnimCombo);
  937. } else if (m_bAnimBlend) {
  938. m_pCRenderObj->Set_Animation (m_pCAnimation, m_CurrentFrame);
  939. } else {
  940. m_pCRenderObj->Set_Animation (m_pCAnimation, (int)m_CurrentFrame);
  941. }
  942. Update_Camera ();
  943. }
  944. return ;
  945. }
  946. ///////////////////////////////////////////////////////////////
  947. //
  948. // GetDataTreeView
  949. //
  950. ///////////////////////////////////////////////////////////////
  951. CDataTreeView *
  952. CW3DViewDoc::GetDataTreeView (void)
  953. {
  954. CDataTreeView *pCDataTreeView = NULL;
  955. // Get a pointer to the main window
  956. CMainFrame *pCMainWnd = (CMainFrame *)::AfxGetMainWnd ();
  957. if (pCMainWnd)
  958. {
  959. // Get the pane from the main window
  960. pCDataTreeView = (CDataTreeView *)pCMainWnd->GetPane (0, 0);
  961. }
  962. // Return a pointer to the tree view
  963. return pCDataTreeView;
  964. }
  965. ///////////////////////////////////////////////////////////////
  966. //
  967. // GetGraphicView
  968. //
  969. ///////////////////////////////////////////////////////////////
  970. CGraphicView *
  971. CW3DViewDoc::GetGraphicView (void)
  972. {
  973. CGraphicView *pCGrephicView = NULL;
  974. // Get a pointer to the main window
  975. CMainFrame *pCMainWnd = (CMainFrame *)::AfxGetMainWnd ();
  976. if (pCMainWnd)
  977. {
  978. // Get the pane from the main window
  979. pCGrephicView = (CGraphicView *)pCMainWnd->GetPane (0, 1);
  980. }
  981. // Return a pointer to the graphic view
  982. return pCGrephicView;
  983. }
  984. ///////////////////////////////////////////////////////////////
  985. //
  986. // GenerateLOD
  987. //
  988. ///////////////////////////////////////////////////////////////
  989. HLodPrototypeClass *
  990. CW3DViewDoc::GenerateLOD
  991. (
  992. LPCTSTR pszLODBaseName,
  993. LOD_NAMING_TYPE type
  994. )
  995. {
  996. // Assume failure
  997. HLodPrototypeClass *plod_prototype = NULL;
  998. // Get an iterator from the asset manager that we can
  999. // use to enumerate the currently loaded assets
  1000. RenderObjIterator *pObjEnum = WW3DAssetManager::Get_Instance()->Create_Render_Obj_Iterator ();
  1001. ASSERT (pObjEnum);
  1002. if (pObjEnum)
  1003. {
  1004. int lod_count = 0;
  1005. int iStartingIndex = 0xFFFF;
  1006. char starting_char = 'Z';
  1007. // Loop through all the assets in the manager looking for hierarchies that match the
  1008. // naming convention
  1009. for (pObjEnum->First ();
  1010. pObjEnum->Is_Done () == FALSE;
  1011. pObjEnum->Next ()) {
  1012. LPCTSTR pszItemName = pObjEnum->Current_Item_Name ();
  1013. // Is this a hierarchy?
  1014. if (WW3DAssetManager::Get_Instance()->Render_Obj_Exists (pszItemName) &&
  1015. (pObjEnum->Current_Item_Class_ID () == RenderObjClass::CLASSID_HLOD)) {
  1016. if (Is_Model_Part_of_LOD (pszItemName, pszLODBaseName, type)) {
  1017. lod_count ++;
  1018. if (type == TYPE_COMMANDO) {
  1019. iStartingIndex = min (iStartingIndex, ::atoi (&pszItemName[::lstrlen (pszItemName)-1]));
  1020. } else {
  1021. starting_char = min (starting_char, (char)::toupper (pszItemName[::lstrlen (pszItemName)-1]));
  1022. }
  1023. }
  1024. }
  1025. }
  1026. // Create an array of LOD models
  1027. RenderObjClass **plod_array = new RenderObjClass *[lod_count];
  1028. ASSERT (plod_array != NULL);
  1029. if (plod_array != NULL) {
  1030. // Loop through all the levels-of-detail and add them to our array
  1031. for (int lod_index = 0; lod_index < lod_count; lod_index ++) {
  1032. CString lod_name;
  1033. if (type == TYPE_COMMANDO) {
  1034. lod_name.Format ("%sL%d", pszLODBaseName, iStartingIndex + lod_index);
  1035. } else {
  1036. lod_name.Format ("%s%c", pszLODBaseName, starting_char++);
  1037. }
  1038. // Add this lod to the array in reverse order (LOD 0 is the lowest-level LOD)
  1039. plod_array[lod_count - (lod_index+1)] = WW3DAssetManager::Get_Instance ()->Create_Render_Obj (lod_name);
  1040. }
  1041. // Create a new HLod prototype from the provided lod array
  1042. HLodClass *pnew_lod = new HLodClass (pszLODBaseName, plod_array, lod_count);
  1043. HLodDefClass *pdefinition = new HLodDefClass (*pnew_lod);
  1044. plod_prototype = new HLodPrototypeClass (pdefinition);
  1045. MEMBER_RELEASE (pnew_lod);
  1046. // Loop through all the LOD definitions and free their names
  1047. for (lod_index = 0; lod_index < lod_count; lod_index ++) {
  1048. MEMBER_RELEASE (plod_array[lod_index]);
  1049. }
  1050. // Free the LOD definition array
  1051. SAFE_DELETE_ARRAY (plod_array);
  1052. }
  1053. SAFE_DELETE (pObjEnum);
  1054. }
  1055. // Return the LOD prototype to the caller
  1056. return plod_prototype;
  1057. }
  1058. ///////////////////////////////////////////////////////////////
  1059. //
  1060. // SetBackgroundBMP
  1061. //
  1062. ///////////////////////////////////////////////////////////////
  1063. void
  1064. CW3DViewDoc::SetBackgroundBMP (LPCTSTR pszBackgroundBMP)
  1065. {
  1066. ASSERT (m_pC2DScene);
  1067. if (m_pC2DScene)
  1068. {
  1069. // Remove the old background BMP if there was one.
  1070. if (m_pCBackgroundBMP)
  1071. {
  1072. // Remove the background BMP from the scene
  1073. // and release its pointer
  1074. m_pCBackgroundBMP->Remove ();
  1075. m_pCBackgroundBMP->Release_Ref ();
  1076. m_pCBackgroundBMP = NULL;
  1077. }
  1078. // Is this a new background BMP?
  1079. if (pszBackgroundBMP &&
  1080. (m_stringBackgroundBMP.CompareNoCase (pszBackgroundBMP) != 0))
  1081. {
  1082. // Create a new instance of the BMP object to use
  1083. m_pCBackgroundBMP = new Bitmap2DObjClass (pszBackgroundBMP, 0.5F, 0.5F, TRUE, FALSE);
  1084. // Were we successful in creating the bitmap object?
  1085. ASSERT (m_pCBackgroundBMP);
  1086. if (m_pCBackgroundBMP)
  1087. {
  1088. // Add the object to the scene
  1089. m_pC2DScene->Add_Render_Object (m_pCBackgroundBMP);
  1090. }
  1091. }
  1092. // Remember what our current background BMP is
  1093. m_stringBackgroundBMP = pszBackgroundBMP;
  1094. }
  1095. return ;
  1096. }
  1097. ///////////////////////////////////////////////////////////////
  1098. //
  1099. // LoadSettings
  1100. //
  1101. ///////////////////////////////////////////////////////////////
  1102. BOOL
  1103. CW3DViewDoc::LoadSettings (LPCTSTR filename)
  1104. {
  1105. // Assume failure
  1106. BOOL bReturn = FALSE;
  1107. // Params OK?
  1108. ASSERT (filename != NULL);
  1109. if (filename != NULL) {
  1110. // Open the INI file
  1111. FileClass * pini_file = _TheFileFactory->Get_File (filename);
  1112. INIClass ini_obj (*pini_file);
  1113. CGraphicView *graphic_view = GetGraphicView ();
  1114. Vector3 color;
  1115. //
  1116. // Ambient light color
  1117. //
  1118. if (ini_obj.Is_Present ("Settings", "AmbientLightR") &&
  1119. ini_obj.Is_Present ("Settings", "AmbientLightG") &&
  1120. ini_obj.Is_Present ("Settings", "AmbientLightB")) {
  1121. // Read the settings from,the INI file
  1122. color.X = ini_obj.Get_Float ("Settings", "AmbientLightR");
  1123. color.Y = ini_obj.Get_Float ("Settings", "AmbientLightG");
  1124. color.Z = ini_obj.Get_Float ("Settings", "AmbientLightB");
  1125. // Pass the ambient light color onto the scene
  1126. m_pCScene->Set_Ambient_Light (color);
  1127. }
  1128. //
  1129. // Scene light color
  1130. //
  1131. if (ini_obj.Is_Present ("Settings", "SceneLightR") &&
  1132. ini_obj.Is_Present ("Settings", "SceneLightG") &&
  1133. ini_obj.Is_Present ("Settings", "SceneLightB")) {
  1134. // Read the settings from,the INI file
  1135. color.X = ini_obj.Get_Float ("Settings", "SceneLightR");
  1136. color.Y = ini_obj.Get_Float ("Settings", "SceneLightG");
  1137. color.Z = ini_obj.Get_Float ("Settings", "SceneLightB");
  1138. // Pass the scene light color onto the light
  1139. m_pCSceneLight->Set_Diffuse (color);
  1140. m_pCSceneLight->Set_Specular (color);
  1141. }
  1142. //
  1143. // Scene light orientation
  1144. //
  1145. if (ini_obj.Is_Present ("Settings", "SceneLightX") &&
  1146. ini_obj.Is_Present ("Settings", "SceneLightY") &&
  1147. ini_obj.Is_Present ("Settings", "SceneLightZ") &&
  1148. ini_obj.Is_Present ("Settings", "SceneLightW")) {
  1149. // Read the settings from,the INI file
  1150. Quaternion orientation;
  1151. orientation.X = ini_obj.Get_Float ("Settings", "SceneLightX");
  1152. orientation.Y = ini_obj.Get_Float ("Settings", "SceneLightY");
  1153. orientation.Z = ini_obj.Get_Float ("Settings", "SceneLightZ");
  1154. orientation.W = ini_obj.Get_Float ("Settings", "SceneLightW");
  1155. // Get the light's transform and inverse transform
  1156. Vector3 obj_pos = graphic_view->Get_Object_Center ();
  1157. Vector3 light_pos = m_pCSceneLight->Get_Position ();
  1158. float distance = (light_pos - obj_pos).Length ();
  1159. // Move the light to the object's center, perform the rotation, and
  1160. Matrix3D light_tm (1);
  1161. light_tm.Set_Translation (obj_pos);
  1162. Matrix3D::Multiply (light_tm, Build_Matrix3D (orientation), &light_tm);
  1163. light_tm.Translate (Vector3 (0, 0, distance));
  1164. // Pass the new transform onto the light
  1165. RenderObjClass *pLightMesh = graphic_view->Get_Light_Mesh ();
  1166. pLightMesh->Set_Transform (light_tm);
  1167. m_pCSceneLight->Set_Transform (light_tm);
  1168. }
  1169. //
  1170. // Scene light distance, intensity, and attenuation
  1171. //
  1172. if (ini_obj.Is_Present ("Settings", "SceneLightDistance") &&
  1173. ini_obj.Is_Present ("Settings", "SceneLightIntensity") &&
  1174. ini_obj.Is_Present ("Settings", "SceneLightAttenStart") &&
  1175. ini_obj.Is_Present ("Settings", "SceneLightAttenEnd") &&
  1176. ini_obj.Is_Present ("Settings", "SceneLightAttenOn")) {
  1177. // Read the settings from,the INI file
  1178. float distance = ini_obj.Get_Float ("Settings", "SceneLightDistance");
  1179. float intensity = ini_obj.Get_Float ("Settings", "SceneLightIntensity");
  1180. float start = ini_obj.Get_Float ("Settings", "SceneLightAttenStart");
  1181. float end = ini_obj.Get_Float ("Settings", "SceneLightAttenEnd");
  1182. int atten_on = ini_obj.Get_Int ("Settings", "SceneLightAttenOn");
  1183. // Pass the intensity and attenuation settings onto the light
  1184. m_pCSceneLight->Set_Intensity (intensity);
  1185. m_pCSceneLight->Set_Far_Attenuation_Range (start, end);
  1186. m_pCSceneLight->Set_Flag (LightClass::FAR_ATTENUATION, (atten_on == 1));
  1187. // Get the position of the light and the displayed object
  1188. Vector3 obj_pos = graphic_view->Get_Object_Center ();
  1189. Vector3 light_pos = m_pCSceneLight->Get_Position ();
  1190. Vector3 new_pos = (light_pos - obj_pos);
  1191. new_pos.Normalize ();
  1192. new_pos = new_pos * distance;
  1193. // Pass the new position onto the light
  1194. RenderObjClass *pLightMesh = graphic_view->Get_Light_Mesh ();
  1195. pLightMesh->Set_Position (new_pos);
  1196. m_pCSceneLight->Set_Position (new_pos);
  1197. }
  1198. //
  1199. // Background color
  1200. //
  1201. if (ini_obj.Is_Present ("Settings", "BackgroundR") &&
  1202. ini_obj.Is_Present ("Settings", "BackgroundG") &&
  1203. ini_obj.Is_Present ("Settings", "BackgroundB")) {
  1204. // Read the settings from,the INI file
  1205. color.X = ini_obj.Get_Float ("Settings", "BackgroundR");
  1206. color.Y = ini_obj.Get_Float ("Settings", "BackgroundG");
  1207. color.Z = ini_obj.Get_Float ("Settings", "BackgroundB");
  1208. // Record the background color for later use
  1209. SetBackgroundColor (color);
  1210. }
  1211. //
  1212. // Background bitmap
  1213. //
  1214. if (ini_obj.Is_Present ("Settings", "BackgroundBMP")) {
  1215. // Load this background BMP
  1216. TCHAR bmp_filename[MAX_PATH];
  1217. ini_obj.Get_String ("Settings", "BackgroundBMP", "", bmp_filename, sizeof (bmp_filename));
  1218. SetBackgroundBMP (bmp_filename);
  1219. }
  1220. //
  1221. // Fog Settings
  1222. //
  1223. if (ini_obj.Is_Present ("Settings", "FogEnabled")) {
  1224. bool enable = ini_obj.Get_Bool ("Settings", "FogEnabled");
  1225. EnableFog(enable);
  1226. }
  1227. // Close the INI file
  1228. _TheFileFactory->Return_File (pini_file);
  1229. }
  1230. // Return the TRUE/FALSE result code
  1231. return bReturn;
  1232. }
  1233. ///////////////////////////////////////////////////////////////
  1234. //
  1235. // SaveSettings
  1236. //
  1237. ///////////////////////////////////////////////////////////////
  1238. BOOL
  1239. CW3DViewDoc::SaveSettings
  1240. (
  1241. LPCTSTR pszFilename,
  1242. DWORD dwSettingsMask
  1243. )
  1244. {
  1245. // Assume failure
  1246. BOOL bReturn = FALSE;
  1247. ASSERT (pszFilename);
  1248. ASSERT (dwSettingsMask != 0L);
  1249. ASSERT (m_pCScene);
  1250. // Is the filename OK?
  1251. HANDLE hFile = ::CreateFile (pszFilename,
  1252. 0,
  1253. 0,
  1254. NULL,
  1255. OPEN_ALWAYS,
  1256. 0L,
  1257. NULL);
  1258. ASSERT (hFile != NULL);
  1259. if (hFile == NULL)
  1260. {
  1261. // Invalid file, let the user know
  1262. ::AfxGetMainWnd ()->MessageBox ("Unable to open file for writing. Please select another filename.", "File Error", MB_ICONERROR | MB_OK);
  1263. }
  1264. else if (pszFilename &&
  1265. (dwSettingsMask != 0L) &&
  1266. (m_pCScene != NULL))
  1267. {
  1268. CString stringCompleteFilename = pszFilename;
  1269. // Does this filename contain a path?
  1270. if (::strrchr (pszFilename, '\\') == NULL)
  1271. {
  1272. // Add the current directories path to the filename
  1273. TCHAR szPath[MAX_PATH] = { 0 };
  1274. ::GetCurrentDirectory (sizeof (szPath), szPath);
  1275. if (szPath[::lstrlen (szPath)-1] != '\\')
  1276. {
  1277. // Ensure the path is directory delimited
  1278. ::strcat (szPath, "\\");
  1279. }
  1280. // Prepend the filename with its new path
  1281. stringCompleteFilename = CString (szPath) + stringCompleteFilename;
  1282. }
  1283. // Should we save light settings?
  1284. if (dwSettingsMask & SAVE_SETTINGS_LIGHT)
  1285. {
  1286. Vector3 colorSettings = m_pCScene->Get_Ambient_Light ();
  1287. // Write the 'Red' component out to the file
  1288. CString stringValue;
  1289. stringValue.Format ("%f", colorSettings.X);
  1290. ::WritePrivateProfileString ("Settings",
  1291. "AmbientLightR",
  1292. stringValue,
  1293. (LPCTSTR)stringCompleteFilename);
  1294. // Write the 'Green' component out to the file
  1295. stringValue.Format ("%f", colorSettings.Y);
  1296. ::WritePrivateProfileString ("Settings",
  1297. "AmbientLightG",
  1298. stringValue,
  1299. (LPCTSTR)stringCompleteFilename);
  1300. // Write the 'Blue' component out to the file
  1301. stringValue.Format ("%f", colorSettings.Z);
  1302. ::WritePrivateProfileString ("Settings",
  1303. "AmbientLightB",
  1304. stringValue,
  1305. (LPCTSTR)stringCompleteFilename);
  1306. m_pCSceneLight->Get_Diffuse (&colorSettings);
  1307. // Write the 'Red' component out to the file
  1308. stringValue.Format ("%f", colorSettings.X);
  1309. ::WritePrivateProfileString ("Settings",
  1310. "SceneLightR",
  1311. stringValue,
  1312. (LPCTSTR)stringCompleteFilename);
  1313. // Write the 'Green' component out to the file
  1314. stringValue.Format ("%f", colorSettings.Y);
  1315. ::WritePrivateProfileString ("Settings",
  1316. "SceneLightG",
  1317. stringValue,
  1318. (LPCTSTR)stringCompleteFilename);
  1319. // Write the 'Blue' component out to the file
  1320. stringValue.Format ("%f", colorSettings.Z);
  1321. ::WritePrivateProfileString ("Settings",
  1322. "SceneLightB",
  1323. stringValue,
  1324. (LPCTSTR)stringCompleteFilename);
  1325. Matrix3D transform = m_pCSceneLight->Get_Transform ();
  1326. Quaternion orientation = ::Build_Quaternion (transform);
  1327. // Write the x-position out to the file
  1328. stringValue.Format ("%f", orientation.X);
  1329. ::WritePrivateProfileString ("Settings",
  1330. "SceneLightX",
  1331. stringValue,
  1332. (LPCTSTR)stringCompleteFilename);
  1333. // Write the y-position out to the file
  1334. stringValue.Format ("%f", orientation.Y);
  1335. ::WritePrivateProfileString ("Settings",
  1336. "SceneLightY",
  1337. stringValue,
  1338. (LPCTSTR)stringCompleteFilename);
  1339. // Write the z-position out to the file
  1340. stringValue.Format ("%f", orientation.Z);
  1341. ::WritePrivateProfileString ("Settings",
  1342. "SceneLightZ",
  1343. stringValue,
  1344. (LPCTSTR)stringCompleteFilename);
  1345. // Write the w-position out to the file
  1346. stringValue.Format ("%f", orientation.W);
  1347. ::WritePrivateProfileString ("Settings",
  1348. "SceneLightW",
  1349. stringValue,
  1350. (LPCTSTR)stringCompleteFilename);
  1351. // Get the light's transform and inverse transform
  1352. CGraphicView *pCGraphicView = GetGraphicView ();
  1353. Vector3 obj_pos = pCGraphicView->Get_Object_Center ();
  1354. Vector3 light_pos = m_pCSceneLight->Get_Position ();
  1355. float distance = (light_pos - obj_pos).Length ();
  1356. // Write the distance out to the file
  1357. stringValue.Format ("%f", distance);
  1358. ::WritePrivateProfileString ("Settings",
  1359. "SceneLightDistance",
  1360. stringValue,
  1361. (LPCTSTR)stringCompleteFilename);
  1362. // Write the intensity out to the file
  1363. float intensity = m_pCSceneLight->Get_Intensity ();
  1364. stringValue.Format ("%f", intensity);
  1365. ::WritePrivateProfileString ("Settings",
  1366. "SceneLightIntensity",
  1367. stringValue,
  1368. (LPCTSTR)stringCompleteFilename);
  1369. // Write the start attenuation out to the file
  1370. double start = 0;
  1371. double end = 0;
  1372. m_pCSceneLight->Get_Far_Attenuation_Range (start, end);
  1373. stringValue.Format ("%f", start);
  1374. ::WritePrivateProfileString ("Settings",
  1375. "SceneLightAttenStart",
  1376. stringValue,
  1377. (LPCTSTR)stringCompleteFilename);
  1378. // Write the end attenuation out to the file
  1379. stringValue.Format ("%f", end);
  1380. ::WritePrivateProfileString ("Settings",
  1381. "SceneLightAttenEnd",
  1382. stringValue,
  1383. (LPCTSTR)stringCompleteFilename);
  1384. // Write the end attenuation out to the file
  1385. BOOL atten_on = m_pCSceneLight->Get_Flag (LightClass::FAR_ATTENUATION);
  1386. stringValue.Format ("%d", atten_on);
  1387. ::WritePrivateProfileString ("Settings",
  1388. "SceneLightAttenOn",
  1389. stringValue,
  1390. (LPCTSTR)stringCompleteFilename);
  1391. }
  1392. // Should we save background settings?
  1393. if (dwSettingsMask & SAVE_SETTINGS_BACK)
  1394. {
  1395. // Write the 'Red' component out to the file
  1396. CString stringValue;
  1397. stringValue.Format ("%f", m_backgroundColor.X);
  1398. ::WritePrivateProfileString ("Settings",
  1399. "BackgroundR",
  1400. stringValue,
  1401. (LPCTSTR)stringCompleteFilename);
  1402. // Write the 'Green' component out to the file
  1403. stringValue.Format ("%f", m_backgroundColor.Y);
  1404. ::WritePrivateProfileString ("Settings",
  1405. "BackgroundG",
  1406. stringValue,
  1407. (LPCTSTR)stringCompleteFilename);
  1408. // Write the 'Blue' component out to the file
  1409. stringValue.Format ("%f", m_backgroundColor.Z);
  1410. ::WritePrivateProfileString ("Settings",
  1411. "BackgroundB",
  1412. stringValue,
  1413. (LPCTSTR)stringCompleteFilename);
  1414. // Write the BMP filename out to the profile
  1415. ::WritePrivateProfileString ("Settings",
  1416. "BackgroundBMP",
  1417. (LPCTSTR)m_stringBackgroundBMP,
  1418. (LPCTSTR)stringCompleteFilename);
  1419. // Write the fog settings out to the file.
  1420. ::WritePrivateProfileString("Settings",
  1421. "FogEnabled",
  1422. IsFogEnabled() ? "true" : "false",
  1423. (LPCTSTR)stringCompleteFilename);
  1424. }
  1425. // Should we save camera settings?
  1426. if (dwSettingsMask & SAVE_SETTINGS_CAMERA)
  1427. {
  1428. }
  1429. // Success!
  1430. bReturn = TRUE;
  1431. }
  1432. // Return the TRUE/FALSE result code
  1433. return bReturn;
  1434. }
  1435. ///////////////////////////////////////////////////////////////
  1436. //
  1437. // Save_Selected_LOD
  1438. //
  1439. ///////////////////////////////////////////////////////////////
  1440. bool
  1441. CW3DViewDoc::Save_Selected_LOD (void)
  1442. {
  1443. // Assume failure
  1444. bool retval = false;
  1445. // Is this an emitter?
  1446. if ((m_pCRenderObj != NULL) &&
  1447. m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_HLOD) {
  1448. // Build the default filename from the name of the LOD
  1449. CString default_filename = GetDataTreeView ()->GetCurrentSelectionName ();
  1450. default_filename += ".w3d";
  1451. RestrictedFileDialogClass dialog (FALSE,
  1452. ".w3d",
  1453. (LPCTSTR)default_filename,
  1454. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  1455. "Westwood 3D Files (*.w3d)|*.~xyzabc||",
  1456. AfxGetMainWnd ());
  1457. // Ask the user what filename they wish to save as.
  1458. dialog.m_ofn.lpstrTitle = "Export LOD";
  1459. if (dialog.DoModal () == IDOK) {
  1460. // Save the LOD to the requested file
  1461. retval = Save_Current_LOD (dialog.GetPathName ());
  1462. }
  1463. }
  1464. // Return the true/false result code
  1465. return retval;
  1466. }
  1467. ///////////////////////////////////////////////////////////////
  1468. //
  1469. // Save_Current_LOD
  1470. //
  1471. ///////////////////////////////////////////////////////////////
  1472. bool
  1473. CW3DViewDoc::Save_Current_LOD (const CString &filename)
  1474. {
  1475. // Assume failure
  1476. bool retval = false;
  1477. // Get the prototype for this aggregate
  1478. HLodPrototypeClass *proto = NULL;
  1479. proto = (HLodPrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pCRenderObj->Get_Name ());
  1480. ASSERT (proto != NULL);
  1481. if (proto != NULL) {
  1482. // Get the definition from the prototype
  1483. HLodDefClass *pdefinition = proto->Get_Definition ();
  1484. ASSERT (pdefinition != NULL);
  1485. if (pdefinition != NULL) {
  1486. // Get a file object for the new file
  1487. FileClass *pfile = _TheFileFactory->Get_File (filename);
  1488. if (pfile) {
  1489. // Open the file for writing
  1490. pfile->Open (FileClass::WRITE);
  1491. // Save the definition to the file
  1492. ChunkSaveClass save_chunk (pfile);
  1493. retval = (pdefinition->Save (save_chunk) == WW3D_ERROR_OK);
  1494. // Close the file
  1495. pfile->Close ();
  1496. _TheFileFactory->Return_File (pfile);
  1497. }
  1498. }
  1499. }
  1500. // Return the true/false result code
  1501. return retval;
  1502. }
  1503. ///////////////////////////////////////////////////////////////
  1504. //
  1505. // SetBackgroundObject
  1506. //
  1507. ///////////////////////////////////////////////////////////////
  1508. void
  1509. CW3DViewDoc::SetBackgroundObject (LPCTSTR pszBackgroundObjectName)
  1510. {
  1511. // State valid?
  1512. ASSERT (m_pCBackObjectScene);
  1513. ASSERT (m_pCBackObjectCamera);
  1514. if (m_pCBackObjectScene && m_pCBackObjectCamera)
  1515. {
  1516. // Did we have an old background object we needed to remove?
  1517. if (m_pCBackgroundObject)
  1518. {
  1519. // Remove the object from the scene
  1520. m_pCBackgroundObject->Remove ();
  1521. // Free the object
  1522. m_pCBackgroundObject->Release_Ref ();
  1523. m_pCBackgroundObject = NULL;
  1524. }
  1525. if (pszBackgroundObjectName)
  1526. {
  1527. // Create a new instance of the render object to use as the background
  1528. m_pCBackgroundObject = WW3DAssetManager::Get_Instance()->Create_Render_Obj (pszBackgroundObjectName);
  1529. ASSERT (m_pCBackgroundObject);
  1530. if (m_pCBackgroundObject)
  1531. {
  1532. // Place the object at world center
  1533. m_pCBackgroundObject->Set_Position (Vector3 (0.00F, 0.00F, 0.00F));
  1534. // Calculate the depth the camera should be at by the objects bouding sphere
  1535. float cameraDepth = m_pCBackgroundObject->Get_Bounding_Sphere ().Radius * 4.0F;
  1536. CGraphicView *pCGraphicView = GetGraphicView ();
  1537. if (pCGraphicView)
  1538. {
  1539. // Set the camera's rotation
  1540. m_pCBackObjectCamera->Set_Transform (pCGraphicView->GetCamera ()->Get_Transform ());
  1541. }
  1542. // Set the camera's position and depth
  1543. m_pCBackObjectCamera->Set_Position (Vector3 (0.00F, 0.00F, 0.00F));
  1544. //m_pCBackObjectCamera->Set_Depth (cameraDepth);
  1545. m_pCBackObjectCamera->Set_Clip_Planes (1, cameraDepth);
  1546. // Add the background object to the scene
  1547. m_pCBackObjectScene->Add_Render_Object (m_pCBackgroundObject);
  1548. }
  1549. }
  1550. // Remember this for later...
  1551. m_stringBackgroundObject = pszBackgroundObjectName;
  1552. }
  1553. return ;
  1554. }
  1555. ///////////////////////////////////////////////////////////////
  1556. //
  1557. // Remove_Object_From_Scene
  1558. //
  1559. ///////////////////////////////////////////////////////////////
  1560. void
  1561. CW3DViewDoc::Remove_Object_From_Scene (RenderObjClass *prender_obj)
  1562. {
  1563. // If the render object is NULL, then remove the current render object
  1564. if (prender_obj == NULL) {
  1565. prender_obj = m_pCRenderObj;
  1566. }
  1567. // Recursively remove objects from the scene (to make sure we get all particle buffers)
  1568. //for (int index = 0; index < prender_obj->Get_Num_Sub_Objects (); index ++) {
  1569. while (prender_obj->Get_Num_Sub_Objects () > 0) {
  1570. RenderObjClass *psub_obj = prender_obj->Get_Sub_Object (0);
  1571. if (psub_obj != NULL) {
  1572. Remove_Object_From_Scene (psub_obj);
  1573. }
  1574. MEMBER_RELEASE (psub_obj);
  1575. }
  1576. // If this is an emitter, then remove its buffer
  1577. if ((prender_obj != NULL) &&
  1578. prender_obj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
  1579. // Attempt to remove this emitter's buffer
  1580. ((ParticleEmitterClass *)prender_obj)->Stop ();
  1581. ((ParticleEmitterClass *)prender_obj)->Remove_Buffer_From_Scene ();
  1582. ((ParticleEmitterClass *)prender_obj)->Buffer_Scene_Not_Needed ();
  1583. }
  1584. // Remove the render object from the scene (if we have a valid scene)
  1585. if (m_pCScene != NULL) {
  1586. prender_obj->Remove ();
  1587. }
  1588. return ;
  1589. }
  1590. ///////////////////////////////////////////////////////////////
  1591. //
  1592. // Save_Selected_Primitive
  1593. //
  1594. ///////////////////////////////////////////////////////////////
  1595. bool
  1596. CW3DViewDoc::Save_Selected_Primitive (void)
  1597. {
  1598. // Assume failure
  1599. bool retval = false;
  1600. // Is this an emitter?
  1601. if ((m_pCRenderObj != NULL) &&
  1602. (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_SPHERE ||
  1603. m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_RING)) {
  1604. // Build the default filename from the name of the emitter
  1605. CString default_filename = GetDataTreeView ()->GetCurrentSelectionName ();
  1606. default_filename += ".w3d";
  1607. RestrictedFileDialogClass dialog (FALSE,
  1608. ".w3d",
  1609. (LPCTSTR)default_filename,
  1610. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  1611. "Westwood 3D Files (*.w3d)|*.~xyzabc||",
  1612. AfxGetMainWnd ());
  1613. if (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_SPHERE) {
  1614. dialog.m_ofn.lpstrTitle = "Export Sphere";
  1615. } else {
  1616. dialog.m_ofn.lpstrTitle = "Export Ring";
  1617. }
  1618. // Ask the user what filename they wish to save as.
  1619. if (dialog.DoModal () == IDOK) {
  1620. // Save the emitter to the requested file
  1621. if (m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_SPHERE) {
  1622. retval = Save_Current_Sphere (dialog.GetPathName ());
  1623. } else {
  1624. retval = Save_Current_Ring (dialog.GetPathName ());
  1625. }
  1626. }
  1627. }
  1628. // Return the true/false result code
  1629. return retval;
  1630. }
  1631. ///////////////////////////////////////////////////////////////
  1632. //
  1633. // Save_Current_Sphere
  1634. //
  1635. ///////////////////////////////////////////////////////////////
  1636. bool
  1637. CW3DViewDoc::Save_Current_Sphere (const CString &filename)
  1638. {
  1639. // Assume failure
  1640. bool retval = false;
  1641. //
  1642. // Get the prototype for this object
  1643. //
  1644. SpherePrototypeClass *proto = NULL;
  1645. proto = (SpherePrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pCRenderObj->Get_Name ());
  1646. ASSERT (proto != NULL);
  1647. if (proto != NULL) {
  1648. //
  1649. // Get a file object for the new file
  1650. //
  1651. FileClass *file = _TheFileFactory->Get_File (filename);
  1652. if (file) {
  1653. // Open the file for writing
  1654. file->Open (FileClass::WRITE);
  1655. // Save the definition to the file
  1656. ChunkSaveClass csave (file);
  1657. proto->Save (csave);
  1658. retval = true;
  1659. // Close the file
  1660. file->Close ();
  1661. _TheFileFactory->Return_File (file);
  1662. }
  1663. }
  1664. return retval;
  1665. }
  1666. ///////////////////////////////////////////////////////////////
  1667. //
  1668. // Save_Current_Ring
  1669. //
  1670. ///////////////////////////////////////////////////////////////
  1671. bool
  1672. CW3DViewDoc::Save_Current_Ring (const CString &filename)
  1673. {
  1674. // Assume failure
  1675. bool retval = false;
  1676. //
  1677. // Get the prototype for this object
  1678. //
  1679. RingPrototypeClass *proto = NULL;
  1680. proto = (RingPrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pCRenderObj->Get_Name ());
  1681. ASSERT (proto != NULL);
  1682. if (proto != NULL) {
  1683. //
  1684. // Get a file object for the new file
  1685. //
  1686. FileClass *file = _TheFileFactory->Get_File (filename);
  1687. if (file) {
  1688. // Open the file for writing
  1689. file->Open (FileClass::WRITE);
  1690. // Save the definition to the file
  1691. ChunkSaveClass csave (file);
  1692. proto->Save (csave);
  1693. retval = true;
  1694. // Close the file
  1695. file->Close ();
  1696. _TheFileFactory->Return_File (file);
  1697. }
  1698. }
  1699. return retval;
  1700. }
  1701. ///////////////////////////////////////////////////////////////
  1702. //
  1703. // Save_Selected_Emitter
  1704. //
  1705. ///////////////////////////////////////////////////////////////
  1706. bool
  1707. CW3DViewDoc::Save_Selected_Emitter (void)
  1708. {
  1709. // Assume failure
  1710. bool retval = false;
  1711. // Is this an emitter?
  1712. if ((m_pCRenderObj != NULL) &&
  1713. m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
  1714. // Build the default filename from the name of the emitter
  1715. CString default_filename = GetDataTreeView ()->GetCurrentSelectionName ();
  1716. default_filename += ".w3d";
  1717. RestrictedFileDialogClass dialog (FALSE,
  1718. ".w3d",
  1719. (LPCTSTR)default_filename,
  1720. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  1721. "Westwood 3D Files (*.w3d)|*.~xyzabc||",
  1722. AfxGetMainWnd ());
  1723. // Ask the user what filename they wish to save as.
  1724. dialog.m_ofn.lpstrTitle = "Export Emitter";
  1725. if (dialog.DoModal () == IDOK) {
  1726. // Save the emitter to the requested file
  1727. retval = Save_Current_Emitter (dialog.GetPathName ());
  1728. }
  1729. }
  1730. // Return the true/false result code
  1731. return retval;
  1732. }
  1733. ///////////////////////////////////////////////////////////////
  1734. //
  1735. // Save_Current_Emitter
  1736. //
  1737. ///////////////////////////////////////////////////////////////
  1738. bool
  1739. CW3DViewDoc::Save_Current_Emitter (const CString &filename)
  1740. {
  1741. // Assume failure
  1742. bool retval = false;
  1743. // Get the prototype for this aggregate
  1744. ParticleEmitterPrototypeClass *proto = NULL;
  1745. proto = (ParticleEmitterPrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pCRenderObj->Get_Name ());
  1746. ASSERT (proto != NULL);
  1747. if (proto != NULL) {
  1748. // Get the definition from the prototype
  1749. ParticleEmitterDefClass *pdefinition = proto->Get_Definition ();
  1750. ASSERT (pdefinition != NULL);
  1751. if (pdefinition != NULL) {
  1752. // Get a file object for the new file
  1753. FileClass *pfile = _TheFileFactory->Get_File (filename);
  1754. if (pfile) {
  1755. // Open the file for writing
  1756. pfile->Open (FileClass::WRITE);
  1757. // Save the definition to the file
  1758. ChunkSaveClass save_chunk (pfile);
  1759. retval = (pdefinition->Save_W3D (save_chunk) == WW3D_ERROR_OK);
  1760. // Close the file
  1761. pfile->Close ();
  1762. _TheFileFactory->Return_File (pfile);
  1763. }
  1764. }
  1765. }
  1766. // Return the true/false result code
  1767. return retval;
  1768. }
  1769. ///////////////////////////////////////////////////////////////
  1770. //
  1771. // Save_Selected_Sound_Object
  1772. //
  1773. ///////////////////////////////////////////////////////////////
  1774. bool
  1775. CW3DViewDoc::Save_Selected_Sound_Object (void)
  1776. {
  1777. bool retval = false;
  1778. //
  1779. // Is this a sound render object?
  1780. //
  1781. if ((m_pCRenderObj != NULL) &&
  1782. m_pCRenderObj->Class_ID () == RenderObjClass::CLASSID_SOUND)
  1783. {
  1784. //
  1785. // Build the default filename from the name of the emitter
  1786. //
  1787. CString default_filename = GetDataTreeView ()->GetCurrentSelectionName ();
  1788. default_filename += ".w3d";
  1789. RestrictedFileDialogClass dialog (FALSE,
  1790. ".w3d",
  1791. (LPCTSTR)default_filename,
  1792. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  1793. "Westwood 3D Files (*.w3d)|*.~xyzabc||",
  1794. AfxGetMainWnd ());
  1795. //
  1796. // Ask the user what filename they wish to save as.
  1797. //
  1798. dialog.m_ofn.lpstrTitle = "Export Sound Object";
  1799. if (dialog.DoModal () == IDOK) {
  1800. //
  1801. // Save the sound object to the requested file
  1802. //
  1803. retval = Save_Current_Sound_Object (dialog.GetPathName ());
  1804. }
  1805. }
  1806. return retval;
  1807. }
  1808. ///////////////////////////////////////////////////////////////
  1809. //
  1810. // Save_Current_Sound_Object
  1811. //
  1812. ///////////////////////////////////////////////////////////////
  1813. bool
  1814. CW3DViewDoc::Save_Current_Sound_Object (const CString &filename)
  1815. {
  1816. bool retval = false;
  1817. //
  1818. // Get the prototype for this sound object
  1819. //
  1820. SoundRenderObjPrototypeClass *proto = NULL;
  1821. proto = (SoundRenderObjPrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pCRenderObj->Get_Name ());
  1822. ASSERT (proto != NULL);
  1823. if (proto != NULL) {
  1824. //
  1825. // Get the definition from the prototype
  1826. //
  1827. SoundRenderObjDefClass *definition = proto->Peek_Definition ();
  1828. ASSERT (definition != NULL);
  1829. if (definition != NULL) {
  1830. //
  1831. // Get a file object for the new file
  1832. //
  1833. FileClass *file = _TheFileFactory->Get_File (filename);
  1834. if (file) {
  1835. //
  1836. // Open the file for writing
  1837. //
  1838. file->Open (FileClass::WRITE);
  1839. //
  1840. // Save the definition to the file
  1841. //
  1842. ChunkSaveClass csave (file);
  1843. retval = (definition->Save_W3D (csave) == WW3D_ERROR_OK);
  1844. //
  1845. // Close the file
  1846. //
  1847. file->Close ();
  1848. _TheFileFactory->Return_File (file);
  1849. }
  1850. }
  1851. }
  1852. return retval;
  1853. }
  1854. ///////////////////////////////////////////////////////////////
  1855. //
  1856. // Auto_Assign_Bones
  1857. //
  1858. ///////////////////////////////////////////////////////////////
  1859. void
  1860. CW3DViewDoc::Auto_Assign_Bones (void)
  1861. {
  1862. if (m_pCRenderObj != NULL) {
  1863. bool bupdate_prototype = false;
  1864. // Loop through all the bones in this render object
  1865. int bone_count = m_pCRenderObj->Get_Num_Bones ();
  1866. for (int index = 0; index < bone_count; index ++) {
  1867. const char *pbone_name = m_pCRenderObj->Get_Bone_Name (index);
  1868. // Attempt to find a render object with the same name as this bone
  1869. if (WW3DAssetManager::Get_Instance ()->Render_Obj_Exists (pbone_name)) {
  1870. // Add this render object to the bone
  1871. RenderObjClass *prender_obj = WW3DAssetManager::Get_Instance ()->Create_Render_Obj (pbone_name);
  1872. m_pCRenderObj->Add_Sub_Object_To_Bone (prender_obj, index);
  1873. MEMBER_RELEASE (prender_obj);
  1874. bupdate_prototype = true;
  1875. }
  1876. }
  1877. if (bupdate_prototype) {
  1878. Update_Aggregate_Prototype (*m_pCRenderObj);
  1879. }
  1880. }
  1881. return ;
  1882. }
  1883. ///////////////////////////////////////////////////////////////
  1884. //
  1885. // Save_Selected_Aggregate
  1886. //
  1887. ///////////////////////////////////////////////////////////////
  1888. bool
  1889. CW3DViewDoc::Save_Selected_Aggregate (void)
  1890. {
  1891. // Assume failure
  1892. bool retval = false;
  1893. // Do we have a valid render object?
  1894. if (m_pCRenderObj != NULL) {
  1895. // Build the default filename from the name of render object
  1896. CString default_filename = GetDataTreeView ()->GetCurrentSelectionName ();
  1897. default_filename += ".w3d";
  1898. RestrictedFileDialogClass dialog (FALSE,
  1899. ".w3d",
  1900. (LPCTSTR)default_filename,
  1901. OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
  1902. "Westwood 3D Files (*.w3d)|*.~xyzabc||",
  1903. AfxGetMainWnd ());
  1904. // Ask the user what filename they wish to save as.
  1905. dialog.m_ofn.lpstrTitle = "Export Aggregate";
  1906. if (dialog.DoModal () == IDOK) {
  1907. // Save the aggregate to the requested file
  1908. retval = Save_Current_Aggregate (dialog.GetPathName ());
  1909. }
  1910. }
  1911. // Return the true/false result code
  1912. return retval;
  1913. }
  1914. ///////////////////////////////////////////////////////////////
  1915. //
  1916. // Save_Current_Aggregate
  1917. //
  1918. ///////////////////////////////////////////////////////////////
  1919. bool
  1920. CW3DViewDoc::Save_Current_Aggregate (const CString &filename)
  1921. {
  1922. // Assume failure
  1923. bool retval = false;
  1924. // Get the prototype for this aggregate
  1925. AggregatePrototypeClass *proto = NULL;
  1926. proto = (AggregatePrototypeClass *)WW3DAssetManager::Get_Instance ()->Find_Prototype (m_pCRenderObj->Get_Name ());
  1927. ASSERT (proto != NULL);
  1928. if (proto != NULL) {
  1929. // Get the definition from the prototype
  1930. AggregateDefClass *pdefinition = proto->Get_Definition ();
  1931. ASSERT (pdefinition != NULL);
  1932. if (pdefinition != NULL) {
  1933. // Get a file object for the new file
  1934. FileClass *pfile = _TheFileFactory->Get_File (filename);
  1935. if (pfile) {
  1936. // Open the file for writing
  1937. pfile->Open (FileClass::WRITE);
  1938. // Save the definition to the file
  1939. ChunkSaveClass save_chunk (pfile);
  1940. retval = (pdefinition->Save_W3D (save_chunk) == WW3D_ERROR_OK);
  1941. // Close the file
  1942. pfile->Close ();
  1943. _TheFileFactory->Return_File (pfile);
  1944. }
  1945. }
  1946. }
  1947. // Return the true/false result code
  1948. return retval;
  1949. }
  1950. ///////////////////////////////////////////////////////////////
  1951. //
  1952. // Update_Aggregate_Prototype
  1953. //
  1954. ///////////////////////////////////////////////////////////////
  1955. void
  1956. CW3DViewDoc::Update_Aggregate_Prototype (RenderObjClass &render_obj)
  1957. {
  1958. // Build a definition object from the render object
  1959. AggregateDefClass *pdefinition = new AggregateDefClass (render_obj);
  1960. AggregatePrototypeClass *pprototype = new AggregatePrototypeClass (pdefinition);
  1961. // Add this prototype to the asset manager
  1962. WW3DAssetManager::Get_Instance ()->Remove_Prototype (pdefinition->Get_Name ());
  1963. WW3DAssetManager::Get_Instance ()->Add_Prototype (pprototype);
  1964. return ;
  1965. }
  1966. ///////////////////////////////////////////////////////////////
  1967. //
  1968. // Update_LOD_Prototype
  1969. //
  1970. ///////////////////////////////////////////////////////////////
  1971. void
  1972. CW3DViewDoc::Update_LOD_Prototype (HLodClass &hlod)
  1973. {
  1974. // Build a definition object from the render object
  1975. HLodDefClass *pdefinition = new HLodDefClass (hlod);
  1976. HLodPrototypeClass *pprototype = new HLodPrototypeClass (pdefinition);
  1977. // Add this prototype to the asset manager
  1978. WW3DAssetManager::Get_Instance ()->Remove_Prototype (pdefinition->Get_Name ());
  1979. WW3DAssetManager::Get_Instance ()->Add_Prototype (pprototype);
  1980. return ;
  1981. }
  1982. ///////////////////////////////////////////////////////////////
  1983. //
  1984. // Animate_Camera
  1985. //
  1986. ///////////////////////////////////////////////////////////////
  1987. void
  1988. CW3DViewDoc::Animate_Camera (bool banimate)
  1989. {
  1990. m_bAnimateCamera = banimate;
  1991. // Restore the camera if we are done animating it
  1992. if (m_bAnimateCamera == false) {
  1993. ::AfxGetMainWnd ()->SendMessage (WM_COMMAND, MAKEWPARAM (IDM_CAMERA_RESET, 0));
  1994. }
  1995. return ;
  1996. }
  1997. ///////////////////////////////////////////////////////////////
  1998. //
  1999. // Make_Movie
  2000. //
  2001. ///////////////////////////////////////////////////////////////
  2002. void
  2003. CW3DViewDoc::Make_Movie (void)
  2004. {
  2005. // Hide the mouse cursor when we're making a movie.
  2006. bool restore_cursor = Is_Cursor_Shown();
  2007. Show_Cursor(false);
  2008. int i;
  2009. CGraphicView *graphic_view= GetGraphicView ();
  2010. if (m_pCRenderObj && m_pCAnimation) {
  2011. // Get the directory where this executable was run from
  2012. TCHAR filename[MAX_PATH];
  2013. ::GetModuleFileName (NULL, filename, sizeof (filename));
  2014. // Strip the filename from the path
  2015. LPTSTR ppath = ::strrchr (filename, '\\');
  2016. if (ppath != NULL) {
  2017. ppath[0] = 0;
  2018. }
  2019. ::SetCurrentDirectory (filename);
  2020. // Rewind the animation
  2021. if (m_pCAnimCombo)
  2022. {
  2023. for (i = 0; i < m_pCAnimCombo->Get_Num_Anims(); i++)
  2024. m_pCAnimCombo->Set_Frame(i, 0.0f);
  2025. m_pCRenderObj->Set_Animation (m_pCAnimCombo);
  2026. }
  2027. else
  2028. m_pCRenderObj->Set_Animation (m_pCAnimation, (int)0);
  2029. graphic_view->RepaintView (FALSE);
  2030. // Begin our movie
  2031. WW3D::Pause_Movie (true);
  2032. WW3D::Start_Movie_Capture ("Grab", 30);
  2033. WW3D::Pause_Movie (true);
  2034. float frames = m_pCAnimation->Get_Num_Frames ();
  2035. float frame_inc = m_pCAnimation->Get_Frame_Rate () / 30.0F;
  2036. DWORD ticks = 1000 / 30;
  2037. // Loop through all the frames of animation
  2038. for (float frame = 0; frame <= (frames - 1.0F); frame += frame_inc) {
  2039. if (m_pCAnimCombo)
  2040. {
  2041. for (i = 0; i < m_pCAnimCombo->Get_Num_Anims(); i++)
  2042. m_pCAnimCombo->Set_Frame(i, frame);
  2043. m_pCRenderObj->Set_Animation (m_pCAnimCombo);
  2044. }
  2045. else
  2046. m_pCRenderObj->Set_Animation (m_pCAnimation, frame);
  2047. // Should we be updating the camera?
  2048. if (m_bAnimateCamera) {
  2049. int index = m_pCRenderObj->Get_Bone_Index ("CAMERA");
  2050. if (index != -1) {
  2051. // Convert the bone's transform into a camera transform
  2052. Matrix3D transform = m_pCRenderObj->Get_Bone_Transform (index);
  2053. Matrix3D cam_transform (Vector3 (0, -1, 0), Vector3 (0, 0, 1), Vector3 (-1, 0, 0), Vector3 (0, 0, 0));
  2054. Matrix3D new_transform = transform * cam_transform;
  2055. // Pass the new transform onto the camera
  2056. CameraClass *pcamera = GetGraphicView()->GetCamera ();
  2057. pcamera->Set_Transform (new_transform);
  2058. }
  2059. }
  2060. graphic_view->RepaintView (FALSE, ticks);
  2061. graphic_view->RepaintView (FALSE, 1);
  2062. WW3D::Update_Movie_Capture ();
  2063. if (::GetAsyncKeyState (VK_ESCAPE) < 0) {
  2064. break;
  2065. }
  2066. }
  2067. // Stop capturing the movie data
  2068. WW3D::Stop_Movie_Capture ();
  2069. }
  2070. // Restore the mouse cursor to its previous visibility state.
  2071. Show_Cursor(restore_cursor);
  2072. return ;
  2073. }
  2074. ///////////////////////////////////////////////////////////////
  2075. //
  2076. // Build_Emitter_List
  2077. //
  2078. ///////////////////////////////////////////////////////////////
  2079. void
  2080. CW3DViewDoc::Build_Emitter_List
  2081. (
  2082. EmitterInstanceListClass *emitter_list,
  2083. LPCTSTR emitter_name,
  2084. RenderObjClass *render_obj
  2085. )
  2086. {
  2087. //
  2088. // If the render object is NULL, then start from the current render object
  2089. //
  2090. if (render_obj == NULL) {
  2091. render_obj = m_pCRenderObj;
  2092. }
  2093. //
  2094. // Recursively walk through the objects in the scene
  2095. //
  2096. for (int index = 0; index < render_obj->Get_Num_Sub_Objects (); index ++) {
  2097. RenderObjClass *psub_obj = render_obj->Get_Sub_Object (index);
  2098. if (psub_obj != NULL) {
  2099. Build_Emitter_List (emitter_list, emitter_name, psub_obj);
  2100. }
  2101. MEMBER_RELEASE (psub_obj);
  2102. }
  2103. //
  2104. // Is this the emitter we are requesting?
  2105. //
  2106. if ((render_obj != NULL) &&
  2107. (render_obj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) &&
  2108. (::lstrcmpi (emitter_name, render_obj->Get_Name ()) == 0)) {
  2109. emitter_list->Add_Emitter ((ParticleEmitterClass *)render_obj);
  2110. }
  2111. return ;
  2112. }
  2113. ///////////////////////////////////////////////////////////////
  2114. //
  2115. // Show_Cursor
  2116. //
  2117. ///////////////////////////////////////////////////////////////
  2118. void
  2119. CW3DViewDoc::Show_Cursor (bool onoff)
  2120. {
  2121. if (m_pCursor == NULL) {
  2122. Create_Cursor ();
  2123. }
  2124. m_pCursor->Set_Hidden (!onoff);
  2125. return ;
  2126. }
  2127. ///////////////////////////////////////////////////////////////
  2128. //
  2129. // Is_Cursor_Shown
  2130. //
  2131. ///////////////////////////////////////////////////////////////
  2132. bool
  2133. CW3DViewDoc::Is_Cursor_Shown (void) const
  2134. {
  2135. return m_pCursor != NULL && m_pCursor->Is_Not_Hidden_At_All ();
  2136. }
  2137. ///////////////////////////////////////////////////////////////
  2138. //
  2139. // Set_Cursor
  2140. //
  2141. ///////////////////////////////////////////////////////////////
  2142. void
  2143. CW3DViewDoc::Set_Cursor (LPCTSTR resource_name)
  2144. {
  2145. m_pCursor->Set_Texture (::Load_RC_Texture (resource_name));
  2146. return ;
  2147. }
  2148. ///////////////////////////////////////////////////////////////
  2149. //
  2150. // Create_Cursor
  2151. //
  2152. ///////////////////////////////////////////////////////////////
  2153. void
  2154. CW3DViewDoc::Create_Cursor (void)
  2155. {
  2156. if (m_pCursor == NULL) {
  2157. m_pCursor = new ScreenCursorClass;
  2158. m_pCursor->Set_Window (GetGraphicView ()->m_hWnd);
  2159. m_pCursor->Set_Texture (::Load_RC_Texture ("cursor.tga"));
  2160. }
  2161. return ;
  2162. }
  2163. ///////////////////////////////////////////////////////////////
  2164. //
  2165. // Count_Particles
  2166. //
  2167. ///////////////////////////////////////////////////////////////
  2168. int
  2169. CW3DViewDoc::Count_Particles (RenderObjClass *render_obj)
  2170. {
  2171. int count = 0;
  2172. //
  2173. // If the render object is NULL, then start from the current render object
  2174. //
  2175. if (render_obj == NULL) {
  2176. render_obj = m_pCRenderObj;
  2177. }
  2178. //
  2179. // Recursively walk through the subobjects
  2180. //
  2181. if (render_obj != NULL) {
  2182. for (int index = 0; index < render_obj->Get_Num_Sub_Objects (); index ++) {
  2183. RenderObjClass *psub_obj = render_obj->Get_Sub_Object (index);
  2184. if (psub_obj != NULL) {
  2185. count += Count_Particles (psub_obj);
  2186. }
  2187. MEMBER_RELEASE (psub_obj);
  2188. }
  2189. // If this is an emitter, then remove its buffer
  2190. if (render_obj->Class_ID () == RenderObjClass::CLASSID_PARTICLEEMITTER) {
  2191. //
  2192. // Add the number of particles in the buffer to the total
  2193. //
  2194. ParticleEmitterClass *emitter = static_cast<ParticleEmitterClass *> (render_obj);
  2195. ParticleBufferClass *buffer = emitter->Peek_Buffer ();
  2196. if (buffer != NULL) {
  2197. count += buffer->Get_Particle_Count ();
  2198. }
  2199. }
  2200. }
  2201. return count;
  2202. }
  2203. ///////////////////////////////////////////////////////////////
  2204. //
  2205. // Update_Particle_Count
  2206. //
  2207. ///////////////////////////////////////////////////////////////
  2208. void
  2209. CW3DViewDoc::Update_Particle_Count (void)
  2210. {
  2211. int particles = Count_Particles ();
  2212. ((CMainFrame *)::AfxGetMainWnd ())->Update_Particle_Count (particles);
  2213. return ;
  2214. }
  2215. ///////////////////////////////////////////////////////////////
  2216. //
  2217. // Switch_LOD
  2218. //
  2219. ///////////////////////////////////////////////////////////////
  2220. void
  2221. CW3DViewDoc::Switch_LOD (int increment, RenderObjClass *render_obj)
  2222. {
  2223. //
  2224. // If the render object is NULL, then start from the current render object
  2225. //
  2226. if (render_obj == NULL) {
  2227. render_obj = m_pCRenderObj;
  2228. }
  2229. //
  2230. // Recursively walk through the subobjects
  2231. //
  2232. if (render_obj != NULL) {
  2233. for (int index = 0; index < render_obj->Get_Num_Sub_Objects (); index ++) {
  2234. RenderObjClass *psub_obj = render_obj->Get_Sub_Object (index);
  2235. if (psub_obj != NULL) {
  2236. Switch_LOD (increment, psub_obj);
  2237. }
  2238. MEMBER_RELEASE (psub_obj);
  2239. }
  2240. //
  2241. // If this is an HLOD then switch its LOD
  2242. //
  2243. if (render_obj->Class_ID () == RenderObjClass::CLASSID_HLOD) {
  2244. int current_lod = ((HLodClass *)render_obj)->Get_LOD_Level ();
  2245. ((HLodClass *)render_obj)->Set_LOD_Level (current_lod + increment);
  2246. }
  2247. }
  2248. return ;
  2249. }
  2250. ///////////////////////////////////////////////////////////////
  2251. //
  2252. // Toggle_Alternate_Materials
  2253. //
  2254. ///////////////////////////////////////////////////////////////
  2255. void
  2256. CW3DViewDoc::Toggle_Alternate_Materials(RenderObjClass * render_obj)
  2257. {
  2258. //
  2259. // If the render object is NULL, start from the current render object
  2260. //
  2261. if (render_obj == NULL) {
  2262. render_obj = m_pCRenderObj;
  2263. }
  2264. if (render_obj != NULL) {
  2265. //
  2266. // If this is a mesh, toggle the materials
  2267. //
  2268. if (render_obj->Class_ID() == RenderObjClass::CLASSID_MESH) {
  2269. MeshModelClass * mdl = ((MeshClass *)render_obj)->Get_Model();
  2270. mdl->Enable_Alternate_Material_Description(!mdl->Is_Alternate_Material_Description_Enabled());
  2271. }
  2272. //
  2273. // Recurse into any children
  2274. //
  2275. for (int index = 0; index < render_obj->Get_Num_Sub_Objects(); index++) {
  2276. RenderObjClass * sub_obj = render_obj->Get_Sub_Object(index);
  2277. Toggle_Alternate_Materials(sub_obj);
  2278. }
  2279. }
  2280. return;
  2281. }
  2282. ///////////////////////////////////////////////////////////////
  2283. //
  2284. // Lookup_Path
  2285. //
  2286. ///////////////////////////////////////////////////////////////
  2287. bool
  2288. CW3DViewDoc::Lookup_Path (LPCTSTR asset_name, CString &path)
  2289. {
  2290. bool retval = false;
  2291. //
  2292. // Loop over every file we've loaded...
  2293. //
  2294. int counter = m_LoadList.Count ();
  2295. while ((counter --) && !retval) {
  2296. //
  2297. // Does this path contain the W3D this asset came from?
  2298. //
  2299. CString curr_path = m_LoadList[counter];
  2300. CString curr_asset = ::Asset_Name_From_Filename (curr_path);
  2301. if (::lstrcmpi (asset_name, curr_asset) == 0) {
  2302. path = curr_path;
  2303. retval = true;
  2304. }
  2305. }
  2306. return retval;
  2307. }
  2308. ///////////////////////////////////////////////////////////////
  2309. //
  2310. // Copy_Assets_To_Dir
  2311. //
  2312. ///////////////////////////////////////////////////////////////
  2313. void
  2314. CW3DViewDoc::Copy_Assets_To_Dir (LPCTSTR directory)
  2315. {
  2316. CDataTreeView *data_tree = GetDataTreeView ();
  2317. SANITY_CHECK ((m_pCRenderObj != NULL && data_tree != NULL)) {
  2318. return ;
  2319. }
  2320. //
  2321. // Attempt to locate the file this asset came from
  2322. //
  2323. LPCTSTR asset_name = data_tree->GetCurrentSelectionName ();
  2324. CString filename;
  2325. if (Lookup_Path (asset_name, filename)) {
  2326. CString src_path = ::Strip_Filename_From_Path (filename);
  2327. CString dest_path = directory;
  2328. ::Delimit_Path (src_path);
  2329. ::Delimit_Path (dest_path);
  2330. //
  2331. // Get a list of dependent files from the render object
  2332. //
  2333. DynamicVectorClass<StringClass> dependency_list;
  2334. m_pCRenderObj->Build_Dependency_List (dependency_list);
  2335. //
  2336. // Loop over the list of dependent files and copy them
  2337. // each to the destination directory
  2338. //
  2339. DynamicVectorClass<CString> copy_failure_list;
  2340. int counter = dependency_list.Count ();
  2341. while (counter --) {
  2342. //
  2343. // Determine the source and destination filenames
  2344. //
  2345. StringClass filename = dependency_list[counter];
  2346. CString src_filename = src_path + CString (filename);
  2347. CString dest_filename = dest_path + CString (filename);
  2348. //
  2349. // Copy the file
  2350. //
  2351. if (::Copy_File (src_filename, dest_filename, true) == false) {
  2352. copy_failure_list.Add (src_filename);
  2353. }
  2354. }
  2355. //
  2356. // Let the user know if something failed to copy
  2357. //
  2358. if (copy_failure_list.Count () > 0) {
  2359. CString message = "Unable to copy the following files:\r\n\r\n";
  2360. counter = copy_failure_list.Count ();
  2361. while (counter --) {
  2362. message += copy_failure_list[counter];
  2363. message += "\r\n";
  2364. }
  2365. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, message, "Copy Failure", MB_ICONERROR | MB_OK);
  2366. }
  2367. } else {
  2368. //
  2369. // Let the user know if we were unable to find the asset's W3D file
  2370. //
  2371. CString message;
  2372. message.Format ("Unable to find file for asset: %s.", asset_name);
  2373. ::MessageBox (::AfxGetMainWnd ()->m_hWnd, message, "File Not Found", MB_ICONEXCLAMATION | MB_OK);
  2374. }
  2375. return ;
  2376. }
  2377. ///////////////////////////////////////////////////////////////
  2378. //
  2379. // Set_Texture_Path1
  2380. //
  2381. ///////////////////////////////////////////////////////////////
  2382. void
  2383. CW3DViewDoc::Set_Texture_Path1 (LPCTSTR path)
  2384. {
  2385. if (m_TexturePath1.CompareNoCase (path) != 0) {
  2386. //
  2387. // Pass the new search path onto the File Factory
  2388. //
  2389. if (::lstrlen (path) > 0) {
  2390. _TheSimpleFileFactory->Append_Sub_Directory(path);
  2391. }
  2392. m_TexturePath1 = path;
  2393. theApp.WriteProfileString ("Config", "TexturePath1", m_TexturePath1);
  2394. }
  2395. return ;
  2396. }
  2397. ///////////////////////////////////////////////////////////////
  2398. //
  2399. // Set_Texture_Path2
  2400. //
  2401. ///////////////////////////////////////////////////////////////
  2402. void
  2403. CW3DViewDoc::Set_Texture_Path2 (LPCTSTR path)
  2404. {
  2405. if (m_TexturePath2.CompareNoCase (path) != 0) {
  2406. //
  2407. // Pass the new search path onto Surrender
  2408. //
  2409. if (::lstrlen (path) > 0) {
  2410. _TheSimpleFileFactory->Append_Sub_Directory(path);
  2411. }
  2412. m_TexturePath2 = path;
  2413. theApp.WriteProfileString ("Config", "TexturePath2", m_TexturePath2);
  2414. }
  2415. return ;
  2416. }
  2417. ///////////////////////////////////////////////////////////////
  2418. //
  2419. // Import_Facial_Animation
  2420. //
  2421. ///////////////////////////////////////////////////////////////
  2422. void
  2423. CW3DViewDoc::Import_Facial_Animation (const CString &heirarchy_name, const CString &filename)
  2424. {
  2425. //
  2426. // Crate a new text file object that can be used to import the animation
  2427. //
  2428. TextFileClass *anim_desc_file = new TextFileClass (filename);
  2429. if (anim_desc_file->Open () == (int)true) {
  2430. //
  2431. // Create the new animation and import its data from the text file
  2432. //
  2433. HMorphAnimClass *new_anim = new HMorphAnimClass;
  2434. new_anim->Import (heirarchy_name, *anim_desc_file);
  2435. //
  2436. // Give the new animation a name
  2437. //
  2438. CString new_name;
  2439. CString animation_name = ::Asset_Name_From_Filename (filename);
  2440. animation_name.MakeUpper ();
  2441. new_name.Format ("%s.%s", (LPCTSTR)heirarchy_name, (LPCTSTR)animation_name);
  2442. new_anim->Set_Name (new_name);
  2443. //
  2444. // Add this animation to the asset manager
  2445. //
  2446. WW3DAssetManager::Get_Instance ()->Add_Anim (new_anim);
  2447. //
  2448. // Save this animation to disk
  2449. //
  2450. CString directory = ::Strip_Filename_From_Path (filename);
  2451. ::Delimit_Path (directory);
  2452. CString path = directory + animation_name + CString (".w3d");
  2453. RawFileClass *animation_file = new RawFileClass (path);
  2454. if ( animation_file->Create () == (int)true &&
  2455. animation_file->Open (FileClass::WRITE) == (int)true)
  2456. {
  2457. ChunkSaveClass csave (animation_file);
  2458. new_anim->Save_W3D (csave);
  2459. animation_file->Close ();
  2460. }
  2461. SAFE_DELETE (animation_file);
  2462. //
  2463. // Cleanup
  2464. //
  2465. anim_desc_file->Close ();
  2466. MEMBER_RELEASE (new_anim);
  2467. SAFE_DELETE (anim_desc_file);
  2468. }
  2469. return ;
  2470. }
  2471. ///////////////////////////////////////////////////////////////
  2472. //
  2473. // Get_Current_HTree
  2474. //
  2475. ///////////////////////////////////////////////////////////////
  2476. const HTreeClass *
  2477. CW3DViewDoc::Get_Current_HTree (void) const
  2478. {
  2479. const HTreeClass *htree = NULL;
  2480. if (m_pCRenderObj != NULL) {
  2481. htree = m_pCRenderObj->Get_HTree ();
  2482. }
  2483. return htree;
  2484. }
  2485. ///////////////////////////////////////////////////////////////
  2486. //
  2487. // Save_Camera_Settings
  2488. //
  2489. ///////////////////////////////////////////////////////////////
  2490. void
  2491. CW3DViewDoc::Save_Camera_Settings (void)
  2492. {
  2493. theApp.WriteProfileInt ("Config", "UseManualFOV", m_ManualFOV);
  2494. theApp.WriteProfileInt ("Config", "UseManualClipPlanes", m_ManualClipPlanes);
  2495. CGraphicView *graphic_view = ::Get_Graphic_View ();
  2496. CameraClass *camera = graphic_view->GetCamera ();
  2497. if (camera != NULL) {
  2498. double hfov = camera->Get_Horizontal_FOV ();
  2499. double vfov = camera->Get_Vertical_FOV ();
  2500. float znear = 0;
  2501. float zfar = 0;
  2502. camera->Get_Clip_Planes (znear, zfar);
  2503. CString hfov_string;
  2504. CString vfov_string;
  2505. CString znear_string;
  2506. CString zfar_string;
  2507. hfov_string.Format ("%f", hfov);
  2508. vfov_string.Format ("%f", vfov);
  2509. znear_string.Format ("%f", znear);
  2510. zfar_string.Format ("%f", zfar);
  2511. theApp.WriteProfileString ("Config", "hfov", hfov_string);
  2512. theApp.WriteProfileString ("Config", "vfov", vfov_string);
  2513. theApp.WriteProfileString ("Config", "znear", znear_string);
  2514. theApp.WriteProfileString ("Config", "zfar", zfar_string);
  2515. }
  2516. return ;
  2517. }
  2518. ///////////////////////////////////////////////////////////////
  2519. //
  2520. // Load_Camera_Settings
  2521. //
  2522. ///////////////////////////////////////////////////////////////
  2523. void
  2524. CW3DViewDoc::Load_Camera_Settings (void)
  2525. {
  2526. m_ManualFOV = (theApp.GetProfileInt ("Config", "UseManualFOV", 0) == TRUE);
  2527. m_ManualClipPlanes = (theApp.GetProfileInt ("Config", "UseManualClipPlanes", 0) == TRUE);
  2528. CGraphicView *graphic_view = GetGraphicView ();
  2529. if (graphic_view != NULL) {
  2530. CameraClass *camera = graphic_view->GetCamera ();
  2531. if (camera != NULL) {
  2532. //
  2533. // Should we load the FOV settings from the registry?
  2534. //
  2535. if (m_ManualFOV) {
  2536. CString hfov_string = theApp.GetProfileString ("Config", "hfov", "0");
  2537. CString vfov_string = theApp.GetProfileString ("Config", "vfov", "0");
  2538. double hfov = ::atof (hfov_string);
  2539. double vfov = ::atof (vfov_string);
  2540. camera->Set_View_Plane (hfov, vfov);
  2541. }
  2542. //
  2543. // Should we load the clip planes from the registry?
  2544. //
  2545. if (m_ManualClipPlanes) {
  2546. CString znear_string = theApp.GetProfileString ("Config", "znear", "0.1F");
  2547. CString zfar_string = theApp.GetProfileString ("Config", "zfar", "100.0F");
  2548. float znear = ::atof (znear_string);
  2549. float zfar = ::atof (zfar_string);
  2550. camera->Set_Clip_Planes (znear, zfar);
  2551. if (m_pCScene != NULL) {
  2552. m_pCScene->Set_Fog_Range (znear, zfar);
  2553. m_pCScene->Recalculate_Fog_Planes();
  2554. }
  2555. }
  2556. }
  2557. }
  2558. return ;
  2559. }
  2560. ///////////////////////////////////////////////////////////////
  2561. //
  2562. // Render_Dazzles
  2563. //
  2564. ///////////////////////////////////////////////////////////////
  2565. void
  2566. CW3DViewDoc::Render_Dazzles (CameraClass * camera)
  2567. {
  2568. if (m_pDazzleLayer != NULL) {
  2569. m_pDazzleLayer->Render(camera);
  2570. }
  2571. }
  2572. void
  2573. CW3DViewDoc::SetBackgroundColor (const Vector3 &backgroundColor)
  2574. {
  2575. m_backgroundColor = backgroundColor;
  2576. // If this assert fires, then we will be getting the background color
  2577. // and the fog color out of sync. That would look funky.
  2578. ASSERT(m_pCScene);
  2579. if (m_pCScene)
  2580. m_pCScene->Set_Fog_Color(backgroundColor);
  2581. }
  2582. void
  2583. CW3DViewDoc::EnableFog (bool enable)
  2584. {
  2585. if (m_pCScene)
  2586. {
  2587. m_pCScene->Set_Fog_Enable(enable);
  2588. m_bFogEnabled = enable;
  2589. }
  2590. }