00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef NVBLASTACTOR_H
00030 #define NVBLASTACTOR_H
00031
00032
00033 #include "NvBlastAsset.h"
00034 #include "NvBlastDLink.h"
00035 #include "NvBlastIteratorBase.h"
00036 #include "NvBlastSupportGraph.h"
00037 #include "NvBlastFamilyGraph.h"
00038 #include "NvBlastPreprocessorInternal.h"
00039
00040 #include <cstring>
00041
00042
00043 namespace Nv
00044 {
00045 namespace Blast
00046 {
00047
00048
00049 class FamilyGraph;
00050 struct FamilyHeader;
00051
00058 class Actor : public NvBlastActor
00059 {
00060 friend struct FamilyHeader;
00061
00062 friend void updateVisibleChunksFromSupportChunk<>(Actor*, IndexDLink<uint32_t>*, uint32_t*, uint32_t, uint32_t, const NvBlastChunk*, uint32_t);
00063
00064 public:
00065 Actor() : m_familyOffset(0), m_firstVisibleChunkIndex(UINT32_MAX), m_visibleChunkCount(0), m_firstGraphNodeIndex(UINT32_MAX), m_graphNodeCount(0), m_leafChunkCount(0) {}
00066
00068
00074 FamilyHeader* getFamilyHeader() const;
00075
00081 const Asset* getAsset() const;
00082
00090 bool isActive() const;
00091
00097 bool isSubSupportChunk() const;
00098
00105 bool isSingleSupportChunk() const;
00106
00112 uint32_t getIndex() const;
00113
00120 uint32_t getVisibleChunkCount() const;
00121
00127 uint32_t getFirstVisibleChunkIndex() const;
00128
00135 uint32_t getGraphNodeCount() const;
00136
00142 uint32_t getLeafChunkCount() const;
00143
00149 uint32_t getFirstGraphNodeIndex() const;
00150
00156 uint32_t getFirstSubsupportChunkIndex() const;
00157
00163 const SupportGraph* getGraph() const;
00164
00171 FamilyGraph* getFamilyGraph() const;
00172
00178 NvBlastChunk* getChunks() const;
00179
00185 NvBlastBond* getBonds() const;
00186
00194 float* getLowerSupportChunkHealths() const;
00195
00201 float* getSubsupportChunkHealths() const;
00202
00208 float* getBondHealths() const;
00209
00215 const uint32_t* getGraphNodeIndexLinks() const;
00216
00217
00219
00233 class VisibleChunkIt : public DListIt<uint32_t>
00234 {
00235 public:
00237 VisibleChunkIt(const Actor& actor);
00238 };
00239
00253 class GraphNodeIt : public LListIt<uint32_t>
00254 {
00255 public:
00257 GraphNodeIt(const Actor& actor);
00258 };
00259
00260
00262
00275 static Actor* create(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn);
00276
00285 static size_t createRequiredScratch(const NvBlastFamily* family);
00286
00298 static Actor* deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog logFn);
00299
00309 uint32_t serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) const;
00310
00318 uint32_t serializationRequiredStorage(NvBlastLog logFn) const;
00319
00326 bool release();
00327
00328
00330
00334 void generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBlastDamageProgram& program, const void* programParams, NvBlastLog logFn, NvBlastTimers* timers) const;
00335
00339 uint32_t damageBond(uint32_t nodeIndex0, uint32_t nodeIndex1, float healthDamage);
00340
00344 void damageBond(uint32_t nodeIndex0, uint32_t nodeIndex1, uint32_t bondIndex, float healthDamage);
00345
00349 uint32_t damageBond(const NvBlastBondFractureData& cmd);
00350
00354 void applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands, NvBlastLog logFn, NvBlastTimers* timers);
00355
00361 size_t splitRequiredScratch() const;
00362
00366 uint32_t split(NvBlastActorSplitEvent* result, uint32_t newActorsMaxCount, void* scratch, NvBlastLog logFn, NvBlastTimers* timers);
00367
00377 uint32_t findIslands(void* scratch);
00378
00395 uint32_t partition(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn);
00396
00400 void updateVisibleChunksFromGraphNodes();
00401
00416 uint32_t partitionSingleLowerSupportChunk(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn);
00417
00432 uint32_t partitionMultipleGraphNodes(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn);
00433
00437 bool isBoundToWorld() const;
00438
00442 bool isSplitRequired() const;
00443
00444 private:
00445
00447
00455 uint32_t m_familyOffset;
00456
00461 uint32_t m_firstVisibleChunkIndex;
00462
00466 uint32_t m_visibleChunkCount;
00467
00472 uint32_t m_firstGraphNodeIndex;
00473
00477 uint32_t m_graphNodeCount;
00478
00482 uint32_t m_leafChunkCount;
00483 };
00484
00485 }
00486 }
00487
00488
00489 #include "NvBlastFamily.h"
00490
00491
00492 namespace Nv
00493 {
00494 namespace Blast
00495 {
00496
00498
00499 NV_INLINE FamilyHeader* Actor::getFamilyHeader() const
00500 {
00501 NVBLAST_ASSERT(isActive());
00502 return (FamilyHeader*)((uintptr_t)this - (uintptr_t)m_familyOffset);
00503 }
00504
00505
00506 NV_INLINE const Asset* Actor::getAsset() const
00507 {
00508 return getFamilyHeader()->m_asset;
00509 }
00510
00511
00512 NV_INLINE bool Actor::isActive() const
00513 {
00514 return m_familyOffset != 0;
00515 }
00516
00517
00518 NV_INLINE bool Actor::isSubSupportChunk() const
00519 {
00520 return m_graphNodeCount == 0;
00521 }
00522
00523
00524 NV_INLINE bool Actor::isSingleSupportChunk() const
00525 {
00526 return m_graphNodeCount == 1;
00527 }
00528
00529
00530 NV_INLINE uint32_t Actor::getIndex() const
00531 {
00532 NVBLAST_ASSERT(isActive());
00533 const FamilyHeader* header = getFamilyHeader();
00534 NVBLAST_ASSERT(header != nullptr);
00535 const size_t index = this - header->getActors();
00536 NVBLAST_ASSERT(index <= UINT32_MAX);
00537 return (uint32_t)index;
00538 }
00539
00540
00541 NV_INLINE uint32_t Actor::getVisibleChunkCount() const
00542 {
00543 return m_visibleChunkCount;
00544 }
00545
00546
00547 NV_INLINE uint32_t Actor::getFirstVisibleChunkIndex() const
00548 {
00549 return m_firstVisibleChunkIndex;
00550 }
00551
00552
00553 NV_INLINE uint32_t Actor::getGraphNodeCount() const
00554 {
00555 return m_graphNodeCount;
00556 }
00557
00558
00559 NV_INLINE uint32_t Actor::getLeafChunkCount() const
00560 {
00561 return m_leafChunkCount;
00562 }
00563
00564
00565 NV_INLINE uint32_t Actor::getFirstGraphNodeIndex() const
00566 {
00567 return m_firstGraphNodeIndex;
00568 }
00569
00570 NV_INLINE uint32_t Actor::getFirstSubsupportChunkIndex() const
00571 {
00572 return getAsset()->m_firstSubsupportChunkIndex;
00573 }
00574
00575 NV_INLINE const SupportGraph* Actor::getGraph() const
00576 {
00577 return &getAsset()->m_graph;
00578 }
00579
00580 NV_INLINE FamilyGraph* Actor::getFamilyGraph() const
00581 {
00582 return getFamilyHeader()->getFamilyGraph();
00583 }
00584
00585 NV_INLINE NvBlastChunk* Actor::getChunks() const
00586 {
00587 return getAsset()->getChunks();
00588 }
00589
00590 NV_INLINE NvBlastBond* Actor::getBonds() const
00591 {
00592 return getAsset()->getBonds();
00593 }
00594
00595 NV_INLINE float* Actor::getLowerSupportChunkHealths() const
00596 {
00597 return getFamilyHeader()->getLowerSupportChunkHealths();
00598 }
00599
00600 NV_INLINE float* Actor::getSubsupportChunkHealths() const
00601 {
00602 return getFamilyHeader()->getSubsupportChunkHealths();
00603 }
00604
00605 NV_INLINE float* Actor::getBondHealths() const
00606 {
00607 return getFamilyHeader()->getBondHealths();
00608 }
00609
00610 NV_INLINE const uint32_t* Actor::getGraphNodeIndexLinks() const
00611 {
00612 return getFamilyHeader()->getGraphNodeIndexLinks();
00613 }
00614
00615
00616 NV_INLINE bool Actor::release()
00617 {
00618
00619 if (!isActive())
00620 {
00621 return false;
00622 }
00623
00624 FamilyHeader* header = getFamilyHeader();
00625
00626
00627 uint32_t* graphNodeIndexLinks = getFamilyHeader()->getGraphNodeIndexLinks();
00628 while (!isInvalidIndex(m_firstGraphNodeIndex))
00629 {
00630 const uint32_t graphNodeIndex = m_firstGraphNodeIndex;
00631 m_firstGraphNodeIndex = graphNodeIndexLinks[m_firstGraphNodeIndex];
00632 graphNodeIndexLinks[graphNodeIndex] = invalidIndex<uint32_t>();
00633 --m_graphNodeCount;
00634 }
00635 NVBLAST_ASSERT(m_graphNodeCount == 0);
00636
00637 const Asset* asset = getAsset();
00638
00639
00640 IndexDLink<uint32_t>* visibleChunkIndexLinks = header->getVisibleChunkIndexLinks();
00641 uint32_t* chunkActorIndices = header->getChunkActorIndices();
00642 while (!isInvalidIndex(m_firstVisibleChunkIndex))
00643 {
00644
00645 for (Asset::DepthFirstIt i(*asset, m_firstVisibleChunkIndex, true); (bool)i; ++i)
00646 {
00647 chunkActorIndices[(uint32_t)i] = invalidIndex<uint32_t>();
00648 }
00649 IndexDList<uint32_t>().removeListHead(m_firstVisibleChunkIndex, visibleChunkIndexLinks);
00650 --m_visibleChunkCount;
00651 }
00652 NVBLAST_ASSERT(m_visibleChunkCount == 0);
00653
00654
00655 m_leafChunkCount = 0;
00656
00657
00658 header->returnActor(*this);
00659
00660 return true;
00661 }
00662
00663
00664 NV_INLINE uint32_t Actor::partition(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn)
00665 {
00666 NVBLASTLL_CHECK(newActorsSize == 0 || newActors != nullptr, logFn, "Nv::Blast::Actor::partition: NULL newActors pointer array input with non-zero newActorCount.", return 0);
00667
00668
00669 return m_graphNodeCount <= 1 ?
00670 partitionSingleLowerSupportChunk(newActors, newActorsSize, logFn) :
00671 partitionMultipleGraphNodes(newActors, newActorsSize, logFn);
00672 }
00673
00674
00675 NV_INLINE bool Actor::isBoundToWorld() const
00676 {
00677 const SupportGraph& graph = *getGraph();
00678
00679 if (graph.m_nodeCount == 0)
00680 {
00681 return false;
00682 }
00683
00684 const uint32_t lastGraphChunkIndex = graph.getChunkIndices()[graph.m_nodeCount - 1];
00685
00686 if (!isInvalidIndex(lastGraphChunkIndex))
00687 {
00688 return false;
00689 }
00690
00691 return getFamilyGraph()->getIslandIds()[graph.m_nodeCount - 1] == getIndex();
00692 }
00693
00694
00695 NV_INLINE bool Actor::isSplitRequired() const
00696 {
00697 NVBLAST_ASSERT(isActive());
00698
00699 if (getGraphNodeCount() <= 1)
00700 {
00701 uint32_t chunkHealthIndex = isSingleSupportChunk() ? getIndex() : getFirstVisibleChunkIndex() - getFirstSubsupportChunkIndex() + getGraph()->m_nodeCount;
00702 float* chunkHealths = getLowerSupportChunkHealths();
00703 if (chunkHealths[chunkHealthIndex] <= 0.0f)
00704 {
00705 const uint32_t chunkIndex = m_graphNodeCount == 0 ? m_firstVisibleChunkIndex : getGraph()->getChunkIndices()[m_firstGraphNodeIndex];
00706 if (!isInvalidIndex(chunkIndex))
00707 {
00708 const NvBlastChunk& chunk = getChunks()[chunkIndex];
00709 uint32_t childCount = chunk.childIndexStop - chunk.firstChildIndex;
00710 return childCount > 0;
00711 }
00712 }
00713 }
00714 else
00715 {
00716 uint32_t* firstDirtyNodeIndices = getFamilyGraph()->getFirstDirtyNodeIndices();
00717 if (!isInvalidIndex(firstDirtyNodeIndices[getIndex()]))
00718 {
00719 return true;
00720 }
00721
00722 }
00723 return false;
00724 }
00725
00726
00728
00729 NV_INLINE Actor::VisibleChunkIt::VisibleChunkIt(const Actor& actor) : DListIt<uint32_t>(actor.m_firstVisibleChunkIndex, actor.getFamilyHeader()->getVisibleChunkIndexLinks())
00730 {
00731 }
00732
00733
00735
00736 NV_INLINE Actor::GraphNodeIt::GraphNodeIt(const Actor& actor) : LListIt<uint32_t>(actor.m_firstGraphNodeIndex, actor.getFamilyHeader()->getGraphNodeIndexLinks())
00737 {
00738 }
00739
00740
00742
00743 #if NVBLASTLL_CHECK_PARAMS
00744
00747 static inline bool isValid(const NvBlastFractureBuffers* buffers)
00748 {
00749 if (buffers->chunkFractureCount != 0 && buffers->chunkFractures == nullptr)
00750 return false;
00751
00752 if (buffers->bondFractureCount != 0 && buffers->bondFractures == nullptr)
00753 return false;
00754
00755 return true;
00756 }
00757 #endif
00758
00759
00760 }
00761 }
00762
00763
00764 #endif // ifndef NVBLASTACTOR_H