mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-14 08:04:40 +00:00
Revert "Updated SDL, Bullet and OpenAL soft libs"
This reverts commit 370161cfb1.
This commit is contained in:
parent
63be684474
commit
bc77ff0833
1102 changed files with 62741 additions and 204988 deletions
|
|
@ -14,9 +14,6 @@ SET(LinearMath_SRCS
|
|||
btSerializer64.cpp
|
||||
btThreads.cpp
|
||||
btVector3.cpp
|
||||
TaskScheduler/btTaskScheduler.cpp
|
||||
TaskScheduler/btThreadSupportPosix.cpp
|
||||
TaskScheduler/btThreadSupportWin32.cpp
|
||||
)
|
||||
|
||||
SET(LinearMath_HDRS
|
||||
|
|
@ -47,7 +44,6 @@ SET(LinearMath_HDRS
|
|||
btTransform.h
|
||||
btTransformUtil.h
|
||||
btVector3.h
|
||||
TaskScheduler/btThreadSupportInterface.h
|
||||
)
|
||||
|
||||
ADD_LIBRARY(LinearMath ${LinearMath_SRCS} ${LinearMath_HDRS})
|
||||
|
|
|
|||
|
|
@ -1,792 +0,0 @@
|
|||
|
||||
#include "LinearMath/btMinMax.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btThreads.h"
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
#if BT_THREADSAFE
|
||||
|
||||
#include "btThreadSupportInterface.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif
|
||||
|
||||
typedef unsigned long long btU64;
|
||||
static const int kCacheLineSize = 64;
|
||||
|
||||
void btSpinPause()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
YieldProcessor();
|
||||
#endif
|
||||
}
|
||||
|
||||
struct WorkerThreadStatus
|
||||
{
|
||||
enum Type
|
||||
{
|
||||
kInvalid,
|
||||
kWaitingForWork,
|
||||
kWorking,
|
||||
kSleeping,
|
||||
};
|
||||
};
|
||||
|
||||
ATTRIBUTE_ALIGNED64(class)
|
||||
WorkerThreadDirectives
|
||||
{
|
||||
static const int kMaxThreadCount = BT_MAX_THREAD_COUNT;
|
||||
// directives for all worker threads packed into a single cacheline
|
||||
char m_threadDirs[kMaxThreadCount];
|
||||
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
kInvalid,
|
||||
kGoToSleep, // go to sleep
|
||||
kStayAwakeButIdle, // wait for not checking job queue
|
||||
kScanForJobs, // actively scan job queue for jobs
|
||||
};
|
||||
WorkerThreadDirectives()
|
||||
{
|
||||
for (int i = 0; i < kMaxThreadCount; ++i)
|
||||
{
|
||||
m_threadDirs[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Type getDirective(int threadId)
|
||||
{
|
||||
btAssert(threadId < kMaxThreadCount);
|
||||
return static_cast<Type>(m_threadDirs[threadId]);
|
||||
}
|
||||
|
||||
void setDirectiveByRange(int threadBegin, int threadEnd, Type dir)
|
||||
{
|
||||
btAssert(threadBegin < threadEnd);
|
||||
btAssert(threadEnd <= kMaxThreadCount);
|
||||
char dirChar = static_cast<char>(dir);
|
||||
for (int i = threadBegin; i < threadEnd; ++i)
|
||||
{
|
||||
m_threadDirs[i] = dirChar;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class JobQueue;
|
||||
|
||||
ATTRIBUTE_ALIGNED64(struct)
|
||||
ThreadLocalStorage
|
||||
{
|
||||
int m_threadId;
|
||||
WorkerThreadStatus::Type m_status;
|
||||
int m_numJobsFinished;
|
||||
btSpinMutex m_mutex;
|
||||
btScalar m_sumResult;
|
||||
WorkerThreadDirectives* m_directive;
|
||||
JobQueue* m_queue;
|
||||
btClock* m_clock;
|
||||
unsigned int m_cooldownTime;
|
||||
};
|
||||
|
||||
struct IJob
|
||||
{
|
||||
virtual void executeJob(int threadId) = 0;
|
||||
};
|
||||
|
||||
class ParallelForJob : public IJob
|
||||
{
|
||||
const btIParallelForBody* m_body;
|
||||
int m_begin;
|
||||
int m_end;
|
||||
|
||||
public:
|
||||
ParallelForJob(int iBegin, int iEnd, const btIParallelForBody& body)
|
||||
{
|
||||
m_body = &body;
|
||||
m_begin = iBegin;
|
||||
m_end = iEnd;
|
||||
}
|
||||
virtual void executeJob(int threadId) BT_OVERRIDE
|
||||
{
|
||||
BT_PROFILE("executeJob");
|
||||
|
||||
// call the functor body to do the work
|
||||
m_body->forLoop(m_begin, m_end);
|
||||
}
|
||||
};
|
||||
|
||||
class ParallelSumJob : public IJob
|
||||
{
|
||||
const btIParallelSumBody* m_body;
|
||||
ThreadLocalStorage* m_threadLocalStoreArray;
|
||||
int m_begin;
|
||||
int m_end;
|
||||
|
||||
public:
|
||||
ParallelSumJob(int iBegin, int iEnd, const btIParallelSumBody& body, ThreadLocalStorage* tls)
|
||||
{
|
||||
m_body = &body;
|
||||
m_threadLocalStoreArray = tls;
|
||||
m_begin = iBegin;
|
||||
m_end = iEnd;
|
||||
}
|
||||
virtual void executeJob(int threadId) BT_OVERRIDE
|
||||
{
|
||||
BT_PROFILE("executeJob");
|
||||
|
||||
// call the functor body to do the work
|
||||
btScalar val = m_body->sumLoop(m_begin, m_end);
|
||||
#if BT_PARALLEL_SUM_DETERMINISTISM
|
||||
// by truncating bits of the result, we can make the parallelSum deterministic (at the expense of precision)
|
||||
const float TRUNC_SCALE = float(1 << 19);
|
||||
val = floor(val * TRUNC_SCALE + 0.5f) / TRUNC_SCALE; // truncate some bits
|
||||
#endif
|
||||
m_threadLocalStoreArray[threadId].m_sumResult += val;
|
||||
}
|
||||
};
|
||||
|
||||
ATTRIBUTE_ALIGNED64(class)
|
||||
JobQueue
|
||||
{
|
||||
btThreadSupportInterface* m_threadSupport;
|
||||
btCriticalSection* m_queueLock;
|
||||
btSpinMutex m_mutex;
|
||||
|
||||
btAlignedObjectArray<IJob*> m_jobQueue;
|
||||
char* m_jobMem;
|
||||
int m_jobMemSize;
|
||||
bool m_queueIsEmpty;
|
||||
int m_tailIndex;
|
||||
int m_headIndex;
|
||||
int m_allocSize;
|
||||
bool m_useSpinMutex;
|
||||
btAlignedObjectArray<JobQueue*> m_neighborContexts;
|
||||
char m_cachePadding[kCacheLineSize]; // prevent false sharing
|
||||
|
||||
void freeJobMem()
|
||||
{
|
||||
if (m_jobMem)
|
||||
{
|
||||
// free old
|
||||
btAlignedFree(m_jobMem);
|
||||
m_jobMem = NULL;
|
||||
}
|
||||
}
|
||||
void resizeJobMem(int newSize)
|
||||
{
|
||||
if (newSize > m_jobMemSize)
|
||||
{
|
||||
freeJobMem();
|
||||
m_jobMem = static_cast<char*>(btAlignedAlloc(newSize, kCacheLineSize));
|
||||
m_jobMemSize = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
JobQueue()
|
||||
{
|
||||
m_jobMem = NULL;
|
||||
m_jobMemSize = 0;
|
||||
m_threadSupport = NULL;
|
||||
m_queueLock = NULL;
|
||||
m_headIndex = 0;
|
||||
m_tailIndex = 0;
|
||||
m_useSpinMutex = false;
|
||||
}
|
||||
~JobQueue()
|
||||
{
|
||||
exit();
|
||||
}
|
||||
void exit()
|
||||
{
|
||||
freeJobMem();
|
||||
if (m_queueLock && m_threadSupport)
|
||||
{
|
||||
m_threadSupport->deleteCriticalSection(m_queueLock);
|
||||
m_queueLock = NULL;
|
||||
m_threadSupport = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void init(btThreadSupportInterface * threadSup, btAlignedObjectArray<JobQueue> * contextArray)
|
||||
{
|
||||
m_threadSupport = threadSup;
|
||||
if (threadSup)
|
||||
{
|
||||
m_queueLock = m_threadSupport->createCriticalSection();
|
||||
}
|
||||
setupJobStealing(contextArray, contextArray->size());
|
||||
}
|
||||
void setupJobStealing(btAlignedObjectArray<JobQueue> * contextArray, int numActiveContexts)
|
||||
{
|
||||
btAlignedObjectArray<JobQueue>& contexts = *contextArray;
|
||||
int selfIndex = 0;
|
||||
for (int i = 0; i < contexts.size(); ++i)
|
||||
{
|
||||
if (this == &contexts[i])
|
||||
{
|
||||
selfIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int numNeighbors = btMin(2, contexts.size() - 1);
|
||||
int neighborOffsets[] = {-1, 1, -2, 2, -3, 3};
|
||||
int numOffsets = sizeof(neighborOffsets) / sizeof(neighborOffsets[0]);
|
||||
m_neighborContexts.reserve(numNeighbors);
|
||||
m_neighborContexts.resizeNoInitialize(0);
|
||||
for (int i = 0; i < numOffsets && m_neighborContexts.size() < numNeighbors; i++)
|
||||
{
|
||||
int neighborIndex = selfIndex + neighborOffsets[i];
|
||||
if (neighborIndex >= 0 && neighborIndex < numActiveContexts)
|
||||
{
|
||||
m_neighborContexts.push_back(&contexts[neighborIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isQueueEmpty() const { return m_queueIsEmpty; }
|
||||
void lockQueue()
|
||||
{
|
||||
if (m_useSpinMutex)
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_queueLock->lock();
|
||||
}
|
||||
}
|
||||
void unlockQueue()
|
||||
{
|
||||
if (m_useSpinMutex)
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_queueLock->unlock();
|
||||
}
|
||||
}
|
||||
void clearQueue(int jobCount, int jobSize)
|
||||
{
|
||||
lockQueue();
|
||||
m_headIndex = 0;
|
||||
m_tailIndex = 0;
|
||||
m_allocSize = 0;
|
||||
m_queueIsEmpty = true;
|
||||
int jobBufSize = jobSize * jobCount;
|
||||
// make sure we have enough memory allocated to store jobs
|
||||
if (jobBufSize > m_jobMemSize)
|
||||
{
|
||||
resizeJobMem(jobBufSize);
|
||||
}
|
||||
// make sure job queue is big enough
|
||||
if (jobCount > m_jobQueue.capacity())
|
||||
{
|
||||
m_jobQueue.reserve(jobCount);
|
||||
}
|
||||
unlockQueue();
|
||||
m_jobQueue.resizeNoInitialize(0);
|
||||
}
|
||||
void* allocJobMem(int jobSize)
|
||||
{
|
||||
btAssert(m_jobMemSize >= (m_allocSize + jobSize));
|
||||
void* jobMem = &m_jobMem[m_allocSize];
|
||||
m_allocSize += jobSize;
|
||||
return jobMem;
|
||||
}
|
||||
void submitJob(IJob * job)
|
||||
{
|
||||
btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
|
||||
m_jobQueue.push_back(job);
|
||||
lockQueue();
|
||||
m_tailIndex++;
|
||||
m_queueIsEmpty = false;
|
||||
unlockQueue();
|
||||
}
|
||||
IJob* consumeJobFromOwnQueue()
|
||||
{
|
||||
if (m_queueIsEmpty)
|
||||
{
|
||||
// lock free path. even if this is taken erroneously it isn't harmful
|
||||
return NULL;
|
||||
}
|
||||
IJob* job = NULL;
|
||||
lockQueue();
|
||||
if (!m_queueIsEmpty)
|
||||
{
|
||||
job = m_jobQueue[m_headIndex++];
|
||||
btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
|
||||
if (m_headIndex == m_tailIndex)
|
||||
{
|
||||
m_queueIsEmpty = true;
|
||||
}
|
||||
}
|
||||
unlockQueue();
|
||||
return job;
|
||||
}
|
||||
IJob* consumeJob()
|
||||
{
|
||||
if (IJob* job = consumeJobFromOwnQueue())
|
||||
{
|
||||
return job;
|
||||
}
|
||||
// own queue is empty, try to steal from neighbor
|
||||
for (int i = 0; i < m_neighborContexts.size(); ++i)
|
||||
{
|
||||
JobQueue* otherContext = m_neighborContexts[i];
|
||||
if (IJob* job = otherContext->consumeJobFromOwnQueue())
|
||||
{
|
||||
return job;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
static void WorkerThreadFunc(void* userPtr)
|
||||
{
|
||||
BT_PROFILE("WorkerThreadFunc");
|
||||
ThreadLocalStorage* localStorage = (ThreadLocalStorage*)userPtr;
|
||||
JobQueue* jobQueue = localStorage->m_queue;
|
||||
|
||||
bool shouldSleep = false;
|
||||
int threadId = localStorage->m_threadId;
|
||||
while (!shouldSleep)
|
||||
{
|
||||
// do work
|
||||
localStorage->m_mutex.lock();
|
||||
while (IJob* job = jobQueue->consumeJob())
|
||||
{
|
||||
localStorage->m_status = WorkerThreadStatus::kWorking;
|
||||
job->executeJob(threadId);
|
||||
localStorage->m_numJobsFinished++;
|
||||
}
|
||||
localStorage->m_status = WorkerThreadStatus::kWaitingForWork;
|
||||
localStorage->m_mutex.unlock();
|
||||
btU64 clockStart = localStorage->m_clock->getTimeMicroseconds();
|
||||
// while queue is empty,
|
||||
while (jobQueue->isQueueEmpty())
|
||||
{
|
||||
// todo: spin wait a bit to avoid hammering the empty queue
|
||||
btSpinPause();
|
||||
if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kGoToSleep)
|
||||
{
|
||||
shouldSleep = true;
|
||||
break;
|
||||
}
|
||||
// if jobs are incoming,
|
||||
if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs)
|
||||
{
|
||||
clockStart = localStorage->m_clock->getTimeMicroseconds(); // reset clock
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 50; ++i)
|
||||
{
|
||||
btSpinPause();
|
||||
btSpinPause();
|
||||
btSpinPause();
|
||||
btSpinPause();
|
||||
if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs || !jobQueue->isQueueEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if no jobs incoming and queue has been empty for the cooldown time, sleep
|
||||
btU64 timeElapsed = localStorage->m_clock->getTimeMicroseconds() - clockStart;
|
||||
if (timeElapsed > localStorage->m_cooldownTime)
|
||||
{
|
||||
shouldSleep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
BT_PROFILE("sleep");
|
||||
// go sleep
|
||||
localStorage->m_mutex.lock();
|
||||
localStorage->m_status = WorkerThreadStatus::kSleeping;
|
||||
localStorage->m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
class btTaskSchedulerDefault : public btITaskScheduler
|
||||
{
|
||||
btThreadSupportInterface* m_threadSupport;
|
||||
WorkerThreadDirectives* m_workerDirective;
|
||||
btAlignedObjectArray<JobQueue> m_jobQueues;
|
||||
btAlignedObjectArray<JobQueue*> m_perThreadJobQueues;
|
||||
btAlignedObjectArray<ThreadLocalStorage> m_threadLocalStorage;
|
||||
btSpinMutex m_antiNestingLock; // prevent nested parallel-for
|
||||
btClock m_clock;
|
||||
int m_numThreads;
|
||||
int m_numWorkerThreads;
|
||||
int m_numActiveJobQueues;
|
||||
int m_maxNumThreads;
|
||||
int m_numJobs;
|
||||
static const int kFirstWorkerThreadId = 1;
|
||||
|
||||
public:
|
||||
btTaskSchedulerDefault() : btITaskScheduler("ThreadSupport")
|
||||
{
|
||||
m_threadSupport = NULL;
|
||||
m_workerDirective = NULL;
|
||||
}
|
||||
|
||||
virtual ~btTaskSchedulerDefault()
|
||||
{
|
||||
waitForWorkersToSleep();
|
||||
|
||||
for (int i = 0; i < m_jobQueues.size(); ++i)
|
||||
{
|
||||
m_jobQueues[i].exit();
|
||||
}
|
||||
|
||||
if (m_threadSupport)
|
||||
{
|
||||
delete m_threadSupport;
|
||||
m_threadSupport = NULL;
|
||||
}
|
||||
if (m_workerDirective)
|
||||
{
|
||||
btAlignedFree(m_workerDirective);
|
||||
m_workerDirective = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
btThreadSupportInterface::ConstructionInfo constructionInfo("TaskScheduler", WorkerThreadFunc);
|
||||
m_threadSupport = btThreadSupportInterface::create(constructionInfo);
|
||||
m_workerDirective = static_cast<WorkerThreadDirectives*>(btAlignedAlloc(sizeof(*m_workerDirective), 64));
|
||||
|
||||
m_numWorkerThreads = m_threadSupport->getNumWorkerThreads();
|
||||
m_maxNumThreads = m_threadSupport->getNumWorkerThreads() + 1;
|
||||
m_numThreads = m_maxNumThreads;
|
||||
// ideal to have one job queue for each physical processor (except for the main thread which needs no queue)
|
||||
int numThreadsPerQueue = m_threadSupport->getLogicalToPhysicalCoreRatio();
|
||||
int numJobQueues = (numThreadsPerQueue == 1) ? (m_maxNumThreads - 1) : (m_maxNumThreads / numThreadsPerQueue);
|
||||
m_jobQueues.resize(numJobQueues);
|
||||
m_numActiveJobQueues = numJobQueues;
|
||||
for (int i = 0; i < m_jobQueues.size(); ++i)
|
||||
{
|
||||
m_jobQueues[i].init(m_threadSupport, &m_jobQueues);
|
||||
}
|
||||
m_perThreadJobQueues.resize(m_numThreads);
|
||||
for (int i = 0; i < m_numThreads; i++)
|
||||
{
|
||||
JobQueue* jq = NULL;
|
||||
// only worker threads get a job queue
|
||||
if (i > 0)
|
||||
{
|
||||
if (numThreadsPerQueue == 1)
|
||||
{
|
||||
// one queue per worker thread
|
||||
jq = &m_jobQueues[i - kFirstWorkerThreadId];
|
||||
}
|
||||
else
|
||||
{
|
||||
// 2 threads share each queue
|
||||
jq = &m_jobQueues[i / numThreadsPerQueue];
|
||||
}
|
||||
}
|
||||
m_perThreadJobQueues[i] = jq;
|
||||
}
|
||||
m_threadLocalStorage.resize(m_numThreads);
|
||||
for (int i = 0; i < m_numThreads; i++)
|
||||
{
|
||||
ThreadLocalStorage& storage = m_threadLocalStorage[i];
|
||||
storage.m_threadId = i;
|
||||
storage.m_directive = m_workerDirective;
|
||||
storage.m_status = WorkerThreadStatus::kSleeping;
|
||||
storage.m_cooldownTime = 100; // 100 microseconds, threads go to sleep after this long if they have nothing to do
|
||||
storage.m_clock = &m_clock;
|
||||
storage.m_queue = m_perThreadJobQueues[i];
|
||||
}
|
||||
setWorkerDirectives(WorkerThreadDirectives::kGoToSleep); // no work for them yet
|
||||
setNumThreads(m_threadSupport->getCacheFriendlyNumThreads());
|
||||
}
|
||||
|
||||
void setWorkerDirectives(WorkerThreadDirectives::Type dir)
|
||||
{
|
||||
m_workerDirective->setDirectiveByRange(kFirstWorkerThreadId, m_numThreads, dir);
|
||||
}
|
||||
|
||||
virtual int getMaxNumThreads() const BT_OVERRIDE
|
||||
{
|
||||
return m_maxNumThreads;
|
||||
}
|
||||
|
||||
virtual int getNumThreads() const BT_OVERRIDE
|
||||
{
|
||||
return m_numThreads;
|
||||
}
|
||||
|
||||
virtual void setNumThreads(int numThreads) BT_OVERRIDE
|
||||
{
|
||||
m_numThreads = btMax(btMin(numThreads, int(m_maxNumThreads)), 1);
|
||||
m_numWorkerThreads = m_numThreads - 1;
|
||||
m_numActiveJobQueues = 0;
|
||||
// if there is at least 1 worker,
|
||||
if (m_numWorkerThreads > 0)
|
||||
{
|
||||
// re-setup job stealing between queues to avoid attempting to steal from an inactive job queue
|
||||
JobQueue* lastActiveContext = m_perThreadJobQueues[m_numThreads - 1];
|
||||
int iLastActiveContext = lastActiveContext - &m_jobQueues[0];
|
||||
m_numActiveJobQueues = iLastActiveContext + 1;
|
||||
for (int i = 0; i < m_jobQueues.size(); ++i)
|
||||
{
|
||||
m_jobQueues[i].setupJobStealing(&m_jobQueues, m_numActiveJobQueues);
|
||||
}
|
||||
}
|
||||
m_workerDirective->setDirectiveByRange(m_numThreads, BT_MAX_THREAD_COUNT, WorkerThreadDirectives::kGoToSleep);
|
||||
}
|
||||
|
||||
void waitJobs()
|
||||
{
|
||||
BT_PROFILE("waitJobs");
|
||||
// have the main thread work until the job queues are empty
|
||||
int numMainThreadJobsFinished = 0;
|
||||
for (int i = 0; i < m_numActiveJobQueues; ++i)
|
||||
{
|
||||
while (IJob* job = m_jobQueues[i].consumeJob())
|
||||
{
|
||||
job->executeJob(0);
|
||||
numMainThreadJobsFinished++;
|
||||
}
|
||||
}
|
||||
|
||||
// done with jobs for now, tell workers to rest (but not sleep)
|
||||
setWorkerDirectives(WorkerThreadDirectives::kStayAwakeButIdle);
|
||||
|
||||
btU64 clockStart = m_clock.getTimeMicroseconds();
|
||||
// wait for workers to finish any jobs in progress
|
||||
while (true)
|
||||
{
|
||||
int numWorkerJobsFinished = 0;
|
||||
for (int iThread = kFirstWorkerThreadId; iThread < m_numThreads; ++iThread)
|
||||
{
|
||||
ThreadLocalStorage* storage = &m_threadLocalStorage[iThread];
|
||||
storage->m_mutex.lock();
|
||||
numWorkerJobsFinished += storage->m_numJobsFinished;
|
||||
storage->m_mutex.unlock();
|
||||
}
|
||||
if (numWorkerJobsFinished + numMainThreadJobsFinished == m_numJobs)
|
||||
{
|
||||
break;
|
||||
}
|
||||
btU64 timeElapsed = m_clock.getTimeMicroseconds() - clockStart;
|
||||
btAssert(timeElapsed < 1000);
|
||||
if (timeElapsed > 100000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
btSpinPause();
|
||||
}
|
||||
}
|
||||
|
||||
void wakeWorkers(int numWorkersToWake)
|
||||
{
|
||||
BT_PROFILE("wakeWorkers");
|
||||
btAssert(m_workerDirective->getDirective(1) == WorkerThreadDirectives::kScanForJobs);
|
||||
int numDesiredWorkers = btMin(numWorkersToWake, m_numWorkerThreads);
|
||||
int numActiveWorkers = 0;
|
||||
for (int iWorker = 0; iWorker < m_numWorkerThreads; ++iWorker)
|
||||
{
|
||||
// note this count of active workers is not necessarily totally reliable, because a worker thread could be
|
||||
// just about to put itself to sleep. So we may on occasion fail to wake up all the workers. It should be rare.
|
||||
ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
|
||||
if (storage.m_status != WorkerThreadStatus::kSleeping)
|
||||
{
|
||||
numActiveWorkers++;
|
||||
}
|
||||
}
|
||||
for (int iWorker = 0; iWorker < m_numWorkerThreads && numActiveWorkers < numDesiredWorkers; ++iWorker)
|
||||
{
|
||||
ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
|
||||
if (storage.m_status == WorkerThreadStatus::kSleeping)
|
||||
{
|
||||
m_threadSupport->runTask(iWorker, &storage);
|
||||
numActiveWorkers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void waitForWorkersToSleep()
|
||||
{
|
||||
BT_PROFILE("waitForWorkersToSleep");
|
||||
setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
|
||||
m_threadSupport->waitForAllTasks();
|
||||
for (int i = kFirstWorkerThreadId; i < m_numThreads; i++)
|
||||
{
|
||||
ThreadLocalStorage& storage = m_threadLocalStorage[i];
|
||||
btAssert(storage.m_status == WorkerThreadStatus::kSleeping);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void sleepWorkerThreadsHint() BT_OVERRIDE
|
||||
{
|
||||
BT_PROFILE("sleepWorkerThreadsHint");
|
||||
// hint the task scheduler that we may not be using these threads for a little while
|
||||
setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
|
||||
}
|
||||
|
||||
void prepareWorkerThreads()
|
||||
{
|
||||
for (int i = kFirstWorkerThreadId; i < m_numThreads; ++i)
|
||||
{
|
||||
ThreadLocalStorage& storage = m_threadLocalStorage[i];
|
||||
storage.m_mutex.lock();
|
||||
storage.m_numJobsFinished = 0;
|
||||
storage.m_mutex.unlock();
|
||||
}
|
||||
setWorkerDirectives(WorkerThreadDirectives::kScanForJobs);
|
||||
}
|
||||
|
||||
virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
|
||||
{
|
||||
BT_PROFILE("parallelFor_ThreadSupport");
|
||||
btAssert(iEnd >= iBegin);
|
||||
btAssert(grainSize >= 1);
|
||||
int iterationCount = iEnd - iBegin;
|
||||
if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
|
||||
{
|
||||
typedef ParallelForJob JobType;
|
||||
int jobCount = (iterationCount + grainSize - 1) / grainSize;
|
||||
m_numJobs = jobCount;
|
||||
btAssert(jobCount >= 2); // need more than one job for multithreading
|
||||
int jobSize = sizeof(JobType);
|
||||
|
||||
for (int i = 0; i < m_numActiveJobQueues; ++i)
|
||||
{
|
||||
m_jobQueues[i].clearQueue(jobCount, jobSize);
|
||||
}
|
||||
// prepare worker threads for incoming work
|
||||
prepareWorkerThreads();
|
||||
// submit all of the jobs
|
||||
int iJob = 0;
|
||||
int iThread = kFirstWorkerThreadId; // first worker thread
|
||||
for (int i = iBegin; i < iEnd; i += grainSize)
|
||||
{
|
||||
btAssert(iJob < jobCount);
|
||||
int iE = btMin(i + grainSize, iEnd);
|
||||
JobQueue* jq = m_perThreadJobQueues[iThread];
|
||||
btAssert(jq);
|
||||
btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
|
||||
void* jobMem = jq->allocJobMem(jobSize);
|
||||
JobType* job = new (jobMem) ParallelForJob(i, iE, body); // placement new
|
||||
jq->submitJob(job);
|
||||
iJob++;
|
||||
iThread++;
|
||||
if (iThread >= m_numThreads)
|
||||
{
|
||||
iThread = kFirstWorkerThreadId; // first worker thread
|
||||
}
|
||||
}
|
||||
wakeWorkers(jobCount - 1);
|
||||
|
||||
// put the main thread to work on emptying the job queue and then wait for all workers to finish
|
||||
waitJobs();
|
||||
m_antiNestingLock.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
BT_PROFILE("parallelFor_mainThread");
|
||||
// just run on main thread
|
||||
body.forLoop(iBegin, iEnd);
|
||||
}
|
||||
}
|
||||
virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
|
||||
{
|
||||
BT_PROFILE("parallelSum_ThreadSupport");
|
||||
btAssert(iEnd >= iBegin);
|
||||
btAssert(grainSize >= 1);
|
||||
int iterationCount = iEnd - iBegin;
|
||||
if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
|
||||
{
|
||||
typedef ParallelSumJob JobType;
|
||||
int jobCount = (iterationCount + grainSize - 1) / grainSize;
|
||||
m_numJobs = jobCount;
|
||||
btAssert(jobCount >= 2); // need more than one job for multithreading
|
||||
int jobSize = sizeof(JobType);
|
||||
for (int i = 0; i < m_numActiveJobQueues; ++i)
|
||||
{
|
||||
m_jobQueues[i].clearQueue(jobCount, jobSize);
|
||||
}
|
||||
|
||||
// initialize summation
|
||||
for (int iThread = 0; iThread < m_numThreads; ++iThread)
|
||||
{
|
||||
m_threadLocalStorage[iThread].m_sumResult = btScalar(0);
|
||||
}
|
||||
|
||||
// prepare worker threads for incoming work
|
||||
prepareWorkerThreads();
|
||||
// submit all of the jobs
|
||||
int iJob = 0;
|
||||
int iThread = kFirstWorkerThreadId; // first worker thread
|
||||
for (int i = iBegin; i < iEnd; i += grainSize)
|
||||
{
|
||||
btAssert(iJob < jobCount);
|
||||
int iE = btMin(i + grainSize, iEnd);
|
||||
JobQueue* jq = m_perThreadJobQueues[iThread];
|
||||
btAssert(jq);
|
||||
btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
|
||||
void* jobMem = jq->allocJobMem(jobSize);
|
||||
JobType* job = new (jobMem) ParallelSumJob(i, iE, body, &m_threadLocalStorage[0]); // placement new
|
||||
jq->submitJob(job);
|
||||
iJob++;
|
||||
iThread++;
|
||||
if (iThread >= m_numThreads)
|
||||
{
|
||||
iThread = kFirstWorkerThreadId; // first worker thread
|
||||
}
|
||||
}
|
||||
wakeWorkers(jobCount - 1);
|
||||
|
||||
// put the main thread to work on emptying the job queue and then wait for all workers to finish
|
||||
waitJobs();
|
||||
|
||||
// add up all the thread sums
|
||||
btScalar sum = btScalar(0);
|
||||
for (int iThread = 0; iThread < m_numThreads; ++iThread)
|
||||
{
|
||||
sum += m_threadLocalStorage[iThread].m_sumResult;
|
||||
}
|
||||
m_antiNestingLock.unlock();
|
||||
return sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
BT_PROFILE("parallelSum_mainThread");
|
||||
// just run on main thread
|
||||
return body.sumLoop(iBegin, iEnd);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
btITaskScheduler* btCreateDefaultTaskScheduler()
|
||||
{
|
||||
btTaskSchedulerDefault* ts = new btTaskSchedulerDefault();
|
||||
ts->init();
|
||||
return ts;
|
||||
}
|
||||
|
||||
#else // #if BT_THREADSAFE
|
||||
|
||||
btITaskScheduler* btCreateDefaultTaskScheduler()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // #else // #if BT_THREADSAFE
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_THREAD_SUPPORT_INTERFACE_H
|
||||
#define BT_THREAD_SUPPORT_INTERFACE_H
|
||||
|
||||
class btCriticalSection
|
||||
{
|
||||
public:
|
||||
btCriticalSection() {}
|
||||
virtual ~btCriticalSection() {}
|
||||
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
};
|
||||
|
||||
class btThreadSupportInterface
|
||||
{
|
||||
public:
|
||||
virtual ~btThreadSupportInterface() {}
|
||||
|
||||
virtual int getNumWorkerThreads() const = 0; // number of worker threads (total number of logical processors - 1)
|
||||
virtual int getCacheFriendlyNumThreads() const = 0; // the number of logical processors sharing a single L3 cache
|
||||
virtual int getLogicalToPhysicalCoreRatio() const = 0; // the number of logical processors per physical processor (usually 1 or 2)
|
||||
virtual void runTask(int threadIndex, void* userData) = 0;
|
||||
virtual void waitForAllTasks() = 0;
|
||||
|
||||
virtual btCriticalSection* createCriticalSection() = 0;
|
||||
virtual void deleteCriticalSection(btCriticalSection* criticalSection) = 0;
|
||||
|
||||
typedef void (*ThreadFunc)(void* userPtr);
|
||||
|
||||
struct ConstructionInfo
|
||||
{
|
||||
ConstructionInfo(const char* uniqueName,
|
||||
ThreadFunc userThreadFunc,
|
||||
int threadStackSize = 65535)
|
||||
: m_uniqueName(uniqueName),
|
||||
m_userThreadFunc(userThreadFunc),
|
||||
m_threadStackSize(threadStackSize)
|
||||
{
|
||||
}
|
||||
|
||||
const char* m_uniqueName;
|
||||
ThreadFunc m_userThreadFunc;
|
||||
int m_threadStackSize;
|
||||
};
|
||||
|
||||
static btThreadSupportInterface* create(const ConstructionInfo& info);
|
||||
};
|
||||
|
||||
#endif //BT_THREAD_SUPPORT_INTERFACE_H
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if BT_THREADSAFE && !defined(_WIN32)
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btThreads.h"
|
||||
#include "LinearMath/btMinMax.h"
|
||||
#include "btThreadSupportInterface.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
|
||||
#endif //_XOPEN_SOURCE
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <unistd.h> //for sysconf
|
||||
|
||||
///
|
||||
/// getNumHardwareThreads()
|
||||
///
|
||||
///
|
||||
/// https://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine
|
||||
///
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
#include <thread>
|
||||
|
||||
int btGetNumHardwareThreads()
|
||||
{
|
||||
return btMax(1u, btMin(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency()));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int btGetNumHardwareThreads()
|
||||
{
|
||||
return btMax(1, btMin<int>(BT_MAX_THREAD_COUNT, sysconf(_SC_NPROCESSORS_ONLN)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// btThreadSupportPosix helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
|
||||
class btThreadSupportPosix : public btThreadSupportInterface
|
||||
{
|
||||
public:
|
||||
struct btThreadStatus
|
||||
{
|
||||
int m_taskId;
|
||||
int m_commandId;
|
||||
int m_status;
|
||||
|
||||
ThreadFunc m_userThreadFunc;
|
||||
void* m_userPtr; //for taskDesc etc
|
||||
|
||||
pthread_t thread;
|
||||
//each tread will wait until this signal to start its work
|
||||
sem_t* startSemaphore;
|
||||
btCriticalSection* m_cs;
|
||||
// this is a copy of m_mainSemaphore,
|
||||
//each tread will signal once it is finished with its work
|
||||
sem_t* m_mainSemaphore;
|
||||
unsigned long threadUsed;
|
||||
};
|
||||
|
||||
private:
|
||||
typedef unsigned long long UINT64;
|
||||
|
||||
btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
|
||||
// m_mainSemaphoresemaphore will signal, if and how many threads are finished with their work
|
||||
sem_t* m_mainSemaphore;
|
||||
int m_numThreads;
|
||||
UINT64 m_startedThreadsMask;
|
||||
void startThreads(const ConstructionInfo& threadInfo);
|
||||
void stopThreads();
|
||||
int waitForResponse();
|
||||
btCriticalSection* m_cs;
|
||||
public:
|
||||
btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo);
|
||||
virtual ~btThreadSupportPosix();
|
||||
|
||||
virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
|
||||
// TODO: return the number of logical processors sharing the first L3 cache
|
||||
virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return m_numThreads + 1; }
|
||||
// TODO: detect if CPU has hyperthreading enabled
|
||||
virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return 1; }
|
||||
|
||||
virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
|
||||
virtual void waitForAllTasks() BT_OVERRIDE;
|
||||
|
||||
virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
|
||||
virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
|
||||
};
|
||||
|
||||
#define checkPThreadFunction(returnValue) \
|
||||
if (0 != returnValue) \
|
||||
{ \
|
||||
printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
|
||||
}
|
||||
|
||||
// The number of threads should be equal to the number of available cores
|
||||
// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
|
||||
|
||||
btThreadSupportPosix::btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo)
|
||||
{
|
||||
m_cs = createCriticalSection();
|
||||
startThreads(threadConstructionInfo);
|
||||
}
|
||||
|
||||
// cleanup/shutdown Libspe2
|
||||
btThreadSupportPosix::~btThreadSupportPosix()
|
||||
{
|
||||
stopThreads();
|
||||
deleteCriticalSection(m_cs);
|
||||
m_cs=0;
|
||||
}
|
||||
|
||||
#if (defined(__APPLE__))
|
||||
#define NAMED_SEMAPHORES
|
||||
#endif
|
||||
|
||||
static sem_t* createSem(const char* baseName)
|
||||
{
|
||||
static int semCount = 0;
|
||||
#ifdef NAMED_SEMAPHORES
|
||||
/// Named semaphore begin
|
||||
char name[32];
|
||||
snprintf(name, 32, "/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++);
|
||||
sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
|
||||
|
||||
if (tempSem != reinterpret_cast<sem_t*>(SEM_FAILED))
|
||||
{
|
||||
// printf("Created \"%s\" Semaphore %p\n", name, tempSem);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Error creating Semaphore %d\n", errno);
|
||||
exit(-1);
|
||||
}
|
||||
/// Named semaphore end
|
||||
#else
|
||||
sem_t* tempSem = new sem_t;
|
||||
checkPThreadFunction(sem_init(tempSem, 0, 0));
|
||||
#endif
|
||||
return tempSem;
|
||||
}
|
||||
|
||||
static void destroySem(sem_t* semaphore)
|
||||
{
|
||||
#ifdef NAMED_SEMAPHORES
|
||||
checkPThreadFunction(sem_close(semaphore));
|
||||
#else
|
||||
checkPThreadFunction(sem_destroy(semaphore));
|
||||
delete semaphore;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void* threadFunction(void* argument)
|
||||
{
|
||||
btThreadSupportPosix::btThreadStatus* status = (btThreadSupportPosix::btThreadStatus*)argument;
|
||||
|
||||
while (1)
|
||||
{
|
||||
checkPThreadFunction(sem_wait(status->startSemaphore));
|
||||
void* userPtr = status->m_userPtr;
|
||||
|
||||
if (userPtr)
|
||||
{
|
||||
btAssert(status->m_status);
|
||||
status->m_userThreadFunc(userPtr);
|
||||
status->m_cs->lock();
|
||||
status->m_status = 2;
|
||||
status->m_cs->unlock();
|
||||
checkPThreadFunction(sem_post(status->m_mainSemaphore));
|
||||
status->threadUsed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//exit Thread
|
||||
status->m_cs->lock();
|
||||
status->m_status = 3;
|
||||
status->m_cs->unlock();
|
||||
checkPThreadFunction(sem_post(status->m_mainSemaphore));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///send messages to SPUs
|
||||
void btThreadSupportPosix::runTask(int threadIndex, void* userData)
|
||||
{
|
||||
///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
|
||||
btAssert(threadIndex >= 0);
|
||||
btAssert(threadIndex < m_activeThreadStatus.size());
|
||||
threadStatus.m_cs = m_cs;
|
||||
threadStatus.m_commandId = 1;
|
||||
threadStatus.m_status = 1;
|
||||
threadStatus.m_userPtr = userData;
|
||||
m_startedThreadsMask |= UINT64(1) << threadIndex;
|
||||
|
||||
// fire event to start new task
|
||||
checkPThreadFunction(sem_post(threadStatus.startSemaphore));
|
||||
}
|
||||
|
||||
///check for messages from SPUs
|
||||
int btThreadSupportPosix::waitForResponse()
|
||||
{
|
||||
///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
|
||||
///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
|
||||
|
||||
btAssert(m_activeThreadStatus.size());
|
||||
|
||||
// wait for any of the threads to finish
|
||||
checkPThreadFunction(sem_wait(m_mainSemaphore));
|
||||
// get at least one thread which has finished
|
||||
size_t last = -1;
|
||||
|
||||
for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
|
||||
{
|
||||
m_cs->lock();
|
||||
bool hasFinished = (2 == m_activeThreadStatus[t].m_status);
|
||||
m_cs->unlock();
|
||||
if (hasFinished)
|
||||
{
|
||||
last = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[last];
|
||||
|
||||
btAssert(threadStatus.m_status > 1);
|
||||
threadStatus.m_status = 0;
|
||||
|
||||
// need to find an active spu
|
||||
btAssert(last >= 0);
|
||||
m_startedThreadsMask &= ~(UINT64(1) << last);
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
void btThreadSupportPosix::waitForAllTasks()
|
||||
{
|
||||
while (m_startedThreadsMask)
|
||||
{
|
||||
waitForResponse();
|
||||
}
|
||||
}
|
||||
|
||||
void btThreadSupportPosix::startThreads(const ConstructionInfo& threadConstructionInfo)
|
||||
{
|
||||
m_numThreads = btGetNumHardwareThreads() - 1; // main thread exists already
|
||||
m_activeThreadStatus.resize(m_numThreads);
|
||||
m_startedThreadsMask = 0;
|
||||
|
||||
m_mainSemaphore = createSem("main");
|
||||
//checkPThreadFunction(sem_wait(mainSemaphore));
|
||||
|
||||
for (int i = 0; i < m_numThreads; i++)
|
||||
{
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[i];
|
||||
threadStatus.startSemaphore = createSem("threadLocal");
|
||||
threadStatus.m_userPtr = 0;
|
||||
threadStatus.m_cs = m_cs;
|
||||
threadStatus.m_taskId = i;
|
||||
threadStatus.m_commandId = 0;
|
||||
threadStatus.m_status = 0;
|
||||
threadStatus.m_mainSemaphore = m_mainSemaphore;
|
||||
threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
|
||||
threadStatus.threadUsed = 0;
|
||||
checkPThreadFunction(pthread_create(&threadStatus.thread, NULL, &threadFunction, (void*)&threadStatus));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///tell the task scheduler we are done with the SPU tasks
|
||||
void btThreadSupportPosix::stopThreads()
|
||||
{
|
||||
for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
|
||||
{
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[t];
|
||||
|
||||
threadStatus.m_userPtr = 0;
|
||||
checkPThreadFunction(sem_post(threadStatus.startSemaphore));
|
||||
checkPThreadFunction(sem_wait(m_mainSemaphore));
|
||||
|
||||
checkPThreadFunction(pthread_join(threadStatus.thread, 0));
|
||||
destroySem(threadStatus.startSemaphore);
|
||||
}
|
||||
destroySem(m_mainSemaphore);
|
||||
m_activeThreadStatus.clear();
|
||||
}
|
||||
|
||||
class btCriticalSectionPosix : public btCriticalSection
|
||||
{
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
public:
|
||||
btCriticalSectionPosix()
|
||||
{
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
}
|
||||
virtual ~btCriticalSectionPosix()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
virtual void lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
virtual void unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
};
|
||||
|
||||
btCriticalSection* btThreadSupportPosix::createCriticalSection()
|
||||
{
|
||||
return new btCriticalSectionPosix();
|
||||
}
|
||||
|
||||
void btThreadSupportPosix::deleteCriticalSection(btCriticalSection* cs)
|
||||
{
|
||||
delete cs;
|
||||
}
|
||||
|
||||
btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
|
||||
{
|
||||
return new btThreadSupportPosix(info);
|
||||
}
|
||||
|
||||
#endif // BT_THREADSAFE && !defined( _WIN32 )
|
||||
|
|
@ -1,452 +0,0 @@
|
|||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && BT_THREADSAFE
|
||||
|
||||
#include "LinearMath/btScalar.h"
|
||||
#include "LinearMath/btMinMax.h"
|
||||
#include "LinearMath/btAlignedObjectArray.h"
|
||||
#include "LinearMath/btThreads.h"
|
||||
#include "btThreadSupportInterface.h"
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct btProcessorInfo
|
||||
{
|
||||
int numLogicalProcessors;
|
||||
int numCores;
|
||||
int numNumaNodes;
|
||||
int numL1Cache;
|
||||
int numL2Cache;
|
||||
int numL3Cache;
|
||||
int numPhysicalPackages;
|
||||
static const int maxNumTeamMasks = 32;
|
||||
int numTeamMasks;
|
||||
UINT64 processorTeamMasks[maxNumTeamMasks];
|
||||
};
|
||||
|
||||
UINT64 getProcessorTeamMask(const btProcessorInfo& procInfo, int procId)
|
||||
{
|
||||
UINT64 procMask = UINT64(1) << procId;
|
||||
for (int i = 0; i < procInfo.numTeamMasks; ++i)
|
||||
{
|
||||
if (procMask & procInfo.processorTeamMasks[i])
|
||||
{
|
||||
return procInfo.processorTeamMasks[i];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getProcessorTeamIndex(const btProcessorInfo& procInfo, int procId)
|
||||
{
|
||||
UINT64 procMask = UINT64(1) << procId;
|
||||
for (int i = 0; i < procInfo.numTeamMasks; ++i)
|
||||
{
|
||||
if (procMask & procInfo.processorTeamMasks[i])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int countSetBits(ULONG64 bits)
|
||||
{
|
||||
int count = 0;
|
||||
while (bits)
|
||||
{
|
||||
if (bits & 1)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
bits >>= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
|
||||
|
||||
void getProcessorInformation(btProcessorInfo* procInfo)
|
||||
{
|
||||
memset(procInfo, 0, sizeof(*procInfo));
|
||||
Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
|
||||
(Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
|
||||
if (getLogicalProcInfo == NULL)
|
||||
{
|
||||
// no info
|
||||
return;
|
||||
}
|
||||
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
|
||||
DWORD bufSize = 0;
|
||||
while (true)
|
||||
{
|
||||
if (getLogicalProcInfo(buf, &bufSize))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
free(buf);
|
||||
}
|
||||
buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int len = bufSize / sizeof(*buf);
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
|
||||
switch (info->Relationship)
|
||||
{
|
||||
case RelationNumaNode:
|
||||
procInfo->numNumaNodes++;
|
||||
break;
|
||||
|
||||
case RelationProcessorCore:
|
||||
procInfo->numCores++;
|
||||
procInfo->numLogicalProcessors += countSetBits(info->ProcessorMask);
|
||||
break;
|
||||
|
||||
case RelationCache:
|
||||
if (info->Cache.Level == 1)
|
||||
{
|
||||
procInfo->numL1Cache++;
|
||||
}
|
||||
else if (info->Cache.Level == 2)
|
||||
{
|
||||
procInfo->numL2Cache++;
|
||||
}
|
||||
else if (info->Cache.Level == 3)
|
||||
{
|
||||
procInfo->numL3Cache++;
|
||||
// processors that share L3 cache are considered to be on the same team
|
||||
// because they can more easily work together on the same data.
|
||||
// Large performance penalties will occur if 2 or more threads from different
|
||||
// teams attempt to frequently read and modify the same cache lines.
|
||||
//
|
||||
// On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
|
||||
// 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
|
||||
// CCXs are operating on the same data, many cycles will be spent keeping the
|
||||
// two caches coherent.
|
||||
if (procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks)
|
||||
{
|
||||
procInfo->processorTeamMasks[procInfo->numTeamMasks] = info->ProcessorMask;
|
||||
procInfo->numTeamMasks++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RelationProcessorPackage:
|
||||
procInfo->numPhysicalPackages++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
///btThreadSupportWin32 helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
|
||||
class btThreadSupportWin32 : public btThreadSupportInterface
|
||||
{
|
||||
public:
|
||||
struct btThreadStatus
|
||||
{
|
||||
int m_taskId;
|
||||
int m_commandId;
|
||||
int m_status;
|
||||
|
||||
ThreadFunc m_userThreadFunc;
|
||||
void* m_userPtr; //for taskDesc etc
|
||||
|
||||
void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
|
||||
|
||||
void* m_eventStartHandle;
|
||||
char m_eventStartHandleName[32];
|
||||
|
||||
void* m_eventCompleteHandle;
|
||||
char m_eventCompleteHandleName[32];
|
||||
};
|
||||
|
||||
private:
|
||||
btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
|
||||
btAlignedObjectArray<void*> m_completeHandles;
|
||||
int m_numThreads;
|
||||
DWORD_PTR m_startedThreadMask;
|
||||
btProcessorInfo m_processorInfo;
|
||||
|
||||
void startThreads(const ConstructionInfo& threadInfo);
|
||||
void stopThreads();
|
||||
int waitForResponse();
|
||||
|
||||
public:
|
||||
btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo);
|
||||
virtual ~btThreadSupportWin32();
|
||||
|
||||
virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
|
||||
virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
|
||||
virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
|
||||
|
||||
virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
|
||||
virtual void waitForAllTasks() BT_OVERRIDE;
|
||||
|
||||
virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
|
||||
virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
|
||||
};
|
||||
|
||||
btThreadSupportWin32::btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo)
|
||||
{
|
||||
startThreads(threadConstructionInfo);
|
||||
}
|
||||
|
||||
btThreadSupportWin32::~btThreadSupportWin32()
|
||||
{
|
||||
stopThreads();
|
||||
}
|
||||
|
||||
DWORD WINAPI win32threadStartFunc(LPVOID lpParam)
|
||||
{
|
||||
btThreadSupportWin32::btThreadStatus* status = (btThreadSupportWin32::btThreadStatus*)lpParam;
|
||||
|
||||
while (1)
|
||||
{
|
||||
WaitForSingleObject(status->m_eventStartHandle, INFINITE);
|
||||
void* userPtr = status->m_userPtr;
|
||||
|
||||
if (userPtr)
|
||||
{
|
||||
btAssert(status->m_status);
|
||||
status->m_userThreadFunc(userPtr);
|
||||
status->m_status = 2;
|
||||
SetEvent(status->m_eventCompleteHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
//exit Thread
|
||||
status->m_status = 3;
|
||||
printf("Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle);
|
||||
SetEvent(status->m_eventCompleteHandle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Thread TERMINATED\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void btThreadSupportWin32::runTask(int threadIndex, void* userData)
|
||||
{
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
|
||||
btAssert(threadIndex >= 0);
|
||||
btAssert(int(threadIndex) < m_activeThreadStatus.size());
|
||||
|
||||
threadStatus.m_commandId = 1;
|
||||
threadStatus.m_status = 1;
|
||||
threadStatus.m_userPtr = userData;
|
||||
m_startedThreadMask |= DWORD_PTR(1) << threadIndex;
|
||||
|
||||
///fire event to start new task
|
||||
SetEvent(threadStatus.m_eventStartHandle);
|
||||
}
|
||||
|
||||
int btThreadSupportWin32::waitForResponse()
|
||||
{
|
||||
btAssert(m_activeThreadStatus.size());
|
||||
|
||||
int last = -1;
|
||||
DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
|
||||
btAssert(res != WAIT_FAILED);
|
||||
last = res - WAIT_OBJECT_0;
|
||||
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[last];
|
||||
btAssert(threadStatus.m_threadHandle);
|
||||
btAssert(threadStatus.m_eventCompleteHandle);
|
||||
|
||||
//WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
|
||||
btAssert(threadStatus.m_status > 1);
|
||||
threadStatus.m_status = 0;
|
||||
|
||||
///need to find an active spu
|
||||
btAssert(last >= 0);
|
||||
m_startedThreadMask &= ~(DWORD_PTR(1) << last);
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
void btThreadSupportWin32::waitForAllTasks()
|
||||
{
|
||||
while (m_startedThreadMask)
|
||||
{
|
||||
waitForResponse();
|
||||
}
|
||||
}
|
||||
|
||||
void btThreadSupportWin32::startThreads(const ConstructionInfo& threadConstructionInfo)
|
||||
{
|
||||
static int uniqueId = 0;
|
||||
uniqueId++;
|
||||
btProcessorInfo& procInfo = m_processorInfo;
|
||||
getProcessorInformation(&procInfo);
|
||||
DWORD_PTR dwProcessAffinityMask = 0;
|
||||
DWORD_PTR dwSystemAffinityMask = 0;
|
||||
if (!GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask))
|
||||
{
|
||||
dwProcessAffinityMask = 0;
|
||||
}
|
||||
///The number of threads should be equal to the number of available cores - 1
|
||||
m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1; // cap to max thread count (-1 because main thread already exists)
|
||||
|
||||
m_activeThreadStatus.resize(m_numThreads);
|
||||
m_completeHandles.resize(m_numThreads);
|
||||
m_startedThreadMask = 0;
|
||||
|
||||
// set main thread affinity
|
||||
if (DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask(procInfo, 0))
|
||||
{
|
||||
SetThreadAffinityMask(GetCurrentThread(), mask);
|
||||
SetThreadIdealProcessor(GetCurrentThread(), 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_numThreads; i++)
|
||||
{
|
||||
printf("starting thread %d\n", i);
|
||||
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[i];
|
||||
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
|
||||
SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
|
||||
LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
|
||||
LPVOID lpParameter = &threadStatus;
|
||||
DWORD dwCreationFlags = 0;
|
||||
LPDWORD lpThreadId = 0;
|
||||
|
||||
threadStatus.m_userPtr = 0;
|
||||
|
||||
sprintf(threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
|
||||
threadStatus.m_eventStartHandle = CreateEventA(0, false, false, threadStatus.m_eventStartHandleName);
|
||||
|
||||
sprintf(threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
|
||||
threadStatus.m_eventCompleteHandle = CreateEventA(0, false, false, threadStatus.m_eventCompleteHandleName);
|
||||
|
||||
m_completeHandles[i] = threadStatus.m_eventCompleteHandle;
|
||||
|
||||
HANDLE handle = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
|
||||
//SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
|
||||
// highest priority -- can cause erratic performance when numThreads > numCores
|
||||
// we don't want worker threads to be higher priority than the main thread or the main thread could get
|
||||
// totally shut out and unable to tell the workers to stop
|
||||
//SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
|
||||
|
||||
{
|
||||
int processorId = i + 1; // leave processor 0 for main thread
|
||||
DWORD_PTR teamMask = getProcessorTeamMask(procInfo, processorId);
|
||||
if (teamMask)
|
||||
{
|
||||
// bind each thread to only execute on processors of it's assigned team
|
||||
// - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
|
||||
// - for multi-socket Intel this will keep threads from migrating from one socket to another
|
||||
// - for AMD Ryzen this will keep threads from migrating from one CCX to another
|
||||
DWORD_PTR mask = teamMask & dwProcessAffinityMask;
|
||||
if (mask)
|
||||
{
|
||||
SetThreadAffinityMask(handle, mask);
|
||||
}
|
||||
}
|
||||
SetThreadIdealProcessor(handle, processorId);
|
||||
}
|
||||
|
||||
threadStatus.m_taskId = i;
|
||||
threadStatus.m_commandId = 0;
|
||||
threadStatus.m_status = 0;
|
||||
threadStatus.m_threadHandle = handle;
|
||||
threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
|
||||
|
||||
printf("started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle);
|
||||
}
|
||||
}
|
||||
|
||||
///tell the task scheduler we are done with the SPU tasks
|
||||
void btThreadSupportWin32::stopThreads()
|
||||
{
|
||||
for (int i = 0; i < m_activeThreadStatus.size(); i++)
|
||||
{
|
||||
btThreadStatus& threadStatus = m_activeThreadStatus[i];
|
||||
if (threadStatus.m_status > 0)
|
||||
{
|
||||
WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
|
||||
}
|
||||
|
||||
threadStatus.m_userPtr = NULL;
|
||||
SetEvent(threadStatus.m_eventStartHandle);
|
||||
WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
|
||||
|
||||
CloseHandle(threadStatus.m_eventCompleteHandle);
|
||||
CloseHandle(threadStatus.m_eventStartHandle);
|
||||
CloseHandle(threadStatus.m_threadHandle);
|
||||
}
|
||||
|
||||
m_activeThreadStatus.clear();
|
||||
m_completeHandles.clear();
|
||||
}
|
||||
|
||||
class btWin32CriticalSection : public btCriticalSection
|
||||
{
|
||||
private:
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
|
||||
public:
|
||||
btWin32CriticalSection()
|
||||
{
|
||||
InitializeCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
~btWin32CriticalSection()
|
||||
{
|
||||
DeleteCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
EnterCriticalSection(&mCriticalSection);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
LeaveCriticalSection(&mCriticalSection);
|
||||
}
|
||||
};
|
||||
|
||||
btCriticalSection* btThreadSupportWin32::createCriticalSection()
|
||||
{
|
||||
unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32CriticalSection), 16);
|
||||
btWin32CriticalSection* cs = new (mem) btWin32CriticalSection();
|
||||
return cs;
|
||||
}
|
||||
|
||||
void btThreadSupportWin32::deleteCriticalSection(btCriticalSection* criticalSection)
|
||||
{
|
||||
criticalSection->~btCriticalSection();
|
||||
btAlignedFree(criticalSection);
|
||||
}
|
||||
|
||||
btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
|
||||
{
|
||||
return new btThreadSupportWin32(info);
|
||||
}
|
||||
|
||||
#endif //defined(_WIN32) && BT_THREADSAFE
|
||||
|
|
@ -12,6 +12,8 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_AABB_UTIL2
|
||||
#define BT_AABB_UTIL2
|
||||
|
||||
|
|
@ -19,18 +21,20 @@ subject to the following restrictions:
|
|||
#include "btVector3.h"
|
||||
#include "btMinMax.h"
|
||||
|
||||
SIMD_FORCE_INLINE void AabbExpand(btVector3& aabbMin,
|
||||
btVector3& aabbMax,
|
||||
const btVector3& expansionMin,
|
||||
const btVector3& expansionMax)
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
|
||||
btVector3& aabbMax,
|
||||
const btVector3& expansionMin,
|
||||
const btVector3& expansionMax)
|
||||
{
|
||||
aabbMin = aabbMin + expansionMin;
|
||||
aabbMax = aabbMax + expansionMax;
|
||||
}
|
||||
|
||||
/// conservative test for overlap between two aabbs
|
||||
SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
|
||||
const btVector3& point)
|
||||
SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
|
||||
const btVector3 &point)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
|
||||
|
|
@ -39,9 +43,10 @@ SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3& aabbMin1, const bt
|
|||
return overlap;
|
||||
}
|
||||
|
||||
|
||||
/// conservative test for overlap between two aabbs
|
||||
SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
|
||||
const btVector3& aabbMin2, const btVector3& aabbMax2)
|
||||
SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
|
||||
const btVector3 &aabbMin2, const btVector3 &aabbMax2)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
|
||||
|
|
@ -51,34 +56,37 @@ SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3& aabbMin1, const btV
|
|||
}
|
||||
|
||||
/// conservative test for overlap between triangle and aabb
|
||||
SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3* vertices,
|
||||
const btVector3& aabbMin, const btVector3& aabbMax)
|
||||
SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices,
|
||||
const btVector3 &aabbMin, const btVector3 &aabbMax)
|
||||
{
|
||||
const btVector3& p1 = vertices[0];
|
||||
const btVector3& p2 = vertices[1];
|
||||
const btVector3& p3 = vertices[2];
|
||||
const btVector3 &p1 = vertices[0];
|
||||
const btVector3 &p2 = vertices[1];
|
||||
const btVector3 &p3 = vertices[2];
|
||||
|
||||
if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
|
||||
if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
|
||||
|
||||
if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
|
||||
if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
|
||||
|
||||
|
||||
if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
|
||||
if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE int btOutcode(const btVector3& p, const btVector3& halfExtent)
|
||||
|
||||
SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent)
|
||||
{
|
||||
return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
|
||||
(p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
|
||||
(p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
|
||||
(p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
|
||||
(p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
|
||||
(p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
|
||||
return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
|
||||
(p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
|
||||
(p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
|
||||
(p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
|
||||
(p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
|
||||
(p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
|
||||
const btVector3& rayInvDirection,
|
||||
const unsigned int raySign[3],
|
||||
|
|
@ -89,11 +97,11 @@ SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
|
|||
{
|
||||
btScalar tmax, tymin, tymax, tzmin, tzmax;
|
||||
tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
|
||||
tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
|
||||
tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
|
||||
tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
|
||||
tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
|
||||
tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
|
||||
|
||||
if ((tmin > tymax) || (tymin > tmax))
|
||||
if ( (tmin > tymax) || (tymin > tmax) )
|
||||
return false;
|
||||
|
||||
if (tymin > tmin)
|
||||
|
|
@ -103,59 +111,59 @@ SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
|
|||
tmax = tymax;
|
||||
|
||||
tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
|
||||
tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
|
||||
tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
|
||||
|
||||
if ((tmin > tzmax) || (tzmin > tmax))
|
||||
if ( (tmin > tzmax) || (tzmin > tmax) )
|
||||
return false;
|
||||
if (tzmin > tmin)
|
||||
tmin = tzmin;
|
||||
if (tzmax < tmax)
|
||||
tmax = tzmax;
|
||||
return ((tmin < lambda_max) && (tmax > lambda_min));
|
||||
return ( (tmin < lambda_max) && (tmax > lambda_min) );
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
|
||||
const btVector3& rayTo,
|
||||
const btVector3& aabbMin,
|
||||
SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
|
||||
const btVector3& rayTo,
|
||||
const btVector3& aabbMin,
|
||||
const btVector3& aabbMax,
|
||||
btScalar& param, btVector3& normal)
|
||||
btScalar& param, btVector3& normal)
|
||||
{
|
||||
btVector3 aabbHalfExtent = (aabbMax - aabbMin) * btScalar(0.5);
|
||||
btVector3 aabbCenter = (aabbMax + aabbMin) * btScalar(0.5);
|
||||
btVector3 source = rayFrom - aabbCenter;
|
||||
btVector3 target = rayTo - aabbCenter;
|
||||
int sourceOutcode = btOutcode(source, aabbHalfExtent);
|
||||
int targetOutcode = btOutcode(target, aabbHalfExtent);
|
||||
btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5);
|
||||
btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5);
|
||||
btVector3 source = rayFrom - aabbCenter;
|
||||
btVector3 target = rayTo - aabbCenter;
|
||||
int sourceOutcode = btOutcode(source,aabbHalfExtent);
|
||||
int targetOutcode = btOutcode(target,aabbHalfExtent);
|
||||
if ((sourceOutcode & targetOutcode) == 0x0)
|
||||
{
|
||||
btScalar lambda_enter = btScalar(0.0);
|
||||
btScalar lambda_exit = param;
|
||||
btScalar lambda_exit = param;
|
||||
btVector3 r = target - source;
|
||||
int i;
|
||||
btScalar normSign = 1;
|
||||
btVector3 hitNormal(0, 0, 0);
|
||||
int bit = 1;
|
||||
btScalar normSign = 1;
|
||||
btVector3 hitNormal(0,0,0);
|
||||
int bit=1;
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
for (int j=0;j<2;j++)
|
||||
{
|
||||
for (i = 0; i != 3; ++i)
|
||||
{
|
||||
if (sourceOutcode & bit)
|
||||
{
|
||||
btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
|
||||
btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
|
||||
if (lambda_enter <= lambda)
|
||||
{
|
||||
lambda_enter = lambda;
|
||||
hitNormal.setValue(0, 0, 0);
|
||||
hitNormal.setValue(0,0,0);
|
||||
hitNormal[i] = normSign;
|
||||
}
|
||||
}
|
||||
else if (targetOutcode & bit)
|
||||
else if (targetOutcode & bit)
|
||||
{
|
||||
btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
|
||||
btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
|
||||
btSetMin(lambda_exit, lambda);
|
||||
}
|
||||
bit <<= 1;
|
||||
bit<<=1;
|
||||
}
|
||||
normSign = btScalar(-1.);
|
||||
}
|
||||
|
|
@ -169,49 +177,56 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
|
|||
return false;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin, const btTransform& t, btVector3& aabbMinOut, btVector3& aabbMaxOut)
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut)
|
||||
{
|
||||
btVector3 halfExtentsWithMargin = halfExtents + btVector3(margin, margin, margin);
|
||||
btMatrix3x3 abs_b = t.getBasis().absolute();
|
||||
btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
|
||||
btMatrix3x3 abs_b = t.getBasis().absolute();
|
||||
btVector3 center = t.getOrigin();
|
||||
btVector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
|
||||
btVector3 extent = halfExtentsWithMargin.dot3( abs_b[0], abs_b[1], abs_b[2] );
|
||||
aabbMinOut = center - extent;
|
||||
aabbMaxOut = center + extent;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin, const btVector3& localAabbMax, btScalar margin, const btTransform& trans, btVector3& aabbMinOut, btVector3& aabbMaxOut)
|
||||
{
|
||||
btAssert(localAabbMin.getX() <= localAabbMax.getX());
|
||||
btAssert(localAabbMin.getY() <= localAabbMax.getY());
|
||||
btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
|
||||
btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
|
||||
localHalfExtents += btVector3(margin, margin, margin);
|
||||
|
||||
btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
|
||||
btMatrix3x3 abs_b = trans.getBasis().absolute();
|
||||
btVector3 center = trans(localCenter);
|
||||
btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
|
||||
aabbMinOut = center - extent;
|
||||
aabbMaxOut = center + extent;
|
||||
SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut)
|
||||
{
|
||||
btAssert(localAabbMin.getX() <= localAabbMax.getX());
|
||||
btAssert(localAabbMin.getY() <= localAabbMax.getY());
|
||||
btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
|
||||
btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
|
||||
localHalfExtents+=btVector3(margin,margin,margin);
|
||||
|
||||
btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
|
||||
btMatrix3x3 abs_b = trans.getBasis().absolute();
|
||||
btVector3 center = trans(localCenter);
|
||||
btVector3 extent = localHalfExtents.dot3( abs_b[0], abs_b[1], abs_b[2] );
|
||||
aabbMinOut = center-extent;
|
||||
aabbMaxOut = center+extent;
|
||||
}
|
||||
|
||||
#define USE_BANCHLESS 1
|
||||
#ifdef USE_BANCHLESS
|
||||
//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
|
||||
SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
|
||||
{
|
||||
return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
|
||||
1, 0));
|
||||
}
|
||||
//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
|
||||
SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
|
||||
{
|
||||
return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
|
||||
& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
|
||||
& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
|
||||
1, 0));
|
||||
}
|
||||
#else
|
||||
SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
|
||||
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
|
||||
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
#endif //USE_BANCHLESS
|
||||
SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
|
||||
overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
|
||||
overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
#endif //USE_BANCHLESS
|
||||
|
||||
#endif //BT_AABB_UTIL2
|
||||
|
||||
|
||||
#endif //BT_AABB_UTIL2
|
||||
|
|
|
|||
|
|
@ -15,11 +15,9 @@ subject to the following restrictions:
|
|||
|
||||
#include "btAlignedAllocator.h"
|
||||
|
||||
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
|
||||
int gNumAlignedAllocs = 0;
|
||||
int gNumAlignedFree = 0;
|
||||
int gTotalBytesAlignedAllocs = 0; //detect memory leaks
|
||||
#endif //BT_DEBUG_MEMORY_ALLOCATIONST_DEBUG_ALLOCATIONS
|
||||
int gTotalBytesAlignedAllocs = 0;//detect memory leaks
|
||||
|
||||
static void *btAllocDefault(size_t size)
|
||||
{
|
||||
|
|
@ -34,7 +32,9 @@ static void btFreeDefault(void *ptr)
|
|||
static btAllocFunc *sAllocFunc = btAllocDefault;
|
||||
static btFreeFunc *sFreeFunc = btFreeDefault;
|
||||
|
||||
#if defined(BT_HAS_ALIGNED_ALLOCATOR)
|
||||
|
||||
|
||||
#if defined (BT_HAS_ALIGNED_ALLOCATOR)
|
||||
#include <malloc.h>
|
||||
static void *btAlignedAllocDefault(size_t size, int alignment)
|
||||
{
|
||||
|
|
@ -59,48 +59,49 @@ static inline void btAlignedFreeDefault(void *ptr)
|
|||
}
|
||||
#else
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static inline void *btAlignedAllocDefault(size_t size, int alignment)
|
||||
{
|
||||
void *ret;
|
||||
char *real;
|
||||
real = (char *)sAllocFunc(size + sizeof(void *) + (alignment - 1));
|
||||
if (real)
|
||||
{
|
||||
ret = btAlignPointer(real + sizeof(void *), alignment);
|
||||
*((void **)(ret)-1) = (void *)(real);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (void *)(real);
|
||||
}
|
||||
return (ret);
|
||||
void *ret;
|
||||
char *real;
|
||||
real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1));
|
||||
if (real) {
|
||||
ret = btAlignPointer(real + sizeof(void *),alignment);
|
||||
*((void **)(ret)-1) = (void *)(real);
|
||||
} else {
|
||||
ret = (void *)(real);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static inline void btAlignedFreeDefault(void *ptr)
|
||||
{
|
||||
void *real;
|
||||
void* real;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
real = *((void **)(ptr)-1);
|
||||
sFreeFunc(real);
|
||||
}
|
||||
if (ptr) {
|
||||
real = *((void **)(ptr)-1);
|
||||
sFreeFunc(real);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
|
||||
static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
|
||||
|
||||
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
|
||||
{
|
||||
sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
|
||||
sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
|
||||
sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
|
||||
sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
|
||||
}
|
||||
|
||||
void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
|
||||
{
|
||||
sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
|
||||
sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
|
||||
sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
|
||||
sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
|
||||
}
|
||||
|
||||
#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
|
||||
|
|
@ -113,15 +114,15 @@ static int mynumallocs = 0;
|
|||
int btDumpMemoryLeaks()
|
||||
{
|
||||
int totalLeak = 0;
|
||||
|
||||
for (int i = 0; i < mynumallocs; i++)
|
||||
|
||||
for (int i=0;i<mynumallocs;i++)
|
||||
{
|
||||
printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
|
||||
totalLeak += allocations_bytes[i];
|
||||
totalLeak+=allocations_bytes[i];
|
||||
}
|
||||
if (totalLeak)
|
||||
{
|
||||
printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n", mynumallocs, totalLeak);
|
||||
printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n",mynumallocs,totalLeak);
|
||||
}
|
||||
return totalLeak;
|
||||
}
|
||||
|
|
@ -130,134 +131,139 @@ int btDumpMemoryLeaks()
|
|||
|
||||
struct btDebugPtrMagic
|
||||
{
|
||||
union {
|
||||
void **vptrptr;
|
||||
void *vptr;
|
||||
int *iptr;
|
||||
char *cptr;
|
||||
union
|
||||
{
|
||||
void** vptrptr;
|
||||
void* vptr;
|
||||
int* iptr;
|
||||
char* cptr;
|
||||
};
|
||||
};
|
||||
|
||||
void *btAlignedAllocInternal(size_t size, int alignment, int line, char *filename)
|
||||
|
||||
void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
|
||||
{
|
||||
if (size == 0)
|
||||
if (size==0)
|
||||
{
|
||||
printf("Whaat? size==0");
|
||||
return 0;
|
||||
}
|
||||
static int allocId = 0;
|
||||
|
||||
void *ret;
|
||||
char *real;
|
||||
|
||||
void *ret;
|
||||
char *real;
|
||||
// to find some particular memory leak, you could do something like this:
|
||||
// if (allocId==172)
|
||||
// {
|
||||
// printf("catch me!\n");
|
||||
// }
|
||||
// if (size>1024*1024)
|
||||
// {
|
||||
// printf("big alloc!%d\n", size);
|
||||
// }
|
||||
|
||||
// to find some particular memory leak, you could do something like this:
|
||||
// if (allocId==172)
|
||||
// {
|
||||
// printf("catch me!\n");
|
||||
// }
|
||||
// if (size>1024*1024)
|
||||
// {
|
||||
// printf("big alloc!%d\n", size);
|
||||
// }
|
||||
gTotalBytesAlignedAllocs += size;
|
||||
gNumAlignedAllocs++;
|
||||
|
||||
gTotalBytesAlignedAllocs += size;
|
||||
gNumAlignedAllocs++;
|
||||
|
||||
int sz4prt = 4*sizeof(void *);
|
||||
|
||||
real = (char *)sAllocFunc(size + sz4prt + (alignment-1));
|
||||
if (real) {
|
||||
|
||||
ret = (void*) btAlignPointer(real + sz4prt, alignment);
|
||||
btDebugPtrMagic p;
|
||||
p.vptr = ret;
|
||||
p.cptr-=sizeof(void*);
|
||||
*p.vptrptr = (void*)real;
|
||||
p.cptr-=sizeof(void*);
|
||||
*p.iptr = size;
|
||||
p.cptr-=sizeof(void*);
|
||||
*p.iptr = allocId;
|
||||
|
||||
allocations_id[mynumallocs] = allocId;
|
||||
allocations_bytes[mynumallocs] = size;
|
||||
mynumallocs++;
|
||||
|
||||
int sz4prt = 4 * sizeof(void *);
|
||||
} else {
|
||||
ret = (void *)(real);//??
|
||||
}
|
||||
|
||||
real = (char *)sAllocFunc(size + sz4prt + (alignment - 1));
|
||||
if (real)
|
||||
{
|
||||
ret = (void *)btAlignPointer(real + sz4prt, alignment);
|
||||
btDebugPtrMagic p;
|
||||
p.vptr = ret;
|
||||
p.cptr -= sizeof(void *);
|
||||
*p.vptrptr = (void *)real;
|
||||
p.cptr -= sizeof(void *);
|
||||
*p.iptr = size;
|
||||
p.cptr -= sizeof(void *);
|
||||
*p.iptr = allocId;
|
||||
|
||||
allocations_id[mynumallocs] = allocId;
|
||||
allocations_bytes[mynumallocs] = size;
|
||||
mynumallocs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (void *)(real); //??
|
||||
}
|
||||
|
||||
printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs);
|
||||
printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n",allocId,real, filename,line,size,gTotalBytesAlignedAllocs);
|
||||
allocId++;
|
||||
|
||||
int *ptr = (int *)ret;
|
||||
*ptr = 12;
|
||||
return (ret);
|
||||
|
||||
int* ptr = (int*)ret;
|
||||
*ptr = 12;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void btAlignedFreeInternal(void *ptr, int line, char *filename)
|
||||
void btAlignedFreeInternal (void* ptr,int line,char* filename)
|
||||
{
|
||||
void *real;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
gNumAlignedFree++;
|
||||
void* real;
|
||||
|
||||
btDebugPtrMagic p;
|
||||
p.vptr = ptr;
|
||||
p.cptr -= sizeof(void *);
|
||||
real = *p.vptrptr;
|
||||
p.cptr -= sizeof(void *);
|
||||
int size = *p.iptr;
|
||||
p.cptr -= sizeof(void *);
|
||||
int allocId = *p.iptr;
|
||||
if (ptr) {
|
||||
gNumAlignedFree++;
|
||||
|
||||
bool found = false;
|
||||
btDebugPtrMagic p;
|
||||
p.vptr = ptr;
|
||||
p.cptr-=sizeof(void*);
|
||||
real = *p.vptrptr;
|
||||
p.cptr-=sizeof(void*);
|
||||
int size = *p.iptr;
|
||||
p.cptr-=sizeof(void*);
|
||||
int allocId = *p.iptr;
|
||||
|
||||
for (int i = 0; i < mynumallocs; i++)
|
||||
{
|
||||
if (allocations_id[i] == allocId)
|
||||
{
|
||||
allocations_id[i] = allocations_id[mynumallocs - 1];
|
||||
allocations_bytes[i] = allocations_bytes[mynumallocs - 1];
|
||||
mynumallocs--;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool found = false;
|
||||
|
||||
for (int i=0;i<mynumallocs;i++)
|
||||
{
|
||||
if ( allocations_id[i] == allocId)
|
||||
{
|
||||
allocations_id[i] = allocations_id[mynumallocs-1];
|
||||
allocations_bytes[i] = allocations_bytes[mynumallocs-1];
|
||||
mynumallocs--;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gTotalBytesAlignedAllocs -= size;
|
||||
|
||||
gTotalBytesAlignedAllocs -= size;
|
||||
int diff = gNumAlignedAllocs-gNumAlignedFree;
|
||||
printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n",allocId,real, filename,line,size, gTotalBytesAlignedAllocs, diff);
|
||||
|
||||
int diff = gNumAlignedAllocs - gNumAlignedFree;
|
||||
printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs, diff);
|
||||
|
||||
sFreeFunc(real);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("deleting a NULL ptr, no effect\n");
|
||||
}
|
||||
sFreeFunc(real);
|
||||
} else
|
||||
{
|
||||
//printf("deleting a NULL ptr, no effect\n");
|
||||
}
|
||||
}
|
||||
|
||||
#else //BT_DEBUG_MEMORY_ALLOCATIONS
|
||||
#else //BT_DEBUG_MEMORY_ALLOCATIONS
|
||||
|
||||
void *btAlignedAllocInternal(size_t size, int alignment)
|
||||
void* btAlignedAllocInternal (size_t size, int alignment)
|
||||
{
|
||||
void *ptr;
|
||||
gNumAlignedAllocs++;
|
||||
void* ptr;
|
||||
ptr = sAlignedAllocFunc(size, alignment);
|
||||
// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
|
||||
// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void btAlignedFreeInternal(void *ptr)
|
||||
void btAlignedFreeInternal (void* ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// printf("btAlignedFreeInternal %x\n",ptr);
|
||||
gNumAlignedFree++;
|
||||
// printf("btAlignedFreeInternal %x\n",ptr);
|
||||
sAlignedFreeFunc(ptr);
|
||||
}
|
||||
|
||||
#endif //BT_DEBUG_MEMORY_ALLOCATIONS
|
||||
#endif //BT_DEBUG_MEMORY_ALLOCATIONS
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ subject to the following restrictions:
|
|||
|
||||
#include "btScalar.h"
|
||||
|
||||
|
||||
///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
|
||||
///for regression tests to detect memory leaks
|
||||
///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
|
||||
|
|
@ -29,87 +30,84 @@ subject to the following restrictions:
|
|||
|
||||
int btDumpMemoryLeaks();
|
||||
|
||||
#define btAlignedAlloc(a, b) \
|
||||
btAlignedAllocInternal(a, b, __LINE__, __FILE__)
|
||||
#define btAlignedAlloc(a,b) \
|
||||
btAlignedAllocInternal(a,b,__LINE__,__FILE__)
|
||||
|
||||
#define btAlignedFree(ptr) \
|
||||
btAlignedFreeInternal(ptr, __LINE__, __FILE__)
|
||||
btAlignedFreeInternal(ptr,__LINE__,__FILE__)
|
||||
|
||||
void* btAlignedAllocInternal(size_t size, int alignment, int line, char* filename);
|
||||
void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename);
|
||||
|
||||
void btAlignedFreeInternal(void* ptr, int line, char* filename);
|
||||
void btAlignedFreeInternal (void* ptr,int line,char* filename);
|
||||
|
||||
#else
|
||||
void* btAlignedAllocInternal(size_t size, int alignment);
|
||||
void btAlignedFreeInternal(void* ptr);
|
||||
void* btAlignedAllocInternal (size_t size, int alignment);
|
||||
void btAlignedFreeInternal (void* ptr);
|
||||
|
||||
#define btAlignedAlloc(size, alignment) btAlignedAllocInternal(size, alignment)
|
||||
#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
|
||||
#define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment)
|
||||
#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
|
||||
|
||||
#endif
|
||||
typedef int size_type;
|
||||
typedef int size_type;
|
||||
|
||||
typedef void*(btAlignedAllocFunc)(size_t size, int alignment);
|
||||
typedef void(btAlignedFreeFunc)(void* memblock);
|
||||
typedef void*(btAllocFunc)(size_t size);
|
||||
typedef void(btFreeFunc)(void* memblock);
|
||||
typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
|
||||
typedef void (btAlignedFreeFunc)(void *memblock);
|
||||
typedef void *(btAllocFunc)(size_t size);
|
||||
typedef void (btFreeFunc)(void *memblock);
|
||||
|
||||
///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
|
||||
void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc);
|
||||
void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
|
||||
///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
|
||||
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc);
|
||||
void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
|
||||
|
||||
|
||||
///The btAlignedAllocator is a portable class for aligned memory allocations.
|
||||
///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
|
||||
template <typename T, unsigned Alignment>
|
||||
class btAlignedAllocator
|
||||
{
|
||||
typedef btAlignedAllocator<T, Alignment> self_type;
|
||||
|
||||
template < typename T , unsigned Alignment >
|
||||
class btAlignedAllocator {
|
||||
|
||||
typedef btAlignedAllocator< T , Alignment > self_type;
|
||||
|
||||
public:
|
||||
|
||||
//just going down a list:
|
||||
btAlignedAllocator() {}
|
||||
/*
|
||||
btAlignedAllocator( const self_type & ) {}
|
||||
*/
|
||||
|
||||
template <typename Other>
|
||||
btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&)
|
||||
{
|
||||
}
|
||||
template < typename Other >
|
||||
btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {}
|
||||
|
||||
typedef const T* const_pointer;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef T value_type;
|
||||
typedef const T* const_pointer;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef T value_type;
|
||||
|
||||
pointer address(reference ref) const { return &ref; }
|
||||
const_pointer address(const_reference ref) const { return &ref; }
|
||||
pointer allocate(size_type n, const_pointer* hint = 0)
|
||||
{
|
||||
pointer address ( reference ref ) const { return &ref; }
|
||||
const_pointer address ( const_reference ref ) const { return &ref; }
|
||||
pointer allocate ( size_type n , const_pointer * hint = 0 ) {
|
||||
(void)hint;
|
||||
return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
|
||||
return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment ));
|
||||
}
|
||||
void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
|
||||
void deallocate(pointer ptr)
|
||||
{
|
||||
btAlignedFree(reinterpret_cast<void*>(ptr));
|
||||
void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); }
|
||||
void deallocate( pointer ptr ) {
|
||||
btAlignedFree( reinterpret_cast< void * >( ptr ) );
|
||||
}
|
||||
void destroy(pointer ptr) { ptr->~value_type(); }
|
||||
void destroy ( pointer ptr ) { ptr->~value_type(); }
|
||||
|
||||
|
||||
template <typename O>
|
||||
struct rebind
|
||||
{
|
||||
typedef btAlignedAllocator<O, Alignment> other;
|
||||
template < typename O > struct rebind {
|
||||
typedef btAlignedAllocator< O , Alignment > other;
|
||||
};
|
||||
template <typename O>
|
||||
self_type& operator=(const btAlignedAllocator<O, Alignment>&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
template < typename O >
|
||||
self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; }
|
||||
|
||||
friend bool operator==(const self_type&, const self_type&) { return true; }
|
||||
friend bool operator==( const self_type & , const self_type & ) { return true; }
|
||||
};
|
||||
|
||||
#endif //BT_ALIGNED_ALLOCATOR
|
||||
|
||||
|
||||
#endif //BT_ALIGNED_ALLOCATOR
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_OBJECT_ARRAY__
|
||||
#define BT_OBJECT_ARRAY__
|
||||
|
||||
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
|
||||
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
|
||||
#include "btAlignedAllocator.h"
|
||||
|
||||
///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
|
||||
|
|
@ -27,371 +28,394 @@ subject to the following restrictions:
|
|||
|
||||
#define BT_USE_PLACEMENT_NEW 1
|
||||
//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
|
||||
#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
|
||||
#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
|
||||
|
||||
#ifdef BT_USE_MEMCPY
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#endif //BT_USE_MEMCPY
|
||||
#endif //BT_USE_MEMCPY
|
||||
|
||||
#ifdef BT_USE_PLACEMENT_NEW
|
||||
#include <new> //for placement new
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
#include <new> //for placement new
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
|
||||
// The register keyword is deprecated in C++11 so don't use it.
|
||||
#if __cplusplus > 199711L
|
||||
#define BT_REGISTER
|
||||
#else
|
||||
#define BT_REGISTER register
|
||||
#endif
|
||||
|
||||
///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
|
||||
///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
|
||||
template <typename T>
|
||||
//template <class T>
|
||||
template <typename T>
|
||||
//template <class T>
|
||||
class btAlignedObjectArray
|
||||
{
|
||||
btAlignedAllocator<T, 16> m_allocator;
|
||||
btAlignedAllocator<T , 16> m_allocator;
|
||||
|
||||
int m_size;
|
||||
int m_capacity;
|
||||
T* m_data;
|
||||
int m_size;
|
||||
int m_capacity;
|
||||
T* m_data;
|
||||
//PCK: added this line
|
||||
bool m_ownsMemory;
|
||||
bool m_ownsMemory;
|
||||
|
||||
#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
|
||||
public:
|
||||
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
|
||||
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other)
|
||||
{
|
||||
copyFromArray(other);
|
||||
return *this;
|
||||
}
|
||||
#else //BT_ALLOW_ARRAY_COPY_OPERATOR
|
||||
#else//BT_ALLOW_ARRAY_COPY_OPERATOR
|
||||
private:
|
||||
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
|
||||
#endif //BT_ALLOW_ARRAY_COPY_OPERATOR
|
||||
SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T> &other);
|
||||
#endif//BT_ALLOW_ARRAY_COPY_OPERATOR
|
||||
|
||||
protected:
|
||||
SIMD_FORCE_INLINE int allocSize(int size)
|
||||
{
|
||||
return (size ? size * 2 : 1);
|
||||
}
|
||||
SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
|
||||
{
|
||||
int i;
|
||||
for (i = start; i < end; ++i)
|
||||
SIMD_FORCE_INLINE int allocSize(int size)
|
||||
{
|
||||
return (size ? size*2 : 1);
|
||||
}
|
||||
SIMD_FORCE_INLINE void copy(int start,int end, T* dest) const
|
||||
{
|
||||
int i;
|
||||
for (i=start;i<end;++i)
|
||||
#ifdef BT_USE_PLACEMENT_NEW
|
||||
new (&dest[i]) T(m_data[i]);
|
||||
new (&dest[i]) T(m_data[i]);
|
||||
#else
|
||||
dest[i] = m_data[i];
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void init()
|
||||
{
|
||||
//PCK: added this line
|
||||
m_ownsMemory = true;
|
||||
m_data = 0;
|
||||
m_size = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
SIMD_FORCE_INLINE void destroy(int first, int last)
|
||||
{
|
||||
int i;
|
||||
for (i = first; i < last; i++)
|
||||
{
|
||||
m_data[i].~T();
|
||||
dest[i] = m_data[i];
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
}
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void* allocate(int size)
|
||||
{
|
||||
if (size)
|
||||
return m_allocator.allocate(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void deallocate()
|
||||
{
|
||||
if (m_data)
|
||||
SIMD_FORCE_INLINE void init()
|
||||
{
|
||||
//PCK: enclosed the deallocation in this block
|
||||
if (m_ownsMemory)
|
||||
{
|
||||
m_allocator.deallocate(m_data);
|
||||
}
|
||||
//PCK: added this line
|
||||
m_ownsMemory = true;
|
||||
m_data = 0;
|
||||
m_size = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
btAlignedObjectArray()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
~btAlignedObjectArray()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
|
||||
btAlignedObjectArray(const btAlignedObjectArray& otherArray)
|
||||
{
|
||||
init();
|
||||
|
||||
int otherSize = otherArray.size();
|
||||
resize(otherSize);
|
||||
otherArray.copy(0, otherSize, m_data);
|
||||
}
|
||||
|
||||
/// return the number of elements in the array
|
||||
SIMD_FORCE_INLINE int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const T& at(int n) const
|
||||
{
|
||||
btAssert(n >= 0);
|
||||
btAssert(n < size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE T& at(int n)
|
||||
{
|
||||
btAssert(n >= 0);
|
||||
btAssert(n < size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const T& operator[](int n) const
|
||||
{
|
||||
btAssert(n >= 0);
|
||||
btAssert(n < size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE T& operator[](int n)
|
||||
{
|
||||
btAssert(n >= 0);
|
||||
btAssert(n < size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
|
||||
SIMD_FORCE_INLINE void clear()
|
||||
{
|
||||
destroy(0, size());
|
||||
|
||||
deallocate();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void pop_back()
|
||||
{
|
||||
btAssert(m_size > 0);
|
||||
m_size--;
|
||||
m_data[m_size].~T();
|
||||
}
|
||||
|
||||
///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
|
||||
///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
|
||||
SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
|
||||
{
|
||||
if (newsize > size())
|
||||
SIMD_FORCE_INLINE void destroy(int first,int last)
|
||||
{
|
||||
reserve(newsize);
|
||||
}
|
||||
m_size = newsize;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
|
||||
{
|
||||
const int curSize = size();
|
||||
|
||||
if (newsize < curSize)
|
||||
{
|
||||
for (int i = newsize; i < curSize; i++)
|
||||
int i;
|
||||
for (i=first; i<last;i++)
|
||||
{
|
||||
m_data[i].~T();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
SIMD_FORCE_INLINE void* allocate(int size)
|
||||
{
|
||||
if (newsize > curSize)
|
||||
if (size)
|
||||
return m_allocator.allocate(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void deallocate()
|
||||
{
|
||||
if(m_data) {
|
||||
//PCK: enclosed the deallocation in this block
|
||||
if (m_ownsMemory)
|
||||
{
|
||||
m_allocator.deallocate(m_data);
|
||||
}
|
||||
m_data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
btAlignedObjectArray()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
~btAlignedObjectArray()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
|
||||
btAlignedObjectArray(const btAlignedObjectArray& otherArray)
|
||||
{
|
||||
init();
|
||||
|
||||
int otherSize = otherArray.size();
|
||||
resize (otherSize);
|
||||
otherArray.copy(0, otherSize, m_data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// return the number of elements in the array
|
||||
SIMD_FORCE_INLINE int size() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const T& at(int n) const
|
||||
{
|
||||
btAssert(n>=0);
|
||||
btAssert(n<size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE T& at(int n)
|
||||
{
|
||||
btAssert(n>=0);
|
||||
btAssert(n<size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE const T& operator[](int n) const
|
||||
{
|
||||
btAssert(n>=0);
|
||||
btAssert(n<size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE T& operator[](int n)
|
||||
{
|
||||
btAssert(n>=0);
|
||||
btAssert(n<size());
|
||||
return m_data[n];
|
||||
}
|
||||
|
||||
|
||||
///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
|
||||
SIMD_FORCE_INLINE void clear()
|
||||
{
|
||||
destroy(0,size());
|
||||
|
||||
deallocate();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void pop_back()
|
||||
{
|
||||
btAssert(m_size>0);
|
||||
m_size--;
|
||||
m_data[m_size].~T();
|
||||
}
|
||||
|
||||
|
||||
///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
|
||||
///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
|
||||
SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
|
||||
{
|
||||
if (newsize > size())
|
||||
{
|
||||
reserve(newsize);
|
||||
}
|
||||
#ifdef BT_USE_PLACEMENT_NEW
|
||||
for (int i = curSize; i < newsize; i++)
|
||||
m_size = newsize;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void resize(int newsize, const T& fillData=T())
|
||||
{
|
||||
const BT_REGISTER int curSize = size();
|
||||
|
||||
if (newsize < curSize)
|
||||
{
|
||||
new (&m_data[i]) T(fillData);
|
||||
}
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
}
|
||||
|
||||
m_size = newsize;
|
||||
}
|
||||
SIMD_FORCE_INLINE T& expandNonInitializing()
|
||||
{
|
||||
const int sz = size();
|
||||
if (sz == capacity())
|
||||
{
|
||||
reserve(allocSize(size()));
|
||||
}
|
||||
m_size++;
|
||||
|
||||
return m_data[sz];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
|
||||
{
|
||||
const int sz = size();
|
||||
if (sz == capacity())
|
||||
{
|
||||
reserve(allocSize(size()));
|
||||
}
|
||||
m_size++;
|
||||
for(int i = newsize; i < curSize; i++)
|
||||
{
|
||||
m_data[i].~T();
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (newsize > curSize)
|
||||
{
|
||||
reserve(newsize);
|
||||
}
|
||||
#ifdef BT_USE_PLACEMENT_NEW
|
||||
new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
|
||||
for (int i=curSize;i<newsize;i++)
|
||||
{
|
||||
new ( &m_data[i]) T(fillData);
|
||||
}
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
|
||||
}
|
||||
|
||||
m_size = newsize;
|
||||
}
|
||||
SIMD_FORCE_INLINE T& expandNonInitializing( )
|
||||
{
|
||||
const BT_REGISTER int sz = size();
|
||||
if( sz == capacity() )
|
||||
{
|
||||
reserve( allocSize(size()) );
|
||||
}
|
||||
m_size++;
|
||||
|
||||
return m_data[sz];
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE T& expand( const T& fillValue=T())
|
||||
{
|
||||
const BT_REGISTER int sz = size();
|
||||
if( sz == capacity() )
|
||||
{
|
||||
reserve( allocSize(size()) );
|
||||
}
|
||||
m_size++;
|
||||
#ifdef BT_USE_PLACEMENT_NEW
|
||||
new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
|
||||
#endif
|
||||
|
||||
return m_data[sz];
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void push_back(const T& _Val)
|
||||
{
|
||||
const int sz = size();
|
||||
if (sz == capacity())
|
||||
{
|
||||
reserve(allocSize(size()));
|
||||
return m_data[sz];
|
||||
}
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void push_back(const T& _Val)
|
||||
{
|
||||
const BT_REGISTER int sz = size();
|
||||
if( sz == capacity() )
|
||||
{
|
||||
reserve( allocSize(size()) );
|
||||
}
|
||||
|
||||
#ifdef BT_USE_PLACEMENT_NEW
|
||||
new (&m_data[m_size]) T(_Val);
|
||||
new ( &m_data[m_size] ) T(_Val);
|
||||
#else
|
||||
m_data[size()] = _Val;
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
m_data[size()] = _Val;
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
|
||||
m_size++;
|
||||
}
|
||||
|
||||
/// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
|
||||
SIMD_FORCE_INLINE int capacity() const
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void reserve(int _Count)
|
||||
{ // determine new minimum length of allocated storage
|
||||
if (capacity() < _Count)
|
||||
{ // not enough room, reallocate
|
||||
T* s = (T*)allocate(_Count);
|
||||
|
||||
copy(0, size(), s);
|
||||
|
||||
destroy(0, size());
|
||||
|
||||
deallocate();
|
||||
|
||||
//PCK: added this line
|
||||
m_ownsMemory = true;
|
||||
|
||||
m_data = s;
|
||||
|
||||
m_capacity = _Count;
|
||||
m_size++;
|
||||
}
|
||||
}
|
||||
|
||||
class less
|
||||
{
|
||||
public:
|
||||
bool operator()(const T& a, const T& b) const
|
||||
|
||||
/// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
|
||||
SIMD_FORCE_INLINE int capacity() const
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void reserve(int _Count)
|
||||
{ // determine new minimum length of allocated storage
|
||||
if (capacity() < _Count)
|
||||
{ // not enough room, reallocate
|
||||
T* s = (T*)allocate(_Count);
|
||||
|
||||
copy(0, size(), s);
|
||||
|
||||
destroy(0,size());
|
||||
|
||||
deallocate();
|
||||
|
||||
//PCK: added this line
|
||||
m_ownsMemory = true;
|
||||
|
||||
m_data = s;
|
||||
|
||||
m_capacity = _Count;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class less
|
||||
{
|
||||
return (a < b);
|
||||
}
|
||||
};
|
||||
public:
|
||||
|
||||
template <typename L>
|
||||
void quickSortInternal(const L& CompareFunc, int lo, int hi)
|
||||
{
|
||||
bool operator() ( const T& a, const T& b ) const
|
||||
{
|
||||
return ( a < b );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename L>
|
||||
void quickSortInternal(const L& CompareFunc,int lo, int hi)
|
||||
{
|
||||
// lo is the lower index, hi is the upper index
|
||||
// of the region of array a that is to be sorted
|
||||
int i = lo, j = hi;
|
||||
T x = m_data[(lo + hi) / 2];
|
||||
int i=lo, j=hi;
|
||||
T x=m_data[(lo+hi)/2];
|
||||
|
||||
// partition
|
||||
do
|
||||
{
|
||||
while (CompareFunc(m_data[i], x))
|
||||
i++;
|
||||
while (CompareFunc(x, m_data[j]))
|
||||
j--;
|
||||
if (i <= j)
|
||||
{
|
||||
swap(i, j);
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
} while (i <= j);
|
||||
// partition
|
||||
do
|
||||
{
|
||||
while (CompareFunc(m_data[i],x))
|
||||
i++;
|
||||
while (CompareFunc(x,m_data[j]))
|
||||
j--;
|
||||
if (i<=j)
|
||||
{
|
||||
swap(i,j);
|
||||
i++; j--;
|
||||
}
|
||||
} while (i<=j);
|
||||
|
||||
// recursion
|
||||
if (lo < j)
|
||||
quickSortInternal(CompareFunc, lo, j);
|
||||
if (i < hi)
|
||||
quickSortInternal(CompareFunc, i, hi);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
void quickSort(const L& CompareFunc)
|
||||
{
|
||||
//don't sort 0 or 1 elements
|
||||
if (size() > 1)
|
||||
{
|
||||
quickSortInternal(CompareFunc, 0, size() - 1);
|
||||
// recursion
|
||||
if (lo<j)
|
||||
quickSortInternal( CompareFunc, lo, j);
|
||||
if (i<hi)
|
||||
quickSortInternal( CompareFunc, i, hi);
|
||||
}
|
||||
}
|
||||
|
||||
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
|
||||
template <typename L>
|
||||
void downHeap(T* pArr, int k, int n, const L& CompareFunc)
|
||||
{
|
||||
/* PRE: a[k+1..N] is a heap */
|
||||
/* POST: a[k..N] is a heap */
|
||||
|
||||
T temp = pArr[k - 1];
|
||||
/* k has child(s) */
|
||||
while (k <= n / 2)
|
||||
template <typename L>
|
||||
void quickSort(const L& CompareFunc)
|
||||
{
|
||||
int child = 2 * k;
|
||||
|
||||
if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
|
||||
//don't sort 0 or 1 elements
|
||||
if (size()>1)
|
||||
{
|
||||
child++;
|
||||
}
|
||||
/* pick larger child */
|
||||
if (CompareFunc(temp, pArr[child - 1]))
|
||||
{
|
||||
/* move child up */
|
||||
pArr[k - 1] = pArr[child - 1];
|
||||
k = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
quickSortInternal(CompareFunc,0,size()-1);
|
||||
}
|
||||
}
|
||||
pArr[k - 1] = temp;
|
||||
} /*downHeap*/
|
||||
|
||||
void swap(int index0, int index1)
|
||||
{
|
||||
|
||||
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
|
||||
template <typename L>
|
||||
void downHeap(T *pArr, int k, int n, const L& CompareFunc)
|
||||
{
|
||||
/* PRE: a[k+1..N] is a heap */
|
||||
/* POST: a[k..N] is a heap */
|
||||
|
||||
T temp = pArr[k - 1];
|
||||
/* k has child(s) */
|
||||
while (k <= n/2)
|
||||
{
|
||||
int child = 2*k;
|
||||
|
||||
if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
|
||||
{
|
||||
child++;
|
||||
}
|
||||
/* pick larger child */
|
||||
if (CompareFunc(temp , pArr[child - 1]))
|
||||
{
|
||||
/* move child up */
|
||||
pArr[k - 1] = pArr[child - 1];
|
||||
k = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
pArr[k - 1] = temp;
|
||||
} /*downHeap*/
|
||||
|
||||
void swap(int index0,int index1)
|
||||
{
|
||||
#ifdef BT_USE_MEMCPY
|
||||
char temp[sizeof(T)];
|
||||
memcpy(temp, &m_data[index0], sizeof(T));
|
||||
memcpy(&m_data[index0], &m_data[index1], sizeof(T));
|
||||
memcpy(&m_data[index1], temp, sizeof(T));
|
||||
char temp[sizeof(T)];
|
||||
memcpy(temp,&m_data[index0],sizeof(T));
|
||||
memcpy(&m_data[index0],&m_data[index1],sizeof(T));
|
||||
memcpy(&m_data[index1],temp,sizeof(T));
|
||||
#else
|
||||
T temp = m_data[index0];
|
||||
m_data[index0] = m_data[index1];
|
||||
m_data[index1] = temp;
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
}
|
||||
T temp = m_data[index0];
|
||||
m_data[index0] = m_data[index1];
|
||||
m_data[index1] = temp;
|
||||
#endif //BT_USE_PLACEMENT_NEW
|
||||
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
void heapSort(const L& CompareFunc)
|
||||
|
|
@ -399,48 +423,49 @@ public:
|
|||
/* sort a[0..N-1], N.B. 0 to N-1 */
|
||||
int k;
|
||||
int n = m_size;
|
||||
for (k = n / 2; k > 0; k--)
|
||||
for (k = n/2; k > 0; k--)
|
||||
{
|
||||
downHeap(m_data, k, n, CompareFunc);
|
||||
}
|
||||
|
||||
/* a[1..N] is now a heap */
|
||||
while (n >= 1)
|
||||
while ( n>=1 )
|
||||
{
|
||||
swap(0, n - 1); /* largest of a[0..n-1] */
|
||||
swap(0,n-1); /* largest of a[0..n-1] */
|
||||
|
||||
|
||||
n = n - 1;
|
||||
/* restore a[1..i-1] heap */
|
||||
downHeap(m_data, 1, n, CompareFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///non-recursive binary search, assumes sorted array
|
||||
int findBinarySearch(const T& key) const
|
||||
int findBinarySearch(const T& key) const
|
||||
{
|
||||
int first = 0;
|
||||
int last = size() - 1;
|
||||
int last = size()-1;
|
||||
|
||||
//assume sorted array
|
||||
while (first <= last)
|
||||
{
|
||||
while (first <= last) {
|
||||
int mid = (first + last) / 2; // compute mid point.
|
||||
if (key > m_data[mid])
|
||||
if (key > m_data[mid])
|
||||
first = mid + 1; // repeat search in top half.
|
||||
else if (key < m_data[mid])
|
||||
last = mid - 1; // repeat search in bottom half.
|
||||
else if (key < m_data[mid])
|
||||
last = mid - 1; // repeat search in bottom half.
|
||||
else
|
||||
return mid; // found it. return position /////
|
||||
return mid; // found it. return position /////
|
||||
}
|
||||
return size(); // failed to find key
|
||||
return size(); // failed to find key
|
||||
}
|
||||
|
||||
int findLinearSearch(const T& key) const
|
||||
|
||||
int findLinearSearch(const T& key) const
|
||||
{
|
||||
int index = size();
|
||||
int index=size();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size(); i++)
|
||||
for (i=0;i<size();i++)
|
||||
{
|
||||
if (m_data[i] == key)
|
||||
{
|
||||
|
|
@ -450,41 +475,41 @@ public:
|
|||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the key is not in the array, return -1 instead of 0,
|
||||
// since 0 also means the first element in the array.
|
||||
int findLinearSearch2(const T& key) const
|
||||
{
|
||||
int index=-1;
|
||||
int i;
|
||||
|
||||
for (i=0;i<size();i++)
|
||||
{
|
||||
if (m_data[i] == key)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// If the key is not in the array, return -1 instead of 0,
|
||||
// since 0 also means the first element in the array.
|
||||
int findLinearSearch2(const T& key) const
|
||||
{
|
||||
int index = -1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size(); i++)
|
||||
{
|
||||
if (m_data[i] == key)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void removeAtIndex(int index)
|
||||
{
|
||||
if (index < size())
|
||||
{
|
||||
swap(index, size() - 1);
|
||||
pop_back();
|
||||
}
|
||||
}
|
||||
void remove(const T& key)
|
||||
void removeAtIndex(int index)
|
||||
{
|
||||
if (index<size())
|
||||
{
|
||||
swap( index,size()-1);
|
||||
pop_back();
|
||||
}
|
||||
}
|
||||
void remove(const T& key)
|
||||
{
|
||||
int findIndex = findLinearSearch(key);
|
||||
removeAtIndex(findIndex);
|
||||
removeAtIndex(findIndex);
|
||||
}
|
||||
|
||||
//PCK: whole function
|
||||
void initializeFromBuffer(void* buffer, int size, int capacity)
|
||||
void initializeFromBuffer(void *buffer, int size, int capacity)
|
||||
{
|
||||
clear();
|
||||
m_ownsMemory = false;
|
||||
|
|
@ -496,9 +521,10 @@ public:
|
|||
void copyFromArray(const btAlignedObjectArray& otherArray)
|
||||
{
|
||||
int otherSize = otherArray.size();
|
||||
resize(otherSize);
|
||||
resize (otherSize);
|
||||
otherArray.copy(0, otherSize, m_data);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_OBJECT_ARRAY__
|
||||
#endif //BT_OBJECT_ARRAY__
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -34,102 +34,106 @@ public:
|
|||
mNumFaces = 0;
|
||||
mNumIndices = 0;
|
||||
}
|
||||
bool mPolygons; // true if indices represents polygons, false indices are triangles
|
||||
unsigned int mNumOutputVertices; // number of vertices in the output hull
|
||||
btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
|
||||
unsigned int mNumFaces; // the number of faces produced
|
||||
unsigned int mNumIndices; // the total number of indices
|
||||
btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
|
||||
bool mPolygons; // true if indices represents polygons, false indices are triangles
|
||||
unsigned int mNumOutputVertices; // number of vertices in the output hull
|
||||
btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
|
||||
unsigned int mNumFaces; // the number of faces produced
|
||||
unsigned int mNumIndices; // the total number of indices
|
||||
btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
|
||||
|
||||
// If triangles, then indices are array indexes into the vertex list.
|
||||
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
|
||||
// If triangles, then indices are array indexes into the vertex list.
|
||||
// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
|
||||
};
|
||||
|
||||
enum HullFlag
|
||||
{
|
||||
QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
|
||||
QF_REVERSE_ORDER = (1 << 1), // reverse order of the triangle indices.
|
||||
QF_DEFAULT = QF_TRIANGLES
|
||||
QF_TRIANGLES = (1<<0), // report results as triangles, not polygons.
|
||||
QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices.
|
||||
QF_DEFAULT = QF_TRIANGLES
|
||||
};
|
||||
|
||||
|
||||
class HullDesc
|
||||
{
|
||||
public:
|
||||
HullDesc(void)
|
||||
{
|
||||
mFlags = QF_DEFAULT;
|
||||
mVcount = 0;
|
||||
mVertices = 0;
|
||||
mVertexStride = sizeof(btVector3);
|
||||
mNormalEpsilon = 0.001f;
|
||||
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
|
||||
mMaxFaces = 4096;
|
||||
mFlags = QF_DEFAULT;
|
||||
mVcount = 0;
|
||||
mVertices = 0;
|
||||
mVertexStride = sizeof(btVector3);
|
||||
mNormalEpsilon = 0.001f;
|
||||
mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
|
||||
mMaxFaces = 4096;
|
||||
};
|
||||
|
||||
HullDesc(HullFlag flag,
|
||||
unsigned int vcount,
|
||||
const btVector3* vertices,
|
||||
unsigned int stride = sizeof(btVector3))
|
||||
unsigned int vcount,
|
||||
const btVector3 *vertices,
|
||||
unsigned int stride = sizeof(btVector3))
|
||||
{
|
||||
mFlags = flag;
|
||||
mVcount = vcount;
|
||||
mVertices = vertices;
|
||||
mVertexStride = stride;
|
||||
mNormalEpsilon = btScalar(0.001);
|
||||
mMaxVertices = 4096;
|
||||
mFlags = flag;
|
||||
mVcount = vcount;
|
||||
mVertices = vertices;
|
||||
mVertexStride = stride;
|
||||
mNormalEpsilon = btScalar(0.001);
|
||||
mMaxVertices = 4096;
|
||||
}
|
||||
|
||||
bool HasHullFlag(HullFlag flag) const
|
||||
{
|
||||
if (mFlags & flag) return true;
|
||||
if ( mFlags & flag ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetHullFlag(HullFlag flag)
|
||||
{
|
||||
mFlags |= flag;
|
||||
mFlags|=flag;
|
||||
}
|
||||
|
||||
void ClearHullFlag(HullFlag flag)
|
||||
{
|
||||
mFlags &= ~flag;
|
||||
mFlags&=~flag;
|
||||
}
|
||||
|
||||
unsigned int mFlags; // flags to use when generating the convex hull.
|
||||
unsigned int mVcount; // number of vertices in the input point cloud
|
||||
const btVector3* mVertices; // the array of vertices.
|
||||
unsigned int mVertexStride; // the stride of each vertex, in bytes.
|
||||
btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
|
||||
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
|
||||
unsigned int mMaxFaces;
|
||||
unsigned int mFlags; // flags to use when generating the convex hull.
|
||||
unsigned int mVcount; // number of vertices in the input point cloud
|
||||
const btVector3 *mVertices; // the array of vertices.
|
||||
unsigned int mVertexStride; // the stride of each vertex, in bytes.
|
||||
btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
|
||||
unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
|
||||
unsigned int mMaxFaces;
|
||||
};
|
||||
|
||||
enum HullError
|
||||
{
|
||||
QE_OK, // success!
|
||||
QE_FAIL // failed.
|
||||
QE_OK, // success!
|
||||
QE_FAIL // failed.
|
||||
};
|
||||
|
||||
class btPlane
|
||||
{
|
||||
public:
|
||||
btVector3 normal;
|
||||
btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
|
||||
btPlane(const btVector3& n, btScalar d) : normal(n), dist(d) {}
|
||||
btPlane() : normal(), dist(0) {}
|
||||
public:
|
||||
btVector3 normal;
|
||||
btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
|
||||
btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
|
||||
btPlane():normal(),dist(0){}
|
||||
|
||||
};
|
||||
|
||||
class ConvexH
|
||||
|
||||
|
||||
class ConvexH
|
||||
{
|
||||
public:
|
||||
public:
|
||||
class HalfEdge
|
||||
{
|
||||
public:
|
||||
public:
|
||||
short ea; // the other half of the edge (index into edges list)
|
||||
unsigned char v; // the vertex at the start of this edge (index into vertices list)
|
||||
unsigned char p; // the facet on which this edge lies (index into facets list)
|
||||
HalfEdge() {}
|
||||
HalfEdge(short _ea, unsigned char _v, unsigned char _p) : ea(_ea), v(_v), p(_p) {}
|
||||
HalfEdge(){}
|
||||
HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
|
||||
};
|
||||
ConvexH()
|
||||
{
|
||||
|
|
@ -139,29 +143,25 @@ public:
|
|||
}
|
||||
btAlignedObjectArray<btVector3> vertices;
|
||||
btAlignedObjectArray<HalfEdge> edges;
|
||||
btAlignedObjectArray<btPlane> facets;
|
||||
ConvexH(int vertices_size, int edges_size, int facets_size);
|
||||
btAlignedObjectArray<btPlane> facets;
|
||||
ConvexH(int vertices_size,int edges_size,int facets_size);
|
||||
};
|
||||
|
||||
|
||||
class int4
|
||||
{
|
||||
public:
|
||||
int x, y, z, w;
|
||||
int x,y,z,w;
|
||||
int4(){};
|
||||
int4(int _x, int _y, int _z, int _w)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
w = _w;
|
||||
}
|
||||
const int& operator[](int i) const { return (&x)[i]; }
|
||||
int& operator[](int i) { return (&x)[i]; }
|
||||
int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
|
||||
const int& operator[](int i) const {return (&x)[i];}
|
||||
int& operator[](int i) {return (&x)[i];}
|
||||
};
|
||||
|
||||
class PHullResult
|
||||
{
|
||||
public:
|
||||
|
||||
PHullResult(void)
|
||||
{
|
||||
mVcount = 0;
|
||||
|
|
@ -173,61 +173,69 @@ public:
|
|||
unsigned int mVcount;
|
||||
unsigned int mIndexCount;
|
||||
unsigned int mFaceCount;
|
||||
btVector3* mVertices;
|
||||
btVector3* mVertices;
|
||||
TUIntArray m_Indices;
|
||||
};
|
||||
|
||||
|
||||
|
||||
///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
|
||||
///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
|
||||
class HullLibrary
|
||||
{
|
||||
|
||||
btAlignedObjectArray<class btHullTriangle*> m_tris;
|
||||
|
||||
public:
|
||||
|
||||
btAlignedObjectArray<int> m_vertexIndexMapping;
|
||||
|
||||
HullError CreateConvexHull(const HullDesc& desc, // describes the input request
|
||||
HullResult& result); // contains the resulst
|
||||
HullError ReleaseResult(HullResult& result); // release memory allocated for this result, we are done with it.
|
||||
|
||||
HullError CreateConvexHull(const HullDesc& desc, // describes the input request
|
||||
HullResult& result); // contains the resulst
|
||||
HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
|
||||
|
||||
private:
|
||||
bool ComputeHull(unsigned int vcount, const btVector3* vertices, PHullResult& result, unsigned int vlimit);
|
||||
|
||||
class btHullTriangle* allocateTriangle(int a, int b, int c);
|
||||
void deAllocateTriangle(btHullTriangle*);
|
||||
void b2bfix(btHullTriangle* s, btHullTriangle* t);
|
||||
bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
|
||||
|
||||
void removeb2b(btHullTriangle* s, btHullTriangle* t);
|
||||
class btHullTriangle* allocateTriangle(int a,int b,int c);
|
||||
void deAllocateTriangle(btHullTriangle*);
|
||||
void b2bfix(btHullTriangle* s,btHullTriangle*t);
|
||||
|
||||
void checkit(btHullTriangle* t);
|
||||
void removeb2b(btHullTriangle* s,btHullTriangle*t);
|
||||
|
||||
void checkit(btHullTriangle *t);
|
||||
|
||||
btHullTriangle* extrudable(btScalar epsilon);
|
||||
|
||||
int calchull(btVector3* verts, int verts_count, TUIntArray& tris_out, int& tris_count, int vlimit);
|
||||
int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
|
||||
|
||||
int calchullgen(btVector3* verts, int verts_count, int vlimit);
|
||||
int calchullgen(btVector3 *verts,int verts_count, int vlimit);
|
||||
|
||||
int4 FindSimplex(btVector3* verts, int verts_count, btAlignedObjectArray<int>& allow);
|
||||
int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
|
||||
|
||||
class ConvexH* ConvexHCrop(ConvexH& convex, const btPlane& slice);
|
||||
class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
|
||||
|
||||
void extrude(class btHullTriangle* t0, int v);
|
||||
void extrude(class btHullTriangle* t0,int v);
|
||||
|
||||
ConvexH* test_cube();
|
||||
|
||||
//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
|
||||
//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
|
||||
//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
|
||||
//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
|
||||
//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
|
||||
void BringOutYourDead(const btVector3* verts, unsigned int vcount, btVector3* overts, unsigned int& ocount, unsigned int* indices, unsigned indexcount);
|
||||
void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
|
||||
|
||||
bool CleanupVertices(unsigned int svcount,
|
||||
const btVector3* svertices,
|
||||
unsigned int stride,
|
||||
unsigned int& vcount, // output number of vertices
|
||||
btVector3* vertices, // location to store the results.
|
||||
btScalar normalepsilon,
|
||||
btVector3& scale);
|
||||
const btVector3* svertices,
|
||||
unsigned int stride,
|
||||
unsigned int &vcount, // output number of vertices
|
||||
btVector3* vertices, // location to store the results.
|
||||
btScalar normalepsilon,
|
||||
btVector3& scale);
|
||||
};
|
||||
|
||||
#endif //BT_CD_HULL_H
|
||||
|
||||
#endif //BT_CD_HULL_H
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -23,56 +23,58 @@ subject to the following restrictions:
|
|||
/// Ole Kniemeyer, MAXON Computer GmbH
|
||||
class btConvexHullComputer
|
||||
{
|
||||
private:
|
||||
btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
|
||||
|
||||
public:
|
||||
class Edge
|
||||
{
|
||||
private:
|
||||
int next;
|
||||
int reverse;
|
||||
int targetVertex;
|
||||
|
||||
friend class btConvexHullComputer;
|
||||
btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
|
||||
|
||||
public:
|
||||
int getSourceVertex() const
|
||||
|
||||
class Edge
|
||||
{
|
||||
return (this + reverse)->targetVertex;
|
||||
}
|
||||
private:
|
||||
int next;
|
||||
int reverse;
|
||||
int targetVertex;
|
||||
|
||||
int getTargetVertex() const
|
||||
{
|
||||
return targetVertex;
|
||||
}
|
||||
friend class btConvexHullComputer;
|
||||
|
||||
const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
|
||||
{
|
||||
return this + next;
|
||||
}
|
||||
public:
|
||||
int getSourceVertex() const
|
||||
{
|
||||
return (this + reverse)->targetVertex;
|
||||
}
|
||||
|
||||
const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
|
||||
{
|
||||
return (this + reverse)->getNextEdgeOfVertex();
|
||||
}
|
||||
int getTargetVertex() const
|
||||
{
|
||||
return targetVertex;
|
||||
}
|
||||
|
||||
const Edge* getReverseEdge() const
|
||||
{
|
||||
return this + reverse;
|
||||
}
|
||||
};
|
||||
const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
|
||||
{
|
||||
return this + next;
|
||||
}
|
||||
|
||||
// Vertices of the output hull
|
||||
btAlignedObjectArray<btVector3> vertices;
|
||||
const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
|
||||
{
|
||||
return (this + reverse)->getNextEdgeOfVertex();
|
||||
}
|
||||
|
||||
// Edges of the output hull
|
||||
btAlignedObjectArray<Edge> edges;
|
||||
const Edge* getReverseEdge() const
|
||||
{
|
||||
return this + reverse;
|
||||
}
|
||||
};
|
||||
|
||||
// Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
|
||||
btAlignedObjectArray<int> faces;
|
||||
|
||||
/*
|
||||
// Vertices of the output hull
|
||||
btAlignedObjectArray<btVector3> vertices;
|
||||
|
||||
// Edges of the output hull
|
||||
btAlignedObjectArray<Edge> edges;
|
||||
|
||||
// Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
|
||||
btAlignedObjectArray<int> faces;
|
||||
|
||||
/*
|
||||
Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
|
||||
between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
|
||||
by that amount (each face is moved by "shrink" length units towards the center along its normal).
|
||||
|
|
@ -84,16 +86,18 @@ public:
|
|||
|
||||
The output convex hull can be found in the member variables "vertices", "edges", "faces".
|
||||
*/
|
||||
btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
|
||||
{
|
||||
return compute(coords, false, stride, count, shrink, shrinkClamp);
|
||||
}
|
||||
btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
|
||||
{
|
||||
return compute(coords, false, stride, count, shrink, shrinkClamp);
|
||||
}
|
||||
|
||||
// same as above, but double precision
|
||||
btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
|
||||
{
|
||||
return compute(coords, true, stride, count, shrink, shrinkClamp);
|
||||
}
|
||||
// same as above, but double precision
|
||||
btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
|
||||
{
|
||||
return compute(coords, true, stride, count, shrink, shrinkClamp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //BT_CONVEX_HULL_COMPUTER_H
|
||||
|
||||
#endif //BT_CONVEX_HULL_COMPUTER_H
|
||||
|
||||
|
|
|
|||
|
|
@ -4,20 +4,20 @@
|
|||
|
||||
#include "LinearMath/btScalar.h"
|
||||
|
||||
#include <string.h> //memset
|
||||
#ifdef USE_SIMD
|
||||
#include <string.h>//memset
|
||||
#ifdef USE_SIMD
|
||||
#include <emmintrin.h>
|
||||
#ifdef BT_ALLOW_SSE4
|
||||
#include <intrin.h>
|
||||
#endif //BT_ALLOW_SSE4
|
||||
#endif //USE_SIMD
|
||||
#endif //BT_ALLOW_SSE4
|
||||
#endif //USE_SIMD
|
||||
|
||||
#if defined BT_USE_NEON
|
||||
#define ARM_NEON_GCC_COMPATIBILITY 1
|
||||
#define ARM_NEON_GCC_COMPATIBILITY 1
|
||||
#include <arm_neon.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h> //for sysctlbyname
|
||||
#endif //BT_USE_NEON
|
||||
#include <sys/sysctl.h> //for sysctlbyname
|
||||
#endif //BT_USE_NEON
|
||||
|
||||
///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP)
|
||||
///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h
|
||||
|
|
@ -26,13 +26,14 @@ class btCpuFeatureUtility
|
|||
public:
|
||||
enum btCpuFeature
|
||||
{
|
||||
CPU_FEATURE_FMA3 = 1,
|
||||
CPU_FEATURE_SSE4_1 = 2,
|
||||
CPU_FEATURE_NEON_HPFP = 4
|
||||
CPU_FEATURE_FMA3=1,
|
||||
CPU_FEATURE_SSE4_1=2,
|
||||
CPU_FEATURE_NEON_HPFP=4
|
||||
};
|
||||
|
||||
static int getCpuFeatures()
|
||||
{
|
||||
|
||||
static int capabilities = 0;
|
||||
static bool testedCapabilities = false;
|
||||
if (0 != testedCapabilities)
|
||||
|
|
@ -48,15 +49,15 @@ public:
|
|||
if (0 == err && hasFeature)
|
||||
capabilities |= CPU_FEATURE_NEON_HPFP;
|
||||
}
|
||||
#endif //BT_USE_NEON
|
||||
#endif //BT_USE_NEON
|
||||
|
||||
#ifdef BT_ALLOW_SSE4
|
||||
#ifdef BT_ALLOW_SSE4
|
||||
{
|
||||
int cpuInfo[4];
|
||||
int cpuInfo[4];
|
||||
memset(cpuInfo, 0, sizeof(cpuInfo));
|
||||
unsigned long long sseExt = 0;
|
||||
unsigned long long sseExt = 0;
|
||||
__cpuid(cpuInfo, 1);
|
||||
|
||||
|
||||
bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
|
||||
bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
|
||||
|
||||
|
|
@ -78,11 +79,14 @@ public:
|
|||
capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1;
|
||||
}
|
||||
}
|
||||
#endif //BT_ALLOW_SSE4
|
||||
#endif//BT_ALLOW_SSE4
|
||||
|
||||
testedCapabilities = true;
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_CPU_UTILITY_H
|
||||
|
||||
#endif //BT_CPU_UTILITY_H
|
||||
|
|
|
|||
|
|
@ -4,37 +4,39 @@
|
|||
#include "btMotionState.h"
|
||||
|
||||
///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
|
||||
ATTRIBUTE_ALIGNED16(struct)
|
||||
btDefaultMotionState : public btMotionState
|
||||
ATTRIBUTE_ALIGNED16(struct) btDefaultMotionState : public btMotionState
|
||||
{
|
||||
btTransform m_graphicsWorldTrans;
|
||||
btTransform m_centerOfMassOffset;
|
||||
btTransform m_centerOfMassOffset;
|
||||
btTransform m_startWorldTrans;
|
||||
void* m_userPointer;
|
||||
void* m_userPointer;
|
||||
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR();
|
||||
|
||||
btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(), const btTransform& centerOfMassOffset = btTransform::getIdentity())
|
||||
btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
|
||||
: m_graphicsWorldTrans(startTrans),
|
||||
m_centerOfMassOffset(centerOfMassOffset),
|
||||
m_startWorldTrans(startTrans),
|
||||
m_userPointer(0)
|
||||
m_centerOfMassOffset(centerOfMassOffset),
|
||||
m_startWorldTrans(startTrans),
|
||||
m_userPointer(0)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
///synchronizes world transform from user to physics
|
||||
virtual void getWorldTransform(btTransform & centerOfMassWorldTrans) const
|
||||
virtual void getWorldTransform(btTransform& centerOfMassWorldTrans ) const
|
||||
{
|
||||
centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse();
|
||||
centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse() ;
|
||||
}
|
||||
|
||||
///synchronizes world transform from physics to user
|
||||
///Bullet only calls the update of worldtransform for active objects
|
||||
virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
|
||||
virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
|
||||
{
|
||||
m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
|
||||
m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_DEFAULT_MOTION_STATE_H
|
||||
#endif //BT_DEFAULT_MOTION_STATE_H
|
||||
|
|
|
|||
|
|
@ -12,43 +12,49 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "btGeometryUtil.h"
|
||||
|
||||
|
||||
/*
|
||||
Make sure this dummy function never changes so that it
|
||||
can be used by probes that are checking whether the
|
||||
library is actually installed.
|
||||
*/
|
||||
extern "C"
|
||||
{
|
||||
void btBulletMathProbe();
|
||||
{
|
||||
void btBulletMathProbe ();
|
||||
|
||||
void btBulletMathProbe() {}
|
||||
void btBulletMathProbe () {}
|
||||
}
|
||||
|
||||
bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
|
||||
|
||||
bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
|
||||
{
|
||||
int numbrushes = planeEquations.size();
|
||||
for (int i = 0; i < numbrushes; i++)
|
||||
for (int i=0;i<numbrushes;i++)
|
||||
{
|
||||
const btVector3& N1 = planeEquations[i];
|
||||
btScalar dist = btScalar(N1.dot(point)) + btScalar(N1[3]) - margin;
|
||||
if (dist > btScalar(0.))
|
||||
btScalar dist = btScalar(N1.dot(point))+btScalar(N1[3])-margin;
|
||||
if (dist>btScalar(0.))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
|
||||
|
||||
bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
|
||||
{
|
||||
int numvertices = vertices.size();
|
||||
for (int i = 0; i < numvertices; i++)
|
||||
for (int i=0;i<numvertices;i++)
|
||||
{
|
||||
const btVector3& N1 = vertices[i];
|
||||
btScalar dist = btScalar(planeNormal.dot(N1)) + btScalar(planeNormal[3]) - margin;
|
||||
if (dist > btScalar(0.))
|
||||
btScalar dist = btScalar(planeNormal.dot(N1))+btScalar(planeNormal[3])-margin;
|
||||
if (dist>btScalar(0.))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -56,98 +62,102 @@ bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations);
|
||||
bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
|
||||
|
||||
bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations)
|
||||
bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
|
||||
{
|
||||
int numbrushes = planeEquations.size();
|
||||
for (int i = 0; i < numbrushes; i++)
|
||||
for (int i=0;i<numbrushes;i++)
|
||||
{
|
||||
const btVector3& N1 = planeEquations[i];
|
||||
if (planeEquation.dot(N1) > btScalar(0.999))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut)
|
||||
void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut )
|
||||
{
|
||||
const int numvertices = vertices.size();
|
||||
const int numvertices = vertices.size();
|
||||
// brute force:
|
||||
for (int i = 0; i < numvertices; i++)
|
||||
for (int i=0;i<numvertices;i++)
|
||||
{
|
||||
const btVector3& N1 = vertices[i];
|
||||
|
||||
|
||||
for (int j = i + 1; j < numvertices; j++)
|
||||
for (int j=i+1;j<numvertices;j++)
|
||||
{
|
||||
const btVector3& N2 = vertices[j];
|
||||
|
||||
for (int k = j + 1; k < numvertices; k++)
|
||||
|
||||
for (int k=j+1;k<numvertices;k++)
|
||||
{
|
||||
|
||||
const btVector3& N3 = vertices[k];
|
||||
|
||||
btVector3 planeEquation, edge0, edge1;
|
||||
edge0 = N2 - N1;
|
||||
edge1 = N3 - N1;
|
||||
btVector3 planeEquation,edge0,edge1;
|
||||
edge0 = N2-N1;
|
||||
edge1 = N3-N1;
|
||||
btScalar normalSign = btScalar(1.);
|
||||
for (int ww = 0; ww < 2; ww++)
|
||||
for (int ww=0;ww<2;ww++)
|
||||
{
|
||||
planeEquation = normalSign * edge0.cross(edge1);
|
||||
if (planeEquation.length2() > btScalar(0.0001))
|
||||
{
|
||||
planeEquation.normalize();
|
||||
if (notExist(planeEquation, planeEquationsOut))
|
||||
if (notExist(planeEquation,planeEquationsOut))
|
||||
{
|
||||
planeEquation[3] = -planeEquation.dot(N1);
|
||||
|
||||
//check if inside, and replace supportingVertexOut if needed
|
||||
if (areVerticesBehindPlane(planeEquation, vertices, btScalar(0.01)))
|
||||
{
|
||||
planeEquationsOut.push_back(planeEquation);
|
||||
}
|
||||
|
||||
//check if inside, and replace supportingVertexOut if needed
|
||||
if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01)))
|
||||
{
|
||||
planeEquationsOut.push_back(planeEquation);
|
||||
}
|
||||
}
|
||||
}
|
||||
normalSign = btScalar(-1.);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut)
|
||||
void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut )
|
||||
{
|
||||
const int numbrushes = planeEquations.size();
|
||||
// brute force:
|
||||
for (int i = 0; i < numbrushes; i++)
|
||||
for (int i=0;i<numbrushes;i++)
|
||||
{
|
||||
const btVector3& N1 = planeEquations[i];
|
||||
|
||||
|
||||
for (int j = i + 1; j < numbrushes; j++)
|
||||
for (int j=i+1;j<numbrushes;j++)
|
||||
{
|
||||
const btVector3& N2 = planeEquations[j];
|
||||
|
||||
for (int k = j + 1; k < numbrushes; k++)
|
||||
|
||||
for (int k=j+1;k<numbrushes;k++)
|
||||
{
|
||||
|
||||
const btVector3& N3 = planeEquations[k];
|
||||
|
||||
btVector3 n2n3;
|
||||
n2n3 = N2.cross(N3);
|
||||
btVector3 n3n1;
|
||||
n3n1 = N3.cross(N1);
|
||||
btVector3 n1n2;
|
||||
n1n2 = N1.cross(N2);
|
||||
|
||||
if ((n2n3.length2() > btScalar(0.0001)) &&
|
||||
(n3n1.length2() > btScalar(0.0001)) &&
|
||||
(n1n2.length2() > btScalar(0.0001)))
|
||||
btVector3 n2n3; n2n3 = N2.cross(N3);
|
||||
btVector3 n3n1; n3n1 = N3.cross(N1);
|
||||
btVector3 n1n2; n1n2 = N1.cross(N2);
|
||||
|
||||
if ( ( n2n3.length2() > btScalar(0.0001) ) &&
|
||||
( n3n1.length2() > btScalar(0.0001) ) &&
|
||||
( n1n2.length2() > btScalar(0.0001) ) )
|
||||
{
|
||||
//point P out of 3 plane equations:
|
||||
|
||||
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
|
||||
//P = -------------------------------------------------------------------------
|
||||
// N1 . ( N2 * N3 )
|
||||
// d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
|
||||
//P = -------------------------------------------------------------------------
|
||||
// N1 . ( N2 * N3 )
|
||||
|
||||
|
||||
btScalar quotient = (N1.dot(n2n3));
|
||||
if (btFabs(quotient) > btScalar(0.000001))
|
||||
|
|
@ -162,7 +172,7 @@ void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<bt
|
|||
potentialVertex *= quotient;
|
||||
|
||||
//check if inside, and replace supportingVertexOut if needed
|
||||
if (isPointInsidePlanes(planeEquations, potentialVertex, btScalar(0.01)))
|
||||
if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01)))
|
||||
{
|
||||
verticesOut.push_back(potentialVertex);
|
||||
}
|
||||
|
|
@ -172,3 +182,4 @@ void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<bt
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_GEOMETRY_UTIL_H
|
||||
#define BT_GEOMETRY_UTIL_H
|
||||
|
||||
|
|
@ -21,16 +22,21 @@ subject to the following restrictions:
|
|||
///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
|
||||
class btGeometryUtil
|
||||
{
|
||||
public:
|
||||
static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut);
|
||||
public:
|
||||
|
||||
|
||||
static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut );
|
||||
|
||||
static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut);
|
||||
static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut );
|
||||
|
||||
static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
|
||||
|
||||
static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
|
||||
|
||||
static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
|
||||
static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
|
||||
|
||||
static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
|
||||
|
||||
static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
|
||||
};
|
||||
|
||||
#endif //BT_GEOMETRY_UTIL_H
|
||||
|
||||
#endif //BT_GEOMETRY_UTIL_H
|
||||
|
||||
|
|
|
|||
|
|
@ -13,40 +13,41 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GRAHAM_SCAN_2D_CONVEX_HULL_H
|
||||
#define GRAHAM_SCAN_2D_CONVEX_HULL_H
|
||||
|
||||
|
||||
#include "btVector3.h"
|
||||
#include "btAlignedObjectArray.h"
|
||||
|
||||
struct GrahamVector3 : public btVector3
|
||||
{
|
||||
GrahamVector3(const btVector3& org, int orgIndex)
|
||||
: btVector3(org),
|
||||
m_orgIndex(orgIndex)
|
||||
:btVector3(org),
|
||||
m_orgIndex(orgIndex)
|
||||
{
|
||||
}
|
||||
btScalar m_angle;
|
||||
btScalar m_angle;
|
||||
int m_orgIndex;
|
||||
};
|
||||
|
||||
struct btAngleCompareFunc
|
||||
{
|
||||
|
||||
struct btAngleCompareFunc {
|
||||
btVector3 m_anchor;
|
||||
btAngleCompareFunc(const btVector3& anchor)
|
||||
: m_anchor(anchor)
|
||||
: m_anchor(anchor)
|
||||
{
|
||||
}
|
||||
bool operator()(const GrahamVector3& a, const GrahamVector3& b) const
|
||||
{
|
||||
bool operator()(const GrahamVector3& a, const GrahamVector3& b) const {
|
||||
if (a.m_angle != b.m_angle)
|
||||
return a.m_angle < b.m_angle;
|
||||
else
|
||||
{
|
||||
btScalar al = (a - m_anchor).length2();
|
||||
btScalar bl = (b - m_anchor).length2();
|
||||
btScalar al = (a-m_anchor).length2();
|
||||
btScalar bl = (b-m_anchor).length2();
|
||||
if (al != bl)
|
||||
return al < bl;
|
||||
return al < bl;
|
||||
else
|
||||
{
|
||||
return a.m_orgIndex < b.m_orgIndex;
|
||||
|
|
@ -57,73 +58,73 @@ struct btAngleCompareFunc
|
|||
|
||||
inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& originalPoints, btAlignedObjectArray<GrahamVector3>& hull, const btVector3& normalAxis)
|
||||
{
|
||||
btVector3 axis0, axis1;
|
||||
btPlaneSpace1(normalAxis, axis0, axis1);
|
||||
btVector3 axis0,axis1;
|
||||
btPlaneSpace1(normalAxis,axis0,axis1);
|
||||
|
||||
|
||||
if (originalPoints.size() <= 1)
|
||||
if (originalPoints.size()<=1)
|
||||
{
|
||||
for (int i = 0; i < originalPoints.size(); i++)
|
||||
for (int i=0;i<originalPoints.size();i++)
|
||||
hull.push_back(originalPoints[0]);
|
||||
return;
|
||||
}
|
||||
//step1 : find anchor point with smallest projection on axis0 and move it to first location
|
||||
for (int i = 0; i < originalPoints.size(); i++)
|
||||
for (int i=0;i<originalPoints.size();i++)
|
||||
{
|
||||
// const btVector3& left = originalPoints[i];
|
||||
// const btVector3& right = originalPoints[0];
|
||||
// const btVector3& left = originalPoints[i];
|
||||
// const btVector3& right = originalPoints[0];
|
||||
btScalar projL = originalPoints[i].dot(axis0);
|
||||
btScalar projR = originalPoints[0].dot(axis0);
|
||||
if (projL < projR)
|
||||
{
|
||||
originalPoints.swap(0, i);
|
||||
originalPoints.swap(0,i);
|
||||
}
|
||||
}
|
||||
|
||||
//also precompute angles
|
||||
originalPoints[0].m_angle = -1e30f;
|
||||
for (int i = 1; i < originalPoints.size(); i++)
|
||||
for (int i=1;i<originalPoints.size();i++)
|
||||
{
|
||||
btVector3 ar = originalPoints[i] - originalPoints[0];
|
||||
btScalar ar1 = axis1.dot(ar);
|
||||
btScalar ar0 = axis0.dot(ar);
|
||||
if (ar1 * ar1 + ar0 * ar0 < FLT_EPSILON)
|
||||
{
|
||||
originalPoints[i].m_angle = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
|
||||
}
|
||||
btVector3 ar = originalPoints[i]-originalPoints[0];
|
||||
btScalar ar1 = axis1.dot(ar);
|
||||
btScalar ar0 = axis0.dot(ar);
|
||||
if( ar1*ar1+ar0*ar0 < FLT_EPSILON )
|
||||
{
|
||||
originalPoints[i].m_angle = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
|
||||
}
|
||||
}
|
||||
|
||||
//step 2: sort all points, based on 'angle' with this anchor
|
||||
btAngleCompareFunc comp(originalPoints[0]);
|
||||
originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
|
||||
originalPoints.quickSortInternal(comp,1,originalPoints.size()-1);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 2; i++)
|
||||
for (i = 0; i<2; i++)
|
||||
hull.push_back(originalPoints[i]);
|
||||
|
||||
//step 3: keep all 'convex' points and discard concave points (using back tracking)
|
||||
for (; i != originalPoints.size(); i++)
|
||||
for (; i != originalPoints.size(); i++)
|
||||
{
|
||||
bool isConvex = false;
|
||||
while (!isConvex && hull.size() > 1)
|
||||
{
|
||||
btVector3& a = hull[hull.size() - 2];
|
||||
btVector3& b = hull[hull.size() - 1];
|
||||
isConvex = btCross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
|
||||
while (!isConvex&& hull.size()>1) {
|
||||
btVector3& a = hull[hull.size()-2];
|
||||
btVector3& b = hull[hull.size()-1];
|
||||
isConvex = btCross(a-b,a-originalPoints[i]).dot(normalAxis)> 0;
|
||||
if (!isConvex)
|
||||
hull.pop_back();
|
||||
else
|
||||
else
|
||||
hull.push_back(originalPoints[i]);
|
||||
}
|
||||
|
||||
if (hull.size() == 1)
|
||||
{
|
||||
hull.push_back(originalPoints[i]);
|
||||
}
|
||||
if( hull.size() == 1 )
|
||||
{
|
||||
hull.push_back( originalPoints[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H
|
||||
#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H
|
||||
|
|
|
|||
|
|
@ -13,73 +13,87 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_HASH_MAP_H
|
||||
#define BT_HASH_MAP_H
|
||||
|
||||
#include <string>
|
||||
#include "btAlignedObjectArray.h"
|
||||
|
||||
///very basic hashable string implementation, compatible with btHashMap
|
||||
struct btHashString
|
||||
{
|
||||
std::string m_string1;
|
||||
unsigned int m_hash;
|
||||
const char* m_string;
|
||||
unsigned int m_hash;
|
||||
|
||||
SIMD_FORCE_INLINE unsigned int getHash() const
|
||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
btHashString()
|
||||
{
|
||||
m_string1 = "";
|
||||
m_hash = 0;
|
||||
}
|
||||
btHashString(const char* name)
|
||||
: m_string1(name)
|
||||
:m_string(name)
|
||||
{
|
||||
/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
|
||||
static const unsigned int InitialFNV = 2166136261u;
|
||||
static const unsigned int InitialFNV = 2166136261u;
|
||||
static const unsigned int FNVMultiple = 16777619u;
|
||||
|
||||
/* Fowler / Noll / Vo (FNV) Hash */
|
||||
unsigned int hash = InitialFNV;
|
||||
|
||||
for (int i = 0; m_string1.c_str()[i]; i++)
|
||||
|
||||
for(int i = 0; m_string[i]; i++)
|
||||
{
|
||||
hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
|
||||
hash = hash * FNVMultiple; /* multiply by the magic number */
|
||||
hash = hash ^ (m_string[i]); /* xor the low 8 bits */
|
||||
hash = hash * FNVMultiple; /* multiply by the magic number */
|
||||
}
|
||||
m_hash = hash;
|
||||
}
|
||||
|
||||
int portableStringCompare(const char* src, const char* dst) const
|
||||
{
|
||||
int ret = 0 ;
|
||||
|
||||
while( ! (ret = *(const unsigned char *)src - *(const unsigned char *)dst) && *dst)
|
||||
++src, ++dst;
|
||||
|
||||
if ( ret < 0 )
|
||||
ret = -1 ;
|
||||
else if ( ret > 0 )
|
||||
ret = 1 ;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
bool equals(const btHashString& other) const
|
||||
{
|
||||
return (m_string1 == other.m_string1);
|
||||
return (m_string == other.m_string) ||
|
||||
(0==portableStringCompare(m_string,other.m_string));
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const int BT_HASH_NULL = 0xffffffff;
|
||||
const int BT_HASH_NULL=0xffffffff;
|
||||
|
||||
|
||||
class btHashInt
|
||||
{
|
||||
int m_uid;
|
||||
|
||||
int m_uid;
|
||||
public:
|
||||
|
||||
btHashInt()
|
||||
{
|
||||
}
|
||||
|
||||
btHashInt(int uid) : m_uid(uid)
|
||||
btHashInt(int uid) :m_uid(uid)
|
||||
{
|
||||
}
|
||||
|
||||
int getUid1() const
|
||||
int getUid1() const
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
void setUid1(int uid)
|
||||
void setUid1(int uid)
|
||||
{
|
||||
m_uid = uid;
|
||||
}
|
||||
|
|
@ -89,35 +103,35 @@ public:
|
|||
return getUid1() == other.getUid1();
|
||||
}
|
||||
//to our success
|
||||
SIMD_FORCE_INLINE unsigned int getHash() const
|
||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||
{
|
||||
unsigned int key = m_uid;
|
||||
// Thomas Wang's hash
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
|
||||
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
|
||||
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class btHashPtr
|
||||
{
|
||||
union {
|
||||
const void* m_pointer;
|
||||
unsigned int m_hashValues[2];
|
||||
|
||||
union
|
||||
{
|
||||
const void* m_pointer;
|
||||
unsigned int m_hashValues[2];
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
btHashPtr(const void* ptr)
|
||||
: m_pointer(ptr)
|
||||
:m_pointer(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
const void* getPointer() const
|
||||
const void* getPointer() const
|
||||
{
|
||||
return m_pointer;
|
||||
}
|
||||
|
|
@ -128,68 +142,64 @@ public:
|
|||
}
|
||||
|
||||
//to our success
|
||||
SIMD_FORCE_INLINE unsigned int getHash() const
|
||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||
{
|
||||
const bool VOID_IS_8 = ((sizeof(void*) == 8));
|
||||
|
||||
unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
|
||||
const bool VOID_IS_8 = ((sizeof(void*)==8));
|
||||
|
||||
unsigned int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
|
||||
// Thomas Wang's hash
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <class Value>
|
||||
class btHashKeyPtr
|
||||
{
|
||||
int m_uid;
|
||||
|
||||
int m_uid;
|
||||
public:
|
||||
btHashKeyPtr(int uid) : m_uid(uid)
|
||||
{
|
||||
}
|
||||
|
||||
int getUid1() const
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
btHashKeyPtr(int uid) :m_uid(uid)
|
||||
{
|
||||
}
|
||||
|
||||
bool equals(const btHashKeyPtr<Value>& other) const
|
||||
{
|
||||
return getUid1() == other.getUid1();
|
||||
}
|
||||
int getUid1() const
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
||||
//to our success
|
||||
SIMD_FORCE_INLINE unsigned int getHash() const
|
||||
{
|
||||
unsigned int key = m_uid;
|
||||
// Thomas Wang's hash
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
return key;
|
||||
}
|
||||
bool equals(const btHashKeyPtr<Value>& other) const
|
||||
{
|
||||
return getUid1() == other.getUid1();
|
||||
}
|
||||
|
||||
//to our success
|
||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||
{
|
||||
unsigned int key = m_uid;
|
||||
// Thomas Wang's hash
|
||||
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <class Value>
|
||||
class btHashKey
|
||||
{
|
||||
int m_uid;
|
||||
|
||||
int m_uid;
|
||||
public:
|
||||
btHashKey(int uid) : m_uid(uid)
|
||||
|
||||
btHashKey(int uid) :m_uid(uid)
|
||||
{
|
||||
}
|
||||
|
||||
int getUid1() const
|
||||
int getUid1() const
|
||||
{
|
||||
return m_uid;
|
||||
}
|
||||
|
|
@ -199,33 +209,30 @@ public:
|
|||
return getUid1() == other.getUid1();
|
||||
}
|
||||
//to our success
|
||||
SIMD_FORCE_INLINE unsigned int getHash() const
|
||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||
{
|
||||
unsigned int key = m_uid;
|
||||
// Thomas Wang's hash
|
||||
key += ~(key << 15);
|
||||
key ^= (key >> 10);
|
||||
key += (key << 3);
|
||||
key ^= (key >> 6);
|
||||
key += ~(key << 11);
|
||||
key ^= (key >> 16);
|
||||
key += ~(key << 15); key ^= (key >> 10); key += (key << 3); key ^= (key >> 6); key += ~(key << 11); key ^= (key >> 16);
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///The btHashMap template class implements a generic and lightweight hashmap.
|
||||
///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
|
||||
template <class Key, class Value>
|
||||
class btHashMap
|
||||
{
|
||||
|
||||
protected:
|
||||
btAlignedObjectArray<int> m_hashTable;
|
||||
btAlignedObjectArray<int> m_next;
|
||||
btAlignedObjectArray<int> m_hashTable;
|
||||
btAlignedObjectArray<int> m_next;
|
||||
|
||||
btAlignedObjectArray<Value> m_valueArray;
|
||||
btAlignedObjectArray<Key> m_keyArray;
|
||||
|
||||
btAlignedObjectArray<Value> m_valueArray;
|
||||
btAlignedObjectArray<Key> m_keyArray;
|
||||
|
||||
void growTables(const Key& /*key*/)
|
||||
void growTables(const Key& /*key*/)
|
||||
{
|
||||
int newCapacity = m_valueArray.capacity();
|
||||
|
||||
|
|
@ -239,7 +246,7 @@ protected:
|
|||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < newCapacity; ++i)
|
||||
for (i= 0; i < newCapacity; ++i)
|
||||
{
|
||||
m_hashTable[i] = BT_HASH_NULL;
|
||||
}
|
||||
|
|
@ -248,28 +255,30 @@ protected:
|
|||
m_next[i] = BT_HASH_NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < curHashtableSize; i++)
|
||||
for(i=0;i<curHashtableSize;i++)
|
||||
{
|
||||
//const Value& value = m_valueArray[i];
|
||||
//const Key& key = m_keyArray[i];
|
||||
|
||||
int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
|
||||
int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
|
||||
m_next[i] = m_hashTable[hashValue];
|
||||
m_hashTable[hashValue] = i;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void insert(const Key& key, const Value& value)
|
||||
{
|
||||
int hash = key.getHash() & (m_valueArray.capacity() - 1);
|
||||
public:
|
||||
|
||||
void insert(const Key& key, const Value& value) {
|
||||
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||
|
||||
//replace value if the key is already there
|
||||
int index = findIndex(key);
|
||||
if (index != BT_HASH_NULL)
|
||||
{
|
||||
m_valueArray[index] = value;
|
||||
m_valueArray[index]=value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -283,19 +292,19 @@ public:
|
|||
{
|
||||
growTables(key);
|
||||
//hash with new capacity
|
||||
hash = key.getHash() & (m_valueArray.capacity() - 1);
|
||||
hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||
}
|
||||
m_next[count] = m_hashTable[hash];
|
||||
m_hashTable[hash] = count;
|
||||
}
|
||||
|
||||
void remove(const Key& key)
|
||||
{
|
||||
int hash = key.getHash() & (m_valueArray.capacity() - 1);
|
||||
void remove(const Key& key) {
|
||||
|
||||
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||
|
||||
int pairIndex = findIndex(key);
|
||||
|
||||
if (pairIndex == BT_HASH_NULL)
|
||||
|
||||
if (pairIndex ==BT_HASH_NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -336,7 +345,7 @@ public:
|
|||
}
|
||||
|
||||
// Remove the last pair from the hash table.
|
||||
int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
|
||||
int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
|
||||
|
||||
index = m_hashTable[lastHash];
|
||||
btAssert(index != BT_HASH_NULL);
|
||||
|
|
@ -368,8 +377,10 @@ public:
|
|||
|
||||
m_valueArray.pop_back();
|
||||
m_keyArray.pop_back();
|
||||
|
||||
}
|
||||
|
||||
|
||||
int size() const
|
||||
{
|
||||
return m_valueArray.size();
|
||||
|
|
@ -378,8 +389,8 @@ public:
|
|||
const Value* getAtIndex(int index) const
|
||||
{
|
||||
btAssert(index < m_valueArray.size());
|
||||
btAssert(index >= 0);
|
||||
if (index >= 0 && index < m_valueArray.size())
|
||||
btAssert(index>=0);
|
||||
if (index>=0 && index < m_valueArray.size())
|
||||
{
|
||||
return &m_valueArray[index];
|
||||
}
|
||||
|
|
@ -389,39 +400,38 @@ public:
|
|||
Value* getAtIndex(int index)
|
||||
{
|
||||
btAssert(index < m_valueArray.size());
|
||||
btAssert(index >= 0);
|
||||
if (index >= 0 && index < m_valueArray.size())
|
||||
btAssert(index>=0);
|
||||
if (index>=0 && index < m_valueArray.size())
|
||||
{
|
||||
return &m_valueArray[index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Key getKeyAtIndex(int index)
|
||||
{
|
||||
btAssert(index < m_keyArray.size());
|
||||
btAssert(index >= 0);
|
||||
Key getKeyAtIndex(int index)
|
||||
{
|
||||
btAssert(index < m_keyArray.size());
|
||||
btAssert(index>=0);
|
||||
return m_keyArray[index];
|
||||
}
|
||||
|
||||
const Key getKeyAtIndex(int index) const
|
||||
{
|
||||
btAssert(index < m_keyArray.size());
|
||||
btAssert(index >= 0);
|
||||
}
|
||||
|
||||
const Key getKeyAtIndex(int index) const
|
||||
{
|
||||
btAssert(index < m_keyArray.size());
|
||||
btAssert(index>=0);
|
||||
return m_keyArray[index];
|
||||
}
|
||||
}
|
||||
|
||||
Value* operator[](const Key& key)
|
||||
{
|
||||
|
||||
Value* operator[](const Key& key) {
|
||||
return find(key);
|
||||
}
|
||||
|
||||
const Value* operator[](const Key& key) const
|
||||
{
|
||||
const Value* operator[](const Key& key) const {
|
||||
return find(key);
|
||||
}
|
||||
|
||||
const Value* find(const Key& key) const
|
||||
const Value* find(const Key& key) const
|
||||
{
|
||||
int index = findIndex(key);
|
||||
if (index == BT_HASH_NULL)
|
||||
|
|
@ -431,7 +441,7 @@ public:
|
|||
return &m_valueArray[index];
|
||||
}
|
||||
|
||||
Value* find(const Key& key)
|
||||
Value* find(const Key& key)
|
||||
{
|
||||
int index = findIndex(key);
|
||||
if (index == BT_HASH_NULL)
|
||||
|
|
@ -441,9 +451,10 @@ public:
|
|||
return &m_valueArray[index];
|
||||
}
|
||||
|
||||
int findIndex(const Key& key) const
|
||||
|
||||
int findIndex(const Key& key) const
|
||||
{
|
||||
unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
|
||||
unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||
|
||||
if (hash >= (unsigned int)m_hashTable.size())
|
||||
{
|
||||
|
|
@ -458,13 +469,14 @@ public:
|
|||
return index;
|
||||
}
|
||||
|
||||
void clear()
|
||||
void clear()
|
||||
{
|
||||
m_hashTable.clear();
|
||||
m_next.clear();
|
||||
m_valueArray.clear();
|
||||
m_keyArray.clear();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_HASH_MAP_H
|
||||
#endif //BT_HASH_MAP_H
|
||||
|
|
|
|||
|
|
@ -13,84 +13,86 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_IDEBUG_DRAW__H
|
||||
#define BT_IDEBUG_DRAW__H
|
||||
|
||||
#include "btVector3.h"
|
||||
#include "btTransform.h"
|
||||
|
||||
|
||||
|
||||
///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
|
||||
///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
|
||||
///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
|
||||
///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
|
||||
class btIDebugDraw
|
||||
class btIDebugDraw
|
||||
{
|
||||
public:
|
||||
ATTRIBUTE_ALIGNED16(struct)
|
||||
DefaultColors
|
||||
{
|
||||
btVector3 m_activeObject;
|
||||
btVector3 m_deactivatedObject;
|
||||
btVector3 m_wantsDeactivationObject;
|
||||
btVector3 m_disabledDeactivationObject;
|
||||
btVector3 m_disabledSimulationObject;
|
||||
btVector3 m_aabb;
|
||||
btVector3 m_contactPoint;
|
||||
public:
|
||||
|
||||
ATTRIBUTE_ALIGNED16(struct) DefaultColors
|
||||
{
|
||||
btVector3 m_activeObject;
|
||||
btVector3 m_deactivatedObject;
|
||||
btVector3 m_wantsDeactivationObject;
|
||||
btVector3 m_disabledDeactivationObject;
|
||||
btVector3 m_disabledSimulationObject;
|
||||
btVector3 m_aabb;
|
||||
btVector3 m_contactPoint;
|
||||
|
||||
DefaultColors()
|
||||
: m_activeObject(1, 1, 1),
|
||||
m_deactivatedObject(0, 1, 0),
|
||||
m_wantsDeactivationObject(0, 1, 1),
|
||||
m_disabledDeactivationObject(1, 0, 0),
|
||||
m_disabledSimulationObject(1, 1, 0),
|
||||
m_aabb(1, 0, 0),
|
||||
m_contactPoint(1, 1, 0)
|
||||
: m_activeObject(1,1,1),
|
||||
m_deactivatedObject(0,1,0),
|
||||
m_wantsDeactivationObject(0,1,1),
|
||||
m_disabledDeactivationObject(1,0,0),
|
||||
m_disabledSimulationObject(1,1,0),
|
||||
m_aabb(1,0,0),
|
||||
m_contactPoint(1,1,0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
enum DebugDrawModes
|
||||
|
||||
enum DebugDrawModes
|
||||
{
|
||||
DBG_NoDebug = 0,
|
||||
DBG_NoDebug=0,
|
||||
DBG_DrawWireframe = 1,
|
||||
DBG_DrawAabb = 2,
|
||||
DBG_DrawFeaturesText = 4,
|
||||
DBG_DrawContactPoints = 8,
|
||||
DBG_NoDeactivation = 16,
|
||||
DBG_DrawAabb=2,
|
||||
DBG_DrawFeaturesText=4,
|
||||
DBG_DrawContactPoints=8,
|
||||
DBG_NoDeactivation=16,
|
||||
DBG_NoHelpText = 32,
|
||||
DBG_DrawText = 64,
|
||||
DBG_DrawText=64,
|
||||
DBG_ProfileTimings = 128,
|
||||
DBG_EnableSatComparison = 256,
|
||||
DBG_DisableBulletLCP = 512,
|
||||
DBG_EnableCCD = 1024,
|
||||
DBG_DrawConstraints = (1 << 11),
|
||||
DBG_DrawConstraintLimits = (1 << 12),
|
||||
DBG_FastWireframe = (1 << 13),
|
||||
DBG_DrawNormals = (1 << 14),
|
||||
DBG_DrawFrames = (1 << 15),
|
||||
DBG_FastWireframe = (1<<13),
|
||||
DBG_DrawNormals = (1<<14),
|
||||
DBG_DrawFrames = (1<<15),
|
||||
DBG_MAX_DEBUG_DRAW_MODE
|
||||
};
|
||||
|
||||
virtual ~btIDebugDraw(){};
|
||||
virtual ~btIDebugDraw() {};
|
||||
|
||||
virtual DefaultColors getDefaultColors() const
|
||||
{
|
||||
DefaultColors colors;
|
||||
return colors;
|
||||
}
|
||||
|
||||
virtual DefaultColors getDefaultColors() const { DefaultColors colors; return colors; }
|
||||
///the default implementation for setDefaultColors has no effect. A derived class can implement it and store the colors.
|
||||
virtual void setDefaultColors(const DefaultColors& /*colors*/) {}
|
||||
|
||||
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) = 0;
|
||||
|
||||
virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
|
||||
|
||||
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
|
||||
|
||||
virtual void drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
|
||||
{
|
||||
(void)toColor;
|
||||
drawLine(from, to, fromColor);
|
||||
(void) toColor;
|
||||
drawLine (from, to, fromColor);
|
||||
}
|
||||
|
||||
virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
|
||||
virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
|
||||
{
|
||||
|
||||
btVector3 center = transform.getOrigin();
|
||||
btVector3 up = transform.getBasis().getColumn(1);
|
||||
btVector3 axis = transform.getBasis().getColumn(0);
|
||||
|
|
@ -99,102 +101,103 @@ public:
|
|||
btScalar minPs = -SIMD_HALF_PI;
|
||||
btScalar maxPs = SIMD_HALF_PI;
|
||||
btScalar stepDegrees = 30.f;
|
||||
drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
|
||||
drawSpherePatch(center, up, -axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
|
||||
drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees ,false);
|
||||
drawSpherePatch(center, up, -axis, radius,minTh, maxTh, minPs, maxPs, color, stepDegrees,false );
|
||||
}
|
||||
|
||||
virtual void drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
|
||||
|
||||
virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
|
||||
{
|
||||
btTransform tr;
|
||||
tr.setIdentity();
|
||||
tr.setOrigin(p);
|
||||
drawSphere(radius, tr, color);
|
||||
drawSphere(radius,tr,color);
|
||||
}
|
||||
|
||||
virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
|
||||
{
|
||||
drawTriangle(v0,v1,v2,color,alpha);
|
||||
}
|
||||
virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
|
||||
{
|
||||
drawLine(v0,v1,color);
|
||||
drawLine(v1,v2,color);
|
||||
drawLine(v2,v0,color);
|
||||
}
|
||||
|
||||
virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& /*n0*/, const btVector3& /*n1*/, const btVector3& /*n2*/, const btVector3& color, btScalar alpha)
|
||||
virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0;
|
||||
|
||||
virtual void reportErrorWarning(const char* warningString) = 0;
|
||||
|
||||
virtual void draw3dText(const btVector3& location,const char* textString) = 0;
|
||||
|
||||
virtual void setDebugMode(int debugMode) =0;
|
||||
|
||||
virtual int getDebugMode() const = 0;
|
||||
|
||||
virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color)
|
||||
{
|
||||
drawTriangle(v0, v1, v2, color, alpha);
|
||||
}
|
||||
virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& color, btScalar /*alpha*/)
|
||||
{
|
||||
drawLine(v0, v1, color);
|
||||
drawLine(v1, v2, color);
|
||||
drawLine(v2, v0, color);
|
||||
}
|
||||
|
||||
virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) = 0;
|
||||
btVector3 halfExtents = (to-from)* 0.5f;
|
||||
btVector3 center = (to+from) *0.5f;
|
||||
int i,j;
|
||||
|
||||
virtual void reportErrorWarning(const char* warningString) = 0;
|
||||
|
||||
virtual void draw3dText(const btVector3& location, const char* textString) = 0;
|
||||
|
||||
virtual void setDebugMode(int debugMode) = 0;
|
||||
|
||||
virtual int getDebugMode() const = 0;
|
||||
|
||||
virtual void drawAabb(const btVector3& from, const btVector3& to, const btVector3& color)
|
||||
{
|
||||
btVector3 halfExtents = (to - from) * 0.5f;
|
||||
btVector3 center = (to + from) * 0.5f;
|
||||
int i, j;
|
||||
|
||||
btVector3 edgecoord(1.f, 1.f, 1.f), pa, pb;
|
||||
for (i = 0; i < 4; i++)
|
||||
btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
|
||||
for (i=0;i<4;i++)
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
for (j=0;j<3;j++)
|
||||
{
|
||||
pa = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
|
||||
edgecoord[2] * halfExtents[2]);
|
||||
pa += center;
|
||||
pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
|
||||
edgecoord[2]*halfExtents[2]);
|
||||
pa+=center;
|
||||
|
||||
int othercoord = j % 3;
|
||||
edgecoord[othercoord] *= -1.f;
|
||||
pb = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
|
||||
edgecoord[2] * halfExtents[2]);
|
||||
pb += center;
|
||||
int othercoord = j%3;
|
||||
edgecoord[othercoord]*=-1.f;
|
||||
pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],
|
||||
edgecoord[2]*halfExtents[2]);
|
||||
pb+=center;
|
||||
|
||||
drawLine(pa, pb, color);
|
||||
drawLine(pa,pb,color);
|
||||
}
|
||||
edgecoord = btVector3(-1.f, -1.f, -1.f);
|
||||
if (i < 3)
|
||||
edgecoord[i] *= -1.f;
|
||||
edgecoord = btVector3(-1.f,-1.f,-1.f);
|
||||
if (i<3)
|
||||
edgecoord[i]*=-1.f;
|
||||
}
|
||||
}
|
||||
virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
|
||||
{
|
||||
btVector3 start = transform.getOrigin();
|
||||
drawLine(start, start + transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(btScalar(1.), btScalar(0.3), btScalar(0.3)));
|
||||
drawLine(start, start + transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(btScalar(0.3), btScalar(1.), btScalar(0.3)));
|
||||
drawLine(start, start + transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(btScalar(0.3), btScalar(0.3), btScalar(1.)));
|
||||
drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(1.f,0.3,0.3));
|
||||
drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0.3,1.f, 0.3));
|
||||
drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0.3, 0.3,1.f));
|
||||
}
|
||||
|
||||
virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
|
||||
const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
|
||||
virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
|
||||
const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
|
||||
{
|
||||
const btVector3& vx = axis;
|
||||
btVector3 vy = normal.cross(axis);
|
||||
btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
|
||||
int nSteps = (int)btFabs((maxAngle - minAngle) / step);
|
||||
if (!nSteps) nSteps = 1;
|
||||
if(!nSteps) nSteps = 1;
|
||||
btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
|
||||
if (drawSect)
|
||||
if(drawSect)
|
||||
{
|
||||
drawLine(center, prev, color);
|
||||
}
|
||||
for (int i = 1; i <= nSteps; i++)
|
||||
for(int i = 1; i <= nSteps; i++)
|
||||
{
|
||||
btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
|
||||
btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
|
||||
drawLine(prev, next, color);
|
||||
prev = next;
|
||||
}
|
||||
if (drawSect)
|
||||
if(drawSect)
|
||||
{
|
||||
drawLine(center, prev, color);
|
||||
}
|
||||
}
|
||||
virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
|
||||
btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f), bool drawCenter = true)
|
||||
virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
|
||||
btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f),bool drawCenter = true)
|
||||
{
|
||||
btVector3 vA[74];
|
||||
btVector3 vB[74];
|
||||
|
|
@ -208,33 +211,33 @@ public:
|
|||
btVector3 jv = kv.cross(iv);
|
||||
bool drawN = false;
|
||||
bool drawS = false;
|
||||
if (minTh <= -SIMD_HALF_PI)
|
||||
if(minTh <= -SIMD_HALF_PI)
|
||||
{
|
||||
minTh = -SIMD_HALF_PI + step;
|
||||
drawN = true;
|
||||
}
|
||||
if (maxTh >= SIMD_HALF_PI)
|
||||
if(maxTh >= SIMD_HALF_PI)
|
||||
{
|
||||
maxTh = SIMD_HALF_PI - step;
|
||||
drawS = true;
|
||||
}
|
||||
if (minTh > maxTh)
|
||||
if(minTh > maxTh)
|
||||
{
|
||||
minTh = -SIMD_HALF_PI + step;
|
||||
maxTh = SIMD_HALF_PI - step;
|
||||
maxTh = SIMD_HALF_PI - step;
|
||||
drawN = drawS = true;
|
||||
}
|
||||
int n_hor = (int)((maxTh - minTh) / step) + 1;
|
||||
if (n_hor < 2) n_hor = 2;
|
||||
if(n_hor < 2) n_hor = 2;
|
||||
btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
|
||||
bool isClosed = false;
|
||||
if (minPs > maxPs)
|
||||
if(minPs > maxPs)
|
||||
{
|
||||
minPs = -SIMD_PI + step;
|
||||
maxPs = SIMD_PI;
|
||||
maxPs = SIMD_PI;
|
||||
isClosed = true;
|
||||
}
|
||||
else if ((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
|
||||
else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
|
||||
{
|
||||
isClosed = true;
|
||||
}
|
||||
|
|
@ -243,64 +246,63 @@ public:
|
|||
isClosed = false;
|
||||
}
|
||||
int n_vert = (int)((maxPs - minPs) / step) + 1;
|
||||
if (n_vert < 2) n_vert = 2;
|
||||
if(n_vert < 2) n_vert = 2;
|
||||
btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
|
||||
for (int i = 0; i < n_hor; i++)
|
||||
for(int i = 0; i < n_hor; i++)
|
||||
{
|
||||
btScalar th = minTh + btScalar(i) * step_h;
|
||||
btScalar sth = radius * btSin(th);
|
||||
btScalar cth = radius * btCos(th);
|
||||
for (int j = 0; j < n_vert; j++)
|
||||
for(int j = 0; j < n_vert; j++)
|
||||
{
|
||||
btScalar psi = minPs + btScalar(j) * step_v;
|
||||
btScalar sps = btSin(psi);
|
||||
btScalar cps = btCos(psi);
|
||||
pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
|
||||
if (i)
|
||||
if(i)
|
||||
{
|
||||
drawLine(pvA[j], pvB[j], color);
|
||||
}
|
||||
else if (drawS)
|
||||
else if(drawS)
|
||||
{
|
||||
drawLine(spole, pvB[j], color);
|
||||
}
|
||||
if (j)
|
||||
if(j)
|
||||
{
|
||||
drawLine(pvB[j - 1], pvB[j], color);
|
||||
drawLine(pvB[j-1], pvB[j], color);
|
||||
}
|
||||
else
|
||||
{
|
||||
arcStart = pvB[j];
|
||||
}
|
||||
if ((i == (n_hor - 1)) && drawN)
|
||||
if((i == (n_hor - 1)) && drawN)
|
||||
{
|
||||
drawLine(npole, pvB[j], color);
|
||||
}
|
||||
|
||||
|
||||
if (drawCenter)
|
||||
{
|
||||
if (isClosed)
|
||||
if(isClosed)
|
||||
{
|
||||
if (j == (n_vert - 1))
|
||||
if(j == (n_vert-1))
|
||||
{
|
||||
drawLine(arcStart, pvB[j], color);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((!i) || (i == (n_hor - 1))) && ((!j) || (j == (n_vert - 1))))
|
||||
if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1))))
|
||||
{
|
||||
drawLine(center, pvB[j], color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pT = pvA;
|
||||
pvA = pvB;
|
||||
pvB = pT;
|
||||
pT = pvA; pvA = pvB; pvB = pT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
|
||||
{
|
||||
drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
|
||||
|
|
@ -336,27 +338,31 @@ public:
|
|||
{
|
||||
int stepDegrees = 30;
|
||||
|
||||
btVector3 capStart(0.f, 0.f, 0.f);
|
||||
btVector3 capStart(0.f,0.f,0.f);
|
||||
capStart[upAxis] = -halfHeight;
|
||||
|
||||
btVector3 capEnd(0.f, 0.f, 0.f);
|
||||
btVector3 capEnd(0.f,0.f,0.f);
|
||||
capEnd[upAxis] = halfHeight;
|
||||
|
||||
// Draw the ends
|
||||
{
|
||||
|
||||
btTransform childTransform = transform;
|
||||
childTransform.getOrigin() = transform * capStart;
|
||||
{
|
||||
btVector3 center = childTransform.getOrigin();
|
||||
btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
|
||||
btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3);
|
||||
btVector3 axis = -childTransform.getBasis().getColumn(upAxis);
|
||||
btScalar minTh = -SIMD_HALF_PI;
|
||||
btScalar maxTh = SIMD_HALF_PI;
|
||||
btScalar minPs = -SIMD_HALF_PI;
|
||||
btScalar maxPs = SIMD_HALF_PI;
|
||||
|
||||
drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
|
||||
|
||||
drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -364,51 +370,52 @@ public:
|
|||
childTransform.getOrigin() = transform * capEnd;
|
||||
{
|
||||
btVector3 center = childTransform.getOrigin();
|
||||
btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
|
||||
btVector3 up = childTransform.getBasis().getColumn((upAxis+1)%3);
|
||||
btVector3 axis = childTransform.getBasis().getColumn(upAxis);
|
||||
btScalar minTh = -SIMD_HALF_PI;
|
||||
btScalar maxTh = SIMD_HALF_PI;
|
||||
btScalar minPs = -SIMD_HALF_PI;
|
||||
btScalar maxPs = SIMD_HALF_PI;
|
||||
drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
|
||||
drawSpherePatch(center, up, axis, radius,minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees) ,false);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw some additional lines
|
||||
btVector3 start = transform.getOrigin();
|
||||
|
||||
for (int i = 0; i < 360; i += stepDegrees)
|
||||
for (int i=0;i<360;i+=stepDegrees)
|
||||
{
|
||||
capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
|
||||
capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
|
||||
drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
|
||||
capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
|
||||
capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
|
||||
drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
|
||||
{
|
||||
btVector3 start = transform.getOrigin();
|
||||
btVector3 offsetHeight(0, 0, 0);
|
||||
btVector3 offsetHeight(0,0,0);
|
||||
offsetHeight[upAxis] = halfHeight;
|
||||
int stepDegrees = 30;
|
||||
btVector3 capStart(0.f, 0.f, 0.f);
|
||||
int stepDegrees=30;
|
||||
btVector3 capStart(0.f,0.f,0.f);
|
||||
capStart[upAxis] = -halfHeight;
|
||||
btVector3 capEnd(0.f, 0.f, 0.f);
|
||||
btVector3 capEnd(0.f,0.f,0.f);
|
||||
capEnd[upAxis] = halfHeight;
|
||||
|
||||
for (int i = 0; i < 360; i += stepDegrees)
|
||||
for (int i=0;i<360;i+=stepDegrees)
|
||||
{
|
||||
capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
|
||||
capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
|
||||
drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
|
||||
capEnd[(upAxis+1)%3] = capStart[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
|
||||
capEnd[(upAxis+2)%3] = capStart[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
|
||||
drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
|
||||
}
|
||||
// Drawing top and bottom caps of the cylinder
|
||||
btVector3 yaxis(0, 0, 0);
|
||||
btVector3 yaxis(0,0,0);
|
||||
yaxis[upAxis] = btScalar(1.0);
|
||||
btVector3 xaxis(0, 0, 0);
|
||||
xaxis[(upAxis + 1) % 3] = btScalar(1.0);
|
||||
drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
|
||||
drawArc(start + transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
|
||||
btVector3 xaxis(0,0,0);
|
||||
xaxis[(upAxis+1)%3] = btScalar(1.0);
|
||||
drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
|
||||
drawArc(start+transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
|
||||
}
|
||||
|
||||
virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
|
||||
|
|
@ -416,49 +423,50 @@ public:
|
|||
int stepDegrees = 30;
|
||||
btVector3 start = transform.getOrigin();
|
||||
|
||||
btVector3 offsetHeight(0, 0, 0);
|
||||
btVector3 offsetHeight(0,0,0);
|
||||
btScalar halfHeight = height * btScalar(0.5);
|
||||
offsetHeight[upAxis] = halfHeight;
|
||||
btVector3 offsetRadius(0, 0, 0);
|
||||
offsetRadius[(upAxis + 1) % 3] = radius;
|
||||
btVector3 offset2Radius(0, 0, 0);
|
||||
offset2Radius[(upAxis + 2) % 3] = radius;
|
||||
btVector3 offsetRadius(0,0,0);
|
||||
offsetRadius[(upAxis+1)%3] = radius;
|
||||
btVector3 offset2Radius(0,0,0);
|
||||
offset2Radius[(upAxis+2)%3] = radius;
|
||||
|
||||
btVector3 capEnd(0.f, 0.f, 0.f);
|
||||
|
||||
btVector3 capEnd(0.f,0.f,0.f);
|
||||
capEnd[upAxis] = -halfHeight;
|
||||
|
||||
for (int i = 0; i < 360; i += stepDegrees)
|
||||
for (int i=0;i<360;i+=stepDegrees)
|
||||
{
|
||||
capEnd[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
|
||||
capEnd[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
|
||||
drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * capEnd, color);
|
||||
capEnd[(upAxis+1)%3] = btSin(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
|
||||
capEnd[(upAxis+2)%3] = btCos(btScalar(i)*SIMD_RADS_PER_DEG)*radius;
|
||||
drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * capEnd, color);
|
||||
}
|
||||
|
||||
drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offsetRadius), color);
|
||||
drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offsetRadius), color);
|
||||
drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offset2Radius), color);
|
||||
drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offset2Radius), color);
|
||||
drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offsetRadius),color);
|
||||
drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offsetRadius),color);
|
||||
drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offset2Radius),color);
|
||||
drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offset2Radius),color);
|
||||
|
||||
// Drawing the base of the cone
|
||||
btVector3 yaxis(0, 0, 0);
|
||||
btVector3 yaxis(0,0,0);
|
||||
yaxis[upAxis] = btScalar(1.0);
|
||||
btVector3 xaxis(0, 0, 0);
|
||||
xaxis[(upAxis + 1) % 3] = btScalar(1.0);
|
||||
drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
|
||||
btVector3 xaxis(0,0,0);
|
||||
xaxis[(upAxis+1)%3] = btScalar(1.0);
|
||||
drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0);
|
||||
}
|
||||
|
||||
virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color)
|
||||
{
|
||||
btVector3 planeOrigin = planeNormal * planeConst;
|
||||
btVector3 vec0, vec1;
|
||||
btPlaneSpace1(planeNormal, vec0, vec1);
|
||||
btVector3 vec0,vec1;
|
||||
btPlaneSpace1(planeNormal,vec0,vec1);
|
||||
btScalar vecLen = 100.f;
|
||||
btVector3 pt0 = planeOrigin + vec0 * vecLen;
|
||||
btVector3 pt1 = planeOrigin - vec0 * vecLen;
|
||||
btVector3 pt2 = planeOrigin + vec1 * vecLen;
|
||||
btVector3 pt3 = planeOrigin - vec1 * vecLen;
|
||||
drawLine(transform * pt0, transform * pt1, color);
|
||||
drawLine(transform * pt2, transform * pt3, color);
|
||||
btVector3 pt0 = planeOrigin + vec0*vecLen;
|
||||
btVector3 pt1 = planeOrigin - vec0*vecLen;
|
||||
btVector3 pt2 = planeOrigin + vec1*vecLen;
|
||||
btVector3 pt3 = planeOrigin - vec1*vecLen;
|
||||
drawLine(transform*pt0,transform*pt1,color);
|
||||
drawLine(transform*pt2,transform*pt3,color);
|
||||
}
|
||||
|
||||
virtual void clearLines()
|
||||
|
|
@ -470,4 +478,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#endif //BT_IDEBUG_DRAW__H
|
||||
|
||||
#endif //BT_IDEBUG_DRAW__H
|
||||
|
||||
|
|
|
|||
|
|
@ -12,62 +12,62 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_GEN_LIST_H
|
||||
#define BT_GEN_LIST_H
|
||||
|
||||
class btGEN_Link
|
||||
{
|
||||
class btGEN_Link {
|
||||
public:
|
||||
btGEN_Link() : m_next(0), m_prev(0) {}
|
||||
btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
|
||||
btGEN_Link() : m_next(0), m_prev(0) {}
|
||||
btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
|
||||
|
||||
btGEN_Link *getNext() const { return m_next; }
|
||||
btGEN_Link *getPrev() const { return m_prev; }
|
||||
|
||||
btGEN_Link *getNext() const { return m_next; }
|
||||
btGEN_Link *getPrev() const { return m_prev; }
|
||||
bool isHead() const { return m_prev == 0; }
|
||||
bool isTail() const { return m_next == 0; }
|
||||
|
||||
bool isHead() const { return m_prev == 0; }
|
||||
bool isTail() const { return m_next == 0; }
|
||||
void insertBefore(btGEN_Link *link) {
|
||||
m_next = link;
|
||||
m_prev = link->m_prev;
|
||||
m_next->m_prev = this;
|
||||
m_prev->m_next = this;
|
||||
}
|
||||
|
||||
void insertBefore(btGEN_Link *link)
|
||||
{
|
||||
m_next = link;
|
||||
m_prev = link->m_prev;
|
||||
m_next->m_prev = this;
|
||||
m_prev->m_next = this;
|
||||
}
|
||||
void insertAfter(btGEN_Link *link) {
|
||||
m_next = link->m_next;
|
||||
m_prev = link;
|
||||
m_next->m_prev = this;
|
||||
m_prev->m_next = this;
|
||||
}
|
||||
|
||||
void insertAfter(btGEN_Link *link)
|
||||
{
|
||||
m_next = link->m_next;
|
||||
m_prev = link;
|
||||
m_next->m_prev = this;
|
||||
m_prev->m_next = this;
|
||||
}
|
||||
void remove() {
|
||||
m_next->m_prev = m_prev;
|
||||
m_prev->m_next = m_next;
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
m_next->m_prev = m_prev;
|
||||
m_prev->m_next = m_next;
|
||||
}
|
||||
|
||||
private:
|
||||
btGEN_Link *m_next;
|
||||
btGEN_Link *m_prev;
|
||||
private:
|
||||
btGEN_Link *m_next;
|
||||
btGEN_Link *m_prev;
|
||||
};
|
||||
|
||||
class btGEN_List
|
||||
{
|
||||
class btGEN_List {
|
||||
public:
|
||||
btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
|
||||
btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
|
||||
|
||||
btGEN_Link *getHead() const { return m_head.getNext(); }
|
||||
btGEN_Link *getTail() const { return m_tail.getPrev(); }
|
||||
|
||||
void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
|
||||
void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
|
||||
btGEN_Link *getHead() const { return m_head.getNext(); }
|
||||
btGEN_Link *getTail() const { return m_tail.getPrev(); }
|
||||
|
||||
void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
|
||||
void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
|
||||
|
||||
private:
|
||||
btGEN_Link m_head;
|
||||
btGEN_Link m_tail;
|
||||
btGEN_Link m_head;
|
||||
btGEN_Link m_tail;
|
||||
};
|
||||
|
||||
#endif //BT_GEN_LIST_H
|
||||
#endif //BT_GEN_LIST_H
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -24,23 +24,24 @@ subject to the following restrictions:
|
|||
//#define BT_DEBUG_OSTREAM
|
||||
#ifdef BT_DEBUG_OSTREAM
|
||||
#include <iostream>
|
||||
#include <iomanip> // std::setw
|
||||
#endif //BT_DEBUG_OSTREAM
|
||||
#include <iomanip> // std::setw
|
||||
#endif //BT_DEBUG_OSTREAM
|
||||
|
||||
class btIntSortPredicate
|
||||
{
|
||||
public:
|
||||
bool operator()(const int& a, const int& b) const
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
public:
|
||||
bool operator() ( const int& a, const int& b ) const
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct btVectorX
|
||||
{
|
||||
btAlignedObjectArray<T> m_storage;
|
||||
|
||||
btAlignedObjectArray<T> m_storage;
|
||||
|
||||
btVectorX()
|
||||
{
|
||||
}
|
||||
|
|
@ -48,7 +49,7 @@ struct btVectorX
|
|||
{
|
||||
m_storage.resize(numRows);
|
||||
}
|
||||
|
||||
|
||||
void resize(int rows)
|
||||
{
|
||||
m_storage.resize(rows);
|
||||
|
|
@ -65,13 +66,13 @@ struct btVectorX
|
|||
{
|
||||
return rows();
|
||||
}
|
||||
|
||||
|
||||
T nrm2() const
|
||||
{
|
||||
T norm = T(0);
|
||||
|
||||
|
||||
int nn = rows();
|
||||
|
||||
|
||||
{
|
||||
if (nn == 1)
|
||||
{
|
||||
|
|
@ -81,11 +82,11 @@ struct btVectorX
|
|||
{
|
||||
T scale = 0.0;
|
||||
T ssq = 1.0;
|
||||
|
||||
|
||||
/* The following loop is equivalent to this call to the LAPACK
|
||||
auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
|
||||
|
||||
for (int ix = 0; ix < nn; ix++)
|
||||
|
||||
for (int ix=0;ix<nn;ix++)
|
||||
{
|
||||
if ((*this)[ix] != 0.0)
|
||||
{
|
||||
|
|
@ -109,36 +110,38 @@ struct btVectorX
|
|||
}
|
||||
}
|
||||
return norm;
|
||||
|
||||
}
|
||||
void setZero()
|
||||
void setZero()
|
||||
{
|
||||
if (m_storage.size())
|
||||
{
|
||||
// for (int i=0;i<m_storage.size();i++)
|
||||
// m_storage[i]=0;
|
||||
//memset(&m_storage[0],0,sizeof(T)*m_storage.size());
|
||||
btSetZero(&m_storage[0], m_storage.size());
|
||||
btSetZero(&m_storage[0],m_storage.size());
|
||||
}
|
||||
}
|
||||
const T& operator[](int index) const
|
||||
const T& operator[] (int index) const
|
||||
{
|
||||
return m_storage[index];
|
||||
}
|
||||
|
||||
T& operator[](int index)
|
||||
|
||||
T& operator[] (int index)
|
||||
{
|
||||
return m_storage[index];
|
||||
}
|
||||
|
||||
|
||||
T* getBufferPointerWritable()
|
||||
{
|
||||
return m_storage.size() ? &m_storage[0] : 0;
|
||||
}
|
||||
|
||||
|
||||
const T* getBufferPointer() const
|
||||
{
|
||||
return m_storage.size() ? &m_storage[0] : 0;
|
||||
}
|
||||
|
||||
};
|
||||
/*
|
||||
template <typename T>
|
||||
|
|
@ -148,7 +151,8 @@ struct btVectorX
|
|||
}
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
|
||||
template <typename T>
|
||||
struct btMatrixX
|
||||
{
|
||||
int m_rows;
|
||||
|
|
@ -157,10 +161,10 @@ struct btMatrixX
|
|||
int m_resizeOperations;
|
||||
int m_setElemOperations;
|
||||
|
||||
btAlignedObjectArray<T> m_storage;
|
||||
mutable btAlignedObjectArray<btAlignedObjectArray<int> > m_rowNonZeroElements1;
|
||||
btAlignedObjectArray<T> m_storage;
|
||||
mutable btAlignedObjectArray< btAlignedObjectArray<int> > m_rowNonZeroElements1;
|
||||
|
||||
T* getBufferPointerWritable()
|
||||
T* getBufferPointerWritable()
|
||||
{
|
||||
return m_storage.size() ? &m_storage[0] : 0;
|
||||
}
|
||||
|
|
@ -170,21 +174,21 @@ struct btMatrixX
|
|||
return m_storage.size() ? &m_storage[0] : 0;
|
||||
}
|
||||
btMatrixX()
|
||||
: m_rows(0),
|
||||
m_cols(0),
|
||||
m_operations(0),
|
||||
m_resizeOperations(0),
|
||||
m_setElemOperations(0)
|
||||
:m_rows(0),
|
||||
m_cols(0),
|
||||
m_operations(0),
|
||||
m_resizeOperations(0),
|
||||
m_setElemOperations(0)
|
||||
{
|
||||
}
|
||||
btMatrixX(int rows, int cols)
|
||||
: m_rows(rows),
|
||||
m_cols(cols),
|
||||
m_operations(0),
|
||||
m_resizeOperations(0),
|
||||
m_setElemOperations(0)
|
||||
btMatrixX(int rows,int cols)
|
||||
:m_rows(rows),
|
||||
m_cols(cols),
|
||||
m_operations(0),
|
||||
m_resizeOperations(0),
|
||||
m_setElemOperations(0)
|
||||
{
|
||||
resize(rows, cols);
|
||||
resize(rows,cols);
|
||||
}
|
||||
void resize(int rows, int cols)
|
||||
{
|
||||
|
|
@ -193,7 +197,7 @@ struct btMatrixX
|
|||
m_cols = cols;
|
||||
{
|
||||
BT_PROFILE("m_storage.resize");
|
||||
m_storage.resize(rows * cols);
|
||||
m_storage.resize(rows*cols);
|
||||
}
|
||||
}
|
||||
int cols() const
|
||||
|
|
@ -211,102 +215,108 @@ struct btMatrixX
|
|||
}
|
||||
*/
|
||||
|
||||
void addElem(int row, int col, T val)
|
||||
void addElem(int row,int col, T val)
|
||||
{
|
||||
if (val)
|
||||
{
|
||||
if (m_storage[col + row * m_cols] == 0.f)
|
||||
if (m_storage[col+row*m_cols]==0.f)
|
||||
{
|
||||
setElem(row, col, val);
|
||||
}
|
||||
else
|
||||
setElem(row,col,val);
|
||||
} else
|
||||
{
|
||||
m_storage[row * m_cols + col] += val;
|
||||
m_storage[row*m_cols+col] += val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setElem(int row, int col, T val)
|
||||
|
||||
|
||||
void setElem(int row,int col, T val)
|
||||
{
|
||||
m_setElemOperations++;
|
||||
m_storage[row * m_cols + col] = val;
|
||||
m_storage[row*m_cols+col] = val;
|
||||
}
|
||||
|
||||
void mulElem(int row, int col, T val)
|
||||
|
||||
void mulElem(int row,int col, T val)
|
||||
{
|
||||
m_setElemOperations++;
|
||||
//mul doesn't change sparsity info
|
||||
|
||||
m_storage[row * m_cols + col] *= val;
|
||||
m_storage[row*m_cols+col] *= val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void copyLowerToUpperTriangle()
|
||||
{
|
||||
int count = 0;
|
||||
for (int row = 0; row < rows(); row++)
|
||||
int count=0;
|
||||
for (int row=0;row<rows();row++)
|
||||
{
|
||||
for (int col = 0; col < row; col++)
|
||||
for (int col=0;col<row;col++)
|
||||
{
|
||||
setElem(col, row, (*this)(row, col));
|
||||
setElem(col,row, (*this)(row,col));
|
||||
count++;
|
||||
|
||||
}
|
||||
}
|
||||
//printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
|
||||
}
|
||||
|
||||
const T& operator()(int row, int col) const
|
||||
|
||||
const T& operator() (int row,int col) const
|
||||
{
|
||||
return m_storage[col + row * m_cols];
|
||||
return m_storage[col+row*m_cols];
|
||||
}
|
||||
|
||||
|
||||
void setZero()
|
||||
{
|
||||
{
|
||||
BT_PROFILE("storage=0");
|
||||
if (m_storage.size())
|
||||
{
|
||||
btSetZero(&m_storage[0], m_storage.size());
|
||||
}
|
||||
btSetZero(&m_storage[0],m_storage.size());
|
||||
//memset(&m_storage[0],0,sizeof(T)*m_storage.size());
|
||||
//for (int i=0;i<m_storage.size();i++)
|
||||
// m_storage[i]=0;
|
||||
// m_storage[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setIdentity()
|
||||
{
|
||||
btAssert(rows() == cols());
|
||||
|
||||
|
||||
setZero();
|
||||
for (int row = 0; row < rows(); row++)
|
||||
for (int row=0;row<rows();row++)
|
||||
{
|
||||
setElem(row, row, 1);
|
||||
setElem(row,row,1);
|
||||
}
|
||||
}
|
||||
|
||||
void printMatrix(const char* msg) const
|
||||
|
||||
|
||||
void printMatrix(const char* msg)
|
||||
{
|
||||
printf("%s ---------------------\n", msg);
|
||||
for (int i = 0; i < rows(); i++)
|
||||
printf("%s ---------------------\n",msg);
|
||||
for (int i=0;i<rows();i++)
|
||||
{
|
||||
printf("\n");
|
||||
for (int j = 0; j < cols(); j++)
|
||||
for (int j=0;j<cols();j++)
|
||||
{
|
||||
printf("%2.1f\t", (*this)(i, j));
|
||||
printf("%2.1f\t",(*this)(i,j));
|
||||
}
|
||||
}
|
||||
printf("\n---------------------\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void rowComputeNonZeroElements() const
|
||||
{
|
||||
m_rowNonZeroElements1.resize(rows());
|
||||
for (int i = 0; i < rows(); i++)
|
||||
for (int i=0;i<rows();i++)
|
||||
{
|
||||
m_rowNonZeroElements1[i].resize(0);
|
||||
for (int j = 0; j < cols(); j++)
|
||||
for (int j=0;j<cols();j++)
|
||||
{
|
||||
if ((*this)(i, j) != 0.f)
|
||||
if ((*this)(i,j)!=0.f)
|
||||
{
|
||||
m_rowNonZeroElements1[i].push_back(j);
|
||||
}
|
||||
|
|
@ -316,52 +326,54 @@ struct btMatrixX
|
|||
btMatrixX transpose() const
|
||||
{
|
||||
//transpose is optimized for sparse matrices
|
||||
btMatrixX tr(m_cols, m_rows);
|
||||
btMatrixX tr(m_cols,m_rows);
|
||||
tr.setZero();
|
||||
for (int i = 0; i < m_cols; i++)
|
||||
for (int j = 0; j < m_rows; j++)
|
||||
for (int i=0;i<m_cols;i++)
|
||||
for (int j=0;j<m_rows;j++)
|
||||
{
|
||||
T v = (*this)(j, i);
|
||||
T v = (*this)(j,i);
|
||||
if (v)
|
||||
{
|
||||
tr.setElem(i, j, v);
|
||||
tr.setElem(i,j,v);
|
||||
}
|
||||
}
|
||||
return tr;
|
||||
}
|
||||
|
||||
|
||||
btMatrixX operator*(const btMatrixX& other)
|
||||
{
|
||||
//btMatrixX*btMatrixX implementation, brute force
|
||||
btAssert(cols() == other.rows());
|
||||
|
||||
btMatrixX res(rows(), other.cols());
|
||||
btMatrixX res(rows(),other.cols());
|
||||
res.setZero();
|
||||
// BT_PROFILE("btMatrixX mul");
|
||||
for (int j = 0; j < res.cols(); ++j)
|
||||
// BT_PROFILE("btMatrixX mul");
|
||||
for (int j=0; j < res.cols(); ++j)
|
||||
{
|
||||
{
|
||||
for (int i = 0; i < res.rows(); ++i)
|
||||
for (int i=0; i < res.rows(); ++i)
|
||||
{
|
||||
T dotProd = 0;
|
||||
// T dotProd2=0;
|
||||
T dotProd=0;
|
||||
// T dotProd2=0;
|
||||
//int waste=0,waste2=0;
|
||||
|
||||
{
|
||||
// bool useOtherCol = true;
|
||||
// bool useOtherCol = true;
|
||||
{
|
||||
for (int v = 0; v < rows(); v++)
|
||||
for (int v=0;v<rows();v++)
|
||||
{
|
||||
T w = (*this)(i, v);
|
||||
if (other(v, j) != 0.f)
|
||||
T w = (*this)(i,v);
|
||||
if (other(v,j)!=0.f)
|
||||
{
|
||||
dotProd += w * other(v, j);
|
||||
dotProd+=w*other(v,j);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dotProd)
|
||||
res.setElem(i, j, dotProd);
|
||||
res.setElem(i,j,dotProd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -369,166 +381,174 @@ struct btMatrixX
|
|||
}
|
||||
|
||||
// this assumes the 4th and 8th rows of B and C are zero.
|
||||
void multiplyAdd2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
|
||||
void multiplyAdd2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther ,int row, int col)
|
||||
{
|
||||
const btScalar* bb = B;
|
||||
for (int i = 0; i < numRows; i++)
|
||||
const btScalar *bb = B;
|
||||
for ( int i = 0;i<numRows;i++)
|
||||
{
|
||||
const btScalar* cc = C;
|
||||
for (int j = 0; j < numRowsOther; j++)
|
||||
const btScalar *cc = C;
|
||||
for ( int j = 0;j<numRowsOther;j++)
|
||||
{
|
||||
btScalar sum;
|
||||
sum = bb[0] * cc[0];
|
||||
sum += bb[1] * cc[1];
|
||||
sum += bb[2] * cc[2];
|
||||
sum += bb[4] * cc[4];
|
||||
sum += bb[5] * cc[5];
|
||||
sum += bb[6] * cc[6];
|
||||
addElem(row + i, col + j, sum);
|
||||
sum = bb[0]*cc[0];
|
||||
sum += bb[1]*cc[1];
|
||||
sum += bb[2]*cc[2];
|
||||
sum += bb[4]*cc[4];
|
||||
sum += bb[5]*cc[5];
|
||||
sum += bb[6]*cc[6];
|
||||
addElem(row+i,col+j,sum);
|
||||
cc += 8;
|
||||
}
|
||||
bb += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void multiply2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
|
||||
void multiply2_p8r (const btScalar *B, const btScalar *C, int numRows, int numRowsOther, int row, int col)
|
||||
{
|
||||
btAssert(numRows > 0 && numRowsOther > 0 && B && C);
|
||||
const btScalar* bb = B;
|
||||
for (int i = 0; i < numRows; i++)
|
||||
btAssert (numRows>0 && numRowsOther>0 && B && C);
|
||||
const btScalar *bb = B;
|
||||
for ( int i = 0;i<numRows;i++)
|
||||
{
|
||||
const btScalar* cc = C;
|
||||
for (int j = 0; j < numRowsOther; j++)
|
||||
const btScalar *cc = C;
|
||||
for ( int j = 0;j<numRowsOther;j++)
|
||||
{
|
||||
btScalar sum;
|
||||
sum = bb[0] * cc[0];
|
||||
sum += bb[1] * cc[1];
|
||||
sum += bb[2] * cc[2];
|
||||
sum += bb[4] * cc[4];
|
||||
sum += bb[5] * cc[5];
|
||||
sum += bb[6] * cc[6];
|
||||
setElem(row + i, col + j, sum);
|
||||
sum = bb[0]*cc[0];
|
||||
sum += bb[1]*cc[1];
|
||||
sum += bb[2]*cc[2];
|
||||
sum += bb[4]*cc[4];
|
||||
sum += bb[5]*cc[5];
|
||||
sum += bb[6]*cc[6];
|
||||
setElem(row+i,col+j,sum);
|
||||
cc += 8;
|
||||
}
|
||||
bb += 8;
|
||||
}
|
||||
}
|
||||
|
||||
void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const T value)
|
||||
|
||||
void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const T value)
|
||||
{
|
||||
int numRows = rowend + 1 - rowstart;
|
||||
int numCols = colend + 1 - colstart;
|
||||
|
||||
for (int row = 0; row < numRows; row++)
|
||||
int numRows = rowend+1-rowstart;
|
||||
int numCols = colend+1-colstart;
|
||||
|
||||
for (int row=0;row<numRows;row++)
|
||||
{
|
||||
for (int col = 0; col < numCols; col++)
|
||||
for (int col=0;col<numCols;col++)
|
||||
{
|
||||
setElem(rowstart + row, colstart + col, value);
|
||||
setElem(rowstart+row,colstart+col,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btMatrixX& block)
|
||||
|
||||
void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btMatrixX& block)
|
||||
{
|
||||
btAssert(rowend + 1 - rowstart == block.rows());
|
||||
btAssert(colend + 1 - colstart == block.cols());
|
||||
for (int row = 0; row < block.rows(); row++)
|
||||
btAssert(rowend+1-rowstart == block.rows());
|
||||
btAssert(colend+1-colstart == block.cols());
|
||||
for (int row=0;row<block.rows();row++)
|
||||
{
|
||||
for (int col = 0; col < block.cols(); col++)
|
||||
for (int col=0;col<block.cols();col++)
|
||||
{
|
||||
setElem(rowstart + row, colstart + col, block(row, col));
|
||||
setElem(rowstart+row,colstart+col,block(row,col));
|
||||
}
|
||||
}
|
||||
}
|
||||
void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btVectorX<T>& block)
|
||||
void setSubMatrix(int rowstart,int colstart,int rowend,int colend,const btVectorX<T>& block)
|
||||
{
|
||||
btAssert(rowend + 1 - rowstart == block.rows());
|
||||
btAssert(colend + 1 - colstart == block.cols());
|
||||
for (int row = 0; row < block.rows(); row++)
|
||||
btAssert(rowend+1-rowstart == block.rows());
|
||||
btAssert(colend+1-colstart == block.cols());
|
||||
for (int row=0;row<block.rows();row++)
|
||||
{
|
||||
for (int col = 0; col < block.cols(); col++)
|
||||
for (int col=0;col<block.cols();col++)
|
||||
{
|
||||
setElem(rowstart + row, colstart + col, block[row]);
|
||||
setElem(rowstart+row,colstart+col,block[row]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
btMatrixX negative()
|
||||
{
|
||||
btMatrixX neg(rows(), cols());
|
||||
for (int i = 0; i < rows(); i++)
|
||||
for (int j = 0; j < cols(); j++)
|
||||
btMatrixX neg(rows(),cols());
|
||||
for (int i=0;i<rows();i++)
|
||||
for (int j=0;j<cols();j++)
|
||||
{
|
||||
T v = (*this)(i, j);
|
||||
neg.setElem(i, j, -v);
|
||||
T v = (*this)(i,j);
|
||||
neg.setElem(i,j,-v);
|
||||
}
|
||||
return neg;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef btMatrixX<float> btMatrixXf;
|
||||
typedef btVectorX<float> btVectorXf;
|
||||
|
||||
typedef btMatrixX<double> btMatrixXd;
|
||||
typedef btVectorX<double> btVectorXd;
|
||||
|
||||
|
||||
#ifdef BT_DEBUG_OSTREAM
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& os, const btMatrixX<T>& mat)
|
||||
{
|
||||
os << " [";
|
||||
//printf("%s ---------------------\n",msg);
|
||||
for (int i = 0; i < mat.rows(); i++)
|
||||
template <typename T>
|
||||
std::ostream& operator<< (std::ostream& os, const btMatrixX<T>& mat)
|
||||
{
|
||||
for (int j = 0; j < mat.cols(); j++)
|
||||
|
||||
os << " [";
|
||||
//printf("%s ---------------------\n",msg);
|
||||
for (int i=0;i<mat.rows();i++)
|
||||
{
|
||||
os << std::setw(12) << mat(i, j);
|
||||
for (int j=0;j<mat.cols();j++)
|
||||
{
|
||||
os << std::setw(12) << mat(i,j);
|
||||
}
|
||||
if (i!=mat.rows()-1)
|
||||
os << std::endl << " ";
|
||||
}
|
||||
if (i != mat.rows() - 1)
|
||||
os << std::endl
|
||||
<< " ";
|
||||
}
|
||||
os << " ]";
|
||||
//printf("\n---------------------\n");
|
||||
os << " ]";
|
||||
//printf("\n---------------------\n");
|
||||
|
||||
return os;
|
||||
}
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& os, const btVectorX<T>& mat)
|
||||
{
|
||||
os << " [";
|
||||
//printf("%s ---------------------\n",msg);
|
||||
for (int i = 0; i < mat.rows(); i++)
|
||||
return os;
|
||||
}
|
||||
template <typename T>
|
||||
std::ostream& operator<< (std::ostream& os, const btVectorX<T>& mat)
|
||||
{
|
||||
os << std::setw(12) << mat[i];
|
||||
if (i != mat.rows() - 1)
|
||||
os << std::endl
|
||||
<< " ";
|
||||
|
||||
os << " [";
|
||||
//printf("%s ---------------------\n",msg);
|
||||
for (int i=0;i<mat.rows();i++)
|
||||
{
|
||||
os << std::setw(12) << mat[i];
|
||||
if (i!=mat.rows()-1)
|
||||
os << std::endl << " ";
|
||||
}
|
||||
os << " ]";
|
||||
//printf("\n---------------------\n");
|
||||
|
||||
return os;
|
||||
}
|
||||
os << " ]";
|
||||
//printf("\n---------------------\n");
|
||||
|
||||
return os;
|
||||
}
|
||||
#endif //BT_DEBUG_OSTREAM
|
||||
|
||||
#endif //BT_DEBUG_OSTREAM
|
||||
|
||||
inline void setElem(btMatrixXd& mat, int row, int col, double val)
|
||||
{
|
||||
mat.setElem(row, col, val);
|
||||
mat.setElem(row,col,val);
|
||||
}
|
||||
|
||||
inline void setElem(btMatrixXf& mat, int row, int col, float val)
|
||||
{
|
||||
mat.setElem(row, col, val);
|
||||
mat.setElem(row,col,val);
|
||||
}
|
||||
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
#define btVectorXu btVectorXd
|
||||
#define btMatrixXu btMatrixXd
|
||||
#define btVectorXu btVectorXd
|
||||
#define btMatrixXu btMatrixXd
|
||||
#else
|
||||
#define btVectorXu btVectorXf
|
||||
#define btMatrixXu btMatrixXf
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
#define btVectorXu btVectorXf
|
||||
#define btMatrixXu btMatrixXf
|
||||
#endif //BT_USE_DOUBLE_PRECISION
|
||||
|
||||
#endif //BT_MATRIX_H_H
|
||||
|
||||
|
||||
#endif//BT_MATRIX_H_H
|
||||
|
|
|
|||
|
|
@ -12,58 +12,60 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_GEN_MINMAX_H
|
||||
#define BT_GEN_MINMAX_H
|
||||
|
||||
#include "btScalar.h"
|
||||
|
||||
template <class T>
|
||||
SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
|
||||
SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
return a < b ? a : b ;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
|
||||
SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
|
||||
SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
|
||||
{
|
||||
return a < lb ? lb : (ub < a ? ub : a);
|
||||
return a < lb ? lb : (ub < a ? ub : a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
|
||||
SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
|
||||
{
|
||||
if (b < a)
|
||||
if (b < a)
|
||||
{
|
||||
a = b;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
|
||||
SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
|
||||
{
|
||||
if (a < b)
|
||||
if (a < b)
|
||||
{
|
||||
a = b;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
|
||||
SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
|
||||
{
|
||||
if (a < lb)
|
||||
if (a < lb)
|
||||
{
|
||||
a = lb;
|
||||
a = lb;
|
||||
}
|
||||
else if (ub < a)
|
||||
else if (ub < a)
|
||||
{
|
||||
a = ub;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //BT_GEN_MINMAX_H
|
||||
#endif //BT_GEN_MINMAX_H
|
||||
|
|
|
|||
|
|
@ -20,17 +20,21 @@ subject to the following restrictions:
|
|||
|
||||
///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
|
||||
///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
|
||||
class btMotionState
|
||||
class btMotionState
|
||||
{
|
||||
public:
|
||||
virtual ~btMotionState()
|
||||
{
|
||||
}
|
||||
public:
|
||||
|
||||
virtual ~btMotionState()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void getWorldTransform(btTransform& worldTrans ) const =0;
|
||||
|
||||
virtual void getWorldTransform(btTransform& worldTrans) const = 0;
|
||||
|
||||
//Bullet only calls the update of worldtransform for active objects
|
||||
virtual void setWorldTransform(const btTransform& worldTrans) = 0;
|
||||
//Bullet only calls the update of worldtransform for active objects
|
||||
virtual void setWorldTransform(const btTransform& worldTrans)=0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_MOTIONSTATE_H
|
||||
#endif //BT_MOTIONSTATE_H
|
||||
|
|
|
|||
|
|
@ -3,92 +3,96 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
btScalar abs_column_sum(const btMatrix3x3& a, int i)
|
||||
{
|
||||
return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
|
||||
btScalar abs_column_sum(const btMatrix3x3& a, int i)
|
||||
{
|
||||
return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
|
||||
}
|
||||
|
||||
btScalar abs_row_sum(const btMatrix3x3& a, int i)
|
||||
{
|
||||
return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
|
||||
}
|
||||
|
||||
btScalar p1_norm(const btMatrix3x3& a)
|
||||
{
|
||||
const btScalar sum0 = abs_column_sum(a,0);
|
||||
const btScalar sum1 = abs_column_sum(a,1);
|
||||
const btScalar sum2 = abs_column_sum(a,2);
|
||||
return btMax(btMax(sum0, sum1), sum2);
|
||||
}
|
||||
|
||||
btScalar pinf_norm(const btMatrix3x3& a)
|
||||
{
|
||||
const btScalar sum0 = abs_row_sum(a,0);
|
||||
const btScalar sum1 = abs_row_sum(a,1);
|
||||
const btScalar sum2 = abs_row_sum(a,2);
|
||||
return btMax(btMax(sum0, sum1), sum2);
|
||||
}
|
||||
}
|
||||
|
||||
btScalar abs_row_sum(const btMatrix3x3& a, int i)
|
||||
{
|
||||
return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
|
||||
}
|
||||
|
||||
btScalar p1_norm(const btMatrix3x3& a)
|
||||
{
|
||||
const btScalar sum0 = abs_column_sum(a, 0);
|
||||
const btScalar sum1 = abs_column_sum(a, 1);
|
||||
const btScalar sum2 = abs_column_sum(a, 2);
|
||||
return btMax(btMax(sum0, sum1), sum2);
|
||||
}
|
||||
|
||||
btScalar pinf_norm(const btMatrix3x3& a)
|
||||
{
|
||||
const btScalar sum0 = abs_row_sum(a, 0);
|
||||
const btScalar sum1 = abs_row_sum(a, 1);
|
||||
const btScalar sum2 = abs_row_sum(a, 2);
|
||||
return btMax(btMax(sum0, sum1), sum2);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
|
||||
: m_tolerance(tolerance), m_maxIterations(maxIterations)
|
||||
: m_tolerance(tolerance)
|
||||
, m_maxIterations(maxIterations)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const
|
||||
{
|
||||
// Use the 'u' and 'h' matrices for intermediate calculations
|
||||
u = a;
|
||||
h = a.inverse();
|
||||
// Use the 'u' and 'h' matrices for intermediate calculations
|
||||
u = a;
|
||||
h = a.inverse();
|
||||
|
||||
for (unsigned int i = 0; i < m_maxIterations; ++i)
|
||||
{
|
||||
const btScalar h_1 = p1_norm(h);
|
||||
const btScalar h_inf = pinf_norm(h);
|
||||
const btScalar u_1 = p1_norm(u);
|
||||
const btScalar u_inf = pinf_norm(u);
|
||||
for (unsigned int i = 0; i < m_maxIterations; ++i)
|
||||
{
|
||||
const btScalar h_1 = p1_norm(h);
|
||||
const btScalar h_inf = pinf_norm(h);
|
||||
const btScalar u_1 = p1_norm(u);
|
||||
const btScalar u_inf = pinf_norm(u);
|
||||
|
||||
const btScalar h_norm = h_1 * h_inf;
|
||||
const btScalar u_norm = u_1 * u_inf;
|
||||
const btScalar h_norm = h_1 * h_inf;
|
||||
const btScalar u_norm = u_1 * u_inf;
|
||||
|
||||
// The matrix is effectively singular so we cannot invert it
|
||||
if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
|
||||
break;
|
||||
// The matrix is effectively singular so we cannot invert it
|
||||
if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
|
||||
break;
|
||||
|
||||
const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
|
||||
const btScalar inv_gamma = btScalar(1.0) / gamma;
|
||||
const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
|
||||
const btScalar inv_gamma = btScalar(1.0) / gamma;
|
||||
|
||||
// Determine the delta to 'u'
|
||||
const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
|
||||
// Determine the delta to 'u'
|
||||
const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
|
||||
|
||||
// Update the matrices
|
||||
u += delta;
|
||||
h = u.inverse();
|
||||
// Update the matrices
|
||||
u += delta;
|
||||
h = u.inverse();
|
||||
|
||||
// Check for convergence
|
||||
if (p1_norm(delta) <= m_tolerance * u_1)
|
||||
{
|
||||
h = u.transpose() * a;
|
||||
h = (h + h.transpose()) * 0.5;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// Check for convergence
|
||||
if (p1_norm(delta) <= m_tolerance * u_1)
|
||||
{
|
||||
h = u.transpose() * a;
|
||||
h = (h + h.transpose()) * 0.5;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// The algorithm has failed to converge to the specified tolerance, but we
|
||||
// want to make sure that the matrices returned are in the right form.
|
||||
h = u.transpose() * a;
|
||||
h = (h + h.transpose()) * 0.5;
|
||||
// The algorithm has failed to converge to the specified tolerance, but we
|
||||
// want to make sure that the matrices returned are in the right form.
|
||||
h = u.transpose() * a;
|
||||
h = (h + h.transpose()) * 0.5;
|
||||
|
||||
return m_maxIterations;
|
||||
return m_maxIterations;
|
||||
}
|
||||
|
||||
unsigned int btPolarDecomposition::maxIterations() const
|
||||
{
|
||||
return m_maxIterations;
|
||||
return m_maxIterations;
|
||||
}
|
||||
|
||||
unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h)
|
||||
{
|
||||
static btPolarDecomposition polar;
|
||||
return polar.decompose(a, u, h);
|
||||
static btPolarDecomposition polar;
|
||||
return polar.decompose(a, u, h);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@
|
|||
*/
|
||||
class btPolarDecomposition
|
||||
{
|
||||
public:
|
||||
/**
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Creates an instance with optional parameters.
|
||||
*
|
||||
* @param tolerance - the tolerance used to determine convergence of the
|
||||
|
|
@ -22,10 +24,10 @@ public:
|
|||
* @param maxIterations - the maximum number of iterations used to achieve
|
||||
* convergence
|
||||
*/
|
||||
btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
|
||||
unsigned int maxIterations = 16);
|
||||
btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
|
||||
unsigned int maxIterations = 16);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Decomposes a matrix into orthogonal and symmetric, positive-definite
|
||||
* parts. If the number of iterations returned by this function is equal to
|
||||
* the maximum number of iterations, the algorithm has failed to converge.
|
||||
|
|
@ -36,19 +38,19 @@ public:
|
|||
*
|
||||
* @return the number of iterations performed by the algorithm.
|
||||
*/
|
||||
unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
|
||||
unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the maximum number of iterations that this algorithm will perform
|
||||
* to achieve convergence.
|
||||
*
|
||||
* @return maximum number of iterations
|
||||
*/
|
||||
unsigned int maxIterations() const;
|
||||
unsigned int maxIterations() const;
|
||||
|
||||
private:
|
||||
btScalar m_tolerance;
|
||||
unsigned int m_maxIterations;
|
||||
private:
|
||||
btScalar m_tolerance;
|
||||
unsigned int m_maxIterations;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -64,6 +66,7 @@ private:
|
|||
*
|
||||
* @return the number of iterations performed by the algorithm.
|
||||
*/
|
||||
unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
|
||||
unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
|
||||
|
||||
#endif // POLARDECOMPOSITION_H
|
||||
|
||||
#endif // POLARDECOMPOSITION_H
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BT_POOL_ALLOCATOR_H
|
||||
#define _BT_POOL_ALLOCATOR_H
|
||||
|
||||
|
|
@ -22,38 +23,38 @@ subject to the following restrictions:
|
|||
///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
|
||||
class btPoolAllocator
|
||||
{
|
||||
int m_elemSize;
|
||||
int m_maxElements;
|
||||
int m_freeCount;
|
||||
void* m_firstFree;
|
||||
unsigned char* m_pool;
|
||||
btSpinMutex m_mutex; // only used if BT_THREADSAFE
|
||||
int m_elemSize;
|
||||
int m_maxElements;
|
||||
int m_freeCount;
|
||||
void* m_firstFree;
|
||||
unsigned char* m_pool;
|
||||
btSpinMutex m_mutex; // only used if BT_THREADSAFE
|
||||
|
||||
public:
|
||||
|
||||
btPoolAllocator(int elemSize, int maxElements)
|
||||
: m_elemSize(elemSize),
|
||||
m_maxElements(maxElements)
|
||||
:m_elemSize(elemSize),
|
||||
m_maxElements(maxElements)
|
||||
{
|
||||
m_pool = (unsigned char*)btAlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
|
||||
m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
|
||||
|
||||
unsigned char* p = m_pool;
|
||||
m_firstFree = p;
|
||||
m_freeCount = m_maxElements;
|
||||
int count = m_maxElements;
|
||||
while (--count)
|
||||
{
|
||||
*(void**)p = (p + m_elemSize);
|
||||
p += m_elemSize;
|
||||
}
|
||||
*(void**)p = 0;
|
||||
}
|
||||
m_firstFree = p;
|
||||
m_freeCount = m_maxElements;
|
||||
int count = m_maxElements;
|
||||
while (--count) {
|
||||
*(void**)p = (p + m_elemSize);
|
||||
p += m_elemSize;
|
||||
}
|
||||
*(void**)p = 0;
|
||||
}
|
||||
|
||||
~btPoolAllocator()
|
||||
{
|
||||
btAlignedFree(m_pool);
|
||||
btAlignedFree( m_pool);
|
||||
}
|
||||
|
||||
int getFreeCount() const
|
||||
int getFreeCount() const
|
||||
{
|
||||
return m_freeCount;
|
||||
}
|
||||
|
|
@ -68,27 +69,26 @@ public:
|
|||
return m_maxElements;
|
||||
}
|
||||
|
||||
void* allocate(int size)
|
||||
void* allocate(int size)
|
||||
{
|
||||
// release mode fix
|
||||
(void)size;
|
||||
btMutexLock(&m_mutex);
|
||||
btAssert(!size || size <= m_elemSize);
|
||||
btMutexLock(&m_mutex);
|
||||
btAssert(!size || size<=m_elemSize);
|
||||
//btAssert(m_freeCount>0); // should return null if all full
|
||||
void* result = m_firstFree;
|
||||
if (NULL != m_firstFree)
|
||||
{
|
||||
m_firstFree = *(void**)m_firstFree;
|
||||
--m_freeCount;
|
||||
}
|
||||
btMutexUnlock(&m_mutex);
|
||||
return result;
|
||||
void* result = m_firstFree;
|
||||
if (NULL != m_firstFree)
|
||||
{
|
||||
m_firstFree = *(void**)m_firstFree;
|
||||
--m_freeCount;
|
||||
}
|
||||
btMutexUnlock(&m_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool validPtr(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -97,34 +97,34 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
void freeMemory(void* ptr)
|
||||
void freeMemory(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
|
||||
if (ptr) {
|
||||
btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
|
||||
|
||||
btMutexLock(&m_mutex);
|
||||
*(void**)ptr = m_firstFree;
|
||||
m_firstFree = ptr;
|
||||
++m_freeCount;
|
||||
btMutexUnlock(&m_mutex);
|
||||
}
|
||||
btMutexLock(&m_mutex);
|
||||
*(void**)ptr = m_firstFree;
|
||||
m_firstFree = ptr;
|
||||
++m_freeCount;
|
||||
btMutexUnlock(&m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int getElementSize() const
|
||||
int getElementSize() const
|
||||
{
|
||||
return m_elemSize;
|
||||
}
|
||||
|
||||
unsigned char* getPoolAddress()
|
||||
unsigned char* getPoolAddress()
|
||||
{
|
||||
return m_pool;
|
||||
}
|
||||
|
||||
const unsigned char* getPoolAddress() const
|
||||
const unsigned char* getPoolAddress() const
|
||||
{
|
||||
return m_pool;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //_BT_POOL_ALLOCATOR_H
|
||||
#endif //_BT_POOL_ALLOCATOR_H
|
||||
|
|
|
|||
|
|
@ -12,13 +12,18 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_SIMD_QUADWORD_H
|
||||
#define BT_SIMD_QUADWORD_H
|
||||
|
||||
#include "btScalar.h"
|
||||
#include "btMinMax.h"
|
||||
|
||||
#if defined(__CELLOS_LV2) && defined(__SPU__)
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined (__CELLOS_LV2) && defined (__SPU__)
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -26,53 +31,51 @@ subject to the following restrictions:
|
|||
* Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
|
||||
*/
|
||||
#ifndef USE_LIBSPE2
|
||||
ATTRIBUTE_ALIGNED16(class)
|
||||
btQuadWord
|
||||
ATTRIBUTE_ALIGNED16(class) btQuadWord
|
||||
#else
|
||||
class btQuadWord
|
||||
#endif
|
||||
{
|
||||
protected:
|
||||
#if defined(__SPU__) && defined(__CELLOS_LV2__)
|
||||
|
||||
#if defined (__SPU__) && defined (__CELLOS_LV2__)
|
||||
union {
|
||||
vec_float4 mVec128;
|
||||
btScalar m_floats[4];
|
||||
btScalar m_floats[4];
|
||||
};
|
||||
|
||||
public:
|
||||
vec_float4 get128() const
|
||||
vec_float4 get128() const
|
||||
{
|
||||
return mVec128;
|
||||
}
|
||||
|
||||
protected:
|
||||
#else //__CELLOS_LV2__ __SPU__
|
||||
#else //__CELLOS_LV2__ __SPU__
|
||||
|
||||
#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
|
||||
#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
|
||||
union {
|
||||
btSimdFloat4 mVec128;
|
||||
btScalar m_floats[4];
|
||||
btScalar m_floats[4];
|
||||
};
|
||||
|
||||
public:
|
||||
SIMD_FORCE_INLINE btSimdFloat4 get128() const
|
||||
SIMD_FORCE_INLINE btSimdFloat4 get128() const
|
||||
{
|
||||
return mVec128;
|
||||
}
|
||||
SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
|
||||
SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
|
||||
{
|
||||
mVec128 = v128;
|
||||
}
|
||||
#else
|
||||
btScalar m_floats[4];
|
||||
#endif // BT_USE_SSE
|
||||
btScalar m_floats[4];
|
||||
#endif // BT_USE_SSE
|
||||
|
||||
#endif //__CELLOS_LV2__ __SPU__
|
||||
#endif //__CELLOS_LV2__ __SPU__
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
|
||||
|
||||
// Set Vector
|
||||
// Set Vector
|
||||
SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)
|
||||
{
|
||||
mVec128 = vec;
|
||||
|
|
@ -85,154 +88,157 @@ public:
|
|||
}
|
||||
|
||||
// Assignment Operator
|
||||
SIMD_FORCE_INLINE btQuadWord&
|
||||
operator=(const btQuadWord& v)
|
||||
SIMD_FORCE_INLINE btQuadWord&
|
||||
operator=(const btQuadWord& v)
|
||||
{
|
||||
mVec128 = v.mVec128;
|
||||
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/**@brief Return the x value */
|
||||
SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
|
||||
/**@brief Return the y value */
|
||||
SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
|
||||
/**@brief Return the z value */
|
||||
SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
|
||||
/**@brief Set the x value */
|
||||
SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
|
||||
/**@brief Set the y value */
|
||||
SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
|
||||
/**@brief Set the z value */
|
||||
SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
|
||||
/**@brief Set the w value */
|
||||
SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
|
||||
/**@brief Return the x value */
|
||||
SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
|
||||
/**@brief Return the y value */
|
||||
SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
|
||||
/**@brief Return the z value */
|
||||
SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
|
||||
/**@brief Return the w value */
|
||||
SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
|
||||
/**@brief Return the x value */
|
||||
SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
|
||||
/**@brief Return the y value */
|
||||
SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
|
||||
/**@brief Return the z value */
|
||||
SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
|
||||
/**@brief Set the x value */
|
||||
SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x;};
|
||||
/**@brief Set the y value */
|
||||
SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y;};
|
||||
/**@brief Set the z value */
|
||||
SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z;};
|
||||
/**@brief Set the w value */
|
||||
SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w;};
|
||||
/**@brief Return the x value */
|
||||
SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
|
||||
/**@brief Return the y value */
|
||||
SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
|
||||
/**@brief Return the z value */
|
||||
SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
|
||||
/**@brief Return the w value */
|
||||
SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
|
||||
|
||||
//SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
|
||||
//SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
|
||||
//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
|
||||
///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
|
||||
SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
|
||||
SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
|
||||
SIMD_FORCE_INLINE operator btScalar *() { return &m_floats[0]; }
|
||||
SIMD_FORCE_INLINE operator const btScalar *() const { return &m_floats[0]; }
|
||||
|
||||
SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
|
||||
SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
|
||||
{
|
||||
#ifdef BT_USE_SSE
|
||||
return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
|
||||
#else
|
||||
return ((m_floats[3] == other.m_floats[3]) &&
|
||||
(m_floats[2] == other.m_floats[2]) &&
|
||||
(m_floats[1] == other.m_floats[1]) &&
|
||||
(m_floats[0] == other.m_floats[0]));
|
||||
return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
|
||||
#else
|
||||
return ((m_floats[3]==other.m_floats[3]) &&
|
||||
(m_floats[2]==other.m_floats[2]) &&
|
||||
(m_floats[1]==other.m_floats[1]) &&
|
||||
(m_floats[0]==other.m_floats[0]));
|
||||
#endif
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
|
||||
SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/**@brief Set x,y,z and zero w
|
||||
/**@brief Set x,y,z and zero w
|
||||
* @param x Value of x
|
||||
* @param y Value of y
|
||||
* @param z Value of z
|
||||
*/
|
||||
SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
|
||||
{
|
||||
m_floats[0] = _x;
|
||||
m_floats[1] = _y;
|
||||
m_floats[2] = _z;
|
||||
m_floats[3] = 0.f;
|
||||
}
|
||||
SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
|
||||
{
|
||||
m_floats[0]=_x;
|
||||
m_floats[1]=_y;
|
||||
m_floats[2]=_z;
|
||||
m_floats[3] = 0.f;
|
||||
}
|
||||
|
||||
/* void getValue(btScalar *m) const
|
||||
/* void getValue(btScalar *m) const
|
||||
{
|
||||
m[0] = m_floats[0];
|
||||
m[1] = m_floats[1];
|
||||
m[2] = m_floats[2];
|
||||
}
|
||||
*/
|
||||
/**@brief Set the values
|
||||
/**@brief Set the values
|
||||
* @param x Value of x
|
||||
* @param y Value of y
|
||||
* @param z Value of z
|
||||
* @param w Value of w
|
||||
*/
|
||||
SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
|
||||
{
|
||||
m_floats[0] = _x;
|
||||
m_floats[1] = _y;
|
||||
m_floats[2] = _z;
|
||||
m_floats[3] = _w;
|
||||
}
|
||||
/**@brief No initialization constructor */
|
||||
SIMD_FORCE_INLINE btQuadWord()
|
||||
// :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
|
||||
{
|
||||
}
|
||||
|
||||
/**@brief Three argument constructor (zeros w)
|
||||
SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
|
||||
{
|
||||
m_floats[0]=_x;
|
||||
m_floats[1]=_y;
|
||||
m_floats[2]=_z;
|
||||
m_floats[3]=_w;
|
||||
}
|
||||
/**@brief No initialization constructor */
|
||||
SIMD_FORCE_INLINE btQuadWord()
|
||||
// :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
|
||||
{
|
||||
}
|
||||
|
||||
/**@brief Three argument constructor (zeros w)
|
||||
* @param x Value of x
|
||||
* @param y Value of y
|
||||
* @param z Value of z
|
||||
*/
|
||||
SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
|
||||
{
|
||||
m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
|
||||
}
|
||||
SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
|
||||
{
|
||||
m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
|
||||
}
|
||||
|
||||
/**@brief Initializing constructor
|
||||
/**@brief Initializing constructor
|
||||
* @param x Value of x
|
||||
* @param y Value of y
|
||||
* @param z Value of z
|
||||
* @param w Value of w
|
||||
*/
|
||||
SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
|
||||
{
|
||||
m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
|
||||
}
|
||||
SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z,const btScalar& _w)
|
||||
{
|
||||
m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
|
||||
}
|
||||
|
||||
/**@brief Set each element to the max of the current values and the values of another btQuadWord
|
||||
/**@brief Set each element to the max of the current values and the values of another btQuadWord
|
||||
* @param other The other btQuadWord to compare with
|
||||
*/
|
||||
SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
|
||||
{
|
||||
#ifdef BT_USE_SSE
|
||||
mVec128 = _mm_max_ps(mVec128, other.mVec128);
|
||||
#elif defined(BT_USE_NEON)
|
||||
mVec128 = vmaxq_f32(mVec128, other.mVec128);
|
||||
#else
|
||||
btSetMax(m_floats[0], other.m_floats[0]);
|
||||
btSetMax(m_floats[1], other.m_floats[1]);
|
||||
btSetMax(m_floats[2], other.m_floats[2]);
|
||||
btSetMax(m_floats[3], other.m_floats[3]);
|
||||
#endif
|
||||
}
|
||||
/**@brief Set each element to the min of the current values and the values of another btQuadWord
|
||||
SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
|
||||
{
|
||||
#ifdef BT_USE_SSE
|
||||
mVec128 = _mm_max_ps(mVec128, other.mVec128);
|
||||
#elif defined(BT_USE_NEON)
|
||||
mVec128 = vmaxq_f32(mVec128, other.mVec128);
|
||||
#else
|
||||
btSetMax(m_floats[0], other.m_floats[0]);
|
||||
btSetMax(m_floats[1], other.m_floats[1]);
|
||||
btSetMax(m_floats[2], other.m_floats[2]);
|
||||
btSetMax(m_floats[3], other.m_floats[3]);
|
||||
#endif
|
||||
}
|
||||
/**@brief Set each element to the min of the current values and the values of another btQuadWord
|
||||
* @param other The other btQuadWord to compare with
|
||||
*/
|
||||
SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
|
||||
{
|
||||
#ifdef BT_USE_SSE
|
||||
mVec128 = _mm_min_ps(mVec128, other.mVec128);
|
||||
#elif defined(BT_USE_NEON)
|
||||
mVec128 = vminq_f32(mVec128, other.mVec128);
|
||||
#else
|
||||
btSetMin(m_floats[0], other.m_floats[0]);
|
||||
btSetMin(m_floats[1], other.m_floats[1]);
|
||||
btSetMin(m_floats[2], other.m_floats[2]);
|
||||
btSetMin(m_floats[3], other.m_floats[3]);
|
||||
#endif
|
||||
}
|
||||
SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
|
||||
{
|
||||
#ifdef BT_USE_SSE
|
||||
mVec128 = _mm_min_ps(mVec128, other.mVec128);
|
||||
#elif defined(BT_USE_NEON)
|
||||
mVec128 = vminq_f32(mVec128, other.mVec128);
|
||||
#else
|
||||
btSetMin(m_floats[0], other.m_floats[0]);
|
||||
btSetMin(m_floats[1], other.m_floats[1]);
|
||||
btSetMin(m_floats[2], other.m_floats[2]);
|
||||
btSetMin(m_floats[3], other.m_floats[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_SIMD_QUADWORD_H
|
||||
#endif //BT_SIMD_QUADWORD_H
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -7,9 +7,11 @@
|
|||
**
|
||||
***************************************************************************************************/
|
||||
|
||||
// Credits: The Clock class was inspired by the Timer classes in
|
||||
// Credits: The Clock class was inspired by the Timer classes in
|
||||
// Ogre (www.ogre3d.org).
|
||||
|
||||
|
||||
|
||||
#ifndef BT_QUICK_PROF_H
|
||||
#define BT_QUICK_PROF_H
|
||||
|
||||
|
|
@ -32,88 +34,96 @@ public:
|
|||
/// Resets the initial reference time.
|
||||
void reset();
|
||||
|
||||
/// Returns the time in ms since the last call to reset or since
|
||||
/// Returns the time in ms since the last call to reset or since
|
||||
/// the btClock was created.
|
||||
unsigned long long int getTimeMilliseconds();
|
||||
|
||||
/// Returns the time in us since the last call to reset or since
|
||||
/// Returns the time in us since the last call to reset or since
|
||||
/// the Clock was created.
|
||||
unsigned long long int getTimeMicroseconds();
|
||||
|
||||
|
||||
unsigned long long int getTimeNanoseconds();
|
||||
|
||||
/// Returns the time in s since the last call to reset or since
|
||||
/// Returns the time in s since the last call to reset or since
|
||||
/// the Clock was created.
|
||||
btScalar getTimeSeconds();
|
||||
|
||||
|
||||
private:
|
||||
struct btClockData* m_data;
|
||||
};
|
||||
|
||||
#endif //USE_BT_CLOCK
|
||||
#endif //USE_BT_CLOCK
|
||||
|
||||
typedef void(btEnterProfileZoneFunc)(const char* msg);
|
||||
typedef void(btLeaveProfileZoneFunc)();
|
||||
typedef void (btEnterProfileZoneFunc)(const char* msg);
|
||||
typedef void (btLeaveProfileZoneFunc)();
|
||||
|
||||
btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
|
||||
btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
|
||||
|
||||
|
||||
|
||||
void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
|
||||
void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
|
||||
|
||||
#ifndef BT_ENABLE_PROFILE
|
||||
#define BT_NO_PROFILE 1
|
||||
#endif //BT_NO_PROFILE
|
||||
|
||||
const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
|
||||
|
||||
//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
|
||||
//otherwise returns thread index in range [0..maxThreads]
|
||||
unsigned int btQuickprofGetCurrentThreadIndex2();
|
||||
#ifndef BT_NO_PROFILE // FIX redefinition
|
||||
//To disable built-in profiling, please comment out next line
|
||||
//#define BT_NO_PROFILE 1
|
||||
#endif //BT_NO_PROFILE
|
||||
|
||||
#ifndef BT_NO_PROFILE
|
||||
//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
|
||||
//otherwise returns thread index in range [0..maxThreads]
|
||||
unsigned int btQuickprofGetCurrentThreadIndex2();
|
||||
const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
|
||||
|
||||
|
||||
#include <stdio.h> //@todo remove this, backwards compatibility
|
||||
#include <stdio.h>//@todo remove this, backwards compatibility
|
||||
|
||||
#include "btAlignedAllocator.h"
|
||||
#include <new>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///A node in the Profile Hierarchy Tree
|
||||
class CProfileNode
|
||||
{
|
||||
class CProfileNode {
|
||||
|
||||
public:
|
||||
CProfileNode(const char* name, CProfileNode* parent);
|
||||
~CProfileNode(void);
|
||||
CProfileNode( const char * name, CProfileNode * parent );
|
||||
~CProfileNode( void );
|
||||
|
||||
CProfileNode* Get_Sub_Node(const char* name);
|
||||
CProfileNode * Get_Sub_Node( const char * name );
|
||||
|
||||
CProfileNode* Get_Parent(void) { return Parent; }
|
||||
CProfileNode* Get_Sibling(void) { return Sibling; }
|
||||
CProfileNode* Get_Child(void) { return Child; }
|
||||
CProfileNode * Get_Parent( void ) { return Parent; }
|
||||
CProfileNode * Get_Sibling( void ) { return Sibling; }
|
||||
CProfileNode * Get_Child( void ) { return Child; }
|
||||
|
||||
void CleanupMemory();
|
||||
void Reset(void);
|
||||
void Call(void);
|
||||
bool Return(void);
|
||||
|
||||
const char* Get_Name(void) { return Name; }
|
||||
int Get_Total_Calls(void) { return TotalCalls; }
|
||||
float Get_Total_Time(void) { return TotalTime; }
|
||||
void* GetUserPointer() const { return m_userPtr; }
|
||||
void SetUserPointer(void* ptr) { m_userPtr = ptr; }
|
||||
void CleanupMemory();
|
||||
void Reset( void );
|
||||
void Call( void );
|
||||
bool Return( void );
|
||||
|
||||
const char * Get_Name( void ) { return Name; }
|
||||
int Get_Total_Calls( void ) { return TotalCalls; }
|
||||
float Get_Total_Time( void ) { return TotalTime; }
|
||||
void* GetUserPointer() const {return m_userPtr;}
|
||||
void SetUserPointer(void* ptr) { m_userPtr = ptr;}
|
||||
protected:
|
||||
const char* Name;
|
||||
int TotalCalls;
|
||||
float TotalTime;
|
||||
unsigned long int StartTime;
|
||||
int RecursionCounter;
|
||||
|
||||
CProfileNode* Parent;
|
||||
CProfileNode* Child;
|
||||
CProfileNode* Sibling;
|
||||
void* m_userPtr;
|
||||
const char * Name;
|
||||
int TotalCalls;
|
||||
float TotalTime;
|
||||
unsigned long int StartTime;
|
||||
int RecursionCounter;
|
||||
|
||||
CProfileNode * Parent;
|
||||
CProfileNode * Child;
|
||||
CProfileNode * Sibling;
|
||||
void* m_userPtr;
|
||||
};
|
||||
|
||||
///An iterator to navigate through the tree
|
||||
|
|
@ -121,80 +131,91 @@ class CProfileIterator
|
|||
{
|
||||
public:
|
||||
// Access all the children of the current parent
|
||||
void First(void);
|
||||
void Next(void);
|
||||
bool Is_Done(void);
|
||||
bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
|
||||
void First(void);
|
||||
void Next(void);
|
||||
bool Is_Done(void);
|
||||
bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
|
||||
|
||||
void Enter_Child(int index); // Make the given child the new parent
|
||||
void Enter_Largest_Child(void); // Make the largest child the new parent
|
||||
void Enter_Parent(void); // Make the current parent's parent the new parent
|
||||
void Enter_Child( int index ); // Make the given child the new parent
|
||||
void Enter_Largest_Child( void ); // Make the largest child the new parent
|
||||
void Enter_Parent( void ); // Make the current parent's parent the new parent
|
||||
|
||||
// Access the current child
|
||||
const char* Get_Current_Name(void) { return CurrentChild->Get_Name(); }
|
||||
int Get_Current_Total_Calls(void) { return CurrentChild->Get_Total_Calls(); }
|
||||
float Get_Current_Total_Time(void) { return CurrentChild->Get_Total_Time(); }
|
||||
const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
|
||||
int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
|
||||
float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
|
||||
|
||||
void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); }
|
||||
void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); }
|
||||
void* Get_Current_UserPointer( void ) { return CurrentChild->GetUserPointer(); }
|
||||
void Set_Current_UserPointer(void* ptr) {CurrentChild->SetUserPointer(ptr);}
|
||||
// Access the current parent
|
||||
const char* Get_Current_Parent_Name(void) { return CurrentParent->Get_Name(); }
|
||||
int Get_Current_Parent_Total_Calls(void) { return CurrentParent->Get_Total_Calls(); }
|
||||
float Get_Current_Parent_Total_Time(void) { return CurrentParent->Get_Total_Time(); }
|
||||
const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
|
||||
int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
|
||||
float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
CProfileNode* CurrentParent;
|
||||
CProfileNode* CurrentChild;
|
||||
|
||||
CProfileIterator(CProfileNode* start);
|
||||
friend class CProfileManager;
|
||||
CProfileNode * CurrentParent;
|
||||
CProfileNode * CurrentChild;
|
||||
|
||||
|
||||
CProfileIterator( CProfileNode * start );
|
||||
friend class CProfileManager;
|
||||
};
|
||||
|
||||
|
||||
///The Manager for the Profile system
|
||||
class CProfileManager
|
||||
{
|
||||
class CProfileManager {
|
||||
public:
|
||||
static void Start_Profile(const char* name);
|
||||
static void Stop_Profile(void);
|
||||
static void Start_Profile( const char * name );
|
||||
static void Stop_Profile( void );
|
||||
|
||||
static void CleanupMemory(void);
|
||||
// {
|
||||
// Root.CleanupMemory();
|
||||
// }
|
||||
static void CleanupMemory(void);
|
||||
// {
|
||||
// Root.CleanupMemory();
|
||||
// }
|
||||
|
||||
static void Reset(void);
|
||||
static void Increment_Frame_Counter(void);
|
||||
static int Get_Frame_Count_Since_Reset(void) { return FrameCounter; }
|
||||
static float Get_Time_Since_Reset(void);
|
||||
static void Reset( void );
|
||||
static void Increment_Frame_Counter( void );
|
||||
static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
|
||||
static float Get_Time_Since_Reset( void );
|
||||
|
||||
static CProfileIterator* Get_Iterator(void);
|
||||
// {
|
||||
//
|
||||
// return new CProfileIterator( &Root );
|
||||
// }
|
||||
static void Release_Iterator(CProfileIterator* iterator) { delete (iterator); }
|
||||
static CProfileIterator * Get_Iterator( void );
|
||||
// {
|
||||
//
|
||||
// return new CProfileIterator( &Root );
|
||||
// }
|
||||
static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
|
||||
|
||||
static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
|
||||
static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
|
||||
|
||||
static void dumpAll();
|
||||
static void dumpAll();
|
||||
|
||||
private:
|
||||
static int FrameCounter;
|
||||
static unsigned long int ResetTime;
|
||||
|
||||
static int FrameCounter;
|
||||
static unsigned long int ResetTime;
|
||||
};
|
||||
|
||||
#endif //#ifndef BT_NO_PROFILE
|
||||
|
||||
|
||||
|
||||
#endif //#ifndef BT_NO_PROFILE
|
||||
|
||||
///ProfileSampleClass is a simple way to profile a function's scope
|
||||
///Use the BT_PROFILE macro at the start of scope to time
|
||||
class CProfileSample
|
||||
{
|
||||
class CProfileSample {
|
||||
public:
|
||||
CProfileSample(const char* name);
|
||||
CProfileSample( const char * name );
|
||||
|
||||
~CProfileSample(void);
|
||||
~CProfileSample( void );
|
||||
};
|
||||
|
||||
#define BT_PROFILE(name) CProfileSample __profile(name)
|
||||
#define BT_PROFILE( name ) CProfileSample __profile( name )
|
||||
|
||||
|
||||
|
||||
#endif //BT_QUICK_PROF_H
|
||||
|
||||
|
||||
#endif //BT_QUICK_PROF_H
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_GEN_RANDOM_H
|
||||
#define BT_GEN_RANDOM_H
|
||||
|
||||
|
|
@ -22,8 +24,8 @@ subject to the following restrictions:
|
|||
|
||||
#define GEN_RAND_MAX UINT_MAX
|
||||
|
||||
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
|
||||
SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
|
||||
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
|
||||
SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
|
||||
|
||||
#else
|
||||
|
||||
|
|
@ -31,9 +33,10 @@ SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
|
|||
|
||||
#define GEN_RAND_MAX RAND_MAX
|
||||
|
||||
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
|
||||
SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
|
||||
SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
|
||||
SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
|
||||
|
||||
#endif
|
||||
|
||||
#endif //BT_GEN_RANDOM_H
|
||||
#endif //BT_GEN_RANDOM_H
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,14 @@ subject to the following restrictions:
|
|||
#include <float.h>
|
||||
|
||||
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
|
||||
#define BT_BULLET_VERSION 288
|
||||
#define BT_BULLET_VERSION 287
|
||||
|
||||
inline int btGetVersion()
|
||||
{
|
||||
return BT_BULLET_VERSION;
|
||||
}
|
||||
|
||||
|
||||
// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
|
||||
// in order suppress the MS Visual C++ Linker warning 4221
|
||||
//
|
||||
|
|
@ -43,19 +44,16 @@ inline int btGetVersion()
|
|||
//
|
||||
// see more https://stackoverflow.com/questions/1822887/what-is-the-best-way-to-eliminate-ms-visual-c-linker-warning-warning-lnk422
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
|
||||
#define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a##b)
|
||||
#define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
|
||||
#define BT_NOT_EMPTY_FILE \
|
||||
namespace \
|
||||
{ \
|
||||
char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); \
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
#define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
|
||||
#define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a ## b)
|
||||
#define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
|
||||
#define BT_NOT_EMPTY_FILE namespace { char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); }
|
||||
#else
|
||||
#define BT_NOT_EMPTY_FILE
|
||||
#define BT_NOT_EMPTY_FILE
|
||||
#endif
|
||||
|
||||
|
||||
// clang and most formatting tools don't support indentation of preprocessor guards, so turn it off
|
||||
// clang-format off
|
||||
#if defined(DEBUG) || defined (_DEBUG)
|
||||
|
|
@ -124,7 +122,7 @@ inline int btGetVersion()
|
|||
#ifdef BT_DEBUG
|
||||
#ifdef _MSC_VER
|
||||
#include <stdio.h>
|
||||
#define btAssert(x) { if(!(x)){printf("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
|
||||
#define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
|
||||
#else//_MSC_VER
|
||||
#include <assert.h>
|
||||
#define btAssert assert
|
||||
|
|
@ -152,7 +150,7 @@ inline int btGetVersion()
|
|||
#ifdef __SPU__
|
||||
#include <spu_printf.h>
|
||||
#define printf spu_printf
|
||||
#define btAssert(x) {if(!(x)){printf("Assert " __FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
|
||||
#define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
|
||||
#else
|
||||
#define btAssert assert
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -12,17 +12,18 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
///These spatial algebra classes are used for btMultiBody,
|
||||
///These spatial algebra classes are used for btMultiBody,
|
||||
///see BulletDynamics/Featherstone
|
||||
|
||||
#ifndef BT_SPATIAL_ALGEBRA_H
|
||||
#define BT_SPATIAL_ALGEBRA_H
|
||||
|
||||
|
||||
#include "btMatrix3x3.h"
|
||||
|
||||
struct btSpatialForceVector
|
||||
{
|
||||
btVector3 m_topVec, m_bottomVec;
|
||||
{
|
||||
btVector3 m_topVec, m_bottomVec;
|
||||
//
|
||||
btSpatialForceVector() { setZero(); }
|
||||
btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
|
||||
|
|
@ -31,34 +32,21 @@ struct btSpatialForceVector
|
|||
setValue(ax, ay, az, lx, ly, lz);
|
||||
}
|
||||
//
|
||||
void setVector(const btVector3 &angular, const btVector3 &linear)
|
||||
{
|
||||
m_topVec = linear;
|
||||
m_bottomVec = angular;
|
||||
}
|
||||
void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = linear; m_bottomVec = angular; }
|
||||
void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
|
||||
{
|
||||
m_bottomVec.setValue(ax, ay, az);
|
||||
m_topVec.setValue(lx, ly, lz);
|
||||
m_bottomVec.setValue(ax, ay, az); m_topVec.setValue(lx, ly, lz);
|
||||
}
|
||||
//
|
||||
void addVector(const btVector3 &angular, const btVector3 &linear)
|
||||
{
|
||||
m_topVec += linear;
|
||||
m_bottomVec += angular;
|
||||
}
|
||||
void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
|
||||
void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
|
||||
{
|
||||
m_bottomVec[0] += ax;
|
||||
m_bottomVec[1] += ay;
|
||||
m_bottomVec[2] += az;
|
||||
m_topVec[0] += lx;
|
||||
m_topVec[1] += ly;
|
||||
m_topVec[2] += lz;
|
||||
m_bottomVec[0] += ax; m_bottomVec[1] += ay; m_bottomVec[2] += az;
|
||||
m_topVec[0] += lx; m_topVec[1] += ly; m_topVec[2] += lz;
|
||||
}
|
||||
//
|
||||
const btVector3 &getLinear() const { return m_topVec; }
|
||||
const btVector3 &getAngular() const { return m_bottomVec; }
|
||||
const btVector3 & getLinear() const { return m_topVec; }
|
||||
const btVector3 & getAngular() const { return m_bottomVec; }
|
||||
//
|
||||
void setLinear(const btVector3 &linear) { m_topVec = linear; }
|
||||
void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
|
||||
|
|
@ -66,28 +54,14 @@ struct btSpatialForceVector
|
|||
void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
|
||||
void addLinear(const btVector3 &linear) { m_topVec += linear; }
|
||||
//
|
||||
void setZero()
|
||||
{
|
||||
m_topVec.setZero();
|
||||
m_bottomVec.setZero();
|
||||
}
|
||||
void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
|
||||
//
|
||||
btSpatialForceVector &operator+=(const btSpatialForceVector &vec)
|
||||
{
|
||||
m_topVec += vec.m_topVec;
|
||||
m_bottomVec += vec.m_bottomVec;
|
||||
return *this;
|
||||
}
|
||||
btSpatialForceVector &operator-=(const btSpatialForceVector &vec)
|
||||
{
|
||||
m_topVec -= vec.m_topVec;
|
||||
m_bottomVec -= vec.m_bottomVec;
|
||||
return *this;
|
||||
}
|
||||
btSpatialForceVector operator-(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
|
||||
btSpatialForceVector operator+(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
|
||||
btSpatialForceVector operator-() const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
|
||||
btSpatialForceVector operator*(const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
|
||||
btSpatialForceVector & operator += (const btSpatialForceVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
|
||||
btSpatialForceVector & operator -= (const btSpatialForceVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
|
||||
btSpatialForceVector operator - (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
|
||||
btSpatialForceVector operator + (const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
|
||||
btSpatialForceVector operator - () const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
|
||||
btSpatialForceVector operator * (const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
|
||||
//btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
|
||||
};
|
||||
|
||||
|
|
@ -96,36 +70,23 @@ struct btSpatialMotionVector
|
|||
btVector3 m_topVec, m_bottomVec;
|
||||
//
|
||||
btSpatialMotionVector() { setZero(); }
|
||||
btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
|
||||
btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
|
||||
//
|
||||
void setVector(const btVector3 &angular, const btVector3 &linear)
|
||||
{
|
||||
m_topVec = angular;
|
||||
m_bottomVec = linear;
|
||||
}
|
||||
void setVector(const btVector3 &angular, const btVector3 &linear) { m_topVec = angular; m_bottomVec = linear; }
|
||||
void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
|
||||
{
|
||||
m_topVec.setValue(ax, ay, az);
|
||||
m_bottomVec.setValue(lx, ly, lz);
|
||||
m_topVec.setValue(ax, ay, az); m_bottomVec.setValue(lx, ly, lz);
|
||||
}
|
||||
//
|
||||
void addVector(const btVector3 &angular, const btVector3 &linear)
|
||||
{
|
||||
m_topVec += linear;
|
||||
m_bottomVec += angular;
|
||||
}
|
||||
void addVector(const btVector3 &angular, const btVector3 &linear) { m_topVec += linear; m_bottomVec += angular; }
|
||||
void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
|
||||
{
|
||||
m_topVec[0] += ax;
|
||||
m_topVec[1] += ay;
|
||||
m_topVec[2] += az;
|
||||
m_bottomVec[0] += lx;
|
||||
m_bottomVec[1] += ly;
|
||||
m_bottomVec[2] += lz;
|
||||
m_topVec[0] += ax; m_topVec[1] += ay; m_topVec[2] += az;
|
||||
m_bottomVec[0] += lx; m_bottomVec[1] += ly; m_bottomVec[2] += lz;
|
||||
}
|
||||
//
|
||||
const btVector3 &getAngular() const { return m_topVec; }
|
||||
const btVector3 &getLinear() const { return m_bottomVec; }
|
||||
//
|
||||
const btVector3 & getAngular() const { return m_topVec; }
|
||||
const btVector3 & getLinear() const { return m_bottomVec; }
|
||||
//
|
||||
void setAngular(const btVector3 &angular) { m_topVec = angular; }
|
||||
void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
|
||||
|
|
@ -133,24 +94,20 @@ struct btSpatialMotionVector
|
|||
void addAngular(const btVector3 &angular) { m_topVec += angular; }
|
||||
void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
|
||||
//
|
||||
void setZero()
|
||||
{
|
||||
m_topVec.setZero();
|
||||
m_bottomVec.setZero();
|
||||
}
|
||||
void setZero() { m_topVec.setZero(); m_bottomVec.setZero(); }
|
||||
//
|
||||
btScalar dot(const btSpatialForceVector &b) const
|
||||
{
|
||||
return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
|
||||
}
|
||||
//
|
||||
template <typename SpatialVectorType>
|
||||
template<typename SpatialVectorType>
|
||||
void cross(const SpatialVectorType &b, SpatialVectorType &out) const
|
||||
{
|
||||
out.m_topVec = m_topVec.cross(b.m_topVec);
|
||||
out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
|
||||
}
|
||||
template <typename SpatialVectorType>
|
||||
template<typename SpatialVectorType>
|
||||
SpatialVectorType cross(const SpatialVectorType &b) const
|
||||
{
|
||||
SpatialVectorType out;
|
||||
|
|
@ -159,36 +116,21 @@ struct btSpatialMotionVector
|
|||
return out;
|
||||
}
|
||||
//
|
||||
btSpatialMotionVector &operator+=(const btSpatialMotionVector &vec)
|
||||
{
|
||||
m_topVec += vec.m_topVec;
|
||||
m_bottomVec += vec.m_bottomVec;
|
||||
return *this;
|
||||
}
|
||||
btSpatialMotionVector &operator-=(const btSpatialMotionVector &vec)
|
||||
{
|
||||
m_topVec -= vec.m_topVec;
|
||||
m_bottomVec -= vec.m_bottomVec;
|
||||
return *this;
|
||||
}
|
||||
btSpatialMotionVector &operator*=(const btScalar &s)
|
||||
{
|
||||
m_topVec *= s;
|
||||
m_bottomVec *= s;
|
||||
return *this;
|
||||
}
|
||||
btSpatialMotionVector operator-(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
|
||||
btSpatialMotionVector operator+(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
|
||||
btSpatialMotionVector operator-() const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
|
||||
btSpatialMotionVector operator*(const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
|
||||
btSpatialMotionVector & operator += (const btSpatialMotionVector &vec) { m_topVec += vec.m_topVec; m_bottomVec += vec.m_bottomVec; return *this; }
|
||||
btSpatialMotionVector & operator -= (const btSpatialMotionVector &vec) { m_topVec -= vec.m_topVec; m_bottomVec -= vec.m_bottomVec; return *this; }
|
||||
btSpatialMotionVector & operator *= (const btScalar &s) { m_topVec *= s; m_bottomVec *= s; return *this; }
|
||||
btSpatialMotionVector operator - (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
|
||||
btSpatialMotionVector operator + (const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
|
||||
btSpatialMotionVector operator - () const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
|
||||
btSpatialMotionVector operator * (const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
|
||||
};
|
||||
|
||||
struct btSymmetricSpatialDyad
|
||||
{
|
||||
btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
|
||||
//
|
||||
//
|
||||
btSymmetricSpatialDyad() { setIdentity(); }
|
||||
btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
|
||||
btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
|
||||
//
|
||||
void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
|
||||
{
|
||||
|
|
@ -204,22 +146,17 @@ struct btSymmetricSpatialDyad
|
|||
m_bottomLeftMat += bottomLeftMat;
|
||||
}
|
||||
//
|
||||
void setIdentity()
|
||||
{
|
||||
m_topLeftMat.setIdentity();
|
||||
m_topRightMat.setIdentity();
|
||||
m_bottomLeftMat.setIdentity();
|
||||
}
|
||||
void setIdentity() { m_topLeftMat.setIdentity(); m_topRightMat.setIdentity(); m_bottomLeftMat.setIdentity(); }
|
||||
//
|
||||
btSymmetricSpatialDyad &operator-=(const btSymmetricSpatialDyad &mat)
|
||||
btSymmetricSpatialDyad & operator -= (const btSymmetricSpatialDyad &mat)
|
||||
{
|
||||
m_topLeftMat -= mat.m_topLeftMat;
|
||||
m_topRightMat -= mat.m_topRightMat;
|
||||
m_bottomLeftMat -= mat.m_bottomLeftMat;
|
||||
return *this;
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
btSpatialForceVector operator*(const btSpatialMotionVector &vec)
|
||||
btSpatialForceVector operator * (const btSpatialMotionVector &vec)
|
||||
{
|
||||
return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
|
||||
}
|
||||
|
|
@ -227,7 +164,7 @@ struct btSymmetricSpatialDyad
|
|||
|
||||
struct btSpatialTransformationMatrix
|
||||
{
|
||||
btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
|
||||
btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
|
||||
btVector3 m_trnVec;
|
||||
//
|
||||
enum eOutputOperation
|
||||
|
|
@ -237,124 +174,128 @@ struct btSpatialTransformationMatrix
|
|||
Subtract = 2
|
||||
};
|
||||
//
|
||||
template <typename SpatialVectorType>
|
||||
void transform(const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
template<typename SpatialVectorType>
|
||||
void transform( const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
{
|
||||
if (outOp == None)
|
||||
if(outOp == None)
|
||||
{
|
||||
outVec.m_topVec = m_rotMat * inVec.m_topVec;
|
||||
outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
|
||||
}
|
||||
else if (outOp == Add)
|
||||
else if(outOp == Add)
|
||||
{
|
||||
outVec.m_topVec += m_rotMat * inVec.m_topVec;
|
||||
outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
|
||||
}
|
||||
else if (outOp == Subtract)
|
||||
else if(outOp == Subtract)
|
||||
{
|
||||
outVec.m_topVec -= m_rotMat * inVec.m_topVec;
|
||||
outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename SpatialVectorType>
|
||||
void transformRotationOnly(const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
template<typename SpatialVectorType>
|
||||
void transformRotationOnly( const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
{
|
||||
if (outOp == None)
|
||||
if(outOp == None)
|
||||
{
|
||||
outVec.m_topVec = m_rotMat * inVec.m_topVec;
|
||||
outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
|
||||
}
|
||||
else if (outOp == Add)
|
||||
else if(outOp == Add)
|
||||
{
|
||||
outVec.m_topVec += m_rotMat * inVec.m_topVec;
|
||||
outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
|
||||
}
|
||||
else if (outOp == Subtract)
|
||||
else if(outOp == Subtract)
|
||||
{
|
||||
outVec.m_topVec -= m_rotMat * inVec.m_topVec;
|
||||
outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename SpatialVectorType>
|
||||
void transformInverse(const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
template<typename SpatialVectorType>
|
||||
void transformInverse( const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
{
|
||||
if (outOp == None)
|
||||
if(outOp == None)
|
||||
{
|
||||
outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
|
||||
outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
|
||||
}
|
||||
else if (outOp == Add)
|
||||
else if(outOp == Add)
|
||||
{
|
||||
outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
|
||||
outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
|
||||
}
|
||||
else if (outOp == Subtract)
|
||||
else if(outOp == Subtract)
|
||||
{
|
||||
outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
|
||||
outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SpatialVectorType>
|
||||
void transformInverseRotationOnly(const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
template<typename SpatialVectorType>
|
||||
void transformInverseRotationOnly( const SpatialVectorType &inVec,
|
||||
SpatialVectorType &outVec,
|
||||
eOutputOperation outOp = None)
|
||||
{
|
||||
if (outOp == None)
|
||||
if(outOp == None)
|
||||
{
|
||||
outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
|
||||
outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
|
||||
}
|
||||
else if (outOp == Add)
|
||||
else if(outOp == Add)
|
||||
{
|
||||
outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
|
||||
outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
|
||||
}
|
||||
else if (outOp == Subtract)
|
||||
else if(outOp == Subtract)
|
||||
{
|
||||
outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
|
||||
outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void transformInverse(const btSymmetricSpatialDyad &inMat,
|
||||
btSymmetricSpatialDyad &outMat,
|
||||
eOutputOperation outOp = None)
|
||||
void transformInverse( const btSymmetricSpatialDyad &inMat,
|
||||
btSymmetricSpatialDyad &outMat,
|
||||
eOutputOperation outOp = None)
|
||||
{
|
||||
const btMatrix3x3 r_cross(0, -m_trnVec[2], m_trnVec[1],
|
||||
m_trnVec[2], 0, -m_trnVec[0],
|
||||
-m_trnVec[1], m_trnVec[0], 0);
|
||||
const btMatrix3x3 r_cross( 0, -m_trnVec[2], m_trnVec[1],
|
||||
m_trnVec[2], 0, -m_trnVec[0],
|
||||
-m_trnVec[1], m_trnVec[0], 0);
|
||||
|
||||
if (outOp == None)
|
||||
|
||||
if(outOp == None)
|
||||
{
|
||||
outMat.m_topLeftMat = m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
|
||||
outMat.m_topLeftMat = m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
|
||||
outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
|
||||
outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
|
||||
}
|
||||
else if (outOp == Add)
|
||||
else if(outOp == Add)
|
||||
{
|
||||
outMat.m_topLeftMat += m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
|
||||
outMat.m_topLeftMat += m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
|
||||
outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
|
||||
outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
|
||||
}
|
||||
else if (outOp == Subtract)
|
||||
else if(outOp == Subtract)
|
||||
{
|
||||
outMat.m_topLeftMat -= m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
|
||||
outMat.m_topLeftMat -= m_rotMat.transpose() * ( inMat.m_topLeftMat - inMat.m_topRightMat * r_cross ) * m_rotMat;
|
||||
outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
|
||||
outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SpatialVectorType>
|
||||
SpatialVectorType operator*(const SpatialVectorType &vec)
|
||||
template<typename SpatialVectorType>
|
||||
SpatialVectorType operator * (const SpatialVectorType &vec)
|
||||
{
|
||||
SpatialVectorType out;
|
||||
transform(vec, out);
|
||||
|
|
@ -362,7 +303,7 @@ struct btSpatialTransformationMatrix
|
|||
}
|
||||
};
|
||||
|
||||
template <typename SpatialVectorType>
|
||||
template<typename SpatialVectorType>
|
||||
void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
|
||||
{
|
||||
//output op maybe?
|
||||
|
|
@ -373,7 +314,7 @@ void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVecto
|
|||
//maybe simple a*spatTranspose(a) would be nicer?
|
||||
}
|
||||
|
||||
template <typename SpatialVectorType>
|
||||
template<typename SpatialVectorType>
|
||||
btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
|
||||
{
|
||||
btSymmetricSpatialDyad out;
|
||||
|
|
@ -386,4 +327,5 @@ btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a,
|
|||
//maybe simple a*spatTranspose(a) would be nicer?
|
||||
}
|
||||
|
||||
#endif //BT_SPATIAL_ALGEBRA_H
|
||||
#endif //BT_SPATIAL_ALGEBRA_H
|
||||
|
||||
|
|
|
|||
|
|
@ -20,99 +20,97 @@ Nov.2006
|
|||
#ifndef BT_STACK_ALLOC
|
||||
#define BT_STACK_ALLOC
|
||||
|
||||
#include "btScalar.h" //for btAssert
|
||||
#include "btScalar.h" //for btAssert
|
||||
#include "btAlignedAllocator.h"
|
||||
|
||||
///The btBlock class is an internal structure for the btStackAlloc memory allocator.
|
||||
struct btBlock
|
||||
{
|
||||
btBlock* previous;
|
||||
unsigned char* address;
|
||||
btBlock* previous;
|
||||
unsigned char* address;
|
||||
};
|
||||
|
||||
///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
|
||||
class btStackAlloc
|
||||
{
|
||||
public:
|
||||
btStackAlloc(unsigned int size)
|
||||
{
|
||||
ctor();
|
||||
create(size);
|
||||
}
|
||||
~btStackAlloc() { destroy(); }
|
||||
|
||||
inline void create(unsigned int size)
|
||||
btStackAlloc(unsigned int size) { ctor();create(size); }
|
||||
~btStackAlloc() { destroy(); }
|
||||
|
||||
inline void create(unsigned int size)
|
||||
{
|
||||
destroy();
|
||||
data = (unsigned char*)btAlignedAlloc(size, 16);
|
||||
totalsize = size;
|
||||
data = (unsigned char*) btAlignedAlloc(size,16);
|
||||
totalsize = size;
|
||||
}
|
||||
inline void destroy()
|
||||
inline void destroy()
|
||||
{
|
||||
btAssert(usedsize == 0);
|
||||
btAssert(usedsize==0);
|
||||
//Raise(L"StackAlloc is still in use");
|
||||
|
||||
if (usedsize == 0)
|
||||
if(usedsize==0)
|
||||
{
|
||||
if (!ischild && data)
|
||||
if(!ischild && data)
|
||||
btAlignedFree(data);
|
||||
|
||||
data = 0;
|
||||
usedsize = 0;
|
||||
data = 0;
|
||||
usedsize = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int getAvailableMemory() const
|
||||
int getAvailableMemory() const
|
||||
{
|
||||
return static_cast<int>(totalsize - usedsize);
|
||||
}
|
||||
|
||||
unsigned char* allocate(unsigned int size)
|
||||
unsigned char* allocate(unsigned int size)
|
||||
{
|
||||
const unsigned int nus(usedsize + size);
|
||||
if (nus < totalsize)
|
||||
const unsigned int nus(usedsize+size);
|
||||
if(nus<totalsize)
|
||||
{
|
||||
usedsize = nus;
|
||||
return (data + (usedsize - size));
|
||||
usedsize=nus;
|
||||
return(data+(usedsize-size));
|
||||
}
|
||||
btAssert(0);
|
||||
//&& (L"Not enough memory"));
|
||||
|
||||
return (0);
|
||||
|
||||
return(0);
|
||||
}
|
||||
SIMD_FORCE_INLINE btBlock* beginBlock()
|
||||
SIMD_FORCE_INLINE btBlock* beginBlock()
|
||||
{
|
||||
btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
|
||||
pb->previous = current;
|
||||
pb->address = data + usedsize;
|
||||
current = pb;
|
||||
return (pb);
|
||||
btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
|
||||
pb->previous = current;
|
||||
pb->address = data+usedsize;
|
||||
current = pb;
|
||||
return(pb);
|
||||
}
|
||||
SIMD_FORCE_INLINE void endBlock(btBlock* block)
|
||||
SIMD_FORCE_INLINE void endBlock(btBlock* block)
|
||||
{
|
||||
btAssert(block == current);
|
||||
btAssert(block==current);
|
||||
//Raise(L"Unmatched blocks");
|
||||
if (block == current)
|
||||
if(block==current)
|
||||
{
|
||||
current = block->previous;
|
||||
usedsize = (unsigned int)((block->address - data) - sizeof(btBlock));
|
||||
current = block->previous;
|
||||
usedsize = (unsigned int)((block->address-data)-sizeof(btBlock));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void ctor()
|
||||
void ctor()
|
||||
{
|
||||
data = 0;
|
||||
totalsize = 0;
|
||||
usedsize = 0;
|
||||
current = 0;
|
||||
ischild = false;
|
||||
data = 0;
|
||||
totalsize = 0;
|
||||
usedsize = 0;
|
||||
current = 0;
|
||||
ischild = false;
|
||||
}
|
||||
unsigned char* data;
|
||||
unsigned int totalsize;
|
||||
unsigned int usedsize;
|
||||
btBlock* current;
|
||||
bool ischild;
|
||||
unsigned char* data;
|
||||
unsigned int totalsize;
|
||||
unsigned int usedsize;
|
||||
btBlock* current;
|
||||
bool ischild;
|
||||
};
|
||||
|
||||
#endif //BT_STACK_ALLOC
|
||||
#endif //BT_STACK_ALLOC
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -12,12 +12,14 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_THREADS_H
|
||||
#define BT_THREADS_H
|
||||
|
||||
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
|
||||
#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
#if defined (_MSC_VER) && _MSC_VER >= 1600
|
||||
// give us a compile error if any signatures of overriden methods is changed
|
||||
#define BT_OVERRIDE override
|
||||
#endif
|
||||
|
|
@ -26,15 +28,13 @@ subject to the following restrictions:
|
|||
#define BT_OVERRIDE
|
||||
#endif
|
||||
|
||||
// Don't set this to larger than 64, without modifying btThreadSupportPosix
|
||||
// and btThreadSupportWin32. They use UINT64 bit-masks.
|
||||
const unsigned int BT_MAX_THREAD_COUNT = 64; // only if BT_THREADSAFE is 1
|
||||
|
||||
// for internal use only
|
||||
bool btIsMainThread();
|
||||
bool btThreadsAreRunning();
|
||||
unsigned int btGetCurrentThreadIndex();
|
||||
void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed
|
||||
void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed
|
||||
|
||||
///
|
||||
/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts
|
||||
|
|
@ -44,18 +44,19 @@ void btResetThreadIndexCounter(); // notify that all worker threads have been d
|
|||
///
|
||||
class btSpinMutex
|
||||
{
|
||||
int mLock;
|
||||
int mLock;
|
||||
|
||||
public:
|
||||
btSpinMutex()
|
||||
{
|
||||
mLock = 0;
|
||||
}
|
||||
void lock();
|
||||
void unlock();
|
||||
bool tryLock();
|
||||
btSpinMutex()
|
||||
{
|
||||
mLock = 0;
|
||||
}
|
||||
void lock();
|
||||
void unlock();
|
||||
bool tryLock();
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// NOTE: btMutex* is for internal Bullet use only
|
||||
//
|
||||
|
|
@ -67,53 +68,38 @@ public:
|
|||
// of bad because if you call any of these functions from external code
|
||||
// (where BT_THREADSAFE is undefined) you will get unexpected race conditions.
|
||||
//
|
||||
SIMD_FORCE_INLINE void btMutexLock(btSpinMutex* mutex)
|
||||
SIMD_FORCE_INLINE void btMutexLock( btSpinMutex* mutex )
|
||||
{
|
||||
#if BT_THREADSAFE
|
||||
mutex->lock();
|
||||
#else
|
||||
(void)mutex;
|
||||
#endif // #if BT_THREADSAFE
|
||||
mutex->lock();
|
||||
#endif // #if BT_THREADSAFE
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btMutexUnlock(btSpinMutex* mutex)
|
||||
SIMD_FORCE_INLINE void btMutexUnlock( btSpinMutex* mutex )
|
||||
{
|
||||
#if BT_THREADSAFE
|
||||
mutex->unlock();
|
||||
#else
|
||||
(void)mutex;
|
||||
#endif // #if BT_THREADSAFE
|
||||
mutex->unlock();
|
||||
#endif // #if BT_THREADSAFE
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE bool btMutexTryLock(btSpinMutex* mutex)
|
||||
SIMD_FORCE_INLINE bool btMutexTryLock( btSpinMutex* mutex )
|
||||
{
|
||||
#if BT_THREADSAFE
|
||||
return mutex->tryLock();
|
||||
return mutex->tryLock();
|
||||
#else
|
||||
(void)mutex;
|
||||
return true;
|
||||
#endif // #if BT_THREADSAFE
|
||||
return true;
|
||||
#endif // #if BT_THREADSAFE
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// btIParallelForBody -- subclass this to express work that can be done in parallel
|
||||
//
|
||||
class btIParallelForBody
|
||||
{
|
||||
public:
|
||||
virtual ~btIParallelForBody() {}
|
||||
virtual void forLoop(int iBegin, int iEnd) const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// btIParallelSumBody -- subclass this to express work that can be done in parallel
|
||||
// and produces a sum over all loop elements
|
||||
//
|
||||
class btIParallelSumBody
|
||||
{
|
||||
public:
|
||||
virtual ~btIParallelSumBody() {}
|
||||
virtual btScalar sumLoop(int iBegin, int iEnd) const = 0;
|
||||
virtual ~btIParallelForBody() {}
|
||||
virtual void forLoop( int iBegin, int iEnd ) const = 0;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -123,30 +109,28 @@ public:
|
|||
class btITaskScheduler
|
||||
{
|
||||
public:
|
||||
btITaskScheduler(const char* name);
|
||||
virtual ~btITaskScheduler() {}
|
||||
const char* getName() const { return m_name; }
|
||||
btITaskScheduler( const char* name );
|
||||
virtual ~btITaskScheduler() {}
|
||||
const char* getName() const { return m_name; }
|
||||
|
||||
virtual int getMaxNumThreads() const = 0;
|
||||
virtual int getNumThreads() const = 0;
|
||||
virtual void setNumThreads(int numThreads) = 0;
|
||||
virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) = 0;
|
||||
virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) = 0;
|
||||
virtual void sleepWorkerThreadsHint() {} // hint the task scheduler that we may not be using these threads for a little while
|
||||
virtual int getMaxNumThreads() const = 0;
|
||||
virtual int getNumThreads() const = 0;
|
||||
virtual void setNumThreads( int numThreads ) = 0;
|
||||
virtual void parallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body ) = 0;
|
||||
|
||||
// internal use only
|
||||
virtual void activate();
|
||||
virtual void deactivate();
|
||||
// internal use only
|
||||
virtual void activate();
|
||||
virtual void deactivate();
|
||||
|
||||
protected:
|
||||
const char* m_name;
|
||||
unsigned int m_savedThreadCounter;
|
||||
bool m_isActive;
|
||||
const char* m_name;
|
||||
unsigned int m_savedThreadCounter;
|
||||
bool m_isActive;
|
||||
};
|
||||
|
||||
// set the task scheduler to use for all calls to btParallelFor()
|
||||
// NOTE: you must set this prior to using any of the multi-threaded "Mt" classes
|
||||
void btSetTaskScheduler(btITaskScheduler* ts);
|
||||
void btSetTaskScheduler( btITaskScheduler* ts );
|
||||
|
||||
// get the current task scheduler
|
||||
btITaskScheduler* btGetTaskScheduler();
|
||||
|
|
@ -154,9 +138,6 @@ btITaskScheduler* btGetTaskScheduler();
|
|||
// get non-threaded task scheduler (always available)
|
||||
btITaskScheduler* btGetSequentialTaskScheduler();
|
||||
|
||||
// create a default task scheduler (Win32 or pthreads based)
|
||||
btITaskScheduler* btCreateDefaultTaskScheduler();
|
||||
|
||||
// get OpenMP task scheduler (if available, otherwise returns null)
|
||||
btITaskScheduler* btGetOpenMPTaskScheduler();
|
||||
|
||||
|
|
@ -168,10 +149,7 @@ btITaskScheduler* btGetPPLTaskScheduler();
|
|||
|
||||
// btParallelFor -- call this to dispatch work like a for-loop
|
||||
// (iterations may be done out of order, so no dependencies are allowed)
|
||||
void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body);
|
||||
void btParallelFor( int iBegin, int iEnd, int grainSize, const btIParallelForBody& body );
|
||||
|
||||
// btParallelSum -- call this to dispatch work like a for-loop, returns the sum of all iterations
|
||||
// (iterations may be done out of order, so no dependencies are allowed)
|
||||
btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef BT_TRANSFORM_H
|
||||
#define BT_TRANSFORM_H
|
||||
|
||||
|
||||
#include "btMatrix3x3.h"
|
||||
|
||||
#ifdef BT_USE_DOUBLE_PRECISION
|
||||
|
|
@ -23,45 +26,46 @@ subject to the following restrictions:
|
|||
#define btTransformData btTransformFloatData
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
|
||||
*It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
|
||||
ATTRIBUTE_ALIGNED16(class)
|
||||
btTransform
|
||||
{
|
||||
///Storage for the rotation
|
||||
ATTRIBUTE_ALIGNED16(class) btTransform {
|
||||
|
||||
///Storage for the rotation
|
||||
btMatrix3x3 m_basis;
|
||||
///Storage for the translation
|
||||
btVector3 m_origin;
|
||||
///Storage for the translation
|
||||
btVector3 m_origin;
|
||||
|
||||
public:
|
||||
/**@brief No initialization constructor */
|
||||
|
||||
/**@brief No initialization constructor */
|
||||
btTransform() {}
|
||||
/**@brief Constructor from btQuaternion (optional btVector3 )
|
||||
/**@brief Constructor from btQuaternion (optional btVector3 )
|
||||
* @param q Rotation from quaternion
|
||||
* @param c Translation from Vector (default 0,0,0) */
|
||||
explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
|
||||
const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
|
||||
explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
|
||||
const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
|
||||
: m_basis(q),
|
||||
m_origin(c)
|
||||
{
|
||||
}
|
||||
m_origin(c)
|
||||
{}
|
||||
|
||||
/**@brief Constructor from btMatrix3x3 (optional btVector3)
|
||||
/**@brief Constructor from btMatrix3x3 (optional btVector3)
|
||||
* @param b Rotation from Matrix
|
||||
* @param c Translation from Vector default (0,0,0)*/
|
||||
explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
|
||||
const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
|
||||
explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
|
||||
const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
|
||||
: m_basis(b),
|
||||
m_origin(c)
|
||||
{
|
||||
}
|
||||
/**@brief Copy constructor */
|
||||
SIMD_FORCE_INLINE btTransform(const btTransform& other)
|
||||
m_origin(c)
|
||||
{}
|
||||
/**@brief Copy constructor */
|
||||
SIMD_FORCE_INLINE btTransform (const btTransform& other)
|
||||
: m_basis(other.m_basis),
|
||||
m_origin(other.m_origin)
|
||||
m_origin(other.m_origin)
|
||||
{
|
||||
}
|
||||
/**@brief Assignment Operator */
|
||||
/**@brief Assignment Operator */
|
||||
SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
|
||||
{
|
||||
m_basis = other.m_basis;
|
||||
|
|
@ -69,70 +73,70 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/**@brief Set the current transform as the value of the product of two transforms
|
||||
|
||||
/**@brief Set the current transform as the value of the product of two transforms
|
||||
* @param t1 Transform 1
|
||||
* @param t2 Transform 2
|
||||
* This = Transform1 * Transform2 */
|
||||
SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2)
|
||||
{
|
||||
m_basis = t1.m_basis * t2.m_basis;
|
||||
m_origin = t1(t2.m_origin);
|
||||
}
|
||||
SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) {
|
||||
m_basis = t1.m_basis * t2.m_basis;
|
||||
m_origin = t1(t2.m_origin);
|
||||
}
|
||||
|
||||
/* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
|
||||
/* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
|
||||
btVector3 v = t2.m_origin - t1.m_origin;
|
||||
m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
|
||||
m_origin = v * t1.m_basis;
|
||||
}
|
||||
*/
|
||||
|
||||
/**@brief Return the transform of the vector */
|
||||
/**@brief Return the transform of the vector */
|
||||
SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
|
||||
{
|
||||
return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
|
||||
return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
|
||||
}
|
||||
|
||||
/**@brief Return the transform of the vector */
|
||||
/**@brief Return the transform of the vector */
|
||||
SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
|
||||
{
|
||||
return (*this)(x);
|
||||
}
|
||||
|
||||
/**@brief Return the transform of the btQuaternion */
|
||||
/**@brief Return the transform of the btQuaternion */
|
||||
SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
|
||||
{
|
||||
return getRotation() * q;
|
||||
}
|
||||
|
||||
/**@brief Return the basis matrix for the rotation */
|
||||
SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
|
||||
/**@brief Return the basis matrix for the rotation */
|
||||
SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
|
||||
/**@brief Return the basis matrix for the rotation */
|
||||
SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
|
||||
/**@brief Return the basis matrix for the rotation */
|
||||
SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
|
||||
|
||||
/**@brief Return the origin vector translation */
|
||||
SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
|
||||
/**@brief Return the origin vector translation */
|
||||
SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
|
||||
/**@brief Return the origin vector translation */
|
||||
SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
|
||||
/**@brief Return the origin vector translation */
|
||||
SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
|
||||
|
||||
/**@brief Return a quaternion representing the rotation */
|
||||
btQuaternion getRotation() const
|
||||
{
|
||||
/**@brief Return a quaternion representing the rotation */
|
||||
btQuaternion getRotation() const {
|
||||
btQuaternion q;
|
||||
m_basis.getRotation(q);
|
||||
return q;
|
||||
}
|
||||
|
||||
/**@brief Set from an array
|
||||
|
||||
|
||||
/**@brief Set from an array
|
||||
* @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
|
||||
void setFromOpenGLMatrix(const btScalar* m)
|
||||
void setFromOpenGLMatrix(const btScalar *m)
|
||||
{
|
||||
m_basis.setFromOpenGLSubMatrix(m);
|
||||
m_origin.setValue(m[12], m[13], m[14]);
|
||||
m_origin.setValue(m[12],m[13],m[14]);
|
||||
}
|
||||
|
||||
/**@brief Fill an array representation
|
||||
/**@brief Fill an array representation
|
||||
* @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
|
||||
void getOpenGLMatrix(btScalar * m) const
|
||||
void getOpenGLMatrix(btScalar *m) const
|
||||
{
|
||||
m_basis.getOpenGLSubMatrix(m);
|
||||
m[12] = m_origin.x();
|
||||
|
|
@ -141,76 +145,80 @@ public:
|
|||
m[15] = btScalar(1.0);
|
||||
}
|
||||
|
||||
/**@brief Set the translational element
|
||||
/**@brief Set the translational element
|
||||
* @param origin The vector to set the translation to */
|
||||
SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
|
||||
{
|
||||
SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
|
||||
{
|
||||
m_origin = origin;
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
|
||||
|
||||
/**@brief Set the rotational element by btMatrix3x3 */
|
||||
|
||||
/**@brief Set the rotational element by btMatrix3x3 */
|
||||
SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
|
||||
{
|
||||
{
|
||||
m_basis = basis;
|
||||
}
|
||||
|
||||
/**@brief Set the rotational element by btQuaternion */
|
||||
/**@brief Set the rotational element by btQuaternion */
|
||||
SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
|
||||
{
|
||||
m_basis.setRotation(q);
|
||||
}
|
||||
|
||||
/**@brief Set this transformation to the identity */
|
||||
|
||||
/**@brief Set this transformation to the identity */
|
||||
void setIdentity()
|
||||
{
|
||||
m_basis.setIdentity();
|
||||
m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
|
||||
}
|
||||
|
||||
/**@brief Multiply this Transform by another(this = this * another)
|
||||
/**@brief Multiply this Transform by another(this = this * another)
|
||||
* @param t The other transform */
|
||||
btTransform& operator*=(const btTransform& t)
|
||||
btTransform& operator*=(const btTransform& t)
|
||||
{
|
||||
m_origin += m_basis * t.m_origin;
|
||||
m_basis *= t.m_basis;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**@brief Return the inverse of this transform */
|
||||
/**@brief Return the inverse of this transform */
|
||||
btTransform inverse() const
|
||||
{
|
||||
{
|
||||
btMatrix3x3 inv = m_basis.transpose();
|
||||
return btTransform(inv, inv * -m_origin);
|
||||
}
|
||||
|
||||
/**@brief Return the inverse of this transform times the other transform
|
||||
/**@brief Return the inverse of this transform times the other transform
|
||||
* @param t The other transform
|
||||
* return this.inverse() * the other */
|
||||
btTransform inverseTimes(const btTransform& t) const;
|
||||
btTransform inverseTimes(const btTransform& t) const;
|
||||
|
||||
/**@brief Return the product of this transform and the other */
|
||||
/**@brief Return the product of this transform and the other */
|
||||
btTransform operator*(const btTransform& t) const;
|
||||
|
||||
/**@brief Return an identity transform */
|
||||
static const btTransform& getIdentity()
|
||||
/**@brief Return an identity transform */
|
||||
static const btTransform& getIdentity()
|
||||
{
|
||||
static const btTransform identityTransform(btMatrix3x3::getIdentity());
|
||||
return identityTransform;
|
||||
}
|
||||
|
||||
void serialize(struct btTransformData & dataOut) const;
|
||||
void serialize(struct btTransformData& dataOut) const;
|
||||
|
||||
void serializeFloat(struct btTransformFloatData & dataOut) const;
|
||||
void serializeFloat(struct btTransformFloatData& dataOut) const;
|
||||
|
||||
void deSerialize(const struct btTransformData& dataIn);
|
||||
void deSerialize(const struct btTransformData& dataIn);
|
||||
|
||||
void deSerializeDouble(const struct btTransformDoubleData& dataIn);
|
||||
void deSerializeDouble(const struct btTransformDoubleData& dataIn);
|
||||
|
||||
void deSerializeFloat(const struct btTransformFloatData& dataIn);
|
||||
|
||||
void deSerializeFloat(const struct btTransformFloatData& dataIn);
|
||||
};
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE btVector3
|
||||
btTransform::invXform(const btVector3& inVec) const
|
||||
{
|
||||
|
|
@ -218,69 +226,80 @@ btTransform::invXform(const btVector3& inVec) const
|
|||
return (m_basis.transpose() * v);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btTransform
|
||||
btTransform::inverseTimes(const btTransform& t) const
|
||||
SIMD_FORCE_INLINE btTransform
|
||||
btTransform::inverseTimes(const btTransform& t) const
|
||||
{
|
||||
btVector3 v = t.getOrigin() - m_origin;
|
||||
return btTransform(m_basis.transposeTimes(t.m_basis),
|
||||
v * m_basis);
|
||||
return btTransform(m_basis.transposeTimes(t.m_basis),
|
||||
v * m_basis);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE btTransform
|
||||
btTransform::operator*(const btTransform& t) const
|
||||
SIMD_FORCE_INLINE btTransform
|
||||
btTransform::operator*(const btTransform& t) const
|
||||
{
|
||||
return btTransform(m_basis * t.m_basis,
|
||||
(*this)(t.m_origin));
|
||||
return btTransform(m_basis * t.m_basis,
|
||||
(*this)(t.m_origin));
|
||||
}
|
||||
|
||||
/**@brief Test if two transforms have all elements equal */
|
||||
SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
|
||||
{
|
||||
return (t1.getBasis() == t2.getBasis() &&
|
||||
t1.getOrigin() == t2.getOrigin());
|
||||
return ( t1.getBasis() == t2.getBasis() &&
|
||||
t1.getOrigin() == t2.getOrigin() );
|
||||
}
|
||||
|
||||
|
||||
///for serialization
|
||||
struct btTransformFloatData
|
||||
struct btTransformFloatData
|
||||
{
|
||||
btMatrix3x3FloatData m_basis;
|
||||
btVector3FloatData m_origin;
|
||||
btMatrix3x3FloatData m_basis;
|
||||
btVector3FloatData m_origin;
|
||||
};
|
||||
|
||||
struct btTransformDoubleData
|
||||
struct btTransformDoubleData
|
||||
{
|
||||
btMatrix3x3DoubleData m_basis;
|
||||
btVector3DoubleData m_origin;
|
||||
btMatrix3x3DoubleData m_basis;
|
||||
btVector3DoubleData m_origin;
|
||||
};
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
|
||||
{
|
||||
m_basis.serialize(dataOut.m_basis);
|
||||
m_origin.serialize(dataOut.m_origin);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
|
||||
SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
|
||||
{
|
||||
m_basis.serializeFloat(dataOut.m_basis);
|
||||
m_origin.serializeFloat(dataOut.m_origin);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
|
||||
{
|
||||
m_basis.deSerialize(dataIn.m_basis);
|
||||
m_origin.deSerialize(dataIn.m_origin);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
|
||||
SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
|
||||
{
|
||||
m_basis.deSerializeFloat(dataIn.m_basis);
|
||||
m_origin.deSerializeFloat(dataIn.m_origin);
|
||||
}
|
||||
|
||||
SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
|
||||
SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
|
||||
{
|
||||
m_basis.deSerializeDouble(dataIn.m_basis);
|
||||
m_origin.deSerializeDouble(dataIn.m_origin);
|
||||
}
|
||||
|
||||
#endif //BT_TRANSFORM_H
|
||||
|
||||
#endif //BT_TRANSFORM_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,66 +12,77 @@ subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BT_TRANSFORM_UTIL_H
|
||||
#define BT_TRANSFORM_UTIL_H
|
||||
|
||||
#include "btTransform.h"
|
||||
#define ANGULAR_MOTION_THRESHOLD btScalar(0.5) * SIMD_HALF_PI
|
||||
#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents, const btVector3& supportDir)
|
||||
|
||||
|
||||
|
||||
SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
|
||||
{
|
||||
return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
|
||||
supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
|
||||
supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
|
||||
supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
|
||||
supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Utils related to temporal transforms
|
||||
class btTransformUtil
|
||||
{
|
||||
|
||||
public:
|
||||
static void integrateTransform(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btTransform& predictedTransform)
|
||||
|
||||
static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
|
||||
{
|
||||
predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
|
||||
// #define QUATERNION_DERIVATIVE
|
||||
#ifdef QUATERNION_DERIVATIVE
|
||||
// #define QUATERNION_DERIVATIVE
|
||||
#ifdef QUATERNION_DERIVATIVE
|
||||
btQuaternion predictedOrn = curTrans.getRotation();
|
||||
predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
|
||||
predictedOrn.safeNormalize();
|
||||
#else
|
||||
#else
|
||||
//Exponential map
|
||||
//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
|
||||
|
||||
btVector3 axis;
|
||||
btScalar fAngle2 = angvel.length2();
|
||||
btScalar fAngle = 0;
|
||||
if (fAngle2 > SIMD_EPSILON)
|
||||
{
|
||||
fAngle = btSqrt(fAngle2);
|
||||
}
|
||||
btScalar fAngle2 = angvel.length2();
|
||||
btScalar fAngle = 0;
|
||||
if (fAngle2>SIMD_EPSILON)
|
||||
{
|
||||
fAngle = btSqrt(fAngle2);
|
||||
}
|
||||
|
||||
//limit the angular motion
|
||||
if (fAngle * timeStep > ANGULAR_MOTION_THRESHOLD)
|
||||
if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
|
||||
{
|
||||
fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
|
||||
}
|
||||
|
||||
if (fAngle < btScalar(0.001))
|
||||
if ( fAngle < btScalar(0.001) )
|
||||
{
|
||||
// use Taylor's expansions of sync function
|
||||
axis = angvel * (btScalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (btScalar(0.020833333333)) * fAngle * fAngle);
|
||||
axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
|
||||
}
|
||||
else
|
||||
{
|
||||
// sync(fAngle) = sin(c*fAngle)/t
|
||||
axis = angvel * (btSin(btScalar(0.5) * fAngle * timeStep) / fAngle);
|
||||
axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
|
||||
}
|
||||
btQuaternion dorn(axis.x(), axis.y(), axis.z(), btCos(fAngle * timeStep * btScalar(0.5)));
|
||||
btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
|
||||
btQuaternion orn0 = curTrans.getRotation();
|
||||
|
||||
btQuaternion predictedOrn = dorn * orn0;
|
||||
predictedOrn.safeNormalize();
|
||||
#endif
|
||||
if (predictedOrn.length2() > SIMD_EPSILON)
|
||||
#endif
|
||||
if (predictedOrn.length2()>SIMD_EPSILON)
|
||||
{
|
||||
predictedTransform.setRotation(predictedOrn);
|
||||
}
|
||||
|
|
@ -81,133 +92,137 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static void calculateVelocityQuaternion(const btVector3& pos0, const btVector3& pos1, const btQuaternion& orn0, const btQuaternion& orn1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
|
||||
static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
|
||||
{
|
||||
linVel = (pos1 - pos0) / timeStep;
|
||||
btVector3 axis;
|
||||
btScalar angle;
|
||||
btScalar angle;
|
||||
if (orn0 != orn1)
|
||||
{
|
||||
calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
|
||||
calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
|
||||
angVel = axis * angle / timeStep;
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
angVel.setValue(0, 0, 0);
|
||||
angVel.setValue(0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0, const btQuaternion& orn1a, btVector3& axis, btScalar& angle)
|
||||
static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
|
||||
{
|
||||
btQuaternion orn1 = orn0.nearest(orn1a);
|
||||
btQuaternion dorn = orn1 * orn0.inverse();
|
||||
angle = dorn.getAngle();
|
||||
axis = btVector3(dorn.x(), dorn.y(), dorn.z());
|
||||
axis = btVector3(dorn.x(),dorn.y(),dorn.z());
|
||||
axis[3] = btScalar(0.);
|
||||
//check for axis length
|
||||
btScalar len = axis.length2();
|
||||
if (len < SIMD_EPSILON * SIMD_EPSILON)
|
||||
axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
|
||||
if (len < SIMD_EPSILON*SIMD_EPSILON)
|
||||
axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
|
||||
else
|
||||
axis /= btSqrt(len);
|
||||
}
|
||||
|
||||
static void calculateVelocity(const btTransform& transform0, const btTransform& transform1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
|
||||
static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
|
||||
{
|
||||
linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
|
||||
btVector3 axis;
|
||||
btScalar angle;
|
||||
calculateDiffAxisAngle(transform0, transform1, axis, angle);
|
||||
btScalar angle;
|
||||
calculateDiffAxisAngle(transform0,transform1,axis,angle);
|
||||
angVel = axis * angle / timeStep;
|
||||
}
|
||||
|
||||
static void calculateDiffAxisAngle(const btTransform& transform0, const btTransform& transform1, btVector3& axis, btScalar& angle)
|
||||
static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
|
||||
{
|
||||
btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
|
||||
btQuaternion dorn;
|
||||
dmat.getRotation(dorn);
|
||||
|
||||
///floating point inaccuracy can lead to w component > 1..., which breaks
|
||||
///floating point inaccuracy can lead to w component > 1..., which breaks
|
||||
dorn.normalize();
|
||||
|
||||
|
||||
angle = dorn.getAngle();
|
||||
axis = btVector3(dorn.x(), dorn.y(), dorn.z());
|
||||
axis = btVector3(dorn.x(),dorn.y(),dorn.z());
|
||||
axis[3] = btScalar(0.);
|
||||
//check for axis length
|
||||
btScalar len = axis.length2();
|
||||
if (len < SIMD_EPSILON * SIMD_EPSILON)
|
||||
axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
|
||||
if (len < SIMD_EPSILON*SIMD_EPSILON)
|
||||
axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
|
||||
else
|
||||
axis /= btSqrt(len);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
|
||||
|
||||
///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
|
||||
///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
|
||||
class btConvexSeparatingDistanceUtil
|
||||
class btConvexSeparatingDistanceUtil
|
||||
{
|
||||
btQuaternion m_ornA;
|
||||
btQuaternion m_ornB;
|
||||
btVector3 m_posA;
|
||||
btVector3 m_posB;
|
||||
btQuaternion m_ornA;
|
||||
btQuaternion m_ornB;
|
||||
btVector3 m_posA;
|
||||
btVector3 m_posB;
|
||||
|
||||
btVector3 m_separatingNormal;
|
||||
|
||||
btVector3 m_separatingNormal;
|
||||
|
||||
btScalar m_boundingRadiusA;
|
||||
btScalar m_boundingRadiusB;
|
||||
btScalar m_separatingDistance;
|
||||
btScalar m_boundingRadiusA;
|
||||
btScalar m_boundingRadiusB;
|
||||
btScalar m_separatingDistance;
|
||||
|
||||
public:
|
||||
btConvexSeparatingDistanceUtil(btScalar boundingRadiusA, btScalar boundingRadiusB)
|
||||
: m_boundingRadiusA(boundingRadiusA),
|
||||
m_boundingRadiusB(boundingRadiusB),
|
||||
m_separatingDistance(0.f)
|
||||
|
||||
btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB)
|
||||
:m_boundingRadiusA(boundingRadiusA),
|
||||
m_boundingRadiusB(boundingRadiusB),
|
||||
m_separatingDistance(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
btScalar getConservativeSeparatingDistance()
|
||||
btScalar getConservativeSeparatingDistance()
|
||||
{
|
||||
return m_separatingDistance;
|
||||
}
|
||||
|
||||
void updateSeparatingDistance(const btTransform& transA, const btTransform& transB)
|
||||
void updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
|
||||
{
|
||||
const btVector3& toPosA = transA.getOrigin();
|
||||
const btVector3& toPosB = transB.getOrigin();
|
||||
btQuaternion toOrnA = transA.getRotation();
|
||||
btQuaternion toOrnB = transB.getRotation();
|
||||
|
||||
if (m_separatingDistance > 0.f)
|
||||
if (m_separatingDistance>0.f)
|
||||
{
|
||||
btVector3 linVelA, angVelA, linVelB, angVelB;
|
||||
btTransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, btScalar(1.), linVelA, angVelA);
|
||||
btTransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, btScalar(1.), linVelB, angVelB);
|
||||
|
||||
|
||||
btVector3 linVelA,angVelA,linVelB,angVelB;
|
||||
btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
|
||||
btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
|
||||
btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
|
||||
btVector3 relLinVel = (linVelB - linVelA);
|
||||
btVector3 relLinVel = (linVelB-linVelA);
|
||||
btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
|
||||
if (relLinVelocLength < 0.f)
|
||||
if (relLinVelocLength<0.f)
|
||||
{
|
||||
relLinVelocLength = 0.f;
|
||||
}
|
||||
|
||||
btScalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
|
||||
|
||||
btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
|
||||
m_separatingDistance -= projectedMotion;
|
||||
}
|
||||
|
||||
|
||||
m_posA = toPosA;
|
||||
m_posB = toPosB;
|
||||
m_ornA = toOrnA;
|
||||
m_ornB = toOrnB;
|
||||
}
|
||||
|
||||
void initSeparatingDistance(const btVector3& separatingVector, btScalar separatingDistance, const btTransform& transA, const btTransform& transB)
|
||||
void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
|
||||
{
|
||||
m_separatingDistance = separatingDistance;
|
||||
|
||||
if (m_separatingDistance > 0.f)
|
||||
if (m_separatingDistance>0.f)
|
||||
{
|
||||
m_separatingNormal = separatingVector;
|
||||
|
||||
|
||||
const btVector3& toPosA = transA.getOrigin();
|
||||
const btVector3& toPosB = transB.getOrigin();
|
||||
btQuaternion toOrnA = transA.getRotation();
|
||||
|
|
@ -218,6 +233,9 @@ public:
|
|||
m_ornB = toOrnB;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_TRANSFORM_UTIL_H
|
||||
|
||||
#endif //BT_TRANSFORM_UTIL_H
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +1,10 @@
|
|||
project "LinearMath"
|
||||
|
||||
kind "StaticLib"
|
||||
if os.is("Linux") then
|
||||
buildoptions{"-fPIC"}
|
||||
end
|
||||
includedirs {
|
||||
"..",
|
||||
}
|
||||
files {
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"TaskScheduler/*.cpp",
|
||||
"TaskScheduler/*.h"
|
||||
"*.h"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue