feat: godot-engine-source-4.3-stable
This commit is contained in:
parent
c59a7dcade
commit
7125d019b5
11149 changed files with 5070401 additions and 0 deletions
334
engine/thirdparty/vhacd/src/VHACD-ASYNC.cpp
vendored
Normal file
334
engine/thirdparty/vhacd/src/VHACD-ASYNC.cpp
vendored
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
#include "../public/VHACD.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <float.h>
|
||||
|
||||
#define ENABLE_ASYNC 1
|
||||
|
||||
#define HACD_ALLOC(x) malloc(x)
|
||||
#define HACD_FREE(x) free(x)
|
||||
#define HACD_ASSERT(x) assert(x)
|
||||
|
||||
namespace VHACD
|
||||
{
|
||||
|
||||
class MyHACD_API : public VHACD::IVHACD, public VHACD::IVHACD::IUserCallback, VHACD::IVHACD::IUserLogger
|
||||
{
|
||||
public:
|
||||
MyHACD_API(void)
|
||||
{
|
||||
mVHACD = VHACD::CreateVHACD();
|
||||
}
|
||||
|
||||
virtual ~MyHACD_API(void)
|
||||
{
|
||||
releaseHACD();
|
||||
Cancel();
|
||||
mVHACD->Release();
|
||||
}
|
||||
|
||||
|
||||
virtual bool Compute(const double* const _points,
|
||||
const uint32_t countPoints,
|
||||
const uint32_t* const _triangles,
|
||||
const uint32_t countTriangles,
|
||||
const Parameters& _desc) final
|
||||
{
|
||||
#if ENABLE_ASYNC
|
||||
Cancel(); // if we previously had a solution running; cancel it.
|
||||
releaseHACD();
|
||||
|
||||
// We need to copy the input vertices and triangles into our own buffers so we can operate
|
||||
// on them safely from the background thread.
|
||||
mVertices = (double *)HACD_ALLOC(sizeof(double)*countPoints * 3);
|
||||
mIndices = (uint32_t *)HACD_ALLOC(sizeof(uint32_t)*countTriangles * 3);
|
||||
memcpy(mVertices, _points, sizeof(double)*countPoints * 3);
|
||||
memcpy(mIndices, _triangles, sizeof(uint32_t)*countTriangles * 3);
|
||||
mRunning = true;
|
||||
mThread = new std::thread([this, countPoints, countTriangles, _desc]()
|
||||
{
|
||||
ComputeNow(mVertices, countPoints, mIndices, countTriangles, _desc);
|
||||
mRunning = false;
|
||||
});
|
||||
#else
|
||||
releaseHACD();
|
||||
ComputeNow(_points, countPoints, _triangles, countTriangles, _desc);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ComputeNow(const double* const points,
|
||||
const uint32_t countPoints,
|
||||
const uint32_t* const triangles,
|
||||
const uint32_t countTriangles,
|
||||
const Parameters& _desc)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
|
||||
mHullCount = 0;
|
||||
mCallback = _desc.m_callback;
|
||||
mLogger = _desc.m_logger;
|
||||
|
||||
IVHACD::Parameters desc = _desc;
|
||||
// Set our intercepting callback interfaces if non-null
|
||||
desc.m_callback = desc.m_callback ? this : nullptr;
|
||||
desc.m_logger = desc.m_logger ? this : nullptr;
|
||||
|
||||
if ( countPoints )
|
||||
{
|
||||
bool ok = mVHACD->Compute(points, countPoints, triangles, countTriangles, desc);
|
||||
if (ok)
|
||||
{
|
||||
ret = mVHACD->GetNConvexHulls();
|
||||
mHulls = new IVHACD::ConvexHull[ret];
|
||||
for (uint32_t i = 0; i < ret; i++)
|
||||
{
|
||||
VHACD::IVHACD::ConvexHull vhull;
|
||||
mVHACD->GetConvexHull(i, vhull);
|
||||
VHACD::IVHACD::ConvexHull h;
|
||||
h.m_nPoints = vhull.m_nPoints;
|
||||
h.m_points = (double *)HACD_ALLOC(sizeof(double) * 3 * h.m_nPoints);
|
||||
memcpy(h.m_points, vhull.m_points, sizeof(double) * 3 * h.m_nPoints);
|
||||
h.m_nTriangles = vhull.m_nTriangles;
|
||||
h.m_triangles = (uint32_t *)HACD_ALLOC(sizeof(uint32_t) * 3 * h.m_nTriangles);
|
||||
memcpy(h.m_triangles, vhull.m_triangles, sizeof(uint32_t) * 3 * h.m_nTriangles);
|
||||
h.m_volume = vhull.m_volume;
|
||||
h.m_center[0] = vhull.m_center[0];
|
||||
h.m_center[1] = vhull.m_center[1];
|
||||
h.m_center[2] = vhull.m_center[2];
|
||||
mHulls[i] = h;
|
||||
if (mCancel)
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mHullCount = ret;
|
||||
return ret ? true : false;
|
||||
}
|
||||
|
||||
void releaseHull(VHACD::IVHACD::ConvexHull &h)
|
||||
{
|
||||
HACD_FREE((void *)h.m_triangles);
|
||||
HACD_FREE((void *)h.m_points);
|
||||
h.m_triangles = nullptr;
|
||||
h.m_points = nullptr;
|
||||
}
|
||||
|
||||
virtual void GetConvexHull(const uint32_t index, VHACD::IVHACD::ConvexHull& ch) const final
|
||||
{
|
||||
if ( index < mHullCount )
|
||||
{
|
||||
ch = mHulls[index];
|
||||
}
|
||||
}
|
||||
|
||||
void releaseHACD(void) // release memory associated with the last HACD request
|
||||
{
|
||||
for (uint32_t i=0; i<mHullCount; i++)
|
||||
{
|
||||
releaseHull(mHulls[i]);
|
||||
}
|
||||
delete[]mHulls;
|
||||
mHulls = nullptr;
|
||||
mHullCount = 0;
|
||||
HACD_FREE(mVertices);
|
||||
mVertices = nullptr;
|
||||
HACD_FREE(mIndices);
|
||||
mIndices = nullptr;
|
||||
}
|
||||
|
||||
|
||||
virtual void release(void) // release the HACD_API interface
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual uint32_t getHullCount(void)
|
||||
{
|
||||
return mHullCount;
|
||||
}
|
||||
|
||||
virtual void Cancel() final
|
||||
{
|
||||
if (mRunning)
|
||||
{
|
||||
mVHACD->Cancel(); // Set the cancel signal to the base VHACD
|
||||
}
|
||||
if (mThread)
|
||||
{
|
||||
mThread->join(); // Wait for the thread to fully exit before we delete the instance
|
||||
delete mThread;
|
||||
mThread = nullptr;
|
||||
Log("Convex Decomposition thread canceled\n");
|
||||
}
|
||||
mCancel = false; // clear the cancel semaphore
|
||||
}
|
||||
|
||||
virtual bool Compute(const float* const points,
|
||||
const uint32_t countPoints,
|
||||
const uint32_t* const triangles,
|
||||
const uint32_t countTriangles,
|
||||
const Parameters& params) final
|
||||
{
|
||||
|
||||
double *vertices = (double *)HACD_ALLOC(sizeof(double)*countPoints * 3);
|
||||
const float *source = points;
|
||||
double *dest = vertices;
|
||||
for (uint32_t i = 0; i < countPoints; i++)
|
||||
{
|
||||
dest[0] = source[0];
|
||||
dest[1] = source[1];
|
||||
dest[2] = source[2];
|
||||
dest += 3;
|
||||
source += 3;
|
||||
}
|
||||
|
||||
bool ret = Compute(vertices, countPoints, triangles, countTriangles, params);
|
||||
HACD_FREE(vertices);
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual uint32_t GetNConvexHulls() const final
|
||||
{
|
||||
processPendingMessages();
|
||||
return mHullCount;
|
||||
}
|
||||
|
||||
virtual void Clean(void) final // release internally allocated memory
|
||||
{
|
||||
Cancel();
|
||||
releaseHACD();
|
||||
mVHACD->Clean();
|
||||
}
|
||||
|
||||
virtual void Release(void) final // release IVHACD
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual bool OCLInit(void* const oclDevice,
|
||||
IVHACD::IUserLogger* const logger = 0) final
|
||||
{
|
||||
return mVHACD->OCLInit(oclDevice, logger);
|
||||
}
|
||||
|
||||
virtual bool OCLRelease(IVHACD::IUserLogger* const logger = 0) final
|
||||
{
|
||||
return mVHACD->OCLRelease(logger);
|
||||
}
|
||||
|
||||
virtual void Update(const double overallProgress,
|
||||
const double stageProgress,
|
||||
const double operationProgress,
|
||||
const char* const stage,
|
||||
const char* const operation) final
|
||||
{
|
||||
mMessageMutex.lock();
|
||||
mHaveUpdateMessage = true;
|
||||
mOverallProgress = overallProgress;
|
||||
mStageProgress = stageProgress;
|
||||
mOperationProgress = operationProgress;
|
||||
mStage = std::string(stage);
|
||||
mOperation = std::string(operation);
|
||||
mMessageMutex.unlock();
|
||||
}
|
||||
|
||||
virtual void Log(const char* const msg) final
|
||||
{
|
||||
mMessageMutex.lock();
|
||||
mHaveLogMessage = true;
|
||||
mMessage = std::string(msg);
|
||||
mMessageMutex.unlock();
|
||||
}
|
||||
|
||||
virtual bool IsReady(void) const final
|
||||
{
|
||||
processPendingMessages();
|
||||
return !mRunning;
|
||||
}
|
||||
|
||||
// As a convenience for the calling application we only send it update and log messages from it's own main
|
||||
// thread. This reduces the complexity burden on the caller by making sure it only has to deal with log
|
||||
// messages in it's main application thread.
|
||||
void processPendingMessages(void) const
|
||||
{
|
||||
// If we have a new update message and the user has specified a callback we send the message and clear the semaphore
|
||||
if (mHaveUpdateMessage && mCallback)
|
||||
{
|
||||
mMessageMutex.lock();
|
||||
mCallback->Update(mOverallProgress, mStageProgress, mOperationProgress, mStage.c_str(), mOperation.c_str());
|
||||
mHaveUpdateMessage = false;
|
||||
mMessageMutex.unlock();
|
||||
}
|
||||
// If we have a new log message and the user has specified a callback we send the message and clear the semaphore
|
||||
if (mHaveLogMessage && mLogger)
|
||||
{
|
||||
mMessageMutex.lock();
|
||||
mLogger->Log(mMessage.c_str());
|
||||
mHaveLogMessage = false;
|
||||
mMessageMutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Will compute the center of mass of the convex hull decomposition results and return it
|
||||
// in 'centerOfMass'. Returns false if the center of mass could not be computed.
|
||||
virtual bool ComputeCenterOfMass(double centerOfMass[3]) const
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
centerOfMass[0] = 0;
|
||||
centerOfMass[1] = 0;
|
||||
centerOfMass[2] = 0;
|
||||
|
||||
if (mVHACD && IsReady() )
|
||||
{
|
||||
ret = mVHACD->ComputeCenterOfMass(centerOfMass);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
double *mVertices{ nullptr };
|
||||
uint32_t *mIndices{ nullptr };
|
||||
std::atomic< uint32_t> mHullCount{ 0 };
|
||||
VHACD::IVHACD::ConvexHull *mHulls{ nullptr };
|
||||
VHACD::IVHACD::IUserCallback *mCallback{ nullptr };
|
||||
VHACD::IVHACD::IUserLogger *mLogger{ nullptr };
|
||||
VHACD::IVHACD *mVHACD{ nullptr };
|
||||
std::thread *mThread{ nullptr };
|
||||
std::atomic< bool > mRunning{ false };
|
||||
std::atomic<bool> mCancel{ false };
|
||||
|
||||
// Thread safe caching mechanism for messages and update status.
|
||||
// This is so that caller always gets messages in his own thread
|
||||
// Member variables are marked as 'mutable' since the message dispatch function
|
||||
// is called from const query methods.
|
||||
mutable std::mutex mMessageMutex;
|
||||
mutable std::atomic< bool > mHaveUpdateMessage{ false };
|
||||
mutable std::atomic< bool > mHaveLogMessage{ false };
|
||||
mutable double mOverallProgress{ 0 };
|
||||
mutable double mStageProgress{ 0 };
|
||||
mutable double mOperationProgress{ 0 };
|
||||
mutable std::string mStage;
|
||||
mutable std::string mOperation;
|
||||
mutable std::string mMessage;
|
||||
};
|
||||
|
||||
IVHACD* CreateVHACD_ASYNC(void)
|
||||
{
|
||||
MyHACD_API *m = new MyHACD_API;
|
||||
return static_cast<IVHACD *>(m);
|
||||
}
|
||||
|
||||
|
||||
}; // end of VHACD namespace
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue