2
0

BsRenderable.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsRenderable.h"
  4. #include "BsRenderableRTTI.h"
  5. #include "BsSceneObject.h"
  6. #include "BsMesh.h"
  7. #include "BsMaterial.h"
  8. #include "BsBounds.h"
  9. #include "BsRenderer.h"
  10. #include "BsAnimation.h"
  11. #include "BsFrameAlloc.h"
  12. #include "BsMorphShapes.h"
  13. #include "BsGpuBuffer.h"
  14. #include "BsAnimationManager.h"
  15. namespace bs
  16. {
  17. template<class T>
  18. bool isMeshValid(const T& mesh) { return false; }
  19. template<>
  20. bool isMeshValid(const HMesh& mesh) { return mesh.isLoaded(); }
  21. template<>
  22. bool isMeshValid(const SPtr<ct::Mesh>& mesh) { return mesh != nullptr; }
  23. template<bool Core>
  24. TRenderable<Core>::TRenderable()
  25. : mLayer(1), mUseOverrideBounds(false), mPosition(BsZero), mTransform(BsIdentity), mTransformNoScale(BsIdentity)
  26. , mIsActive(true), mAnimType(RenderableAnimType::None)
  27. {
  28. mMaterials.resize(1);
  29. }
  30. template<bool Core>
  31. TRenderable<Core>::~TRenderable()
  32. {
  33. }
  34. template<bool Core>
  35. void TRenderable<Core>::setMesh(const MeshType& mesh)
  36. {
  37. mMesh = mesh;
  38. int numSubMeshes = 0;
  39. if (isMeshValid(mesh))
  40. numSubMeshes = mesh->getProperties().getNumSubMeshes();
  41. mMaterials.resize(numSubMeshes);
  42. onMeshChanged();
  43. _markDependenciesDirty();
  44. _markResourcesDirty();
  45. _markCoreDirty();
  46. }
  47. template<bool Core>
  48. void TRenderable<Core>::setMaterial(UINT32 idx, const MaterialType& material)
  49. {
  50. if (idx >= (UINT32)mMaterials.size())
  51. return;
  52. mMaterials[idx] = material;
  53. _markDependenciesDirty();
  54. _markResourcesDirty();
  55. _markCoreDirty();
  56. }
  57. template<bool Core>
  58. void TRenderable<Core>::setMaterials(const Vector<MaterialType>& materials)
  59. {
  60. UINT32 numMaterials = (UINT32)mMaterials.size();
  61. UINT32 min = std::min(numMaterials, (UINT32)materials.size());
  62. for (UINT32 i = 0; i < min; i++)
  63. mMaterials[i] = materials[i];
  64. for (UINT32 i = min; i < numMaterials; i++)
  65. mMaterials[i] = nullptr;
  66. _markDependenciesDirty();
  67. _markResourcesDirty();
  68. _markCoreDirty();
  69. }
  70. template<bool Core>
  71. void TRenderable<Core>::setMaterial(const MaterialType& material)
  72. {
  73. setMaterial(0, material);
  74. }
  75. template<bool Core>
  76. void TRenderable<Core>::setLayer(UINT64 layer)
  77. {
  78. bool isPow2 = layer && !((layer - 1) & layer);
  79. if (!isPow2)
  80. {
  81. LOGWRN("Invalid layer provided. Only one layer bit may be set. Ignoring.");
  82. return;
  83. }
  84. mLayer = layer;
  85. _markCoreDirty();
  86. }
  87. template<bool Core>
  88. void TRenderable<Core>::setTransform(const Matrix4& transform, const Matrix4& transformNoScale)
  89. {
  90. mTransform = transform;
  91. mTransformNoScale = transformNoScale;
  92. mPosition = mTransform.getTranslation();
  93. _markCoreDirty(RenderableDirtyFlag::Transform);
  94. }
  95. template<bool Core>
  96. void TRenderable<Core>::setIsActive(bool active)
  97. {
  98. mIsActive = active;
  99. _markCoreDirty();
  100. }
  101. template<bool Core>
  102. void TRenderable<Core>::setOverrideBounds(const AABox& bounds)
  103. {
  104. mOverrideBounds = bounds;
  105. if(mUseOverrideBounds)
  106. _markCoreDirty();
  107. }
  108. template<bool Core>
  109. void TRenderable<Core>::setUseOverrideBounds(bool enable)
  110. {
  111. if (mUseOverrideBounds == enable)
  112. return;
  113. mUseOverrideBounds = enable;
  114. _markCoreDirty();
  115. }
  116. template class TRenderable < false >;
  117. template class TRenderable < true >;
  118. Renderable::Renderable()
  119. :mLastUpdateHash(0)
  120. {
  121. }
  122. void Renderable::setAnimation(const SPtr<Animation>& animation)
  123. {
  124. mAnimation = animation;
  125. refreshAnimation();
  126. _markCoreDirty();
  127. }
  128. Bounds Renderable::getBounds() const
  129. {
  130. if(mUseOverrideBounds)
  131. {
  132. Sphere sphere(mOverrideBounds.getCenter(), mOverrideBounds.getRadius());
  133. Bounds bounds(mOverrideBounds, sphere);
  134. bounds.transformAffine(mTransform);
  135. return bounds;
  136. }
  137. HMesh mesh = getMesh();
  138. if (!mesh.isLoaded())
  139. {
  140. AABox box(mPosition, mPosition);
  141. Sphere sphere(mPosition, 0.0f);
  142. return Bounds(box, sphere);
  143. }
  144. else
  145. {
  146. Bounds bounds = mesh->getProperties().getBounds();
  147. bounds.transformAffine(mTransform);
  148. return bounds;
  149. }
  150. }
  151. SPtr<ct::Renderable> Renderable::getCore() const
  152. {
  153. return std::static_pointer_cast<ct::Renderable>(mCoreSpecific);
  154. }
  155. SPtr<ct::CoreObject> Renderable::createCore() const
  156. {
  157. ct::Renderable* handler = new (bs_alloc<ct::Renderable>()) ct::Renderable();
  158. SPtr<ct::Renderable> handlerPtr = bs_shared_ptr<ct::Renderable>(handler);
  159. handlerPtr->_setThisPtr(handlerPtr);
  160. return handlerPtr;
  161. }
  162. void Renderable::onMeshChanged()
  163. {
  164. refreshAnimation();
  165. }
  166. void Renderable::refreshAnimation()
  167. {
  168. if (mAnimation == nullptr)
  169. {
  170. mAnimType = RenderableAnimType::None;
  171. return;
  172. }
  173. if (mMesh.isLoaded(false))
  174. {
  175. SPtr<Skeleton> skeleton = mMesh->getSkeleton();
  176. SPtr<MorphShapes> morphShapes = mMesh->getMorphShapes();
  177. if (skeleton != nullptr && morphShapes != nullptr)
  178. mAnimType = RenderableAnimType::SkinnedMorph;
  179. else if (skeleton != nullptr)
  180. mAnimType = RenderableAnimType::Skinned;
  181. else if (morphShapes != nullptr)
  182. mAnimType = RenderableAnimType::Morph;
  183. else
  184. mAnimType = RenderableAnimType::None;
  185. mAnimation->setSkeleton(mMesh->getSkeleton());
  186. mAnimation->setMorphShapes(mMesh->getMorphShapes());
  187. }
  188. else
  189. {
  190. mAnimType = RenderableAnimType::None;
  191. mAnimation->setSkeleton(nullptr);
  192. mAnimation->setMorphShapes(nullptr);
  193. }
  194. }
  195. void Renderable::_updateTransform(const HSceneObject& so, bool force)
  196. {
  197. UINT32 curHash = so->getTransformHash();
  198. if (curHash != _getLastModifiedHash() || force)
  199. {
  200. // If skinned animation, don't include own transform since that will be handled by root bone animation
  201. bool ignoreOwnTransform;
  202. if (mAnimType == RenderableAnimType::Skinned || mAnimType == RenderableAnimType::SkinnedMorph)
  203. ignoreOwnTransform = mAnimation->_getAnimatesRoot();
  204. else
  205. ignoreOwnTransform = false;
  206. if (ignoreOwnTransform)
  207. {
  208. // Note: Technically we're checking child's hash but using parent's transform. Ideally we check the parent's
  209. // hash to reduce the number of required updates.
  210. HSceneObject parentSO = so->getParent();
  211. if (parentSO != nullptr)
  212. {
  213. Matrix4 transformNoScale = Matrix4::TRS(parentSO->getWorldPosition(), parentSO->getWorldRotation(),
  214. Vector3::ONE);
  215. setTransform(parentSO->getWorldTfrm(), transformNoScale);
  216. }
  217. else
  218. setTransform(Matrix4::IDENTITY, Matrix4::IDENTITY);
  219. }
  220. else
  221. {
  222. Matrix4 transformNoScale = Matrix4::TRS(so->getWorldPosition(), so->getWorldRotation(), Vector3::ONE);
  223. setTransform(so->getWorldTfrm(), transformNoScale);
  224. }
  225. _setLastModifiedHash(curHash);
  226. }
  227. }
  228. void Renderable::_markCoreDirty(RenderableDirtyFlag flag)
  229. {
  230. markCoreDirty((UINT32)flag);
  231. }
  232. void Renderable::_markDependenciesDirty()
  233. {
  234. markDependenciesDirty();
  235. }
  236. void Renderable::_markResourcesDirty()
  237. {
  238. markListenerResourcesDirty();
  239. }
  240. CoreSyncData Renderable::syncToCore(FrameAlloc* allocator)
  241. {
  242. UINT32 numMaterials = (UINT32)mMaterials.size();
  243. UINT64 animationId;
  244. if (mAnimation != nullptr)
  245. animationId = mAnimation->_getId();
  246. else
  247. animationId = (UINT64)-1;
  248. UINT32 size = rttiGetElemSize(mLayer) +
  249. rttiGetElemSize(mOverrideBounds) +
  250. rttiGetElemSize(mUseOverrideBounds) +
  251. rttiGetElemSize(numMaterials) +
  252. rttiGetElemSize(mTransform) +
  253. rttiGetElemSize(mTransformNoScale) +
  254. rttiGetElemSize(mPosition) +
  255. rttiGetElemSize(mIsActive) +
  256. rttiGetElemSize(animationId) +
  257. rttiGetElemSize(mAnimType) +
  258. rttiGetElemSize(getCoreDirtyFlags()) +
  259. sizeof(SPtr<ct::Mesh>) +
  260. numMaterials * sizeof(SPtr<ct::Material>);
  261. UINT8* data = allocator->alloc(size);
  262. char* dataPtr = (char*)data;
  263. dataPtr = rttiWriteElem(mLayer, dataPtr);
  264. dataPtr = rttiWriteElem(mOverrideBounds, dataPtr);
  265. dataPtr = rttiWriteElem(mUseOverrideBounds, dataPtr);
  266. dataPtr = rttiWriteElem(numMaterials, dataPtr);
  267. dataPtr = rttiWriteElem(mTransform, dataPtr);
  268. dataPtr = rttiWriteElem(mTransformNoScale, dataPtr);
  269. dataPtr = rttiWriteElem(mPosition, dataPtr);
  270. dataPtr = rttiWriteElem(mIsActive, dataPtr);
  271. dataPtr = rttiWriteElem(animationId, dataPtr);
  272. dataPtr = rttiWriteElem(mAnimType, dataPtr);
  273. dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
  274. SPtr<ct::Mesh>* mesh = new (dataPtr) SPtr<ct::Mesh>();
  275. if (mMesh.isLoaded())
  276. *mesh = mMesh->getCore();
  277. dataPtr += sizeof(SPtr<ct::Mesh>);
  278. for (UINT32 i = 0; i < numMaterials; i++)
  279. {
  280. SPtr<ct::Material>* material = new (dataPtr)SPtr<ct::Material>();
  281. if (mMaterials[i].isLoaded())
  282. *material = mMaterials[i]->getCore();
  283. dataPtr += sizeof(SPtr<ct::Material>);
  284. }
  285. return CoreSyncData(data, size);
  286. }
  287. void Renderable::getCoreDependencies(Vector<CoreObject*>& dependencies)
  288. {
  289. if (mMesh.isLoaded())
  290. dependencies.push_back(mMesh.get());
  291. for (auto& material : mMaterials)
  292. {
  293. if (material.isLoaded())
  294. dependencies.push_back(material.get());
  295. }
  296. }
  297. void Renderable::getListenerResources(Vector<HResource>& resources)
  298. {
  299. if (mMesh != nullptr)
  300. resources.push_back(mMesh);
  301. for (auto& material : mMaterials)
  302. {
  303. if (material != nullptr)
  304. resources.push_back(material);
  305. }
  306. }
  307. void Renderable::notifyResourceLoaded(const HResource& resource)
  308. {
  309. if (resource == mMesh)
  310. onMeshChanged();
  311. markDependenciesDirty();
  312. markCoreDirty();
  313. }
  314. void Renderable::notifyResourceChanged(const HResource& resource)
  315. {
  316. if(resource == mMesh)
  317. onMeshChanged();
  318. markDependenciesDirty();
  319. markCoreDirty();
  320. }
  321. SPtr<Renderable> Renderable::create()
  322. {
  323. SPtr<Renderable> handlerPtr = createEmpty();
  324. handlerPtr->initialize();
  325. return handlerPtr;
  326. }
  327. SPtr<Renderable> Renderable::createEmpty()
  328. {
  329. Renderable* handler = new (bs_alloc<Renderable>()) Renderable();
  330. SPtr<Renderable> handlerPtr = bs_core_ptr<Renderable>(handler);
  331. handlerPtr->_setThisPtr(handlerPtr);
  332. return handlerPtr;
  333. }
  334. RTTITypeBase* Renderable::getRTTIStatic()
  335. {
  336. return RenderableRTTI::instance();
  337. }
  338. RTTITypeBase* Renderable::getRTTI() const
  339. {
  340. return Renderable::getRTTIStatic();
  341. }
  342. namespace ct
  343. {
  344. Renderable::Renderable()
  345. :mRendererId(0), mAnimationId((UINT64)-1), mMorphShapeVersion(0)
  346. {
  347. }
  348. Renderable::~Renderable()
  349. {
  350. if (mIsActive)
  351. gRenderer()->notifyRenderableRemoved(this);
  352. }
  353. void Renderable::initialize()
  354. {
  355. gRenderer()->notifyRenderableAdded(this);
  356. CoreObject::initialize();
  357. }
  358. Bounds Renderable::getBounds() const
  359. {
  360. if (mUseOverrideBounds)
  361. {
  362. Sphere sphere(mOverrideBounds.getCenter(), mOverrideBounds.getRadius());
  363. Bounds bounds(mOverrideBounds, sphere);
  364. bounds.transformAffine(mTransform);
  365. return bounds;
  366. }
  367. SPtr<Mesh> mesh = getMesh();
  368. if (mesh == nullptr)
  369. {
  370. AABox box(mPosition, mPosition);
  371. Sphere sphere(mPosition, 0.0f);
  372. return Bounds(box, sphere);
  373. }
  374. else
  375. {
  376. Bounds bounds = mesh->getProperties().getBounds();
  377. bounds.transformAffine(mTransform);
  378. return bounds;
  379. }
  380. }
  381. void Renderable::createAnimationBuffers()
  382. {
  383. if (mAnimType == RenderableAnimType::Skinned || mAnimType == RenderableAnimType::SkinnedMorph)
  384. {
  385. SPtr<Skeleton> skeleton = mMesh->getSkeleton();
  386. UINT32 numBones = skeleton != nullptr ? skeleton->getNumBones() : 0;
  387. if (numBones > 0)
  388. {
  389. GPU_BUFFER_DESC desc;
  390. desc.elementCount = numBones * 3;
  391. desc.elementSize = 0;
  392. desc.type = GBT_STANDARD;
  393. desc.format = BF_32X4F;
  394. desc.usage = GBU_DYNAMIC;
  395. SPtr<GpuBuffer> buffer = GpuBuffer::create(desc);
  396. UINT8* dest = (UINT8*)buffer->lock(0, numBones * 3 * sizeof(Vector4), GBL_WRITE_ONLY_DISCARD);
  397. // Initialize bone transforms to identity, so the object renders properly even if no animation is animating it
  398. for (UINT32 i = 0; i < numBones; i++)
  399. {
  400. memcpy(dest, &Matrix4::IDENTITY, 12 * sizeof(float)); // Assuming row-major format
  401. dest += 12 * sizeof(float);
  402. }
  403. buffer->unlock();
  404. mBoneMatrixBuffer = buffer;
  405. }
  406. else
  407. mBoneMatrixBuffer = nullptr;
  408. }
  409. else
  410. mBoneMatrixBuffer = nullptr;
  411. if (mAnimType == RenderableAnimType::Morph || mAnimType == RenderableAnimType::SkinnedMorph)
  412. {
  413. SPtr<MorphShapes> morphShapes = mMesh->getMorphShapes();
  414. UINT32 vertexSize = sizeof(Vector3) + sizeof(UINT32);
  415. UINT32 numVertices = morphShapes->getNumVertices();
  416. VERTEX_BUFFER_DESC desc;
  417. desc.vertexSize = vertexSize;
  418. desc.numVerts = numVertices;
  419. desc.usage = GBU_DYNAMIC;
  420. SPtr<VertexBuffer> vertexBuffer = VertexBuffer::create(desc);
  421. UINT32 totalSize = vertexSize * numVertices;
  422. UINT8* dest = (UINT8*)vertexBuffer->lock(0, totalSize, GBL_WRITE_ONLY_DISCARD);
  423. memset(dest, 0, totalSize);
  424. vertexBuffer->unlock();
  425. mMorphShapeBuffer = vertexBuffer;
  426. }
  427. else
  428. mMorphShapeBuffer = nullptr;
  429. mMorphShapeVersion = 0;
  430. }
  431. void Renderable::updateAnimationBuffers(const RendererAnimationData& animData)
  432. {
  433. if (mAnimationId == (UINT64)-1)
  434. return;
  435. const RendererAnimationData::AnimInfo* animInfo = nullptr;
  436. auto iterFind = animData.infos.find(mAnimationId);
  437. if (iterFind != animData.infos.end())
  438. animInfo = &iterFind->second;
  439. if (animInfo == nullptr)
  440. return;
  441. if (mAnimType == RenderableAnimType::Skinned || mAnimType == RenderableAnimType::SkinnedMorph)
  442. {
  443. const RendererAnimationData::PoseInfo& poseInfo = animInfo->poseInfo;
  444. // Note: If multiple elements are using the same animation (not possible atm), this buffer should be shared by
  445. // all such elements
  446. UINT8* dest = (UINT8*)mBoneMatrixBuffer->lock(0, poseInfo.numBones * 3 * sizeof(Vector4), GBL_WRITE_ONLY_DISCARD);
  447. for (UINT32 j = 0; j < poseInfo.numBones; j++)
  448. {
  449. const Matrix4& transform = animData.transforms[poseInfo.startIdx + j];
  450. memcpy(dest, &transform, 12 * sizeof(float)); // Assuming row-major format
  451. dest += 12 * sizeof(float);
  452. }
  453. mBoneMatrixBuffer->unlock();
  454. }
  455. if (mAnimType == RenderableAnimType::Morph || mAnimType == RenderableAnimType::SkinnedMorph)
  456. {
  457. if (mMorphShapeVersion < animInfo->morphShapeInfo.version)
  458. {
  459. SPtr<MeshData> meshData = animInfo->morphShapeInfo.meshData;
  460. UINT32 bufferSize = meshData->getSize();
  461. UINT8* data = meshData->getData();
  462. mMorphShapeBuffer->writeData(0, bufferSize, data, BWT_DISCARD);
  463. mMorphShapeVersion = animInfo->morphShapeInfo.version;
  464. }
  465. }
  466. }
  467. void Renderable::syncToCore(const CoreSyncData& data)
  468. {
  469. char* dataPtr = (char*)data.getBuffer();
  470. mMaterials.clear();
  471. UINT32 numMaterials = 0;
  472. UINT32 dirtyFlags = 0;
  473. bool oldIsActive = mIsActive;
  474. dataPtr = rttiReadElem(mLayer, dataPtr);
  475. dataPtr = rttiReadElem(mOverrideBounds, dataPtr);
  476. dataPtr = rttiReadElem(mUseOverrideBounds, dataPtr);
  477. dataPtr = rttiReadElem(numMaterials, dataPtr);
  478. dataPtr = rttiReadElem(mTransform, dataPtr);
  479. dataPtr = rttiReadElem(mTransformNoScale, dataPtr);
  480. dataPtr = rttiReadElem(mPosition, dataPtr);
  481. dataPtr = rttiReadElem(mIsActive, dataPtr);
  482. dataPtr = rttiReadElem(mAnimationId, dataPtr);
  483. dataPtr = rttiReadElem(mAnimType, dataPtr);
  484. dataPtr = rttiReadElem(dirtyFlags, dataPtr);
  485. SPtr<Mesh>* mesh = (SPtr<Mesh>*)dataPtr;
  486. mMesh = *mesh;
  487. mesh->~SPtr<Mesh>();
  488. dataPtr += sizeof(SPtr<Mesh>);
  489. for (UINT32 i = 0; i < numMaterials; i++)
  490. {
  491. SPtr<Material>* material = (SPtr<Material>*)dataPtr;
  492. mMaterials.push_back(*material);
  493. material->~SPtr<Material>();
  494. dataPtr += sizeof(SPtr<Material>);
  495. }
  496. if (dirtyFlags == (UINT32)RenderableDirtyFlag::Transform)
  497. {
  498. if (mIsActive)
  499. gRenderer()->notifyRenderableUpdated(this);
  500. }
  501. else
  502. {
  503. createAnimationBuffers();
  504. // Create special vertex declaration if using morph shapes
  505. if (mAnimType == RenderableAnimType::Morph || mAnimType == RenderableAnimType::SkinnedMorph)
  506. {
  507. SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
  508. *vertexDesc = * mMesh->getVertexDesc();
  509. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION, 1, 1);
  510. vertexDesc->addVertElem(VET_UBYTE4_NORM, VES_NORMAL, 1, 1);
  511. mMorphVertexDeclaration = VertexDeclaration::create(vertexDesc);
  512. }
  513. else
  514. mMorphVertexDeclaration = nullptr;
  515. if (oldIsActive != mIsActive)
  516. {
  517. if (mIsActive)
  518. gRenderer()->notifyRenderableAdded(this);
  519. else
  520. gRenderer()->notifyRenderableRemoved(this);
  521. }
  522. else
  523. {
  524. gRenderer()->notifyRenderableRemoved(this);
  525. gRenderer()->notifyRenderableAdded(this);
  526. }
  527. }
  528. }
  529. }
  530. }