BsRenderable.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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::setAnimation(const SPtr<Animation>& animation)
  116. {
  117. mAnimation = animation;
  118. refreshAnimation();
  119. _markCoreDirty();
  120. }
  121. Bounds Renderable::getBounds() const
  122. {
  123. if(mUseOverrideBounds)
  124. {
  125. Sphere sphere(mOverrideBounds.getCenter(), mOverrideBounds.getRadius());
  126. Bounds bounds(mOverrideBounds, sphere);
  127. bounds.transformAffine(mTfrmMatrix);
  128. return bounds;
  129. }
  130. HMesh mesh = getMesh();
  131. if (!mesh.isLoaded())
  132. {
  133. const Transform& tfrm = getTransform();
  134. AABox box(tfrm.getPosition(), tfrm.getPosition());
  135. Sphere sphere(tfrm.getPosition(), 0.0f);
  136. return Bounds(box, sphere);
  137. }
  138. else
  139. {
  140. Bounds bounds = mesh->getProperties().getBounds();
  141. bounds.transformAffine(mTfrmMatrix);
  142. return bounds;
  143. }
  144. }
  145. SPtr<ct::Renderable> Renderable::getCore() const
  146. {
  147. return std::static_pointer_cast<ct::Renderable>(mCoreSpecific);
  148. }
  149. SPtr<ct::CoreObject> Renderable::createCore() const
  150. {
  151. ct::Renderable* handler = new (bs_alloc<ct::Renderable>()) ct::Renderable();
  152. SPtr<ct::Renderable> handlerPtr = bs_shared_ptr<ct::Renderable>(handler);
  153. handlerPtr->_setThisPtr(handlerPtr);
  154. return handlerPtr;
  155. }
  156. void Renderable::onMeshChanged()
  157. {
  158. refreshAnimation();
  159. }
  160. void Renderable::refreshAnimation()
  161. {
  162. if (mAnimation == nullptr)
  163. {
  164. mAnimType = RenderableAnimType::None;
  165. return;
  166. }
  167. if (mMesh.isLoaded(false))
  168. {
  169. SPtr<Skeleton> skeleton = mMesh->getSkeleton();
  170. SPtr<MorphShapes> morphShapes = mMesh->getMorphShapes();
  171. if (skeleton != nullptr && morphShapes != nullptr)
  172. mAnimType = RenderableAnimType::SkinnedMorph;
  173. else if (skeleton != nullptr)
  174. mAnimType = RenderableAnimType::Skinned;
  175. else if (morphShapes != nullptr)
  176. mAnimType = RenderableAnimType::Morph;
  177. else
  178. mAnimType = RenderableAnimType::None;
  179. mAnimation->setSkeleton(mMesh->getSkeleton());
  180. mAnimation->setMorphShapes(mMesh->getMorphShapes());
  181. }
  182. else
  183. {
  184. mAnimType = RenderableAnimType::None;
  185. mAnimation->setSkeleton(nullptr);
  186. mAnimation->setMorphShapes(nullptr);
  187. }
  188. }
  189. void Renderable::_updateState(const SceneObject& so, bool force)
  190. {
  191. UINT32 curHash = so.getTransformHash();
  192. if (curHash != mHash || force)
  193. {
  194. // If skinned animation, don't include own transform since that will be handled by root bone animation
  195. bool ignoreOwnTransform;
  196. if (mAnimType == RenderableAnimType::Skinned || mAnimType == RenderableAnimType::SkinnedMorph)
  197. ignoreOwnTransform = mAnimation->_getAnimatesRoot();
  198. else
  199. ignoreOwnTransform = false;
  200. if (ignoreOwnTransform)
  201. {
  202. // Note: Technically we're checking child's hash but using parent's transform. Ideally we check the parent's
  203. // hash to reduce the number of required updates.
  204. HSceneObject parentSO = so.getParent();
  205. if (parentSO != nullptr)
  206. setTransform(parentSO->getTransform());
  207. else
  208. setTransform(Transform());
  209. }
  210. else
  211. setTransform(so.getTransform());
  212. mHash = curHash;
  213. }
  214. // Hash now matches so transform won't be applied twice, so we can just call base class version
  215. SceneActor::_updateState(so, force);
  216. }
  217. void Renderable::_markCoreDirty(ActorDirtyFlag flag)
  218. {
  219. markCoreDirty((UINT32)flag);
  220. }
  221. void Renderable::_markDependenciesDirty()
  222. {
  223. markDependenciesDirty();
  224. }
  225. void Renderable::_markResourcesDirty()
  226. {
  227. markListenerResourcesDirty();
  228. }
  229. CoreSyncData Renderable::syncToCore(FrameAlloc* allocator)
  230. {
  231. UINT32 numMaterials = (UINT32)mMaterials.size();
  232. UINT64 animationId;
  233. if (mAnimation != nullptr)
  234. animationId = mAnimation->_getId();
  235. else
  236. animationId = (UINT64)-1;
  237. UINT32 size =
  238. getActorSyncDataSize() +
  239. rttiGetElemSize(mLayer) +
  240. rttiGetElemSize(mOverrideBounds) +
  241. rttiGetElemSize(mUseOverrideBounds) +
  242. rttiGetElemSize(numMaterials) +
  243. rttiGetElemSize(mTfrmMatrix) +
  244. rttiGetElemSize(mTfrmMatrixNoScale) +
  245. rttiGetElemSize(animationId) +
  246. rttiGetElemSize(mAnimType) +
  247. rttiGetElemSize(getCoreDirtyFlags()) +
  248. sizeof(SPtr<ct::Mesh>) +
  249. numMaterials * sizeof(SPtr<ct::Material>);
  250. UINT8* data = allocator->alloc(size);
  251. char* dataPtr = (char*)data;
  252. dataPtr = syncActorTo(dataPtr);
  253. dataPtr = rttiWriteElem(mLayer, dataPtr);
  254. dataPtr = rttiWriteElem(mOverrideBounds, dataPtr);
  255. dataPtr = rttiWriteElem(mUseOverrideBounds, dataPtr);
  256. dataPtr = rttiWriteElem(numMaterials, dataPtr);
  257. dataPtr = rttiWriteElem(mTfrmMatrix, dataPtr);
  258. dataPtr = rttiWriteElem(mTfrmMatrixNoScale, dataPtr);
  259. dataPtr = rttiWriteElem(animationId, dataPtr);
  260. dataPtr = rttiWriteElem(mAnimType, dataPtr);
  261. dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
  262. SPtr<ct::Mesh>* mesh = new (dataPtr) SPtr<ct::Mesh>();
  263. if (mMesh.isLoaded())
  264. *mesh = mMesh->getCore();
  265. dataPtr += sizeof(SPtr<ct::Mesh>);
  266. for (UINT32 i = 0; i < numMaterials; i++)
  267. {
  268. SPtr<ct::Material>* material = new (dataPtr)SPtr<ct::Material>();
  269. if (mMaterials[i].isLoaded())
  270. *material = mMaterials[i]->getCore();
  271. dataPtr += sizeof(SPtr<ct::Material>);
  272. }
  273. return CoreSyncData(data, size);
  274. }
  275. void Renderable::getCoreDependencies(Vector<CoreObject*>& dependencies)
  276. {
  277. if (mMesh.isLoaded())
  278. dependencies.push_back(mMesh.get());
  279. for (auto& material : mMaterials)
  280. {
  281. if (material.isLoaded())
  282. dependencies.push_back(material.get());
  283. }
  284. }
  285. void Renderable::getListenerResources(Vector<HResource>& resources)
  286. {
  287. if (mMesh != nullptr)
  288. resources.push_back(mMesh);
  289. for (auto& material : mMaterials)
  290. {
  291. if (material != nullptr)
  292. resources.push_back(material);
  293. }
  294. }
  295. void Renderable::notifyResourceLoaded(const HResource& resource)
  296. {
  297. if (resource == mMesh)
  298. onMeshChanged();
  299. markDependenciesDirty();
  300. markCoreDirty();
  301. }
  302. void Renderable::notifyResourceChanged(const HResource& resource)
  303. {
  304. if(resource == mMesh)
  305. onMeshChanged();
  306. markDependenciesDirty();
  307. markCoreDirty();
  308. }
  309. SPtr<Renderable> Renderable::create()
  310. {
  311. SPtr<Renderable> handlerPtr = createEmpty();
  312. handlerPtr->initialize();
  313. return handlerPtr;
  314. }
  315. SPtr<Renderable> Renderable::createEmpty()
  316. {
  317. Renderable* handler = new (bs_alloc<Renderable>()) Renderable();
  318. SPtr<Renderable> handlerPtr = bs_core_ptr<Renderable>(handler);
  319. handlerPtr->_setThisPtr(handlerPtr);
  320. return handlerPtr;
  321. }
  322. RTTITypeBase* Renderable::getRTTIStatic()
  323. {
  324. return RenderableRTTI::instance();
  325. }
  326. RTTITypeBase* Renderable::getRTTI() const
  327. {
  328. return Renderable::getRTTIStatic();
  329. }
  330. namespace ct
  331. {
  332. Renderable::Renderable()
  333. :mRendererId(0), mAnimationId((UINT64)-1), mMorphShapeVersion(0)
  334. {
  335. }
  336. Renderable::~Renderable()
  337. {
  338. if (mActive)
  339. gRenderer()->notifyRenderableRemoved(this);
  340. }
  341. void Renderable::initialize()
  342. {
  343. gRenderer()->notifyRenderableAdded(this);
  344. CoreObject::initialize();
  345. }
  346. Bounds Renderable::getBounds() const
  347. {
  348. if (mUseOverrideBounds)
  349. {
  350. Sphere sphere(mOverrideBounds.getCenter(), mOverrideBounds.getRadius());
  351. Bounds bounds(mOverrideBounds, sphere);
  352. bounds.transformAffine(mTfrmMatrix);
  353. return bounds;
  354. }
  355. SPtr<Mesh> mesh = getMesh();
  356. if (mesh == nullptr)
  357. {
  358. const Transform& tfrm = getTransform();
  359. AABox box(tfrm.getPosition(), tfrm.getPosition());
  360. Sphere sphere(tfrm.getPosition(), 0.0f);
  361. return Bounds(box, sphere);
  362. }
  363. else
  364. {
  365. Bounds bounds = mesh->getProperties().getBounds();
  366. bounds.transformAffine(mTfrmMatrix);
  367. return bounds;
  368. }
  369. }
  370. void Renderable::createAnimationBuffers()
  371. {
  372. if (mAnimType == RenderableAnimType::Skinned || mAnimType == RenderableAnimType::SkinnedMorph)
  373. {
  374. SPtr<Skeleton> skeleton = mMesh->getSkeleton();
  375. UINT32 numBones = skeleton != nullptr ? skeleton->getNumBones() : 0;
  376. if (numBones > 0)
  377. {
  378. GPU_BUFFER_DESC desc;
  379. desc.elementCount = numBones * 3;
  380. desc.elementSize = 0;
  381. desc.type = GBT_STANDARD;
  382. desc.format = BF_32X4F;
  383. desc.usage = GBU_DYNAMIC;
  384. SPtr<GpuBuffer> buffer = GpuBuffer::create(desc);
  385. UINT8* dest = (UINT8*)buffer->lock(0, numBones * 3 * sizeof(Vector4), GBL_WRITE_ONLY_DISCARD);
  386. // Initialize bone transforms to identity, so the object renders properly even if no animation is animating it
  387. for (UINT32 i = 0; i < numBones; i++)
  388. {
  389. memcpy(dest, &Matrix4::IDENTITY, 12 * sizeof(float)); // Assuming row-major format
  390. dest += 12 * sizeof(float);
  391. }
  392. buffer->unlock();
  393. mBoneMatrixBuffer = buffer;
  394. }
  395. else
  396. mBoneMatrixBuffer = nullptr;
  397. }
  398. else
  399. mBoneMatrixBuffer = nullptr;
  400. if (mAnimType == RenderableAnimType::Morph || mAnimType == RenderableAnimType::SkinnedMorph)
  401. {
  402. SPtr<MorphShapes> morphShapes = mMesh->getMorphShapes();
  403. UINT32 vertexSize = sizeof(Vector3) + sizeof(UINT32);
  404. UINT32 numVertices = morphShapes->getNumVertices();
  405. VERTEX_BUFFER_DESC desc;
  406. desc.vertexSize = vertexSize;
  407. desc.numVerts = numVertices;
  408. desc.usage = GBU_DYNAMIC;
  409. SPtr<VertexBuffer> vertexBuffer = VertexBuffer::create(desc);
  410. UINT32 totalSize = vertexSize * numVertices;
  411. UINT8* dest = (UINT8*)vertexBuffer->lock(0, totalSize, GBL_WRITE_ONLY_DISCARD);
  412. memset(dest, 0, totalSize);
  413. vertexBuffer->unlock();
  414. mMorphShapeBuffer = vertexBuffer;
  415. }
  416. else
  417. mMorphShapeBuffer = nullptr;
  418. mMorphShapeVersion = 0;
  419. }
  420. void Renderable::updateAnimationBuffers(const RendererAnimationData& animData)
  421. {
  422. if (mAnimationId == (UINT64)-1)
  423. return;
  424. const RendererAnimationData::AnimInfo* animInfo = nullptr;
  425. auto iterFind = animData.infos.find(mAnimationId);
  426. if (iterFind != animData.infos.end())
  427. animInfo = &iterFind->second;
  428. if (animInfo == nullptr)
  429. return;
  430. if (mAnimType == RenderableAnimType::Skinned || mAnimType == RenderableAnimType::SkinnedMorph)
  431. {
  432. const RendererAnimationData::PoseInfo& poseInfo = animInfo->poseInfo;
  433. // Note: If multiple elements are using the same animation (not possible atm), this buffer should be shared by
  434. // all such elements
  435. UINT8* dest = (UINT8*)mBoneMatrixBuffer->lock(0, poseInfo.numBones * 3 * sizeof(Vector4), GBL_WRITE_ONLY_DISCARD);
  436. for (UINT32 j = 0; j < poseInfo.numBones; j++)
  437. {
  438. const Matrix4& transform = animData.transforms[poseInfo.startIdx + j];
  439. memcpy(dest, &transform, 12 * sizeof(float)); // Assuming row-major format
  440. dest += 12 * sizeof(float);
  441. }
  442. mBoneMatrixBuffer->unlock();
  443. }
  444. if (mAnimType == RenderableAnimType::Morph || mAnimType == RenderableAnimType::SkinnedMorph)
  445. {
  446. if (mMorphShapeVersion != animInfo->morphShapeInfo.version)
  447. {
  448. SPtr<MeshData> meshData = animInfo->morphShapeInfo.meshData;
  449. UINT32 bufferSize = meshData->getSize();
  450. UINT8* data = meshData->getData();
  451. mMorphShapeBuffer->writeData(0, bufferSize, data, BWT_DISCARD);
  452. mMorphShapeVersion = animInfo->morphShapeInfo.version;
  453. }
  454. }
  455. }
  456. void Renderable::syncToCore(const CoreSyncData& data)
  457. {
  458. char* dataPtr = (char*)data.getBuffer();
  459. mMaterials.clear();
  460. UINT32 numMaterials = 0;
  461. UINT32 dirtyFlags = 0;
  462. bool oldIsActive = mActive;
  463. dataPtr = syncActorFrom(dataPtr);
  464. dataPtr = rttiReadElem(mLayer, dataPtr);
  465. dataPtr = rttiReadElem(mOverrideBounds, dataPtr);
  466. dataPtr = rttiReadElem(mUseOverrideBounds, dataPtr);
  467. dataPtr = rttiReadElem(numMaterials, dataPtr);
  468. dataPtr = rttiReadElem(mTfrmMatrix, dataPtr);
  469. dataPtr = rttiReadElem(mTfrmMatrixNoScale, dataPtr);
  470. dataPtr = rttiReadElem(mAnimationId, dataPtr);
  471. dataPtr = rttiReadElem(mAnimType, dataPtr);
  472. dataPtr = rttiReadElem(dirtyFlags, dataPtr);
  473. SPtr<Mesh>* mesh = (SPtr<Mesh>*)dataPtr;
  474. mMesh = *mesh;
  475. mesh->~SPtr<Mesh>();
  476. dataPtr += sizeof(SPtr<Mesh>);
  477. for (UINT32 i = 0; i < numMaterials; i++)
  478. {
  479. SPtr<Material>* material = (SPtr<Material>*)dataPtr;
  480. mMaterials.push_back(*material);
  481. material->~SPtr<Material>();
  482. dataPtr += sizeof(SPtr<Material>);
  483. }
  484. if((dirtyFlags & ((UINT32)ActorDirtyFlag::Everything | (UINT32)ActorDirtyFlag::Active)) != 0)
  485. {
  486. createAnimationBuffers();
  487. // Create special vertex declaration if using morph shapes
  488. if (mAnimType == RenderableAnimType::Morph || mAnimType == RenderableAnimType::SkinnedMorph)
  489. {
  490. SPtr<VertexDataDesc> vertexDesc = VertexDataDesc::create();
  491. *vertexDesc = * mMesh->getVertexDesc();
  492. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION, 1, 1);
  493. vertexDesc->addVertElem(VET_UBYTE4_NORM, VES_NORMAL, 1, 1);
  494. mMorphVertexDeclaration = VertexDeclaration::create(vertexDesc);
  495. }
  496. else
  497. mMorphVertexDeclaration = nullptr;
  498. if (oldIsActive != mActive)
  499. {
  500. if (mActive)
  501. gRenderer()->notifyRenderableAdded(this);
  502. else
  503. gRenderer()->notifyRenderableRemoved(this);
  504. }
  505. else
  506. {
  507. gRenderer()->notifyRenderableRemoved(this);
  508. gRenderer()->notifyRenderableAdded(this);
  509. }
  510. }
  511. else if((dirtyFlags & (UINT32)ActorDirtyFlag::Mobility) != 0)
  512. {
  513. gRenderer()->notifyRenderableRemoved(this);
  514. gRenderer()->notifyRenderableAdded(this);
  515. }
  516. else if ((dirtyFlags & (UINT32)ActorDirtyFlag::Transform) != 0)
  517. {
  518. if (mActive)
  519. gRenderer()->notifyRenderableUpdated(this);
  520. }
  521. }
  522. }
  523. }