aboutsummaryrefslogtreecommitdiff
path: root/sdk/lowlevel/source/NvBlastActor.h
blob: a12e70fb57113d56bc19b905dea294fab2a6d320 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
// This code contains NVIDIA Confidential Information and is disclosed to you
// under a form of NVIDIA software license agreement provided separately to you.
//
// Notice
// NVIDIA Corporation and its licensors retain all intellectual property and
// proprietary rights in and to this software and related documentation and
// any modifications thereto. Any use, reproduction, disclosure, or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA Corporation is strictly prohibited.
//
// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
//
// Information and code furnished is believed to be accurate and reliable.
// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
// information or for any infringement of patents or other rights of third parties that may
// result from its use. No license is granted by implication or otherwise under any patent
// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
// This code supersedes and replaces all information previously supplied.
// NVIDIA Corporation products are not authorized for use as critical
// components in life support devices or systems without express written approval of
// NVIDIA Corporation.
//
// Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved.


#ifndef NVBLASTACTOR_H
#define NVBLASTACTOR_H


#include "NvBlastAsset.h"
#include "NvBlastDLink.h"
#include "NvBlastIteratorBase.h"
#include "NvBlastSupportGraph.h"
#include "NvBlastFamilyGraph.h"
#include "NvBlastPreprocessorInternal.h"

#include <cstring>


namespace Nv
{
namespace Blast
{

// Forward declarations
class FamilyGraph;
struct FamilyHeader;

/**
Internal implementation of solver actor.

These objects are stored within the family in a single array.  A pointer to a Actor class will be given
to the user through the NvBlastActor opaque type.
*/
class Actor : public NvBlastActor
{
	friend struct FamilyHeader;

	friend void updateVisibleChunksFromSupportChunk<>(Actor*, IndexDLink<uint32_t>*, uint32_t*, uint32_t, uint32_t, const NvBlastChunk*, uint32_t);

public:
	Actor() : m_familyOffset(0), m_firstVisibleChunkIndex(UINT32_MAX), m_visibleChunkCount(0), m_firstGraphNodeIndex(UINT32_MAX), m_graphNodeCount(0), m_leafChunkCount(0) {}

	//////// Accessors ////////

	/**
	Find the family (see FamilyHeader) that this actor belongs to.

	\return	a pointer to the FamilyHeader for this actor.
	*/
	FamilyHeader*		getFamilyHeader() const;

	/**
	Utility to get the asset this actor is associated with, through its family.

	\return	the asset associated with this actor.
	*/
	const Asset*		getAsset() const;

	/**
	Since this object is not deleted (unless the family is deleted), we use m_familyOffset
	to determine if the actor is valid, or "active."  When no actors in an instance return isActive(),
	it should be safe to delete the family.

	\return true iff this actor is valid for use (active).
	*/
	bool				isActive() const;

	/**
	Whether or not this actor represents a subsupport chunk.  If the actor contains a subsupport chunk, then it can have only that chunk.

	\return true iff this actor contains a chunk which is a descendant of a support chunk.
	*/
	bool				isSubSupportChunk() const;

	/**
	Whether or not this actor represents a single support chunk.  If the actor contains a single support chunk, it can have no other
	chunks associated with it.

	\return true iff this actor contains exactly one support chunk.
	*/
	bool				isSingleSupportChunk() const;

	/**
	Utility to calculate actor index.

	\return the index of this actor in the FamilyHeader's getActors() array.
	*/
	uint32_t			getIndex() const;

	/**
	The number of visible chunks.  This is calculated from updateVisibleChunksFromGraphNodes().
	See also getFirstVisibleChunkIndex.

	\return the number of chunks in the actor's visible chunk index list.
	*/
	uint32_t			getVisibleChunkCount() const;

	/**
	Access to visible chunk linked list for this actor.  The index returned is that of a link in the FamilyHeader's getVisibleChunkIndexLinks().

	\return the index of the head of the visible chunk linked list.
	*/
	uint32_t			getFirstVisibleChunkIndex() const;

	/**
	The number of graph nodes, corresponding to support chunks, for this actor.
	See also getFirstGraphNodeIndex.

	\return the number of graph nodes in the actor's graph node index list.
	*/
	uint32_t			getGraphNodeCount() const;

	/**
	The number of leaf chunks for this actor.

	\return number of leaf chunks for this actor.
	*/
	uint32_t			getLeafChunkCount() const;

	/**
	Access to graph node linked list for this actor.  The index returned is that of a link in the FamilyHeader's getGraphNodeIndexLinks().

	\return the index of the head of the graph node linked list.
	*/
	uint32_t			getFirstGraphNodeIndex() const;

	/**
	Access to the index of the first subsupport chunk.

	\return the index of the first subsupport chunk.
	*/
	uint32_t			getFirstSubsupportChunkIndex() const;

	/**
	Access to the support graph.

	\return the support graph associated with this actor.
	*/
	const SupportGraph*	getGraph() const;

	/**
	Access the instance graph for islands searching.

	Return the dynamic data generated for the support graph.  (See FamilyGraph.)
	This is used to store current connectivity information based upon bond and chunk healths, as well as cached intermediate data for faster incremental updates.
	*/
	FamilyGraph*		getFamilyGraph() const;

	/**
	Access to the chunks, of type NvBlastChunk.

	\return an array of size m_chunkCount.
	*/
	NvBlastChunk*		getChunks() const;

	/**
	Access to the bonds, of type NvBlastBond.

	\return an array of size m_bondCount.
	*/
	NvBlastBond*		getBonds() const;

	/**
	Access to the health for each support chunk and subsupport chunk, of type float.

	Use getAsset()->getContiguousLowerSupportIndex() to map lower-support chunk indices into the range of indices valid for this array.

	\return a float array of chunk healths.
	*/
	float*				getLowerSupportChunkHealths() const;

	/**
	Access to the start of the subsupport chunk health array.

	\return the array of health values associated with all descendants of support chunks.
	*/
	float*				getSubsupportChunkHealths() const;

	/**
	Bond health for the interfaces between two chunks, of type float.  Since the bond is shared by two chunks, the same bond health is used for chunk[i] -> chunk[j] as for chunk[j] -> chunk[i].

	\return the array of healths associated with all bonds in the support graph.
	*/
	float*				getBondHealths() const;

	/**
	Graph node index links, of type uint32_t.  The successor to index[i] is m_graphNodeIndexLinksOffset[i].  A value of invalidIndex<uint32_t>() indicates no successor.

	getGraphNodeIndexLinks returns an array of size m_asset->m_graphNodeCount.
	*/
	const uint32_t*		getGraphNodeIndexLinks() const;


	//////// Iterators ////////

	/**
	Visible chunk iterator.  Usage:

	Given a solver actor a,

	for (Actor::VisibleChunkIt i = a; (bool)i; ++i)
	{
		uint32_t visibleChunkIndex = (uint32_t)i;

		// visibleChunkIndex references the asset index list
	}

	*/
	class VisibleChunkIt : public DListIt<uint32_t>
	{
	public:
		/** Constructed from an actor. */
		VisibleChunkIt(const Actor& actor);
	};

	/**
	Graph node iterator.  Usage:

	Given a solver actor a,

	for (Actor::GraphNodeIt i = a; (bool)i; ++i)
	{
	uint32_t graphNodeIndex = (uint32_t)i;

	// graphNodeIndex references the asset's graph node index list
	}

	*/
	class GraphNodeIt : public LListIt<uint32_t>
	{
	public:
		/** Constructed from an actor. */
		GraphNodeIt(const Actor& actor);
	};


	//////// Operations ////////

	/**
	Create an actor from a descriptor (creates a family).  This actor will represent an unfractured instance of the asset.
	The asset must be in a valid state, for example each chunk hierarchy in it must contain at least one support chunk (a single
	support chunk in a hierarchy corresponds to the root chunk).  This will always be the case for assets created by NvBlastCreateAsset.

	\param[in] family	Family in which to create a new actor.  The family must be valid and have no other actors in it.  (See createFamily.)
	\param[in] desc		Actor initialization data, must be a valid pointer.
	\param[in] scratch	User-supplied scratch memory of size createRequiredScratch(desc) bytes.
	\param[in] logFn	User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return the new actor if the input is valid (by the conditions described above), NULL otherwise.
	*/
	static Actor*		create(NvBlastFamily* family, const NvBlastActorDesc* desc, void* scratch, NvBlastLog logFn);

	/**
	Returns the size of the scratch space (in bytes) required to be passed into the create function, based upon
	the family that will be passed to the create function.

	\param[in] family	The family being instanced.

	\return the number of bytes required.
	*/
	static size_t		createRequiredScratch(const NvBlastFamily* family);

	/**
	Deserialize a single Actor from a buffer.  An actor family must given, into which
	the actor will be inserted if it is compatible.  That is, it must not share any chunks or internal
	IDs with the actors already present in the block.

	\param[in] family	Family in which to deserialize the actor.
	\param[in] buffer	Buffer containing the serialized actor data.
	\param[in] logFn	User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return the deserialized actor if successful, NULL otherwise.
	*/
	static Actor*		deserialize(NvBlastFamily* family, const void* buffer, NvBlastLog logFn);

	/**
	Serialize actor into single-actor buffer.

	\param[out] buffer		User-supplied buffer, must be at least of size given by NvBlastActorGetSerializationSize(actor).
	\param[in] bufferSize	The size of the user-supplied buffer.  The buffer size must be less than 4GB.  If NvBlastActorGetSerializationSize(actor) >= 4GB, this actor cannot be serialized with this method.
	\param[in] logFn		User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return the number of bytes written to the buffer, or 0 if there is an error (such as an under-sized buffer).
	*/
	uint32_t			serialize(void* buffer, uint32_t bufferSize, NvBlastLog logFn) const;

	/**
	Calculate the space required to serialize this actor.

	\param[in] logFn	User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return the required buffer size in bytes.
	*/
	uint32_t			serializationRequiredStorage(NvBlastLog logFn) const;

	/**
	Release this actor's association with a family, if any.  This actor should be considered deleted
	after this function is called.

	\return true if release was successful (actor was active).
	*/
	bool				release();


	//////// Damage and fracturing methods ////////

	/**
	See NvBlastActorGenerateFracture
	*/
	void				generateFracture(NvBlastFractureBuffers* commandBuffers, const NvBlastDamageProgram& program, const void* programParams, NvBlastLog logFn, NvBlastTimers* timers) const;

	/**
	Damage bond between two chunks by health amount (instance graph also will be notified in case bond is broken after).
	*/
	uint32_t			damageBond(uint32_t nodeIndex0, uint32_t nodeIndex1, float healthDamage);

	/**
	TODO: document
	*/
	void				damageBond(uint32_t nodeIndex0, uint32_t nodeIndex1, uint32_t bondIndex, float healthDamage);

	/**
	TODO: document
	*/
	uint32_t			damageBond(const NvBlastBondFractureData& cmd);

	/**
	See NvBlastActorApplyFracture
	*/
	void				applyFracture(NvBlastFractureBuffers* eventBuffers, const NvBlastFractureBuffers* commands, NvBlastLog logFn, NvBlastTimers* timers);

	/**
	The scratch space required to call the findIslands function, or the split function, in bytes.
	
	\return the number of bytes required.
	*/
	size_t				splitRequiredScratch() const;

	/**
	See NvBlastActorSplit
	*/
	uint32_t			split(NvBlastActorSplitEvent* result, uint32_t newActorsMaxCount, void* scratch, NvBlastLog logFn, NvBlastTimers* timers);

	/**
	Perform islands search.  Bonds which are broken when their health values drop to zero (or below) may lead
	to new islands of chunks which need to be split into new actors.  This function labels all nodes in the instance
	graph (see FamilyGraph) with a unique index per island that may be used as actor indices for new islands.

	\param[in] scratch	User-supplied scratch memory of size splitRequiredScratch().

	\return	the number of new islands found.
	*/
	uint32_t			findIslands(void* scratch);

	/**
	Partition this actor into smaller pieces.

	If this actor represents a single support or subsupport chunk, then after this operation
	this actor will released if child chunks are created (see Return value), and its pointer no longer valid for use (unless it appears in the newActors list).

	This function will not split a leaf chunk actor.  In that case, the actor is not destroyed and this function returns 0.

	\param[in] newActors		user-supplied array of actor pointers to hold the actors generated from this partitioning.
								This array must be of size equal to the number of leaf chunks in the asset, to guarantee
								that all actors are reported.  (See AssetDataHeader::m_leafChunkCount.)
	\param[in] newActorsSize	The size of the user-supplied newActors array.
	\param[in] logFn			User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return	the number of new actors created.  If greater than newActorsSize, some actors are not reported in the newActors array.
	*/
	uint32_t			partition(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn);

	/**
	Recalculate the visible chunk list for this actor based upon it graph node list (does not modify subsupport chunk actors)
	*/
	void				updateVisibleChunksFromGraphNodes();

	/**
	Partition this actor into smaller pieces if it is a single lower-support chunk actor.  Use this function on single support or sub-support chunks.

	After this operation, if successful (child chunks created, see Return value), this actor will released, and its pointer no longer valid for use.

	This function will not split a leaf chunk actor.  In that case, the actor is not destroyed and this function returns 0.

	\param[in] newActors		User-supplied array of actor pointers to hold the actors generated from this partitioning.  Note: this actor will be released.
								This array must be of size equal to the lower-support chunk's child count, to guarantee that all actors are reported.
	\param[in] newActorsSize	The size of the user-supplied newActors array.
	\param[in] logFn			User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return the number of new actors created.
	*/
	uint32_t			partitionSingleLowerSupportChunk(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn);

	/**
	Partition this actor into smaller pieces.  Use this function if this actor contains more than one support chunk. 

	After this operation, if successful, this actor will released, and its pointer no longer valid for use (unless it appears in the newActors list).

	\param[in] newActors		User-supplied array of actor pointers to hold the actors generated from this partitioning.  Note: this actor will not be released,
								but will hold a subset of the graph nodes that it had before the function was called.
								This array must be of size equal to the number of graph nodes in the asset, to guarantee
								that all actors are reported.
	\param[in] newActorsSize	The size of the user-supplied newActors array.
	\param[in] logFn			User-supplied message function (see NvBlastLog definition).  May be NULL.

	\return the number of new actors created.
	*/
	uint32_t			partitionMultipleGraphNodes(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn);

	/**
	\return true iff this actor contains the "world" support graph node, created when a bond contains the invalidIndex<uint32_t>() value for one of their chunkIndices.
	*/
	bool				isBoundToWorld() const;

	/**
	\return true iff this actor was damaged and split() call is required.
	*/
	bool				isSplitRequired() const;

private:

	//////// Data ////////

	/**
	Offset to block of memory which holds the data associated with all actors in this actor's lineage.
	This offset is positive.  The block address is this object's pointer _minus_ the m_familyOffset.
	This value is initialized to 0, which denotes an invalid actor.  Actors should be obtained through
	the FamilyHeader::borrowActor API, which will create a valid offset, and
	the FamilyHeader::returnActor API, which will zero the offset.
	*/
	uint32_t	m_familyOffset;

	/**
	The index of the head of a doubly-linked list of visible chunk indices.  If m_firstVisibleChunkIndex == invalidIndex<uint32_t>(),
	then there are no visible chunks.
	*/
	uint32_t	m_firstVisibleChunkIndex;

	/**
	The number of elements in the visible chunk list.
	*/
	uint32_t	m_visibleChunkCount;

	/**
	The index of the head of a singly-linked list of graph node indices.  If m_firstGraphNodeIndex == invalidIndex<uint32_t>(),
	then there are no graph nodes.
	*/
	uint32_t	m_firstGraphNodeIndex;

	/**
	The number of elements in the graph node list.
	*/
	uint32_t	m_graphNodeCount;

	/**
	The number of leaf chunks in this actor.
	*/
	uint32_t	m_leafChunkCount;
};

} // namespace Blast
} // namespace Nv


#include "NvBlastFamily.h"


namespace Nv
{
namespace Blast
{

//////// Actor inline methods ////////

NV_INLINE FamilyHeader* Actor::getFamilyHeader() const
{
	NVBLAST_ASSERT(isActive());
	return (FamilyHeader*)((uintptr_t)this - (uintptr_t)m_familyOffset);
}


NV_INLINE const Asset* Actor::getAsset() const
{
	return getFamilyHeader()->m_asset;
}


NV_INLINE bool Actor::isActive() const
{
	return m_familyOffset != 0;
}


NV_INLINE bool Actor::isSubSupportChunk() const
{
	return m_graphNodeCount == 0;
}


NV_INLINE bool Actor::isSingleSupportChunk() const
{
	return m_graphNodeCount == 1;
}


NV_INLINE uint32_t Actor::getIndex() const
{
	NVBLAST_ASSERT(isActive());
	const FamilyHeader* header = getFamilyHeader();
	NVBLAST_ASSERT(header != nullptr);
	const size_t index = this - header->getActors();
	NVBLAST_ASSERT(index <= UINT32_MAX);
	return (uint32_t)index;
}


NV_INLINE uint32_t Actor::getVisibleChunkCount() const
{
	return m_visibleChunkCount;
}


NV_INLINE uint32_t Actor::getFirstVisibleChunkIndex() const
{
	return m_firstVisibleChunkIndex;
}


NV_INLINE uint32_t Actor::getGraphNodeCount() const
{
	return m_graphNodeCount;
}


NV_INLINE uint32_t Actor::getLeafChunkCount() const
{
	return m_leafChunkCount;
}


NV_INLINE uint32_t Actor::getFirstGraphNodeIndex() const
{
	return m_firstGraphNodeIndex;
}

NV_INLINE uint32_t Actor::getFirstSubsupportChunkIndex() const
{
	return getAsset()->m_firstSubsupportChunkIndex;
}

NV_INLINE const SupportGraph* Actor::getGraph() const
{
	return &getAsset()->m_graph;
}

NV_INLINE FamilyGraph* Actor::getFamilyGraph() const
{
	return getFamilyHeader()->getFamilyGraph();
}

NV_INLINE NvBlastChunk* Actor::getChunks() const
{
	return getAsset()->getChunks();
}

NV_INLINE NvBlastBond* Actor::getBonds() const
{
	return getAsset()->getBonds();
}

NV_INLINE float* Actor::getLowerSupportChunkHealths() const
{
	return getFamilyHeader()->getLowerSupportChunkHealths();
}

NV_INLINE float*	Actor::getSubsupportChunkHealths() const
{
	return getFamilyHeader()->getSubsupportChunkHealths();
}

NV_INLINE float* Actor::getBondHealths() const
{
	return getFamilyHeader()->getBondHealths();
}

NV_INLINE const uint32_t* Actor::getGraphNodeIndexLinks() const
{
	return getFamilyHeader()->getGraphNodeIndexLinks();
}


NV_INLINE bool Actor::release()
{
	// Do nothing if this actor is not currently active.
	if (!isActive())
	{
		return false;
	}

	FamilyHeader* header = getFamilyHeader();

	// Clear the graph node list
	uint32_t* graphNodeIndexLinks = getFamilyHeader()->getGraphNodeIndexLinks();
	while (!isInvalidIndex(m_firstGraphNodeIndex))
	{
		const uint32_t graphNodeIndex = m_firstGraphNodeIndex;
		m_firstGraphNodeIndex = graphNodeIndexLinks[m_firstGraphNodeIndex];
		graphNodeIndexLinks[graphNodeIndex] = invalidIndex<uint32_t>();
		--m_graphNodeCount;
	}
	NVBLAST_ASSERT(m_graphNodeCount == 0);

	const Asset* asset = getAsset();

	// Clear the visible chunk list
	IndexDLink<uint32_t>* visibleChunkIndexLinks = header->getVisibleChunkIndexLinks();
	uint32_t* chunkActorIndices = header->getChunkActorIndices();
	while (!isInvalidIndex(m_firstVisibleChunkIndex))
	{
		// Descendants of the visible actor may be accessed again if the actor is deserialized.  Clear subtree.
		for (Asset::DepthFirstIt i(*asset, m_firstVisibleChunkIndex, true); (bool)i; ++i)
		{
			chunkActorIndices[(uint32_t)i] = invalidIndex<uint32_t>();
		}
		IndexDList<uint32_t>().removeListHead(m_firstVisibleChunkIndex, visibleChunkIndexLinks);
		--m_visibleChunkCount;
	}
	NVBLAST_ASSERT(m_visibleChunkCount == 0);

	// Clear the leaf chunk count
	m_leafChunkCount = 0;

	// This invalidates the actor and decrements the reference count
	header->returnActor(*this);

	return true;
}


NV_INLINE uint32_t Actor::partition(Actor** newActors, uint32_t newActorsSize, NvBlastLog logFn)
{
	NVBLASTLL_CHECK(newActorsSize == 0 || newActors != nullptr, logFn, "Nv::Blast::Actor::partition: NULL newActors pointer array input with non-zero newActorCount.", return 0);

	// Call one of two partition functions depending on the actor's support status
	return m_graphNodeCount <= 1 ?
		partitionSingleLowerSupportChunk(newActors, newActorsSize, logFn) :	// This actor will partition into subsupport chunks
		partitionMultipleGraphNodes(newActors, newActorsSize, logFn);		// This actor will partition into support chunks
}


NV_INLINE bool Actor::isBoundToWorld() const
{
	const SupportGraph& graph = *getGraph();

	if (graph.m_nodeCount == 0)
	{
		return false;	// This shouldn't happen
	}

	const uint32_t lastGraphChunkIndex = graph.getChunkIndices()[graph.m_nodeCount - 1];

	if (!isInvalidIndex(lastGraphChunkIndex))
	{
		return false;	// There is no world node
	}

	return getFamilyGraph()->getIslandIds()[graph.m_nodeCount - 1] == getIndex();
}


NV_INLINE bool Actor::isSplitRequired() const
{
	NVBLAST_ASSERT(isActive());

	if (getGraphNodeCount() <= 1)
	{
		uint32_t chunkHealthIndex = isSingleSupportChunk() ? getIndex() : getFirstVisibleChunkIndex() - getFirstSubsupportChunkIndex() + getGraph()->m_nodeCount;
		float* chunkHealths = getLowerSupportChunkHealths();
		if (chunkHealths[chunkHealthIndex] <= 0.0f)
		{
			const uint32_t chunkIndex = m_graphNodeCount == 0 ? m_firstVisibleChunkIndex : getGraph()->getChunkIndices()[m_firstGraphNodeIndex];
			if (!isInvalidIndex(chunkIndex))
			{
				const NvBlastChunk& chunk = getChunks()[chunkIndex];
				uint32_t childCount = chunk.childIndexStop - chunk.firstChildIndex;
				return childCount > 0;
			}
		}
	}
	else
	{
		uint32_t* firstDirtyNodeIndices = getFamilyGraph()->getFirstDirtyNodeIndices();
		if (!isInvalidIndex(firstDirtyNodeIndices[getIndex()]))
		{
			return true;
		}

	}
	return false;
}


//////// Actor::VisibleChunkIt inline methods ////////

NV_INLINE Actor::VisibleChunkIt::VisibleChunkIt(const Actor& actor) : DListIt<uint32_t>(actor.m_firstVisibleChunkIndex, actor.getFamilyHeader()->getVisibleChunkIndexLinks())
{
}


//////// Actor::GraphNodeIt inline methods ////////

NV_INLINE Actor::GraphNodeIt::GraphNodeIt(const Actor& actor) : LListIt<uint32_t>(actor.m_firstGraphNodeIndex, actor.getFamilyHeader()->getGraphNodeIndexLinks())
{
}


//////// Helper functions ////////

#if NVBLASTLL_CHECK_PARAMS
/**
Helper function to validate fracture buffer values being meaningful.
*/
static inline bool isValid(const NvBlastFractureBuffers* buffers)
{
	if (buffers->chunkFractureCount != 0 && buffers->chunkFractures == nullptr)
		return false;

	if (buffers->bondFractureCount != 0 && buffers->bondFractures == nullptr)
		return false;

	return true;
}
#endif


} // namespace Blast
} // namespace Nv


#endif // ifndef NVBLASTACTOR_H