From 41e9595522c71534219158609e97186e4bfeac69 Mon Sep 17 00:00:00 2001 From: Rye Date: Mon, 20 Oct 2025 13:10:19 -0400 Subject: Rework new convex decomp into a physicsextensions stub package and fix havok and havok_tpv builds for darwin universal to utilize new vhacd stub (#4858) --- autobuild.xml | 30 -- indra/CMakeLists.txt | 4 +- indra/cmake/LLPhysicsExtensions.cmake | 24 +- indra/llconvexdecomposition/CMakeLists.txt | 39 -- .../llconvexdecomposition.cpp | 83 ---- .../llconvexdecomposition/llconvexdecomposition.h | 231 ---------- .../llconvexdecompositionvhacd.cpp | 492 --------------------- .../llconvexdecompositionvhacd.h | 339 -------------- indra/llphysicsextensionsos/CMakeLists.txt | 47 ++ .../llphysicsextensionsos/LLPathingLibStubImpl.cpp | 109 +++++ indra/llphysicsextensionsos/LLPathingLibStubImpl.h | 78 ++++ .../LLPhysicsExtensionsStubImpl.cpp | 51 +++ .../LLPhysicsExtensionsStubImpl.h | 46 ++ .../llconvexdecomposition.cpp | 83 ++++ .../llphysicsextensionsos/llconvexdecomposition.h | 231 ++++++++++ .../llconvexdecompositionvhacd.cpp | 492 +++++++++++++++++++++ .../llconvexdecompositionvhacd.h | 339 ++++++++++++++ indra/llphysicsextensionsos/llpathinglib.cpp | 83 ++++ indra/llphysicsextensionsos/llpathinglib.h | 187 ++++++++ .../llphysicsextensionsos/llphysicsextensions.cpp | 78 ++++ indra/llphysicsextensionsos/llphysicsextensions.h | 59 +++ indra/llprimitive/CMakeLists.txt | 11 +- indra/newview/CMakeLists.txt | 33 +- 23 files changed, 1927 insertions(+), 1242 deletions(-) delete mode 100644 indra/llconvexdecomposition/CMakeLists.txt delete mode 100644 indra/llconvexdecomposition/llconvexdecomposition.cpp delete mode 100644 indra/llconvexdecomposition/llconvexdecomposition.h delete mode 100644 indra/llconvexdecomposition/llconvexdecompositionvhacd.cpp delete mode 100644 indra/llconvexdecomposition/llconvexdecompositionvhacd.h create mode 100644 indra/llphysicsextensionsos/CMakeLists.txt create mode 100644 indra/llphysicsextensionsos/LLPathingLibStubImpl.cpp create mode 100644 indra/llphysicsextensionsos/LLPathingLibStubImpl.h create mode 100644 indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.cpp create mode 100644 indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.h create mode 100644 indra/llphysicsextensionsos/llconvexdecomposition.cpp create mode 100644 indra/llphysicsextensionsos/llconvexdecomposition.h create mode 100644 indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp create mode 100644 indra/llphysicsextensionsos/llconvexdecompositionvhacd.h create mode 100644 indra/llphysicsextensionsos/llpathinglib.cpp create mode 100644 indra/llphysicsextensionsos/llpathinglib.h create mode 100644 indra/llphysicsextensionsos/llphysicsextensions.cpp create mode 100644 indra/llphysicsextensionsos/llphysicsextensions.h diff --git a/autobuild.xml b/autobuild.xml index 8492dff304..2983307cbe 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -1460,36 +1460,6 @@ name llphysicsextensions_source - llphysicsextensions_stub - - platforms - - common - - archive - - hash - bc41438b10ac6474cf5560465a3662a64f9e65a81342e4c33f18f6694581c7ee28c9ee6f091c36e80a0b1e10c68205be71eb5f8e40fef115d2c744fc2bbfcb43 - hash_algorithm - blake2b - url - https://github.com/AlchemyViewer/llphysicsextensions_stub/releases/download/v1.0-cb4900e/llphysicsextensions_stub-1.0-common-17836965684.tar.zst - - name - common - - - license - internal - license_file - LICENSES/llphysicsextensions.txt - copyright - Copyright (c) 2010, Linden Research, Inc. - version - 1.0 - name - llphysicsextensions_stub - llphysicsextensions_tpv platforms diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 246bd7bfa0..8fde58fa43 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -61,9 +61,6 @@ add_subdirectory(cmake) add_subdirectory(${LIBS_OPEN_PREFIX}llaudio) add_subdirectory(${LIBS_OPEN_PREFIX}llappearance) add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter) -if (NOT HAVOK AND NOT HAVOK_TPV) - add_subdirectory(${LIBS_OPEN_PREFIX}llconvexdecomposition) -endif () add_subdirectory(${LIBS_OPEN_PREFIX}llcommon) add_subdirectory(${LIBS_OPEN_PREFIX}llcorehttp) add_subdirectory(${LIBS_OPEN_PREFIX}llimage) @@ -73,6 +70,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llinventory) add_subdirectory(${LIBS_OPEN_PREFIX}llmath) add_subdirectory(${LIBS_OPEN_PREFIX}llmeshoptimizer) add_subdirectory(${LIBS_OPEN_PREFIX}llmessage) +add_subdirectory(${LIBS_OPEN_PREFIX}llphysicsextensionsos) add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive) add_subdirectory(${LIBS_OPEN_PREFIX}llrender) add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem) diff --git a/indra/cmake/LLPhysicsExtensions.cmake b/indra/cmake/LLPhysicsExtensions.cmake index 25563546eb..84722b45a7 100644 --- a/indra/cmake/LLPhysicsExtensions.cmake +++ b/indra/cmake/LLPhysicsExtensions.cmake @@ -22,7 +22,6 @@ if (HAVOK) include(Havok) use_prebuilt_binary(llphysicsextensions_source) set(LLPHYSICSEXTENSIONS_SRC_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/src) - target_compile_definitions( llphysicsextensions_impl INTERFACE LL_HAVOK=1 ) if(DARWIN) set(LLPHYSICSEXTENSIONS_STUB_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/stub) # can't set these library dependencies per-arch here, need to do it using XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=*] in newview/CMakeLists.txt @@ -30,19 +29,18 @@ if (HAVOK) #target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensionsstub) else() target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensions) + target_compile_definitions( llphysicsextensions_impl INTERFACE LL_HAVOK=1 ) endif() + target_include_directories( llphysicsextensions_impl INTERFACE ${LIBS_PREBUILT_DIR}/include/llphysicsextensions) elseif (HAVOK_TPV) use_prebuilt_binary(llphysicsextensions_tpv) - if(WINDOWS) - target_link_libraries( llphysicsextensions_impl INTERFACE ${ARCH_PREBUILT_DIRS}/llphysicsextensions_tpv.lib) - else() - target_link_libraries( llphysicsextensions_impl INTERFACE ${ARCH_PREBUILT_DIRS}/libllphysicsextensions_tpv.a) + if (NOT DARWIN) + if(WINDOWS) + target_link_libraries( llphysicsextensions_impl INTERFACE ${ARCH_PREBUILT_DIRS}/llphysicsextensions_tpv.lib) + elseif(LINUX) + target_link_libraries( llphysicsextensions_impl INTERFACE ${ARCH_PREBUILT_DIRS}/libllphysicsextensions_tpv.a) + endif() + target_compile_definitions( llphysicsextensions_impl INTERFACE LL_HAVOK=1 ) endif() - target_compile_definitions( llphysicsextensions_impl INTERFACE LL_HAVOK=1 ) -else (HAVOK) - use_prebuilt_binary(llphysicsextensions_stub) - set(LLPHYSICSEXTENSIONS_SRC_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/stub) - target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensionsstub) -endif (HAVOK) - -target_include_directories( llphysicsextensions_impl INTERFACE ${LIBS_PREBUILT_DIR}/include/llphysicsextensions) + target_include_directories( llphysicsextensions_impl INTERFACE ${LIBS_PREBUILT_DIR}/include/llphysicsextensions) +endif () diff --git a/indra/llconvexdecomposition/CMakeLists.txt b/indra/llconvexdecomposition/CMakeLists.txt deleted file mode 100644 index 7dae884db8..0000000000 --- a/indra/llconvexdecomposition/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -# -*- cmake -*- - -project(llconvexdecomposition) - -include(00-Common) -include(LLCommon) -include(LLMath) -include(VHACD) - -set(llconvexdecomposition_SOURCE_FILES - llconvexdecomposition.cpp - llconvexdecompositionvhacd.cpp - ) - -set(llconvexdecomposition_HEADER_FILES - CMakeLists.txt - llconvexdecomposition.h - llconvexdecompositionvhacd.h - ) - -set_source_files_properties(${llconvexdecomposition_HEADER_FILES} - PROPERTIES HEADER_FILE_ONLY TRUE) - -list(APPEND llconvexdecomposition_SOURCE_FILES ${llconvexdecomposition_HEADER_FILES}) - -add_library (llconvexdecomposition ${llconvexdecomposition_SOURCE_FILES}) -target_include_directories(llconvexdecomposition INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - -target_link_libraries(llconvexdecomposition - llcommon - llmath - ll::vhacd) - -if(WINDOWS) - target_compile_options(llconvexdecomposition PRIVATE /bigobj) -endif() - -# Add tests - diff --git a/indra/llconvexdecomposition/llconvexdecomposition.cpp b/indra/llconvexdecomposition/llconvexdecomposition.cpp deleted file mode 100644 index 7b9d775c53..0000000000 --- a/indra/llconvexdecomposition/llconvexdecomposition.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/** -* @file llconvexdecomposition.cpp -* @author falcon@lindenlab.com -* @brief Inner implementation of LLConvexDecomposition interface -* -* $LicenseInfo:firstyear=2011&license=lgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2011, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* 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 GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "linden_common.h" - -#include "llconvexdecompositionvhacd.h" -#include "llconvexdecomposition.h" - -bool LLConvexDecomposition::s_isInitialized = false; - -// static -bool LLConvexDecomposition::isFunctional() -{ - return LLConvexDecompositionVHACD::isFunctional(); -} - -// static -LLConvexDecomposition* LLConvexDecomposition::getInstance() -{ - if ( !s_isInitialized ) - { - return nullptr; - } - else - { - return LLConvexDecompositionVHACD::getInstance(); - } -} - -// static -LLCDResult LLConvexDecomposition::initSystem() -{ - LLCDResult result = LLConvexDecompositionVHACD::initSystem(); - if ( result == LLCD_OK ) - { - s_isInitialized = true; - } - return result; -} - -// static -LLCDResult LLConvexDecomposition::initThread() -{ - return LLConvexDecompositionVHACD::initThread(); -} - -// static -LLCDResult LLConvexDecomposition::quitThread() -{ - return LLConvexDecompositionVHACD::quitThread(); -} - -// static -LLCDResult LLConvexDecomposition::quitSystem() -{ - return LLConvexDecompositionVHACD::quitSystem(); -} - - diff --git a/indra/llconvexdecomposition/llconvexdecomposition.h b/indra/llconvexdecomposition/llconvexdecomposition.h deleted file mode 100644 index 8008bc6e12..0000000000 --- a/indra/llconvexdecomposition/llconvexdecomposition.h +++ /dev/null @@ -1,231 +0,0 @@ -/** - * @file llconvexdecomposition.cpp - * @brief LLConvexDecomposition interface definition - * - * $LicenseInfo:firstyear=2011&license=lgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * 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 GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_CONVEX_DECOMPOSITION -#define LL_CONVEX_DECOMPOSITION - -typedef int bool32; - -#if defined(_WIN32) || defined(_WIN64) -#define LLCD_CALL __cdecl -#else -#define LLCD_CALL -#endif - -struct LLCDParam -{ - enum LLCDParamType - { - LLCD_INVALID = 0, - LLCD_INTEGER, - LLCD_FLOAT, - LLCD_BOOLEAN, - LLCD_ENUM - }; - - struct LLCDEnumItem - { - const char* mName; - int mValue; - }; - - union LLCDValue - { - float mFloat; - int mIntOrEnumValue; - bool32 mBool; - }; - - union LLCDParamDetails - { - struct { - LLCDValue mLow; - LLCDValue mHigh; - LLCDValue mDelta; - } mRange; - - struct { - int mNumEnums; - LLCDEnumItem* mEnumsArray; - } mEnumValues; - }; - - const char* mName; - const char* mDescription; - LLCDParamType mType; - LLCDParamDetails mDetails; - LLCDValue mDefault; - int mStage; - - // WARNING: Only the LLConvexDecomposition implementation - // should change this value - int mReserved; -}; - -struct LLCDStageData -{ - const char* mName; - const char* mDescription; - bool32 mSupportsCallback; -}; - -struct LLCDMeshData -{ - enum IndexType - { - INT_16, - INT_32 - }; - - const float* mVertexBase; - int mVertexStrideBytes; - int mNumVertices; - const void* mIndexBase; - IndexType mIndexType; - int mIndexStrideBytes; - int mNumTriangles; -}; - -struct LLCDHull -{ - const float* mVertexBase; - int mVertexStrideBytes; - int mNumVertices; -}; - -enum LLCDResult -{ - LLCD_OK = 0, - LLCD_UNKOWN_ERROR, - LLCD_NULL_PTR, - LLCD_INVALID_STAGE, - LLCD_UNKNOWN_PARAM, - LLCD_BAD_VALUE, - LLCD_REQUEST_OUT_OF_RANGE, - LLCD_INVALID_MESH_DATA, - LLCD_INVALID_HULL_DATA, - LLCD_STAGE_NOT_READY, - LLCD_INVALID_THREAD, - LLCD_NOT_IMPLEMENTED -}; - -// This callback will receive a string describing the current subtask being performed -// as well as a pair of numbers indicating progress. (The values should not be interpreted -// as a completion percentage as 'current' may be greater than 'final'.) -// If the callback returns zero, the decomposition will be terminated -typedef int (LLCD_CALL *llcdCallbackFunc)(const char* description, int current_progress, int final_progress); - -class LLConvexDecomposition -{ -public: - // Obtain a pointer to the actual implementation - static LLConvexDecomposition* getInstance(); - - /// @returns false if this is the stub - static bool isFunctional(); - - static LLCDResult initSystem(); - static LLCDResult initThread(); - static LLCDResult quitThread(); - static LLCDResult quitSystem(); - - // Generate a decomposition object handle - virtual void genDecomposition(int& decomp) = 0; - // Delete decomposition object handle - virtual void deleteDecomposition(int decomp) = 0; - // Bind given decomposition handle - // Commands operate on currently bound decomposition - virtual void bindDecomposition(int decomp) = 0; - - // Sets *paramsOut to the address of the LLCDParam array and returns - // the number of parameters - virtual int getParameters(const LLCDParam** paramsOut) = 0; - - - // Sets *stagesOut to the address of the LLCDStageData array and returns - // the number of stages - virtual int getStages(const LLCDStageData** stagesOut) = 0; - - - // Set a parameter by name. Pass enum values as integers. - virtual LLCDResult setParam(const char* name, float val) = 0; - virtual LLCDResult setParam(const char* name, int val) = 0; - virtual LLCDResult setParam(const char* name, bool val) = 0; - - - // Set incoming mesh data. Data is copied to local buffers and will - // persist until the next setMeshData call - virtual LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based ) = 0; - - - // Register a callback to be called periodically during the specified stage - // See the typedef above for more information - virtual LLCDResult registerCallback( int stage, llcdCallbackFunc callback ) = 0; - - - // Execute the specified decomposition stage - virtual LLCDResult executeStage(int stage) = 0; - virtual LLCDResult buildSingleHull() = 0 ; - - - // Gets the number of hulls generated by the specified decompositions stage - virtual int getNumHullsFromStage(int stage) = 0; - - - // Populates hullOut to reference the internal copy of the requested hull - // The data will persist only until the next executeStage call for that stage. - virtual LLCDResult getHullFromStage( int stage, int hull, LLCDHull* hullOut ) = 0; - - virtual LLCDResult getSingleHull( LLCDHull* hullOut ) = 0 ; - - - // TODO: Implement lock of some kind to disallow this call if data not yet ready - // Populates the meshDataOut to reference the utility's copy of the mesh geometry - // for the hull and stage specified. - // You must copy this data if you want to continue using it after the next executeStage - // call - virtual LLCDResult getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut) = 0; - - - // Creates a mesh from hullIn and temporarily stores it internally in the utility. - // The mesh data persists only until the next call to getMeshFromHull - virtual LLCDResult getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ) = 0; - - // Takes meshIn, generates a single convex hull from it, converts that to a mesh - // stored internally, and populates meshOut to reference the internally stored data. - // The data is persistent only until the next call to generateSingleHullMeshFromMesh - virtual LLCDResult generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut) = 0; - - // - /// Debug - virtual void loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut) = 0; - -private: - static bool s_isInitialized; -}; - -#endif //LL_CONVEX_DECOMPOSITION - diff --git a/indra/llconvexdecomposition/llconvexdecompositionvhacd.cpp b/indra/llconvexdecomposition/llconvexdecompositionvhacd.cpp deleted file mode 100644 index 78876f9f36..0000000000 --- a/indra/llconvexdecomposition/llconvexdecompositionvhacd.cpp +++ /dev/null @@ -1,492 +0,0 @@ -/** -* @file llconvexdecompositionvhacd.cpp -* @author rye@alchemyviewer.org -* @brief A VHACD based implementation of LLConvexDecomposition -* -* $LicenseInfo:firstyear=2025&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2025, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* 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 GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "linden_common.h" - -#include "llmath.h" -#include "v3math.h" - -#include -#include - -#define ENABLE_VHACD_IMPLEMENTATION 1 -#include "VHACD.h" - -#include "llconvexdecompositionvhacd.h" - -constexpr S32 MAX_HULLS = 256; -constexpr S32 MAX_VERTICES_PER_HULL = 256; - -bool LLConvexDecompositionVHACD::isFunctional() -{ - return true; -} - -LLConvexDecomposition* LLConvexDecompositionVHACD::getInstance() -{ - return LLSimpleton::getInstance(); -} - -LLCDResult LLConvexDecompositionVHACD::initSystem() -{ - createInstance(); - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::initThread() -{ - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::quitThread() -{ - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::quitSystem() -{ - deleteSingleton(); - return LLCD_OK; -} - -LLConvexDecompositionVHACD::LLConvexDecompositionVHACD() -{ - //Create our vhacd instance and setup default parameters - mVHACD = VHACD::CreateVHACD(); - - mVHACDParameters.m_callback = &mVHACDCallback; - mVHACDParameters.m_logger = &mVHACDLogger; - - mDecompStages[0].mName = "Analyze"; - mDecompStages[0].mDescription = nullptr; - - LLCDParam param; - param.mName = "Fill Mode"; - param.mDescription = nullptr; - param.mType = LLCDParam::LLCD_ENUM; - param.mDetails.mEnumValues.mNumEnums = 3; - - static LLCDParam::LLCDEnumItem fill_enums[3]; - fill_enums[(size_t)VHACD::FillMode::FLOOD_FILL].mName = "Flood"; - fill_enums[(size_t)VHACD::FillMode::FLOOD_FILL].mValue = (int)VHACD::FillMode::FLOOD_FILL; - fill_enums[(size_t)VHACD::FillMode::SURFACE_ONLY].mName = "Surface Only"; - fill_enums[(size_t)VHACD::FillMode::SURFACE_ONLY].mValue = (int)VHACD::FillMode::SURFACE_ONLY; - fill_enums[(size_t)VHACD::FillMode::RAYCAST_FILL].mName = "Raycast"; - fill_enums[(size_t)VHACD::FillMode::RAYCAST_FILL].mValue = (int)VHACD::FillMode::RAYCAST_FILL; - - param.mDetails.mEnumValues.mEnumsArray = fill_enums; - param.mDefault.mIntOrEnumValue = (int)VHACD::FillMode::FLOOD_FILL; - param.mStage = 0; - param.mReserved = -1; - mDecompParams.push_back(param); - - enum EVoxelQualityLevels - { - E_LOW_QUALITY = 0, - E_NORMAL_QUALITY, - E_HIGH_QUALITY, - E_VERY_HIGH_QUALITY, - E_ULTRA_QUALITY, - E_MAX_QUALITY, - E_NUM_QUALITY_LEVELS - }; - - param.mName = "Voxel Resolution"; - param.mDescription = nullptr; - param.mType = LLCDParam::LLCD_ENUM; - param.mDetails.mEnumValues.mNumEnums = E_NUM_QUALITY_LEVELS; - - static LLCDParam::LLCDEnumItem voxel_quality_enums[E_NUM_QUALITY_LEVELS]; - voxel_quality_enums[E_LOW_QUALITY].mName = "Low"; - voxel_quality_enums[E_LOW_QUALITY].mValue = 200000; - voxel_quality_enums[E_NORMAL_QUALITY].mName = "Normal"; - voxel_quality_enums[E_NORMAL_QUALITY].mValue = 400000; - voxel_quality_enums[E_HIGH_QUALITY].mName = "High"; - voxel_quality_enums[E_HIGH_QUALITY].mValue = 800000; - voxel_quality_enums[E_VERY_HIGH_QUALITY].mName = "Very High"; - voxel_quality_enums[E_VERY_HIGH_QUALITY].mValue = 1200000; - voxel_quality_enums[E_ULTRA_QUALITY].mName = "Ultra"; - voxel_quality_enums[E_ULTRA_QUALITY].mValue = 1600000; - voxel_quality_enums[E_MAX_QUALITY].mName = "Maximum"; - voxel_quality_enums[E_MAX_QUALITY].mValue = 2000000; - - param.mDetails.mEnumValues.mEnumsArray = voxel_quality_enums; - param.mDefault.mIntOrEnumValue = 400000; - param.mStage = 0; - param.mReserved = -1; - mDecompParams.push_back(param); - - param.mName = "Num Hulls"; - param.mDescription = nullptr; - param.mType = LLCDParam::LLCD_FLOAT; - param.mDetails.mRange.mLow.mFloat = 1.f; - param.mDetails.mRange.mHigh.mFloat = MAX_HULLS; - param.mDetails.mRange.mDelta.mFloat = 1.f; - param.mDefault.mFloat = 8.f; - param.mStage = 0; - param.mReserved = -1; - mDecompParams.push_back(param); - - param.mName = "Num Vertices"; - param.mDescription = nullptr; - param.mType = LLCDParam::LLCD_FLOAT; - param.mDetails.mRange.mLow.mFloat = 3.f; - param.mDetails.mRange.mHigh.mFloat = MAX_VERTICES_PER_HULL; - param.mDetails.mRange.mDelta.mFloat = 1.f; - param.mDefault.mFloat = 32.f; - param.mStage = 0; - param.mReserved = -1; - mDecompParams.push_back(param); - - param.mName = "Error Tolerance"; - param.mDescription = nullptr; - param.mType = LLCDParam::LLCD_FLOAT; - param.mDetails.mRange.mLow.mFloat = 0.0001f; - param.mDetails.mRange.mHigh.mFloat = 99.f; - param.mDetails.mRange.mDelta.mFloat = 0.001f; - param.mDefault.mFloat = 1.f; - param.mStage = 0; - param.mReserved = -1; - mDecompParams.push_back(param); - - for (const LLCDParam& param : mDecompParams) - { - const char* const name = param.mName; - - switch (param.mType) - { - case LLCDParam::LLCD_FLOAT: - { - setParam(name, param.mDefault.mFloat); - break; - } - case LLCDParam::LLCD_ENUM: - case LLCDParam::LLCD_INTEGER: - { - setParam(name, param.mDefault.mIntOrEnumValue); - break; - } - case LLCDParam::LLCD_BOOLEAN: - { - setParam(name, (param.mDefault.mBool != 0)); - break; - } - case LLCDParam::LLCD_INVALID: - default: - { - break; - } - } - } -} - -LLConvexDecompositionVHACD::~LLConvexDecompositionVHACD() -{ - mBoundDecomp = nullptr; - mDecompData.clear(); - - mVHACD->Release(); -} - -void LLConvexDecompositionVHACD::genDecomposition(int& decomp) -{ - int new_decomp_id = static_cast(mDecompData.size()) + 1; - mDecompData[new_decomp_id] = LLDecompData(); - decomp = new_decomp_id; -} - -void LLConvexDecompositionVHACD::deleteDecomposition(int decomp) -{ - auto iter = mDecompData.find(decomp); - if (iter != mDecompData.end()) - { - if (mBoundDecomp == &iter->second) - { - mBoundDecomp = nullptr; - } - mDecompData.erase(iter); - } -} - -void LLConvexDecompositionVHACD::bindDecomposition(int decomp) -{ - auto iter = mDecompData.find(decomp); - if (iter != mDecompData.end()) - { - mBoundDecomp = &iter->second; - } - else - { - LL_WARNS() << "Failed to bind unknown decomposition: " << decomp << LL_ENDL; - mBoundDecomp = nullptr; - } -} - -LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, float val) -{ - if (name == std::string("Num Hulls")) - { - mVHACDParameters.m_maxConvexHulls = llclamp(ll_round(val), 1, MAX_HULLS); - } - else if (name == std::string("Num Vertices")) - { - mVHACDParameters.m_maxNumVerticesPerCH = llclamp(ll_round(val), 3, MAX_VERTICES_PER_HULL); - } - else if (name == std::string("Error Tolerance")) - { - mVHACDParameters.m_minimumVolumePercentErrorAllowed = val; - } - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, bool val) -{ - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, int val) -{ - if (name == std::string("Fill Mode")) - { - mVHACDParameters.m_fillMode = (VHACD::FillMode)val; - } - else if (name == std::string("Voxel Resolution")) - { - mVHACDParameters.m_resolution = val; - } - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::setMeshData( const LLCDMeshData* data, bool vertex_based ) -{ - if (!mBoundDecomp) - { - return LLCD_NULL_PTR; - } - - return mBoundDecomp->mSourceMesh.from(data, vertex_based); -} - -LLCDResult LLConvexDecompositionVHACD::registerCallback(int stage, llcdCallbackFunc callback ) -{ - if (stage == 0) - { - mVHACDCallback.setCallbackFunc(callback); - return LLCD_OK; - } - else - { - return LLCD_INVALID_STAGE; - } -} - -LLCDResult LLConvexDecompositionVHACD::executeStage(int stage) -{ - if (!mBoundDecomp) - { - return LLCD_NULL_PTR; - } - - if (stage != 0) - { - return LLCD_INVALID_STAGE; - } - - mBoundDecomp->mDecomposedHulls.clear(); - - const auto& decomp_mesh = mBoundDecomp->mSourceMesh; - if (!mVHACD->Compute((const double* const)decomp_mesh.mVertices.data(), static_cast(decomp_mesh.mVertices.size()), (const uint32_t* const)decomp_mesh.mIndices.data(), static_cast(decomp_mesh.mIndices.size()), mVHACDParameters)) - { - return LLCD_INVALID_HULL_DATA; - } - - uint32_t num_nulls = mVHACD->GetNConvexHulls(); - if (num_nulls == 0) - { - return LLCD_INVALID_HULL_DATA; - } - - for (uint32_t i = 0; num_nulls > i; ++i) - { - VHACD::IVHACD::ConvexHull ch; - if (!mVHACD->GetConvexHull(i, ch)) - continue; - - LLConvexMesh out_mesh; - out_mesh.setVertices(ch.m_points); - out_mesh.setIndices(ch.m_triangles); - - mBoundDecomp->mDecomposedHulls.push_back(std::move(out_mesh)); - } - - mVHACD->Clean(); - - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::buildSingleHull() -{ - LL_INFOS() << "Building single hull mesh" << LL_ENDL; - if (!mBoundDecomp || mBoundDecomp->mSourceMesh.mVertices.empty()) - { - return LLCD_NULL_PTR; - } - - mBoundDecomp->mSingleHullMesh.clear(); - - VHACD::QuickHull quickhull; - uint32_t num_tris = quickhull.ComputeConvexHull(mBoundDecomp->mSourceMesh.mVertices, MAX_VERTICES_PER_HULL); - if (num_tris > 0) - { - mBoundDecomp->mSingleHullMesh.setVertices(quickhull.GetVertices()); - mBoundDecomp->mSingleHullMesh.setIndices(quickhull.GetIndices()); - - return LLCD_OK; - } - - return LLCD_INVALID_MESH_DATA; -} - -int LLConvexDecompositionVHACD::getNumHullsFromStage(int stage) -{ - if (!mBoundDecomp || stage != 0) - { - return 0; - } - - return narrow(mBoundDecomp->mDecomposedHulls.size()); -} - -LLCDResult LLConvexDecompositionVHACD::getSingleHull( LLCDHull* hullOut ) -{ - memset( hullOut, 0, sizeof(LLCDHull) ); - - if (!mBoundDecomp) - { - return LLCD_NULL_PTR; - } - - if (mBoundDecomp->mSingleHullMesh.vertices.empty()) - { - return LLCD_INVALID_HULL_DATA; - } - - mBoundDecomp->mSingleHullMesh.to(hullOut); - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::getHullFromStage( int stage, int hull, LLCDHull* hullOut ) -{ - memset( hullOut, 0, sizeof(LLCDHull) ); - - if (!mBoundDecomp) - { - return LLCD_NULL_PTR; - } - - if (stage != 0) - { - return LLCD_INVALID_STAGE; - } - - if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull) - { - return LLCD_REQUEST_OUT_OF_RANGE; - } - - mBoundDecomp->mDecomposedHulls[hull].to(hullOut); - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut ) -{ - memset( meshDataOut, 0, sizeof(LLCDMeshData)); - if (!mBoundDecomp) - { - return LLCD_NULL_PTR; - } - - if (stage != 0) - { - return LLCD_INVALID_STAGE; - } - - if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull) - { - return LLCD_REQUEST_OUT_OF_RANGE; - } - - mBoundDecomp->mDecomposedHulls[hull].to(meshDataOut); - return LLCD_OK; -} - -LLCDResult LLConvexDecompositionVHACD::getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ) -{ - memset(meshOut, 0, sizeof(LLCDMeshData)); - - LLVHACDMesh inMesh(hullIn); - - VHACD::QuickHull quickhull; - uint32_t num_tris = quickhull.ComputeConvexHull(inMesh.mVertices, MAX_VERTICES_PER_HULL); - if (num_tris > 0) - { - mMeshFromHullData.setVertices(quickhull.GetVertices()); - mMeshFromHullData.setIndices(quickhull.GetIndices()); - - mMeshFromHullData.to(meshOut); - return LLCD_OK; - } - - return LLCD_INVALID_HULL_DATA; -} - -LLCDResult LLConvexDecompositionVHACD::generateSingleHullMeshFromMesh(LLCDMeshData* meshIn, LLCDMeshData* meshOut) -{ - memset( meshOut, 0, sizeof(LLCDMeshData) ); - - LLVHACDMesh inMesh(meshIn, true); - - VHACD::QuickHull quickhull; - uint32_t num_tris = quickhull.ComputeConvexHull(inMesh.mVertices, MAX_VERTICES_PER_HULL); - if (num_tris > 0) - { - mSingleHullMeshFromMeshData.setVertices(quickhull.GetVertices()); - mSingleHullMeshFromMeshData.setIndices(quickhull.GetIndices()); - - mSingleHullMeshFromMeshData.to(meshOut); - return LLCD_OK; - } - - return LLCD_INVALID_MESH_DATA; -} - -void LLConvexDecompositionVHACD::loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut) -{ - static LLCDMeshData meshData; - memset( &meshData, 0, sizeof(LLCDMeshData) ); - *meshDataOut = &meshData; -} diff --git a/indra/llconvexdecomposition/llconvexdecompositionvhacd.h b/indra/llconvexdecomposition/llconvexdecompositionvhacd.h deleted file mode 100644 index 675356629c..0000000000 --- a/indra/llconvexdecomposition/llconvexdecompositionvhacd.h +++ /dev/null @@ -1,339 +0,0 @@ -/** -* @file llconvexdecompositionvhacd.h -* @author rye@alchemyviewer.org -* @brief A VHACD based implementation of LLConvexDecomposition -* -* $LicenseInfo:firstyear=2025&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2025, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* 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 GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#ifndef LL_CONVEX_DECOMP_UTIL_VHACD_H -#define LL_CONVEX_DECOMP_UTIL_VHACD_H - -#include "llconvexdecomposition.h" -#include "llsingleton.h" -#include "llmath.h" - -#include - -#include "VHACD.h" - -class LLDecompDataVHACD; - -class LLConvexDecompositionVHACD : public LLSimpleton, public LLConvexDecomposition -{ - class VHACDCallback : public VHACD::IVHACD::IUserCallback - { - public: - void Update(const double overallProgress, const double stageProgress, const char* const stage, const char* operation) override - { - std::string out_msg = llformat("Stage: %s Operation: %s", stage, operation); - if (mCurrentStage != stage && mCurrentOperation != operation) - { - mCurrentStage = stage; - mCurrentOperation = operation; - LL_INFOS("VHACD") << out_msg << LL_ENDL; - } - - if(mCallbackFunc) - { - mCallbackFunc(out_msg.c_str(), ll_round(static_cast(stageProgress)), ll_round(static_cast(overallProgress))); - } - } - - void setCallbackFunc(llcdCallbackFunc func) - { - mCallbackFunc = func; - } - - private: - std::string mCurrentStage; - std::string mCurrentOperation; - llcdCallbackFunc mCallbackFunc = nullptr; - }; - - class VHACDLogger : public VHACD::IVHACD::IUserLogger - { - void Log(const char* const msg) override - { - LL_INFOS("VHACD") << msg << LL_ENDL; - } - }; - -public: - - LLConvexDecompositionVHACD(); - virtual ~LLConvexDecompositionVHACD(); - - static bool isFunctional(); - static LLConvexDecomposition* getInstance(); - static LLCDResult initSystem(); - static LLCDResult initThread(); - static LLCDResult quitThread(); - static LLCDResult quitSystem(); - - void genDecomposition(int& decomp); - void deleteDecomposition(int decomp); - void bindDecomposition(int decomp); - - // Sets *paramsOut to the address of the LLCDParam array and returns - // the length of the array - int getParameters(const LLCDParam** paramsOut) - { - *paramsOut = mDecompParams.data(); - return narrow(mDecompParams.size()); - } - - int getStages(const LLCDStageData** stagesOut) - { - *stagesOut = mDecompStages.data(); - return narrow(mDecompStages.size()); - } - - // Set a parameter by name. Returns false if out of bounds or unsupported parameter - LLCDResult setParam(const char* name, float val); - LLCDResult setParam(const char* name, int val); - LLCDResult setParam(const char* name, bool val); - LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based ); - LLCDResult registerCallback(int stage, llcdCallbackFunc callback ); - - LLCDResult executeStage(int stage); - LLCDResult buildSingleHull(); - - int getNumHullsFromStage(int stage); - - LLCDResult getHullFromStage( int stage, int hull, LLCDHull* hullOut ); - LLCDResult getSingleHull( LLCDHull* hullOut ) ; - - // TODO: Implement lock of some kind to disallow this call if data not yet ready - LLCDResult getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut); - LLCDResult getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ); - - // For visualizing convex hull shapes in the viewer physics shape display - LLCDResult generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut); - - /// Debug - void loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut); - -private: - std::vector mDecompParams; - std::array mDecompStages; - - struct LLVHACDMesh - { - using vertex_type = VHACD::Vertex; - using index_type = VHACD::Triangle; - using vertex_array_type = std::vector; - using index_array_type = std::vector; - - LLVHACDMesh() = default; - LLVHACDMesh(const LLCDHull* hullIn) - { - if (hullIn) - { - from(hullIn); - } - }; - - LLVHACDMesh(const LLCDMeshData* meshIn, bool vertex_based) - { - if (meshIn) - { - from(meshIn, vertex_based); - } - }; - - void clear() - { - mVertices.clear(); - mIndices.clear(); - } - - void setVertices(const float* data, int num_vertices, int vertex_stride_bytes) - { - vertex_array_type vertices; - vertices.reserve(num_vertices); - - const int stride = vertex_stride_bytes / sizeof(float); - for (int i = 0; i < num_vertices; ++i) - { - vertices.emplace_back(data[i * stride + 0], - data[i * stride + 1], - data[i * stride + 2]); - } - - mVertices = std::move(vertices); - } - - void setIndices(const void* data, int num_indices, int index_stride_bytes, LLCDMeshData::IndexType type) - { - index_array_type indices; - indices.reserve(num_indices); - - if (type == LLCDMeshData::INT_16) - { - const U16* index_data = static_cast(data); - const int stride = index_stride_bytes / sizeof(U16); - for (int i = 0; i < num_indices; ++i) - { - indices.emplace_back(index_data[i * stride + 0], - index_data[i * stride + 1], - index_data[i * stride + 2]); - } - } - else - { - const U32* index_data = static_cast(data); - const int stride = index_stride_bytes / sizeof(U32); - for (int i = 0; i < num_indices; ++i) - { - indices.emplace_back(index_data[i * stride + 0], - index_data[i * stride + 1], - index_data[i * stride + 2]); - } - } - - mIndices = std::move(indices); - } - - LLCDResult from(const LLCDHull* hullIn) - { - clear(); - - if (!hullIn || !hullIn->mVertexBase || (hullIn->mNumVertices < 3) || (hullIn->mVertexStrideBytes != 12 && hullIn->mVertexStrideBytes != 16)) - { - return LLCD_INVALID_HULL_DATA; - } - - setVertices(hullIn->mVertexBase, hullIn->mNumVertices, hullIn->mVertexStrideBytes); - - return LLCD_OK; - } - - LLCDResult from(const LLCDMeshData* meshIn, bool vertex_based) - { - clear(); - - if (!meshIn || !meshIn->mVertexBase || (meshIn->mNumVertices < 3) || (meshIn->mVertexStrideBytes != 12 && meshIn->mVertexStrideBytes != 16)) - { - return LLCD_INVALID_MESH_DATA; - } - - if (!vertex_based && ((meshIn->mNumTriangles < 1) || !meshIn->mIndexBase)) - { - return LLCD_INVALID_MESH_DATA; - } - - setVertices(meshIn->mVertexBase, meshIn->mNumVertices, meshIn->mVertexStrideBytes); - if(!vertex_based) - { - setIndices(meshIn->mIndexBase, meshIn->mNumTriangles, meshIn->mIndexStrideBytes, meshIn->mIndexType); - } - - return LLCD_OK; - } - - vertex_array_type mVertices; - index_array_type mIndices; - }; - - struct LLConvexMesh - { - using vertex_type = glm::vec3; - using index_type = glm::u32vec3; - using vertex_array_type = std::vector; - using index_array_type = std::vector; - - LLConvexMesh() = default; - - void clear() - { - vertices.clear(); - indices.clear(); - } - - void setVertices(const std::vector& in_vertices) - { - vertices.clear(); - vertices.reserve(in_vertices.size()); - - for (const auto& vertex : in_vertices) - { - vertices.emplace_back(narrow(vertex.mX), narrow(vertex.mY), narrow(vertex.mZ)); - } - } - - void setIndices(const std::vector& in_indices) - { - indices.clear(); - indices.reserve(in_indices.size()); - - for (const auto& triangle : in_indices) - { - indices.emplace_back(narrow(triangle.mI0), narrow(triangle.mI1), narrow(triangle.mI2)); - } - } - - void to(LLCDHull* meshOut) const - { - meshOut->mVertexBase = (float*)vertices.data(); - meshOut->mVertexStrideBytes = sizeof(vertex_type); - meshOut->mNumVertices = (int)vertices.size(); - } - - void to(LLCDMeshData* meshOut) const - { - meshOut->mVertexBase = (float*)vertices.data(); - meshOut->mVertexStrideBytes = sizeof(vertex_type); - meshOut->mNumVertices = (int)vertices.size(); - - meshOut->mIndexType = LLCDMeshData::INT_32; - meshOut->mIndexBase = indices.data(); - meshOut->mIndexStrideBytes = sizeof(index_type); - meshOut->mNumTriangles = (int)indices.size(); - } - - vertex_array_type vertices; - index_array_type indices; - }; - - struct LLDecompData - { - LLVHACDMesh mSourceMesh; - LLConvexMesh mSingleHullMesh; - - std::vector mDecomposedHulls; - }; - - std::unordered_map mDecompData; - - LLDecompData* mBoundDecomp = nullptr; - - VHACD::IVHACD* mVHACD = nullptr; - VHACDCallback mVHACDCallback; - VHACDLogger mVHACDLogger; - VHACD::IVHACD::Parameters mVHACDParameters; - - LLConvexMesh mMeshFromHullData; - LLConvexMesh mSingleHullMeshFromMeshData; -}; - -#endif //LL_CONVEX_DECOMP_UTIL_VHACD_H diff --git a/indra/llphysicsextensionsos/CMakeLists.txt b/indra/llphysicsextensionsos/CMakeLists.txt new file mode 100644 index 0000000000..c04115ef26 --- /dev/null +++ b/indra/llphysicsextensionsos/CMakeLists.txt @@ -0,0 +1,47 @@ +# -*- cmake -*- + +project(llphysicsextensionsos) + +include(00-Common) +include(LLCommon) +include(LLMath) +include(VHACD) + +set(llphysicsextensionsos_SOURCE_FILES + llconvexdecomposition.cpp + llconvexdecompositionvhacd.cpp + llpathinglib.cpp + LLPathingLibStubImpl.cpp + llphysicsextensions.cpp + LLPhysicsExtensionsStubImpl.cpp + ) + +set(llphysicsextensionsos_HEADER_FILES + CMakeLists.txt + llconvexdecomposition.h + llconvexdecompositionvhacd.h + llpathinglib.h + LLPathingLibStubImpl.h + llphysicsextensions.h + LLPhysicsExtensionsStubImpl.h + ) + +set_source_files_properties(${llphysicsextensionsos_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llphysicsextensionsos_SOURCE_FILES ${llphysicsextensionsos_HEADER_FILES}) + +add_library (llphysicsextensionsos ${llphysicsextensionsos_SOURCE_FILES}) +target_include_directories(llphysicsextensionsos INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(llphysicsextensionsos + llcommon + llmath + ll::vhacd) + +if(WINDOWS) + target_compile_options(llphysicsextensionsos PRIVATE /bigobj) +endif() + +# Add tests + diff --git a/indra/llphysicsextensionsos/LLPathingLibStubImpl.cpp b/indra/llphysicsextensionsos/LLPathingLibStubImpl.cpp new file mode 100644 index 0000000000..9830fd1ad0 --- /dev/null +++ b/indra/llphysicsextensionsos/LLPathingLibStubImpl.cpp @@ -0,0 +1,109 @@ +/** +* @file LLPathingLibStubImpl.cpp +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPathingLib +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 20112010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llpathinglib.h" +#include "LLPathingLibStubImpl.h" + +#include "llsd.h" + +//============================================================================= +LLPathingLibImpl::LLPathingLibImpl() +{ +} + +LLPathingLibImpl::~LLPathingLibImpl() +{ + +} + +LLPathingLib* LLPathingLibImpl::getInstance() +{ + return NULL; +} + + +LLPathingLib::LLPLResult LLPathingLibImpl::initSystem() +{ + return LLPL_NOT_IMPLEMENTED; +} + +LLPathingLib::LLPLResult LLPathingLibImpl::quitSystem() +{ + return LLPL_NOT_IMPLEMENTED; +} + +LLPathingLib::LLPLResult LLPathingLibImpl::extractNavMeshSrcFromLLSD( const LLSD::Binary& dataBlock, int dir ) +{ + return LLPL_NOT_IMPLEMENTED; +} + +void LLPathingLibImpl::processNavMeshData() +{ +} + +LLPathingLibImpl::LLPLResult LLPathingLibImpl::generatePath( const PathingPacket& pathingPacket ) +{ + return LLPL_NOT_IMPLEMENTED; +} + +void LLPathingLibImpl::setNavMeshMaterialType( LLPLCharacterType materialType ) +{ +} + +void LLPathingLibImpl::setNavMeshColors( const NavMeshColors& color ) +{ +} + +void LLPathingLibImpl::renderNavMesh() +{ +} + +void LLPathingLibImpl::renderNavMeshEdges() +{ +} + +void LLPathingLibImpl::renderNavMeshShapesVBO( U32 shapeRenderFlags ) +{ +} + +void LLPathingLibImpl::renderPath() +{ +} + +void LLPathingLibImpl::renderPathBookend( LLRender& gl, LLPathingLib::LLPLPathBookEnd type ) +{ +} + +void LLPathingLibImpl::cleanupVBOManager() +{ +} + +void LLPathingLibImpl::cleanupResidual() +{ +} diff --git a/indra/llphysicsextensionsos/LLPathingLibStubImpl.h b/indra/llphysicsextensionsos/LLPathingLibStubImpl.h new file mode 100644 index 0000000000..8a97566e8c --- /dev/null +++ b/indra/llphysicsextensionsos/LLPathingLibStubImpl.h @@ -0,0 +1,78 @@ +/** +* @file LLPathingLibSubImpl.h +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPathingLib +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_PATHING_LIB_H +#define LL_PATHING_LIB_H + +#include "llpathinglib.h" + +class LLSD; + +//============================================================================= +class LLPathingLibImpl : public LLPathingLib +{ +public: + LLPathingLibImpl(); + virtual ~LLPathingLibImpl(); + + // Obtain a pointer to the actual implementation + static LLPathingLib* getInstance(); + static LLPathingLib::LLPLResult initSystem(); + static LLPathingLib::LLPLResult quitSystem(); + + //Extract and store navmesh data from the llsd datablock sent down by the server + virtual LLPLResult extractNavMeshSrcFromLLSD( const LLSD::Binary& dataBlock, int dir ); + //Stitch any stored navmeshes together + virtual void processNavMeshData(); + + //Method used to generate and visualize a path on the viewers navmesh + virtual LLPLResult generatePath( const PathingPacket& pathingPacket ); + + //Set the material type for the heatmap type + virtual void setNavMeshMaterialType( LLPLCharacterType materialType ); + //Set the various navmesh colors + virtual void setNavMeshColors( const NavMeshColors& color ); + + //The entry method to rendering the client side navmesh + virtual void renderNavMesh(); + //The entry method to rendering the client side navmesh edges + virtual void renderNavMeshEdges(); + //The entry method to render the client navmesh shapes VBO + virtual void renderNavMeshShapesVBO( U32 shapeRenderFlags ); + //The entry method to render the clients designated path + virtual void renderPath(); + //The entry method to render the capsule bookends for the clients designated path + virtual void renderPathBookend( LLRender& gl, LLPathingLib::LLPLPathBookEnd type ); + + //Method to delete any vbo's that are currently being managed by the pathing library + virtual void cleanupVBOManager(); + //Method to cleanup any allocations within the implementation + virtual void cleanupResidual(); +}; + +#endif //LL_PATHING_LIB_H + diff --git a/indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.cpp b/indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.cpp new file mode 100644 index 0000000000..8401e16e9c --- /dev/null +++ b/indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.cpp @@ -0,0 +1,51 @@ +/** +* @file LLPhysicsExtensionsStubImpl.cpp +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPhysicsExtensions +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llphysicsextensions.h" +#include "LLPhysicsExtensionsStubImpl.h" + +//============================================================================= +LLPhysicsExtensionsImpl::LLPhysicsExtensionsImpl() +{ +} + +LLPhysicsExtensionsImpl::~LLPhysicsExtensionsImpl() +{ +} + +bool LLPhysicsExtensionsImpl::initSystem() +{ + return false; +} + +bool LLPhysicsExtensionsImpl::quitSystem() +{ + return false; +} + diff --git a/indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.h b/indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.h new file mode 100644 index 0000000000..135f92bb88 --- /dev/null +++ b/indra/llphysicsextensionsos/LLPhysicsExtensionsStubImpl.h @@ -0,0 +1,46 @@ +/** +* @file LLPhysicsExtensionsSubImpl.h +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPhysicsExtensions +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_PHYSICS_EXTENSIONS_STUB_IMPL_H +#define LL_PHYSICS_EXTENSIONS_STUB_IMPL_H + +#include "llphysicsextensions.h" + +//============================================================================= +class LLPhysicsExtensionsImpl : public LLPhysicsExtensions +{ + public: + + LLPhysicsExtensionsImpl(); + virtual ~LLPhysicsExtensionsImpl(); + + static bool initSystem(); + static bool quitSystem(); +}; + +#endif //LL_PHYSICS_EXTENSIONS_STUB_IMPL_H + diff --git a/indra/llphysicsextensionsos/llconvexdecomposition.cpp b/indra/llphysicsextensionsos/llconvexdecomposition.cpp new file mode 100644 index 0000000000..7b9d775c53 --- /dev/null +++ b/indra/llphysicsextensionsos/llconvexdecomposition.cpp @@ -0,0 +1,83 @@ +/** +* @file llconvexdecomposition.cpp +* @author falcon@lindenlab.com +* @brief Inner implementation of LLConvexDecomposition interface +* +* $LicenseInfo:firstyear=2011&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llconvexdecompositionvhacd.h" +#include "llconvexdecomposition.h" + +bool LLConvexDecomposition::s_isInitialized = false; + +// static +bool LLConvexDecomposition::isFunctional() +{ + return LLConvexDecompositionVHACD::isFunctional(); +} + +// static +LLConvexDecomposition* LLConvexDecomposition::getInstance() +{ + if ( !s_isInitialized ) + { + return nullptr; + } + else + { + return LLConvexDecompositionVHACD::getInstance(); + } +} + +// static +LLCDResult LLConvexDecomposition::initSystem() +{ + LLCDResult result = LLConvexDecompositionVHACD::initSystem(); + if ( result == LLCD_OK ) + { + s_isInitialized = true; + } + return result; +} + +// static +LLCDResult LLConvexDecomposition::initThread() +{ + return LLConvexDecompositionVHACD::initThread(); +} + +// static +LLCDResult LLConvexDecomposition::quitThread() +{ + return LLConvexDecompositionVHACD::quitThread(); +} + +// static +LLCDResult LLConvexDecomposition::quitSystem() +{ + return LLConvexDecompositionVHACD::quitSystem(); +} + + diff --git a/indra/llphysicsextensionsos/llconvexdecomposition.h b/indra/llphysicsextensionsos/llconvexdecomposition.h new file mode 100644 index 0000000000..8008bc6e12 --- /dev/null +++ b/indra/llphysicsextensionsos/llconvexdecomposition.h @@ -0,0 +1,231 @@ +/** + * @file llconvexdecomposition.cpp + * @brief LLConvexDecomposition interface definition + * + * $LicenseInfo:firstyear=2011&license=lgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * 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 GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_CONVEX_DECOMPOSITION +#define LL_CONVEX_DECOMPOSITION + +typedef int bool32; + +#if defined(_WIN32) || defined(_WIN64) +#define LLCD_CALL __cdecl +#else +#define LLCD_CALL +#endif + +struct LLCDParam +{ + enum LLCDParamType + { + LLCD_INVALID = 0, + LLCD_INTEGER, + LLCD_FLOAT, + LLCD_BOOLEAN, + LLCD_ENUM + }; + + struct LLCDEnumItem + { + const char* mName; + int mValue; + }; + + union LLCDValue + { + float mFloat; + int mIntOrEnumValue; + bool32 mBool; + }; + + union LLCDParamDetails + { + struct { + LLCDValue mLow; + LLCDValue mHigh; + LLCDValue mDelta; + } mRange; + + struct { + int mNumEnums; + LLCDEnumItem* mEnumsArray; + } mEnumValues; + }; + + const char* mName; + const char* mDescription; + LLCDParamType mType; + LLCDParamDetails mDetails; + LLCDValue mDefault; + int mStage; + + // WARNING: Only the LLConvexDecomposition implementation + // should change this value + int mReserved; +}; + +struct LLCDStageData +{ + const char* mName; + const char* mDescription; + bool32 mSupportsCallback; +}; + +struct LLCDMeshData +{ + enum IndexType + { + INT_16, + INT_32 + }; + + const float* mVertexBase; + int mVertexStrideBytes; + int mNumVertices; + const void* mIndexBase; + IndexType mIndexType; + int mIndexStrideBytes; + int mNumTriangles; +}; + +struct LLCDHull +{ + const float* mVertexBase; + int mVertexStrideBytes; + int mNumVertices; +}; + +enum LLCDResult +{ + LLCD_OK = 0, + LLCD_UNKOWN_ERROR, + LLCD_NULL_PTR, + LLCD_INVALID_STAGE, + LLCD_UNKNOWN_PARAM, + LLCD_BAD_VALUE, + LLCD_REQUEST_OUT_OF_RANGE, + LLCD_INVALID_MESH_DATA, + LLCD_INVALID_HULL_DATA, + LLCD_STAGE_NOT_READY, + LLCD_INVALID_THREAD, + LLCD_NOT_IMPLEMENTED +}; + +// This callback will receive a string describing the current subtask being performed +// as well as a pair of numbers indicating progress. (The values should not be interpreted +// as a completion percentage as 'current' may be greater than 'final'.) +// If the callback returns zero, the decomposition will be terminated +typedef int (LLCD_CALL *llcdCallbackFunc)(const char* description, int current_progress, int final_progress); + +class LLConvexDecomposition +{ +public: + // Obtain a pointer to the actual implementation + static LLConvexDecomposition* getInstance(); + + /// @returns false if this is the stub + static bool isFunctional(); + + static LLCDResult initSystem(); + static LLCDResult initThread(); + static LLCDResult quitThread(); + static LLCDResult quitSystem(); + + // Generate a decomposition object handle + virtual void genDecomposition(int& decomp) = 0; + // Delete decomposition object handle + virtual void deleteDecomposition(int decomp) = 0; + // Bind given decomposition handle + // Commands operate on currently bound decomposition + virtual void bindDecomposition(int decomp) = 0; + + // Sets *paramsOut to the address of the LLCDParam array and returns + // the number of parameters + virtual int getParameters(const LLCDParam** paramsOut) = 0; + + + // Sets *stagesOut to the address of the LLCDStageData array and returns + // the number of stages + virtual int getStages(const LLCDStageData** stagesOut) = 0; + + + // Set a parameter by name. Pass enum values as integers. + virtual LLCDResult setParam(const char* name, float val) = 0; + virtual LLCDResult setParam(const char* name, int val) = 0; + virtual LLCDResult setParam(const char* name, bool val) = 0; + + + // Set incoming mesh data. Data is copied to local buffers and will + // persist until the next setMeshData call + virtual LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based ) = 0; + + + // Register a callback to be called periodically during the specified stage + // See the typedef above for more information + virtual LLCDResult registerCallback( int stage, llcdCallbackFunc callback ) = 0; + + + // Execute the specified decomposition stage + virtual LLCDResult executeStage(int stage) = 0; + virtual LLCDResult buildSingleHull() = 0 ; + + + // Gets the number of hulls generated by the specified decompositions stage + virtual int getNumHullsFromStage(int stage) = 0; + + + // Populates hullOut to reference the internal copy of the requested hull + // The data will persist only until the next executeStage call for that stage. + virtual LLCDResult getHullFromStage( int stage, int hull, LLCDHull* hullOut ) = 0; + + virtual LLCDResult getSingleHull( LLCDHull* hullOut ) = 0 ; + + + // TODO: Implement lock of some kind to disallow this call if data not yet ready + // Populates the meshDataOut to reference the utility's copy of the mesh geometry + // for the hull and stage specified. + // You must copy this data if you want to continue using it after the next executeStage + // call + virtual LLCDResult getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut) = 0; + + + // Creates a mesh from hullIn and temporarily stores it internally in the utility. + // The mesh data persists only until the next call to getMeshFromHull + virtual LLCDResult getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ) = 0; + + // Takes meshIn, generates a single convex hull from it, converts that to a mesh + // stored internally, and populates meshOut to reference the internally stored data. + // The data is persistent only until the next call to generateSingleHullMeshFromMesh + virtual LLCDResult generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut) = 0; + + // + /// Debug + virtual void loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut) = 0; + +private: + static bool s_isInitialized; +}; + +#endif //LL_CONVEX_DECOMPOSITION + diff --git a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp new file mode 100644 index 0000000000..78876f9f36 --- /dev/null +++ b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.cpp @@ -0,0 +1,492 @@ +/** +* @file llconvexdecompositionvhacd.cpp +* @author rye@alchemyviewer.org +* @brief A VHACD based implementation of LLConvexDecomposition +* +* $LicenseInfo:firstyear=2025&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2025, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llmath.h" +#include "v3math.h" + +#include +#include + +#define ENABLE_VHACD_IMPLEMENTATION 1 +#include "VHACD.h" + +#include "llconvexdecompositionvhacd.h" + +constexpr S32 MAX_HULLS = 256; +constexpr S32 MAX_VERTICES_PER_HULL = 256; + +bool LLConvexDecompositionVHACD::isFunctional() +{ + return true; +} + +LLConvexDecomposition* LLConvexDecompositionVHACD::getInstance() +{ + return LLSimpleton::getInstance(); +} + +LLCDResult LLConvexDecompositionVHACD::initSystem() +{ + createInstance(); + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::initThread() +{ + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::quitThread() +{ + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::quitSystem() +{ + deleteSingleton(); + return LLCD_OK; +} + +LLConvexDecompositionVHACD::LLConvexDecompositionVHACD() +{ + //Create our vhacd instance and setup default parameters + mVHACD = VHACD::CreateVHACD(); + + mVHACDParameters.m_callback = &mVHACDCallback; + mVHACDParameters.m_logger = &mVHACDLogger; + + mDecompStages[0].mName = "Analyze"; + mDecompStages[0].mDescription = nullptr; + + LLCDParam param; + param.mName = "Fill Mode"; + param.mDescription = nullptr; + param.mType = LLCDParam::LLCD_ENUM; + param.mDetails.mEnumValues.mNumEnums = 3; + + static LLCDParam::LLCDEnumItem fill_enums[3]; + fill_enums[(size_t)VHACD::FillMode::FLOOD_FILL].mName = "Flood"; + fill_enums[(size_t)VHACD::FillMode::FLOOD_FILL].mValue = (int)VHACD::FillMode::FLOOD_FILL; + fill_enums[(size_t)VHACD::FillMode::SURFACE_ONLY].mName = "Surface Only"; + fill_enums[(size_t)VHACD::FillMode::SURFACE_ONLY].mValue = (int)VHACD::FillMode::SURFACE_ONLY; + fill_enums[(size_t)VHACD::FillMode::RAYCAST_FILL].mName = "Raycast"; + fill_enums[(size_t)VHACD::FillMode::RAYCAST_FILL].mValue = (int)VHACD::FillMode::RAYCAST_FILL; + + param.mDetails.mEnumValues.mEnumsArray = fill_enums; + param.mDefault.mIntOrEnumValue = (int)VHACD::FillMode::FLOOD_FILL; + param.mStage = 0; + param.mReserved = -1; + mDecompParams.push_back(param); + + enum EVoxelQualityLevels + { + E_LOW_QUALITY = 0, + E_NORMAL_QUALITY, + E_HIGH_QUALITY, + E_VERY_HIGH_QUALITY, + E_ULTRA_QUALITY, + E_MAX_QUALITY, + E_NUM_QUALITY_LEVELS + }; + + param.mName = "Voxel Resolution"; + param.mDescription = nullptr; + param.mType = LLCDParam::LLCD_ENUM; + param.mDetails.mEnumValues.mNumEnums = E_NUM_QUALITY_LEVELS; + + static LLCDParam::LLCDEnumItem voxel_quality_enums[E_NUM_QUALITY_LEVELS]; + voxel_quality_enums[E_LOW_QUALITY].mName = "Low"; + voxel_quality_enums[E_LOW_QUALITY].mValue = 200000; + voxel_quality_enums[E_NORMAL_QUALITY].mName = "Normal"; + voxel_quality_enums[E_NORMAL_QUALITY].mValue = 400000; + voxel_quality_enums[E_HIGH_QUALITY].mName = "High"; + voxel_quality_enums[E_HIGH_QUALITY].mValue = 800000; + voxel_quality_enums[E_VERY_HIGH_QUALITY].mName = "Very High"; + voxel_quality_enums[E_VERY_HIGH_QUALITY].mValue = 1200000; + voxel_quality_enums[E_ULTRA_QUALITY].mName = "Ultra"; + voxel_quality_enums[E_ULTRA_QUALITY].mValue = 1600000; + voxel_quality_enums[E_MAX_QUALITY].mName = "Maximum"; + voxel_quality_enums[E_MAX_QUALITY].mValue = 2000000; + + param.mDetails.mEnumValues.mEnumsArray = voxel_quality_enums; + param.mDefault.mIntOrEnumValue = 400000; + param.mStage = 0; + param.mReserved = -1; + mDecompParams.push_back(param); + + param.mName = "Num Hulls"; + param.mDescription = nullptr; + param.mType = LLCDParam::LLCD_FLOAT; + param.mDetails.mRange.mLow.mFloat = 1.f; + param.mDetails.mRange.mHigh.mFloat = MAX_HULLS; + param.mDetails.mRange.mDelta.mFloat = 1.f; + param.mDefault.mFloat = 8.f; + param.mStage = 0; + param.mReserved = -1; + mDecompParams.push_back(param); + + param.mName = "Num Vertices"; + param.mDescription = nullptr; + param.mType = LLCDParam::LLCD_FLOAT; + param.mDetails.mRange.mLow.mFloat = 3.f; + param.mDetails.mRange.mHigh.mFloat = MAX_VERTICES_PER_HULL; + param.mDetails.mRange.mDelta.mFloat = 1.f; + param.mDefault.mFloat = 32.f; + param.mStage = 0; + param.mReserved = -1; + mDecompParams.push_back(param); + + param.mName = "Error Tolerance"; + param.mDescription = nullptr; + param.mType = LLCDParam::LLCD_FLOAT; + param.mDetails.mRange.mLow.mFloat = 0.0001f; + param.mDetails.mRange.mHigh.mFloat = 99.f; + param.mDetails.mRange.mDelta.mFloat = 0.001f; + param.mDefault.mFloat = 1.f; + param.mStage = 0; + param.mReserved = -1; + mDecompParams.push_back(param); + + for (const LLCDParam& param : mDecompParams) + { + const char* const name = param.mName; + + switch (param.mType) + { + case LLCDParam::LLCD_FLOAT: + { + setParam(name, param.mDefault.mFloat); + break; + } + case LLCDParam::LLCD_ENUM: + case LLCDParam::LLCD_INTEGER: + { + setParam(name, param.mDefault.mIntOrEnumValue); + break; + } + case LLCDParam::LLCD_BOOLEAN: + { + setParam(name, (param.mDefault.mBool != 0)); + break; + } + case LLCDParam::LLCD_INVALID: + default: + { + break; + } + } + } +} + +LLConvexDecompositionVHACD::~LLConvexDecompositionVHACD() +{ + mBoundDecomp = nullptr; + mDecompData.clear(); + + mVHACD->Release(); +} + +void LLConvexDecompositionVHACD::genDecomposition(int& decomp) +{ + int new_decomp_id = static_cast(mDecompData.size()) + 1; + mDecompData[new_decomp_id] = LLDecompData(); + decomp = new_decomp_id; +} + +void LLConvexDecompositionVHACD::deleteDecomposition(int decomp) +{ + auto iter = mDecompData.find(decomp); + if (iter != mDecompData.end()) + { + if (mBoundDecomp == &iter->second) + { + mBoundDecomp = nullptr; + } + mDecompData.erase(iter); + } +} + +void LLConvexDecompositionVHACD::bindDecomposition(int decomp) +{ + auto iter = mDecompData.find(decomp); + if (iter != mDecompData.end()) + { + mBoundDecomp = &iter->second; + } + else + { + LL_WARNS() << "Failed to bind unknown decomposition: " << decomp << LL_ENDL; + mBoundDecomp = nullptr; + } +} + +LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, float val) +{ + if (name == std::string("Num Hulls")) + { + mVHACDParameters.m_maxConvexHulls = llclamp(ll_round(val), 1, MAX_HULLS); + } + else if (name == std::string("Num Vertices")) + { + mVHACDParameters.m_maxNumVerticesPerCH = llclamp(ll_round(val), 3, MAX_VERTICES_PER_HULL); + } + else if (name == std::string("Error Tolerance")) + { + mVHACDParameters.m_minimumVolumePercentErrorAllowed = val; + } + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, bool val) +{ + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::setParam(const char* name, int val) +{ + if (name == std::string("Fill Mode")) + { + mVHACDParameters.m_fillMode = (VHACD::FillMode)val; + } + else if (name == std::string("Voxel Resolution")) + { + mVHACDParameters.m_resolution = val; + } + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::setMeshData( const LLCDMeshData* data, bool vertex_based ) +{ + if (!mBoundDecomp) + { + return LLCD_NULL_PTR; + } + + return mBoundDecomp->mSourceMesh.from(data, vertex_based); +} + +LLCDResult LLConvexDecompositionVHACD::registerCallback(int stage, llcdCallbackFunc callback ) +{ + if (stage == 0) + { + mVHACDCallback.setCallbackFunc(callback); + return LLCD_OK; + } + else + { + return LLCD_INVALID_STAGE; + } +} + +LLCDResult LLConvexDecompositionVHACD::executeStage(int stage) +{ + if (!mBoundDecomp) + { + return LLCD_NULL_PTR; + } + + if (stage != 0) + { + return LLCD_INVALID_STAGE; + } + + mBoundDecomp->mDecomposedHulls.clear(); + + const auto& decomp_mesh = mBoundDecomp->mSourceMesh; + if (!mVHACD->Compute((const double* const)decomp_mesh.mVertices.data(), static_cast(decomp_mesh.mVertices.size()), (const uint32_t* const)decomp_mesh.mIndices.data(), static_cast(decomp_mesh.mIndices.size()), mVHACDParameters)) + { + return LLCD_INVALID_HULL_DATA; + } + + uint32_t num_nulls = mVHACD->GetNConvexHulls(); + if (num_nulls == 0) + { + return LLCD_INVALID_HULL_DATA; + } + + for (uint32_t i = 0; num_nulls > i; ++i) + { + VHACD::IVHACD::ConvexHull ch; + if (!mVHACD->GetConvexHull(i, ch)) + continue; + + LLConvexMesh out_mesh; + out_mesh.setVertices(ch.m_points); + out_mesh.setIndices(ch.m_triangles); + + mBoundDecomp->mDecomposedHulls.push_back(std::move(out_mesh)); + } + + mVHACD->Clean(); + + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::buildSingleHull() +{ + LL_INFOS() << "Building single hull mesh" << LL_ENDL; + if (!mBoundDecomp || mBoundDecomp->mSourceMesh.mVertices.empty()) + { + return LLCD_NULL_PTR; + } + + mBoundDecomp->mSingleHullMesh.clear(); + + VHACD::QuickHull quickhull; + uint32_t num_tris = quickhull.ComputeConvexHull(mBoundDecomp->mSourceMesh.mVertices, MAX_VERTICES_PER_HULL); + if (num_tris > 0) + { + mBoundDecomp->mSingleHullMesh.setVertices(quickhull.GetVertices()); + mBoundDecomp->mSingleHullMesh.setIndices(quickhull.GetIndices()); + + return LLCD_OK; + } + + return LLCD_INVALID_MESH_DATA; +} + +int LLConvexDecompositionVHACD::getNumHullsFromStage(int stage) +{ + if (!mBoundDecomp || stage != 0) + { + return 0; + } + + return narrow(mBoundDecomp->mDecomposedHulls.size()); +} + +LLCDResult LLConvexDecompositionVHACD::getSingleHull( LLCDHull* hullOut ) +{ + memset( hullOut, 0, sizeof(LLCDHull) ); + + if (!mBoundDecomp) + { + return LLCD_NULL_PTR; + } + + if (mBoundDecomp->mSingleHullMesh.vertices.empty()) + { + return LLCD_INVALID_HULL_DATA; + } + + mBoundDecomp->mSingleHullMesh.to(hullOut); + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::getHullFromStage( int stage, int hull, LLCDHull* hullOut ) +{ + memset( hullOut, 0, sizeof(LLCDHull) ); + + if (!mBoundDecomp) + { + return LLCD_NULL_PTR; + } + + if (stage != 0) + { + return LLCD_INVALID_STAGE; + } + + if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull) + { + return LLCD_REQUEST_OUT_OF_RANGE; + } + + mBoundDecomp->mDecomposedHulls[hull].to(hullOut); + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut ) +{ + memset( meshDataOut, 0, sizeof(LLCDMeshData)); + if (!mBoundDecomp) + { + return LLCD_NULL_PTR; + } + + if (stage != 0) + { + return LLCD_INVALID_STAGE; + } + + if (mBoundDecomp->mDecomposedHulls.empty() || mBoundDecomp->mDecomposedHulls.size() <= hull) + { + return LLCD_REQUEST_OUT_OF_RANGE; + } + + mBoundDecomp->mDecomposedHulls[hull].to(meshDataOut); + return LLCD_OK; +} + +LLCDResult LLConvexDecompositionVHACD::getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ) +{ + memset(meshOut, 0, sizeof(LLCDMeshData)); + + LLVHACDMesh inMesh(hullIn); + + VHACD::QuickHull quickhull; + uint32_t num_tris = quickhull.ComputeConvexHull(inMesh.mVertices, MAX_VERTICES_PER_HULL); + if (num_tris > 0) + { + mMeshFromHullData.setVertices(quickhull.GetVertices()); + mMeshFromHullData.setIndices(quickhull.GetIndices()); + + mMeshFromHullData.to(meshOut); + return LLCD_OK; + } + + return LLCD_INVALID_HULL_DATA; +} + +LLCDResult LLConvexDecompositionVHACD::generateSingleHullMeshFromMesh(LLCDMeshData* meshIn, LLCDMeshData* meshOut) +{ + memset( meshOut, 0, sizeof(LLCDMeshData) ); + + LLVHACDMesh inMesh(meshIn, true); + + VHACD::QuickHull quickhull; + uint32_t num_tris = quickhull.ComputeConvexHull(inMesh.mVertices, MAX_VERTICES_PER_HULL); + if (num_tris > 0) + { + mSingleHullMeshFromMeshData.setVertices(quickhull.GetVertices()); + mSingleHullMeshFromMeshData.setIndices(quickhull.GetIndices()); + + mSingleHullMeshFromMeshData.to(meshOut); + return LLCD_OK; + } + + return LLCD_INVALID_MESH_DATA; +} + +void LLConvexDecompositionVHACD::loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut) +{ + static LLCDMeshData meshData; + memset( &meshData, 0, sizeof(LLCDMeshData) ); + *meshDataOut = &meshData; +} diff --git a/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h new file mode 100644 index 0000000000..675356629c --- /dev/null +++ b/indra/llphysicsextensionsos/llconvexdecompositionvhacd.h @@ -0,0 +1,339 @@ +/** +* @file llconvexdecompositionvhacd.h +* @author rye@alchemyviewer.org +* @brief A VHACD based implementation of LLConvexDecomposition +* +* $LicenseInfo:firstyear=2025&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2025, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_CONVEX_DECOMP_UTIL_VHACD_H +#define LL_CONVEX_DECOMP_UTIL_VHACD_H + +#include "llconvexdecomposition.h" +#include "llsingleton.h" +#include "llmath.h" + +#include + +#include "VHACD.h" + +class LLDecompDataVHACD; + +class LLConvexDecompositionVHACD : public LLSimpleton, public LLConvexDecomposition +{ + class VHACDCallback : public VHACD::IVHACD::IUserCallback + { + public: + void Update(const double overallProgress, const double stageProgress, const char* const stage, const char* operation) override + { + std::string out_msg = llformat("Stage: %s Operation: %s", stage, operation); + if (mCurrentStage != stage && mCurrentOperation != operation) + { + mCurrentStage = stage; + mCurrentOperation = operation; + LL_INFOS("VHACD") << out_msg << LL_ENDL; + } + + if(mCallbackFunc) + { + mCallbackFunc(out_msg.c_str(), ll_round(static_cast(stageProgress)), ll_round(static_cast(overallProgress))); + } + } + + void setCallbackFunc(llcdCallbackFunc func) + { + mCallbackFunc = func; + } + + private: + std::string mCurrentStage; + std::string mCurrentOperation; + llcdCallbackFunc mCallbackFunc = nullptr; + }; + + class VHACDLogger : public VHACD::IVHACD::IUserLogger + { + void Log(const char* const msg) override + { + LL_INFOS("VHACD") << msg << LL_ENDL; + } + }; + +public: + + LLConvexDecompositionVHACD(); + virtual ~LLConvexDecompositionVHACD(); + + static bool isFunctional(); + static LLConvexDecomposition* getInstance(); + static LLCDResult initSystem(); + static LLCDResult initThread(); + static LLCDResult quitThread(); + static LLCDResult quitSystem(); + + void genDecomposition(int& decomp); + void deleteDecomposition(int decomp); + void bindDecomposition(int decomp); + + // Sets *paramsOut to the address of the LLCDParam array and returns + // the length of the array + int getParameters(const LLCDParam** paramsOut) + { + *paramsOut = mDecompParams.data(); + return narrow(mDecompParams.size()); + } + + int getStages(const LLCDStageData** stagesOut) + { + *stagesOut = mDecompStages.data(); + return narrow(mDecompStages.size()); + } + + // Set a parameter by name. Returns false if out of bounds or unsupported parameter + LLCDResult setParam(const char* name, float val); + LLCDResult setParam(const char* name, int val); + LLCDResult setParam(const char* name, bool val); + LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based ); + LLCDResult registerCallback(int stage, llcdCallbackFunc callback ); + + LLCDResult executeStage(int stage); + LLCDResult buildSingleHull(); + + int getNumHullsFromStage(int stage); + + LLCDResult getHullFromStage( int stage, int hull, LLCDHull* hullOut ); + LLCDResult getSingleHull( LLCDHull* hullOut ) ; + + // TODO: Implement lock of some kind to disallow this call if data not yet ready + LLCDResult getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut); + LLCDResult getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ); + + // For visualizing convex hull shapes in the viewer physics shape display + LLCDResult generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut); + + /// Debug + void loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut); + +private: + std::vector mDecompParams; + std::array mDecompStages; + + struct LLVHACDMesh + { + using vertex_type = VHACD::Vertex; + using index_type = VHACD::Triangle; + using vertex_array_type = std::vector; + using index_array_type = std::vector; + + LLVHACDMesh() = default; + LLVHACDMesh(const LLCDHull* hullIn) + { + if (hullIn) + { + from(hullIn); + } + }; + + LLVHACDMesh(const LLCDMeshData* meshIn, bool vertex_based) + { + if (meshIn) + { + from(meshIn, vertex_based); + } + }; + + void clear() + { + mVertices.clear(); + mIndices.clear(); + } + + void setVertices(const float* data, int num_vertices, int vertex_stride_bytes) + { + vertex_array_type vertices; + vertices.reserve(num_vertices); + + const int stride = vertex_stride_bytes / sizeof(float); + for (int i = 0; i < num_vertices; ++i) + { + vertices.emplace_back(data[i * stride + 0], + data[i * stride + 1], + data[i * stride + 2]); + } + + mVertices = std::move(vertices); + } + + void setIndices(const void* data, int num_indices, int index_stride_bytes, LLCDMeshData::IndexType type) + { + index_array_type indices; + indices.reserve(num_indices); + + if (type == LLCDMeshData::INT_16) + { + const U16* index_data = static_cast(data); + const int stride = index_stride_bytes / sizeof(U16); + for (int i = 0; i < num_indices; ++i) + { + indices.emplace_back(index_data[i * stride + 0], + index_data[i * stride + 1], + index_data[i * stride + 2]); + } + } + else + { + const U32* index_data = static_cast(data); + const int stride = index_stride_bytes / sizeof(U32); + for (int i = 0; i < num_indices; ++i) + { + indices.emplace_back(index_data[i * stride + 0], + index_data[i * stride + 1], + index_data[i * stride + 2]); + } + } + + mIndices = std::move(indices); + } + + LLCDResult from(const LLCDHull* hullIn) + { + clear(); + + if (!hullIn || !hullIn->mVertexBase || (hullIn->mNumVertices < 3) || (hullIn->mVertexStrideBytes != 12 && hullIn->mVertexStrideBytes != 16)) + { + return LLCD_INVALID_HULL_DATA; + } + + setVertices(hullIn->mVertexBase, hullIn->mNumVertices, hullIn->mVertexStrideBytes); + + return LLCD_OK; + } + + LLCDResult from(const LLCDMeshData* meshIn, bool vertex_based) + { + clear(); + + if (!meshIn || !meshIn->mVertexBase || (meshIn->mNumVertices < 3) || (meshIn->mVertexStrideBytes != 12 && meshIn->mVertexStrideBytes != 16)) + { + return LLCD_INVALID_MESH_DATA; + } + + if (!vertex_based && ((meshIn->mNumTriangles < 1) || !meshIn->mIndexBase)) + { + return LLCD_INVALID_MESH_DATA; + } + + setVertices(meshIn->mVertexBase, meshIn->mNumVertices, meshIn->mVertexStrideBytes); + if(!vertex_based) + { + setIndices(meshIn->mIndexBase, meshIn->mNumTriangles, meshIn->mIndexStrideBytes, meshIn->mIndexType); + } + + return LLCD_OK; + } + + vertex_array_type mVertices; + index_array_type mIndices; + }; + + struct LLConvexMesh + { + using vertex_type = glm::vec3; + using index_type = glm::u32vec3; + using vertex_array_type = std::vector; + using index_array_type = std::vector; + + LLConvexMesh() = default; + + void clear() + { + vertices.clear(); + indices.clear(); + } + + void setVertices(const std::vector& in_vertices) + { + vertices.clear(); + vertices.reserve(in_vertices.size()); + + for (const auto& vertex : in_vertices) + { + vertices.emplace_back(narrow(vertex.mX), narrow(vertex.mY), narrow(vertex.mZ)); + } + } + + void setIndices(const std::vector& in_indices) + { + indices.clear(); + indices.reserve(in_indices.size()); + + for (const auto& triangle : in_indices) + { + indices.emplace_back(narrow(triangle.mI0), narrow(triangle.mI1), narrow(triangle.mI2)); + } + } + + void to(LLCDHull* meshOut) const + { + meshOut->mVertexBase = (float*)vertices.data(); + meshOut->mVertexStrideBytes = sizeof(vertex_type); + meshOut->mNumVertices = (int)vertices.size(); + } + + void to(LLCDMeshData* meshOut) const + { + meshOut->mVertexBase = (float*)vertices.data(); + meshOut->mVertexStrideBytes = sizeof(vertex_type); + meshOut->mNumVertices = (int)vertices.size(); + + meshOut->mIndexType = LLCDMeshData::INT_32; + meshOut->mIndexBase = indices.data(); + meshOut->mIndexStrideBytes = sizeof(index_type); + meshOut->mNumTriangles = (int)indices.size(); + } + + vertex_array_type vertices; + index_array_type indices; + }; + + struct LLDecompData + { + LLVHACDMesh mSourceMesh; + LLConvexMesh mSingleHullMesh; + + std::vector mDecomposedHulls; + }; + + std::unordered_map mDecompData; + + LLDecompData* mBoundDecomp = nullptr; + + VHACD::IVHACD* mVHACD = nullptr; + VHACDCallback mVHACDCallback; + VHACDLogger mVHACDLogger; + VHACD::IVHACD::Parameters mVHACDParameters; + + LLConvexMesh mMeshFromHullData; + LLConvexMesh mSingleHullMeshFromMeshData; +}; + +#endif //LL_CONVEX_DECOMP_UTIL_VHACD_H diff --git a/indra/llphysicsextensionsos/llpathinglib.cpp b/indra/llphysicsextensionsos/llpathinglib.cpp new file mode 100644 index 0000000000..f41cb9c45f --- /dev/null +++ b/indra/llphysicsextensionsos/llpathinglib.cpp @@ -0,0 +1,83 @@ +/** +* @file llpathinglib.cpp +* @author prep@lindenlab.com +* @brief LLPathingLib core creation methods +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "LLPathingLibStubImpl.h" + +#include "llpathinglib.h" + +//============================================================================= + +/*static */bool LLPathingLib::s_isInitialized = false; + +//============================================================================= + + +/*static*/bool LLPathingLib::isFunctional() +{ + return false; +} + +/*static*/LLPathingLib* LLPathingLib::getInstance() +{ + if ( !s_isInitialized ) + { + return NULL; + } + else + { + return LLPathingLibImpl::getInstance(); + } +} + +//============================================================================= + +/*static */LLPathingLib::LLPLResult LLPathingLib::initSystem() +{ + if ( LLPathingLibImpl::initSystem() == LLPL_OK ) + { + s_isInitialized = true; + return LLPL_OK; + } + return LLPL_UNKOWN_ERROR; +} +//============================================================================= +/*static */LLPathingLib::LLPLResult LLPathingLib::quitSystem() +{ + LLPLResult quitResult = LLPL_UNKOWN_ERROR; + + if (s_isInitialized) + { + quitResult = LLPathingLibImpl::quitSystem(); + s_isInitialized = false; + } + + return quitResult; +} +//============================================================================= + diff --git a/indra/llphysicsextensionsos/llpathinglib.h b/indra/llphysicsextensionsos/llpathinglib.h new file mode 100644 index 0000000000..41583f1fd1 --- /dev/null +++ b/indra/llphysicsextensionsos/llpathinglib.h @@ -0,0 +1,187 @@ +/** + * @file llpathinglib.cpp + * @author prep@lindenlab.com + * @brief LLPathingLib interface definition + * + * $LicenseInfo:firstyear=2012&license=lgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * 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 GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_PATHING_LIBRARY +#define LL_PATHING_LIBRARY + +#include "llpreprocessor.h" +#include "llsd.h" +#include "v3dmath.h" +#include "v4math.h" + +#include "v4color.h" +#include "v4coloru.h" +#include "llphysicsextensions.h" + +typedef int bool32; + +#if defined(_WIN32) || defined(_WIN64) +#define LLCD_CALL __cdecl +#else +#define LLCD_CALL +#endif + +class LLRender; + +//============================================================================= +class LLPathingLib +{ + +public: + enum LLShapeType + { + LLST_WalkableObjects = 0, + LLST_ObstacleObjects, + LLST_MaterialPhantoms, + LLST_ExclusionPhantoms, + LLST_MaxShapeTypes = LLST_ExclusionPhantoms+1, + LLST_None = LLST_MaxShapeTypes+2, + LLST_SimpleBox = LLST_None+1, + LLST_SimpleCapsule = LLST_SimpleBox+1, + }; + + enum LLShapeTypeFlag + { + LLSTB_WalkableObjects = 0x1 << 1, + LLSTB_ObstacleObjects = 0x1 << 2, + LLSTB_MaterialPhantoms = 0x1 << 3, + LLSTB_ExclusionPhantoms = 0x1 << 4, + LLSTB_None = 0x1 << 5 + }; + + enum LLPLPathBookEnd + { + LLPL_START = 0, + LLPL_END, + }; + + enum LLPLResult + { + LLPL_OK = 0, + LLPL_NOTSET, + LLPL_ERROR, + LLPL_NO_NAVMESH, + LLPL_UNKOWN_ERROR, + LLPL_NO_PATH, + LLPL_PATH_GENERATED_OK, + LLPL_NOT_IMPLEMENTED, + }; + + enum LLPLCharacterType + { + LLPL_CHARACTER_TYPE_A = 4, + LLPL_CHARACTER_TYPE_B = 3, + LLPL_CHARACTER_TYPE_C = 2, + LLPL_CHARACTER_TYPE_D = 1, + LLPL_CHARACTER_TYPE_NONE = 0 + }; + + struct PathingPacket + { + PathingPacket() : mHasPointA(false), mHasPointB(false), mCharacterWidth(0.0f), mCharacterType(LLPL_CHARACTER_TYPE_NONE) {} + bool mHasPointA; + LLVector3 mStartPointA; + LLVector3 mEndPointA; + bool mHasPointB; + LLVector3 mStartPointB; + LLVector3 mEndPointB; + F32 mCharacterWidth; + LLPLCharacterType mCharacterType; + }; + + struct NavMeshColors + { + LLColor4U mWalkable; + LLColor4U mObstacle; + LLColor4U mMaterial; + LLColor4U mExclusion; + LLColor4U mConnectedEdge; + LLColor4U mBoundaryEdge; + LLColor4 mHeatColorBase; + LLColor4 mHeatColorMax; + LLColor4U mFaceColor; + LLColor4U mStarValid; + LLColor4U mStarInvalid; + LLColor4U mTestPath; + LLColor4U mWaterColor; + }; + +public: + //Ctor + LLPathingLib() {} + virtual ~LLPathingLib() {} + + /// @returns false if this is the stub + static bool isFunctional(); + + // Obtain a pointer to the actual implementation + static LLPathingLib* getInstance(); + static LLPathingLib::LLPLResult initSystem(); + static LLPathingLib::LLPLResult quitSystem(); + + //Extract and store navmesh data from the llsd datablock sent down by the server + virtual LLPLResult extractNavMeshSrcFromLLSD( const LLSD::Binary& dataBlock, int dir ) = 0; + //Stitch any stored navmeshes together + virtual void processNavMeshData( ) = 0; + + //Method used to generate and visualize a path on the viewers navmesh + virtual LLPLResult generatePath( const PathingPacket& pathingPacket ) = 0; + + //Set the material type for the heatmap type + virtual void setNavMeshMaterialType( LLPLCharacterType materialType ) = 0; + //Set the various navmesh colors + virtual void setNavMeshColors( const NavMeshColors& color ) = 0; + + //The entry method to rendering the client side navmesh + virtual void renderNavMesh() = 0; + //The entry method to rendering the client side navmesh edges + virtual void renderNavMeshEdges() = 0; + //The entry method to render the client navmesh shapes VBO + virtual void renderNavMeshShapesVBO( U32 shapeRenderFlags ) = 0; + //The entry method to render the clients designated path + virtual void renderPath() = 0; + //The entry method to render the capsule bookends for the clients designated path + virtual void renderPathBookend( LLRender& gl, LLPathingLib::LLPLPathBookEnd type ) = 0; + //Renders all of the generated simple shapes (using their default transforms) + virtual void renderSimpleShapes( LLRender& gl, F32 regionsWaterHeight ) = 0; + + //Method called from second life to create a capsule from properties of a character + virtual void createPhysicsCapsuleRep( F32 length, F32 radius, BOOL horizontal, const LLUUID& id ) = 0; + //Removes any cached physics capsule using a list of cached uuids + virtual void cleanupPhysicsCapsuleRepResiduals() = 0; + //Renders a selected uuids physics rep + virtual void renderSimpleShapeCapsuleID( LLRender& gl, const LLUUID& id, const LLVector3& pos, const LLQuaternion& rot ) = 0; + + //Method to delete any vbo's that are currently being managed by the pathing library + virtual void cleanupVBOManager( ) = 0; + //Method to cleanup any allocations within the implementation + virtual void cleanupResidual( ) = 0; +private: + static bool s_isInitialized; +}; + +#endif //LL_PATHING_LIBRARY diff --git a/indra/llphysicsextensionsos/llphysicsextensions.cpp b/indra/llphysicsextensionsos/llphysicsextensions.cpp new file mode 100644 index 0000000000..3bb8ffbf1a --- /dev/null +++ b/indra/llphysicsextensionsos/llphysicsextensions.cpp @@ -0,0 +1,78 @@ +/** +* @file llphysicsextensions.cpp +* @author nyx@lindenlab.com +* @brief LLPhysicsExtensions core initialization methods +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "llphysicsextensions.h" +#include "LLPhysicsExtensionsStubImpl.h" + + +//disable the undefined symbol optimization +//#pragma warning (disable : 4221) + +//============================================================================= + +/*static */bool LLPhysicsExtensions::s_isInitialized = false; + + +/*static*/bool LLPhysicsExtensions::isFunctional() +{ + return false; +} + +//============================================================================= + +/*static*/LLPhysicsExtensions* LLPhysicsExtensions::getInstance() +{ + if ( !s_isInitialized ) + { + return NULL; + } + else + { + return LLPhysicsExtensionsImpl::getInstance(); + } +} + +//============================================================================= + +/*static */bool LLPhysicsExtensions::initSystem() +{ + bool result = LLPhysicsExtensionsImpl::initSystem(); + if ( result ) + { + s_isInitialized = true; + } + return result; +} +//============================================================================= +/*static */bool LLPhysicsExtensions::quitSystem() +{ + return LLPhysicsExtensionsImpl::quitSystem(); +} +//============================================================================= + diff --git a/indra/llphysicsextensionsos/llphysicsextensions.h b/indra/llphysicsextensionsos/llphysicsextensions.h new file mode 100644 index 0000000000..fa23ebd725 --- /dev/null +++ b/indra/llphysicsextensionsos/llphysicsextensions.h @@ -0,0 +1,59 @@ +/** +* @file llphysicsextensions.h +* @author nyx@lindenlab.com +* @brief LLPhysicsExtensions core shared initialization +* routines +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* 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 GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_PHYSICS_EXTENSIONS +#define LL_PHYSICS_EXTENSIONS + +#include "llpreprocessor.h" +#include "llsd.h" +#include "v3dmath.h" + +#define LLPHYSICSEXTENSIONS_VERSION "1.0" + +typedef int bool32; + +class LLPhysicsExtensions +{ + +public: + // Obtain a pointer to the actual implementation + static LLPhysicsExtensions* getInstance(); + + /// @returns false if this is the stub + static bool isFunctional(); + + static bool initSystem(); + static bool quitSystem(); + +private: + static bool s_isInitialized; +}; + +#endif //LL_PATHING_LIBRARY + + diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 9e90314a51..ff0cad58d6 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -65,15 +65,18 @@ target_link_libraries(llprimitive llxml llcharacter llrender - llphysicsextensions_impl ll::colladadom ll::glm ) -if (TARGET llconvexdecomposition) +if (HAVOK OR HAVOK_TPV) target_link_libraries(llprimitive - llconvexdecomposition - ) + llphysicsextensions_impl + ) +else() + target_link_libraries(llprimitive + llphysicsextensionsos + ) endif () #add unit tests diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4c6c42e7a2..8869f4b1f6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -50,7 +50,7 @@ include(VulkanGltf) include(ZLIBNG) include(LLPrimitive) -if (NOT HAVOK_TPV) +if (HAVOK) # When using HAVOK_TPV, the library is precompiled, so no need for this # Stub and probably havok lib itself is a hack, autobuild loads a 3p that really is a source tarball @@ -76,7 +76,7 @@ if (NOT HAVOK_TPV) target_compile_options( llphysicsextensions PRIVATE -Wno-unused-local-typedef) endif (DARWIN) endif() -endif (NOT HAVOK_TPV) +endif () set(viewer_SOURCE_FILES gltfscenemanager.cpp @@ -1952,13 +1952,30 @@ elseif (DARWIN) PROPERTIES RESOURCE SecondLife.xib LINK_FLAGS_RELEASE "${LINK_FLAGS_RELEASE} -Xlinker -dead_strip" - # arch specific flags for universal builds: https://stackoverflow.com/a/77942065 - XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=x86_64] "$(inherited) -DLLPHYSICSEXTENSIONS_USE_FULL" - XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=arm64] "$(inherited) -DLLPHYSICSEXTENSIONS_USE_STUB" - # only generate the .MAP file for llphysicsextensions_tpv on x86_64 - XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=x86_64] "$(inherited) -L${CMAKE_CURRENT_BINARY_DIR}/llphysicsextensions/$,$,${CMAKE_CFG_INTDIR}>/ -lllphysicsextensions -Xlinker -map -Xlinker ${CMAKE_CURRENT_BINARY_DIR}/${VIEWER_BINARY_NAME}.MAP" - XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=arm64] "$(inherited) -L${CMAKE_CURRENT_BINARY_DIR}/llphysicsextensionsstub/$,$,${CMAKE_CFG_INTDIR}>/ -lllphysicsextensionsstub" ) + if(HAVOK) + set_target_properties(${VIEWER_BINARY_NAME} + PROPERTIES + # arch specific flags for universal builds: https://stackoverflow.com/a/77942065 + XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=x86_64] "$(inherited) -DLLPHYSICSEXTENSIONS_USE_FULL -DLL_HAVOK=1" + XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=arm64] "$(inherited) -DLLPHYSICSEXTENSIONS_USE_STUB" + # only generate the .MAP file for llphysicsextensions_tpv on x86_64 + XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=x86_64] "$(inherited) -L${CMAKE_CURRENT_BINARY_DIR}/llphysicsextensions/$,$,${CMAKE_CFG_INTDIR}>/ -lllphysicsextensions -Xlinker -map -Xlinker ${CMAKE_CURRENT_BINARY_DIR}/${VIEWER_BINARY_NAME}.MAP" + XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=arm64] "$(inherited) -L${CMAKE_BINARY_DIR}/llphysicsextensionsos/$,$,${CMAKE_CFG_INTDIR}>/ -lllphysicsextensionsos" + ) + elseif(HAVOK_TPV) + set_target_properties(${VIEWER_BINARY_NAME} + PROPERTIES + # arch specific flags for universal builds: https://stackoverflow.com/a/77942065 + XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=x86_64] "$(inherited) -DLLPHYSICSEXTENSIONS_USE_FULL -DLL_HAVOK=1" + XCODE_ATTRIBUTE_OTHER_CFLAGS[arch=arm64] "$(inherited) -DLLPHYSICSEXTENSIONS_USE_STUB" + # only generate the .MAP file for llphysicsextensions_tpv on x86_64 + XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=x86_64] "$(inherited) -L${ARCH_PREBUILT_DIRS}/ -lllphysicsextensions_tpv" + XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=arm64] "$(inherited) -L${CMAKE_BINARY_DIR}/llphysicsextensionsos/$,$,${CMAKE_CFG_INTDIR}>/ -lllphysicsextensionsos" + ) + else() + target_link_libraries(${VIEWER_BINARY_NAME} llphysicsextensionsos) + endif() else (WINDOWS) # Linux set_target_properties(${VIEWER_BINARY_NAME} -- cgit v1.3