2
0

assimp_view.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. //-------------------------------------------------------------------------------
  2. /**
  3. * This program is distributed under the terms of the GNU Lesser General
  4. * Public License (LGPL).
  5. *
  6. * ASSIMP Viewer Utility
  7. *
  8. */
  9. //-------------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "assimp_view.h"
  12. namespace AssimpView {
  13. //-------------------------------------------------------------------------------
  14. // evil globals
  15. //-------------------------------------------------------------------------------
  16. HINSTANCE g_hInstance = NULL;
  17. HWND g_hDlg = NULL;
  18. IDirect3D9* g_piD3D = NULL;
  19. IDirect3DDevice9* g_piDevice = NULL;
  20. double g_fFPS = 0.0f;
  21. char g_szFileName[MAX_PATH];
  22. ID3DXEffect* g_piDefaultEffect = NULL;
  23. ID3DXEffect* g_piNormalsEffect = NULL;
  24. ID3DXEffect* g_piPassThroughEffect = NULL;
  25. bool g_bMousePressed = false;
  26. bool g_bMousePressedR = false;
  27. bool g_bMousePressedM = false;
  28. bool g_bMousePressedBoth = false;
  29. float g_fElpasedTime = 0.0f;
  30. D3DCAPS9 g_sCaps;
  31. bool g_bLoadingFinished = false;
  32. HANDLE g_hThreadHandle = NULL;
  33. float g_fWheelPos = -10.0f;
  34. bool g_bLoadingCanceled = false;
  35. IDirect3DTexture9* g_pcTexture = NULL;
  36. aiMatrix4x4 g_mWorld;
  37. aiMatrix4x4 g_mWorldRotate;
  38. aiVector3D g_vRotateSpeed = aiVector3D(0.5f,0.5f,0.5f);
  39. aiVector3D g_avLightDirs[1] = { aiVector3D(-0.5f,0.6f,0.2f) /*,
  40. aiVector3D(-0.5f,0.5f,0.5f)*/};
  41. POINT g_mousePos;
  42. POINT g_LastmousePos;
  43. bool g_bFPSView = false;
  44. bool g_bInvert = false;
  45. EClickPos g_eClick = EClickPos_Circle;
  46. unsigned int g_iCurrentColor = 0;
  47. float g_fLightIntensity = 1.0f;
  48. float g_fLightColor = 1.0f;
  49. RenderOptions g_sOptions;
  50. Camera g_sCamera;
  51. AssetHelper *g_pcAsset = NULL;
  52. //
  53. // Contains the mask image for the HUD
  54. // (used to determine the position of a click)
  55. //
  56. unsigned char* g_szImageMask = NULL;
  57. //-------------------------------------------------------------------------------
  58. // table of colors used for normal vectors.
  59. //-------------------------------------------------------------------------------
  60. D3DXVECTOR4 g_aclNormalColors[14] =
  61. {
  62. D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0xFF / 255.0f, 1.0f), // white
  63. D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // red
  64. D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // green
  65. D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // blue
  66. D3DXVECTOR4(0xFF / 255.0f,0xFF / 255.0f,0x00 / 255.0f,1.0f), // yellow
  67. D3DXVECTOR4(0xFF / 255.0f,0x00 / 255.0f,0xFF / 255.0f,1.0f), // magenta
  68. D3DXVECTOR4(0x00 / 255.0f,0xFF / 255.0f,0xFF / 255.0f,1.0f), // wtf
  69. D3DXVECTOR4(0xFF / 255.0f,0x60 / 255.0f,0x60 / 255.0f,1.0f), // light red
  70. D3DXVECTOR4(0x60 / 255.0f,0xFF / 255.0f,0x60 / 255.0f,1.0f), // light green
  71. D3DXVECTOR4(0x60 / 255.0f,0x60 / 255.0f,0xFF / 255.0f,1.0f), // light blue
  72. D3DXVECTOR4(0xA0 / 255.0f,0x00 / 255.0f,0x00 / 255.0f,1.0f), // dark red
  73. D3DXVECTOR4(0x00 / 255.0f,0xA0 / 255.0f,0x00 / 255.0f,1.0f), // dark green
  74. D3DXVECTOR4(0x00 / 255.0f,0x00 / 255.0f,0xA0 / 255.0f,1.0f), // dark blue
  75. D3DXVECTOR4(0x88 / 255.0f,0x88 / 255.0f,0x88 / 255.0f, 1.0f) // gray
  76. };
  77. //-------------------------------------------------------------------------------
  78. //! \brief Entry point for loader thread
  79. //-------------------------------------------------------------------------------
  80. DWORD WINAPI LoadThreadProc(LPVOID lpParameter)
  81. {
  82. UNREFERENCED_PARAMETER(lpParameter);
  83. double fCur = (double)timeGetTime();
  84. g_pcAsset->pcScene = aiImportFile(g_szFileName,
  85. aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices | aiProcess_Triangulate |
  86. aiProcess_GenSmoothNormals | aiProcess_ConvertToLeftHanded | aiProcess_SplitLargeMeshes);
  87. double fEnd = (double)timeGetTime();
  88. double dTime = (fEnd - fCur) / 1000;
  89. char szTemp[128];
  90. sprintf(szTemp,"%.5f",(float)dTime);
  91. SetDlgItemText(g_hDlg,IDC_ELOAD,szTemp);
  92. g_bLoadingFinished = true;
  93. if (NULL == g_pcAsset->pcScene)
  94. {
  95. CLogDisplay::Instance().AddEntry("[ERROR] Unable to load this asset:",
  96. D3DCOLOR_ARGB(0xFF,0xFF,0,0));
  97. CLogDisplay::Instance().AddEntry(aiGetErrorString(),
  98. D3DCOLOR_ARGB(0xFF,0xFF,0,0));
  99. return 1;
  100. }
  101. return 0;
  102. }
  103. //-------------------------------------------------------------------------------
  104. //-------------------------------------------------------------------------------
  105. int LoadAsset(void)
  106. {
  107. g_mWorldRotate = aiMatrix4x4();
  108. g_mWorld = aiMatrix4x4();
  109. DWORD dwID;
  110. g_bLoadingCanceled = false;
  111. g_pcAsset = new AssetHelper();
  112. g_hThreadHandle = CreateThread(NULL,0,&LoadThreadProc,NULL,0,&dwID);
  113. DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_LOADDIALOG),
  114. g_hDlg,&ProgressMessageProc);
  115. g_bLoadingFinished = false;
  116. if (!g_pcAsset || !g_pcAsset->pcScene)
  117. {
  118. if (g_pcAsset)
  119. {
  120. delete g_pcAsset;
  121. g_pcAsset = NULL;
  122. }
  123. return 0;
  124. }
  125. g_pcAsset->apcMeshes = new AssetHelper::MeshHelper*[
  126. g_pcAsset->pcScene->mNumMeshes]();
  127. unsigned int iNumVert = 0;
  128. unsigned int iNumFaces = 0;
  129. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  130. {
  131. iNumVert += g_pcAsset->pcScene->mMeshes[i]->mNumVertices;
  132. iNumFaces += g_pcAsset->pcScene->mMeshes[i]->mNumFaces;
  133. g_pcAsset->apcMeshes[i] = new AssetHelper::MeshHelper();
  134. }
  135. char szOut[120];
  136. sprintf(szOut,"%i",(int)iNumVert);
  137. SetDlgItemText(g_hDlg,IDC_EVERT,szOut);
  138. sprintf(szOut,"%i",(int)iNumFaces);
  139. SetDlgItemText(g_hDlg,IDC_EFACE,szOut);
  140. sprintf(szOut,"%i",(int)g_pcAsset->pcScene->mNumMaterials);
  141. SetDlgItemText(g_hDlg,IDC_EMAT,szOut);
  142. ScaleAsset();
  143. g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f);
  144. g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f);
  145. g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f);
  146. g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f);
  147. return CreateAssetData();
  148. }
  149. //-------------------------------------------------------------------------------
  150. //-------------------------------------------------------------------------------
  151. int DeleteAsset(void)
  152. {
  153. if (!g_pcAsset)return 0;
  154. Render();
  155. DeleteAssetData();
  156. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  157. {
  158. delete g_pcAsset->apcMeshes[i];
  159. }
  160. aiReleaseImport(g_pcAsset->pcScene);
  161. delete[] g_pcAsset->apcMeshes;
  162. delete g_pcAsset;
  163. g_pcAsset = NULL;
  164. SetDlgItemText(g_hDlg,IDC_EVERT,"0");
  165. SetDlgItemText(g_hDlg,IDC_EFACE,"0");
  166. SetDlgItemText(g_hDlg,IDC_EMAT,"0");
  167. return 1;
  168. }
  169. //-------------------------------------------------------------------------------
  170. //-------------------------------------------------------------------------------
  171. int CalculateBounds(aiNode* piNode, aiVector3D* p_avOut,
  172. const aiMatrix4x4& piMatrix)
  173. {
  174. aiMatrix4x4 mTemp = piNode->mTransformation;
  175. mTemp.Transpose();
  176. aiMatrix4x4 aiMe = mTemp * piMatrix;
  177. for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
  178. {
  179. for( unsigned int a = 0; a < g_pcAsset->pcScene->mMeshes[
  180. piNode->mMeshes[i]]->mNumVertices;++a)
  181. {
  182. aiVector3D pc =g_pcAsset->pcScene->mMeshes[
  183. piNode->mMeshes[i]]->mVertices[a];
  184. aiVector3D pc1;
  185. D3DXVec3TransformCoord((D3DXVECTOR3*)&pc1,(D3DXVECTOR3*)&pc,
  186. (D3DXMATRIX*)&aiMe);
  187. p_avOut[0].x = std::min( p_avOut[0].x, pc1.x);
  188. p_avOut[0].y = std::min( p_avOut[0].y, pc1.y);
  189. p_avOut[0].z = std::min( p_avOut[0].z, pc1.z);
  190. p_avOut[1].x = std::max( p_avOut[1].x, pc1.x);
  191. p_avOut[1].y = std::max( p_avOut[1].y, pc1.y);
  192. p_avOut[1].z = std::max( p_avOut[1].z, pc1.z);
  193. }
  194. }
  195. for (unsigned int i = 0; i < piNode->mNumChildren;++i)
  196. {
  197. CalculateBounds( piNode->mChildren[i], p_avOut, aiMe );
  198. }
  199. return 1;
  200. }
  201. //-------------------------------------------------------------------------------
  202. //-------------------------------------------------------------------------------
  203. int ScaleAsset(void)
  204. {
  205. aiVector3D aiVecs[2] = {aiVector3D( 1e10f, 1e10f, 1e10f),
  206. aiVector3D( -1e10f, -1e10f, -1e10f) };
  207. if (g_pcAsset->pcScene->mRootNode)
  208. {
  209. aiMatrix4x4 m;
  210. CalculateBounds(g_pcAsset->pcScene->mRootNode,aiVecs,m);
  211. }
  212. aiVector3D vDelta = aiVecs[1]-aiVecs[0];
  213. aiVector3D vHalf = aiVecs[0] + (vDelta / 2.0f);
  214. float fScale = 10.0f / vDelta.Length();
  215. g_mWorld = aiMatrix4x4(
  216. 1.0f,0.0f,0.0f,0.0f,
  217. 0.0f,1.0f,0.0f,0.0f,
  218. 0.0f,0.0f,1.0f,0.0f,
  219. -vHalf.x,-vHalf.y,-vHalf.z,1.0f) *
  220. aiMatrix4x4(
  221. fScale,0.0f,0.0f,0.0f,
  222. 0.0f,fScale,0.0f,0.0f,
  223. 0.0f,0.0f,fScale,0.0f,
  224. 0.0f,0.0f,0.0f,1.0f);
  225. #if 0
  226. // now handle the fact that the asset might have its
  227. // own transformation matrix (handle scaling and translation)
  228. if (NULL != g_pcAsset->pcScene->mRootNode)
  229. {
  230. if (0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[0][0] &&
  231. 0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[1][1] &&
  232. 0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[2][2] &&
  233. 0.0f != g_pcAsset->pcScene->mRootNode->mTransformation[3][3])
  234. {
  235. g_mWorld[0][0] /= g_pcAsset->pcScene->mRootNode->mTransformation[0][0];
  236. g_mWorld[1][1] /= g_pcAsset->pcScene->mRootNode->mTransformation[1][1];
  237. g_mWorld[2][2] /= g_pcAsset->pcScene->mRootNode->mTransformation[2][2];
  238. g_mWorld[3][3] /= g_pcAsset->pcScene->mRootNode->mTransformation[3][3];
  239. }
  240. g_mWorld[3][0] -= g_pcAsset->pcScene->mRootNode->mTransformation[3][0];
  241. g_mWorld[3][1] -= g_pcAsset->pcScene->mRootNode->mTransformation[3][1];
  242. g_mWorld[3][2] -= g_pcAsset->pcScene->mRootNode->mTransformation[3][2];
  243. aiMatrix4x4 m;
  244. if ( 0 == memcmp(&m,&g_pcAsset->pcScene->mRootNode->mTransformation,sizeof(aiMatrix4x4)) &&
  245. 1 <= g_pcAsset->pcScene->mRootNode->mNumChildren)
  246. {
  247. if (0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[0][0] &&
  248. 0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[1][1] &&
  249. 0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[2][2] &&
  250. 0.0f != g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][3])
  251. {
  252. g_mWorld[0][0] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[0][0];
  253. g_mWorld[1][1] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[1][1];
  254. g_mWorld[2][2] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[2][2];
  255. g_mWorld[3][3] /= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][3];
  256. }
  257. g_mWorld[3][0] -= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][0];
  258. g_mWorld[3][1] -= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][1];
  259. g_mWorld[3][2] -= g_pcAsset->pcScene->mRootNode->mChildren[0]->mTransformation[3][2];
  260. }
  261. }
  262. #endif
  263. return 1;
  264. }
  265. //-------------------------------------------------------------------------------
  266. //-------------------------------------------------------------------------------
  267. int GenerateNormalsAsLineList(AssetHelper::MeshHelper* pcMesh,const aiMesh* pcSource)
  268. {
  269. if (!pcSource->mNormals)return 0;
  270. // create vertex buffer
  271. if(FAILED( g_piDevice->CreateVertexBuffer(sizeof(AssetHelper::LineVertex) *
  272. pcSource->mNumVertices * 2,
  273. D3DUSAGE_WRITEONLY,
  274. AssetHelper::LineVertex::GetFVF(),
  275. D3DPOOL_DEFAULT, &pcMesh->piVBNormals,NULL)))
  276. {
  277. MessageBox(g_hDlg,"Failed to create vertex buffer for the normal list",
  278. "ASSIMP Viewer Utility",MB_OK);
  279. return 2;
  280. }
  281. // now fill the vertex buffer
  282. AssetHelper::LineVertex* pbData2;
  283. pcMesh->piVBNormals->Lock(0,0,(void**)&pbData2,0);
  284. for (unsigned int x = 0; x < pcSource->mNumVertices;++x)
  285. {
  286. pbData2->vPosition = pcSource->mVertices[x];
  287. ++pbData2;
  288. aiVector3D vNormal = pcSource->mNormals[x];
  289. vNormal.Normalize();
  290. vNormal.x /= g_mWorld.a1*4;
  291. vNormal.y /= g_mWorld.b2*4;
  292. vNormal.z /= g_mWorld.c3*4;
  293. pbData2->vPosition = pcSource->mVertices[x] + vNormal;
  294. ++pbData2;
  295. }
  296. pcMesh->piVBNormals->Unlock();
  297. return 1;
  298. }
  299. //-------------------------------------------------------------------------------
  300. // Fill the UI combobox with a list of all supported animations
  301. //
  302. // The animations are added in order
  303. //-------------------------------------------------------------------------------
  304. int FillAnimList(void)
  305. {
  306. // clear the combo box
  307. SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_RESETCONTENT,0,0);
  308. if (0 == g_pcAsset->pcScene->mNumAnimations)
  309. {
  310. // disable all UI components related to animations
  311. EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),FALSE);
  312. EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),FALSE);
  313. EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),FALSE);
  314. EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),FALSE);
  315. EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),FALSE);
  316. EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),FALSE);
  317. EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),FALSE);
  318. }
  319. else
  320. {
  321. // reenable all animation components if they have been
  322. // disabled for a previous mesh
  323. EnableWindow(GetDlgItem(g_hDlg,IDC_PLAYANIM),TRUE);
  324. EnableWindow(GetDlgItem(g_hDlg,IDC_SPEED),TRUE);
  325. EnableWindow(GetDlgItem(g_hDlg,IDC_PINORDER),TRUE);
  326. EnableWindow(GetDlgItem(g_hDlg,IDC_SSPEED),TRUE);
  327. EnableWindow(GetDlgItem(g_hDlg,IDC_SANIMGB),TRUE);
  328. EnableWindow(GetDlgItem(g_hDlg,IDC_SANIM),TRUE);
  329. EnableWindow(GetDlgItem(g_hDlg,IDC_COMBO1),TRUE);
  330. // now fill in all animation names
  331. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumAnimations;++i)
  332. {
  333. SendDlgItemMessage(g_hDlg,IDC_COMBO1,CB_ADDSTRING,0,
  334. ( LPARAM ) g_pcAsset->pcScene->mAnimations[i]->mName.data);
  335. }
  336. }
  337. return 1;
  338. }
  339. //-------------------------------------------------------------------------------
  340. //-------------------------------------------------------------------------------
  341. int CreateAssetData(void)
  342. {
  343. if (!g_pcAsset)return 0;
  344. g_iShaderCount = 0;
  345. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  346. {
  347. // create vertex buffer
  348. if(FAILED( g_piDevice->CreateVertexBuffer(sizeof(AssetHelper::Vertex) *
  349. g_pcAsset->pcScene->mMeshes[i]->mNumVertices,
  350. D3DUSAGE_WRITEONLY,
  351. AssetHelper::Vertex::GetFVF(),
  352. D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piVB,NULL)))
  353. {
  354. MessageBox(g_hDlg,"Failed to create vertex buffer",
  355. "ASSIMP Viewer Utility",MB_OK);
  356. return 2;
  357. }
  358. // create index buffer
  359. if(FAILED( g_piDevice->CreateIndexBuffer( 4 *
  360. g_pcAsset->pcScene->mMeshes[i]->mNumFaces * 3,
  361. D3DUSAGE_WRITEONLY,
  362. D3DFMT_INDEX32,
  363. D3DPOOL_DEFAULT, &g_pcAsset->apcMeshes[i]->piIB,NULL)))
  364. {
  365. MessageBox(g_hDlg,"Failed to create index buffer",
  366. "ASSIMP Viewer Utility",MB_OK);
  367. return 2;
  368. }
  369. // now fill the index buffer
  370. unsigned int* pbData;
  371. g_pcAsset->apcMeshes[i]->piIB->Lock(0,0,(void**)&pbData,0);
  372. for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumFaces;++x)
  373. {
  374. for (unsigned int a = 0; a < 3;++a)
  375. {
  376. *pbData++ = g_pcAsset->pcScene->mMeshes[i]->mFaces[x].mIndices[a];
  377. }
  378. }
  379. g_pcAsset->apcMeshes[i]->piIB->Unlock();
  380. // now fill the vertex buffer
  381. AssetHelper::Vertex* pbData2;
  382. g_pcAsset->apcMeshes[i]->piVB->Lock(0,0,(void**)&pbData2,0);
  383. for (unsigned int x = 0; x < g_pcAsset->pcScene->mMeshes[i]->mNumVertices;++x)
  384. {
  385. pbData2->vPosition = g_pcAsset->pcScene->mMeshes[i]->mVertices[x];
  386. if (NULL == g_pcAsset->pcScene->mMeshes[i]->mNormals)
  387. pbData2->vNormal = aiVector3D(0.0f,0.0f,0.0f);
  388. else pbData2->vNormal = g_pcAsset->pcScene->mMeshes[i]->mNormals[x];
  389. if (NULL == g_pcAsset->pcScene->mMeshes[i]->mTangents)
  390. {
  391. pbData2->vTangent = aiVector3D(0.0f,0.0f,0.0f);
  392. pbData2->vBitangent = aiVector3D(0.0f,0.0f,0.0f);
  393. }
  394. else
  395. {
  396. pbData2->vTangent = g_pcAsset->pcScene->mMeshes[i]->mTangents[x];
  397. pbData2->vBitangent = g_pcAsset->pcScene->mMeshes[i]->mBitangents[x];
  398. }
  399. if (g_pcAsset->pcScene->mMeshes[i]->HasVertexColors( 0))
  400. {
  401. pbData2->dColorDiffuse = D3DCOLOR_ARGB(
  402. ((unsigned char)std::max( std::min( g_pcAsset->pcScene->
  403. mMeshes[i]->mColors[0][x].a * 255.0f, 255.0f),0.0f)),
  404. ((unsigned char)std::max( std::min( g_pcAsset->pcScene->
  405. mMeshes[i]->mColors[0][x].r * 255.0f, 255.0f),0.0f)),
  406. ((unsigned char)std::max( std::min( g_pcAsset->pcScene->
  407. mMeshes[i]->mColors[0][x].g * 255.0f, 255.0f),0.0f)),
  408. ((unsigned char)std::max( std::min( g_pcAsset->pcScene->
  409. mMeshes[i]->mColors[0][x].b * 255.0f, 255.0f),0.0f)));
  410. }
  411. else pbData2->dColorDiffuse = D3DCOLOR_ARGB(0xFF,0,0,0);
  412. // ignore a third texture coordinate component
  413. if (g_pcAsset->pcScene->mMeshes[i]->HasTextureCoords( 0))
  414. {
  415. pbData2->vTextureUV = aiVector2D(
  416. g_pcAsset->pcScene->mMeshes[i]->mTextureCoords[0][x].x,
  417. g_pcAsset->pcScene->mMeshes[i]->mTextureCoords[0][x].y);
  418. }
  419. else pbData2->vTextureUV = aiVector2D(0.0f,0.0f);
  420. ++pbData2;
  421. }
  422. g_pcAsset->apcMeshes[i]->piVB->Unlock();
  423. // now generate the second vertex buffer, holding all normals
  424. GenerateNormalsAsLineList(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
  425. // create the material for the mesh
  426. CreateMaterial(g_pcAsset->apcMeshes[i],g_pcAsset->pcScene->mMeshes[i]);
  427. }
  428. CLogDisplay::Instance().AddEntry("[OK] The asset has been loaded successfully");
  429. // now get the number of unique shaders generated for the asset
  430. // (even if the environment changes this number won't change)
  431. char szTemp[32];
  432. sprintf(szTemp,"%i", g_iShaderCount);
  433. SetDlgItemText(g_hDlg,IDC_ESHADER,szTemp);
  434. return FillAnimList();
  435. }
  436. //-------------------------------------------------------------------------------
  437. //-------------------------------------------------------------------------------
  438. int DeleteAssetData(void)
  439. {
  440. if (!g_pcAsset)return 0;
  441. // TODO: Move this to a proper destructor
  442. for (unsigned int i = 0; i < g_pcAsset->pcScene->mNumMeshes;++i)
  443. {
  444. if(g_pcAsset->apcMeshes[i]->piVB)
  445. {
  446. g_pcAsset->apcMeshes[i]->piVB->Release();
  447. g_pcAsset->apcMeshes[i]->piVB = NULL;
  448. }
  449. if(g_pcAsset->apcMeshes[i]->piVBNormals)
  450. {
  451. g_pcAsset->apcMeshes[i]->piVBNormals->Release();
  452. g_pcAsset->apcMeshes[i]->piVBNormals = NULL;
  453. }
  454. if(g_pcAsset->apcMeshes[i]->piIB)
  455. {
  456. g_pcAsset->apcMeshes[i]->piIB->Release();
  457. g_pcAsset->apcMeshes[i]->piIB = NULL;
  458. }
  459. if(g_pcAsset->apcMeshes[i]->piEffect)
  460. {
  461. g_pcAsset->apcMeshes[i]->piEffect->Release();
  462. g_pcAsset->apcMeshes[i]->piEffect = NULL;
  463. }
  464. if(g_pcAsset->apcMeshes[i]->piDiffuseTexture)
  465. {
  466. g_pcAsset->apcMeshes[i]->piDiffuseTexture->Release();
  467. g_pcAsset->apcMeshes[i]->piDiffuseTexture = NULL;
  468. }
  469. if(g_pcAsset->apcMeshes[i]->piNormalTexture)
  470. {
  471. g_pcAsset->apcMeshes[i]->piNormalTexture->Release();
  472. g_pcAsset->apcMeshes[i]->piNormalTexture = NULL;
  473. }
  474. if(g_pcAsset->apcMeshes[i]->piSpecularTexture)
  475. {
  476. g_pcAsset->apcMeshes[i]->piSpecularTexture->Release();
  477. g_pcAsset->apcMeshes[i]->piSpecularTexture = NULL;
  478. }
  479. if(g_pcAsset->apcMeshes[i]->piAmbientTexture)
  480. {
  481. g_pcAsset->apcMeshes[i]->piAmbientTexture->Release();
  482. g_pcAsset->apcMeshes[i]->piAmbientTexture = NULL;
  483. }
  484. if(g_pcAsset->apcMeshes[i]->piEmissiveTexture)
  485. {
  486. g_pcAsset->apcMeshes[i]->piEmissiveTexture->Release();
  487. g_pcAsset->apcMeshes[i]->piEmissiveTexture = NULL;
  488. }
  489. }
  490. return 1;
  491. }
  492. //-------------------------------------------------------------------------------
  493. //-------------------------------------------------------------------------------
  494. int SetupFPSView()
  495. {
  496. if (!g_bFPSView)
  497. {
  498. g_sCamera.vPos = aiVector3D(0.0f,0.0f,g_fWheelPos);
  499. g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f);
  500. g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f);
  501. g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f);
  502. }
  503. else
  504. {
  505. g_fWheelPos = g_sCamera.vPos.z;
  506. g_sCamera.vPos = aiVector3D(0.0f,0.0f,-10.0f);
  507. g_sCamera.vLookAt = aiVector3D(0.0f,0.0f,1.0f);
  508. g_sCamera.vUp = aiVector3D(0.0f,1.0f,0.0f);
  509. g_sCamera.vRight = aiVector3D(0.0f,1.0f,0.0f);
  510. }
  511. return 1;
  512. }
  513. //-------------------------------------------------------------------------------
  514. //-------------------------------------------------------------------------------
  515. int InitD3D(void)
  516. {
  517. if (NULL == g_piD3D)
  518. {
  519. g_piD3D = Direct3DCreate9(D3D_SDK_VERSION);
  520. if (NULL == g_piD3D)return 0;
  521. }
  522. return 1;
  523. }
  524. //-------------------------------------------------------------------------------
  525. //-------------------------------------------------------------------------------
  526. int ShutdownD3D(void)
  527. {
  528. ShutdownDevice();
  529. if (NULL != g_piD3D)
  530. {
  531. g_piD3D->Release();
  532. g_piD3D = NULL;
  533. }
  534. return 1;
  535. }
  536. //-------------------------------------------------------------------------------
  537. //-------------------------------------------------------------------------------
  538. int ShutdownDevice(void)
  539. {
  540. if (NULL != g_piDevice)
  541. {
  542. g_piDevice->Release();
  543. g_piDevice = NULL;
  544. }
  545. if (NULL != g_piDefaultEffect)
  546. {
  547. g_piDefaultEffect->Release();
  548. g_piDefaultEffect = NULL;
  549. }
  550. if (NULL != g_piNormalsEffect)
  551. {
  552. g_piNormalsEffect->Release();
  553. g_piNormalsEffect = NULL;
  554. }
  555. if (NULL != g_piPassThroughEffect)
  556. {
  557. g_piPassThroughEffect->Release();
  558. g_piPassThroughEffect = NULL;
  559. }
  560. if (NULL != g_pcTexture)
  561. {
  562. g_pcTexture->Release();
  563. g_pcTexture = NULL;
  564. }
  565. delete[] g_szImageMask;
  566. g_szImageMask = NULL;
  567. CBackgroundPainter::Instance().ReleaseNativeResource();
  568. CLogDisplay::Instance().ReleaseNativeResource();
  569. return 1;
  570. }
  571. //-------------------------------------------------------------------------------
  572. //-------------------------------------------------------------------------------
  573. int CreateHUDTexture()
  574. {
  575. // lock the memory resource ourselves
  576. HRSRC res = FindResource(NULL,MAKEINTRESOURCE(IDR_HUD),RT_RCDATA);
  577. HGLOBAL hg = LoadResource(NULL,res);
  578. void* pData = LockResource(hg);
  579. if(FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice,
  580. pData,SizeofResource(NULL,res),
  581. D3DX_DEFAULT_NONPOW2,
  582. D3DX_DEFAULT_NONPOW2,
  583. 1,
  584. 0,
  585. D3DFMT_A8R8G8B8,
  586. D3DPOOL_MANAGED,
  587. D3DX_DEFAULT,
  588. D3DX_DEFAULT,
  589. 0,
  590. NULL,
  591. NULL,
  592. &g_pcTexture)))
  593. {
  594. CLogDisplay::Instance().AddEntry("[ERROR] Unable to load HUD texture",
  595. D3DCOLOR_ARGB(0xFF,0xFF,0,0));
  596. g_pcTexture = NULL;
  597. g_szImageMask = NULL;
  598. UnlockResource(hg);
  599. FreeResource(hg);
  600. return 0;
  601. }
  602. UnlockResource(hg);
  603. FreeResource(hg);
  604. D3DSURFACE_DESC sDesc;
  605. g_pcTexture->GetLevelDesc(0,&sDesc);
  606. // lock the memory resource ourselves
  607. res = FindResource(NULL,MAKEINTRESOURCE(IDR_HUDMASK),RT_RCDATA);
  608. hg = LoadResource(NULL,res);
  609. pData = LockResource(hg);
  610. IDirect3DTexture9* pcTex;
  611. if(FAILED(D3DXCreateTextureFromFileInMemoryEx(g_piDevice,
  612. pData,SizeofResource(NULL,res),
  613. sDesc.Width,
  614. sDesc.Height,
  615. 1,
  616. 0,
  617. D3DFMT_L8,
  618. D3DPOOL_MANAGED, // unnecessary
  619. D3DX_DEFAULT,
  620. D3DX_DEFAULT,
  621. 0,
  622. NULL,
  623. NULL,
  624. &pcTex)))
  625. {
  626. CLogDisplay::Instance().AddEntry("[ERROR] Unable to load HUD mask texture",
  627. D3DCOLOR_ARGB(0xFF,0xFF,0,0));
  628. g_szImageMask = NULL;
  629. UnlockResource(hg);
  630. FreeResource(hg);
  631. return 0;
  632. }
  633. UnlockResource(hg);
  634. FreeResource(hg);
  635. // lock the texture and copy it to get a pointer
  636. D3DLOCKED_RECT sRect;
  637. pcTex->LockRect(0,&sRect,NULL,D3DLOCK_READONLY);
  638. unsigned char* szOut = new unsigned char[sDesc.Width * sDesc.Height];
  639. unsigned char* _szOut = szOut;
  640. unsigned char* szCur = (unsigned char*) sRect.pBits;
  641. for (unsigned int y = 0; y < sDesc.Height;++y)
  642. {
  643. memcpy(_szOut,szCur,sDesc.Width);
  644. szCur += sRect.Pitch;
  645. _szOut += sDesc.Width;
  646. }
  647. pcTex->UnlockRect(0);
  648. pcTex->Release();
  649. g_szImageMask = szOut;
  650. return 1;
  651. }
  652. //-------------------------------------------------------------------------------
  653. //-------------------------------------------------------------------------------
  654. int CreateDevice (bool p_bMultiSample,bool p_bSuperSample,bool bHW /*= true*/)
  655. {
  656. D3DDEVTYPE eType = bHW ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
  657. RECT sRect;
  658. GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
  659. sRect.right -= sRect.left;
  660. sRect.bottom -= sRect.top;
  661. D3DPRESENT_PARAMETERS sParams;
  662. memset(&sParams,0,sizeof(D3DPRESENT_PARAMETERS));
  663. D3DDISPLAYMODE sMode;
  664. g_piD3D->GetAdapterDisplayMode(0,&sMode);
  665. sParams.Windowed = TRUE;
  666. sParams.hDeviceWindow = GetDlgItem( g_hDlg, IDC_RT );
  667. sParams.EnableAutoDepthStencil = TRUE;
  668. sParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  669. sParams.BackBufferWidth = (UINT)sRect.right;
  670. sParams.BackBufferHeight = (UINT)sRect.bottom;
  671. sParams.AutoDepthStencilFormat = D3DFMT_D24X8;
  672. sParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
  673. // find the highest multisample type available on this device
  674. D3DMULTISAMPLE_TYPE sMS = D3DMULTISAMPLE_2_SAMPLES;
  675. D3DMULTISAMPLE_TYPE sMSOut = D3DMULTISAMPLE_NONE;
  676. DWORD dwQuality = 0;
  677. if (p_bMultiSample)
  678. {
  679. while ((D3DMULTISAMPLE_TYPE)(D3DMULTISAMPLE_16_SAMPLES + 1) !=
  680. (sMS = (D3DMULTISAMPLE_TYPE)(sMS + 1)))
  681. {
  682. if(SUCCEEDED( g_piD3D->CheckDeviceMultiSampleType(0,eType,
  683. sMode.Format,TRUE,sMS,&dwQuality)))
  684. {
  685. sMSOut = sMS;
  686. }
  687. }
  688. if (0 != dwQuality)dwQuality -= 1;
  689. sParams.MultiSampleQuality = dwQuality;
  690. sParams.MultiSampleType = sMSOut;
  691. }
  692. if(FAILED(g_piD3D->CreateDevice(0,eType,
  693. g_hDlg,D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,&sParams,&g_piDevice)))
  694. {
  695. if(FAILED(g_piD3D->CreateDevice(0,eType,
  696. g_hDlg,D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,&sParams,&g_piDevice)))
  697. {
  698. // if hardware fails use software rendering instead
  699. if (bHW)return CreateDevice(p_bMultiSample,p_bSuperSample,false);
  700. return 0;
  701. }
  702. }
  703. g_piDevice->SetFVF(AssetHelper::Vertex::GetFVF());
  704. ID3DXBuffer* piBuffer = NULL;
  705. if(FAILED( D3DXCreateEffect(g_piDevice,
  706. g_szDefaultShader.c_str(),
  707. (UINT)g_szDefaultShader.length(),
  708. NULL,
  709. NULL,
  710. D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,
  711. NULL,
  712. &g_piDefaultEffect,&piBuffer)))
  713. {
  714. if( piBuffer)
  715. {
  716. MessageBox(g_hDlg,(LPCSTR)piBuffer->GetBufferPointer(),"HLSL",MB_OK);
  717. piBuffer->Release();
  718. }
  719. return 0;
  720. }
  721. if( piBuffer)
  722. {
  723. piBuffer->Release();
  724. piBuffer = NULL;
  725. }
  726. if(FAILED( D3DXCreateEffect(g_piDevice,
  727. g_szPassThroughShader.c_str(),(UINT)g_szPassThroughShader.length(),
  728. NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piPassThroughEffect,&piBuffer)))
  729. {
  730. if( piBuffer)
  731. {
  732. MessageBox(g_hDlg,(LPCSTR
  733. )piBuffer->GetBufferPointer(),"HLSL",MB_OK);
  734. piBuffer->Release();
  735. }
  736. return 0;
  737. }
  738. if( piBuffer)
  739. {
  740. piBuffer->Release();
  741. piBuffer = NULL;
  742. }
  743. if(FAILED( D3DXCreateEffect(g_piDevice,
  744. g_szNormalsShader.c_str(),(UINT)g_szNormalsShader.length(),
  745. NULL,NULL,D3DXSHADER_USE_LEGACY_D3DX9_31_DLL,NULL,&g_piNormalsEffect, &piBuffer)))
  746. {
  747. if( piBuffer)
  748. {
  749. MessageBox(g_hDlg,(LPCSTR
  750. )piBuffer->GetBufferPointer(),"HLSL",MB_OK);
  751. piBuffer->Release();
  752. }
  753. return 0;
  754. }
  755. if( piBuffer)
  756. {
  757. piBuffer->Release();
  758. piBuffer = NULL;
  759. }
  760. g_piDevice->GetDeviceCaps(&g_sCaps);
  761. if(g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0))
  762. {
  763. EnableWindow(GetDlgItem(g_hDlg,IDC_LOWQUALITY),FALSE);
  764. }
  765. // create the texture for the HUD
  766. CreateHUDTexture();
  767. CBackgroundPainter::Instance().RecreateNativeResource();
  768. CLogDisplay::Instance().RecreateNativeResource();
  769. g_piPassThroughEffect->SetTexture("TEXTURE_2D",g_pcTexture);
  770. return 1;
  771. }
  772. //-------------------------------------------------------------------------------
  773. //-------------------------------------------------------------------------------
  774. int CreateDevice (void)
  775. {
  776. return CreateDevice(g_sOptions.bMultiSample,
  777. g_sOptions.bSuperSample);
  778. }
  779. //-------------------------------------------------------------------------------
  780. //-------------------------------------------------------------------------------
  781. int GetProjectionMatrix (aiMatrix4x4& p_mOut)
  782. {
  783. const float fFarPlane = 100.0f;
  784. const float fNearPlane = 0.1f;
  785. const float fFOV = (float)(45.0 * 0.0174532925);
  786. const float s = 1.0f / tanf(fFOV * 0.5f);
  787. const float Q = fFarPlane / (fFarPlane - fNearPlane);
  788. RECT sRect;
  789. GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
  790. sRect.right -= sRect.left;
  791. sRect.bottom -= sRect.top;
  792. const float fAspect = (float)sRect.right / (float)sRect.bottom;
  793. p_mOut = aiMatrix4x4(
  794. s / fAspect, 0.0f, 0.0f, 0.0f,
  795. 0.0f, s, 0.0f, 0.0f,
  796. 0.0f, 0.0f, Q, 1.0f,
  797. 0.0f, 0.0f, -Q * fNearPlane, 0.0f);
  798. return 1;
  799. }
  800. //-------------------------------------------------------------------------------
  801. //-------------------------------------------------------------------------------
  802. aiVector3D GetCameraMatrix (aiMatrix4x4& p_mOut)
  803. {
  804. D3DXMATRIX view;
  805. D3DXMatrixIdentity( &view );
  806. D3DXVec3Normalize( (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vLookAt );
  807. D3DXVec3Cross( (D3DXVECTOR3*)&g_sCamera.vRight, (D3DXVECTOR3*)&g_sCamera.vUp, (D3DXVECTOR3*)&g_sCamera.vLookAt );
  808. D3DXVec3Normalize( (D3DXVECTOR3*)&g_sCamera.vRight, (D3DXVECTOR3*)&g_sCamera.vRight );
  809. D3DXVec3Cross( (D3DXVECTOR3*)&g_sCamera.vUp, (D3DXVECTOR3*)&g_sCamera.vLookAt, (D3DXVECTOR3*)&g_sCamera.vRight );
  810. D3DXVec3Normalize( (D3DXVECTOR3*)&g_sCamera.vUp, (D3DXVECTOR3*)&g_sCamera.vUp );
  811. view._11 = g_sCamera.vRight.x;
  812. view._12 = g_sCamera.vUp.x;
  813. view._13 = g_sCamera.vLookAt.x;
  814. view._14 = 0.0f;
  815. view._21 = g_sCamera.vRight.y;
  816. view._22 = g_sCamera.vUp.y;
  817. view._23 = g_sCamera.vLookAt.y;
  818. view._24 = 0.0f;
  819. view._31 = g_sCamera.vRight.z;
  820. view._32 = g_sCamera.vUp.z;
  821. view._33 = g_sCamera.vLookAt.z;
  822. view._34 = 0.0f;
  823. view._41 = -D3DXVec3Dot( (D3DXVECTOR3*)&g_sCamera.vPos, (D3DXVECTOR3*)&g_sCamera.vRight );
  824. view._42 = -D3DXVec3Dot( (D3DXVECTOR3*)&g_sCamera.vPos, (D3DXVECTOR3*)&g_sCamera.vUp );
  825. view._43 = -D3DXVec3Dot( (D3DXVECTOR3*)&g_sCamera.vPos, (D3DXVECTOR3*)&g_sCamera.vLookAt );
  826. view._44 = 1.0f;
  827. memcpy(&p_mOut,&view,sizeof(aiMatrix4x4));
  828. return g_sCamera.vPos;
  829. }
  830. //-------------------------------------------------------------------------------
  831. //-------------------------------------------------------------------------------
  832. int SetupMaterial (AssetHelper::MeshHelper* pcMesh,
  833. const aiMatrix4x4& pcProj,
  834. const aiMatrix4x4& aiMe,
  835. const aiMatrix4x4& pcCam,
  836. const aiVector3D& vPos)
  837. {
  838. if (!pcMesh->piEffect)return 0;
  839. ID3DXEffect* piEnd = pcMesh->piEffect;
  840. piEnd->SetMatrix("WorldViewProjection",
  841. (const D3DXMATRIX*)&pcProj);
  842. piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe);
  843. piEnd->SetMatrix("WorldInverseTranspose",
  844. (const D3DXMATRIX*)&pcCam);
  845. D3DXVECTOR4 apcVec[5];
  846. memset(apcVec,0,sizeof(apcVec));
  847. apcVec[0].x = g_avLightDirs[0].x;
  848. apcVec[0].y = g_avLightDirs[0].y;
  849. apcVec[0].z = g_avLightDirs[0].z;
  850. apcVec[1].x = g_avLightDirs[0].x * -1.0f;
  851. apcVec[1].y = g_avLightDirs[0].y * -1.0f;
  852. apcVec[1].z = g_avLightDirs[0].z * -1.0f;
  853. D3DXVec4Normalize(&apcVec[0],&apcVec[0]);
  854. D3DXVec4Normalize(&apcVec[1],&apcVec[1]);
  855. piEnd->SetVectorArray("afLightDir",apcVec,5);
  856. if(g_sOptions.b3Lights)
  857. {
  858. apcVec[0].x = 1.0f;
  859. apcVec[0].y = 1.0f;
  860. apcVec[0].z = 1.0f;
  861. apcVec[0].w = 1.0f;
  862. apcVec[1].x = 0.1f;
  863. apcVec[1].y = 1.0f;
  864. apcVec[1].z = 0.1f;
  865. apcVec[1].w = 1.0f;
  866. }
  867. else
  868. {
  869. apcVec[0].x = 1.0f;
  870. apcVec[0].y = 1.0f;
  871. apcVec[0].z = 1.0f;
  872. apcVec[0].w = 1.0f;
  873. apcVec[1].x = 0.0f;
  874. apcVec[1].y = 0.0f;
  875. apcVec[1].z = 0.0f;
  876. apcVec[1].w = 0.0f;
  877. }
  878. apcVec[0] *= g_fLightIntensity;
  879. apcVec[1] *= g_fLightIntensity;
  880. piEnd->SetVectorArray("afLightColor",apcVec,5);
  881. if(g_sOptions.b3Lights)
  882. {
  883. apcVec[0].x = 0.05f;
  884. apcVec[0].y = 0.05f;
  885. apcVec[0].z = 0.05f;
  886. apcVec[0].w = 1.0f;
  887. apcVec[1].x = 0.05f;
  888. apcVec[1].y = 0.05f;
  889. apcVec[1].z = 0.05f;
  890. apcVec[1].w = 1.0f;
  891. }
  892. else
  893. {
  894. apcVec[0].x = 0.05f;
  895. apcVec[0].y = 0.05f;
  896. apcVec[0].z = 0.05f;
  897. apcVec[0].w = 1.0f;
  898. apcVec[1].x = 0.0f;
  899. apcVec[1].y = 0.0f;
  900. apcVec[1].z = 0.0f;
  901. apcVec[1].w = 0.0f;
  902. }
  903. apcVec[0] *= g_fLightIntensity;
  904. apcVec[1] *= g_fLightIntensity;
  905. piEnd->SetVectorArray("afLightColorAmbient",apcVec,5);
  906. apcVec[0].x = vPos.x;
  907. apcVec[0].y = vPos.y;
  908. apcVec[0].z = vPos.z;
  909. piEnd->SetVector( "vCameraPos",&apcVec[0]);
  910. if (pcMesh->bSharedFX)
  911. {
  912. // now commit all constants to the shader
  913. if (1.0f != pcMesh->fOpacity)
  914. pcMesh->piEffect->SetFloat("TRANSPARENCY",pcMesh->fOpacity);
  915. if (pcMesh->eShadingMode != aiShadingMode_Gouraud)
  916. pcMesh->piEffect->SetFloat("SPECULARITY",pcMesh->fShininess);
  917. pcMesh->piEffect->SetVector("DIFFUSE_COLOR",&pcMesh->vDiffuseColor);
  918. pcMesh->piEffect->SetVector("SPECULAR_COLOR",&pcMesh->vSpecularColor);
  919. pcMesh->piEffect->SetVector("AMBIENT_COLOR",&pcMesh->vAmbientColor);
  920. pcMesh->piEffect->SetVector("EMISSIVE_COLOR",&pcMesh->vEmissiveColor);
  921. if (pcMesh->piOpacityTexture)
  922. pcMesh->piEffect->SetTexture("OPACITY_TEXTURE",pcMesh->piOpacityTexture);
  923. if (pcMesh->piDiffuseTexture)
  924. pcMesh->piEffect->SetTexture("DIFFUSE_TEXTURE",pcMesh->piDiffuseTexture);
  925. if (pcMesh->piSpecularTexture)
  926. pcMesh->piEffect->SetTexture("SPECULAR_TEXTURE",pcMesh->piSpecularTexture);
  927. if (pcMesh->piAmbientTexture)
  928. pcMesh->piEffect->SetTexture("AMBIENT_TEXTURE",pcMesh->piAmbientTexture);
  929. if (pcMesh->piEmissiveTexture)
  930. pcMesh->piEffect->SetTexture("EMISSIVE_TEXTURE",pcMesh->piEmissiveTexture);
  931. if (pcMesh->piNormalTexture)
  932. pcMesh->piEffect->SetTexture("NORMAL_TEXTURE",pcMesh->piNormalTexture);
  933. if (CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  934. {
  935. piEnd->SetTexture("lw_tex_envmap",CBackgroundPainter::Instance().GetTexture());
  936. }
  937. }
  938. if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality)
  939. {
  940. if (g_sOptions.b3Lights)
  941. piEnd->SetTechnique("MaterialFXSpecular_PS20_D2");
  942. else piEnd->SetTechnique("MaterialFXSpecular_PS20_D1");
  943. }
  944. else
  945. {
  946. if (g_sOptions.b3Lights)
  947. piEnd->SetTechnique("MaterialFXSpecular_D2");
  948. else piEnd->SetTechnique("MaterialFXSpecular_D1");
  949. }
  950. UINT dwPasses = 0;
  951. piEnd->Begin(&dwPasses,0);
  952. piEnd->BeginPass(0);
  953. return 1;
  954. }
  955. //-------------------------------------------------------------------------------
  956. //-------------------------------------------------------------------------------
  957. int EndMaterial (AssetHelper::MeshHelper* pcMesh)
  958. {
  959. if (!pcMesh->piEffect)return 0;
  960. pcMesh->piEffect->EndPass();
  961. pcMesh->piEffect->End();
  962. return 1;
  963. }
  964. //-------------------------------------------------------------------------------
  965. //-------------------------------------------------------------------------------
  966. int RenderNode (aiNode* piNode,const aiMatrix4x4& piMatrix, bool bAlpha = false)
  967. {
  968. aiMatrix4x4 mTemp = piNode->mTransformation;
  969. mTemp.Transpose();
  970. aiMatrix4x4 aiMe = mTemp * piMatrix;
  971. aiMatrix4x4 pcProj;
  972. GetProjectionMatrix(pcProj);
  973. aiMatrix4x4 pcCam;
  974. aiVector3D vPos = GetCameraMatrix(pcCam);
  975. pcProj = (aiMe * pcCam) * pcProj;
  976. pcCam = aiMe;
  977. pcCam.Inverse().Transpose();
  978. // VERY UNOPTIMIZED, much stuff is redundant. Who cares?
  979. if (!g_sOptions.bRenderMats && !bAlpha)
  980. {
  981. // this is very similar to the code in SetupMaterial()
  982. ID3DXEffect* piEnd = g_piDefaultEffect;
  983. piEnd->SetMatrix("WorldViewProjection",
  984. (const D3DXMATRIX*)&pcProj);
  985. piEnd->SetMatrix("World",(const D3DXMATRIX*)&aiMe);
  986. piEnd->SetMatrix("WorldInverseTranspose",
  987. (const D3DXMATRIX*)&pcCam);
  988. if ( CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  989. {
  990. pcCam = pcCam * pcProj;
  991. piEnd->SetMatrix("ViewProj",(const D3DXMATRIX*)&pcCam);
  992. pcCam.Inverse();
  993. piEnd->SetMatrix("InvViewProj",
  994. (const D3DXMATRIX*)&pcCam);
  995. }
  996. D3DXVECTOR4 apcVec[5];
  997. apcVec[0].x = g_avLightDirs[0].x;
  998. apcVec[0].y = g_avLightDirs[0].y;
  999. apcVec[0].z = g_avLightDirs[0].z;
  1000. apcVec[1].x = g_avLightDirs[0].x * -1.0f;
  1001. apcVec[1].y = g_avLightDirs[0].y * -1.0f;
  1002. apcVec[1].z = g_avLightDirs[0].z * -1.0f;
  1003. D3DXVec4Normalize(&apcVec[0],&apcVec[0]);
  1004. D3DXVec4Normalize(&apcVec[1],&apcVec[1]);
  1005. piEnd->SetVectorArray("afLightDir",apcVec,5);
  1006. if(g_sOptions.b3Lights)
  1007. {
  1008. apcVec[0].x = 0.6f;
  1009. apcVec[0].y = 0.6f;
  1010. apcVec[0].z = 0.6f;
  1011. apcVec[0].w = 1.0f;
  1012. apcVec[1].x = 0.3f;
  1013. apcVec[1].y = 0.0f;
  1014. apcVec[1].z = 0.0f;
  1015. apcVec[1].w = 1.0f;
  1016. }
  1017. else
  1018. {
  1019. apcVec[0].x = 1.0f;
  1020. apcVec[0].y = 1.0f;
  1021. apcVec[0].z = 1.0f;
  1022. apcVec[0].w = 1.0f;
  1023. apcVec[1].x = 0.0f;
  1024. apcVec[1].y = 0.0f;
  1025. apcVec[1].z = 0.0f;
  1026. apcVec[1].w = 0.0f;
  1027. }
  1028. apcVec[0] *= g_fLightIntensity;
  1029. apcVec[1] *= g_fLightIntensity;
  1030. piEnd->SetVectorArray("afLightColor",apcVec,5);
  1031. apcVec[0].x = vPos.x;
  1032. apcVec[0].y = vPos.y;
  1033. apcVec[0].z = vPos.z;
  1034. piEnd->SetVector( "vCameraPos",&apcVec[0]);
  1035. if (g_sCaps.PixelShaderVersion < D3DPS_VERSION(3,0) || g_sOptions.bLowQuality)
  1036. {
  1037. if (g_sOptions.b3Lights)
  1038. piEnd->SetTechnique("DefaultFXSpecular_PS20_D2");
  1039. else piEnd->SetTechnique("DefaultFXSpecular_PS20_D1");
  1040. }
  1041. else
  1042. {
  1043. if (g_sOptions.b3Lights)
  1044. piEnd->SetTechnique("DefaultFXSpecular_D2");
  1045. else piEnd->SetTechnique("DefaultFXSpecular_D1");
  1046. }
  1047. UINT dwPasses = 0;
  1048. piEnd->Begin(&dwPasses,0);
  1049. piEnd->BeginPass(0);
  1050. }
  1051. D3DXVECTOR4 vVector = g_aclNormalColors[g_iCurrentColor];
  1052. if (++g_iCurrentColor == 14)
  1053. {
  1054. g_iCurrentColor = 0;
  1055. }
  1056. if (! (!g_sOptions.bRenderMats && bAlpha))
  1057. {
  1058. for (unsigned int i = 0; i < piNode->mNumMeshes;++i)
  1059. {
  1060. // don't render the mesh if the render pass is incorrect
  1061. if (g_sOptions.bRenderMats && (
  1062. g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piOpacityTexture ||
  1063. g_pcAsset->apcMeshes[piNode->mMeshes[i]]->fOpacity != 1.0f))
  1064. {
  1065. if (!bAlpha)continue;
  1066. }
  1067. else if (bAlpha)continue;
  1068. // set vertex and index buffer and the material ...
  1069. g_piDevice->SetStreamSource(0,
  1070. g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVB,0,
  1071. sizeof(AssetHelper::Vertex));
  1072. // now setup the material
  1073. if (g_sOptions.bRenderMats)
  1074. SetupMaterial(g_pcAsset->apcMeshes[piNode->mMeshes[i]],pcProj,aiMe,pcCam,vPos);
  1075. g_piDevice->SetIndices(g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piIB);
  1076. g_piDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
  1077. 0,0,
  1078. g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumVertices,0,
  1079. g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumFaces);
  1080. // now end the material
  1081. if (g_sOptions.bRenderMats)
  1082. EndMaterial(g_pcAsset->apcMeshes[piNode->mMeshes[i]]);
  1083. // render normal vectors?
  1084. if (g_sOptions.bRenderNormals && g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVBNormals)
  1085. {
  1086. // this is very similar to the code in SetupMaterial()
  1087. ID3DXEffect* piEnd = g_piNormalsEffect;
  1088. piEnd->SetVector("OUTPUT_COLOR",&vVector);
  1089. piEnd->SetMatrix("WorldViewProjection",
  1090. (const D3DXMATRIX*)&pcProj);
  1091. UINT dwPasses = 0;
  1092. piEnd->Begin(&dwPasses,0);
  1093. piEnd->BeginPass(0);
  1094. g_piDevice->SetStreamSource(0,
  1095. g_pcAsset->apcMeshes[piNode->mMeshes[i]]->piVBNormals,0,
  1096. sizeof(AssetHelper::LineVertex));
  1097. g_piDevice->DrawPrimitive(D3DPT_LINELIST,0,
  1098. g_pcAsset->pcScene->mMeshes[piNode->mMeshes[i]]->mNumVertices);
  1099. piEnd->EndPass();
  1100. piEnd->End();
  1101. }
  1102. }
  1103. if (!g_sOptions.bRenderMats)
  1104. {
  1105. g_piDefaultEffect->EndPass();
  1106. g_piDefaultEffect->End();
  1107. }
  1108. }
  1109. for (unsigned int i = 0; i < piNode->mNumChildren;++i)
  1110. {
  1111. RenderNode(piNode->mChildren[i],aiMe,bAlpha );
  1112. }
  1113. return 1;
  1114. }
  1115. //-------------------------------------------------------------------------------
  1116. //-------------------------------------------------------------------------------
  1117. int Render (void)
  1118. {
  1119. g_iCurrentColor = 0;
  1120. // setup wireframe/solid rendering mode
  1121. if (g_sOptions.eDrawMode == RenderOptions::WIREFRAME)
  1122. {
  1123. g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
  1124. }
  1125. else g_piDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_SOLID);
  1126. g_piDevice->BeginScene();
  1127. // draw the scene background (clear and texture 2d)
  1128. CBackgroundPainter::Instance().OnPreRender();
  1129. // draw all opaque objects in the scene
  1130. aiMatrix4x4 m;
  1131. if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
  1132. {
  1133. if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  1134. HandleMouseInputSkyBox();
  1135. // handle input commands
  1136. HandleMouseInputLightRotate();
  1137. HandleMouseInputLightIntensityAndColor();
  1138. if(g_bFPSView)
  1139. {
  1140. HandleMouseInputFPS();
  1141. HandleKeyboardInputFPS();
  1142. }
  1143. else
  1144. {
  1145. HandleMouseInputLocal();
  1146. }
  1147. // compute auto rotation depending on the time passed
  1148. if (g_sOptions.bRotate)
  1149. {
  1150. aiMatrix4x4 mMat;
  1151. D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
  1152. g_vRotateSpeed.x * g_fElpasedTime,
  1153. g_vRotateSpeed.y * g_fElpasedTime,
  1154. g_vRotateSpeed.z * g_fElpasedTime);
  1155. g_mWorldRotate = g_mWorldRotate * mMat;
  1156. }
  1157. // Handle rotations of light source(s)
  1158. if (g_sOptions.bLightRotate)
  1159. {
  1160. aiMatrix4x4 mMat;
  1161. D3DXMatrixRotationYawPitchRoll((D3DXMATRIX*)&mMat,
  1162. g_vRotateSpeed.x * g_fElpasedTime * 0.5f,
  1163. g_vRotateSpeed.y * g_fElpasedTime * 0.5f,
  1164. g_vRotateSpeed.z * g_fElpasedTime * 0.5f);
  1165. D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[0],
  1166. (D3DXVECTOR3*)&g_avLightDirs[0],(D3DXMATRIX*)&mMat);
  1167. // 2 lights to rotate?
  1168. if (g_sOptions.b3Lights)
  1169. {
  1170. D3DXVec3TransformNormal((D3DXVECTOR3*)&g_avLightDirs[1],
  1171. (D3DXVECTOR3*)&g_avLightDirs[1],(D3DXMATRIX*)&mMat);
  1172. g_avLightDirs[1].Normalize();
  1173. }
  1174. g_avLightDirs[0].Normalize();
  1175. }
  1176. m = g_mWorld * g_mWorldRotate ;
  1177. RenderNode(g_pcAsset->pcScene->mRootNode,m,false);
  1178. }
  1179. // if a cube texture is loaded as background image, the user
  1180. // should be able to rotate it even if no asset is loaded
  1181. else if(CBackgroundPainter::TEXTURE_CUBE == CBackgroundPainter::Instance().GetMode())
  1182. {
  1183. if (g_bFPSView)
  1184. {
  1185. HandleMouseInputFPS();
  1186. HandleKeyboardInputFPS();
  1187. }
  1188. HandleMouseInputSkyBox();
  1189. // need to store the last mouse position in the global variable
  1190. // HandleMouseInputFPS() is doing this internally
  1191. if (!g_bFPSView)
  1192. {
  1193. g_LastmousePos.x = g_mousePos.x;
  1194. g_LastmousePos.y = g_mousePos.y;
  1195. }
  1196. }
  1197. // draw the scene background
  1198. CBackgroundPainter::Instance().OnPostRender();
  1199. // draw all non-opaque objects in the scene
  1200. if (NULL != g_pcAsset && NULL != g_pcAsset->pcScene->mRootNode)
  1201. {
  1202. RenderNode(g_pcAsset->pcScene->mRootNode,m,true);
  1203. }
  1204. // draw the HUD texture on top of the rendered scene using
  1205. // pre-projected vertices
  1206. if (!g_bFPSView && g_pcAsset && g_pcTexture)
  1207. {
  1208. RECT sRect;
  1209. GetWindowRect(GetDlgItem(g_hDlg,IDC_RT),&sRect);
  1210. sRect.right -= sRect.left;
  1211. sRect.bottom -= sRect.top;
  1212. struct SVertex
  1213. {
  1214. float x,y,z,w,u,v;
  1215. };
  1216. UINT dw;
  1217. g_piPassThroughEffect->Begin(&dw,0);
  1218. g_piPassThroughEffect->BeginPass(0);
  1219. D3DSURFACE_DESC sDesc;
  1220. g_pcTexture->GetLevelDesc(0,&sDesc);
  1221. SVertex as[4];
  1222. float fHalfX = ((float)sRect.right-(float)sDesc.Width) / 2.0f;
  1223. float fHalfY = ((float)sRect.bottom-(float)sDesc.Height) / 2.0f;
  1224. as[1].x = fHalfX;
  1225. as[1].y = fHalfY;
  1226. as[1].z = 0.2f;
  1227. as[1].w = 1.0f;
  1228. as[1].u = 0.0f;
  1229. as[1].v = 0.0f;
  1230. as[3].x = (float)sRect.right-fHalfX;
  1231. as[3].y = fHalfY;
  1232. as[3].z = 0.2f;
  1233. as[3].w = 1.0f;
  1234. as[3].u = 1.0f;
  1235. as[3].v = 0.0f;
  1236. as[0].x = fHalfX;
  1237. as[0].y = (float)sRect.bottom-fHalfY;
  1238. as[0].z = 0.2f;
  1239. as[0].w = 1.0f;
  1240. as[0].u = 0.0f;
  1241. as[0].v = 1.0f;
  1242. as[2].x = (float)sRect.right-fHalfX;
  1243. as[2].y = (float)sRect.bottom-fHalfY;
  1244. as[2].z = 0.2f;
  1245. as[2].w = 1.0f;
  1246. as[2].u = 1.0f;
  1247. as[2].v = 1.0f;
  1248. as[0].x -= 0.5f;as[1].x -= 0.5f;as[2].x -= 0.5f;as[3].x -= 0.5f;
  1249. as[0].y -= 0.5f;as[1].y -= 0.5f;as[2].y -= 0.5f;as[3].y -= 0.5f;
  1250. DWORD dw2;g_piDevice->GetFVF(&dw2);
  1251. g_piDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
  1252. g_piDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,
  1253. &as,sizeof(SVertex));
  1254. g_piPassThroughEffect->EndPass();
  1255. g_piPassThroughEffect->End();
  1256. g_piDevice->SetFVF(dw2);
  1257. }
  1258. // Now render the log display in the upper right corner of the window
  1259. CLogDisplay::Instance().OnRender();
  1260. // present the backbuffer
  1261. g_piDevice->EndScene();
  1262. g_piDevice->Present(NULL,NULL,NULL,NULL);
  1263. // don't remove this, problems on some older machines (AMD timing bug)
  1264. Sleep(10);
  1265. return 1;
  1266. }
  1267. };