Mesh.cpp 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603
  1. //--------------------------------------------------------------------------------------
  2. // File: Mesh.cpp
  3. //
  4. // Mesh processing helper class
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //
  13. // http://go.microsoft.com/fwlink/?LinkID=324981
  14. //--------------------------------------------------------------------------------------
  15. #include "mesh.h"
  16. #include <DirectXPackedVector.h>
  17. #include <DirectXCollision.h>
  18. #include <UVAtlas.h>
  19. using namespace DirectX;
  20. namespace
  21. {
  22. struct handle_closer { void operator()(HANDLE h) { if (h) CloseHandle(h); } };
  23. typedef public std::unique_ptr<void, handle_closer> ScopedHandle;
  24. inline HANDLE safe_handle(HANDLE h) { return (h == INVALID_HANDLE_VALUE) ? 0 : h; }
  25. template<typename T> inline HRESULT write_file(HANDLE hFile, const T& value)
  26. {
  27. DWORD bytesWritten;
  28. if (!WriteFile(hFile, &value, static_cast<DWORD>(sizeof(T)), &bytesWritten, nullptr))
  29. return HRESULT_FROM_WIN32(GetLastError());
  30. if (bytesWritten != sizeof(T))
  31. return E_FAIL;
  32. return S_OK;
  33. }
  34. inline HRESULT write_file_string(HANDLE hFile, const WCHAR* value)
  35. {
  36. UINT length = (value) ? static_cast<UINT>( wcslen(value)+1 ) : 1;
  37. DWORD bytesWritten;
  38. if (!WriteFile(hFile, &length, static_cast<DWORD>(sizeof(UINT)), &bytesWritten, nullptr))
  39. return HRESULT_FROM_WIN32(GetLastError());
  40. if (bytesWritten != sizeof(UINT))
  41. return E_FAIL;
  42. if (length > 0)
  43. {
  44. DWORD bytes = static_cast<DWORD>(sizeof(WCHAR) * length);
  45. if (!WriteFile(hFile, value, bytes, &bytesWritten, nullptr))
  46. return HRESULT_FROM_WIN32(GetLastError());
  47. if (bytesWritten != bytes)
  48. return E_FAIL;
  49. }
  50. else
  51. {
  52. WCHAR nul = 0;
  53. if (!WriteFile(hFile, &nul, sizeof(WCHAR), &bytesWritten, nullptr))
  54. return HRESULT_FROM_WIN32(GetLastError());
  55. if (bytesWritten != sizeof(WCHAR))
  56. return E_FAIL;
  57. }
  58. return S_OK;
  59. }
  60. inline UINT64 roundup4k(UINT64 value)
  61. {
  62. return ((value + 4095) / 4096) * 4096;
  63. }
  64. static const uint8_t g_padding[4096] = { 0 };
  65. }
  66. // Move constructor
  67. Mesh::Mesh(Mesh&& moveFrom)
  68. {
  69. *this = std::move(moveFrom);
  70. }
  71. // Move operator
  72. Mesh& Mesh::operator= (Mesh&& moveFrom)
  73. {
  74. if (this != &moveFrom)
  75. {
  76. mnFaces = moveFrom.mnFaces;
  77. mnVerts = moveFrom.mnVerts;
  78. mIndices.swap( moveFrom.mIndices );
  79. mAttributes.swap( moveFrom.mAttributes );
  80. mAdjacency.swap( moveFrom.mAdjacency );
  81. mPositions.swap( moveFrom.mPositions );
  82. mNormals.swap( moveFrom.mNormals );
  83. mTangents.swap( moveFrom.mTangents );
  84. mBiTangents.swap( moveFrom.mBiTangents );
  85. mTexCoords.swap( moveFrom.mTexCoords );
  86. mColors.swap( moveFrom.mColors );
  87. mBlendIndices.swap( moveFrom.mBlendIndices );
  88. mBlendWeights.swap( moveFrom.mBlendWeights );
  89. }
  90. return *this;
  91. }
  92. //--------------------------------------------------------------------------------------
  93. void Mesh::Clear()
  94. {
  95. mnFaces = mnVerts = 0;
  96. // Release face data
  97. mIndices.reset();
  98. mAttributes.reset();
  99. mAdjacency.reset();
  100. // Release vertex data
  101. mPositions.reset();
  102. mNormals.reset();
  103. mTangents.reset();
  104. mBiTangents.reset();
  105. mTexCoords.reset();
  106. mColors.reset();
  107. mBlendIndices.reset();
  108. mBlendWeights.reset();
  109. }
  110. //--------------------------------------------------------------------------------------
  111. _Use_decl_annotations_
  112. HRESULT Mesh::SetIndexData( size_t nFaces, const uint16_t* indices, uint32_t* attributes )
  113. {
  114. if ( !nFaces || !indices )
  115. return E_INVALIDARG;
  116. if ( ( uint64_t(nFaces) * 3 ) >= UINT32_MAX )
  117. return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
  118. // Release face data
  119. mnFaces = 0;
  120. mIndices.reset();
  121. mAttributes.reset();
  122. std::unique_ptr<uint32_t[]> ib(new (std::nothrow) uint32_t[nFaces * 3]);
  123. if (!ib)
  124. return E_OUTOFMEMORY;
  125. for( size_t j = 0; j < (nFaces*3); ++j )
  126. {
  127. if ( indices[ j ] == uint16_t(-1) )
  128. {
  129. ib[ j ] = uint32_t(-1);
  130. }
  131. else
  132. {
  133. ib[ j ] = indices[ j ];
  134. }
  135. }
  136. std::unique_ptr<uint32_t[]> attr;
  137. if ( attributes )
  138. {
  139. attr.reset( new (std::nothrow) uint32_t[ nFaces ] );
  140. if ( !attr )
  141. return E_OUTOFMEMORY;
  142. memcpy( attr.get(), attributes, sizeof(uint32_t) * nFaces);
  143. }
  144. mIndices.swap(ib);
  145. mAttributes.swap(attr);
  146. mnFaces = nFaces;
  147. return S_OK;
  148. }
  149. _Use_decl_annotations_
  150. HRESULT Mesh::SetIndexData( size_t nFaces, const uint32_t* indices, uint32_t* attributes )
  151. {
  152. if ( !nFaces || !indices )
  153. return E_INVALIDARG;
  154. if ( ( uint64_t(nFaces) * 3 ) >= UINT32_MAX )
  155. return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
  156. mnFaces = 0;
  157. mIndices.reset();
  158. mAttributes.reset();
  159. std::unique_ptr<uint32_t[]> ib( new (std::nothrow) uint32_t[ nFaces * 3] );
  160. if ( !ib )
  161. return E_OUTOFMEMORY;
  162. memcpy( ib.get(), indices, sizeof(uint32_t) * nFaces * 3 );
  163. std::unique_ptr<uint32_t[]> attr;
  164. if ( attributes )
  165. {
  166. attr.reset( new (std::nothrow) uint32_t[ nFaces ] );
  167. if ( !attr )
  168. return E_OUTOFMEMORY;
  169. memcpy( attr.get(), attributes, sizeof(uint32_t) * nFaces );
  170. }
  171. mIndices.swap(ib);
  172. mAttributes.swap(attr);
  173. mnFaces = nFaces;
  174. return S_OK;
  175. }
  176. //--------------------------------------------------------------------------------------
  177. HRESULT Mesh::SetVertexData( _Inout_ DirectX::VBReader& reader, _In_ size_t nVerts )
  178. {
  179. if ( !nVerts )
  180. return E_INVALIDARG;
  181. // Release vertex data
  182. mnVerts = 0;
  183. mPositions.reset();
  184. mNormals.reset();
  185. mTangents.reset();
  186. mBiTangents.reset();
  187. mTexCoords.reset();
  188. mColors.reset();
  189. mBlendIndices.reset();
  190. mBlendWeights.reset();
  191. // Load positions (required)
  192. std::unique_ptr<XMFLOAT3[]> pos( new (std::nothrow) XMFLOAT3[ nVerts ] );
  193. if (!pos)
  194. return E_OUTOFMEMORY;
  195. HRESULT hr = reader.Read(pos.get(), "SV_Position", 0, nVerts);
  196. if (FAILED(hr))
  197. return hr;
  198. // Load normals
  199. std::unique_ptr<XMFLOAT3[]> norms;
  200. auto e = reader.GetElement("NORMAL", 0);
  201. if (e)
  202. {
  203. norms.reset(new (std::nothrow) XMFLOAT3[nVerts]);
  204. if (!norms)
  205. return E_OUTOFMEMORY;
  206. hr = reader.Read(norms.get(), "NORMAL", 0, nVerts);
  207. if (FAILED(hr))
  208. return hr;
  209. }
  210. // Load tangents
  211. std::unique_ptr<XMFLOAT4[]> tans1;
  212. e = reader.GetElement("TANGENT", 0);
  213. if (e)
  214. {
  215. tans1.reset(new (std::nothrow) XMFLOAT4[nVerts]);
  216. if (!tans1)
  217. return E_OUTOFMEMORY;
  218. hr = reader.Read(tans1.get(), "TANGENT", 0, nVerts);
  219. if (FAILED(hr))
  220. return hr;
  221. }
  222. // Load bi-tangents
  223. std::unique_ptr<XMFLOAT3[]> tans2;
  224. e = reader.GetElement("BINORMAL", 0);
  225. if (e)
  226. {
  227. tans2.reset(new (std::nothrow) XMFLOAT3[nVerts]);
  228. if (!tans2)
  229. return E_OUTOFMEMORY;
  230. hr = reader.Read(tans2.get(), "BINORMAL", 0, nVerts);
  231. if (FAILED(hr))
  232. return hr;
  233. }
  234. // Load texture coordinates
  235. std::unique_ptr<XMFLOAT2[]> texcoord;
  236. e = reader.GetElement("TEXCOORD", 0);
  237. if (e)
  238. {
  239. texcoord.reset(new (std::nothrow) XMFLOAT2[nVerts]);
  240. if (!texcoord)
  241. return E_OUTOFMEMORY;
  242. hr = reader.Read(texcoord.get(), "TEXCOORD", 0, nVerts);
  243. if (FAILED(hr))
  244. return hr;
  245. }
  246. // Load vertex colors
  247. std::unique_ptr<XMFLOAT4[]> colors;
  248. e = reader.GetElement("COLOR", 0);
  249. if (e)
  250. {
  251. colors.reset(new (std::nothrow) XMFLOAT4[nVerts]);
  252. if (!colors)
  253. return E_OUTOFMEMORY;
  254. hr = reader.Read(colors.get(), "COLOR", 0, nVerts);
  255. if (FAILED(hr))
  256. return hr;
  257. }
  258. // Load skinning bone indices
  259. std::unique_ptr<XMFLOAT4[]> blendIndices;
  260. e = reader.GetElement("BLENDINDICES", 0);
  261. if (e)
  262. {
  263. blendIndices.reset(new (std::nothrow) XMFLOAT4[nVerts]);
  264. if (!blendIndices)
  265. return E_OUTOFMEMORY;
  266. hr = reader.Read(blendIndices.get(), "BLENDINDICES", 0, nVerts);
  267. if (FAILED(hr))
  268. return hr;
  269. }
  270. // Load skinning bone weights
  271. std::unique_ptr<XMFLOAT4[]> blendWeights;
  272. e = reader.GetElement("BLENDWEIGHT", 0);
  273. if (e)
  274. {
  275. blendWeights.reset(new (std::nothrow) XMFLOAT4[nVerts]);
  276. if (!blendWeights)
  277. return E_OUTOFMEMORY;
  278. hr = reader.Read(blendWeights.get(), "BLENDWEIGHT", 0, nVerts);
  279. if (FAILED(hr))
  280. return hr;
  281. }
  282. // Return values
  283. mPositions.swap( pos );
  284. mNormals.swap( norms );
  285. mTangents.swap( tans1 );
  286. mBiTangents.swap( tans2 );
  287. mTexCoords.swap( texcoord );
  288. mColors.swap( colors );
  289. mBlendIndices.swap( blendIndices );
  290. mBlendWeights.swap( blendWeights );
  291. mnVerts = nVerts;
  292. return S_OK;
  293. }
  294. //--------------------------------------------------------------------------------------
  295. _Use_decl_annotations_
  296. HRESULT Mesh::Validate(DWORD flags, std::wstring* msgs) const
  297. {
  298. if (!mnFaces || !mIndices || !mnVerts)
  299. return E_UNEXPECTED;
  300. return DirectX::Validate(mIndices.get(), mnFaces, mnVerts, mAdjacency.get(), flags, msgs);
  301. }
  302. //--------------------------------------------------------------------------------------
  303. HRESULT Mesh::Clean( _In_ bool breakBowties )
  304. {
  305. if (!mnFaces || !mIndices || !mnVerts || !mPositions)
  306. return E_UNEXPECTED;
  307. std::vector<uint32_t> dups;
  308. HRESULT hr = DirectX::Clean(mIndices.get(), mnFaces, mnVerts, mAdjacency.get(), mAttributes.get(), dups, breakBowties);
  309. if (FAILED(hr))
  310. return hr;
  311. if (dups.empty())
  312. {
  313. // No vertex duplication is needed for mesh clean
  314. return S_OK;
  315. }
  316. size_t nNewVerts = mnVerts + dups.size();
  317. std::unique_ptr<XMFLOAT3[]> pos(new (std::nothrow) XMFLOAT3[nNewVerts]);
  318. if (!pos)
  319. return E_OUTOFMEMORY;
  320. memcpy(pos.get(), mPositions.get(), sizeof(XMFLOAT3) * mnVerts);
  321. std::unique_ptr<XMFLOAT3[]> norms;
  322. if (mNormals)
  323. {
  324. norms.reset(new (std::nothrow) XMFLOAT3[nNewVerts]);
  325. if (!norms)
  326. return E_OUTOFMEMORY;
  327. memcpy(norms.get(), mNormals.get(), sizeof(XMFLOAT3) * mnVerts);
  328. }
  329. std::unique_ptr<XMFLOAT4[]> tans1;
  330. if (mTangents)
  331. {
  332. tans1.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  333. if (!tans1)
  334. return E_OUTOFMEMORY;
  335. memcpy(tans1.get(), mTangents.get(), sizeof(XMFLOAT4) * mnVerts);
  336. }
  337. std::unique_ptr<XMFLOAT3[]> tans2;
  338. if (mBiTangents)
  339. {
  340. tans2.reset(new (std::nothrow) XMFLOAT3[nNewVerts]);
  341. if (!tans2)
  342. return E_OUTOFMEMORY;
  343. memcpy(tans2.get(), mBiTangents.get(), sizeof(XMFLOAT3) * mnVerts);
  344. }
  345. std::unique_ptr<XMFLOAT2[]> texcoord;
  346. if (mTexCoords)
  347. {
  348. texcoord.reset(new (std::nothrow) XMFLOAT2[nNewVerts]);
  349. if (!texcoord)
  350. return E_OUTOFMEMORY;
  351. memcpy(texcoord.get(), mTexCoords.get(), sizeof(XMFLOAT2) * mnVerts);
  352. }
  353. std::unique_ptr<XMFLOAT4[]> colors;
  354. if (mColors)
  355. {
  356. colors.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  357. if (!colors)
  358. return E_OUTOFMEMORY;
  359. memcpy(colors.get(), mColors.get(), sizeof(XMFLOAT4) * mnVerts);
  360. }
  361. std::unique_ptr<XMFLOAT4[]> blendIndices;
  362. if (mBlendIndices)
  363. {
  364. blendIndices.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  365. if (!blendIndices)
  366. return E_OUTOFMEMORY;
  367. memcpy(blendIndices.get(), mBlendIndices.get(), sizeof(XMFLOAT4) * mnVerts);
  368. }
  369. std::unique_ptr<XMFLOAT4 []> blendWeights;
  370. if (mBlendWeights)
  371. {
  372. blendWeights.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  373. if (!blendWeights)
  374. return E_OUTOFMEMORY;
  375. memcpy(blendWeights.get(), mBlendWeights.get(), sizeof(XMFLOAT4) * mnVerts);
  376. }
  377. size_t j = mnVerts;
  378. for (auto it = dups.begin(); it != dups.end() && (j < nNewVerts); ++it, ++j)
  379. {
  380. assert(*it < mnVerts);
  381. pos[ j ] = mPositions[ *it ];
  382. if (norms)
  383. {
  384. norms[ j ] = mNormals[ *it ];
  385. }
  386. if (tans1)
  387. {
  388. tans1[ j ] = mTangents[ *it ];
  389. }
  390. if (tans2)
  391. {
  392. tans2[ j ] = mBiTangents[*it];
  393. }
  394. if (texcoord)
  395. {
  396. texcoord.get() [ j] = mTexCoords[*it];
  397. }
  398. if (colors)
  399. {
  400. colors[j] = mColors[*it];
  401. }
  402. if (blendIndices)
  403. {
  404. blendIndices[j] = mBlendIndices[*it];
  405. }
  406. if (blendWeights)
  407. {
  408. blendWeights[j] = mBlendWeights[*it];
  409. }
  410. }
  411. mPositions.swap(pos);
  412. mNormals.swap(norms);
  413. mTangents.swap(tans1);
  414. mBiTangents.swap(tans2);
  415. mTexCoords.swap(texcoord);
  416. mColors.swap(colors);
  417. mBlendIndices.swap(blendIndices);
  418. mBlendWeights.swap(blendWeights);
  419. mnVerts = nNewVerts;
  420. return S_OK;
  421. }
  422. //--------------------------------------------------------------------------------------
  423. HRESULT Mesh::GenerateAdjacency( _In_ float epsilon )
  424. {
  425. if (!mnFaces || !mIndices || !mnVerts || !mPositions)
  426. return E_UNEXPECTED;
  427. if ((uint64_t(mnFaces) * 3) >= UINT32_MAX)
  428. return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
  429. mAdjacency.reset( new (std::nothrow) uint32_t[ mnFaces * 3 ] );
  430. if ( !mAdjacency )
  431. return E_OUTOFMEMORY;
  432. return DirectX::GenerateAdjacencyAndPointReps(mIndices.get(), mnFaces, mPositions.get(), mnVerts, epsilon, nullptr, mAdjacency.get());
  433. }
  434. //--------------------------------------------------------------------------------------
  435. HRESULT Mesh::ComputeNormals( _In_ DWORD flags )
  436. {
  437. if (!mnFaces || !mIndices || !mnVerts || !mPositions)
  438. return E_UNEXPECTED;
  439. mNormals.reset( new (std::nothrow) XMFLOAT3[ mnVerts ] );
  440. if (!mNormals)
  441. return E_OUTOFMEMORY;
  442. return DirectX::ComputeNormals(mIndices.get(), mnFaces, mPositions.get(), mnVerts, flags, mNormals.get());
  443. }
  444. //--------------------------------------------------------------------------------------
  445. HRESULT Mesh::ComputeTangentFrame( _In_ bool bitangents )
  446. {
  447. if (!mnFaces || !mIndices || !mnVerts || !mPositions || !mNormals || !mTexCoords)
  448. return E_UNEXPECTED;
  449. mTangents.reset();
  450. mBiTangents.reset();
  451. std::unique_ptr<XMFLOAT4[]> tan1( new (std::nothrow) XMFLOAT4[mnVerts] );
  452. if (!tan1)
  453. return E_OUTOFMEMORY;
  454. std::unique_ptr<XMFLOAT3[]> tan2;
  455. if (bitangents)
  456. {
  457. tan2.reset( new (std::nothrow) XMFLOAT3[mnVerts] );
  458. if (!tan2)
  459. return E_OUTOFMEMORY;
  460. HRESULT hr = DirectX::ComputeTangentFrame(mIndices.get(), mnFaces, mPositions.get(), mNormals.get(), mTexCoords.get(), mnVerts,
  461. tan1.get(), tan2.get());
  462. if (FAILED(hr))
  463. return hr;
  464. }
  465. else
  466. {
  467. mBiTangents.reset();
  468. HRESULT hr = DirectX::ComputeTangentFrame(mIndices.get(), mnFaces, mPositions.get(), mNormals.get(), mTexCoords.get(), mnVerts,
  469. tan1.get());
  470. if (FAILED(hr))
  471. return hr;
  472. }
  473. mTangents.swap( tan1 );
  474. mBiTangents.swap( tan2 );
  475. return S_OK;
  476. }
  477. //--------------------------------------------------------------------------------------
  478. _Use_decl_annotations_
  479. HRESULT Mesh::UpdateFaces( size_t nFaces, const uint32_t* indices )
  480. {
  481. if (!nFaces || !indices)
  482. return E_INVALIDARG;
  483. if (!mnFaces || !mIndices)
  484. return E_UNEXPECTED;
  485. if ( mnFaces != nFaces )
  486. return E_FAIL;
  487. if ((uint64_t(nFaces) * 3) >= UINT32_MAX)
  488. return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
  489. memcpy( mIndices.get(), indices, sizeof(uint32_t) * 3 * nFaces );
  490. return S_OK;
  491. }
  492. //--------------------------------------------------------------------------------------
  493. _Use_decl_annotations_
  494. HRESULT Mesh::UpdateAttributes( size_t nFaces, const uint32_t* attributes )
  495. {
  496. if (!nFaces || !attributes)
  497. return E_INVALIDARG;
  498. if (!mnFaces || !mIndices || !mnVerts || !mPositions)
  499. return E_UNEXPECTED;
  500. if ( mnFaces != nFaces )
  501. return E_FAIL;
  502. if ( !mAttributes )
  503. {
  504. std::unique_ptr<uint32_t[]> attr( new (std::nothrow) uint32_t[ nFaces ] );
  505. if ( !attr )
  506. return E_OUTOFMEMORY;
  507. memcpy( attr.get(), attributes, sizeof(uint32_t) * nFaces );
  508. mAttributes.swap(attr);
  509. }
  510. else
  511. {
  512. memcpy( mAttributes.get(), attributes, sizeof(uint32_t) * nFaces );
  513. }
  514. std::unique_ptr<uint32_t> remap(new (std::nothrow) uint32_t[mnFaces]);
  515. if (!remap)
  516. return E_OUTOFMEMORY;
  517. HRESULT hr = AttributeSort(mnFaces, mAttributes.get(), remap.get());
  518. if (FAILED(hr))
  519. return hr;
  520. if (mAdjacency)
  521. {
  522. hr = ReorderIBAndAdjacency(mIndices.get(), mnFaces, mAdjacency.get(), remap.get());
  523. }
  524. else
  525. {
  526. hr = ReorderIB(mIndices.get(), mnFaces, remap.get());
  527. }
  528. if (FAILED(hr))
  529. return hr;
  530. return S_OK;
  531. }
  532. //--------------------------------------------------------------------------------------
  533. _Use_decl_annotations_
  534. HRESULT Mesh::UpdateUVs(size_t nVerts, const XMFLOAT2* uvs)
  535. {
  536. if (!nVerts || !uvs)
  537. return E_INVALIDARG;
  538. if (!mnVerts || !mPositions)
  539. return E_UNEXPECTED;
  540. if (nVerts != mnVerts)
  541. return E_FAIL;
  542. if (!mTexCoords)
  543. {
  544. std::unique_ptr<XMFLOAT2 []> texcoord;
  545. texcoord.reset(new (std::nothrow) XMFLOAT2[mnVerts]);
  546. if (!texcoord)
  547. return E_OUTOFMEMORY;
  548. memcpy(texcoord.get(), uvs, sizeof(XMFLOAT2) * mnVerts);
  549. mTexCoords.swap(texcoord);
  550. }
  551. else
  552. {
  553. memcpy(mTexCoords.get(), uvs, sizeof(XMFLOAT2) * mnVerts);
  554. }
  555. return S_OK;
  556. }
  557. //--------------------------------------------------------------------------------------
  558. _Use_decl_annotations_
  559. HRESULT Mesh::VertexRemap( const uint32_t* remap, size_t nNewVerts )
  560. {
  561. if (!remap || !nNewVerts)
  562. return E_INVALIDARG;
  563. if (!mnVerts || !mPositions)
  564. return E_UNEXPECTED;
  565. if (nNewVerts < mnVerts)
  566. return E_FAIL;
  567. std::unique_ptr<XMFLOAT3[]> pos(new (std::nothrow) XMFLOAT3[nNewVerts]);
  568. if (!pos)
  569. return E_OUTOFMEMORY;
  570. HRESULT hr = UVAtlasApplyRemap(mPositions.get(), sizeof(XMFLOAT3), mnVerts, nNewVerts, remap, pos.get() );
  571. if (FAILED(hr))
  572. return hr;
  573. std::unique_ptr<XMFLOAT3[]> norms;
  574. if (mNormals)
  575. {
  576. norms.reset(new (std::nothrow) XMFLOAT3[nNewVerts]);
  577. if (!norms)
  578. return E_OUTOFMEMORY;
  579. hr = UVAtlasApplyRemap(mNormals.get(), sizeof(XMFLOAT3), mnVerts, nNewVerts, remap, norms.get() );
  580. if (FAILED(hr))
  581. return hr;
  582. }
  583. std::unique_ptr<XMFLOAT4[]> tans1;
  584. if (mTangents)
  585. {
  586. tans1.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  587. if (!tans1)
  588. return E_OUTOFMEMORY;
  589. hr = UVAtlasApplyRemap(mTangents.get(), sizeof(XMFLOAT4), mnVerts, nNewVerts, remap, tans1.get() );
  590. if (FAILED(hr))
  591. return hr;
  592. }
  593. std::unique_ptr<XMFLOAT3[]> tans2;
  594. if (mBiTangents)
  595. {
  596. tans2.reset(new (std::nothrow) XMFLOAT3[nNewVerts]);
  597. if (!tans2)
  598. return E_OUTOFMEMORY;
  599. hr = UVAtlasApplyRemap(mBiTangents.get(), sizeof(XMFLOAT3), mnVerts, nNewVerts, remap, tans2.get() );
  600. if (FAILED(hr))
  601. return hr;
  602. }
  603. std::unique_ptr<XMFLOAT2[]> texcoord;
  604. if (mTexCoords)
  605. {
  606. texcoord.reset(new (std::nothrow) XMFLOAT2[nNewVerts]);
  607. if (!texcoord)
  608. return E_OUTOFMEMORY;
  609. hr = UVAtlasApplyRemap(mTexCoords.get(), sizeof(XMFLOAT2), mnVerts, nNewVerts, remap, texcoord.get() );
  610. if (FAILED(hr))
  611. return hr;
  612. }
  613. std::unique_ptr<XMFLOAT4[]> colors;
  614. if (mColors)
  615. {
  616. colors.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  617. if (!colors)
  618. return E_OUTOFMEMORY;
  619. hr = UVAtlasApplyRemap(mColors.get(), sizeof(XMFLOAT4), mnVerts, nNewVerts, remap, colors.get() );
  620. if (FAILED(hr))
  621. return hr;
  622. }
  623. std::unique_ptr<XMFLOAT4[]> blendIndices;
  624. if (mBlendIndices)
  625. {
  626. blendIndices.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  627. if (!blendIndices)
  628. return E_OUTOFMEMORY;
  629. hr = UVAtlasApplyRemap(mBlendIndices.get(), sizeof(XMFLOAT4), mnVerts, nNewVerts, remap, blendIndices.get() );
  630. if (FAILED(hr))
  631. return hr;
  632. }
  633. std::unique_ptr<XMFLOAT4 []> blendWeights;
  634. if (mBlendWeights)
  635. {
  636. blendWeights.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
  637. if (!blendWeights)
  638. return E_OUTOFMEMORY;
  639. hr = UVAtlasApplyRemap(mBlendWeights.get(), sizeof(XMFLOAT4), mnVerts, nNewVerts, remap, blendWeights.get() );
  640. if (FAILED(hr))
  641. return hr;
  642. }
  643. mPositions.swap(pos);
  644. mNormals.swap(norms);
  645. mTangents.swap(tans1);
  646. mBiTangents.swap(tans2);
  647. mTexCoords.swap(texcoord);
  648. mColors.swap(colors);
  649. mBlendIndices.swap(blendIndices);
  650. mBlendWeights.swap(blendWeights);
  651. mnVerts = nNewVerts;
  652. return S_OK;
  653. }
  654. //--------------------------------------------------------------------------------------
  655. HRESULT Mesh::ReverseWinding(bool texcoords)
  656. {
  657. if (!mIndices || !mnFaces)
  658. return E_UNEXPECTED;
  659. auto iptr = mIndices.get();
  660. for (size_t j = 0; j < mnFaces; ++j)
  661. {
  662. std::swap( *iptr, *(iptr + 2) );
  663. iptr += 3;
  664. }
  665. if (texcoords && mTexCoords)
  666. {
  667. auto tptr = mTexCoords.get();
  668. for (size_t j = 0; j < mnVerts; ++j, ++tptr)
  669. {
  670. tptr->x = 1.f - tptr->x;
  671. }
  672. }
  673. return S_OK;
  674. }
  675. //--------------------------------------------------------------------------------------
  676. HRESULT Mesh::VisualizeUVs()
  677. {
  678. if (!mnVerts || !mPositions || !mTexCoords)
  679. return E_UNEXPECTED;
  680. const XMFLOAT2* sptr = mTexCoords.get();
  681. XMFLOAT3* dptr = mPositions.get();
  682. for (size_t j = 0; j < mnVerts; ++j)
  683. {
  684. dptr->x = sptr->x;
  685. dptr->y = sptr->y;
  686. dptr->z = 0;
  687. ++sptr;
  688. ++dptr;
  689. }
  690. if (mNormals)
  691. {
  692. XMFLOAT3* nptr = mNormals.get();
  693. for (size_t j = 0; j < mnVerts; ++j)
  694. {
  695. XMStoreFloat3( nptr, g_XMIdentityR2 );
  696. ++nptr;
  697. }
  698. }
  699. return S_OK;
  700. }
  701. //--------------------------------------------------------------------------------------
  702. bool Mesh::Is16BitIndexBuffer() const
  703. {
  704. if (!mIndices || !mnFaces)
  705. return false;
  706. if ((uint64_t(mnFaces) * 3) >= UINT32_MAX)
  707. return false;
  708. const uint32_t* iptr = mIndices.get();
  709. for (size_t j = 0; j < (mnFaces * 3); ++j )
  710. {
  711. uint32_t index = *(iptr++);
  712. if (index != uint32_t(-1)
  713. && (index >= UINT16_MAX))
  714. {
  715. return false;
  716. }
  717. }
  718. return true;
  719. }
  720. //--------------------------------------------------------------------------------------
  721. std::unique_ptr<uint16_t[]> Mesh::GetIndexBuffer16() const
  722. {
  723. std::unique_ptr<uint16_t[]> ib;
  724. if (!mIndices || !mnFaces)
  725. return ib;
  726. if ((uint64_t(mnFaces) * 3) >= UINT32_MAX)
  727. return ib;
  728. size_t count = mnFaces * 3;
  729. ib.reset(new (std::nothrow) uint16_t[count]);
  730. if (!ib)
  731. return ib;
  732. const uint32_t* iptr = mIndices.get();
  733. for (size_t j = 0; j < count; ++j)
  734. {
  735. uint32_t index = *(iptr++);
  736. if (index == uint32_t(-1))
  737. {
  738. ib[j] = uint16_t(-1);
  739. }
  740. else if (index >= UINT16_MAX)
  741. {
  742. ib.reset();
  743. return ib;
  744. }
  745. else
  746. {
  747. ib[j] = static_cast<uint16_t>(index);
  748. }
  749. }
  750. return ib;
  751. }
  752. //--------------------------------------------------------------------------------------
  753. HRESULT Mesh::GetVertexBuffer(_Inout_ DirectX::VBWriter& writer) const
  754. {
  755. if (!mnVerts || !mPositions)
  756. return E_UNEXPECTED;
  757. HRESULT hr = writer.Write(mPositions.get(), "SV_Position", 0, mnVerts );
  758. if (FAILED(hr))
  759. return hr;
  760. if (mNormals)
  761. {
  762. auto e = writer.GetElement("NORMAL", 0);
  763. if (e)
  764. {
  765. hr = writer.Write(mNormals.get(), "NORMAL", 0, mnVerts);
  766. if (FAILED(hr))
  767. return hr;
  768. }
  769. }
  770. if (mTangents)
  771. {
  772. auto e = writer.GetElement("TANGENT", 0);
  773. if (e)
  774. {
  775. hr = writer.Write(mTangents.get(), "TANGENT", 0, mnVerts);
  776. if (FAILED(hr))
  777. return hr;
  778. }
  779. }
  780. if (mBiTangents)
  781. {
  782. auto e = writer.GetElement("BINORMAL", 0);
  783. if (e)
  784. {
  785. hr = writer.Write(mBiTangents.get(), "BINORMAL", 0, mnVerts);
  786. if (FAILED(hr))
  787. return hr;
  788. }
  789. }
  790. if (mTexCoords)
  791. {
  792. auto e = writer.GetElement("TEXCOORD", 0);
  793. if (e)
  794. {
  795. hr = writer.Write(mTexCoords.get(), "TEXCOORD", 0, mnVerts);
  796. if (FAILED(hr))
  797. return hr;
  798. }
  799. }
  800. if (mColors)
  801. {
  802. auto e = writer.GetElement("COLOR", 0);
  803. if (e)
  804. {
  805. hr = writer.Write(mColors.get(), "COLOR", 0, mnVerts);
  806. if (FAILED(hr))
  807. return hr;
  808. }
  809. }
  810. if (mBlendIndices)
  811. {
  812. auto e = writer.GetElement("BLENDINDICES", 0);
  813. if (e)
  814. {
  815. hr = writer.Write(mBlendIndices.get(), "BLENDINDICES", 0, mnVerts);
  816. if (FAILED(hr))
  817. return hr;
  818. }
  819. }
  820. if (mBlendWeights)
  821. {
  822. auto e = writer.GetElement("BLENDWEIGHT", 0);
  823. if (e)
  824. {
  825. hr = writer.Write(mBlendWeights.get(), "BLENDWEIGHT", 0, mnVerts);
  826. if (FAILED(hr))
  827. return hr;
  828. }
  829. }
  830. return S_OK;
  831. }
  832. //======================================================================================
  833. // VBO
  834. //======================================================================================
  835. namespace VBO
  836. {
  837. #pragma pack(push,1)
  838. struct header_t
  839. {
  840. uint32_t numVertices;
  841. uint32_t numIndices;
  842. };
  843. struct vertex_t
  844. {
  845. DirectX::XMFLOAT3 position;
  846. DirectX::XMFLOAT3 normal;
  847. DirectX::XMFLOAT2 textureCoordinate;
  848. };
  849. #pragma pack(pop)
  850. static_assert(sizeof(header_t) == 8, "VBO header size mismatch");
  851. static_assert(sizeof(vertex_t) == 32, "VBO vertex size mismatch");
  852. }; // namespace
  853. //--------------------------------------------------------------------------------------
  854. _Use_decl_annotations_
  855. HRESULT Mesh::ExportToVBO( const wchar_t* szFileName ) const
  856. {
  857. using namespace VBO;
  858. if ( !szFileName )
  859. return E_INVALIDARG;
  860. if (!mnFaces || !mIndices || !mnVerts || !mPositions || !mNormals || !mTexCoords)
  861. return E_UNEXPECTED;
  862. if ( ( uint64_t(mnFaces) * 3 ) >= UINT32_MAX )
  863. return HRESULT_FROM_WIN32( ERROR_ARITHMETIC_OVERFLOW );
  864. if ( mnVerts >= UINT16_MAX )
  865. return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
  866. // Setup VBO header
  867. header_t header;
  868. header.numVertices = static_cast<uint32_t>( mnVerts );
  869. header.numIndices = static_cast<uint32_t>( mnFaces*3 );
  870. // Setup vertices/indices for VBO
  871. std::unique_ptr<vertex_t[]> vb(new (std::nothrow) vertex_t[mnVerts]);
  872. std::unique_ptr<uint16_t[]> ib(new (std::nothrow) uint16_t[header.numIndices]);
  873. if (!vb || !ib)
  874. return E_OUTOFMEMORY;
  875. // Copy to VB
  876. auto vptr = vb.get();
  877. for (size_t j = 0; j < mnVerts; ++j, ++vptr)
  878. {
  879. vptr->position = mPositions[j];
  880. vptr->normal = mNormals[j];
  881. vptr->textureCoordinate = mTexCoords[j];
  882. }
  883. // Copy to IB
  884. auto iptr = ib.get();
  885. for (size_t j = 0; j < header.numIndices; ++j, ++iptr)
  886. {
  887. uint32_t index = mIndices[j];
  888. if (index == uint32_t(-1))
  889. {
  890. *iptr = uint16_t(-1);
  891. }
  892. else if (index >= UINT16_MAX)
  893. {
  894. return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  895. }
  896. else
  897. {
  898. *iptr = static_cast<uint16_t>(index);
  899. }
  900. }
  901. // Write header and data
  902. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  903. ScopedHandle hFile(safe_handle(CreateFile2(szFileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0)));
  904. #else
  905. ScopedHandle hFile(safe_handle(CreateFileW(szFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)));
  906. #endif
  907. if (!hFile)
  908. return HRESULT_FROM_WIN32(GetLastError());
  909. HRESULT hr = write_file( hFile.get(), header );
  910. if (FAILED(hr))
  911. return hr;
  912. DWORD vertSize = static_cast<DWORD>( sizeof(vertex_t) * header.numVertices );
  913. DWORD bytesWritten;
  914. if (!WriteFile(hFile.get(), vb.get(), vertSize, &bytesWritten, nullptr))
  915. return HRESULT_FROM_WIN32(GetLastError());
  916. if (bytesWritten != vertSize)
  917. return E_FAIL;
  918. DWORD indexSize = static_cast<DWORD>( sizeof(uint16_t) * header.numIndices );
  919. if (!WriteFile(hFile.get(), ib.get(), indexSize, &bytesWritten, nullptr))
  920. return HRESULT_FROM_WIN32(GetLastError());
  921. if (bytesWritten != indexSize)
  922. return E_FAIL;
  923. return S_OK;
  924. }
  925. //--------------------------------------------------------------------------------------
  926. _Use_decl_annotations_
  927. HRESULT Mesh::CreateFromVBO( const wchar_t* szFileName, std::unique_ptr<Mesh>& result )
  928. {
  929. using namespace VBO;
  930. if (!szFileName)
  931. return E_INVALIDARG;
  932. result.reset();
  933. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  934. ScopedHandle hFile(safe_handle(CreateFile2(szFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr)));
  935. #else
  936. ScopedHandle hFile(safe_handle(CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)));
  937. #endif
  938. if (!hFile)
  939. {
  940. return HRESULT_FROM_WIN32(GetLastError());
  941. }
  942. // Get the file size
  943. LARGE_INTEGER FileSize = { 0 };
  944. #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
  945. FILE_STANDARD_INFO fileInfo;
  946. if (!GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo)))
  947. {
  948. return HRESULT_FROM_WIN32(GetLastError());
  949. }
  950. FileSize = fileInfo.EndOfFile;
  951. #else
  952. GetFileSizeEx(hFile.get(), &FileSize);
  953. #endif
  954. // File is too big for 32-bit allocation, so reject read
  955. if (FileSize.HighPart > 0)
  956. return E_FAIL;
  957. // Need at least enough data to read the header
  958. if (FileSize.LowPart < sizeof(header_t))
  959. return E_FAIL;
  960. // Read VBO header
  961. DWORD bytesRead = 0;
  962. header_t header;
  963. if (!ReadFile(hFile.get(), &header, sizeof(header_t), &bytesRead, nullptr))
  964. {
  965. return HRESULT_FROM_WIN32(GetLastError());
  966. }
  967. if (bytesRead != sizeof(header))
  968. return E_FAIL;
  969. if (!header.numVertices || !header.numIndices)
  970. return E_FAIL;
  971. result.reset( new (std::nothrow) Mesh );
  972. if (!result)
  973. return E_OUTOFMEMORY;
  974. // Read vertices/indices from VBO
  975. std::unique_ptr<vertex_t[]> vb(new (std::nothrow) vertex_t[header.numVertices]);
  976. std::unique_ptr<uint16_t[]> ib( new (std::nothrow) uint16_t[ header.numIndices ] );
  977. if (!vb || !ib)
  978. return E_OUTOFMEMORY;
  979. DWORD vertSize = static_cast<DWORD>( sizeof(vertex_t) * header.numVertices );
  980. if (!ReadFile(hFile.get(), vb.get(), vertSize, &bytesRead, nullptr))
  981. {
  982. return HRESULT_FROM_WIN32(GetLastError());
  983. }
  984. if (bytesRead != vertSize)
  985. return E_FAIL;
  986. DWORD indexSize = static_cast<DWORD>(sizeof(uint16_t) * header.numIndices );
  987. if (!ReadFile(hFile.get(), ib.get(), indexSize, &bytesRead, nullptr))
  988. {
  989. return HRESULT_FROM_WIN32(GetLastError());
  990. }
  991. if (bytesRead != indexSize)
  992. return E_FAIL;
  993. // Copy VB to result
  994. std::unique_ptr<XMFLOAT3[]> pos(new (std::nothrow) XMFLOAT3[header.numVertices]);
  995. std::unique_ptr<XMFLOAT3[]> norm(new (std::nothrow) XMFLOAT3[header.numVertices]);
  996. std::unique_ptr<XMFLOAT2[]> texcoord(new (std::nothrow) XMFLOAT2[header.numVertices]);
  997. if (!pos || !norm || !texcoord)
  998. return E_OUTOFMEMORY;
  999. auto vptr = vb.get();
  1000. for (size_t j = 0; j < header.numVertices; ++j, ++vptr)
  1001. {
  1002. pos[ j ] = vptr->position;
  1003. norm[ j ] = vptr->normal;
  1004. texcoord[ j] = vptr->textureCoordinate;
  1005. }
  1006. // Copy IB to result
  1007. std::unique_ptr<uint32_t[]> indices(new (std::nothrow) uint32_t[header.numIndices]);
  1008. if (!indices)
  1009. return E_OUTOFMEMORY;
  1010. auto iptr = ib.get();
  1011. for (size_t j = 0; j < header.numIndices; ++j, ++iptr)
  1012. {
  1013. uint16_t index = *iptr;
  1014. if (index == uint16_t(-1))
  1015. indices[ j ] = uint32_t(-1);
  1016. else
  1017. indices[ j ] = index;
  1018. }
  1019. result->mPositions.swap(pos);
  1020. result->mNormals.swap(norm);
  1021. result->mTexCoords.swap(texcoord);
  1022. result->mIndices.swap(indices);
  1023. result->mnVerts = header.numVertices;
  1024. result->mnFaces = header.numIndices / 3;
  1025. return S_OK;
  1026. }
  1027. //======================================================================================
  1028. // Visual Studio CMO
  1029. //======================================================================================
  1030. //--------------------------------------------------------------------------------------
  1031. // .CMO files are built by Visual Studio 2012 and an example renderer is provided
  1032. // in the VS Direct3D Starter Kit
  1033. // http://code.msdn.microsoft.com/Visual-Studio-3D-Starter-455a15f1
  1034. //--------------------------------------------------------------------------------------
  1035. namespace VSD3DStarter
  1036. {
  1037. // .CMO files
  1038. // UINT - Mesh count
  1039. // { [Mesh count]
  1040. // UINT - Length of name
  1041. // wchar_t[] - Name of mesh (if length > 0)
  1042. // UINT - Material count
  1043. // { [Material count]
  1044. // UINT - Length of material name
  1045. // wchar_t[] - Name of material (if length > 0)
  1046. // Material structure
  1047. // UINT - Length of pixel shader name
  1048. // wchar_t[] - Name of pixel shader (if length > 0)
  1049. // { [8]
  1050. // UINT - Length of texture name
  1051. // wchar_t[] - Name of texture (if length > 0)
  1052. // }
  1053. // }
  1054. // BYTE - 1 if there is skeletal animation data present
  1055. // UINT - SubMesh count
  1056. // { [SubMesh count]
  1057. // SubMesh structure
  1058. // }
  1059. // UINT - IB Count
  1060. // { [IB Count]
  1061. // UINT - Number of USHORTs in IB
  1062. // USHORT[] - Array of indices
  1063. // }
  1064. // UINT - VB Count
  1065. // { [VB Count]
  1066. // UINT - Number of verts in VB
  1067. // Vertex[] - Array of vertices
  1068. // }
  1069. // UINT - Skinning VB Count
  1070. // { [Skinning VB Count]
  1071. // UINT - Number of verts in Skinning VB
  1072. // SkinningVertex[] - Array of skinning verts
  1073. // }
  1074. // MeshExtents structure
  1075. // [If skeleton animation data is not present, file ends here]
  1076. // UINT - Bone count
  1077. // { [Bone count]
  1078. // UINT - Length of bone name
  1079. // wchar_t[] - Bone name (if length > 0)
  1080. // Bone structure
  1081. // }
  1082. // UINT - Animation clip count
  1083. // { [Animation clip count]
  1084. // UINT - Length of clip name
  1085. // wchar_t[] - Clip name (if length > 0)
  1086. // float - Start time
  1087. // float - End time
  1088. // UINT - Keyframe count
  1089. // { [Keyframe count]
  1090. // Keyframe structure
  1091. // }
  1092. // }
  1093. // }
  1094. #pragma pack(push,1)
  1095. struct Material
  1096. {
  1097. DirectX::XMFLOAT4 Ambient;
  1098. DirectX::XMFLOAT4 Diffuse;
  1099. DirectX::XMFLOAT4 Specular;
  1100. float SpecularPower;
  1101. DirectX::XMFLOAT4 Emissive;
  1102. DirectX::XMFLOAT4X4 UVTransform;
  1103. };
  1104. const uint32_t MAX_TEXTURE = 8;
  1105. struct SubMesh
  1106. {
  1107. UINT MaterialIndex;
  1108. UINT IndexBufferIndex;
  1109. UINT VertexBufferIndex;
  1110. UINT StartIndex;
  1111. UINT PrimCount;
  1112. };
  1113. const uint32_t NUM_BONE_INFLUENCES = 4;
  1114. struct Vertex
  1115. {
  1116. DirectX::XMFLOAT3 Position;
  1117. DirectX::XMFLOAT3 Normal;
  1118. DirectX::XMFLOAT4 Tangent;
  1119. UINT color;
  1120. DirectX::XMFLOAT2 TextureCoordinates;
  1121. };
  1122. struct SkinningVertex
  1123. {
  1124. UINT boneIndex[NUM_BONE_INFLUENCES];
  1125. float boneWeight[NUM_BONE_INFLUENCES];
  1126. };
  1127. struct MeshExtents
  1128. {
  1129. float CenterX, CenterY, CenterZ;
  1130. float Radius;
  1131. float MinX, MinY, MinZ;
  1132. float MaxX, MaxY, MaxZ;
  1133. };
  1134. struct Bone
  1135. {
  1136. INT ParentIndex;
  1137. DirectX::XMFLOAT4X4 InvBindPos;
  1138. DirectX::XMFLOAT4X4 BindPos;
  1139. DirectX::XMFLOAT4X4 LocalTransform;
  1140. };
  1141. struct Clip
  1142. {
  1143. float StartTime;
  1144. float EndTime;
  1145. UINT keys;
  1146. };
  1147. struct Keyframe
  1148. {
  1149. UINT BoneIndex;
  1150. float Time;
  1151. DirectX::XMFLOAT4X4 Transform;
  1152. };
  1153. #pragma pack(pop)
  1154. }; // namespace
  1155. static_assert(sizeof(VSD3DStarter::Material) == 132, "CMO Mesh structure size incorrect");
  1156. static_assert(sizeof(VSD3DStarter::SubMesh) == 20, "CMO Mesh structure size incorrect");
  1157. static_assert(sizeof(VSD3DStarter::Vertex) == 52, "CMO Mesh structure size incorrect");
  1158. static_assert(sizeof(VSD3DStarter::SkinningVertex) == 32, "CMO Mesh structure size incorrect");
  1159. static_assert(sizeof(VSD3DStarter::MeshExtents) == 40, "CMO Mesh structure size incorrect");
  1160. static_assert(sizeof(VSD3DStarter::Bone) == 196, "CMO Mesh structure size incorrect");
  1161. static_assert(sizeof(VSD3DStarter::Clip) == 12, "CMO Mesh structure size incorrect");
  1162. static_assert(sizeof(VSD3DStarter::Keyframe) == 72, "CMO Mesh structure size incorrect");
  1163. //--------------------------------------------------------------------------------------
  1164. _Use_decl_annotations_
  1165. HRESULT Mesh::ExportToCMO(const wchar_t* szFileName, size_t nMaterials, const Material* materials) const
  1166. {
  1167. using namespace VSD3DStarter;
  1168. if (!szFileName)
  1169. return E_INVALIDARG;
  1170. if (nMaterials > 0 && !materials)
  1171. return E_INVALIDARG;
  1172. if (!mnFaces || !mIndices || !mnVerts || !mPositions || !mNormals || !mTexCoords || !mTangents)
  1173. return E_UNEXPECTED;
  1174. if ((uint64_t(mnFaces) * 3) >= UINT32_MAX)
  1175. return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
  1176. if (mnVerts >= UINT16_MAX)
  1177. return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  1178. UINT nIndices = static_cast<UINT>( mnFaces * 3 );
  1179. // Setup vertices/indices for CMO
  1180. std::unique_ptr<Vertex []> vb(new (std::nothrow) Vertex[mnVerts]);
  1181. std::unique_ptr<uint16_t []> ib(new (std::nothrow) uint16_t[nIndices]);
  1182. if (!vb || !ib)
  1183. return E_OUTOFMEMORY;
  1184. std::unique_ptr<SkinningVertex []> vbSkin;
  1185. if (mBlendIndices && mBlendWeights)
  1186. {
  1187. vbSkin.reset(new (std::nothrow) SkinningVertex[mnVerts]);
  1188. if (!vbSkin)
  1189. return E_OUTOFMEMORY;
  1190. }
  1191. // Copy to VB
  1192. auto vptr = vb.get();
  1193. for (size_t j = 0; j < mnVerts; ++j, ++vptr)
  1194. {
  1195. vptr->Position = mPositions[j];
  1196. vptr->Normal = mNormals[j];
  1197. vptr->Tangent = mTangents[j];
  1198. vptr->TextureCoordinates = mTexCoords[j];
  1199. if (mColors)
  1200. {
  1201. XMVECTOR icolor = XMLoadFloat4(&mColors[j]);
  1202. PackedVector::XMUBYTEN4 rgba;
  1203. PackedVector::XMStoreUByteN4(&rgba, icolor);
  1204. vptr->color = rgba.v;
  1205. }
  1206. else
  1207. vptr->color = 0xFFFFFFFF;
  1208. }
  1209. // Copy to SkinVB
  1210. auto sptr = vbSkin.get();
  1211. if ( sptr )
  1212. {
  1213. for (size_t j = 0; j < mnVerts; ++j, ++sptr)
  1214. {
  1215. XMVECTOR v = XMLoadFloat4(&mBlendIndices[j]);
  1216. XMStoreUInt4( reinterpret_cast<XMUINT4*>( &sptr->boneIndex[0] ), v);
  1217. const XMFLOAT4* w = &mBlendWeights[j];
  1218. sptr->boneWeight[0] = w->x;
  1219. sptr->boneWeight[1] = w->y;
  1220. sptr->boneWeight[2] = w->z;
  1221. sptr->boneWeight[3] = w->w;
  1222. }
  1223. }
  1224. // Copy to IB
  1225. auto iptr = ib.get();
  1226. for (size_t j = 0; j < nIndices; ++j, ++iptr)
  1227. {
  1228. uint32_t index = mIndices[j];
  1229. if (index == uint32_t(-1))
  1230. {
  1231. *iptr = uint16_t(-1);
  1232. }
  1233. else if (index >= UINT16_MAX)
  1234. {
  1235. return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  1236. }
  1237. else
  1238. {
  1239. *iptr = static_cast<uint16_t>(index);
  1240. }
  1241. }
  1242. // Create CMO file
  1243. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  1244. ScopedHandle hFile(safe_handle(CreateFile2(szFileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0)));
  1245. #else
  1246. ScopedHandle hFile(safe_handle(CreateFileW(szFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)));
  1247. #endif
  1248. if (!hFile)
  1249. return HRESULT_FROM_WIN32(GetLastError());
  1250. // Write 1 mesh, name based on the filename
  1251. UINT n = 1;
  1252. HRESULT hr = write_file(hFile.get(), n);
  1253. if (FAILED(hr))
  1254. return hr;
  1255. {
  1256. WCHAR fname[_MAX_FNAME];
  1257. _wsplitpath_s(szFileName, nullptr, 0, nullptr, 0, fname, _MAX_FNAME, nullptr, 0);
  1258. hr = write_file_string(hFile.get(), fname);
  1259. if (FAILED(hr))
  1260. return hr;
  1261. }
  1262. // Write materials
  1263. static const Mesh::Material s_defMaterial = { L"default", false, 1.f, 1.f,
  1264. XMFLOAT3(0.2f, 0.2f, 0.2f), XMFLOAT3(0.8f, 0.8f, 0.8f),
  1265. XMFLOAT3(0.f, 0.f, 0.f), XMFLOAT3(0.f, 0.f, 0.f), L"" };
  1266. UINT materialCount = 1;
  1267. if (nMaterials > 0)
  1268. {
  1269. materialCount = static_cast<UINT>(nMaterials);
  1270. }
  1271. else
  1272. {
  1273. nMaterials = 1;
  1274. materials = &s_defMaterial;
  1275. }
  1276. hr = write_file(hFile.get(), materialCount);
  1277. if (FAILED(hr))
  1278. return hr;
  1279. for (UINT j = 0; j < materialCount; ++j)
  1280. {
  1281. auto& m = materials[j];
  1282. if ( !m.name.empty() )
  1283. {
  1284. hr = write_file_string(hFile.get(), m.name.c_str() );
  1285. }
  1286. else
  1287. {
  1288. WCHAR name[64];
  1289. swprintf_s(name, L"material%03u\n", j);
  1290. hr = write_file_string(hFile.get(), name);
  1291. }
  1292. if (FAILED(hr))
  1293. return hr;
  1294. VSD3DStarter::Material mdata;
  1295. memset( &mdata, 0, sizeof(mdata) );
  1296. mdata.Ambient.x = m.ambientColor.x;
  1297. mdata.Ambient.y = m.ambientColor.y;
  1298. mdata.Ambient.z = m.ambientColor.z;
  1299. mdata.Ambient.w = 1.f;
  1300. mdata.Diffuse.x = m.diffuseColor.x;
  1301. mdata.Diffuse.y = m.diffuseColor.y;
  1302. mdata.Diffuse.z = m.diffuseColor.z;
  1303. mdata.Diffuse.w = m.alpha;
  1304. if (m.specularColor.x > 0.f || m.specularColor.y > 0.f || m.specularColor.z > 0.f)
  1305. {
  1306. mdata.Specular.x = m.specularColor.x;
  1307. mdata.Specular.y = m.specularColor.y;
  1308. mdata.Specular.z = m.specularColor.z;
  1309. mdata.SpecularPower = ( m.specularPower <= 0.f ) ? 16.f : m.specularPower;
  1310. }
  1311. else
  1312. {
  1313. mdata.SpecularPower = 1.f;
  1314. }
  1315. mdata.Specular.w = 1.f;
  1316. mdata.Emissive.x = m.emissiveColor.x;
  1317. mdata.Emissive.y = m.emissiveColor.y;
  1318. mdata.Emissive.z = m.emissiveColor.z;
  1319. mdata.Emissive.w = 1.f;
  1320. XMMATRIX id = XMMatrixIdentity();
  1321. XMStoreFloat4x4(&mdata.UVTransform, id);
  1322. hr = write_file(hFile.get(), mdata);
  1323. if (FAILED(hr))
  1324. return hr;
  1325. if (m.specularColor.x > 0.f || m.specularColor.y > 0.f || m.specularColor.z > 0.f)
  1326. {
  1327. hr = write_file_string(hFile.get(), L"phong.dgsl");
  1328. }
  1329. else
  1330. {
  1331. hr = write_file_string(hFile.get(), L"lambert.dgsl");
  1332. }
  1333. if (FAILED(hr))
  1334. return hr;
  1335. hr = write_file_string(hFile.get(), m.texture.c_str() );
  1336. if (FAILED(hr))
  1337. return hr;
  1338. for (size_t k = 1; k < MAX_TEXTURE; ++k)
  1339. {
  1340. hr = write_file_string(hFile.get(), L"" );
  1341. if (FAILED(hr))
  1342. return hr;
  1343. }
  1344. }
  1345. BYTE sd = 0; // No skeleton/animation data
  1346. hr = write_file(hFile.get(), sd);
  1347. if (FAILED(hr))
  1348. return hr;
  1349. if (mAttributes)
  1350. {
  1351. auto subsets = ComputeSubsets(mAttributes.get(), mnFaces);
  1352. n = static_cast<UINT>(subsets.size());
  1353. hr = write_file(hFile.get(), n);
  1354. if (FAILED(hr))
  1355. return hr;
  1356. size_t startIndex = 0;
  1357. for (auto it = subsets.cbegin(); it != subsets.end(); ++it)
  1358. {
  1359. SubMesh smesh;
  1360. smesh.MaterialIndex = mAttributes[it->first];
  1361. if (smesh.MaterialIndex >= nMaterials)
  1362. smesh.MaterialIndex = 0;
  1363. smesh.IndexBufferIndex = 0;
  1364. smesh.VertexBufferIndex = 0;
  1365. smesh.StartIndex = static_cast<UINT>( startIndex );
  1366. smesh.PrimCount = static_cast<UINT>( it->second );
  1367. hr = write_file(hFile.get(), smesh);
  1368. if (FAILED(hr))
  1369. return hr;
  1370. if ((startIndex + (it->second * 3)) > mnFaces * 3)
  1371. return E_FAIL;
  1372. startIndex += smesh.PrimCount * 3;
  1373. }
  1374. }
  1375. else
  1376. {
  1377. n = 1;
  1378. hr = write_file(hFile.get(), n);
  1379. if (FAILED(hr))
  1380. return hr;
  1381. SubMesh smesh;
  1382. smesh.MaterialIndex = 0;
  1383. smesh.IndexBufferIndex = 0;
  1384. smesh.VertexBufferIndex = 0;
  1385. smesh.StartIndex = 0;
  1386. smesh.PrimCount = static_cast<UINT>(mnFaces);
  1387. hr = write_file(hFile.get(), smesh);
  1388. if (FAILED(hr))
  1389. return hr;
  1390. }
  1391. // Write indices (one IB shared across submeshes)
  1392. n = 1;
  1393. hr = write_file(hFile.get(), n);
  1394. if (FAILED(hr))
  1395. return hr;
  1396. hr = write_file(hFile.get(), nIndices);
  1397. if (FAILED(hr))
  1398. return hr;
  1399. DWORD indexSize = static_cast<DWORD>(sizeof(uint16_t) * nIndices);
  1400. DWORD bytesWritten;
  1401. if (!WriteFile(hFile.get(), ib.get(), indexSize, &bytesWritten, nullptr))
  1402. return HRESULT_FROM_WIN32(GetLastError());
  1403. if (bytesWritten != indexSize)
  1404. return E_FAIL;
  1405. // Write vertices (one VB shared across submeshes)
  1406. n = 1;
  1407. hr = write_file(hFile.get(), n);
  1408. if (FAILED(hr))
  1409. return hr;
  1410. n = static_cast<UINT>( mnVerts );
  1411. hr = write_file(hFile.get(), n);
  1412. if (FAILED(hr))
  1413. return hr;
  1414. DWORD vertSize = static_cast<DWORD>(sizeof(Vertex) * mnVerts);
  1415. if (!WriteFile(hFile.get(), vb.get(), vertSize, &bytesWritten, nullptr))
  1416. return HRESULT_FROM_WIN32(GetLastError());
  1417. if (bytesWritten != vertSize)
  1418. return E_FAIL;
  1419. // Write skinning vertices (one SkinVB shared across submeshes)
  1420. if ( vbSkin )
  1421. {
  1422. n = 1;
  1423. hr = write_file(hFile.get(), n);
  1424. if (FAILED(hr))
  1425. return hr;
  1426. n = static_cast<UINT>(mnVerts);
  1427. hr = write_file(hFile.get(), n);
  1428. if (FAILED(hr))
  1429. return hr;
  1430. DWORD skinVertSize = static_cast<DWORD>(sizeof(SkinningVertex) * mnVerts);
  1431. if (!WriteFile(hFile.get(), vbSkin.get(), skinVertSize, &bytesWritten, nullptr))
  1432. return HRESULT_FROM_WIN32(GetLastError());
  1433. if (bytesWritten != skinVertSize)
  1434. return E_FAIL;
  1435. }
  1436. else
  1437. {
  1438. n = 0;
  1439. hr = write_file(hFile.get(), n);
  1440. if (FAILED(hr))
  1441. return hr;
  1442. }
  1443. // Write extents
  1444. {
  1445. BoundingSphere sphere;
  1446. BoundingSphere::CreateFromPoints(sphere, mnVerts, mPositions.get(), sizeof(XMFLOAT3));
  1447. BoundingBox box;
  1448. BoundingBox::CreateFromPoints(box, mnVerts, mPositions.get(), sizeof(XMFLOAT3));
  1449. MeshExtents extents;
  1450. extents.CenterX = sphere.Center.x;
  1451. extents.CenterY = sphere.Center.y;
  1452. extents.CenterZ = sphere.Center.z;
  1453. extents.Radius = sphere.Radius;
  1454. extents.MinX = box.Center.x - box.Extents.x;
  1455. extents.MinY = box.Center.y - box.Extents.y;
  1456. extents.MinZ = box.Center.z - box.Extents.z;
  1457. extents.MaxX = box.Center.x + box.Extents.x;
  1458. extents.MaxY = box.Center.y + box.Extents.y;
  1459. extents.MaxZ = box.Center.z + box.Extents.z;
  1460. hr = write_file(hFile.get(), extents);
  1461. if (FAILED(hr))
  1462. return hr;
  1463. }
  1464. // No skeleton data, so no animations
  1465. return S_OK;
  1466. }
  1467. //======================================================================================
  1468. // SDKMESH
  1469. //======================================================================================
  1470. //--------------------------------------------------------------------------------------
  1471. // SDKMESH format is generated by the legacy DirectX SDK's Content Exporter and
  1472. // originally rendered by the DXUT helper class SDKMesh
  1473. //
  1474. // http://go.microsoft.com/fwlink/?LinkId=226208
  1475. //--------------------------------------------------------------------------------------
  1476. namespace DXUT
  1477. {
  1478. // .SDKMESH files
  1479. // SDKMESH_HEADER
  1480. // SDKMESH_VERTEX_BUFFER_HEADER header->VertexStreamHeadersOffset
  1481. // SDKMESH_INDEX_BUFFER_HEADER header->IndexStreamHeadersOffset
  1482. // SDKMESH_MESH header->MeshDataOffset
  1483. // SDKMESH_SUBSET header->SubsetDataOffset
  1484. // SDKMESH_FRAME header->FrameDataOffset
  1485. // SDKMESH_MATERIAL header->MaterialDataOffset
  1486. // [header->NonBufferDataSize]
  1487. // { [ header->NumVertexBuffers]
  1488. // VB data
  1489. // }
  1490. // { [ header->NumIndexBuffers]
  1491. // IB data
  1492. // }
  1493. // .SDDKANIM files
  1494. // SDKANIMATION_FILE_HEADER
  1495. // BYTE[] - Length of fileheader->AnimationDataSize
  1496. // .SDKMESH uses Direct3D 9 decls, but only a subset of these is ever generated by the legacy DirectX SDK Content Exporter
  1497. // D3DDECLUSAGE_POSITION / D3DDECLTYPE_FLOAT3
  1498. // (D3DDECLUSAGE_BLENDWEIGHT / D3DDECLTYPE_UBYTE4N
  1499. // D3DDECLUSAGE_BLENDINDICES / D3DDECLTYPE_UBYTE4)?
  1500. // (D3DDECLUSAGE_NORMAL / D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4)?
  1501. // (D3DDECLUSAGE_COLOR / D3DDECLTYPE_D3DCOLOR)?
  1502. // (D3DDECLUSAGE_TEXCOORD / D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2 or D3DDECLTYPE_FLOAT16_2, D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4, D3DDECLTYPE_FLOAT4 or D3DDECLTYPE_FLOAT16_4)*
  1503. // (D3DDECLUSAGE_TANGENT / D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4)?
  1504. // (D3DDECLUSAGE_BINORMAL / D3DDECLTYPE_FLOAT3 or D3DDECLTYPE_FLOAT16_4)?
  1505. enum D3DDECLUSAGE
  1506. {
  1507. D3DDECLUSAGE_POSITION = 0,
  1508. D3DDECLUSAGE_BLENDWEIGHT = 1,
  1509. D3DDECLUSAGE_BLENDINDICES = 2,
  1510. D3DDECLUSAGE_NORMAL = 3,
  1511. D3DDECLUSAGE_TEXCOORD = 5,
  1512. D3DDECLUSAGE_TANGENT = 6,
  1513. D3DDECLUSAGE_BINORMAL = 7,
  1514. D3DDECLUSAGE_COLOR = 10,
  1515. };
  1516. enum D3DDECLTYPE
  1517. {
  1518. D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
  1519. D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
  1520. D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
  1521. D3DDECLTYPE_FLOAT4 = 3, // 4D float
  1522. D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
  1523. // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
  1524. D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
  1525. D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
  1526. D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
  1527. D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
  1528. D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
  1529. D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
  1530. };
  1531. #pragma pack(push,4)
  1532. struct D3DVERTEXELEMENT9
  1533. {
  1534. WORD Stream; // Stream index
  1535. WORD Offset; // Offset in the stream in bytes
  1536. BYTE Type; // Data type
  1537. BYTE Method; // Processing method
  1538. BYTE Usage; // Semantics
  1539. BYTE UsageIndex; // Semantic index
  1540. };
  1541. #pragma pack(pop)
  1542. //--------------------------------------------------------------------------------------
  1543. // Hard Defines for the various structures
  1544. //--------------------------------------------------------------------------------------
  1545. const uint32_t SDKMESH_FILE_VERSION = 101;
  1546. const uint32_t MAX_VERTEX_ELEMENTS = 32;
  1547. const uint32_t MAX_VERTEX_STREAMS = 16;
  1548. const uint32_t MAX_FRAME_NAME = 100;
  1549. const uint32_t MAX_MESH_NAME = 100;
  1550. const uint32_t MAX_SUBSET_NAME = 100;
  1551. const uint32_t MAX_MATERIAL_NAME = 100;
  1552. const uint32_t MAX_TEXTURE_NAME = MAX_PATH;
  1553. const uint32_t MAX_MATERIAL_PATH = MAX_PATH;
  1554. const uint32_t INVALID_FRAME = uint32_t(-1);
  1555. const uint32_t INVALID_MESH = uint32_t(-1);
  1556. const uint32_t INVALID_MATERIAL = uint32_t(-1);
  1557. const uint32_t INVALID_SUBSET = uint32_t(-1);
  1558. const uint32_t INVALID_ANIMATION_DATA = uint32_t(-1);
  1559. const uint32_t INVALID_SAMPLER_SLOT = uint32_t(-1);
  1560. const uint32_t ERROR_RESOURCE_VALUE = 1;
  1561. template<typename TYPE> bool IsErrorResource(TYPE data)
  1562. {
  1563. if ((TYPE) ERROR_RESOURCE_VALUE == data)
  1564. return true;
  1565. return false;
  1566. }
  1567. //--------------------------------------------------------------------------------------
  1568. // Enumerated Types. These will have mirrors in both D3D9 and D3D11
  1569. //--------------------------------------------------------------------------------------
  1570. enum SDKMESH_PRIMITIVE_TYPE
  1571. {
  1572. PT_TRIANGLE_LIST = 0,
  1573. PT_TRIANGLE_STRIP,
  1574. PT_LINE_LIST,
  1575. PT_LINE_STRIP,
  1576. PT_POINT_LIST,
  1577. PT_TRIANGLE_LIST_ADJ,
  1578. PT_TRIANGLE_STRIP_ADJ,
  1579. PT_LINE_LIST_ADJ,
  1580. PT_LINE_STRIP_ADJ,
  1581. PT_QUAD_PATCH_LIST,
  1582. PT_TRIANGLE_PATCH_LIST,
  1583. };
  1584. enum SDKMESH_INDEX_TYPE
  1585. {
  1586. IT_16BIT = 0,
  1587. IT_32BIT,
  1588. };
  1589. enum FRAME_TRANSFORM_TYPE
  1590. {
  1591. FTT_RELATIVE = 0,
  1592. FTT_ABSOLUTE, //This is not currently used but is here to support absolute transformations in the future
  1593. };
  1594. //--------------------------------------------------------------------------------------
  1595. // Structures.
  1596. //--------------------------------------------------------------------------------------
  1597. #pragma pack(push,8)
  1598. struct SDKMESH_HEADER
  1599. {
  1600. //Basic Info and sizes
  1601. UINT Version;
  1602. BYTE IsBigEndian;
  1603. UINT64 HeaderSize;
  1604. UINT64 NonBufferDataSize;
  1605. UINT64 BufferDataSize;
  1606. //Stats
  1607. UINT NumVertexBuffers;
  1608. UINT NumIndexBuffers;
  1609. UINT NumMeshes;
  1610. UINT NumTotalSubsets;
  1611. UINT NumFrames;
  1612. UINT NumMaterials;
  1613. //Offsets to Data
  1614. UINT64 VertexStreamHeadersOffset;
  1615. UINT64 IndexStreamHeadersOffset;
  1616. UINT64 MeshDataOffset;
  1617. UINT64 SubsetDataOffset;
  1618. UINT64 FrameDataOffset;
  1619. UINT64 MaterialDataOffset;
  1620. };
  1621. struct SDKMESH_VERTEX_BUFFER_HEADER
  1622. {
  1623. UINT64 NumVertices;
  1624. UINT64 SizeBytes;
  1625. UINT64 StrideBytes;
  1626. D3DVERTEXELEMENT9 Decl[MAX_VERTEX_ELEMENTS];
  1627. union
  1628. {
  1629. UINT64 DataOffset;
  1630. ID3D11Buffer* pVB11;
  1631. };
  1632. };
  1633. struct SDKMESH_INDEX_BUFFER_HEADER
  1634. {
  1635. UINT64 NumIndices;
  1636. UINT64 SizeBytes;
  1637. UINT IndexType;
  1638. union
  1639. {
  1640. UINT64 DataOffset;
  1641. ID3D11Buffer* pIB11;
  1642. };
  1643. };
  1644. struct SDKMESH_MESH
  1645. {
  1646. char Name[MAX_MESH_NAME];
  1647. BYTE NumVertexBuffers;
  1648. UINT VertexBuffers[MAX_VERTEX_STREAMS];
  1649. UINT IndexBuffer;
  1650. UINT NumSubsets;
  1651. UINT NumFrameInfluences; //aka bones
  1652. DirectX::XMFLOAT3 BoundingBoxCenter;
  1653. DirectX::XMFLOAT3 BoundingBoxExtents;
  1654. union
  1655. {
  1656. UINT64 SubsetOffset;
  1657. INT* pSubsets;
  1658. };
  1659. union
  1660. {
  1661. UINT64 FrameInfluenceOffset;
  1662. UINT* pFrameInfluences;
  1663. };
  1664. };
  1665. struct SDKMESH_SUBSET
  1666. {
  1667. char Name[MAX_SUBSET_NAME];
  1668. UINT MaterialID;
  1669. UINT PrimitiveType;
  1670. UINT64 IndexStart;
  1671. UINT64 IndexCount;
  1672. UINT64 VertexStart;
  1673. UINT64 VertexCount;
  1674. };
  1675. struct SDKMESH_FRAME
  1676. {
  1677. char Name[MAX_FRAME_NAME];
  1678. UINT Mesh;
  1679. UINT ParentFrame;
  1680. UINT ChildFrame;
  1681. UINT SiblingFrame;
  1682. DirectX::XMFLOAT4X4 Matrix;
  1683. UINT AnimationDataIndex; //Used to index which set of keyframes transforms this frame
  1684. };
  1685. struct SDKMESH_MATERIAL
  1686. {
  1687. char Name[MAX_MATERIAL_NAME];
  1688. // Use MaterialInstancePath
  1689. char MaterialInstancePath[MAX_MATERIAL_PATH];
  1690. // Or fall back to d3d8-type materials
  1691. char DiffuseTexture[MAX_TEXTURE_NAME];
  1692. char NormalTexture[MAX_TEXTURE_NAME];
  1693. char SpecularTexture[MAX_TEXTURE_NAME];
  1694. DirectX::XMFLOAT4 Diffuse;
  1695. DirectX::XMFLOAT4 Ambient;
  1696. DirectX::XMFLOAT4 Specular;
  1697. DirectX::XMFLOAT4 Emissive;
  1698. FLOAT Power;
  1699. union
  1700. {
  1701. UINT64 Force64_1; //Force the union to 64bits
  1702. ID3D11Texture2D* pDiffuseTexture11;
  1703. };
  1704. union
  1705. {
  1706. UINT64 Force64_2; //Force the union to 64bits
  1707. ID3D11Texture2D* pNormalTexture11;
  1708. };
  1709. union
  1710. {
  1711. UINT64 Force64_3; //Force the union to 64bits
  1712. ID3D11Texture2D* pSpecularTexture11;
  1713. };
  1714. union
  1715. {
  1716. UINT64 Force64_4; //Force the union to 64bits
  1717. ID3D11ShaderResourceView* pDiffuseRV11;
  1718. };
  1719. union
  1720. {
  1721. UINT64 Force64_5; //Force the union to 64bits
  1722. ID3D11ShaderResourceView* pNormalRV11;
  1723. };
  1724. union
  1725. {
  1726. UINT64 Force64_6; //Force the union to 64bits
  1727. ID3D11ShaderResourceView* pSpecularRV11;
  1728. };
  1729. };
  1730. struct SDKANIMATION_FILE_HEADER
  1731. {
  1732. UINT Version;
  1733. BYTE IsBigEndian;
  1734. UINT FrameTransformType;
  1735. UINT NumFrames;
  1736. UINT NumAnimationKeys;
  1737. UINT AnimationFPS;
  1738. UINT64 AnimationDataSize;
  1739. UINT64 AnimationDataOffset;
  1740. };
  1741. struct SDKANIMATION_DATA
  1742. {
  1743. DirectX::XMFLOAT3 Translation;
  1744. DirectX::XMFLOAT4 Orientation;
  1745. DirectX::XMFLOAT3 Scaling;
  1746. };
  1747. struct SDKANIMATION_FRAME_DATA
  1748. {
  1749. char FrameName[MAX_FRAME_NAME];
  1750. union
  1751. {
  1752. UINT64 DataOffset;
  1753. SDKANIMATION_DATA* pAnimationData;
  1754. };
  1755. };
  1756. #pragma pack(pop)
  1757. }; // namespace
  1758. static_assert(sizeof(DXUT::D3DVERTEXELEMENT9) == 8, "Direct3D9 Decl structure size incorrect");
  1759. static_assert(sizeof(DXUT::SDKMESH_HEADER) == 104, "SDK Mesh structure size incorrect");
  1760. static_assert(sizeof(DXUT::SDKMESH_VERTEX_BUFFER_HEADER) == 288, "SDK Mesh structure size incorrect");
  1761. static_assert(sizeof(DXUT::SDKMESH_INDEX_BUFFER_HEADER) == 32, "SDK Mesh structure size incorrect");
  1762. static_assert(sizeof(DXUT::SDKMESH_MESH) == 224, "SDK Mesh structure size incorrect");
  1763. static_assert(sizeof(DXUT::SDKMESH_SUBSET) == 144, "SDK Mesh structure size incorrect");
  1764. static_assert(sizeof(DXUT::SDKMESH_FRAME) == 184, "SDK Mesh structure size incorrect");
  1765. static_assert(sizeof(DXUT::SDKMESH_MATERIAL) == 1256, "SDK Mesh structure size incorrect");
  1766. static_assert(sizeof(DXUT::SDKANIMATION_FILE_HEADER) == 40, "SDK Mesh structure size incorrect");
  1767. static_assert(sizeof(DXUT::SDKANIMATION_DATA) == 40, "SDK Mesh structure size incorrect");
  1768. static_assert(sizeof(DXUT::SDKANIMATION_FRAME_DATA) == 112, "SDK Mesh structure size incorrect");
  1769. //--------------------------------------------------------------------------------------
  1770. _Use_decl_annotations_
  1771. HRESULT Mesh::ExportToSDKMESH(const wchar_t* szFileName, size_t nMaterials, const Material* materials) const
  1772. {
  1773. using namespace DXUT;
  1774. if (!szFileName)
  1775. return E_INVALIDARG;
  1776. if (nMaterials > 0 && !materials)
  1777. return E_INVALIDARG;
  1778. if (!mnFaces || !mIndices || !mnVerts || !mPositions)
  1779. return E_UNEXPECTED;
  1780. if ((uint64_t(mnFaces) * 3) >= UINT32_MAX)
  1781. return HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW);
  1782. // Build input layout/vertex decalaration
  1783. static const D3D11_INPUT_ELEMENT_DESC s_elements [] =
  1784. {
  1785. { "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 0
  1786. { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 1
  1787. { "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 2
  1788. { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 3
  1789. { "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 4
  1790. { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 5
  1791. { "BLENDINDICES", 0, DXGI_FORMAT_R8G8B8A8_UINT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 6
  1792. { "BLENDWEIGHT", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, // 7
  1793. };
  1794. static const D3DVERTEXELEMENT9 s_decls [] =
  1795. {
  1796. { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 }, // 0
  1797. { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 }, // 1
  1798. { 0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 }, // 2
  1799. { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TANGENT, 0 }, // 3
  1800. { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BINORMAL, 0 }, // 4
  1801. { 0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 }, // 5
  1802. { 0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0 }, // 6
  1803. { 0, 0, D3DDECLTYPE_UBYTE4N, 0, D3DDECLUSAGE_BLENDWEIGHT, 0 }, // 7
  1804. { 0xFF, 0, D3DDECLTYPE_UNUSED, 0, 0, 0 },
  1805. };
  1806. static_assert((_countof(s_elements) + 1) == _countof(s_decls), "InputLayouts and Vertex Decls disagree");
  1807. SDKMESH_VERTEX_BUFFER_HEADER vbHeader = { 0 };
  1808. vbHeader.NumVertices = mnVerts;
  1809. vbHeader.Decl[0] = s_decls[0];
  1810. D3D11_INPUT_ELEMENT_DESC inputLayout[MAX_VERTEX_ELEMENTS] = { 0 };
  1811. inputLayout[0] = s_elements[0];
  1812. size_t nDecl = 1;
  1813. size_t stride = sizeof(XMFLOAT3);
  1814. if (mBlendIndices && mBlendWeights)
  1815. {
  1816. // BLENDWEIGHT
  1817. vbHeader.Decl[nDecl] = s_decls[7];
  1818. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1819. inputLayout[nDecl] = s_elements[7];
  1820. ++nDecl;
  1821. stride += sizeof(UINT);
  1822. // BLENDINDICES
  1823. vbHeader.Decl[nDecl] = s_decls[6];
  1824. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1825. inputLayout[nDecl] = s_elements[6];
  1826. ++nDecl;
  1827. stride += sizeof(UINT);
  1828. }
  1829. if (mNormals)
  1830. {
  1831. vbHeader.Decl[nDecl] = s_decls[1];
  1832. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1833. inputLayout[nDecl] = s_elements[1];
  1834. ++nDecl;
  1835. stride += sizeof(XMFLOAT3);
  1836. }
  1837. if (mColors)
  1838. {
  1839. vbHeader.Decl[nDecl] = s_decls[2];
  1840. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1841. inputLayout[nDecl] = s_elements[2];
  1842. ++nDecl;
  1843. stride += sizeof(UINT);
  1844. }
  1845. if (mTexCoords)
  1846. {
  1847. vbHeader.Decl[nDecl] = s_decls[5];
  1848. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1849. inputLayout[nDecl] = s_elements[5];
  1850. ++nDecl;
  1851. stride += sizeof(XMFLOAT2);
  1852. }
  1853. if (mTangents)
  1854. {
  1855. vbHeader.Decl[nDecl] = s_decls[3];
  1856. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1857. inputLayout[nDecl] = s_elements[3];
  1858. ++nDecl;
  1859. stride += sizeof(XMFLOAT3);
  1860. }
  1861. if (mBiTangents)
  1862. {
  1863. vbHeader.Decl[nDecl] = s_decls[4];
  1864. vbHeader.Decl[nDecl].Offset = static_cast<WORD>(stride);
  1865. inputLayout[nDecl] = s_elements[4];
  1866. ++nDecl;
  1867. stride += sizeof(XMFLOAT3);
  1868. }
  1869. assert(nDecl < MAX_VERTEX_ELEMENTS);
  1870. vbHeader.Decl[nDecl] = s_decls[_countof(s_decls) - 1];
  1871. // Build vertex buffer
  1872. std::unique_ptr<uint8_t> vb(new (std::nothrow) uint8_t[mnVerts * stride]);
  1873. if (!vb)
  1874. return E_OUTOFMEMORY;
  1875. vbHeader.SizeBytes = mnVerts * stride;
  1876. vbHeader.StrideBytes = stride;
  1877. {
  1878. VBWriter writer;
  1879. HRESULT hr = writer.Initialize(inputLayout, nDecl);
  1880. if (FAILED(hr))
  1881. return hr;
  1882. hr = writer.AddStream(vb.get(), mnVerts, 0, stride);
  1883. if (FAILED(hr))
  1884. return hr;
  1885. hr = GetVertexBuffer(writer);
  1886. if (FAILED(hr))
  1887. return hr;
  1888. }
  1889. // Build index buffer
  1890. SDKMESH_INDEX_BUFFER_HEADER ibHeader = { 0 };
  1891. ibHeader.NumIndices = mnFaces * 3;
  1892. std::unique_ptr<uint16_t[]> ib16;
  1893. if (Is16BitIndexBuffer())
  1894. {
  1895. ibHeader.SizeBytes = mnFaces * 3 * sizeof(uint16_t);
  1896. ibHeader.IndexType = IT_16BIT;
  1897. ib16 = GetIndexBuffer16();
  1898. if (!ib16)
  1899. return E_OUTOFMEMORY;
  1900. }
  1901. else
  1902. {
  1903. ibHeader.SizeBytes = mnFaces * 3 * sizeof(uint32_t);
  1904. ibHeader.IndexType = IT_32BIT;
  1905. }
  1906. // Build materials buffer
  1907. std::unique_ptr<SDKMESH_MATERIAL[]> mats;
  1908. if (!nMaterials)
  1909. {
  1910. mats.reset(new (std::nothrow) SDKMESH_MATERIAL[1]);
  1911. if (!mats)
  1912. return E_OUTOFMEMORY;
  1913. memset(mats.get(), 0, sizeof(SDKMESH_MATERIAL));
  1914. strcpy_s(mats[0].Name, "default");
  1915. mats[0].Diffuse = XMFLOAT4(0.8f, 0.8f, 0.8f, 1.f);
  1916. mats[0].Ambient = XMFLOAT4(0.2f, 02.f, 0.2f, 1.f);
  1917. mats[0].Power = 1.f;
  1918. }
  1919. else
  1920. {
  1921. mats.reset(new (std::nothrow) SDKMESH_MATERIAL[nMaterials]);
  1922. if (!mats)
  1923. return E_OUTOFMEMORY;
  1924. for (size_t j = 0; j < nMaterials; ++j)
  1925. {
  1926. auto m0 = &materials[j];
  1927. auto m = &mats[j];
  1928. memset( m, 0, sizeof(SDKMESH_MATERIAL) );
  1929. int result = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
  1930. m0->name.c_str(), -1,
  1931. m->Name, MAX_MATERIAL_NAME, nullptr, FALSE);
  1932. if (!result)
  1933. {
  1934. *m->Name = 0;
  1935. }
  1936. result = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS,
  1937. m0->texture.c_str(), -1,
  1938. m->DiffuseTexture, MAX_TEXTURE_NAME, nullptr, FALSE);
  1939. if (!result)
  1940. {
  1941. *m->DiffuseTexture = 0;
  1942. }
  1943. m->Diffuse.x = m0->diffuseColor.x;
  1944. m->Diffuse.y = m0->diffuseColor.y;
  1945. m->Diffuse.z = m0->diffuseColor.z;
  1946. m->Diffuse.w = m0->alpha;
  1947. m->Ambient.x = m0->ambientColor.x;
  1948. m->Ambient.y = m0->ambientColor.y;
  1949. m->Ambient.z = m0->ambientColor.z;
  1950. m->Ambient.w = 1.f;
  1951. if (m0->specularColor.x > 0.f || m0->specularColor.y > 0.f || m0->specularColor.z > 0.f)
  1952. {
  1953. m->Specular.x = m0->specularColor.x;
  1954. m->Specular.y = m0->specularColor.y;
  1955. m->Specular.z = m0->specularColor.z;
  1956. m->Power = ( m0->specularPower <= 0.f ) ? 16.f : m0->specularPower;
  1957. }
  1958. else
  1959. {
  1960. m->Power = 1.f;
  1961. }
  1962. m->Emissive.x = m0->emissiveColor.x;
  1963. m->Emissive.y = m0->emissiveColor.y;
  1964. m->Emissive.z = m0->emissiveColor.z;
  1965. }
  1966. }
  1967. // Build subsets
  1968. std::vector<SDKMESH_SUBSET> submeshes;
  1969. std::vector<UINT> subsetArray;
  1970. if (mAttributes)
  1971. {
  1972. auto subsets = ComputeSubsets(mAttributes.get(), mnFaces);
  1973. UINT64 startIndex = 0;
  1974. for (auto it = subsets.cbegin(); it != subsets.cend(); ++it)
  1975. {
  1976. subsetArray.push_back(static_cast<UINT>(submeshes.size()));
  1977. SDKMESH_SUBSET s = { 0 };
  1978. s.MaterialID = mAttributes[it->first];
  1979. if (s.MaterialID >= nMaterials)
  1980. s.MaterialID = 0;
  1981. s.PrimitiveType = PT_TRIANGLE_LIST;
  1982. s.IndexStart = startIndex;
  1983. s.IndexCount = it->second * 3;
  1984. s.VertexCount = mnVerts;
  1985. submeshes.push_back(s);
  1986. if ((startIndex + s.IndexCount) > mnFaces * 3)
  1987. return E_FAIL;
  1988. startIndex += s.IndexCount;
  1989. }
  1990. }
  1991. else
  1992. {
  1993. SDKMESH_SUBSET s = { 0 };
  1994. s.PrimitiveType = PT_TRIANGLE_LIST;
  1995. s.IndexCount = mnFaces * 3;
  1996. s.VertexCount = mnVerts;
  1997. subsetArray.push_back(0);
  1998. submeshes.push_back(s);
  1999. }
  2000. // Create file
  2001. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
  2002. ScopedHandle hFile(safe_handle(CreateFile2(szFileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0)));
  2003. #else
  2004. ScopedHandle hFile(safe_handle(CreateFileW(szFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)));
  2005. #endif
  2006. if (!hFile)
  2007. return HRESULT_FROM_WIN32(GetLastError());
  2008. // Write file header
  2009. SDKMESH_HEADER header = { 0 };
  2010. header.Version = SDKMESH_FILE_VERSION;
  2011. header.IsBigEndian = 0;
  2012. header.NumVertexBuffers = 1;
  2013. header.NumIndexBuffers = 1;
  2014. header.NumMeshes = 1;
  2015. header.NumTotalSubsets = static_cast<UINT>( submeshes.size() );
  2016. header.NumFrames = 1;
  2017. header.NumMaterials = (nMaterials > 0) ? static_cast<UINT>(nMaterials) : 1;
  2018. header.HeaderSize = sizeof(SDKMESH_HEADER) + sizeof(SDKMESH_VERTEX_BUFFER_HEADER) + sizeof(SDKMESH_INDEX_BUFFER_HEADER);
  2019. size_t staticDataSize = sizeof(SDKMESH_MESH)
  2020. + header.NumTotalSubsets * sizeof(SDKMESH_SUBSET)
  2021. + sizeof(SDKMESH_FRAME)
  2022. + header.NumMaterials * sizeof(SDKMESH_MATERIAL);
  2023. header.NonBufferDataSize = staticDataSize + subsetArray.size() * sizeof(UINT) + sizeof(UINT);
  2024. header.BufferDataSize = roundup4k( vbHeader.SizeBytes ) + roundup4k( ibHeader.SizeBytes );
  2025. header.VertexStreamHeadersOffset = sizeof(SDKMESH_HEADER);
  2026. header.IndexStreamHeadersOffset = header.VertexStreamHeadersOffset + sizeof(SDKMESH_VERTEX_BUFFER_HEADER);
  2027. header.MeshDataOffset = header.IndexStreamHeadersOffset + sizeof(SDKMESH_INDEX_BUFFER_HEADER);
  2028. header.SubsetDataOffset = header.MeshDataOffset + sizeof(SDKMESH_MESH);
  2029. header.FrameDataOffset = header.SubsetDataOffset + header.NumTotalSubsets * sizeof(SDKMESH_SUBSET);
  2030. header.MaterialDataOffset = header.FrameDataOffset + sizeof(SDKMESH_FRAME);
  2031. HRESULT hr = write_file(hFile.get(), header);
  2032. if (FAILED(hr))
  2033. return hr;
  2034. // Write buffer headers
  2035. UINT64 offset = header.HeaderSize + header.NonBufferDataSize;
  2036. vbHeader.DataOffset = offset;
  2037. offset += roundup4k(vbHeader.SizeBytes);
  2038. hr = write_file(hFile.get(), vbHeader);
  2039. if (FAILED(hr))
  2040. return hr;
  2041. ibHeader.DataOffset = offset;
  2042. offset += roundup4k(ibHeader.SizeBytes);
  2043. hr = write_file(hFile.get(), ibHeader);
  2044. if (FAILED(hr))
  2045. return hr;
  2046. // Write mesh headers
  2047. assert(header.NumMeshes == 1);
  2048. offset = header.HeaderSize + staticDataSize;
  2049. SDKMESH_MESH meshHeader = { 0 };
  2050. meshHeader.NumVertexBuffers = 1;
  2051. meshHeader.NumFrameInfluences = 1;
  2052. {
  2053. BoundingBox box;
  2054. BoundingBox::CreateFromPoints(box, mnVerts, mPositions.get(), sizeof(XMFLOAT3));
  2055. meshHeader.BoundingBoxCenter = box.Center;
  2056. meshHeader.BoundingBoxExtents = box.Extents;
  2057. }
  2058. meshHeader.NumSubsets = static_cast<UINT>(submeshes.size());
  2059. meshHeader.SubsetOffset = offset;
  2060. offset += meshHeader.NumSubsets * sizeof(UINT);
  2061. meshHeader.FrameInfluenceOffset = offset;
  2062. offset += sizeof(UINT);
  2063. hr = write_file(hFile.get(), meshHeader);
  2064. if (FAILED(hr))
  2065. return hr;
  2066. // Write subsets
  2067. DWORD bytesToWrite = static_cast<DWORD>( sizeof(SDKMESH_SUBSET) * submeshes.size() );
  2068. DWORD bytesWritten;
  2069. if ( !WriteFile(hFile.get(), &submeshes.front(), bytesToWrite, &bytesWritten, nullptr) )
  2070. return HRESULT_FROM_WIN32(GetLastError());
  2071. if (bytesWritten != bytesToWrite)
  2072. return E_FAIL;
  2073. // Write frames
  2074. SDKMESH_FRAME frame = { 0 };
  2075. strcpy_s( frame.Name, "root");
  2076. frame.ParentFrame = frame.ChildFrame = frame.SiblingFrame = DWORD(-1);
  2077. frame.AnimationDataIndex = INVALID_ANIMATION_DATA;
  2078. XMMATRIX id = XMMatrixIdentity();
  2079. XMStoreFloat4x4(&frame.Matrix, id);
  2080. hr = write_file(hFile.get(), frame);
  2081. if (FAILED(hr))
  2082. return hr;
  2083. // Write materials
  2084. bytesToWrite = static_cast<DWORD>(sizeof(SDKMESH_MATERIAL) * ((nMaterials > 0) ? nMaterials : 1));
  2085. if (!WriteFile(hFile.get(), mats.get(), bytesToWrite, &bytesWritten, nullptr))
  2086. return HRESULT_FROM_WIN32(GetLastError());
  2087. if (bytesWritten != bytesToWrite)
  2088. return E_FAIL;
  2089. // Write subset index list
  2090. assert(meshHeader.NumSubsets == subsetArray.size());
  2091. bytesToWrite = meshHeader.NumSubsets * sizeof(UINT);
  2092. if (!WriteFile(hFile.get(), &subsetArray.front(), bytesToWrite, &bytesWritten, nullptr))
  2093. return HRESULT_FROM_WIN32(GetLastError());
  2094. if (bytesWritten != bytesToWrite)
  2095. return E_FAIL;
  2096. // Write frame influence list
  2097. assert(meshHeader.NumFrameInfluences == 1);
  2098. UINT frameIndex = 0;
  2099. hr = write_file(hFile.get(), frameIndex);
  2100. if (FAILED(hr))
  2101. return hr;
  2102. // Write VB data
  2103. bytesToWrite = static_cast<DWORD>(vbHeader.SizeBytes);
  2104. if (!WriteFile(hFile.get(), vb.get(), bytesToWrite, &bytesWritten, nullptr))
  2105. return HRESULT_FROM_WIN32(GetLastError());
  2106. if (bytesWritten != bytesToWrite)
  2107. return E_FAIL;
  2108. bytesToWrite = static_cast<DWORD>( roundup4k(vbHeader.SizeBytes) - vbHeader.SizeBytes );
  2109. if (bytesToWrite > 0)
  2110. {
  2111. assert(bytesToWrite < sizeof(g_padding));
  2112. if (!WriteFile(hFile.get(), g_padding, bytesToWrite, &bytesWritten, nullptr))
  2113. return HRESULT_FROM_WIN32(GetLastError());
  2114. if (bytesWritten != bytesToWrite)
  2115. return E_FAIL;
  2116. }
  2117. // Write IB data
  2118. bytesToWrite = static_cast<DWORD>(ibHeader.SizeBytes);
  2119. if (!WriteFile(hFile.get(), (ib16) ? static_cast<void*>( ib16.get() ) : static_cast<void*>( mIndices.get() ),
  2120. bytesToWrite, &bytesWritten, nullptr))
  2121. return HRESULT_FROM_WIN32(GetLastError());
  2122. if (bytesWritten != bytesToWrite)
  2123. return E_FAIL;
  2124. bytesToWrite = static_cast<DWORD>(roundup4k(ibHeader.SizeBytes) - ibHeader.SizeBytes);
  2125. if (bytesToWrite > 0)
  2126. {
  2127. assert(bytesToWrite < sizeof(g_padding));
  2128. if (!WriteFile(hFile.get(), g_padding, bytesToWrite, &bytesWritten, nullptr))
  2129. return HRESULT_FROM_WIN32(GetLastError());
  2130. if (bytesWritten != bytesToWrite)
  2131. return E_FAIL;
  2132. }
  2133. return S_OK;
  2134. }