From c5fc66ee58f2c60f2d226868bb1cf5b91badaf53 Mon Sep 17 00:00:00 2001 From: sanine Date: Sat, 1 Oct 2022 20:59:36 -0500 Subject: add ode --- .../ode/src/collision_trimesh_internal.cpp | 804 +++++++++++++++++++++ 1 file changed, 804 insertions(+) create mode 100644 libs/ode-0.16.1/ode/src/collision_trimesh_internal.cpp (limited to 'libs/ode-0.16.1/ode/src/collision_trimesh_internal.cpp') diff --git a/libs/ode-0.16.1/ode/src/collision_trimesh_internal.cpp b/libs/ode-0.16.1/ode/src/collision_trimesh_internal.cpp new file mode 100644 index 0000000..b96e25f --- /dev/null +++ b/libs/ode-0.16.1/ode/src/collision_trimesh_internal.cpp @@ -0,0 +1,804 @@ +/************************************************************************* + * * + * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * + * All rights reserved. Email: russ@q12.org Web: www.q12.org * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of EITHER: * + * (1) The GNU Lesser General Public License as published by the Free * + * Software Foundation; either version 2.1 of the License, or (at * + * your option) any later version. The text of the GNU Lesser * + * General Public License is included with this library in the * + * file LICENSE.TXT. * + * (2) The BSD-style license that is included with this library in * + * the file LICENSE-BSD.TXT. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * + * LICENSE.TXT and LICENSE-BSD.TXT for more details. * + * * + *************************************************************************/ + +// TriMesh storage classes refactoring and face angle computation code by Oleh Derevenko (C) 2016-2019 + +#include +#include +#include "config.h" +#include "matrix.h" +#include "odemath.h" + + +#if dTRIMESH_ENABLED + +#include "collision_trimesh_internal.h" +#include "odeou.h" + +#include + + + +////////////////////////////////////////////////////////////////////////// + +enum EdgeStorageSignInclusion +{ + SSI__MIN, + + SSI_SIGNED_STORED = SSI__MIN, + SSI_POSITIVE_STORED, + + SSI__MAX, +}; + +template +class FaceAngleStorageCodec; + +template +class FaceAngleStorageCodec +{ +public: + typedef typename _make_signed::type storage_type; + enum + { + STORAGE_TYPE_MAX = (typename _make_unsigned::type)(~(typename _make_unsigned::type)0) >> 1, + }; + + static bool areNegativeAnglesCoded() + { + return true; + } + + static storage_type encodeForStorage(dReal angleValue) + { + unsigned angleAsInt = (unsigned)dFloor(dFabs(angleValue) * (dReal)(STORAGE_TYPE_MAX / M_PI)); + unsigned limitedAngleAsInt = dMACRO_MIN(angleAsInt, STORAGE_TYPE_MAX); + storage_type result = angleValue < REAL(0.0) ? -(storage_type)limitedAngleAsInt : (storage_type)limitedAngleAsInt; + return result; + } + + static FaceAngleDomain classifyStorageValue(storage_type storedValue) + { + dSASSERT(EAD__MAX == 3); + + return storedValue < 0 ? FAD_CONCAVE : (storedValue == 0 ? FAD_FLAT : FAD_CONVEX); + } + + static bool isAngleDomainStored(FaceAngleDomain domainValue) + { + return !dTMPL_IN_RANGE(domainValue, FAD__SIGNSTORED_IMPLICITVALUE_MIN, FAD__SIGNSTORED_IMPLICITVALUE_MAX); + } + + static dReal decodeStorageValue(storage_type storedValue) + { + return storedValue * (dReal)(M_PI / STORAGE_TYPE_MAX); + } +}; + +template +class FaceAngleStorageCodec +{ +public: + typedef typename _make_unsigned::type storage_type; + enum + { + STORAGE_TYPE_MIN = 0, + STORAGE_TYPE_MAX = (storage_type)(~(storage_type)0), + }; + + static bool areNegativeAnglesCoded() + { + return false; + } + + static storage_type encodeForStorage(dReal angleValue) + { + storage_type result = STORAGE_TYPE_MIN; + + if (angleValue >= REAL(0.0)) + { + unsigned angleAsInt = (unsigned)dFloor(angleValue * (dReal)(((STORAGE_TYPE_MAX - STORAGE_TYPE_MIN - 1) / M_PI))); + result = (STORAGE_TYPE_MIN + 1) + dMACRO_MIN(angleAsInt, STORAGE_TYPE_MAX - STORAGE_TYPE_MIN - 1); + } + + return result; + } + + static FaceAngleDomain classifyStorageValue(storage_type storedValue) + { + dSASSERT(EAD__MAX == 3); + + return storedValue < STORAGE_TYPE_MIN + 1 ? FAD_CONCAVE : (storedValue == STORAGE_TYPE_MIN + 1 ? FAD_FLAT : FAD_CONVEX); + } + + static bool isAngleDomainStored(FaceAngleDomain domainValue) + { + return dTMPL_IN_RANGE(domainValue, FAD__BYTEPOS_STORED_MIN, FAD__BYTEPOS_STORED_MAX); + } + + static dReal decodeStorageValue(storage_type storedValue) + { + dIASSERT(storedValue >= (STORAGE_TYPE_MIN + 1)); + + return (storedValue - (STORAGE_TYPE_MIN + 1)) * (dReal)(M_PI / (STORAGE_TYPE_MAX - STORAGE_TYPE_MIN - 1)); + } +}; + +template +class FaceAnglesWrapper: + public IFaceAngleStorageControl, + public IFaceAngleStorageView +{ +protected: + FaceAnglesWrapper(unsigned triangleCount) { setAllocatedTriangleCount(triangleCount); } + +public: + virtual ~FaceAnglesWrapper(); + + static IFaceAngleStorageControl *allocateInstance(unsigned triangleCount, IFaceAngleStorageView *&out_storageView); + + static bool calculateInstanceSizeRequired(sizeint &out_sizeRequired, unsigned triangleCount); + +private: + void freeInstance(); + +private: + typedef typename TStorageCodec::storage_type storage_type; + typedef storage_type TriangleFaceAngles[dMTV__MAX]; + + struct StorageRecord + { + StorageRecord(): m_triangleCount(0) {} + + unsigned m_triangleCount; + TriangleFaceAngles m_triangleFaceAngles[1]; + }; + + static sizeint calculateStorageSizeForTriangleCount(unsigned triangleCount) + { + const unsigned baseIncludedTriangleCount = dSTATIC_ARRAY_SIZE(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles); + const sizeint singleTriangleSize = membersize(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles[0]); + return sizeof(FaceAnglesWrapper) + (triangleCount > baseIncludedTriangleCount ? (triangleCount - baseIncludedTriangleCount) * singleTriangleSize : 0U); + } + + static sizeint calculateTriangleCountForStorageSize(sizeint storageSize) + { + dIASSERT(storageSize >= sizeof(FaceAnglesWrapper)); + + const unsigned baseIncludedTriangleCount = dSTATIC_ARRAY_SIZE(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles); + const sizeint singleTriangleSize = membersize(FaceAnglesWrapper::StorageRecord, m_triangleFaceAngles[0]); + return (storageSize - sizeof(FaceAnglesWrapper)) / singleTriangleSize + baseIncludedTriangleCount; + } + +private: // IFaceAngleStorageControl + virtual void disposeStorage(); + + virtual bool areNegativeAnglesStored() const; + + virtual void assignFacesAngleIntoStorage(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue); + +private: // IFaceAngleStorageView + virtual FaceAngleDomain retrieveFacesAngleFromStorage(dReal &out_angleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex); + +public: + void setFaceAngle(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue) + { + dIASSERT(dTMPL_IN_RANGE(triangleIndex, 0, getAllocatedTriangleCount())); + dIASSERT(dTMPL_IN_RANGE(vertexIndex, dMTV__MIN, dMTV__MAX)); + + m_record.m_triangleFaceAngles[triangleIndex][vertexIndex] = TStorageCodec::encodeForStorage(dAngleValue); + } + + FaceAngleDomain getFaceAngle(dReal &out_angleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex) const + { + dIASSERT(dTMPL_IN_RANGE(triangleIndex, 0, getAllocatedTriangleCount())); + dIASSERT(dTMPL_IN_RANGE(vertexIndex, dMTV__MIN, dMTV__MAX)); + + storage_type storedValue = m_record.m_triangleFaceAngles[triangleIndex][vertexIndex]; + FaceAngleDomain resultDomain = TStorageCodec::classifyStorageValue(storedValue); + + out_angleValue = TStorageCodec::isAngleDomainStored(resultDomain) ? TStorageCodec::decodeStorageValue(storedValue) : REAL(0.0); + return resultDomain; + } + +private: + unsigned getAllocatedTriangleCount() const { return m_record.m_triangleCount; } + void setAllocatedTriangleCount(unsigned triangleCount) { m_record.m_triangleCount = triangleCount; } + +private: + StorageRecord m_record; +}; + + +template +FaceAnglesWrapper::~FaceAnglesWrapper() +{ +} + + +template +/*static */ +IFaceAngleStorageControl *FaceAnglesWrapper::allocateInstance(unsigned triangleCount, IFaceAngleStorageView *&out_storageView) +{ + FaceAnglesWrapper *result = NULL; + + do + { + sizeint sizeRequired; + if (!FaceAnglesWrapper::calculateInstanceSizeRequired(sizeRequired, triangleCount)) + { + break; + } + + void *bufferPointer = dAlloc(sizeRequired); + if (bufferPointer == NULL) + { + break; + } + + result = (FaceAnglesWrapper *)bufferPointer; + new(result) FaceAnglesWrapper(triangleCount); + + out_storageView = result; + } + while (false); + + return result; +} + +template +/*static */ +bool FaceAnglesWrapper::calculateInstanceSizeRequired(sizeint &out_sizeRequired, unsigned triangleCount) +{ + bool result = false; + + do + { + sizeint triangleMaximumCount = calculateTriangleCountForStorageSize(SIZE_MAX); + dIASSERT(triangleCount <= triangleMaximumCount); + + if (triangleCount > triangleMaximumCount) // Check for overflow + { + break; + } + + out_sizeRequired = calculateStorageSizeForTriangleCount(triangleCount); // Trailing alignment is going to be added by memory manager automatically + result = true; + } + while (false); + + return result; +} + +template +void FaceAnglesWrapper::freeInstance() +{ + unsigned triangleCount = getAllocatedTriangleCount(); + + this->FaceAnglesWrapper::~FaceAnglesWrapper(); + + sizeint memoryBlockSize = calculateStorageSizeForTriangleCount(triangleCount); + dFree(this, memoryBlockSize); +} + + +template +/*virtual */ +void FaceAnglesWrapper::disposeStorage() +{ + freeInstance(); +} + +template +/*virtual */ +bool FaceAnglesWrapper::areNegativeAnglesStored() const +{ + return TStorageCodec::areNegativeAnglesCoded(); +} + +template +/*virtual */ +void FaceAnglesWrapper::assignFacesAngleIntoStorage(unsigned triangleIndex, dMeshTriangleVertex vertexIndex, dReal dAngleValue) +{ + setFaceAngle(triangleIndex, vertexIndex, dAngleValue); +} + +template +/*virtual */ +FaceAngleDomain FaceAnglesWrapper::retrieveFacesAngleFromStorage(dReal &out_angleValue, unsigned triangleIndex, dMeshTriangleVertex vertexIndex) +{ + return getFaceAngle(out_angleValue, triangleIndex, vertexIndex); +} + + +typedef IFaceAngleStorageControl *(FAngleStorageAllocProc)(unsigned triangleCount, IFaceAngleStorageView *&out_storageView); + +BEGIN_NAMESPACE_OU(); +template<> +FAngleStorageAllocProc *const CEnumUnsortedElementArray::m_aetElementArray[] = +{ + &FaceAnglesWrapper >::allocateInstance, // ASM_BYTE_SIGNED, + &FaceAnglesWrapper >::allocateInstance, // ASM_BYTE_POSITIVE, + &FaceAnglesWrapper >::allocateInstance, // ASM_WORD_SIGNED, +}; +END_NAMESPACE_OU(); +static const CEnumUnsortedElementArray g_AngleStorageAllocProcs; + + +////////////////////////////////////////////////////////////////////////// + +dxTriDataBase::~dxTriDataBase() +{ + freeFaceAngles(); +} + + +void dxTriDataBase::buildData(const void *vertices, int vertexStride, unsigned vertexCount, + const void *indices, unsigned indexCount, int triStride, + const void *normals, + bool single) +{ + dIASSERT(vertices); + dIASSERT(indices); + dIASSERT(vertexStride); + dIASSERT(triStride); + dIASSERT(indexCount); + dIASSERT(indexCount % dMTV__MAX == 0); + + m_vertices = vertices; + m_vertexStride = vertexStride; + m_vertexCount = vertexCount; + m_indices = indices; + m_triangleCount = indexCount / dMTV__MAX; + m_triStride = triStride; + m_single = single; + + m_normals = normals; +} + + +bool dxTriDataBase::allocateFaceAngles(FaceAngleStorageMethod storageMethod) +{ + bool result = false; + + dIASSERT(m_faceAngles == NULL); + + IFaceAngleStorageView *storageView; + + unsigned triangleCount = m_triangleCount; + + FAngleStorageAllocProc *allocProc = g_AngleStorageAllocProcs.Encode(storageMethod); + IFaceAngleStorageControl *storageInstance = allocProc(triangleCount, storageView); + + if (storageInstance != NULL) + { + m_faceAngles = storageInstance; + m_faceAngleView = storageView; + result = true; + } + + return result; +} + +void dxTriDataBase::freeFaceAngles() +{ + if (m_faceAngles != NULL) + { + m_faceAngles->disposeStorage(); + m_faceAngles = NULL; + m_faceAngleView = NULL; + } +} + + +void dxTriDataBase::EdgeRecord::setupEdge(dMeshTriangleVertex edgeIdx, int triIdx, const unsigned vertexIndices[dMTV__MAX]) +{ + if (edgeIdx < dMTV_SECOND) + { + dIASSERT(edgeIdx == dMTV_FIRST); + + m_edgeFlags = dxTriMeshData::CUF_USE_FIRST_EDGE; + m_vert1Flags = dxTriMeshData::CUF_USE_FIRST_VERTEX; + m_vert2Flags = dxTriMeshData::CUF_USE_SECOND_VERTEX; + m_vertIdx1 = vertexIndices[dMTV_FIRST]; + m_vertIdx2 = vertexIndices[dMTV_SECOND]; + } + else if (edgeIdx == dMTV_SECOND) + { + m_edgeFlags = dxTriMeshData::CUF_USE_SECOND_EDGE; + m_vert1Flags = dxTriMeshData::CUF_USE_SECOND_VERTEX; + m_vert2Flags = dxTriMeshData::CUF_USE_THIRD_VERTEX; + m_vertIdx1 = vertexIndices[dMTV_SECOND]; + m_vertIdx2 = vertexIndices[dMTV_THIRD]; + } + else + { + dIASSERT(edgeIdx == dMTV_THIRD); + + m_edgeFlags = dxTriMeshData::CUF_USE_THIRD_EDGE; + m_vert1Flags = dxTriMeshData::CUF_USE_THIRD_VERTEX; + m_vert2Flags = dxTriMeshData::CUF_USE_FIRST_VERTEX; + m_vertIdx1 = vertexIndices[dMTV_THIRD]; + m_vertIdx2 = vertexIndices[dMTV_FIRST]; + } + + // Make sure vertex index 1 is less than index 2 (for easier sorting) + if (m_vertIdx1 > m_vertIdx2) + { + dxSwap(m_vertIdx1, m_vertIdx2); + dxSwap(m_vert1Flags, m_vert2Flags); + } + + m_triIdx = triIdx; + m_absVertexFlags = 0; +} + + +BEGIN_NAMESPACE_OU(); +template<> +const dMeshTriangleVertex CEnumUnsortedElementArray::m_aetElementArray[] = +{ + dMTV_FIRST, // kVert0 / kVert_Base + dMTV_SECOND, // kVert1 / kVert_Base + dMTV__MAX, + dMTV_THIRD, // kVert2 / kVert_Base +}; +END_NAMESPACE_OU(); +/*extern */const CEnumUnsortedElementArray g_VertFlagOppositeIndices; + +BEGIN_NAMESPACE_OU(); +template<> +const dMeshTriangleVertex CEnumUnsortedElementArray::m_aetElementArray[] = +{ + dMTV_SECOND, // kVert0 / kVert_Base + dMTV_THIRD, // kVert1 / kVert_Base + dMTV__MAX, + dMTV_FIRST, // kVert2 / kVert_Base +}; +END_NAMESPACE_OU(); +/*extern */const CEnumUnsortedElementArray g_VertFlagEdgeStartIndices; + + +////////////////////////////////////////////////////////////////////////// + +/*extern ODE_API */ +void dGeomTriMeshDataBuildSimple1(dTriMeshDataID g, + const dReal* Vertices, int VertexCount, + const dTriIndex* Indices, int IndexCount, + const int *Normals) +{ +#ifdef dSINGLE + dGeomTriMeshDataBuildSingle1(g, + Vertices, 4 * sizeof(dReal), VertexCount, + Indices, IndexCount, 3 * sizeof(dTriIndex), + Normals); +#else + dGeomTriMeshDataBuildDouble1(g, Vertices, 4 * sizeof(dReal), VertexCount, + Indices, IndexCount, 3 * sizeof(dTriIndex), + Normals); +#endif +} + + +/*extern ODE_API */ +void dGeomTriMeshDataBuildSingle(dTriMeshDataID g, + const void* Vertices, int VertexStride, int VertexCount, + const void* Indices, int IndexCount, int TriStride) +{ + dGeomTriMeshDataBuildSingle1(g, Vertices, VertexStride, VertexCount, + Indices, IndexCount, TriStride, (const void *)NULL); +} + +/*extern ODE_API */ +void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, + const void* Vertices, int VertexStride, int VertexCount, + const void* Indices, int IndexCount, int TriStride) +{ + dGeomTriMeshDataBuildDouble1(g, Vertices, VertexStride, VertexCount, + Indices, IndexCount, TriStride, NULL); +} + +/*extern ODE_API */ +void dGeomTriMeshDataBuildSimple(dTriMeshDataID g, + const dReal* Vertices, int VertexCount, + const dTriIndex* Indices, int IndexCount) +{ + dGeomTriMeshDataBuildSimple1(g, + Vertices, VertexCount, Indices, IndexCount, + (int *)NULL); +} + + +/*extern ODE_API */ +int dGeomTriMeshDataPreprocess(dTriMeshDataID g) +{ + unsigned buildRequestFlags = (1U << dTRIDATAPREPROCESS_BUILD_CONCAVE_EDGES); + return dGeomTriMeshDataPreprocess2(g, buildRequestFlags, NULL); +} + + +BEGIN_NAMESPACE_OU(); +template<> +const FaceAngleStorageMethod CEnumUnsortedElementArray::m_aetElementArray[] = +{ + ASM_BYTE_POSITIVE, // dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_POSITIVE, + ASM_BYTE_SIGNED, // dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_BYTE_ALL, + ASM_WORD_SIGNED, // dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA_WORD_ALL, +}; +END_NAMESPACE_OU(); +static const CEnumUnsortedElementArray g_TriMeshDataPreprocess_FaceAndlesExtraDataAngleStorageMethods; + +/*extern ODE_API */ +int dGeomTriMeshDataPreprocess2(dTriMeshDataID g, unsigned int buildRequestFlags, const intptr *requestExtraData/*=NULL | const intptr (*)[dTRIDATAPREPROCESS_BUILD__MAX]*/) +{ + dUASSERT(g, "The argument is not a trimesh data"); + dAASSERT((buildRequestFlags & (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES)) == 0 || requestExtraData == NULL || dIN_RANGE(requestExtraData[dTRIDATAPREPROCESS_BUILD_FACE_ANGLES], dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MIN, dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MAX)); + + dxTriMeshData *data = g; + + bool buildUseFlags = (buildRequestFlags & (1U << dTRIDATAPREPROCESS_BUILD_CONCAVE_EDGES)) != 0; + FaceAngleStorageMethod faceAnglesRequirement = (buildRequestFlags & (1U << dTRIDATAPREPROCESS_BUILD_FACE_ANGLES)) != 0 + ? g_TriMeshDataPreprocess_FaceAndlesExtraDataAngleStorageMethods.Encode(requestExtraData != NULL && dIN_RANGE(requestExtraData[dTRIDATAPREPROCESS_BUILD_FACE_ANGLES], dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MIN, dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__MAX) ? (unsigned)requestExtraData[dTRIDATAPREPROCESS_BUILD_FACE_ANGLES] : dTRIDATAPREPROCESS_FACE_ANGLES_EXTRA__DEFAULT) + : ASM__INVALID; + return data->preprocessData(buildUseFlags, faceAnglesRequirement); +} + +/*extern ODE_API */ +void dGeomTriMeshDataUpdate(dTriMeshDataID g) +{ + dUASSERT(g, "The argument is not a trimesh data"); + + dxTriMeshData *data = g; + data->updateData(); +} + + +////////////////////////////////////////////////////////////////////////// + +/*extern ODE_API */ +void dGeomTriMeshSetCallback(dGeomID g, dTriCallback* Callback) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + mesh->assignCallback(Callback); +} + +/*extern ODE_API */ +dTriCallback* dGeomTriMeshGetCallback(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + return mesh->retrieveCallback(); +} + +/*extern ODE_API */ +void dGeomTriMeshSetArrayCallback(dGeomID g, dTriArrayCallback* ArrayCallback) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + mesh->assignArrayCallback(ArrayCallback); +} + +/*extern ODE_API */ +dTriArrayCallback *dGeomTriMeshGetArrayCallback(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + return mesh->retrieveArrayCallback(); +} + +/*extern ODE_API */ +void dGeomTriMeshSetRayCallback(dGeomID g, dTriRayCallback* Callback) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + mesh->assignRayCallback(Callback); +} + +/*extern ODE_API */ +dTriRayCallback* dGeomTriMeshGetRayCallback(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + return mesh->retrieveRayCallback(); +} + +/*extern ODE_API */ +void dGeomTriMeshSetTriMergeCallback(dGeomID g, dTriTriMergeCallback* Callback) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + mesh->assignTriMergeCallback(Callback); +} + +/*extern ODE_API */ +dTriTriMergeCallback *dGeomTriMeshGetTriMergeCallback(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + return mesh->retrieveTriMergeCallback(); +} + +/*extern ODE_API */ +void dGeomTriMeshSetData(dGeomID g, dTriMeshDataID Data) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + mesh->assignMeshData(Data); +} + +/*extern ODE_API */ +dTriMeshDataID dGeomTriMeshGetData(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + return mesh->retrieveMeshData(); +} + + +BEGIN_NAMESPACE_OU(); +template<> +const int CEnumSortedElementArray::m_aetElementArray[] = +{ + dSphereClass, // TTC_SPHERE, + dBoxClass, // TTC_BOX, + dCapsuleClass, // TTC_CAPSULE, +}; +END_NAMESPACE_OU(); +static const CEnumSortedElementArray g_asiMeshTCGeomClasses; + +/*extern ODE_API */ +void dGeomTriMeshEnableTC(dGeomID g, int geomClass, int enable) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + + dxTriMesh::TRIMESHTC tc = g_asiMeshTCGeomClasses.Decode(geomClass); + + if (g_asiMeshTCGeomClasses.IsValidDecode(tc)) + { + mesh->assignDoTC(tc, enable != 0); + } +} + +/*extern ODE_API */ +int dGeomTriMeshIsTCEnabled(dGeomID g, int geomClass) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + + dxTriMesh::TRIMESHTC tc = g_asiMeshTCGeomClasses.Decode(geomClass); + + bool result = g_asiMeshTCGeomClasses.IsValidDecode(tc) + && mesh->retrieveDoTC(tc); + return result; +} + + +/*extern ODE_API */ +dTriMeshDataID dGeomTriMeshGetTriMeshDataID(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + return mesh->retrieveMeshData(); +} + + +/*extern ODE_API */ +void dGeomTriMeshClearTCCache(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + mesh->clearTCCache(); +} + + +/*extern ODE_API */ +int dGeomTriMeshGetTriangleCount(dGeomID g) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + const dxTriMesh *mesh = static_cast(g); + unsigned result = mesh->getMeshTriangleCount(); + return result; +} + + +/*extern ODE_API */ +void dGeomTriMeshGetTriangle(dGeomID g, int index, dVector3 *v0/*=NULL*/, dVector3 *v1/*=NULL*/, dVector3 *v2/*=NULL*/) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + dUASSERT(v0 != NULL || v1 != NULL || v2 != NULL, "A meaningless call"); + + dxTriMesh *mesh = static_cast(g); + + dVector3 *pv[3] = { v0, v1, v2 }; + mesh->fetchMeshTransformedTriangle(pv, index); +} + +/*extern ODE_API */ +void dGeomTriMeshGetPoint(dGeomID g, int index, dReal u, dReal v, dVector3 Out) +{ + dUASSERT(g && g->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(g); + + dVector3 dv[3]; + mesh->fetchMeshTransformedTriangle(dv, index); + + GetPointFromBarycentric(dv, u, v, Out); +} + + +/*extern */ +IFaceAngleStorageView *dxGeomTriMeshGetFaceAngleView(dxGeom *triMeshGeom) +{ + dUASSERT(triMeshGeom && triMeshGeom->type == dTriMeshClass, "The argument is not a trimesh"); + + dxTriMesh *mesh = static_cast(triMeshGeom); + return mesh->retrieveFaceAngleView(); +} + + +#endif // #if dTRIMESH_ENABLED + + +////////////////////////////////////////////////////////////////////////// +// Deprecated functions + +/*extern */ +void dGeomTriMeshDataGetBuffer(dTriMeshDataID g, unsigned char **buf, int *bufLen) +{ + sizeint dataSizeStorage; + void *dataPointer = dGeomTriMeshDataGet2(g, dTRIMESHDATA_USE_FLAGS, (bufLen != NULL ? &dataSizeStorage : NULL)); + + if (bufLen != NULL) + { + *bufLen = (int)dataSizeStorage; + } + + if (buf != NULL) + { + *buf = (unsigned char *)dataPointer; + } +} + +/*extern */ +void dGeomTriMeshDataSetBuffer(dTriMeshDataID g, unsigned char* buf) +{ + dGeomTriMeshDataSet(g, dTRIMESHDATA_USE_FLAGS, (void *)buf); +} + -- cgit v1.2.1