Model.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. //
  2. // Copyright (c) 2008-2022 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/Context.h"
  24. #include "../Core/Profiler.h"
  25. #include "../Graphics/Geometry.h"
  26. #include "../Graphics/Graphics.h"
  27. #include "../Graphics/Model.h"
  28. #include "../GraphicsAPI/IndexBuffer.h"
  29. #include "../GraphicsAPI/VertexBuffer.h"
  30. #include "../IO/File.h"
  31. #include "../IO/FileSystem.h"
  32. #include "../IO/Log.h"
  33. #include "../Resource/ResourceCache.h"
  34. #include "../Resource/XMLFile.h"
  35. #include "../DebugNew.h"
  36. namespace Urho3D
  37. {
  38. unsigned LookupVertexBuffer(VertexBuffer* buffer, const Vector<SharedPtr<VertexBuffer> >& buffers)
  39. {
  40. for (unsigned i = 0; i < buffers.Size(); ++i)
  41. {
  42. if (buffers[i] == buffer)
  43. return i;
  44. }
  45. return 0;
  46. }
  47. unsigned LookupIndexBuffer(IndexBuffer* buffer, const Vector<SharedPtr<IndexBuffer> >& buffers)
  48. {
  49. for (unsigned i = 0; i < buffers.Size(); ++i)
  50. {
  51. if (buffers[i] == buffer)
  52. return i;
  53. }
  54. return 0;
  55. }
  56. Model::Model(Context* context) :
  57. ResourceWithMetadata(context)
  58. {
  59. }
  60. Model::~Model() = default;
  61. void Model::RegisterObject(Context* context)
  62. {
  63. context->RegisterFactory<Model>();
  64. }
  65. bool Model::BeginLoad(Deserializer& source)
  66. {
  67. // Check ID
  68. String fileID = source.ReadFileID();
  69. if (fileID != "UMDL" && fileID != "UMD2")
  70. {
  71. URHO3D_LOGERROR(source.GetName() + " is not a valid model file");
  72. return false;
  73. }
  74. bool hasVertexDeclarations = (fileID == "UMD2");
  75. geometries_.Clear();
  76. geometryBoneMappings_.Clear();
  77. geometryCenters_.Clear();
  78. morphs_.Clear();
  79. vertexBuffers_.Clear();
  80. indexBuffers_.Clear();
  81. unsigned memoryUse = sizeof(Model);
  82. bool async = GetAsyncLoadState() == ASYNC_LOADING;
  83. // Read vertex buffers
  84. unsigned numVertexBuffers = source.ReadUInt();
  85. vertexBuffers_.Reserve(numVertexBuffers);
  86. morphRangeStarts_.Resize(numVertexBuffers);
  87. morphRangeCounts_.Resize(numVertexBuffers);
  88. loadVBData_.Resize(numVertexBuffers);
  89. for (unsigned i = 0; i < numVertexBuffers; ++i)
  90. {
  91. VertexBufferDesc& desc = loadVBData_[i];
  92. desc.vertexCount_ = source.ReadUInt();
  93. if (!hasVertexDeclarations)
  94. {
  95. unsigned elementMask = source.ReadUInt();
  96. desc.vertexElements_ = VertexBuffer::GetElements(elementMask);
  97. }
  98. else
  99. {
  100. desc.vertexElements_.Clear();
  101. unsigned numElements = source.ReadUInt();
  102. for (unsigned j = 0; j < numElements; ++j)
  103. {
  104. unsigned elementDesc = source.ReadUInt();
  105. auto type = (VertexElementType)(elementDesc & 0xffu);
  106. auto semantic = (VertexElementSemantic)((elementDesc >> 8u) & 0xffu);
  107. auto index = (unsigned char)((elementDesc >> 16u) & 0xffu);
  108. desc.vertexElements_.Push(VertexElement(type, semantic, index));
  109. }
  110. }
  111. morphRangeStarts_[i] = source.ReadUInt();
  112. morphRangeCounts_[i] = source.ReadUInt();
  113. SharedPtr<VertexBuffer> buffer(new VertexBuffer(context_));
  114. unsigned vertexSize = VertexBuffer::GetVertexSize(desc.vertexElements_);
  115. desc.dataSize_ = desc.vertexCount_ * vertexSize;
  116. // Prepare vertex buffer data to be uploaded during EndLoad()
  117. if (async)
  118. {
  119. desc.data_ = new unsigned char[desc.dataSize_];
  120. source.Read(desc.data_.Get(), desc.dataSize_);
  121. }
  122. else
  123. {
  124. // If not async loading, use locking to avoid extra allocation & copy
  125. desc.data_.Reset(); // Make sure no previous data
  126. buffer->SetShadowed(true);
  127. buffer->SetSize(desc.vertexCount_, desc.vertexElements_);
  128. void* dest = buffer->Lock(0, desc.vertexCount_);
  129. source.Read(dest, desc.vertexCount_ * vertexSize);
  130. buffer->Unlock();
  131. }
  132. memoryUse += sizeof(VertexBuffer) + desc.vertexCount_ * vertexSize;
  133. vertexBuffers_.Push(buffer);
  134. }
  135. // Read index buffers
  136. unsigned numIndexBuffers = source.ReadUInt();
  137. indexBuffers_.Reserve(numIndexBuffers);
  138. loadIBData_.Resize(numIndexBuffers);
  139. for (unsigned i = 0; i < numIndexBuffers; ++i)
  140. {
  141. unsigned indexCount = source.ReadUInt();
  142. unsigned indexSize = source.ReadUInt();
  143. SharedPtr<IndexBuffer> buffer(new IndexBuffer(context_));
  144. // Prepare index buffer data to be uploaded during EndLoad()
  145. if (async)
  146. {
  147. loadIBData_[i].indexCount_ = indexCount;
  148. loadIBData_[i].indexSize_ = indexSize;
  149. loadIBData_[i].dataSize_ = indexCount * indexSize;
  150. loadIBData_[i].data_ = new unsigned char[loadIBData_[i].dataSize_];
  151. source.Read(loadIBData_[i].data_.Get(), loadIBData_[i].dataSize_);
  152. }
  153. else
  154. {
  155. // If not async loading, use locking to avoid extra allocation & copy
  156. loadIBData_[i].data_.Reset(); // Make sure no previous data
  157. buffer->SetShadowed(true);
  158. buffer->SetSize(indexCount, indexSize > sizeof(unsigned short));
  159. void* dest = buffer->Lock(0, indexCount);
  160. source.Read(dest, indexCount * indexSize);
  161. buffer->Unlock();
  162. }
  163. memoryUse += sizeof(IndexBuffer) + indexCount * indexSize;
  164. indexBuffers_.Push(buffer);
  165. }
  166. // Read geometries
  167. unsigned numGeometries = source.ReadUInt();
  168. geometries_.Reserve(numGeometries);
  169. geometryBoneMappings_.Reserve(numGeometries);
  170. geometryCenters_.Reserve(numGeometries);
  171. loadGeometries_.Resize(numGeometries);
  172. for (unsigned i = 0; i < numGeometries; ++i)
  173. {
  174. // Read bone mappings
  175. unsigned boneMappingCount = source.ReadUInt();
  176. PODVector<unsigned> boneMapping(boneMappingCount);
  177. for (unsigned j = 0; j < boneMappingCount; ++j)
  178. boneMapping[j] = source.ReadUInt();
  179. geometryBoneMappings_.Push(boneMapping);
  180. unsigned numLodLevels = source.ReadUInt();
  181. Vector<SharedPtr<Geometry> > geometryLodLevels;
  182. geometryLodLevels.Reserve(numLodLevels);
  183. loadGeometries_[i].Resize(numLodLevels);
  184. for (unsigned j = 0; j < numLodLevels; ++j)
  185. {
  186. float distance = source.ReadFloat();
  187. auto type = (PrimitiveType)source.ReadUInt();
  188. unsigned vbRef = source.ReadUInt();
  189. unsigned ibRef = source.ReadUInt();
  190. unsigned indexStart = source.ReadUInt();
  191. unsigned indexCount = source.ReadUInt();
  192. if (vbRef >= vertexBuffers_.Size())
  193. {
  194. URHO3D_LOGERROR("Vertex buffer index out of bounds");
  195. loadVBData_.Clear();
  196. loadIBData_.Clear();
  197. loadGeometries_.Clear();
  198. return false;
  199. }
  200. if (ibRef >= indexBuffers_.Size())
  201. {
  202. URHO3D_LOGERROR("Index buffer index out of bounds");
  203. loadVBData_.Clear();
  204. loadIBData_.Clear();
  205. loadGeometries_.Clear();
  206. return false;
  207. }
  208. SharedPtr<Geometry> geometry(new Geometry(context_));
  209. geometry->SetLodDistance(distance);
  210. // Prepare geometry to be defined during EndLoad()
  211. loadGeometries_[i][j].type_ = type;
  212. loadGeometries_[i][j].vbRef_ = vbRef;
  213. loadGeometries_[i][j].ibRef_ = ibRef;
  214. loadGeometries_[i][j].indexStart_ = indexStart;
  215. loadGeometries_[i][j].indexCount_ = indexCount;
  216. geometryLodLevels.Push(geometry);
  217. memoryUse += sizeof(Geometry);
  218. }
  219. geometries_.Push(geometryLodLevels);
  220. }
  221. // Read morphs
  222. unsigned numMorphs = source.ReadUInt();
  223. morphs_.Reserve(numMorphs);
  224. for (unsigned i = 0; i < numMorphs; ++i)
  225. {
  226. ModelMorph newMorph;
  227. newMorph.name_ = source.ReadString();
  228. newMorph.nameHash_ = newMorph.name_;
  229. newMorph.weight_ = 0.0f;
  230. unsigned numBuffers = source.ReadUInt();
  231. for (unsigned j = 0; j < numBuffers; ++j)
  232. {
  233. VertexBufferMorph newBuffer;
  234. unsigned bufferIndex = source.ReadUInt();
  235. newBuffer.elementMask_ = VertexMaskFlags(source.ReadUInt());
  236. newBuffer.vertexCount_ = source.ReadUInt();
  237. // Base size: size of each vertex index
  238. unsigned vertexSize = sizeof(unsigned);
  239. // Add size of individual elements
  240. if (newBuffer.elementMask_ & MASK_POSITION)
  241. vertexSize += sizeof(Vector3);
  242. if (newBuffer.elementMask_ & MASK_NORMAL)
  243. vertexSize += sizeof(Vector3);
  244. if (newBuffer.elementMask_ & MASK_TANGENT)
  245. vertexSize += sizeof(Vector3);
  246. newBuffer.dataSize_ = newBuffer.vertexCount_ * vertexSize;
  247. newBuffer.morphData_ = new unsigned char[newBuffer.dataSize_];
  248. source.Read(&newBuffer.morphData_[0], newBuffer.vertexCount_ * vertexSize);
  249. newMorph.buffers_[bufferIndex] = newBuffer;
  250. memoryUse += sizeof(VertexBufferMorph) + newBuffer.vertexCount_ * vertexSize;
  251. }
  252. morphs_.Push(newMorph);
  253. memoryUse += sizeof(ModelMorph);
  254. }
  255. // Read skeleton
  256. skeleton_.Load(source);
  257. memoryUse += skeleton_.GetNumBones() * sizeof(Bone);
  258. // Read bounding box
  259. boundingBox_ = source.ReadBoundingBox();
  260. // Read geometry centers
  261. for (unsigned i = 0; i < geometries_.Size() && !source.IsEof(); ++i)
  262. geometryCenters_.Push(source.ReadVector3());
  263. while (geometryCenters_.Size() < geometries_.Size())
  264. geometryCenters_.Push(Vector3::ZERO);
  265. memoryUse += sizeof(Vector3) * geometries_.Size();
  266. // Read metadata
  267. auto* cache = GetSubsystem<ResourceCache>();
  268. String xmlName = ReplaceExtension(GetName(), ".xml");
  269. SharedPtr<XMLFile> file(cache->GetTempResource<XMLFile>(xmlName, false));
  270. if (file)
  271. LoadMetadataFromXML(file->GetRoot());
  272. SetMemoryUse(memoryUse);
  273. return true;
  274. }
  275. bool Model::EndLoad()
  276. {
  277. // Upload vertex buffer data
  278. for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
  279. {
  280. VertexBuffer* buffer = vertexBuffers_[i];
  281. VertexBufferDesc& desc = loadVBData_[i];
  282. if (desc.data_)
  283. {
  284. buffer->SetShadowed(true);
  285. buffer->SetSize(desc.vertexCount_, desc.vertexElements_);
  286. buffer->SetData(desc.data_.Get());
  287. }
  288. }
  289. // Upload index buffer data
  290. for (unsigned i = 0; i < indexBuffers_.Size(); ++i)
  291. {
  292. IndexBuffer* buffer = indexBuffers_[i];
  293. IndexBufferDesc& desc = loadIBData_[i];
  294. if (desc.data_)
  295. {
  296. buffer->SetShadowed(true);
  297. buffer->SetSize(desc.indexCount_, desc.indexSize_ > sizeof(unsigned short));
  298. buffer->SetData(desc.data_.Get());
  299. }
  300. }
  301. // Set up geometries
  302. for (unsigned i = 0; i < geometries_.Size(); ++i)
  303. {
  304. for (unsigned j = 0; j < geometries_[i].Size(); ++j)
  305. {
  306. Geometry* geometry = geometries_[i][j];
  307. GeometryDesc& desc = loadGeometries_[i][j];
  308. geometry->SetVertexBuffer(0, vertexBuffers_[desc.vbRef_]);
  309. geometry->SetIndexBuffer(indexBuffers_[desc.ibRef_]);
  310. geometry->SetDrawRange(desc.type_, desc.indexStart_, desc.indexCount_);
  311. }
  312. }
  313. loadVBData_.Clear();
  314. loadIBData_.Clear();
  315. loadGeometries_.Clear();
  316. return true;
  317. }
  318. bool Model::Save(Serializer& dest) const
  319. {
  320. // Write ID
  321. if (!dest.WriteFileID("UMD2"))
  322. return false;
  323. // Write vertex buffers
  324. dest.WriteUInt(vertexBuffers_.Size());
  325. for (unsigned i = 0; i < vertexBuffers_.Size(); ++i)
  326. {
  327. VertexBuffer* buffer = vertexBuffers_[i];
  328. dest.WriteUInt(buffer->GetVertexCount());
  329. const PODVector<VertexElement>& elements = buffer->GetElements();
  330. dest.WriteUInt(elements.Size());
  331. for (unsigned j = 0; j < elements.Size(); ++j)
  332. {
  333. unsigned elementDesc = ((unsigned)elements[j].type_) |
  334. (((unsigned)elements[j].semantic_) << 8u) |
  335. (((unsigned)elements[j].index_) << 16u);
  336. dest.WriteUInt(elementDesc);
  337. }
  338. dest.WriteUInt(morphRangeStarts_[i]);
  339. dest.WriteUInt(morphRangeCounts_[i]);
  340. dest.Write(buffer->GetShadowData(), buffer->GetVertexCount() * buffer->GetVertexSize());
  341. }
  342. // Write index buffers
  343. dest.WriteUInt(indexBuffers_.Size());
  344. for (unsigned i = 0; i < indexBuffers_.Size(); ++i)
  345. {
  346. IndexBuffer* buffer = indexBuffers_[i];
  347. dest.WriteUInt(buffer->GetIndexCount());
  348. dest.WriteUInt(buffer->GetIndexSize());
  349. dest.Write(buffer->GetShadowData(), buffer->GetIndexCount() * buffer->GetIndexSize());
  350. }
  351. // Write geometries
  352. dest.WriteUInt(geometries_.Size());
  353. for (unsigned i = 0; i < geometries_.Size(); ++i)
  354. {
  355. // Write bone mappings
  356. dest.WriteUInt(geometryBoneMappings_[i].Size());
  357. for (unsigned j = 0; j < geometryBoneMappings_[i].Size(); ++j)
  358. dest.WriteUInt(geometryBoneMappings_[i][j]);
  359. // Write the LOD levels
  360. dest.WriteUInt(geometries_[i].Size());
  361. for (unsigned j = 0; j < geometries_[i].Size(); ++j)
  362. {
  363. Geometry* geometry = geometries_[i][j];
  364. dest.WriteFloat(geometry->GetLodDistance());
  365. dest.WriteUInt(geometry->GetPrimitiveType());
  366. dest.WriteUInt(LookupVertexBuffer(geometry->GetVertexBuffer(0), vertexBuffers_));
  367. dest.WriteUInt(LookupIndexBuffer(geometry->GetIndexBuffer(), indexBuffers_));
  368. dest.WriteUInt(geometry->GetIndexStart());
  369. dest.WriteUInt(geometry->GetIndexCount());
  370. }
  371. }
  372. // Write morphs
  373. dest.WriteUInt(morphs_.Size());
  374. for (unsigned i = 0; i < morphs_.Size(); ++i)
  375. {
  376. dest.WriteString(morphs_[i].name_);
  377. dest.WriteUInt(morphs_[i].buffers_.Size());
  378. // Write morph vertex buffers
  379. for (HashMap<unsigned, VertexBufferMorph>::ConstIterator j = morphs_[i].buffers_.Begin();
  380. j != morphs_[i].buffers_.End(); ++j)
  381. {
  382. dest.WriteUInt(j->first_);
  383. dest.WriteUInt(j->second_.elementMask_);
  384. dest.WriteUInt(j->second_.vertexCount_);
  385. // Base size: size of each vertex index
  386. unsigned vertexSize = sizeof(unsigned);
  387. // Add size of individual elements
  388. if (j->second_.elementMask_ & MASK_POSITION)
  389. vertexSize += sizeof(Vector3);
  390. if (j->second_.elementMask_ & MASK_NORMAL)
  391. vertexSize += sizeof(Vector3);
  392. if (j->second_.elementMask_ & MASK_TANGENT)
  393. vertexSize += sizeof(Vector3);
  394. dest.Write(j->second_.morphData_.Get(), vertexSize * j->second_.vertexCount_);
  395. }
  396. }
  397. // Write skeleton
  398. skeleton_.Save(dest);
  399. // Write bounding box
  400. dest.WriteBoundingBox(boundingBox_);
  401. // Write geometry centers
  402. for (unsigned i = 0; i < geometryCenters_.Size(); ++i)
  403. dest.WriteVector3(geometryCenters_[i]);
  404. // Write metadata
  405. if (HasMetadata())
  406. {
  407. auto* destFile = dynamic_cast<File*>(&dest);
  408. if (destFile)
  409. {
  410. String xmlName = ReplaceExtension(destFile->GetName(), ".xml");
  411. SharedPtr<XMLFile> xml(new XMLFile(context_));
  412. XMLElement rootElem = xml->CreateRoot("model");
  413. SaveMetadataToXML(rootElem);
  414. File xmlFile(context_, xmlName, FILE_WRITE);
  415. xml->Save(xmlFile);
  416. }
  417. else
  418. URHO3D_LOGWARNING("Can not save model metadata when not saving into a file");
  419. }
  420. return true;
  421. }
  422. void Model::SetBoundingBox(const BoundingBox& box)
  423. {
  424. boundingBox_ = box;
  425. }
  426. bool Model::SetVertexBuffers(const Vector<SharedPtr<VertexBuffer> >& buffers, const PODVector<unsigned>& morphRangeStarts,
  427. const PODVector<unsigned>& morphRangeCounts)
  428. {
  429. for (unsigned i = 0; i < buffers.Size(); ++i)
  430. {
  431. if (!buffers[i])
  432. {
  433. URHO3D_LOGERROR("Null model vertex buffers specified");
  434. return false;
  435. }
  436. if (!buffers[i]->IsShadowed())
  437. {
  438. URHO3D_LOGERROR("Model vertex buffers must be shadowed");
  439. return false;
  440. }
  441. }
  442. vertexBuffers_ = buffers;
  443. morphRangeStarts_.Resize(buffers.Size());
  444. morphRangeCounts_.Resize(buffers.Size());
  445. // If morph ranges are not specified for buffers, assume to be zero
  446. for (unsigned i = 0; i < buffers.Size(); ++i)
  447. {
  448. morphRangeStarts_[i] = i < morphRangeStarts.Size() ? morphRangeStarts[i] : 0;
  449. morphRangeCounts_[i] = i < morphRangeCounts.Size() ? morphRangeCounts[i] : 0;
  450. }
  451. return true;
  452. }
  453. bool Model::SetIndexBuffers(const Vector<SharedPtr<IndexBuffer> >& buffers)
  454. {
  455. for (unsigned i = 0; i < buffers.Size(); ++i)
  456. {
  457. if (!buffers[i])
  458. {
  459. URHO3D_LOGERROR("Null model index buffers specified");
  460. return false;
  461. }
  462. if (!buffers[i]->IsShadowed())
  463. {
  464. URHO3D_LOGERROR("Model index buffers must be shadowed");
  465. return false;
  466. }
  467. }
  468. indexBuffers_ = buffers;
  469. return true;
  470. }
  471. void Model::SetNumGeometries(unsigned num)
  472. {
  473. geometries_.Resize(num);
  474. geometryBoneMappings_.Resize(num);
  475. geometryCenters_.Resize(num);
  476. // For easier creation of from-scratch geometry, ensure that all geometries start with at least 1 LOD level (0 makes no sense)
  477. for (unsigned i = 0; i < geometries_.Size(); ++i)
  478. {
  479. if (geometries_[i].Empty())
  480. geometries_[i].Resize(1);
  481. }
  482. }
  483. bool Model::SetNumGeometryLodLevels(unsigned index, unsigned num)
  484. {
  485. if (index >= geometries_.Size())
  486. {
  487. URHO3D_LOGERROR("Geometry index out of bounds");
  488. return false;
  489. }
  490. if (!num)
  491. {
  492. URHO3D_LOGERROR("Zero LOD levels not allowed");
  493. return false;
  494. }
  495. geometries_[index].Resize(num);
  496. return true;
  497. }
  498. bool Model::SetGeometry(unsigned index, unsigned lodLevel, Geometry* geometry)
  499. {
  500. if (index >= geometries_.Size())
  501. {
  502. URHO3D_LOGERROR("Geometry index out of bounds");
  503. return false;
  504. }
  505. if (lodLevel >= geometries_[index].Size())
  506. {
  507. URHO3D_LOGERROR("LOD level index out of bounds");
  508. return false;
  509. }
  510. geometries_[index][lodLevel] = geometry;
  511. return true;
  512. }
  513. bool Model::SetGeometryCenter(unsigned index, const Vector3& center)
  514. {
  515. if (index >= geometryCenters_.Size())
  516. {
  517. URHO3D_LOGERROR("Geometry index out of bounds");
  518. return false;
  519. }
  520. geometryCenters_[index] = center;
  521. return true;
  522. }
  523. void Model::SetSkeleton(const Skeleton& skeleton)
  524. {
  525. skeleton_ = skeleton;
  526. }
  527. void Model::SetGeometryBoneMappings(const Vector<PODVector<unsigned> >& geometryBoneMappings)
  528. {
  529. geometryBoneMappings_ = geometryBoneMappings;
  530. }
  531. void Model::SetMorphs(const Vector<ModelMorph>& morphs)
  532. {
  533. morphs_ = morphs;
  534. }
  535. SharedPtr<Model> Model::Clone(const String& cloneName) const
  536. {
  537. SharedPtr<Model> ret(new Model(context_));
  538. ret->SetName(cloneName);
  539. ret->boundingBox_ = boundingBox_;
  540. ret->skeleton_ = skeleton_;
  541. ret->geometryBoneMappings_ = geometryBoneMappings_;
  542. ret->geometryCenters_ = geometryCenters_;
  543. ret->morphs_ = morphs_;
  544. ret->morphRangeStarts_ = morphRangeStarts_;
  545. ret->morphRangeCounts_ = morphRangeCounts_;
  546. // Deep copy vertex/index buffers
  547. HashMap<VertexBuffer*, VertexBuffer*> vbMapping;
  548. for (Vector<SharedPtr<VertexBuffer> >::ConstIterator i = vertexBuffers_.Begin(); i != vertexBuffers_.End(); ++i)
  549. {
  550. VertexBuffer* origBuffer = *i;
  551. SharedPtr<VertexBuffer> cloneBuffer;
  552. if (origBuffer)
  553. {
  554. cloneBuffer = new VertexBuffer(context_);
  555. cloneBuffer->SetSize(origBuffer->GetVertexCount(), origBuffer->GetElementMask(), origBuffer->IsDynamic());
  556. cloneBuffer->SetShadowed(origBuffer->IsShadowed());
  557. if (origBuffer->IsShadowed())
  558. cloneBuffer->SetData(origBuffer->GetShadowData());
  559. else
  560. {
  561. void* origData = origBuffer->Lock(0, origBuffer->GetVertexCount());
  562. if (origData)
  563. cloneBuffer->SetData(origData);
  564. else
  565. URHO3D_LOGERROR("Failed to lock original vertex buffer for copying");
  566. }
  567. vbMapping[origBuffer] = cloneBuffer;
  568. }
  569. ret->vertexBuffers_.Push(cloneBuffer);
  570. }
  571. HashMap<IndexBuffer*, IndexBuffer*> ibMapping;
  572. for (Vector<SharedPtr<IndexBuffer> >::ConstIterator i = indexBuffers_.Begin(); i != indexBuffers_.End(); ++i)
  573. {
  574. IndexBuffer* origBuffer = *i;
  575. SharedPtr<IndexBuffer> cloneBuffer;
  576. if (origBuffer)
  577. {
  578. cloneBuffer = new IndexBuffer(context_);
  579. cloneBuffer->SetSize(origBuffer->GetIndexCount(), origBuffer->GetIndexSize() == sizeof(unsigned),
  580. origBuffer->IsDynamic());
  581. cloneBuffer->SetShadowed(origBuffer->IsShadowed());
  582. if (origBuffer->IsShadowed())
  583. cloneBuffer->SetData(origBuffer->GetShadowData());
  584. else
  585. {
  586. void* origData = origBuffer->Lock(0, origBuffer->GetIndexCount());
  587. if (origData)
  588. cloneBuffer->SetData(origData);
  589. else
  590. URHO3D_LOGERROR("Failed to lock original index buffer for copying");
  591. }
  592. ibMapping[origBuffer] = cloneBuffer;
  593. }
  594. ret->indexBuffers_.Push(cloneBuffer);
  595. }
  596. // Deep copy all the geometry LOD levels and refer to the copied vertex/index buffers
  597. ret->geometries_.Resize(geometries_.Size());
  598. for (unsigned i = 0; i < geometries_.Size(); ++i)
  599. {
  600. ret->geometries_[i].Resize(geometries_[i].Size());
  601. for (unsigned j = 0; j < geometries_[i].Size(); ++j)
  602. {
  603. SharedPtr<Geometry> cloneGeometry;
  604. Geometry* origGeometry = geometries_[i][j];
  605. if (origGeometry)
  606. {
  607. cloneGeometry = new Geometry(context_);
  608. cloneGeometry->SetIndexBuffer(ibMapping[origGeometry->GetIndexBuffer()]);
  609. unsigned numVbs = origGeometry->GetNumVertexBuffers();
  610. for (unsigned k = 0; k < numVbs; ++k)
  611. {
  612. cloneGeometry->SetVertexBuffer(k, vbMapping[origGeometry->GetVertexBuffer(k)]);
  613. }
  614. cloneGeometry->SetDrawRange(origGeometry->GetPrimitiveType(), origGeometry->GetIndexStart(),
  615. origGeometry->GetIndexCount(), origGeometry->GetVertexStart(), origGeometry->GetVertexCount(), false);
  616. cloneGeometry->SetLodDistance(origGeometry->GetLodDistance());
  617. }
  618. ret->geometries_[i][j] = cloneGeometry;
  619. }
  620. }
  621. // Deep copy the morph data (if any) to allow modifying it
  622. for (Vector<ModelMorph>::Iterator i = ret->morphs_.Begin(); i != ret->morphs_.End(); ++i)
  623. {
  624. ModelMorph& morph = *i;
  625. for (HashMap<unsigned, VertexBufferMorph>::Iterator j = morph.buffers_.Begin(); j != morph.buffers_.End(); ++j)
  626. {
  627. VertexBufferMorph& vbMorph = j->second_;
  628. if (vbMorph.dataSize_)
  629. {
  630. SharedArrayPtr<unsigned char> cloneData(new unsigned char[vbMorph.dataSize_]);
  631. memcpy(cloneData.Get(), vbMorph.morphData_.Get(), vbMorph.dataSize_);
  632. vbMorph.morphData_ = cloneData;
  633. }
  634. }
  635. }
  636. ret->SetMemoryUse(GetMemoryUse());
  637. return ret;
  638. }
  639. unsigned Model::GetNumGeometryLodLevels(unsigned index) const
  640. {
  641. return index < geometries_.Size() ? geometries_[index].Size() : 0;
  642. }
  643. Geometry* Model::GetGeometry(unsigned index, unsigned lodLevel) const
  644. {
  645. if (index >= geometries_.Size() || geometries_[index].Empty())
  646. return nullptr;
  647. if (lodLevel >= geometries_[index].Size())
  648. lodLevel = geometries_[index].Size() - 1;
  649. return geometries_[index][lodLevel];
  650. }
  651. const ModelMorph* Model::GetMorph(unsigned index) const
  652. {
  653. return index < morphs_.Size() ? &morphs_[index] : nullptr;
  654. }
  655. const ModelMorph* Model::GetMorph(const String& name) const
  656. {
  657. return GetMorph(StringHash(name));
  658. }
  659. const ModelMorph* Model::GetMorph(StringHash nameHash) const
  660. {
  661. for (Vector<ModelMorph>::ConstIterator i = morphs_.Begin(); i != morphs_.End(); ++i)
  662. {
  663. if (i->nameHash_ == nameHash)
  664. return &(*i);
  665. }
  666. return nullptr;
  667. }
  668. unsigned Model::GetMorphRangeStart(unsigned bufferIndex) const
  669. {
  670. return bufferIndex < vertexBuffers_.Size() ? morphRangeStarts_[bufferIndex] : 0;
  671. }
  672. unsigned Model::GetMorphRangeCount(unsigned bufferIndex) const
  673. {
  674. return bufferIndex < vertexBuffers_.Size() ? morphRangeCounts_[bufferIndex] : 0;
  675. }
  676. }