BsRenderable.cpp 16 KB

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