Files
XCEngine/engine/third_party/physx/source/geomutils/include/GuPruner.h

228 lines
8.8 KiB
C++

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef GU_PRUNER_H
#define GU_PRUNER_H
#include "foundation/PxUserAllocated.h"
#include "foundation/PxTransform.h"
#include "GuPrunerPayload.h"
#include "GuPrunerTypedef.h"
namespace physx
{
class PxRenderOutput;
class PxBounds3;
namespace Gu
{
class ShapeData;
struct PrunerRaycastCallback
{
PrunerRaycastCallback() {}
virtual ~PrunerRaycastCallback() {}
virtual bool invoke(PxReal& distance, PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) = 0;
};
struct PrunerOverlapCallback
{
PrunerOverlapCallback() {}
virtual ~PrunerOverlapCallback() {}
virtual bool invoke(PxU32 primIndex, const PrunerPayload* payloads, const PxTransform* transforms) = 0;
};
class BasePruner : public PxUserAllocated
{
public:
BasePruner() {}
virtual ~BasePruner() {}
// shift the origin of the pruner objects
virtual void shiftOrigin(const PxVec3& shift) = 0;
// additional 'internal' interface
virtual void visualize(PxRenderOutput&, PxU32, PxU32) const {}
};
class Pruner : public BasePruner
{
public:
Pruner() {}
virtual ~Pruner() {}
/**
\brief Adds objects to the pruner.
\param[out] results Returned handles for added objects
\param[in] bounds Bounds of added objects. These bounds are used as-is so they should be pre-inflated if inflation is needed.
\param[in] data Payloads for added objects.
\param[in] transforms Transforms of added objects.
\param[in] count Number of objects in the arrays
\param[in] hasPruningStructure True if added objects have pruning structure. The structure will be merged later, adding the objects will not invalidate the pruner.
\return true if success, false if internal allocation failed. The first failing add results in a INVALID_PRUNERHANDLE.
\see PxPruningStructure
*/
virtual bool addObjects(PrunerHandle* results, const PxBounds3* bounds, const PrunerPayload* data, const PxTransform* transforms, PxU32 count, bool hasPruningStructure) = 0;
/**
\brief Removes objects from the pruner.
\param[in] handles The objects to remove
\param[in] count The number of objects to remove
\param[in] removalCallback Optional callback, called for each removed object (giving access to its payload for keeping external structures in sync)
*/
virtual void removeObjects(const PrunerHandle* handles, PxU32 count, PrunerPayloadRemovalCallback* removalCallback) = 0;
/**
\brief Updates objects with new bounds & transforms.
There are two ways to use this function:
1) manual bounds update: you can manually update the bounds via "getPayloadData" calls prior to calling "updateObjects".
In this case "updateObjects" only notifies the system that the data for these objects has changed. In this mode the
"inflation", "boundsIndices", "newBounds" and "newTransforms" parameters should remain null.
2) synchronization mode: in this case the new bounds (and optionally the new transforms) have been computed by an
external source and "updateObjects" tells the system to update its data from passed buffers. The new bounds are
always inflated by the "inflation" parameter while being copied. "boundsIndices" is an optional remap table, allowing
this call to only update a subset of the existing bounds (i.e. the updated bounds don't have to be first copied to a
separate contiguous buffer).
\param[in] handles The objects to update
\param[in] count The number of objects to update
\param[in] inflation Bounds inflation value
\param[in] boundsIndices The indices of the bounds in the bounds array (or NULL)
\param[in] newBounds Updated bounds array (or NULL)
\param[in] newTransforms Updated transforms array (or NULL)
*/
virtual void updateObjects(const PrunerHandle* handles, PxU32 count, float inflation=0.0f, const PxU32* boundsIndices=NULL, const PxBounds3* newBounds=NULL, const PxTransform32* newTransforms=NULL) = 0;
/**
\brief Gets rid of internal accel struct.
*/
virtual void purge() = 0;
/**
\brief Makes the queries consistent with previous changes.
This function must be called before starting queries on an updated Pruner and assert otherwise.
*/
virtual void commit() = 0;
/**
\brief Merges pruning structure to current pruner, parameters may differ for each pruner implementation.
\param[in] mergeParams Implementation-dependent merge data
*/
virtual void merge(const void* mergeParams) = 0;
/**
* Query functions
*
* Note: return value may disappear if PrunerCallback contains the necessary information
* currently it is still used for the dynamic pruner internally (to decide if added objects must be queried)
*/
virtual bool raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal& inOutDistance, PrunerRaycastCallback&) const = 0;
virtual bool overlap(const Gu::ShapeData& queryVolume, PrunerOverlapCallback&) const = 0;
virtual bool sweep(const Gu::ShapeData& queryVolume, const PxVec3& unitDir, PxReal& inOutDistance, PrunerRaycastCallback&) const = 0;
/**
\brief Retrieves the object's payload and data associated with the handle.
This function returns the payload associated with a given handle. Additionally it can return the
destination addresses for the object's bounds & transform. The user can then write the new bounds
and transform there, before eventually calling updateObjects().
\param[in] handle Object handle (initially returned by addObjects())
\param[out] data Optional location where to store the internal data associated with the payload.
\return The payload associated with the given handle.
*/
virtual const PrunerPayload& getPayloadData(PrunerHandle handle, PrunerPayloadData* data=NULL) const = 0;
/**
\brief Preallocate space
\param[in] nbEntries The number of entries to preallocate space for
*/
virtual void preallocate(PxU32 nbEntries) = 0;
/**
\brief Sets object's transform
\note This is equivalent to retrieving the transform's address with "getPayloadData" and writing
the transform there.
\param[in] handle Object handle (initially returned by addObjects())
\param[in] transform New transform
\return True if success
*/
virtual bool setTransform(PrunerHandle handle, const PxTransform& transform) = 0;
// PT: from the SQ branch, maybe temporary, unclear if a getType() function would be better etc
virtual bool isDynamic() const { return false; }
virtual void getGlobalBounds(PxBounds3&) const = 0;
};
/**
* Pruner building accel structure over time base class
*/
class DynamicPruner : public Pruner
{
public:
/**
* sets the rebuild hint rate used for step building the accel structure.
*/
virtual void setRebuildRateHint(PxU32 nbStepsForRebuild) = 0;
/**
* Steps the accel structure build.
* synchronousCall specifies if initialization can happen. It should not initialize build when called from a different thread
* returns true if finished
*/
virtual bool buildStep(bool synchronousCall = true) = 0;
/**
* Prepares new tree build
* returns true if new tree is needed
*/
virtual bool prepareBuild() = 0;
};
}
}
#endif