This commit is contained in:
2025-11-28 23:13:44 +05:30
commit a3a8e79709
7360 changed files with 1156074 additions and 0 deletions

View File

@ -0,0 +1,119 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
cmake_minimum_required(VERSION 3.7)
project(Snippets C CXX)
IF(NOT DEFINED CMAKEMODULES_VERSION)
SET(CMAKEMODULES_PATH $ENV{PM_CMakeModules_PATH} CACHE INTERNAL "Path to CMakeModules")
SET(CMAKEMODULES_NAME $ENV{PM_CMakeModules_NAME} CACHE INTERNAL "CMakeModules name")
SET(CMAKEMODULES_VERSION $ENV{PM_CMakeModules_VERSION} CACHE INTERNAL "CMakeModules version from generation batch")
#TODO: More elegance
IF(NOT EXISTS ${CMAKEMODULES_PATH})
MESSAGE(FATAL_ERROR "Could not find ${CMAKEMODULES_PATH}")
ENDIF()
ENDIF()
SET(CMAKE_MODULE_PATH ${CMAKEMODULES_PATH})
# This is required to be defined by external callers!
IF(NOT DEFINED PHYSX_ROOT_DIR)
MESSAGE(FATAL_ERROR "PHYSX_ROOT_DIR variable wasn't set.")
ENDIF()
IF(NOT EXISTS ${PHYSX_ROOT_DIR})
MESSAGE(FATAL_ERROR "PHYSX_ROOT_DIR variable was invalid.")
ENDIF()
INCLUDE(NvidiaBuildOptions)
IF(CMAKE_CONFIGURATION_TYPES)
SET(CMAKE_CONFIGURATION_TYPES debug checked profile release)
SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
"Reset config to what we need"
FORCE)
# Need to define these at least once.
SET(CMAKE_SHARED_LINKER_FLAGS_CHECKED "/DEBUG")
SET(CMAKE_SHARED_LINKER_FLAGS_PROFILE "/DEBUG")
SET(CMAKE_EXE_LINKER_FLAGS_PROFILE "/DEBUG")
SET(CMAKE_EXE_LINKER_FLAGS_CHECKED "/DEBUG")
ENDIF()
SET(PROJECT_CMAKE_FILES_DIR compiler/cmake)
SET(PLATFORM_CMAKELISTS ${PHYSX_ROOT_DIR}/snippets/${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/CMakeLists.txt)
IF(NOT EXISTS ${PLATFORM_CMAKELISTS})
MESSAGE(FATAL_ERROR "Unable to find platform CMakeLists.txt for ${TARGET_BUILD_PLATFORM} at ${PLATFORM_CMAKELISTS}")
ENDIF()
# Include the platform specific CMakeLists
INCLUDE(${PHYSX_ROOT_DIR}/snippets/${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/CMakeLists.txt)
SET(SOURCE_DISTRO_FILE_LIST "")
# Include all of the projects
SET(SNIPPETS_LIST Articulation BVHStructure ContactModification ContactReport ContactReportCCD ConvexMeshCreate
CustomJoint CustomProfiler DeformableMesh HelloWorld ImmediateArticulation ImmediateMode Joint MBP MultiThreading
PrunerSerialization RaycastCCD Serialization SplitFetchResults
SplitSim Stepper ToleranceScale TriangleMeshCreate Triggers)
LIST(APPEND SNIPPETS_LIST ${PLATFORM_SNIPPETS_LIST})
SET(SNIPPETS_VEHICLE_LIST NestedScene Vehicle4W VehicleContactMod VehicleMultiThreading
VehicleNoDrive VehicleScale VehicleTank)
LIST(APPEND SNIPPETS_VEHICLE_LIST ${PLATFORM_SNIPPETS_VEHICLE_LIST})
IF(SNIPPET_RENDER_ENABLED)
INCLUDE(SnippetRender.cmake)
SET_PROPERTY(TARGET SnippetRender PROPERTY FOLDER "Snippets/Libraries only")
ENDIF()
INCLUDE(SnippetUtils.cmake)
SET_PROPERTY(TARGET SnippetUtils PROPERTY FOLDER "Snippets/Libraries only")
FOREACH(SNIPPET_NAME ${SNIPPETS_LIST})
INCLUDE(SnippetTemplate.cmake)
SET_PROPERTY(TARGET Snippet${SNIPPET_NAME} PROPERTY FOLDER "Snippets")
ENDFOREACH()
FOREACH(SNIPPET_NAME ${SNIPPETS_VEHICLE_LIST})
INCLUDE(SnippetVehicleTemplate.cmake)
SET_PROPERTY(TARGET Snippet${SNIPPET_NAME} PROPERTY FOLDER "Snippets")
ENDFOREACH()
IF(PX_GENERATE_SOURCE_DISTRO)
FOREACH(FILE_NAME ${SOURCE_DISTRO_FILE_LIST})
FILE(APPEND "${CMAKE_CURRENT_BINARY_DIR}/source_distro_list.txt" "${FILE_NAME}\n")
ENDFOREACH()
ENDIF()

View File

@ -0,0 +1,87 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetRender common
#
# Include here after the directories are defined so that the platform specific file can use the variables.
include(${PHYSX_ROOT_DIR}/snippets/${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/SnippetRender.cmake)
SET(SNIPPETRENDER_FILES
${PHYSX_ROOT_DIR}/snippets/snippetrender/SnippetCamera.cpp
${PHYSX_ROOT_DIR}/snippets/snippetrender/SnippetCamera.h
${PHYSX_ROOT_DIR}/snippets/snippetrender/SnippetRender.cpp
${PHYSX_ROOT_DIR}/snippets/snippetrender/SnippetRender.h
)
ADD_LIBRARY(SnippetRender STATIC
${SNIPPETRENDER_FILES}
${SNIPPETRENDER_PLATFORM_FILES}
)
TARGET_INCLUDE_DIRECTORIES(SnippetRender
PRIVATE ${PHYSX_ROOT_DIR}/include
PUBLIC ${SNIPPETRENDER_PLATFORM_INCLUDES}
)
TARGET_COMPILE_DEFINITIONS(SnippetRender
PRIVATE ${SNIPPETRENDER_COMPILE_DEFS}
)
IF(NV_USE_GAMEWORKS_OUTPUT_DIRS)
SET_TARGET_PROPERTIES(SnippetRender PROPERTIES
COMPILE_PDB_NAME_DEBUG "SnippetRender_static_${CMAKE_DEBUG_POSTFIX}"
COMPILE_PDB_NAME_CHECKED "SnippetRender_static_${CMAKE_CHECKED_POSTFIX}"
COMPILE_PDB_NAME_PROFILE "SnippetRender_static_${CMAKE_PROFILE_POSTFIX}"
COMPILE_PDB_NAME_RELEASE "SnippetRender_static_${CMAKE_RELEASE_POSTFIX}"
ARCHIVE_OUTPUT_NAME_DEBUG "SnippetRender_static"
ARCHIVE_OUTPUT_NAME_CHECKED "SnippetRender_static"
ARCHIVE_OUTPUT_NAME_PROFILE "SnippetRender_static"
ARCHIVE_OUTPUT_NAME_RELEASE "SnippetRender_static"
)
ELSE()
SET_TARGET_PROPERTIES(SnippetRender PROPERTIES
COMPILE_PDB_NAME_DEBUG "SnippetRender${CMAKE_DEBUG_POSTFIX}"
COMPILE_PDB_NAME_CHECKED "SnippetRender${CMAKE_CHECKED_POSTFIX}"
COMPILE_PDB_NAME_PROFILE "SnippetRender${CMAKE_PROFILE_POSTFIX}"
COMPILE_PDB_NAME_RELEASE "SnippetRender${CMAKE_RELEASE_POSTFIX}"
)
ENDIF()
TARGET_LINK_LIBRARIES(SnippetRender
PUBLIC PhysXFoundation
PUBLIC ${SNIPPETRENDER_PLATFORM_LINKED_LIBS})
IF(PX_GENERATE_SOURCE_DISTRO)
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SNIPPETRENDER_FILES})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SNIPPETRENDER_PLATFORM_FILES})
ENDIF()

View File

@ -0,0 +1,91 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet common template
#
# Include here after the directories are defined so that the platform specific file can use the variables.
INCLUDE(${PHYSX_ROOT_DIR}/snippets/${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/SnippetTemplate.cmake)
STRING(TOLOWER ${SNIPPET_NAME} SNIPPET_NAME_LOWER)
FILE(GLOB SnippetSources ${PHYSX_ROOT_DIR}/snippets/snippet${SNIPPET_NAME_LOWER}/*.cpp)
FILE(GLOB SnippetHeaders ${PHYSX_ROOT_DIR}/snippets/snippet${SNIPPET_NAME_LOWER}/*.h)
ADD_EXECUTABLE(Snippet${SNIPPET_NAME} ${SNIPPET_BUNDLE}
${SNIPPET_PLATFORM_SOURCES}
${SnippetSources}
${SnippetHeaders}
)
TARGET_INCLUDE_DIRECTORIES(Snippet${SNIPPET_NAME}
PRIVATE ${SNIPPET_PLATFORM_INCLUDES}
PRIVATE ${PHYSX_ROOT_DIR}/include/
PRIVATE ${PHYSX_ROOT_DIR}/source/physxextensions/src
)
TARGET_COMPILE_DEFINITIONS(Snippet${SNIPPET_NAME}
PRIVATE ${SNIPPET_COMPILE_DEFS}
)
IF(NV_USE_GAMEWORKS_OUTPUT_DIRS)
SET_TARGET_PROPERTIES(Snippet${SNIPPET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PX_EXE_OUTPUT_DIRECTORY_DEBUG}${EXE_PLATFORM_DIR}
RUNTIME_OUTPUT_DIRECTORY_PROFILE ${PX_EXE_OUTPUT_DIRECTORY_PROFILE}${EXE_PLATFORM_DIR}
RUNTIME_OUTPUT_DIRECTORY_CHECKED ${PX_EXE_OUTPUT_DIRECTORY_CHECKED}${EXE_PLATFORM_DIR}
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PX_EXE_OUTPUT_DIRECTORY_RELEASE}${EXE_PLATFORM_DIR}
OUTPUT_NAME Snippet${SNIPPET_NAME}${EXE_SUFFIX}
)
ELSE()
IF(APPEND_CONFIG_NAME)
SET_TARGET_PROPERTIES(Snippet${SNIPPET_NAME} PROPERTIES
DEBUG_OUTPUT_NAME Snippet${SNIPPET_NAME}DEBUG
PROFILE_OUTPUT_NAME Snippet${SNIPPET_NAME}PROFILE
CHECKED_OUTPUT_NAME Snippet${SNIPPET_NAME}CHECKED
RELEASE_OUTPUT_NAME Snippet${SNIPPET_NAME}
)
ENDIF()
ENDIF()
TARGET_LINK_LIBRARIES(Snippet${SNIPPET_NAME}
PUBLIC PhysXExtensions PhysX PhysXPvdSDK PhysXVehicle PhysXCharacterKinematic PhysXCooking PhysXCommon PhysXFoundation SnippetUtils
PUBLIC ${SNIPPET_PLATFORM_LINKED_LIBS})
IF(CUSTOM_SNIPPET_TARGET_PROPERTIES)
SET_TARGET_PROPERTIES(Snippet${SNIPPET_NAME} PROPERTIES
${CUSTOM_SNIPPET_TARGET_PROPERTIES}
)
ENDIF()
IF(PX_GENERATE_SOURCE_DISTRO)
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SNIPPET_PLATFORM_SOURCES})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SnippetSources})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SnippetHeaders})
ENDIF()

View File

@ -0,0 +1,84 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetUtils common
#
# Include here after the directories are defined so that the platform specific file can use the variables.
INCLUDE(${PHYSX_ROOT_DIR}/snippets/${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/SnippetUtils.cmake)
SET(SNIPPETUTILS_FILES
${PHYSX_ROOT_DIR}/snippets/snippetutils/SnippetUtils.cpp
${PHYSX_ROOT_DIR}/snippets/snippetutils/SnippetUtils.h
)
ADD_LIBRARY(SnippetUtils STATIC
${SNIPPETUTILS_FILES}
)
TARGET_INCLUDE_DIRECTORIES(SnippetUtils
PRIVATE ${SNIPPETUTILS_PLATFORM_INCLUDES}
PRIVATE ${PHYSX_ROOT_DIR}/include
PRIVATE ${PHYSX_ROOT_DIR}/source/common/src
)
TARGET_COMPILE_DEFINITIONS(SnippetUtils
PRIVATE ${SNIPPETUTILS_COMPILE_DEFS}
)
IF(NV_USE_GAMEWORKS_OUTPUT_DIRS)
SET_TARGET_PROPERTIES(SnippetUtils PROPERTIES
COMPILE_PDB_NAME_DEBUG "SnippetUtils_static_${CMAKE_DEBUG_POSTFIX}"
COMPILE_PDB_NAME_CHECKED "SnippetUtils_static_${CMAKE_CHECKED_POSTFIX}"
COMPILE_PDB_NAME_PROFILE "SnippetUtils_static_${CMAKE_PROFILE_POSTFIX}"
COMPILE_PDB_NAME_RELEASE "SnippetUtils_static_${CMAKE_RELEASE_POSTFIX}"
ARCHIVE_OUTPUT_NAME_DEBUG "SnippetUtils_static"
ARCHIVE_OUTPUT_NAME_CHECKED "SnippetUtils_static"
ARCHIVE_OUTPUT_NAME_PROFILE "SnippetUtils_static"
ARCHIVE_OUTPUT_NAME_RELEASE "SnippetUtils_static"
)
ELSE()
SET_TARGET_PROPERTIES(SnippetUtils PROPERTIES
COMPILE_PDB_NAME_DEBUG "SnippetUtils${CMAKE_DEBUG_POSTFIX}"
COMPILE_PDB_NAME_CHECKED "SnippetUtils${CMAKE_CHECKED_POSTFIX}"
COMPILE_PDB_NAME_PROFILE "SnippetUtils${CMAKE_PROFILE_POSTFIX}"
COMPILE_PDB_NAME_RELEASE "SnippetUtils${CMAKE_RELEASE_POSTFIX}"
)
ENDIF()
TARGET_LINK_LIBRARIES(SnippetUtils
PUBLIC PhysXFoundation
)
IF(PX_GENERATE_SOURCE_DISTRO)
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SNIPPETUTILS_FILES})
ENDIF()

View File

@ -0,0 +1,96 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippetvehicle common template
#
# Include here after the directories are defined so that the platform specific file can use the variables.
INCLUDE(${PHYSX_ROOT_DIR}/snippets/${PROJECT_CMAKE_FILES_DIR}/${TARGET_BUILD_PLATFORM}/SnippetVehicleTemplate.cmake)
STRING(TOLOWER ${SNIPPET_NAME} SNIPPET_NAME_LOWER)
FILE(GLOB SnippetSources ${PHYSX_ROOT_DIR}/snippets/snippet${SNIPPET_NAME_LOWER}/*.cpp)
FILE(GLOB VehicleSources ${PHYSX_ROOT_DIR}/snippets/snippetvehiclecommon/*.cpp)
FILE(GLOB SnippetHeaders ${PHYSX_ROOT_DIR}/snippets/snippet${SNIPPET_NAME_LOWER}/*.h)
FILE(GLOB VehicleHeaders ${PHYSX_ROOT_DIR}/snippets/snippetvehiclecommon/*.h)
ADD_EXECUTABLE(Snippet${SNIPPET_NAME} ${SNIPPET_BUNDLE}
${SNIPPET_PLATFORM_SOURCES}
${SnippetSources}
${VehicleSources}
${SnippetHeaders}
${VehicleHeaders}
)
TARGET_INCLUDE_DIRECTORIES(Snippet${SNIPPET_NAME}
PRIVATE ${SNIPPET_PLATFORM_INCLUDES}
PRIVATE ${PHYSX_ROOT_DIR}/include/
)
TARGET_COMPILE_DEFINITIONS(Snippet${SNIPPET_NAME}
PRIVATE ${SNIPPET_COMPILE_DEFS}
)
IF(NV_USE_GAMEWORKS_OUTPUT_DIRS)
SET_TARGET_PROPERTIES(Snippet${SNIPPET_NAME} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PX_EXE_OUTPUT_DIRECTORY_DEBUG}${EXE_PLATFORM_DIR}
RUNTIME_OUTPUT_DIRECTORY_PROFILE ${PX_EXE_OUTPUT_DIRECTORY_PROFILE}${EXE_PLATFORM_DIR}
RUNTIME_OUTPUT_DIRECTORY_CHECKED ${PX_EXE_OUTPUT_DIRECTORY_CHECKED}${EXE_PLATFORM_DIR}
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PX_EXE_OUTPUT_DIRECTORY_RELEASE}${EXE_PLATFORM_DIR}
OUTPUT_NAME Snippet${SNIPPET_NAME}${EXE_SUFFIX}
)
ELSE()
IF(APPEND_CONFIG_NAME)
SET_TARGET_PROPERTIES(Snippet${SNIPPET_NAME} PROPERTIES
DEBUG_OUTPUT_NAME Snippet${SNIPPET_NAME}DEBUG
PROFILE_OUTPUT_NAME Snippet${SNIPPET_NAME}PROFILE
CHECKED_OUTPUT_NAME Snippet${SNIPPET_NAME}CHECKED
RELEASE_OUTPUT_NAME Snippet${SNIPPET_NAME}
)
ENDIF()
ENDIF()
TARGET_LINK_LIBRARIES(Snippet${SNIPPET_NAME}
PUBLIC PhysXExtensions PhysX PhysXPvdSDK PhysXVehicle PhysXCharacterKinematic PhysXCooking PhysXCommon PhysXFoundation SnippetUtils
PUBLIC ${SNIPPET_PLATFORM_LINKED_LIBS})
IF(CUSTOM_SNIPPET_TARGET_PROPERTIES)
SET_TARGET_PROPERTIES(Snippet${SNIPPET_NAME} PROPERTIES
${CUSTOM_SNIPPET_TARGET_PROPERTIES}
)
ENDIF()
IF(PX_GENERATE_SOURCE_DISTRO)
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SNIPPET_PLATFORM_SOURCES})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SnippetSources})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${VehicleSources})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${SnippetHeaders})
LIST(APPEND SOURCE_DISTRO_FILE_LIST ${VehicleHeaders})
ENDIF()

View File

@ -0,0 +1,53 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
IF(NOT DEFINED PHYSX_ANDROID_COMPILE_DEFS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX compile defs, and they're not defined when they need to be.")
ENDIF()
IF (NOT DEFINED PHYSX_CXX_FLAGS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX CXX flags, and they're not defined when they need to be.")
ENDIF()
STRING(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWERCASE)
# Get the CXX Flags from the Cached variables set by the PhysX CMakeLists
SET(CMAKE_CXX_FLAGS "${PHYSX_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_DEBUG "${PHYSX_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_CHECKED ${PHYSX_CXX_FLAGS_CHECKED})
SET(CMAKE_CXX_FLAGS_PROFILE ${PHYSX_CXX_FLAGS_PROFILE})
SET(CMAKE_CXX_FLAGS_RELEASE ${PHYSX_CXX_FLAGS_RELEASE})
# Build PDBs for all configurations
SET(CMAKE_SHARED_LINKER_FLAGS "/DEBUG")
SET(PHYSX_LIB_PATH "${PHYSX_ROOT_DIR}/lib/${COMPILER_AND_PLATFORM}")

View File

@ -0,0 +1,54 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet android template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_ANDROID_COMPILE_DEFS};ANDROID;GLES2;
$<$<CONFIG:debug>:${PHYSX_ANDROID_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_ANDROID_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_ANDROID_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_ANDROID_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_LINKED_LIBS
)

View File

@ -0,0 +1,44 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetUtils
#
SET(SNIPPETUTILS_PLATFORM_INCLUDES
)
SET(SNIPPETUTILS_COMPILE_DEFS
# Common to all configurations
${PHYSX_ANDROID_COMPILE_DEFS};PX_PHYSX_STATIC_LIB;ANDROID;GLES2
$<$<CONFIG:debug>:${PHYSX_ANDROID_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_ANDROID_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_ANDROID_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_ANDROID_RELEASE_COMPILE_DEFS};>
)

View File

@ -0,0 +1,54 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetVehicle android template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_ANDROID_COMPILE_DEFS};ANDROID;GLES2;
$<$<CONFIG:debug>:${PHYSX_ANDROID_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_ANDROID_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_ANDROID_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_ANDROID_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_LINKED_LIBS
)

View File

@ -0,0 +1,62 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
IF(NOT DEFINED PHYSX_IOS_COMPILE_DEFS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX compile defs, and they're not defined when they need to be.")
ENDIF()
IF (NOT DEFINED PHYSX_CXX_FLAGS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX CXX flags, and they're not defined when they need to be.")
ENDIF()
# Get the CXX Flags from the Cached variables set by the PhysX CMakeLists
SET(CMAKE_CXX_FLAGS "${PHYSX_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_DEBUG "${PHYSX_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_CHECKED ${PHYSX_CXX_FLAGS_CHECKED})
SET(CMAKE_CXX_FLAGS_PROFILE ${PHYSX_CXX_FLAGS_PROFILE})
SET(CMAKE_CXX_FLAGS_RELEASE ${PHYSX_CXX_FLAGS_RELEASE})
# Build PDBs for all configurations
SET(CMAKE_SHARED_LINKER_FLAGS "/DEBUG")
SET(PHYSX_LIB_PATH "${PHYSX_ROOT_DIR}/lib/${COMPILER_AND_PLATFORM}")
SET(SNIPPET_BUNDLE MACOSX_BUNDLE)
SET(CUSTOM_SNIPPET_TARGET_PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer"
XCODE_ATTRIBUTE_INFOPLIST_FILE "${PHYSX_ROOT_DIR}/snippets/deployment/ios64/PhysXAppIos64-Info.plist"
MACOSX_BUNDLE_INFO_PLIST "${PHYSX_ROOT_DIR}/snippets/deployment/ios64/PhysXAppIos64-Info.plist"
XCODE_ATTRIBUTE_INFOPLIST_PREPROCESS YES
CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "7.0"
XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "YES"
)

View File

@ -0,0 +1,53 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet ios template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_IOS_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_IOS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_IOS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_IOS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_IOS_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_LINKED_LIBS
)

View File

@ -0,0 +1,45 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetUtils
#
SET(SNIPPETUTILS_PLATFORM_INCLUDES
)
SET(SNIPPETUTILS_COMPILE_DEFS
# Common to all configurations
${PHYSX_IOS_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_IOS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_IOS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_IOS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_IOS_RELEASE_COMPILE_DEFS};>
)

View File

@ -0,0 +1,53 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetVehicle ios template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_IOS_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_IOS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_IOS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_IOS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_IOS_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_LINKED_LIBS
)

View File

@ -0,0 +1,61 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
IF(NOT DEFINED PHYSX_LINUX_COMPILE_DEFS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX compile defs, and they're not defined when they need to be.")
ENDIF()
IF (NOT DEFINED PHYSX_CXX_FLAGS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX CXX flags, and they're not defined when they need to be.")
ENDIF()
IF(NOT DEFINED TINYXML2_PATH)
SET(TINYXML2_PATH $ENV{PM_tinyxml2_PATH} CACHE INTERNAL "Path to tinyxml2")
ENDIF()
# Get the CXX Flags from the Cached variables set by the PhysX CMakeLists
SET(CMAKE_CXX_FLAGS "${PHYSX_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_DEBUG "${PHYSX_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_CHECKED ${PHYSX_CXX_FLAGS_CHECKED})
SET(CMAKE_CXX_FLAGS_PROFILE ${PHYSX_CXX_FLAGS_PROFILE})
SET(CMAKE_CXX_FLAGS_RELEASE ${PHYSX_CXX_FLAGS_RELEASE})
# Build PDBs for all configurations
SET(CMAKE_SHARED_LINKER_FLAGS "/DEBUG")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
# Include all of the projects
SET(PLATFORM_SNIPPETS_LIST Convert LoadCollection)
IF(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
SET(SNIPPET_RENDER_ENABLED 0)
ELSE()
SET(SNIPPET_RENDER_ENABLED 1)
LIST(APPEND PLATFORM_SNIPPETS_LIST HelloGRB)
ENDIF()

View File

@ -0,0 +1,48 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetRender
#
find_package(OpenGL $ENV{PM_OpenGL_VERSION} CONFIG REQUIRED) # Pull in OpenGL and GLUT
SET(SNIPPETRENDER_COMPILE_DEFS
# Common to all configurations
${PHYSX_LINUX_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_LINUX_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_LINUX_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_LINUX_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_LINUX_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPETRENDER_PLATFORM_INCLUDES
)
SET(SNIPPETRENDER_PLATFORM_LINKED_LIBS GL GLUT GLU)

View File

@ -0,0 +1,90 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet linux template
#
IF(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_LINUX_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_LINUX_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_LINUX_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_LINUX_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_LINUX_RELEASE_COMPILE_DEFS};>
)
ELSE()
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_LINUX_COMPILE_DEFS};RENDER_SNIPPET;
$<$<CONFIG:debug>:${PHYSX_LINUX_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_LINUX_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_LINUX_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_LINUX_RELEASE_COMPILE_DEFS};>
)
ENDIF()
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
IF(${SNIPPET_NAME} STREQUAL "ArticulationLoader")
LIST(APPEND SNIPPET_PLATFORM_SOURCES
${TINYXML2_PATH}/tinyxml2.h
${TINYXML2_PATH}/tinyxml2.cpp
)
LIST(APPEND SNIPPET_PLATFORM_INCLUDES
${TINYXML2_PATH}
)
ENDIF()
IF(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
SET(SNIPPET_PLATFORM_LINKED_LIBS
rt pthread dl
)
ELSE()
SET(SNIPPET_PLATFORM_LINKED_LIBS
SnippetRender GL GLU GLUT X11 rt pthread dl -Wl,-rpath='${ORIGIN}'
)
ENDIF()
IF(PX_GENERATE_GPU_STATIC_LIBRARIES)
IF(${SNIPPET_NAME} STREQUAL "ConvexDecomposition")
LIST(APPEND SNIPPET_PLATFORM_LINKED_LIBS VHACD)
ENDIF()
ENDIF()

View File

@ -0,0 +1,45 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetUtils
#
SET(SNIPPETUTILS_PLATFORM_INCLUDES
)
SET(SNIPPETUTILS_COMPILE_DEFS
# Common to all configurations
${PHYSX_LINUX_COMPILE_DEFS};PX_PHYSX_STATIC_LIB;
$<$<CONFIG:debug>:${PHYSX_LINUX_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_LINUX_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_LINUX_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_LINUX_RELEASE_COMPILE_DEFS};>
)

View File

@ -0,0 +1,72 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetVehicle linux template
#
IF(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_LINUX_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_LINUX_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_LINUX_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_LINUX_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_LINUX_RELEASE_COMPILE_DEFS};>
)
ELSE()
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_LINUX_COMPILE_DEFS};RENDER_SNIPPET;
$<$<CONFIG:debug>:${PHYSX_LINUX_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_LINUX_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_LINUX_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_LINUX_RELEASE_COMPILE_DEFS};>
)
ENDIF()
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
IF(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
SET(SNIPPET_PLATFORM_LINKED_LIBS
rt pthread dl
)
ELSE()
SET(SNIPPET_PLATFORM_LINKED_LIBS
SnippetRender GL GLU GLUT X11 rt pthread dl
)
ENDIF()

View File

@ -0,0 +1,57 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
IF(NOT DEFINED PHYSX_MAC_COMPILE_DEFS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX compile defs, and they're not defined when they need to be.")
ENDIF()
IF (NOT DEFINED PHYSX_CXX_FLAGS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX CXX flags, and they're not defined when they need to be.")
ENDIF()
# Get the CXX Flags from the Cached variables set by the PhysX CMakeLists
SET(CMAKE_CXX_FLAGS "${PHYSX_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_DEBUG "${PHYSX_CXX_FLAGS_DEBUG}")
SET(CMAKE_CXX_FLAGS_CHECKED ${PHYSX_CXX_FLAGS_CHECKED})
SET(CMAKE_CXX_FLAGS_PROFILE ${PHYSX_CXX_FLAGS_PROFILE})
SET(CMAKE_CXX_FLAGS_RELEASE ${PHYSX_CXX_FLAGS_RELEASE})
# Build PDBs for all configurations
SET(CMAKE_SHARED_LINKER_FLAGS "")
SET(CMAKE_EXE_LINKER_FLAGS_PROFILE "")
SET(CMAKE_EXE_LINKER_FLAGS_CHECKED "")
SET(PHYSX_LIB_PATH "${PHYSX_ROOT_DIR}/lib/${COMPILER_AND_PLATFORM}")
SET(SNIPPET_RENDER_ENABLED 1)
# Include all of the projects
SET(PLATFORM_SNIPPETS_LIST Convert LoadCollection)

View File

@ -0,0 +1,44 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetRender
#
SET(SNIPPETRENDER_PLATFORM_INCLUDES
)
SET(SNIPPETRENDER_COMPILE_DEFS
# Common to all configurations
${PHYSX_MAC_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_MAC_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_MAC_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_MAC_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_MAC_RELEASE_COMPILE_DEFS};>
)

View File

@ -0,0 +1,63 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet mac template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_MAC_COMPILE_DEFS};RENDER_SNIPPET;
$<$<CONFIG:debug>:${PHYSX_MAC_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_MAC_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_MAC_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_MAC_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
FIND_PACKAGE(OpenGL REQUIRED)
FIND_PACKAGE(GLUT REQUIRED)
SET(SNIPPET_PLATFORM_LINKED_LIBS
SnippetRender ${OPENGL_LIBRARIES} ${GLUT_LIBRARY}
)
IF(${SNIPPET_NAME} STREQUAL "ConvexDecomposition")
LIST(APPEND SNIPPET_PLATFORM_LINKED_LIBS
VHACD
)
ENDIF()

View File

@ -0,0 +1,44 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetUtils
#
SET(SNIPPETUTILS_PLATFORM_INCLUDES
)
SET(SNIPPETUTILS_COMPILE_DEFS
# Common to all configurations
${PHYSX_MAC_COMPILE_DEFS};
$<$<CONFIG:debug>:${PHYSX_MAC_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_MAC_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_MAC_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_MAC_RELEASE_COMPILE_DEFS};>
)

View File

@ -0,0 +1,57 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetVehicle mac template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_MAC_COMPILE_DEFS};RENDER_SNIPPET;
$<$<CONFIG:debug>:${PHYSX_MAC_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_MAC_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_MAC_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_MAC_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
FIND_PACKAGE(OpenGL REQUIRED)
FIND_PACKAGE(GLUT REQUIRED)
SET(SNIPPET_PLATFORM_LINKED_LIBS
SnippetRender ${OPENGL_LIBRARIES} ${GLUT_LIBRARY}
)

View File

@ -0,0 +1,71 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
IF(NOT DEFINED PHYSX_WINDOWS_COMPILE_DEFS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX compile defs, and they're not defined when they need to be.")
ENDIF()
IF (NOT DEFINED PHYSX_CXX_FLAGS)
MESSAGE(FATAL ERROR "Snippets uses the PhysX CXX flags, and they're not defined when they need to be.")
ENDIF()
IF(NOT DEFINED TINYXML2_PATH)
SET(TINYXML2_PATH $ENV{PM_tinyxml2_PATH} CACHE INTERNAL "Path to tinyxml2")
ENDIF()
# Get the CXX Flags from the Cached variables set by the PhysX CMakeLists
SET(CMAKE_CXX_FLAGS "${PHYSX_CXX_FLAGS} /EHsc")
SET(CMAKE_CXX_FLAGS_DEBUG ${PHYSX_CXX_FLAGS_DEBUG})
SET(CMAKE_CXX_FLAGS_CHECKED ${PHYSX_CXX_FLAGS_CHECKED})
SET(CMAKE_CXX_FLAGS_PROFILE ${PHYSX_CXX_FLAGS_PROFILE})
SET(CMAKE_CXX_FLAGS_RELEASE ${PHYSX_CXX_FLAGS_RELEASE})
# Build PDBs for all configurations
SET(CMAKE_SHARED_LINKER_FLAGS "/DEBUG")
SET(SLN_PHYSXDEVICE_PATH "$ENV{PM_PhysXDevice_PATH}/bin/x86/")
# Include ConfigureFileMT to expose that function
INCLUDE(ConfigureFileMt)
SET(SNIPPET_RENDER_ENABLED 1)
# Include all of the projects
SET(PLATFORM_SNIPPETS_LIST Convert LoadCollection DelayLoadHook)
IF(PUBLIC_RELEASE)
LIST(APPEND PLATFORM_SNIPPETS_LIST HelloGRB)
ELSE()
IF(PX_GENERATE_GPU_PROJECTS)
LIST(APPEND PLATFORM_SNIPPETS_LIST HelloGRB)
ENDIF()
ENDIF()
IF(PX_BUILDVHACD)
LIST(APPEND PLATFORM_SNIPPETS_LIST ConvexDecomposition)
ENDIF()

View File

@ -0,0 +1,52 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetRender
#
SET(SNIPPETRENDER_COMPILE_DEFS
# Common to all configurations
${PHYSX_WINDOWS_COMPILE_DEFS};PX_PHYSX_STATIC_LIB;GLUT_NO_LIB_PRAGMA;${PHYSX_LIBTYPE_DEFS};${PHYSXGPU_LIBTYPE_DEFS}
$<$<CONFIG:debug>:${PHYSX_WINDOWS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_WINDOWS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_WINDOWS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_WINDOWS_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPETRENDER_PLATFORM_FILES
${PHYSX_ROOT_DIR}/snippets/graphics/include/win32/GL/glut.h
)
# Include OpenGL
SET(SNIPPETRENDER_PLATFORM_INCLUDES
${PHYSX_ROOT_DIR}/snippets/Graphics/include/win32/GL
)
SET(SNIPPETRENDER_PLATFORM_LINKED_LIBS ${PHYSX_ROOT_DIR}/snippets/Graphics/lib/win${LIBPATH_SUFFIX}/glut/glut32.lib opengl32.lib glu32.lib)

View File

@ -0,0 +1,80 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet win template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_WINDOWS_COMPILE_DEFS};RENDER_SNIPPET;${PHYSX_LIBTYPE_DEFS};${PHYSXGPU_LIBTYPE_DEFS}
$<$<CONFIG:debug>:${PHYSX_WINDOWS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_WINDOWS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_WINDOWS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_WINDOWS_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
${PHYSX_ROOT_DIR}/snippets/snippetcommon/SnippetPrint.h
${PHYSX_ROOT_DIR}/snippets/snippetcommon/SnippetPVD.h
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_LINKED_LIBS
SnippetRender
)
IF(${SNIPPET_NAME} STREQUAL "ArticulationLoader")
LIST(APPEND SNIPPET_PLATFORM_SOURCES
${TINYXML2_PATH}/tinyxml2.h
${TINYXML2_PATH}/tinyxml2.cpp
)
LIST(APPEND SNIPPET_PLATFORM_INCLUDES
${TINYXML2_PATH}
)
ENDIF()
IF(${SNIPPET_NAME} STREQUAL "ConvexDecomposition")
LIST(APPEND SNIPPET_PLATFORM_LINKED_LIBS
VHACD
)
ENDIF()
IF(PX_GENERATE_GPU_STATIC_LIBRARIES)
LIST(APPEND SNIPPET_PLATFORM_LINKED_LIBS PhysXGpu ${CUDA_CUDA_LIBRARY})
ENDIF()

View File

@ -0,0 +1,44 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build SnippetUtils
#
SET(SNIPPETUTILS_PLATFORM_INCLUDES
)
SET(SNIPPETUTILS_COMPILE_DEFS
# Common to all configurations
${PHYSX_WINDOWS_COMPILE_DEFS};${PHYSX_LIBTYPE_DEFS};${PHYSXGPU_LIBTYPE_DEFS}
$<$<CONFIG:debug>:${PHYSX_WINDOWS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_WINDOWS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_WINDOWS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_WINDOWS_RELEASE_COMPILE_DEFS};>
)

View File

@ -0,0 +1,61 @@
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions
## are met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in the
## documentation and/or other materials provided with the distribution.
## * Neither the name of NVIDIA CORPORATION nor the names of its
## contributors may be used to endorse or promote products derived
## from this software without specific prior written permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##
## Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#
# Build Snippet win template
#
SET(SNIPPET_COMPILE_DEFS
# Common to all configurations
${PHYSX_WINDOWS_COMPILE_DEFS};RENDER_SNIPPET;${PHYSX_LIBTYPE_DEFS};${PHYSXGPU_LIBTYPE_DEFS}
$<$<CONFIG:debug>:${PHYSX_WINDOWS_DEBUG_COMPILE_DEFS};>
$<$<CONFIG:checked>:${PHYSX_WINDOWS_CHECKED_COMPILE_DEFS};>
$<$<CONFIG:profile>:${PHYSX_WINDOWS_PROFILE_COMPILE_DEFS};>
$<$<CONFIG:release>:${PHYSX_WINDOWS_RELEASE_COMPILE_DEFS};>
)
SET(SNIPPET_PLATFORM_SOURCES
${PHYSX_ROOT_DIR}/snippets/snippetcommon/ClassicMain.cpp
)
SET(SNIPPET_PLATFORM_INCLUDES
)
SET(SNIPPET_PLATFORM_LINKED_LIBS
SnippetRender
)
IF(PX_GENERATE_GPU_STATIC_LIBRARIES)
LIST(APPEND SNIPPET_PLATFORM_LINKED_LIBS PhysXGpu)
ENDIF()
IF(NOT PX_GENERATE_STATIC_LIBRARIES)
LIST(APPEND SNIPPET_PLATFORM_LINKED_LIBS PhysXTask)
ENDIF()

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.${PRODUCT_NAME}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<false/>
<key>NSMainNibFile</key>
<string>MainWindow</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIInterfaceOrientation</key>
<string>UIInterfaceOrientationLandscapeRight</string>
</dict>
</plist>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.${PRODUCT_NAME}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<false/>
<key>NSMainNibFile</key>
<string>MainWindow</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIInterfaceOrientation</key>
<string>UIInterfaceOrientationLandscapeRight</string>
</dict>
</plist>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>nvidia.${PRODUCT_NAME}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2014 Simon Schirm. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,786 @@
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#ifndef __glut_h__
#define __glut_h__
/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998, 2000, 2006. */
/* This program is freely distributable without licensing fees and is
provided without guarantee or warrantee expressed or implied. This
program is -not- in the public domain. */
#ifdef _WIN32
/* GLUT 3.7 now tries to avoid including <windows.h>
to avoid name space pollution, but Win32's <GL/gl.h>
needs APIENTRY and WINGDIAPI defined properly. */
# if 0
/* This would put tons of macros in our clean name space. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# else
/* XXX This is from Win32's <windef.h> */
# ifndef APIENTRY
# define GLUT_APIENTRY_DEFINED
/* Cygwin and MingW32 are two free GNU-based Open Source compilation
environments for Win32. Note that __CYGWIN32__ is deprecated
in favor of simply __CYGWIN__. */
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
# ifdef i386
# define APIENTRY __attribute__ ((stdcall))
# else
# define APIENTRY
# endif
# else
# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
# define APIENTRY __stdcall
# else
# define APIENTRY
# endif
# endif
# endif
/* XXX This is from Win32's <winnt.h> */
# ifndef CALLBACK
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
# define CALLBACK __attribute__ ((stdcall))
# else
# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
# define CALLBACK __stdcall
# else
# define CALLBACK
# endif
# endif
# endif
/* XXX This is from Win32's <wingdi.h> and <winnt.h> */
# ifndef WINGDIAPI
# define GLUT_WINGDIAPI_DEFINED
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
# define WINGDIAPI
# else
# define WINGDIAPI __declspec(dllimport)
# endif
# endif
# if defined(__MINGW32__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
/* Rely on Cygwin32/MingW32 <stddef.h> to set wchar_t. */
/* XXX Warning. The Cygwin32/MingW32 definition for wchar_t
is an "int" instead of the "short" used by Windows. */
# include <stddef.h>
# else
/* XXX This is from Win32's <ctype.h> */
# ifndef _WCHAR_T_DEFINED
typedef unsigned short wchar_t;
# define _WCHAR_T_DEFINED
# endif
# endif
# endif
/* To disable automatic library usage for GLUT, define GLUT_NO_LIB_PRAGMA
in your compile preprocessor options. */
# if !defined(GLUT_BUILDING_LIB) && !defined(GLUT_NO_LIB_PRAGMA)
# pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */
# pragma comment (lib, "user32.lib") /* link with Windows User lib */
# pragma comment (lib, "gdi32.lib") /* link with Windows GDI lib */
/* To enable automatic SGI OpenGL for Windows library usage for GLUT,
define GLUT_USE_SGI_OPENGL in your compile preprocessor options. */
# ifdef GLUT_USE_SGI_OPENGL
# pragma comment (lib, "opengl.lib") /* link with SGI OpenGL for Windows lib */
# pragma comment (lib, "glu.lib") /* link with SGI OpenGL Utility lib */
# if defined(GLUT_STATIC_LIB)
# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */
# else
# pragma comment (lib, "glut.lib") /* link with Win32 GLUT lib */
# endif
# else
# pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */
# pragma comment (lib, "glu32.lib") /* link with Microsoft OpenGL Utility lib */
# if defined(GLUT_STATIC_LIB)
# pragma comment (lib, "glutstatic.lib") /* link with static Win32 GLUT lib */
# else
# pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */
# endif
# endif
# endif
/* To disable supression of annoying warnings about floats being promoted
to doubles, define GLUT_NO_WARNING_DISABLE in your compile preprocessor
options. */
# if defined(_MSC_VER) && !defined(GLUT_NO_WARNING_DISABLE)
# pragma warning (disable:4244) /* Disable bogus VC++ 4.2 conversion warnings. */
# pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */
# endif
/* Win32 has an annoying issue where there are multiple C run-time
libraries (CRTs). If the executable is linked with a different CRT
from the GLUT DLL, the GLUT DLL will not share the same CRT static
data seen by the executable. In particular, atexit callbacks registered
in the executable will not be called if GLUT calls its (different)
exit routine). GLUT is typically built with the
"/MD" option (the CRT with multithreading DLL support), but the Visual
C++ linker default is "/ML" (the single threaded CRT).
One workaround to this issue is requiring users to always link with
the same CRT as GLUT is compiled with. That requires users supply a
non-standard option. GLUT 3.7 has its own built-in workaround where
the executable's "exit" function pointer is covertly passed to GLUT.
GLUT then calls the executable's exit function pointer to ensure that
any "atexit" calls registered by the application are called if GLUT
needs to exit.
Note that the __glut*WithExit routines should NEVER be called directly.
To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
/* XXX This is from Win32's <process.h> */
# if !defined(_MSC_VER) && !defined(__cdecl)
/* Define __cdecl for non-Microsoft compilers. */
# define __cdecl
# define GLUT_DEFINED___CDECL
# endif
# ifndef _CRTIMP
# ifdef _NTSDK
/* Definition compatible with NT SDK */
# define _CRTIMP
# else
/* Current definition */
# ifdef _DLL
# define _CRTIMP __declspec(dllimport)
# else
# define _CRTIMP
# endif
# endif
# define GLUT_DEFINED__CRTIMP
# endif
/* GLUT API entry point declarations for Win32. */
# ifdef GLUT_BUILDING_LIB
/* MSDN article 835326 says "When you build a DLL by using the 64-bit
version of the Microsoft Visual C++ Compiler and Linker, you may
receive Linker error number LNK4197 if a function has been declared
for export more than one time." GLUT builds with glut.def that
declares GLUT's EXPORTS list so do not use __declspec(dllexport)
to keep 64-bit compiler happy. */
# define GLUTAPI /*__declspec(dllexport)*/
# else
# ifdef _DLL
# define GLUTAPI __declspec(dllimport)
# else
# define GLUTAPI extern
# endif
# endif
/* GLUT callback calling convention for Win32. */
# define GLUTCALLBACK __cdecl
# if (_MSC_VER >= 800) || defined(__MINGW32__) || defined(_STDCALL_SUPPORTED) || defined(__CYGWIN32__)
# define GLUTAPIENTRY __stdcall
# else
# define GLUTAPIENTRY
# endif
#endif /* _WIN32 */
#include <GL/gl.h>
#include <GL/glu.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
# ifndef GLUT_BUILDING_LIB
# if __BORLANDC__
# if defined(_BUILDRTLDLL)
void __cdecl __export exit(int __status);
# else
void __cdecl exit(int __status);
# endif
# else
# if _MSC_VER >= 1200
extern _CRTIMP __declspec(noreturn) void __cdecl exit(int);
# else
extern _CRTIMP void __cdecl exit(int);
# endif
# endif
# endif
#else
/* non-Win32 case. */
/* Define APIENTRY and CALLBACK to nothing if we aren't on Win32. */
# define APIENTRY
# define GLUT_APIENTRY_DEFINED
# define CALLBACK
/* Define GLUTAPI and GLUTCALLBACK as below if we aren't on Win32. */
# define GLUTAPI extern
# define GLUTAPIENTRY
# define GLUTCALLBACK
/* Prototype exit for the non-Win32 case (see above). */
# ifdef __GNUC__
extern void exit(int __status) __attribute__((__noreturn__));
# else
extern void exit(int);
# endif
#endif
/**
GLUT API revision history:
GLUT_API_VERSION is updated to reflect incompatible GLUT
API changes (interface changes, semantic changes, deletions,
or additions).
GLUT_API_VERSION=1 First public release of GLUT. 11/29/94
GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling,
extension. Supports new input devices like tablet, dial and button
box, and Spaceball. Easy to query OpenGL extensions.
GLUT_API_VERSION=3 glutMenuStatus added.
GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer,
glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic
video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc,
glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat,
glutJoystickFunc, glutForceJoystickFunc, glutStrokeWidthf,
glutStrokeLengthf (NOT FINALIZED!).
**/
#ifndef GLUT_API_VERSION /* allow this to be overriden */
#define GLUT_API_VERSION 3
#endif
/**
GLUT implementation revision history:
GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT
API revisions and implementation revisions (ie, bug fixes).
GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of
GLUT Xlib-based implementation. 11/29/94
GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of
GLUT Xlib-based implementation providing GLUT version 2
interfaces.
GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95
GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95
GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95
GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96
GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner
and video resize. 1/3/97
GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines.
GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release.
GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling.
GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 beta with GameGLUT support.
GLUT_XLIB_IMPLEMENTATION=14 mjk's GLUT 3.7 beta with f90gl friend interface.
GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa <GL/glut.h>
GLUT_XLIB_IMPLEMENTATION=16 mjk's early GLUT 3.8
GLUT_XLIB_IMPLEMENTATION=17 mjk's GLUT 3.8 with glutStrokeWidthf and glutStrokeLengthf
**/
#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */
#define GLUT_XLIB_IMPLEMENTATION 17
#endif
/* Display mode bit masks. */
#define GLUT_RGB 0
#define GLUT_RGBA GLUT_RGB
#define GLUT_INDEX 1
#define GLUT_SINGLE 0
#define GLUT_DOUBLE 2
#define GLUT_ACCUM 4
#define GLUT_ALPHA 8
#define GLUT_DEPTH 16
#define GLUT_STENCIL 32
#if (GLUT_API_VERSION >= 2)
#define GLUT_MULTISAMPLE 128
#define GLUT_STEREO 256
#endif
#if (GLUT_API_VERSION >= 3)
#define GLUT_LUMINANCE 512
#endif
/* Mouse buttons. */
#define GLUT_LEFT_BUTTON 0
#define GLUT_MIDDLE_BUTTON 1
#define GLUT_RIGHT_BUTTON 2
/* Mouse button state. */
#define GLUT_DOWN 0
#define GLUT_UP 1
#if (GLUT_API_VERSION >= 2)
/* function keys */
#define GLUT_KEY_F1 1
#define GLUT_KEY_F2 2
#define GLUT_KEY_F3 3
#define GLUT_KEY_F4 4
#define GLUT_KEY_F5 5
#define GLUT_KEY_F6 6
#define GLUT_KEY_F7 7
#define GLUT_KEY_F8 8
#define GLUT_KEY_F9 9
#define GLUT_KEY_F10 10
#define GLUT_KEY_F11 11
#define GLUT_KEY_F12 12
/* directional keys */
#define GLUT_KEY_LEFT 100
#define GLUT_KEY_UP 101
#define GLUT_KEY_RIGHT 102
#define GLUT_KEY_DOWN 103
#define GLUT_KEY_PAGE_UP 104
#define GLUT_KEY_PAGE_DOWN 105
#define GLUT_KEY_HOME 106
#define GLUT_KEY_END 107
#define GLUT_KEY_INSERT 108
#endif
/* Entry/exit state. */
#define GLUT_LEFT 0
#define GLUT_ENTERED 1
/* Menu usage state. */
#define GLUT_MENU_NOT_IN_USE 0
#define GLUT_MENU_IN_USE 1
/* Visibility state. */
#define GLUT_NOT_VISIBLE 0
#define GLUT_VISIBLE 1
/* Window status state. */
#define GLUT_HIDDEN 0
#define GLUT_FULLY_RETAINED 1
#define GLUT_PARTIALLY_RETAINED 2
#define GLUT_FULLY_COVERED 3
/* Color index component selection values. */
#define GLUT_RED 0
#define GLUT_GREEN 1
#define GLUT_BLUE 2
#ifdef _WIN32
/* Stroke font constants (use these in GLUT program). */
#define GLUT_STROKE_ROMAN ((void*)0)
#define GLUT_STROKE_MONO_ROMAN ((void*)1)
/* Bitmap font constants (use these in GLUT program). */
#define GLUT_BITMAP_9_BY_15 ((void*)2)
#define GLUT_BITMAP_8_BY_13 ((void*)3)
#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4)
#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5)
#if (GLUT_API_VERSION >= 3)
#define GLUT_BITMAP_HELVETICA_10 ((void*)6)
#define GLUT_BITMAP_HELVETICA_12 ((void*)7)
#define GLUT_BITMAP_HELVETICA_18 ((void*)8)
#endif
#else
/* Stroke font opaque addresses (use constants instead in source code). */
GLUTAPI void *glutStrokeRoman;
GLUTAPI void *glutStrokeMonoRoman;
/* Stroke font constants (use these in GLUT program). */
#define GLUT_STROKE_ROMAN (&glutStrokeRoman)
#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman)
/* Bitmap font opaque addresses (use constants instead in source code). */
GLUTAPI void *glutBitmap9By15;
GLUTAPI void *glutBitmap8By13;
GLUTAPI void *glutBitmapTimesRoman10;
GLUTAPI void *glutBitmapTimesRoman24;
GLUTAPI void *glutBitmapHelvetica10;
GLUTAPI void *glutBitmapHelvetica12;
GLUTAPI void *glutBitmapHelvetica18;
/* Bitmap font constants (use these in GLUT program). */
#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15)
#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13)
#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10)
#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24)
#if (GLUT_API_VERSION >= 3)
#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10)
#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12)
#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18)
#endif
#endif
/* glutGet parameters. */
#define GLUT_WINDOW_X ((GLenum) 100)
#define GLUT_WINDOW_Y ((GLenum) 101)
#define GLUT_WINDOW_WIDTH ((GLenum) 102)
#define GLUT_WINDOW_HEIGHT ((GLenum) 103)
#define GLUT_WINDOW_BUFFER_SIZE ((GLenum) 104)
#define GLUT_WINDOW_STENCIL_SIZE ((GLenum) 105)
#define GLUT_WINDOW_DEPTH_SIZE ((GLenum) 106)
#define GLUT_WINDOW_RED_SIZE ((GLenum) 107)
#define GLUT_WINDOW_GREEN_SIZE ((GLenum) 108)
#define GLUT_WINDOW_BLUE_SIZE ((GLenum) 109)
#define GLUT_WINDOW_ALPHA_SIZE ((GLenum) 110)
#define GLUT_WINDOW_ACCUM_RED_SIZE ((GLenum) 111)
#define GLUT_WINDOW_ACCUM_GREEN_SIZE ((GLenum) 112)
#define GLUT_WINDOW_ACCUM_BLUE_SIZE ((GLenum) 113)
#define GLUT_WINDOW_ACCUM_ALPHA_SIZE ((GLenum) 114)
#define GLUT_WINDOW_DOUBLEBUFFER ((GLenum) 115)
#define GLUT_WINDOW_RGBA ((GLenum) 116)
#define GLUT_WINDOW_PARENT ((GLenum) 117)
#define GLUT_WINDOW_NUM_CHILDREN ((GLenum) 118)
#define GLUT_WINDOW_COLORMAP_SIZE ((GLenum) 119)
#if (GLUT_API_VERSION >= 2)
#define GLUT_WINDOW_NUM_SAMPLES ((GLenum) 120)
#define GLUT_WINDOW_STEREO ((GLenum) 121)
#endif
#if (GLUT_API_VERSION >= 3)
#define GLUT_WINDOW_CURSOR ((GLenum) 122)
#endif
#define GLUT_SCREEN_WIDTH ((GLenum) 200)
#define GLUT_SCREEN_HEIGHT ((GLenum) 201)
#define GLUT_SCREEN_WIDTH_MM ((GLenum) 202)
#define GLUT_SCREEN_HEIGHT_MM ((GLenum) 203)
#define GLUT_MENU_NUM_ITEMS ((GLenum) 300)
#define GLUT_DISPLAY_MODE_POSSIBLE ((GLenum) 400)
#define GLUT_INIT_WINDOW_X ((GLenum) 500)
#define GLUT_INIT_WINDOW_Y ((GLenum) 501)
#define GLUT_INIT_WINDOW_WIDTH ((GLenum) 502)
#define GLUT_INIT_WINDOW_HEIGHT ((GLenum) 503)
#define GLUT_INIT_DISPLAY_MODE ((GLenum) 504)
#if (GLUT_API_VERSION >= 2)
#define GLUT_ELAPSED_TIME ((GLenum) 700)
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
#define GLUT_WINDOW_FORMAT_ID ((GLenum) 123)
#endif
#if (GLUT_API_VERSION >= 2)
/* glutDeviceGet parameters. */
#define GLUT_HAS_KEYBOARD ((GLenum) 600)
#define GLUT_HAS_MOUSE ((GLenum) 601)
#define GLUT_HAS_SPACEBALL ((GLenum) 602)
#define GLUT_HAS_DIAL_AND_BUTTON_BOX ((GLenum) 603)
#define GLUT_HAS_TABLET ((GLenum) 604)
#define GLUT_NUM_MOUSE_BUTTONS ((GLenum) 605)
#define GLUT_NUM_SPACEBALL_BUTTONS ((GLenum) 606)
#define GLUT_NUM_BUTTON_BOX_BUTTONS ((GLenum) 607)
#define GLUT_NUM_DIALS ((GLenum) 608)
#define GLUT_NUM_TABLET_BUTTONS ((GLenum) 609)
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
#define GLUT_DEVICE_IGNORE_KEY_REPEAT ((GLenum) 610)
#define GLUT_DEVICE_KEY_REPEAT ((GLenum) 611)
#define GLUT_HAS_JOYSTICK ((GLenum) 612)
#define GLUT_OWNS_JOYSTICK ((GLenum) 613)
#define GLUT_JOYSTICK_BUTTONS ((GLenum) 614)
#define GLUT_JOYSTICK_AXES ((GLenum) 615)
#define GLUT_JOYSTICK_POLL_RATE ((GLenum) 616)
#endif
#if (GLUT_API_VERSION >= 3)
/* glutLayerGet parameters. */
#define GLUT_OVERLAY_POSSIBLE ((GLenum) 800)
#define GLUT_LAYER_IN_USE ((GLenum) 801)
#define GLUT_HAS_OVERLAY ((GLenum) 802)
#define GLUT_TRANSPARENT_INDEX ((GLenum) 803)
#define GLUT_NORMAL_DAMAGED ((GLenum) 804)
#define GLUT_OVERLAY_DAMAGED ((GLenum) 805)
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
/* glutVideoResizeGet parameters. */
#define GLUT_VIDEO_RESIZE_POSSIBLE ((GLenum) 900)
#define GLUT_VIDEO_RESIZE_IN_USE ((GLenum) 901)
#define GLUT_VIDEO_RESIZE_X_DELTA ((GLenum) 902)
#define GLUT_VIDEO_RESIZE_Y_DELTA ((GLenum) 903)
#define GLUT_VIDEO_RESIZE_WIDTH_DELTA ((GLenum) 904)
#define GLUT_VIDEO_RESIZE_HEIGHT_DELTA ((GLenum) 905)
#define GLUT_VIDEO_RESIZE_X ((GLenum) 906)
#define GLUT_VIDEO_RESIZE_Y ((GLenum) 907)
#define GLUT_VIDEO_RESIZE_WIDTH ((GLenum) 908)
#define GLUT_VIDEO_RESIZE_HEIGHT ((GLenum) 909)
#endif
/* glutUseLayer parameters. */
#define GLUT_NORMAL ((GLenum) 0)
#define GLUT_OVERLAY ((GLenum) 1)
/* glutGetModifiers return mask. */
#define GLUT_ACTIVE_SHIFT 1
#define GLUT_ACTIVE_CTRL 2
#define GLUT_ACTIVE_ALT 4
/* glutSetCursor parameters. */
/* Basic arrows. */
#define GLUT_CURSOR_RIGHT_ARROW 0
#define GLUT_CURSOR_LEFT_ARROW 1
/* Symbolic cursor shapes. */
#define GLUT_CURSOR_INFO 2
#define GLUT_CURSOR_DESTROY 3
#define GLUT_CURSOR_HELP 4
#define GLUT_CURSOR_CYCLE 5
#define GLUT_CURSOR_SPRAY 6
#define GLUT_CURSOR_WAIT 7
#define GLUT_CURSOR_TEXT 8
#define GLUT_CURSOR_CROSSHAIR 9
/* Directional cursors. */
#define GLUT_CURSOR_UP_DOWN 10
#define GLUT_CURSOR_LEFT_RIGHT 11
/* Sizing cursors. */
#define GLUT_CURSOR_TOP_SIDE 12
#define GLUT_CURSOR_BOTTOM_SIDE 13
#define GLUT_CURSOR_LEFT_SIDE 14
#define GLUT_CURSOR_RIGHT_SIDE 15
#define GLUT_CURSOR_TOP_LEFT_CORNER 16
#define GLUT_CURSOR_TOP_RIGHT_CORNER 17
#define GLUT_CURSOR_BOTTOM_RIGHT_CORNER 18
#define GLUT_CURSOR_BOTTOM_LEFT_CORNER 19
/* Inherit from parent window. */
#define GLUT_CURSOR_INHERIT 100
/* Blank cursor. */
#define GLUT_CURSOR_NONE 101
/* Fullscreen crosshair (if available). */
#define GLUT_CURSOR_FULL_CROSSHAIR 102
#endif
/* GLUT initialization sub-API. */
GLUTAPI void GLUTAPIENTRY glutInit(int *argcp, char **argv);
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
GLUTAPI void GLUTAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
#ifndef GLUT_BUILDING_LIB
static void GLUTAPIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
#define glutInit glutInit_ATEXIT_HACK
#endif
#endif
GLUTAPI void GLUTAPIENTRY glutInitDisplayMode(unsigned int mode);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI void GLUTAPIENTRY glutInitDisplayString(const char *string);
#endif
GLUTAPI void GLUTAPIENTRY glutInitWindowPosition(int x, int y);
GLUTAPI void GLUTAPIENTRY glutInitWindowSize(int width, int height);
GLUTAPI void GLUTAPIENTRY glutMainLoop(void);
/* GLUT window sub-API. */
GLUTAPI int GLUTAPIENTRY glutCreateWindow(const char *title);
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
GLUTAPI int GLUTAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
#ifndef GLUT_BUILDING_LIB
static int GLUTAPIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
#endif
#endif
GLUTAPI int GLUTAPIENTRY glutCreateSubWindow(int win, int x, int y, int width, int height);
GLUTAPI void GLUTAPIENTRY glutDestroyWindow(int win);
GLUTAPI void GLUTAPIENTRY glutPostRedisplay(void);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
GLUTAPI void GLUTAPIENTRY glutPostWindowRedisplay(int win);
#endif
GLUTAPI void GLUTAPIENTRY glutSwapBuffers(void);
GLUTAPI int GLUTAPIENTRY glutGetWindow(void);
GLUTAPI void GLUTAPIENTRY glutSetWindow(int win);
GLUTAPI void GLUTAPIENTRY glutSetWindowTitle(const char *title);
GLUTAPI void GLUTAPIENTRY glutSetIconTitle(const char *title);
GLUTAPI void GLUTAPIENTRY glutPositionWindow(int x, int y);
GLUTAPI void GLUTAPIENTRY glutReshapeWindow(int width, int height);
GLUTAPI void GLUTAPIENTRY glutPopWindow(void);
GLUTAPI void GLUTAPIENTRY glutPushWindow(void);
GLUTAPI void GLUTAPIENTRY glutIconifyWindow(void);
GLUTAPI void GLUTAPIENTRY glutShowWindow(void);
GLUTAPI void GLUTAPIENTRY glutHideWindow(void);
#if (GLUT_API_VERSION >= 3)
GLUTAPI void GLUTAPIENTRY glutFullScreen(void);
GLUTAPI void GLUTAPIENTRY glutSetCursor(int cursor);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI void GLUTAPIENTRY glutWarpPointer(int x, int y);
#endif
/* GLUT overlay sub-API. */
GLUTAPI void GLUTAPIENTRY glutEstablishOverlay(void);
GLUTAPI void GLUTAPIENTRY glutRemoveOverlay(void);
GLUTAPI void GLUTAPIENTRY glutUseLayer(GLenum layer);
GLUTAPI void GLUTAPIENTRY glutPostOverlayRedisplay(void);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 11)
GLUTAPI void GLUTAPIENTRY glutPostWindowOverlayRedisplay(int win);
#endif
GLUTAPI void GLUTAPIENTRY glutShowOverlay(void);
GLUTAPI void GLUTAPIENTRY glutHideOverlay(void);
#endif
/* GLUT menu sub-API. */
GLUTAPI int GLUTAPIENTRY glutCreateMenu(void (GLUTCALLBACK *func)(int));
#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
GLUTAPI int GLUTAPIENTRY __glutCreateMenuWithExit(void (GLUTCALLBACK *func)(int), void (__cdecl *exitfunc)(int));
#ifndef GLUT_BUILDING_LIB
static int GLUTAPIENTRY glutCreateMenu_ATEXIT_HACK(void (GLUTCALLBACK *func)(int)) { return __glutCreateMenuWithExit(func, exit); }
#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
#endif
#endif
GLUTAPI void GLUTAPIENTRY glutDestroyMenu(int menu);
GLUTAPI int GLUTAPIENTRY glutGetMenu(void);
GLUTAPI void GLUTAPIENTRY glutSetMenu(int menu);
GLUTAPI void GLUTAPIENTRY glutAddMenuEntry(const char *label, int value);
GLUTAPI void GLUTAPIENTRY glutAddSubMenu(const char *label, int submenu);
GLUTAPI void GLUTAPIENTRY glutChangeToMenuEntry(int item, const char *label, int value);
GLUTAPI void GLUTAPIENTRY glutChangeToSubMenu(int item, const char *label, int submenu);
GLUTAPI void GLUTAPIENTRY glutRemoveMenuItem(int item);
GLUTAPI void GLUTAPIENTRY glutAttachMenu(int button);
GLUTAPI void GLUTAPIENTRY glutDetachMenu(int button);
/* GLUT window callback sub-API. */
GLUTAPI void GLUTAPIENTRY glutDisplayFunc(void (GLUTCALLBACK *func)(void));
GLUTAPI void GLUTAPIENTRY glutReshapeFunc(void (GLUTCALLBACK *func)(int width, int height));
GLUTAPI void GLUTAPIENTRY glutKeyboardFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutMouseFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
GLUTAPI void GLUTAPIENTRY glutMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
GLUTAPI void GLUTAPIENTRY glutPassiveMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
GLUTAPI void GLUTAPIENTRY glutEntryFunc(void (GLUTCALLBACK *func)(int state));
GLUTAPI void GLUTAPIENTRY glutVisibilityFunc(void (GLUTCALLBACK *func)(int state));
GLUTAPI void GLUTAPIENTRY glutIdleFunc(void (GLUTCALLBACK *func)(void));
GLUTAPI void GLUTAPIENTRY glutTimerFunc(unsigned int millis, void (GLUTCALLBACK *func)(int value), int value);
GLUTAPI void GLUTAPIENTRY glutMenuStateFunc(void (GLUTCALLBACK *func)(int state));
#if (GLUT_API_VERSION >= 2)
GLUTAPI void GLUTAPIENTRY glutSpecialFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutSpaceballMotionFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
GLUTAPI void GLUTAPIENTRY glutSpaceballRotateFunc(void (GLUTCALLBACK *func)(int x, int y, int z));
GLUTAPI void GLUTAPIENTRY glutSpaceballButtonFunc(void (GLUTCALLBACK *func)(int button, int state));
GLUTAPI void GLUTAPIENTRY glutButtonBoxFunc(void (GLUTCALLBACK *func)(int button, int state));
GLUTAPI void GLUTAPIENTRY glutDialsFunc(void (GLUTCALLBACK *func)(int dial, int value));
GLUTAPI void GLUTAPIENTRY glutTabletMotionFunc(void (GLUTCALLBACK *func)(int x, int y));
GLUTAPI void GLUTAPIENTRY glutTabletButtonFunc(void (GLUTCALLBACK *func)(int button, int state, int x, int y));
#if (GLUT_API_VERSION >= 3)
GLUTAPI void GLUTAPIENTRY glutMenuStatusFunc(void (GLUTCALLBACK *func)(int status, int x, int y));
GLUTAPI void GLUTAPIENTRY glutOverlayDisplayFunc(void (GLUTCALLBACK *func)(void));
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI void GLUTAPIENTRY glutWindowStatusFunc(void (GLUTCALLBACK *func)(int state));
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
GLUTAPI void GLUTAPIENTRY glutKeyboardUpFunc(void (GLUTCALLBACK *func)(unsigned char key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutSpecialUpFunc(void (GLUTCALLBACK *func)(int key, int x, int y));
GLUTAPI void GLUTAPIENTRY glutJoystickFunc(void (GLUTCALLBACK *func)(unsigned int buttonMask, int x, int y, int z), int pollInterval);
#endif
#endif
#endif
/* GLUT color index sub-API. */
GLUTAPI void GLUTAPIENTRY glutSetColor(int, GLfloat red, GLfloat green, GLfloat blue);
GLUTAPI GLfloat GLUTAPIENTRY glutGetColor(int ndx, int component);
GLUTAPI void GLUTAPIENTRY glutCopyColormap(int win);
/* GLUT state retrieval sub-API. */
GLUTAPI int GLUTAPIENTRY glutGet(GLenum type);
GLUTAPI int GLUTAPIENTRY glutDeviceGet(GLenum type);
#if (GLUT_API_VERSION >= 2)
/* GLUT extension support sub-API */
GLUTAPI int GLUTAPIENTRY glutExtensionSupported(const char *name);
#endif
#if (GLUT_API_VERSION >= 3)
GLUTAPI int GLUTAPIENTRY glutGetModifiers(void);
GLUTAPI int GLUTAPIENTRY glutLayerGet(GLenum type);
#endif
/* GLUT font sub-API */
GLUTAPI void GLUTAPIENTRY glutBitmapCharacter(void *font, int character);
GLUTAPI int GLUTAPIENTRY glutBitmapWidth(void *font, int character);
GLUTAPI void GLUTAPIENTRY glutStrokeCharacter(void *font, int character);
GLUTAPI int GLUTAPIENTRY glutStrokeWidth(void *font, int character);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
GLUTAPI int GLUTAPIENTRY glutBitmapLength(void *font, const unsigned char *string);
GLUTAPI int GLUTAPIENTRY glutStrokeLength(void *font, const unsigned char *string);
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 17)
GLUTAPI float GLUTAPIENTRY glutStrokeWidthf(void *font, int character);
GLUTAPI float GLUTAPIENTRY glutStrokeLengthf(void *font, const unsigned char *string);
#endif
/* GLUT pre-built models sub-API */
GLUTAPI void GLUTAPIENTRY glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
GLUTAPI void GLUTAPIENTRY glutWireCube(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutSolidCube(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutWireTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
GLUTAPI void GLUTAPIENTRY glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, GLint sides, GLint rings);
GLUTAPI void GLUTAPIENTRY glutWireDodecahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidDodecahedron(void);
GLUTAPI void GLUTAPIENTRY glutWireTeapot(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutSolidTeapot(GLdouble size);
GLUTAPI void GLUTAPIENTRY glutWireOctahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidOctahedron(void);
GLUTAPI void GLUTAPIENTRY glutWireTetrahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidTetrahedron(void);
GLUTAPI void GLUTAPIENTRY glutWireIcosahedron(void);
GLUTAPI void GLUTAPIENTRY glutSolidIcosahedron(void);
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 9)
/* GLUT video resize sub-API. */
GLUTAPI int GLUTAPIENTRY glutVideoResizeGet(GLenum param);
GLUTAPI void GLUTAPIENTRY glutSetupVideoResizing(void);
GLUTAPI void GLUTAPIENTRY glutStopVideoResizing(void);
GLUTAPI void GLUTAPIENTRY glutVideoResize(int x, int y, int width, int height);
GLUTAPI void GLUTAPIENTRY glutVideoPan(int x, int y, int width, int height);
/* GLUT debugging sub-API. */
GLUTAPI void GLUTAPIENTRY glutReportErrors(void);
#endif
#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13)
/* GLUT device control sub-API. */
/* glutSetKeyRepeat modes. */
#define GLUT_KEY_REPEAT_OFF 0
#define GLUT_KEY_REPEAT_ON 1
#define GLUT_KEY_REPEAT_DEFAULT 2
/* Joystick button masks. */
#define GLUT_JOYSTICK_BUTTON_A 1
#define GLUT_JOYSTICK_BUTTON_B 2
#define GLUT_JOYSTICK_BUTTON_C 4
#define GLUT_JOYSTICK_BUTTON_D 8
GLUTAPI void GLUTAPIENTRY glutIgnoreKeyRepeat(int ignore);
GLUTAPI void GLUTAPIENTRY glutSetKeyRepeat(int repeatMode);
GLUTAPI void GLUTAPIENTRY glutForceJoystickFunc(void);
/* GLUT game mode sub-API. */
/* glutGameModeGet. */
#define GLUT_GAME_MODE_ACTIVE ((GLenum) 0)
#define GLUT_GAME_MODE_POSSIBLE ((GLenum) 1)
#define GLUT_GAME_MODE_WIDTH ((GLenum) 2)
#define GLUT_GAME_MODE_HEIGHT ((GLenum) 3)
#define GLUT_GAME_MODE_PIXEL_DEPTH ((GLenum) 4)
#define GLUT_GAME_MODE_REFRESH_RATE ((GLenum) 5)
#define GLUT_GAME_MODE_DISPLAY_CHANGED ((GLenum) 6)
GLUTAPI void GLUTAPIENTRY glutGameModeString(const char *string);
GLUTAPI int GLUTAPIENTRY glutEnterGameMode(void);
GLUTAPI void GLUTAPIENTRY glutLeaveGameMode(void);
GLUTAPI int GLUTAPIENTRY glutGameModeGet(GLenum mode);
#endif
#ifdef __cplusplus
}
#endif
#ifdef GLUT_APIENTRY_DEFINED
# undef GLUT_APIENTRY_DEFINED
# undef APIENTRY
#endif
#ifdef GLUT_WINGDIAPI_DEFINED
# undef GLUT_WINGDIAPI_DEFINED
# undef WINGDIAPI
#endif
#ifdef GLUT_DEFINED___CDECL
# undef GLUT_DEFINED___CDECL
# undef __cdecl
#endif
#ifdef GLUT_DEFINED__CRTIMP
# undef GLUT_DEFINED__CRTIMP
# undef _CRTIMP
#endif
#endif /* __glut_h__ */

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,610 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet demonstrates the use of articulations.
// ****************************************************************************
#include <ctype.h>
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#define USE_REDUCED_COORDINATE_ARTICULATION 1
#define CREATE_SCISSOR_LIFT 1
#if CREATE_SCISSOR_LIFT
bool gCreateLiftScene = true;
#else
bool gCreateLiftScene = false;
#endif
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
#if USE_REDUCED_COORDINATE_ARTICULATION
PxArticulationReducedCoordinate* gArticulation = NULL;
PxArticulationJointReducedCoordinate* gDriveJoint = NULL;
#else
PxArticulation* gArticulation = NULL;
#endif
#if USE_REDUCED_COORDINATE_ARTICULATION
PxFilterFlags scissorFilter(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(constantBlock);
PX_UNUSED(constantBlockSize);
if (filterData0.word2 != 0 && filterData0.word2 == filterData1.word2)
return PxFilterFlag::eKILL;
pairFlags |= PxPairFlag::eCONTACT_DEFAULT;
return PxFilterFlag::eDEFAULT;
}
void createScissorLift()
{
const PxReal runnerLength = 2.f;
const PxReal placementDistance = 1.8f;
const PxReal cosAng = (placementDistance) / (runnerLength);
const PxReal angle = PxAcos(cosAng);
const PxReal sinAng = PxSin(angle);
const PxQuat leftRot(-angle, PxVec3(1.f, 0.f, 0.f));
const PxQuat rightRot(angle, PxVec3(1.f, 0.f, 0.f));
//(1) Create base...
PxArticulationLink* base = gArticulation->createLink(NULL, PxTransform(PxVec3(0.f, 0.25f, 0.f)));
PxRigidActorExt::createExclusiveShape(*base, PxBoxGeometry(0.5f, 0.25f, 1.5f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*base, 3.f);
//Now create the slider and fixed joints...
gArticulation->setSolverIterationCounts(32);
PxArticulationLink* leftRoot = gArticulation->createLink(base, PxTransform(PxVec3(0.f, 0.55f, -0.9f)));
PxRigidActorExt::createExclusiveShape(*leftRoot, PxBoxGeometry(0.5f, 0.05f, 0.05f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*leftRoot, 1.f);
PxArticulationLink* rightRoot = gArticulation->createLink(base, PxTransform(PxVec3(0.f, 0.55f, 0.9f)));
PxRigidActorExt::createExclusiveShape(*rightRoot, PxBoxGeometry(0.5f, 0.05f, 0.05f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*rightRoot, 1.f);
PxArticulationJointReducedCoordinate* joint = static_cast<PxArticulationJointReducedCoordinate*>(leftRoot->getInboundJoint());
joint->setJointType(PxArticulationJointType::eFIX);
joint->setParentPose(PxTransform(PxVec3(0.f, 0.25f, -0.9f)));
joint->setChildPose(PxTransform(PxVec3(0.f, -0.05f, 0.f)));
//Set up the drive joint...
gDriveJoint = static_cast<PxArticulationJointReducedCoordinate*>(rightRoot->getInboundJoint());
gDriveJoint->setJointType(PxArticulationJointType::ePRISMATIC);
gDriveJoint->setMotion(PxArticulationAxis::eZ, PxArticulationMotion::eLIMITED);
gDriveJoint->setLimit(PxArticulationAxis::eZ, -1.4f, 0.2f);
gDriveJoint->setDrive(PxArticulationAxis::eZ, 100000.f, 0.f, PX_MAX_F32);
gDriveJoint->setParentPose(PxTransform(PxVec3(0.f, 0.25f, 0.9f)));
gDriveJoint->setChildPose(PxTransform(PxVec3(0.f, -0.05f, 0.f)));
const PxU32 linkHeight = 3;
PxArticulationLink* currLeft = leftRoot, *currRight = rightRoot;
PxQuat rightParentRot(PxIdentity);
PxQuat leftParentRot(PxIdentity);
for (PxU32 i = 0; i < linkHeight; ++i)
{
const PxVec3 pos(0.5f, 0.55f + 0.1f*(1 + i), 0.f);
PxArticulationLink* leftLink = gArticulation->createLink(currLeft, PxTransform(pos + PxVec3(0.f, sinAng*(2 * i + 1), 0.f), leftRot));
PxRigidActorExt::createExclusiveShape(*leftLink, PxBoxGeometry(0.05f, 0.05f, 1.f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*leftLink, 1.f);
const PxVec3 leftAnchorLocation = pos + PxVec3(0.f, sinAng*(2 * i), -0.9f);
joint = static_cast<PxArticulationJointReducedCoordinate*>(leftLink->getInboundJoint());
joint->setParentPose(PxTransform(currLeft->getGlobalPose().transformInv(leftAnchorLocation), leftParentRot));
joint->setChildPose(PxTransform(PxVec3(0.f, 0.f, -1.f), rightRot));
joint->setJointType(PxArticulationJointType::eREVOLUTE);
leftParentRot = leftRot;
joint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eLIMITED);
joint->setLimit(PxArticulationAxis::eTWIST, -PxPi, angle);
PxArticulationLink* rightLink = gArticulation->createLink(currRight, PxTransform(pos + PxVec3(0.f, sinAng*(2 * i + 1), 0.f), rightRot));
PxRigidActorExt::createExclusiveShape(*rightLink, PxBoxGeometry(0.05f, 0.05f, 1.f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*rightLink, 1.f);
const PxVec3 rightAnchorLocation = pos + PxVec3(0.f, sinAng*(2 * i), 0.9f);
joint = static_cast<PxArticulationJointReducedCoordinate*>(rightLink->getInboundJoint());
joint->setJointType(PxArticulationJointType::eREVOLUTE);
joint->setParentPose(PxTransform(currRight->getGlobalPose().transformInv(rightAnchorLocation), rightParentRot));
joint->setChildPose(PxTransform(PxVec3(0.f, 0.f, 1.f), leftRot));
joint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eLIMITED);
joint->setLimit(PxArticulationAxis::eTWIST, -angle, PxPi);
rightParentRot = rightRot;
PxD6Joint* d6joint = PxD6JointCreate(*gPhysics, leftLink, PxTransform(PxIdentity), rightLink, PxTransform(PxIdentity));
d6joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
currLeft = rightLink;
currRight = leftLink;
}
PxArticulationLink* leftTop = gArticulation->createLink(currLeft, currLeft->getGlobalPose().transform(PxTransform(PxVec3(-0.5f, 0.f, -1.0f), leftParentRot)));
PxRigidActorExt::createExclusiveShape(*leftTop, PxBoxGeometry(0.5f, 0.05f, 0.05f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*leftTop, 1.f);
PxArticulationLink* rightTop = gArticulation->createLink(currRight, currRight->getGlobalPose().transform(PxTransform(PxVec3(-0.5f, 0.f, 1.0f), rightParentRot)));
PxRigidActorExt::createExclusiveShape(*rightTop, PxCapsuleGeometry(0.05f, 0.8f), *gMaterial);
//PxRigidActorExt::createExclusiveShape(*rightTop, PxBoxGeometry(0.5f, 0.05f, 0.05f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*rightTop, 1.f);
joint = static_cast<PxArticulationJointReducedCoordinate*>(leftTop->getInboundJoint());
joint->setParentPose(PxTransform(PxVec3(0.f, 0.f, -1.f), currLeft->getGlobalPose().q.getConjugate()));
joint->setChildPose(PxTransform(PxVec3(0.5f, 0.f, 0.f), leftTop->getGlobalPose().q.getConjugate()));
joint->setJointType(PxArticulationJointType::eREVOLUTE);
joint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eFREE);
//joint->setDrive(PxArticulationAxis::eTWIST, 0.f, 10.f, PX_MAX_F32);
joint = static_cast<PxArticulationJointReducedCoordinate*>(rightTop->getInboundJoint());
joint->setParentPose(PxTransform(PxVec3(0.f, 0.f, 1.f), currRight->getGlobalPose().q.getConjugate()));
joint->setChildPose(PxTransform(PxVec3(0.5f, 0.f, 0.f), rightTop->getGlobalPose().q.getConjugate()));
joint->setJointType(PxArticulationJointType::eREVOLUTE);
joint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eFREE);
//joint->setDrive(PxArticulationAxis::eTWIST, 0.f, 10.f, PX_MAX_F32);
currLeft = leftRoot;
currRight = rightRoot;
rightParentRot = PxQuat(PxIdentity);
leftParentRot = PxQuat(PxIdentity);
for (PxU32 i = 0; i < linkHeight; ++i)
{
const PxVec3 pos(-0.5f, 0.55f + 0.1f*(1 + i), 0.f);
PxArticulationLink* leftLink = gArticulation->createLink(currLeft, PxTransform(pos + PxVec3(0.f, sinAng*(2 * i + 1), 0.f), leftRot));
PxRigidActorExt::createExclusiveShape(*leftLink, PxBoxGeometry(0.05f, 0.05f, 1.f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*leftLink, 1.f);
const PxVec3 leftAnchorLocation = pos + PxVec3(0.f, sinAng*(2 * i), -0.9f);
joint = static_cast<PxArticulationJointReducedCoordinate*>(leftLink->getInboundJoint());
joint->setJointType(PxArticulationJointType::eREVOLUTE);
joint->setParentPose(PxTransform(currLeft->getGlobalPose().transformInv(leftAnchorLocation), leftParentRot));
joint->setChildPose(PxTransform(PxVec3(0.f, 0.f, -1.f), rightRot));
leftParentRot = leftRot;
joint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eLIMITED);
joint->setLimit(PxArticulationAxis::eTWIST, -PxPi, angle);
PxArticulationLink* rightLink = gArticulation->createLink(currRight, PxTransform(pos + PxVec3(0.f, sinAng*(2 * i + 1), 0.f), rightRot));
PxRigidActorExt::createExclusiveShape(*rightLink, PxBoxGeometry(0.05f, 0.05f, 1.f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*rightLink, 1.f);
const PxVec3 rightAnchorLocation = pos + PxVec3(0.f, sinAng*(2 * i), 0.9f);
/*joint = PxD6JointCreate(getPhysics(), currRight, PxTransform(currRight->getGlobalPose().transformInv(rightAnchorLocation)),
rightLink, PxTransform(PxVec3(0.f, 0.f, 1.f)));*/
joint = static_cast<PxArticulationJointReducedCoordinate*>(rightLink->getInboundJoint());
joint->setParentPose(PxTransform(currRight->getGlobalPose().transformInv(rightAnchorLocation), rightParentRot));
joint->setJointType(PxArticulationJointType::eREVOLUTE);
joint->setChildPose(PxTransform(PxVec3(0.f, 0.f, 1.f), leftRot));
joint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eLIMITED);
joint->setLimit(PxArticulationAxis::eTWIST, -angle, PxPi);
rightParentRot = rightRot;
PxD6Joint* d6joint = PxD6JointCreate(*gPhysics, leftLink, PxTransform(PxIdentity), rightLink, PxTransform(PxIdentity));
d6joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
currLeft = rightLink;
currRight = leftLink;
}
PxD6Joint* d6joint = PxD6JointCreate(*gPhysics, currLeft, PxTransform(PxVec3(0.f, 0.f, -1.f)), leftTop, PxTransform(PxVec3(-0.5f, 0.f, 0.f)));
d6joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
d6joint = PxD6JointCreate(*gPhysics, currRight, PxTransform(PxVec3(0.f, 0.f, 1.f)), rightTop, PxTransform(PxVec3(-0.5f, 0.f, 0.f)));
d6joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
d6joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
const PxTransform topPose(PxVec3(0.f, leftTop->getGlobalPose().p.y + 0.15f, 0.f));
PxArticulationLink* top = gArticulation->createLink(leftTop, topPose);
PxRigidActorExt::createExclusiveShape(*top, PxBoxGeometry(0.5f, 0.1f, 1.5f), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*top, 1.f);
joint = static_cast<PxArticulationJointReducedCoordinate*>(top->getInboundJoint());
joint->setJointType(PxArticulationJointType::eFIX);
joint->setParentPose(PxTransform(PxVec3(0.f, 0.0f, 0.f)));
joint->setChildPose(PxTransform(PxVec3(0.f, -0.15f, -0.9f)));
gScene->addArticulation(*gArticulation);
for (PxU32 i = 0; i < gArticulation->getNbLinks(); ++i)
{
PxArticulationLink* link;
gArticulation->getLinks(&link, 1, i);
link->setLinearDamping(0.2f);
link->setAngularDamping(0.2f);
link->setMaxAngularVelocity(20.f);
link->setMaxLinearVelocity(100.f);
if (link != top)
{
for (PxU32 b = 0; b < link->getNbShapes(); ++b)
{
PxShape* shape;
link->getShapes(&shape, 1, b);
shape->setSimulationFilterData(PxFilterData(0, 0, 1, 0));
}
}
}
const PxVec3 halfExt(0.25f);
const PxReal density(0.5f);
PxRigidDynamic* box0 = gPhysics->createRigidDynamic(PxTransform(PxVec3(-0.25f, 5.f, 0.5f)));
PxRigidActorExt::createExclusiveShape(*box0, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box0, density);
gScene->addActor(*box0);
PxRigidDynamic* box1 = gPhysics->createRigidDynamic(PxTransform(PxVec3(0.25f, 5.f, 0.5f)));
PxRigidActorExt::createExclusiveShape(*box1, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box1, density);
gScene->addActor(*box1);
PxRigidDynamic* box2 = gPhysics->createRigidDynamic(PxTransform(PxVec3(-0.25f, 4.5f, 0.5f)));
PxRigidActorExt::createExclusiveShape(*box2, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box2, density);
gScene->addActor(*box2);
PxRigidDynamic* box3 = gPhysics->createRigidDynamic(PxTransform(PxVec3(0.25f, 4.5f, 0.5f)));
PxRigidActorExt::createExclusiveShape(*box3, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box3, density);
gScene->addActor(*box3);
PxRigidDynamic* box4 = gPhysics->createRigidDynamic(PxTransform(PxVec3(-0.25f, 5.f, 0.f)));
PxRigidActorExt::createExclusiveShape(*box4, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box4, density);
gScene->addActor(*box4);
PxRigidDynamic* box5 = gPhysics->createRigidDynamic(PxTransform(PxVec3(0.25f, 5.f, 0.f)));
PxRigidActorExt::createExclusiveShape(*box5, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box5, density);
gScene->addActor(*box5);
PxRigidDynamic* box6 = gPhysics->createRigidDynamic(PxTransform(PxVec3(-0.25f, 4.5f, 0.f)));
PxRigidActorExt::createExclusiveShape(*box6, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box6, density);
gScene->addActor(*box6);
PxRigidDynamic* box7 = gPhysics->createRigidDynamic(PxTransform(PxVec3(0.25f, 4.5f, 0.f)));
PxRigidActorExt::createExclusiveShape(*box7, PxBoxGeometry(halfExt), *gMaterial);
PxRigidBodyExt::updateMassAndInertia(*box7, density);
gScene->addActor(*box7);
}
#endif
void createLongChain()
{
const float scale = 0.25f;
const float radius = 0.5f*scale;
const float halfHeight = 1.0f*scale;
const PxU32 nbCapsules = 40;
const float capsuleMass = 1.0f;
const PxVec3 initPos(0.0f, 24.0f, 0.0f);
PxVec3 pos = initPos;
PxShape* capsuleShape = gPhysics->createShape(PxCapsuleGeometry(radius, halfHeight), *gMaterial);
PxArticulationLink* firstLink = NULL;
PxArticulationLink* parent = NULL;
const bool overlappingLinks = true; // Change this for another kind of rope
gArticulation->setSolverIterationCounts(16);
// Create rope
for (PxU32 i = 0; i<nbCapsules; i++)
{
PxArticulationLink* link = gArticulation->createLink(parent, PxTransform(pos));
if (!firstLink)
firstLink = link;
link->attachShape(*capsuleShape);
PxRigidBodyExt::setMassAndUpdateInertia(*link, capsuleMass);
link->setLinearDamping(0.1f);
link->setAngularDamping(0.1f);
link->setMaxAngularVelocity(30.f);
link->setMaxLinearVelocity(100.f);
PxArticulationJointBase* joint = link->getInboundJoint();
if (joint) // Will be null for root link
{
#if USE_REDUCED_COORDINATE_ARTICULATION
PxArticulationJointReducedCoordinate* rcJoint = static_cast<PxArticulationJointReducedCoordinate*>(joint);
rcJoint->setJointType(PxArticulationJointType::eSPHERICAL);
rcJoint->setMotion(PxArticulationAxis::eSWING2, PxArticulationMotion::eFREE);
rcJoint->setMotion(PxArticulationAxis::eSWING1, PxArticulationMotion::eFREE);
rcJoint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eFREE);
rcJoint->setFrictionCoefficient(1.f);
rcJoint->setMaxJointVelocity(1000000.f);
#endif
if (overlappingLinks)
{
joint->setParentPose(PxTransform(PxVec3(halfHeight, 0.0f, 0.0f)));
joint->setChildPose(PxTransform(PxVec3(-halfHeight, 0.0f, 0.0f)));
}
else
{
joint->setParentPose(PxTransform(PxVec3(radius + halfHeight, 0.0f, 0.0f)));
joint->setChildPose(PxTransform(PxVec3(-radius - halfHeight, 0.0f, 0.0f)));
}
}
if (overlappingLinks)
pos.x += (radius + halfHeight*2.0f);
else
pos.x += (radius + halfHeight) * 2.0f;
parent = link;
}
//Attach large & heavy box at the end of the rope
{
const float boxMass = 50.0f;
const float boxSize = 1.0f;
PxShape* boxShape = gPhysics->createShape(PxBoxGeometry(boxSize, boxSize, boxSize), *gMaterial);
pos.x -= (radius + halfHeight) * 2.0f;
pos.x += (radius + halfHeight) + boxSize;
PxArticulationLink* link = gArticulation->createLink(parent, PxTransform(pos));
link->setLinearDamping(0.1f);
link->setAngularDamping(0.1f);
link->setMaxAngularVelocity(30.f);
link->setMaxLinearVelocity(100.f);
link->attachShape(*boxShape);
PxRigidBodyExt::setMassAndUpdateInertia(*link, boxMass);
PxArticulationJointBase* joint = link->getInboundJoint();
#if USE_REDUCED_COORDINATE_ARTICULATION
PxArticulationJointReducedCoordinate* rcJoint = static_cast<PxArticulationJointReducedCoordinate*>(joint);
rcJoint->setJointType(PxArticulationJointType::eSPHERICAL);
rcJoint->setMotion(PxArticulationAxis::eSWING2, PxArticulationMotion::eFREE);
rcJoint->setMotion(PxArticulationAxis::eSWING1, PxArticulationMotion::eFREE);
rcJoint->setMotion(PxArticulationAxis::eTWIST, PxArticulationMotion::eFREE);
rcJoint->setFrictionCoefficient(1.f);
rcJoint->setMaxJointVelocity(1000000.f);
#endif
if (joint) // Will be null for root link
{
joint->setParentPose(PxTransform(PxVec3(radius + halfHeight, 0.0f, 0.0f)));
joint->setChildPose(PxTransform(PxVec3(-boxSize, 0.0f, 0.0f)));
}
}
gScene->addArticulation(*gArticulation);
#if USE_REDUCED_COORDINATE_ARTICULATION
gArticulation->setArticulationFlags(PxArticulationFlag::eFIX_BASE);
#else
// Attach articulation to static world
{
PxShape* anchorShape = gPhysics->createShape(PxSphereGeometry(0.05f), *gMaterial);
PxRigidStatic* anchor = PxCreateStatic(*gPhysics, PxTransform(initPos), *anchorShape);
gScene->addActor(*anchor);
PxSphericalJoint* j = PxSphericalJointCreate(*gPhysics, anchor, PxTransform(PxVec3(0.0f)), firstLink, PxTransform(PxVec3(0.0f)));
PX_UNUSED(j);
}
#endif
// Create obstacle
{
PxShape* boxShape = gPhysics->createShape(PxBoxGeometry(1.0f, 0.1f, 2.0f), *gMaterial);
PxRigidStatic* obstacle = PxCreateStatic(*gPhysics, PxTransform(initPos + PxVec3(10.0f, -3.0f, 0.0f)), *boxShape);
gScene->addActor(*obstacle);
}
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxInitExtensions(*gPhysics, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
#if USE_REDUCED_COORDINATE_ARTICULATION
sceneDesc.solverType = PxSolverType::eTGS;
#if CREATE_SCISSOR_LIFT
sceneDesc.filterShader = scissorFilter;
#endif
#endif
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
#if USE_REDUCED_COORDINATE_ARTICULATION
gArticulation = gPhysics->createArticulationReducedCoordinate();
#else
gArticulation = gPhysics->createArticulation();
// Stabilization can create artefacts on jointed objects so we just disable it
gArticulation->setStabilizationThreshold(0.0f);
gArticulation->setMaxProjectionIterations(16);
gArticulation->setSeparationTolerance(0.001f);
#endif
#if USE_REDUCED_COORDINATE_ARTICULATION & CREATE_SCISSOR_LIFT
createScissorLift();
#else
createLongChain();
#endif
}
#if USE_REDUCED_COORDINATE_ARTICULATION
static bool gClosing = true;
#endif
void stepPhysics(bool /*interactive*/)
{
const PxReal dt = 1.0f / 60.f;
#if USE_REDUCED_COORDINATE_ARTICULATION & CREATE_SCISSOR_LIFT
PxReal driveValue = gDriveJoint->getDriveTarget(PxArticulationAxis::eZ);
if (gClosing && driveValue < -1.2f)
gClosing = false;
else if (!gClosing && driveValue > 0.f)
gClosing = true;
if (gClosing)
driveValue -= dt*0.25f;
else
driveValue += dt*0.25f;
gDriveJoint->setDriveTarget(PxArticulationAxis::eZ, driveValue);
#endif
gScene->simulate(dt);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
gArticulation->release();
gScene->release();
gDispatcher->release();
gPhysics->release();
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release();
transport->release();
PxCloseExtensions();
gFoundation->release();
printf("SnippetArticulation done.\n");
}
void keyPress(unsigned char /*key*/, const PxTransform& /*camera*/)
{
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,145 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
PxU32 nbArticulations = scene->getNbArticulations();
for(PxU32 i=0;i<nbArticulations;i++)
{
PxArticulationBase* articulation;
scene->getArticulations(&articulation, 1, i);
const PxU32 nbLinks = articulation->getNbLinks();
std::vector<PxArticulationLink*> links(nbLinks);
articulation->getLinks(&links[0], nbLinks);
Snippets::renderActors(reinterpret_cast<PxRigidActor**>(&links[0]), static_cast<PxU32>(links.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
const PxVec3 gCamEyeChain(9.621917f, 24.677629f, 16.127209f);
const PxVec3 gCamDirChain(-0.138525f, -0.468482f, -0.872546f);
const PxVec3 gCamEyeLift(8.605188f, 4.050591f, 0.145860f);
const PxVec3 gCamDirLift(-0.999581f, -0.026449f, 0.011790f);
extern bool gCreateLiftScene;
void renderLoop()
{
if(gCreateLiftScene)
sCamera = new Snippets::Camera(gCamEyeLift, gCamDirLift);
else
sCamera = new Snippets::Camera(gCamEyeChain, gCamDirChain);
Snippets::setupDefaultWindow("PhysX Snippet Articulation");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,201 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the usage of PxBVHStructure
//
// It creates a large number of small sphere shapes forming a large sphere. Large sphere
// represents an actor and the actor is inserted into the scene with BVHStructure
// that is precomputed from all the small spheres. When an actor is insterted this
// way the scene queries against this object behave actor centric rather than shape
// centric.
// Each actor that is added with a BVHSctructure does not update any of its shape bounds
// within a pruning structure. It does update just the actor bounds and the query then
// goes into actors bounds pruner, then a local query is done against the shapes in the
// actor.
// For a dynamic actor consisting of a large amound of shapes there can be a significant
// performance benefits. During fetch results, there is no need to synchronize all
// shape bounds into scene query system. Also when a new AABB tree is build inside
// scene query system these actors shapes are not contained there.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
void createLargeSphere(const PxTransform& t, PxU32 density, PxReal largeRadius, PxReal radius, bool useAggregate)
{
PxRigidDynamic* body = gPhysics->createRigidDynamic(t);
// generate the sphere shapes
const float gStep = PxPi/float(density);
const float tStep = 2.0f*PxPi/float(density);
for(PxU32 i=0; i<density;i++)
{
for(PxU32 j=0;j<density;j++)
{
const float sinG = PxSin(gStep * i);
const float cosG = PxCos(gStep * i);
const float sinT = PxSin(tStep * j);
const float cosT = PxCos(tStep * j);
PxTransform localTm(PxVec3(largeRadius*sinG*cosT, largeRadius*sinG*sinT, largeRadius*cosG));
PxShape* shape = gPhysics->createShape(PxSphereGeometry(radius), *gMaterial);
shape->setLocalPose(localTm);
body->attachShape(*shape);
shape->release();
}
}
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
// get the bounds from the actor, this can be done through a helper function in PhysX extensions
PxU32 numBounds = 0;
PxBounds3* bounds = PxRigidActorExt::getRigidActorShapeLocalBoundsList(*body, numBounds);
// setup the PxBVHStructureDesc, it does contain only the PxBounds3 data
PxBVHStructureDesc bvhDesc;
bvhDesc.bounds.count = numBounds;
bvhDesc.bounds.data = bounds;
bvhDesc.bounds.stride = sizeof(PxBounds3);
// cook the bvh structure
PxBVHStructure* bvh = gCooking->createBVHStructure(bvhDesc, gPhysics->getPhysicsInsertionCallback());
// release the memory allocated within extensions, the bounds are not required anymore
gAllocator.deallocate(bounds);
// add the actor to the scene and provide the bvh structure (regular path without aggregate usage)
if(!useAggregate)
gScene->addActor(*body, bvh);
// Note that when objects with large amound of shapes are created it is also
// recommended to create an aggregate from them, see the code below that would replace
// the gScene->addActor(*body, bvh)
if(useAggregate)
{
PxAggregate* aggregate = gPhysics->createAggregate(1, false);
aggregate->addActor(*body, bvh);
gScene->addAggregate(*aggregate);
}
// bvh can be released at this point, the precomputed BVH structure was copied to the SDK pruners.
bvh->release();
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i = 0; i < 10; i++)
createLargeSphere(PxTransform(PxVec3(200.0f*i, .0f, 100.0f)), 50, 30.0f, 1.0f, false);
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
PX_RELEASE(gCooking);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetBVHStructure done.\n");
}
void keyPress(unsigned char , const PxTransform& )
{
}
int snippetMain(int, const char*const*)
{
static const PxU32 frameCount = 50;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
return 0;
}

View File

@ -0,0 +1,35 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
extern int snippetMain(int, const char*const*);
int main(int argc, char** argv)
{
return snippetMain(argc, argv);
}

View File

@ -0,0 +1,36 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PHYSX_SNIPPET_PVD_H
#define PHYSX_SNIPPET_PVD_H
#define PVD_HOST "127.0.0.1" //Set this to the IP address of the system running the PhysX Visual Debugger that you want to connect to.
#endif //PHYSX_SNIPPET_PVD_H

View File

@ -0,0 +1,45 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PHYSX_SNIPPET_PRINT_H
#define PHYSX_SNIPPET_PRINT_H
#include "foundation/PxPreprocessor.h"
#if PX_XBOXONE
void OutputDebugPrint(const char*, ...);
#define printf OutputDebugPrint
#elif PX_XBOX_SERIES_X
#include "PsString.h"
#define printf shdfnd::printFormatted
#elif PX_SWITCH
#include "../SnippetCommon/Switch/SwitchSnippetPrint.h"
#endif
#endif // PHYSX_SNIPPET_PRINT_H

View File

@ -0,0 +1,347 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of simple contact reports and contact modification.
//
// It defines a filter shader function that requests contact modification and
// touch reports for all pairs, and a contact callback function that saves
// the contact points. It configures the scene to use this filter and callback,
// and prints the number of contact reports each frame. If rendering, it renders
// each contact as a line whose length and direction are defined by the contact
// impulse.
// This test sets up a situation that would be unstable without contact modification
// due to very large mass ratios. This test uses local mass modification to make
// the configuration stable. It also demonstrates how to interpret contact impulses
// when local mass modification is used.
// Local mass modification can be disabled with the MODIFY_MASS_PROPERTIES #define
// to demonstrate the instability if it was not used.
//
// ****************************************************************************
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
#define MODIFY_MASS_PROPERTIES 1
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
std::vector<PxVec3> gContactPositions;
std::vector<PxVec3> gContactImpulses;
std::vector<PxVec3> gContactLinearImpulses[2];
std::vector<PxVec3> gContactAngularImpulses[2];
PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
// all initial and persisting reports for everything, with per-point data
pairFlags = PxPairFlag::eSOLVE_CONTACT | PxPairFlag::eDETECT_DISCRETE_CONTACT
| PxPairFlag::eNOTIFY_TOUCH_FOUND
| PxPairFlag::eNOTIFY_TOUCH_PERSISTS
| PxPairFlag::eNOTIFY_CONTACT_POINTS
| PxPairFlag::eMODIFY_CONTACTS;
return PxFilterFlag::eDEFAULT;
}
class ContactModifyCallback: public PxContactModifyCallback
{
void onContactModify(PxContactModifyPair* const pairs, PxU32 count)
{
#if MODIFY_MASS_PROPERTIES
//We define a maximum mass ratio that we will accept in this test, which is a ratio of 2
const PxReal maxMassRatio = 2.f;
for(PxU32 i = 0; i < count; i++)
{
const PxRigidDynamic* dynamic0 = pairs[i].actor[0]->is<PxRigidDynamic>();
const PxRigidDynamic* dynamic1 = pairs[i].actor[1]->is<PxRigidDynamic>();
if(dynamic0 != NULL && dynamic1 != NULL)
{
//We only want to perform local mass modification between 2 dynamic bodies because we intend on
//normalizing the mass ratios between the pair within a tolerable range
PxReal mass0 = dynamic0->getMass();
PxReal mass1 = dynamic1->getMass();
if(mass0 > mass1)
{
//dynamic0 is heavier than dynamic1 so we will locally increase the mass of dynamic1
//to be half the mass of dynamic0.
PxReal ratio = mass0/mass1;
if(ratio > maxMassRatio)
{
PxReal invMassScale = maxMassRatio/ratio;
pairs[i].contacts.setInvMassScale1(invMassScale);
pairs[i].contacts.setInvInertiaScale1(invMassScale);
}
}
else
{
//dynamic1 is heavier than dynamic0 so we will locally increase the mass of dynamic0
//to be half the mass of dynamic1.
PxReal ratio = mass1/mass0;
if(ratio > maxMassRatio)
{
PxReal invMassScale = maxMassRatio/ratio;
pairs[i].contacts.setInvMassScale0(invMassScale);
pairs[i].contacts.setInvInertiaScale0(invMassScale);
}
}
}
}
#endif
}
};
ContactModifyCallback gContactModifyCallback;
PxU32 extractContactsWithMassScale(const PxContactPair& pair, PxContactPairPoint* userBuffer, PxU32 bufferSize, PxReal& invMassScale0, PxReal& invMassScale1)
{
const PxU8* contactStream = pair.contactPoints;
const PxU8* patchStream = pair.contactPatches;
const PxU32* faceIndices = pair.getInternalFaceIndices();
PxU32 nbContacts = 0;
if(pair.contactCount && bufferSize)
{
PxContactStreamIterator iter(patchStream, contactStream, faceIndices, pair.patchCount, pair.contactCount);
const PxReal* impulses = reinterpret_cast<const PxReal*>(pair.contactImpulses);
PxU32 flippedContacts = (pair.flags & PxContactPairFlag::eINTERNAL_CONTACTS_ARE_FLIPPED);
PxU32 hasImpulses = (pair.flags & PxContactPairFlag::eINTERNAL_HAS_IMPULSES);
invMassScale0 = iter.getInvMassScale0();
invMassScale1 = iter.getInvMassScale1();
while(iter.hasNextPatch())
{
iter.nextPatch();
while(iter.hasNextContact())
{
iter.nextContact();
PxContactPairPoint& dst = userBuffer[nbContacts];
dst.position = iter.getContactPoint();
dst.separation = iter.getSeparation();
dst.normal = iter.getContactNormal();
if (!flippedContacts)
{
dst.internalFaceIndex0 = iter.getFaceIndex0();
dst.internalFaceIndex1 = iter.getFaceIndex1();
}
else
{
dst.internalFaceIndex0 = iter.getFaceIndex1();
dst.internalFaceIndex1 = iter.getFaceIndex0();
}
if (hasImpulses)
{
PxReal impulse = impulses[nbContacts];
dst.impulse = dst.normal * impulse;
}
else
dst.impulse = PxVec3(0.0f);
++nbContacts;
if(nbContacts == bufferSize)
return nbContacts;
}
}
}
return nbContacts;
}
class ContactReportCallback: public PxSimulationEventCallback
{
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED(constraints); PX_UNUSED(count); }
void onWake(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED(pairs); PX_UNUSED(count); }
void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
PX_UNUSED((pairHeader));
std::vector<PxContactPairPoint> contactPoints;
for(PxU32 i=0;i<nbPairs;i++)
{
PxU32 contactCount = pairs[i].contactCount;
if(contactCount)
{
contactPoints.resize(contactCount);
PxReal invMassScale[2];
extractContactsWithMassScale(pairs[i], &contactPoints[0], contactCount, invMassScale[0], invMassScale[1]);
for(PxU32 j=0;j<contactCount;j++)
{
gContactPositions.push_back(contactPoints[j].position);
//Push back reported contact impulses
gContactImpulses.push_back(contactPoints[j].impulse);
//Compute the effective linear/angular impulses for each body.
//Note that the local mass scaling permits separate scales for invMass and invInertia.
for(PxU32 k = 0; k < 2; ++k)
{
const PxRigidDynamic* dynamic = pairHeader.actors[k]->is<PxRigidDynamic>();
PxVec3 linImpulse(0.f), angImpulse(0.f);
if(dynamic != NULL)
{
PxRigidBodyExt::computeLinearAngularImpulse(*dynamic, dynamic->getGlobalPose(), contactPoints[j].position,
k == 0 ? contactPoints[j].impulse : -contactPoints[j].impulse, invMassScale[k], invMassScale[k], linImpulse, angImpulse);
}
gContactLinearImpulses[k].push_back(linImpulse);
gContactAngularImpulses[k].push_back(angImpulse);
}
}
}
}
}
};
ContactReportCallback gContactReportCallback;
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
PxTransform localTm(PxVec3(0, PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, (i+1)*(i+1)*(i+1)*10.0f);
gScene->addActor(*body);
}
shape->release();
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxInitExtensions(*gPhysics, gPvd);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
sceneDesc.filterShader = contactReportFilterShader;
sceneDesc.simulationEventCallback = &gContactReportCallback;
sceneDesc.contactModifyCallback = &gContactModifyCallback;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
createStack(PxTransform(PxVec3(0,0.0f,10.0f)), 5, 2.0f);
}
void stepPhysics(bool /*interactive*/)
{
gContactPositions.clear();
gContactImpulses.clear();
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
printf("%d contact reports\n", PxU32(gContactPositions.size()));
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetContactModification done.\n");
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics(false);
for(PxU32 i=0; i<250; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,135 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern std::vector<PxVec3> gContactPositions;
extern std::vector<PxVec3> gContactImpulses;
std::vector<PxVec3> gContactVertices;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
sCamera->handleKey(key, x, y);
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
if(gContactPositions.size())
{
gContactVertices.clear();
for(PxU32 i=0;i<gContactPositions.size();i++)
{
gContactVertices.push_back(gContactPositions[i]);
gContactVertices.push_back(gContactPositions[i]+gContactImpulses[i]*0.1f);
}
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &gContactVertices[0]);
glDrawArrays(GL_LINES, 0, GLint(gContactVertices.size()));
glDisableClientState(GL_VERTEX_ARRAY);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet ContactReport");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,207 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of simple contact reports.
//
// It defines a filter shader function that requests touch reports for
// all pairs, and a contact callback function that saves the contact points.
// It configures the scene to use this filter and callback, and prints the
// number of contact reports each frame. If rendering, it renders each
// contact as a line whose length and direction are defined by the contact
// impulse.
//
// ****************************************************************************
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
std::vector<PxVec3> gContactPositions;
std::vector<PxVec3> gContactImpulses;
PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
// all initial and persisting reports for everything, with per-point data
pairFlags = PxPairFlag::eSOLVE_CONTACT | PxPairFlag::eDETECT_DISCRETE_CONTACT
| PxPairFlag::eNOTIFY_TOUCH_FOUND
| PxPairFlag::eNOTIFY_TOUCH_PERSISTS
| PxPairFlag::eNOTIFY_CONTACT_POINTS;
return PxFilterFlag::eDEFAULT;
}
class ContactReportCallback: public PxSimulationEventCallback
{
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED(constraints); PX_UNUSED(count); }
void onWake(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED(pairs); PX_UNUSED(count); }
void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
PX_UNUSED((pairHeader));
std::vector<PxContactPairPoint> contactPoints;
for(PxU32 i=0;i<nbPairs;i++)
{
PxU32 contactCount = pairs[i].contactCount;
if(contactCount)
{
contactPoints.resize(contactCount);
pairs[i].extractContacts(&contactPoints[0], contactCount);
for(PxU32 j=0;j<contactCount;j++)
{
gContactPositions.push_back(contactPoints[j].position);
gContactImpulses.push_back(contactPoints[j].impulse);
}
}
}
}
};
ContactReportCallback gContactReportCallback;
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
PxInitExtensions(*gPhysics,gPvd);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
sceneDesc.filterShader = contactReportFilterShader;
sceneDesc.simulationEventCallback = &gContactReportCallback;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
createStack(PxTransform(PxVec3(0,3.0f,10.0f)), 5, 2.0f);
}
void stepPhysics(bool /*interactive*/)
{
gContactPositions.clear();
gContactImpulses.clear();
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
printf("%d contact reports\n", PxU32(gContactPositions.size()));
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetContactReport done.\n");
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics(false);
for(PxU32 i=0; i<250; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,135 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern std::vector<PxVec3> gContactPositions;
extern std::vector<PxVec3> gContactImpulses;
std::vector<PxVec3> gContactVertices;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
sCamera->handleKey(key, x, y);
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
if(gContactPositions.size())
{
gContactVertices.clear();
for(PxU32 i=0;i<gContactPositions.size();i++)
{
gContactVertices.push_back(gContactPositions[i]);
gContactVertices.push_back(gContactPositions[i]+gContactImpulses[i]*0.1f);
}
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &gContactVertices[0]);
glDrawArrays(GL_LINES, 0, GLint(gContactVertices.size()));
glDisableClientState(GL_VERTEX_ARRAY);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet ContactReport");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,334 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of simple contact reports in combination
// with continuous collision detection (CCD). Furthermore, extra contact report
// data will be requested.
//
// The snippet defines a filter shader function that enables CCD and requests
// touch reports for all pairs, and a contact callback function that saves the
// contact points and the actor positions at time of impact.
// It configures the scene to use this filter and callback, enables CCD and
// prints the number of contact points found. If rendering, it renders each
// contact as a line whose length and direction are defined by the contact
// impulse (the line points in the opposite direction of the impulse). In
// addition, the path of the fast moving dynamic object is drawn with lines.
//
// ****************************************************************************
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxTriangleMesh* gTriangleMesh = NULL;
PxRigidStatic* gTriangleMeshActor = NULL;
PxRigidDynamic* gSphereActor = NULL;
PxPvd* gPvd = NULL;
PxU32 gSimStepCount = 0;
std::vector<PxVec3> gContactPositions;
std::vector<PxVec3> gContactImpulses;
std::vector<PxVec3> gContactSphereActorPositions;
PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
//
// Enable CCD for the pair, request contact reports for initial and CCD contacts.
// Additionally, provide information per contact point and provide the actor
// pose at the time of contact.
//
pairFlags = PxPairFlag::eCONTACT_DEFAULT
| PxPairFlag::eDETECT_CCD_CONTACT
| PxPairFlag::eNOTIFY_TOUCH_CCD
| PxPairFlag::eNOTIFY_TOUCH_FOUND
| PxPairFlag::eNOTIFY_CONTACT_POINTS
| PxPairFlag::eCONTACT_EVENT_POSE;
return PxFilterFlag::eDEFAULT;
}
class ContactReportCallback: public PxSimulationEventCallback
{
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED(constraints); PX_UNUSED(count); }
void onWake(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED(pairs); PX_UNUSED(count); }
void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
std::vector<PxContactPairPoint> contactPoints;
PxTransform spherePose(PxIdentity);
PxU32 nextPairIndex = 0xffffffff;
PxContactPairExtraDataIterator iter(pairHeader.extraDataStream, pairHeader.extraDataStreamSize);
bool hasItemSet = iter.nextItemSet();
if (hasItemSet)
nextPairIndex = iter.contactPairIndex;
for(PxU32 i=0; i < nbPairs; i++)
{
//
// Get the pose of the dynamic object at time of impact.
//
if (nextPairIndex == i)
{
if (pairHeader.actors[0]->is<PxRigidDynamic>())
spherePose = iter.eventPose->globalPose[0];
else
spherePose = iter.eventPose->globalPose[1];
gContactSphereActorPositions.push_back(spherePose.p);
hasItemSet = iter.nextItemSet();
if (hasItemSet)
nextPairIndex = iter.contactPairIndex;
}
//
// Get the contact points for the pair.
//
const PxContactPair& cPair = pairs[i];
if (cPair.events & (PxPairFlag::eNOTIFY_TOUCH_FOUND | PxPairFlag::eNOTIFY_TOUCH_CCD))
{
PxU32 contactCount = cPair.contactCount;
contactPoints.resize(contactCount);
cPair.extractContacts(&contactPoints[0], contactCount);
for(PxU32 j=0; j < contactCount; j++)
{
gContactPositions.push_back(contactPoints[j].position);
gContactImpulses.push_back(contactPoints[j].impulse);
}
}
}
}
};
ContactReportCallback gContactReportCallback;
void initScene()
{
//
// Create a static triangle mesh
//
PxVec3 vertices[] = { PxVec3(-8.0f, 0.0f, -3.0f),
PxVec3(-8.0f, 0.0f, 3.0f),
PxVec3(0.0f, 0.0f, 3.0f),
PxVec3(0.0f, 0.0f, -3.0f),
PxVec3(-8.0f, 10.0f, -3.0f),
PxVec3(-8.0f, 10.0f, 3.0f),
PxVec3(0.0f, 10.0f, 3.0f),
PxVec3(0.0f, 10.0f, -3.0f),
};
PxU32 vertexCount = sizeof(vertices) / sizeof(vertices[0]);
PxU32 triangleIndices[] = { 0, 1, 2,
0, 2, 3,
0, 5, 1,
0, 4, 5,
4, 6, 5,
4, 7, 6
};
PxU32 triangleCount = (sizeof(triangleIndices) / sizeof(triangleIndices[0])) / 3;
PxTriangleMeshDesc triangleMeshDesc;
triangleMeshDesc.points.count = vertexCount;
triangleMeshDesc.points.data = vertices;
triangleMeshDesc.points.stride = sizeof(PxVec3);
triangleMeshDesc.triangles.count = triangleCount;
triangleMeshDesc.triangles.data = triangleIndices;
triangleMeshDesc.triangles.stride = 3 * sizeof(PxU32);
gTriangleMesh = gCooking->createTriangleMesh(triangleMeshDesc, gPhysics->getPhysicsInsertionCallback());
if (!gTriangleMesh)
return;
gTriangleMeshActor = gPhysics->createRigidStatic(PxTransform(PxVec3(0.0f, 1.0f, 0.0f), PxQuat(PxHalfPi / 60.0f, PxVec3(0.0f, 1.0f, 0.0f))));
if (!gTriangleMeshActor)
return;
PxTriangleMeshGeometry triGeom(gTriangleMesh);
PxShape* triangleMeshShape = PxRigidActorExt::createExclusiveShape(*gTriangleMeshActor, triGeom, *gMaterial);
if (!triangleMeshShape)
return;
gScene->addActor(*gTriangleMeshActor);
//
// Create a fast moving sphere that will hit and bounce off the static triangle mesh 3 times
// in one simulation step.
//
PxTransform spherePose(PxVec3(0.0f, 5.0f, 1.0f));
gContactSphereActorPositions.push_back(spherePose.p);
gSphereActor = gPhysics->createRigidDynamic(spherePose);
gSphereActor->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);
if (!gSphereActor)
return;
PxSphereGeometry sphereGeom(1.0f);
PxShape* sphereShape = PxRigidActorExt::createExclusiveShape(*gSphereActor, sphereGeom, *gMaterial);
if (!sphereShape)
return;
PxRigidBodyExt::updateMassAndInertia(*gSphereActor, 1.0f);
PxReal velMagn = 900.0f;
PxVec3 vel = PxVec3(-1.0f, -1.0f, 0.0f);
vel.normalize();
vel *= velMagn;
gSphereActor->setLinearVelocity(vel);
gScene->addActor(*gSphereActor);
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
PxInitExtensions(*gPhysics, gPvd);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.gravity = PxVec3(0, 0, 0);
sceneDesc.filterShader = contactReportFilterShader;
sceneDesc.simulationEventCallback = &gContactReportCallback;
sceneDesc.flags |= PxSceneFlag::eENABLE_CCD;
sceneDesc.ccdMaxPasses = 4;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 1.0f);
initScene();
}
void stepPhysics(bool /*interactive*/)
{
if (!gSimStepCount)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
printf("%d contact points\n", PxU32(gContactPositions.size()));
if (gSphereActor)
gContactSphereActorPositions.push_back(gSphereActor->getGlobalPose().p);
gSimStepCount = 1;
}
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gSphereActor);
PX_RELEASE(gTriangleMeshActor);
PX_RELEASE(gTriangleMesh);
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics);
PX_RELEASE(gCooking);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetContactReportCCD done.\n");
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics(false);
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,155 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern std::vector<PxVec3> gContactPositions;
extern std::vector<PxVec3> gContactImpulses;
extern std::vector<PxVec3> gContactSphereActorPositions;
std::vector<PxVec3> gContactVertices;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
sCamera->handleKey(key, x, y);
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
if(gContactPositions.size())
{
gContactVertices.clear();
for(PxU32 i=0; i < gContactPositions.size(); i++)
{
gContactVertices.push_back(gContactPositions[i]);
gContactVertices.push_back(gContactPositions[i]-gContactImpulses[i]*0.0001f);
}
glDisable(GL_LIGHTING);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &gContactVertices[0]);
glDrawArrays(GL_LINES, 0, GLint(gContactVertices.size()));
glDisableClientState(GL_VERTEX_ARRAY);
glEnable(GL_LIGHTING);
}
if(gContactSphereActorPositions.size())
{
gContactVertices.clear();
for(PxU32 i=0; i < gContactSphereActorPositions.size() - 1; i++)
{
gContactVertices.push_back(gContactSphereActorPositions[i]);
gContactVertices.push_back(gContactSphereActorPositions[i+1]);
}
glDisable(GL_LIGHTING);
glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &gContactVertices[0]);
glDrawArrays(GL_LINES, 0, GLint(gContactVertices.size()));
glDisableClientState(GL_VERTEX_ARRAY);
glEnable(GL_LIGHTING);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(-1.5f, 6.0f, 14.0f), PxVec3(-0.1f,0.0f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet ContactReport CCD");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,325 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ***********************************************************************************************
// This snippet illustrates how to convert PhysX 3 serialized binary files from one platform to
// another. The conversion requires three input files:
//
// 1. A metadata file that was created on the source platform. This file specifies the
// source platform as well as the layout of PhysX data structures on the source platform.
// 2. A metadata file that was created on the target platform. This file specifies the target
// (destination) platform as well as the layout of PhysX data structures on the target platform.
// 3. A source file containing a binary serialized collection. The platform this file was created
// on needs to match with the platform the source metadata file has been created on.
//
// A set of pre-built binary metadata files for various platforms is included with the PhysX SDK
// at [path to installed PhysX SDK]/Tools/BinaryMetaData.
//
// Optionally this snippet allows to create a example file with binary serialized data for the
// platform the snippet runs on.
//
// The conversion snippet only compiles and runs on authoring platforms (windows, osx and linux).
//
// SnippetConvert is a simple command-line tool supporting the following options::
//
// --srcMetadata=<filename> Specify the source metadata (and the source platform)
// --dstMetadata=<filename> Specify the target metadata (and the target platform)
// --srcBinFile=<filename> Source binary file to convert (serialized on target platform)
// --dstBinFile=<filename> Outputs target binary file
// --generateExampleFile=<filename> Generates an example file
// --dumpBinaryMetaData=<filename> Dump binary meta data for current runtime platform
// --verbose Enables verbose mode
//
// ***********************************************************************************************
#include "PxPhysicsAPI.h"
#include <iostream>
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxSerializationRegistry* gSerializationRegistry = NULL;
struct CmdLineParameters
{
bool verbose;
const char* srcMetadata;
const char* dstMetadata;
const char* srcBinFile;
const char* dstBinFile;
const char* exampleFile;
const char* dumpMetaDataFile;
CmdLineParameters()
: verbose(false)
, srcMetadata(NULL)
, dstMetadata(NULL)
, srcBinFile(NULL)
, dstBinFile(NULL)
, exampleFile(NULL)
, dumpMetaDataFile(NULL)
{
}
};
static bool match(const char* opt, const char* ref)
{
std::string s1(opt);
std::string s2(ref);
return !s1.compare(0, s2.length(), s2);
}
static void printHelpMsg()
{
printf("SnippetConvert usage:\n"
"SnippetConvert "
"--srcMetadata=<filename> "
"--dstMetadata=<filename> "
"--srcBinFile=<filename> "
"--dstBinFile=<filename> "
"--generateExampleFile=<filename> "
"--dumpBinaryMetaData=<filename> "
"--verbose \n"
"A set of pre-built binary metadata is included with the PhysX SDK "
"at [path to installed PhysX SDK]/Tools/BinaryMetaData.\n");
printf("--srcMetadata=<filename>\n");
printf(" Defines source metadata file\n");
printf("--dstMetadata=<filename>\n");
printf(" Defines target metadata file\n");
printf("--srcBinFile=<filename>\n");
printf(" Source binary file to convert\n");
printf("--dstBinFile=<filename>\n");
printf(" Outputs target binary file\n");
printf("--generateExampleFile=<filename>\n");
printf(" Generates an example file\n");
printf("--dumpBinaryMetaData=<filename>\n");
printf(" Dump binary meta data for current runtime platform\n");
printf("--verbose\n");
printf(" Enables verbose mode\n");
}
static bool parseCommandLine(CmdLineParameters& result, int argc, const char *const*argv)
{
if( argc <= 1 )
{
printHelpMsg();
return false;
}
#define GET_PARAMETER(v, s) \
{ \
v = argv[i] + strlen(s); \
if( v == NULL ) \
{ \
printf("[ERROR] \"%s\" should have extra parameter\n", argv[i]);\
printHelpMsg(); \
return false; \
} \
}
for(int i = 0; i < argc; ++i)
{
if(argv[i][0] != '-' || argv[i][1] != '-')
{
if( i > 0 )
{
printf( "[ERROR] Unknown command line parameter \"%s\"\n", argv[i] );
printHelpMsg();
return false;
}
continue;
}
if(match(argv[i], "--verbose"))
{
result.verbose = true;
}
else if(match(argv[i], "--srcMetadata="))
{
GET_PARAMETER(result.srcMetadata, "--srcMetadata=");
}
else if(match(argv[i], "--dstMetadata="))
{
GET_PARAMETER(result.dstMetadata, "--dstMetadata=");
}
else if(match(argv[i], "--srcBinFile="))
{
GET_PARAMETER(result.srcBinFile, "--srcBinFile=");
}
else if(match(argv[i], "--dstBinFile="))
{
GET_PARAMETER(result.dstBinFile, "--dstBinFile=");
}
else if(match(argv[i], "--generateExampleFile="))
{
GET_PARAMETER(result.exampleFile, "--generateExampleFile=");
break;
}
else if (match(argv[i], "--dumpBinaryMetaData="))
{
GET_PARAMETER(result.dumpMetaDataFile, "--dumpBinaryMetaData=");
break;
}
else
{
printf( "[ERROR] Unknown command line parameter \"%s\"\n", argv[i] );
printHelpMsg();
return false;
}
}
if( result.exampleFile || result.dumpMetaDataFile)
return true;
if( !result.srcMetadata || !result.dstMetadata || !result.srcBinFile || !result.dstBinFile)
{
printf("[ERROR] Missed args!! \n");
printHelpMsg();
return false;
}
return true;
}
static bool generateExampleFile(const char* filename)
{
PxCollection* collection = PxCreateCollection();
PX_ASSERT( collection );
PxMaterial *material = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PX_ASSERT( material );
PxShape* shape = gPhysics->createShape(PxBoxGeometry(2.f, 2.f, 2.f), *material);
PxRigidStatic* theStatic = PxCreateStatic(*gPhysics, PxTransform(PxIdentity), *shape);
collection->add(*material);
collection->add(*shape);
collection->add(*theStatic);
PxDefaultFileOutputStream s(filename);
bool bret = PxSerialization::serializeCollectionToBinary(s, *collection, *gSerializationRegistry);
collection->release();
return bret;
}
static bool dumpBinaryMetaData(const char* filename)
{
PxDefaultFileOutputStream s(filename);
PxSerialization::dumpBinaryMetaData(s, *gSerializationRegistry);
return true;
}
static void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true);
gSerializationRegistry = PxSerialization::createSerializationRegistry(*gPhysics);
PxInitVehicleSDK(*gPhysics, gSerializationRegistry);
}
static void cleanupPhysics()
{
PxCloseVehicleSDK(gSerializationRegistry);
gSerializationRegistry->release();
gPhysics->release();
gFoundation->release();
printf("SnippetConvert done.\n");
}
int snippetMain(int argc, const char *const*argv)
{
CmdLineParameters result;
if(!parseCommandLine(result, argc, argv))
return 1;
bool bret = false;
initPhysics();
if(result.exampleFile || result.dumpMetaDataFile)
{
if (result.exampleFile)
{
bret = generateExampleFile(result.exampleFile);
}
if (result.dumpMetaDataFile)
{
bret &= dumpBinaryMetaData(result.dumpMetaDataFile);
}
}
else
{
PxBinaryConverter* binaryConverter = PxSerialization::createBinaryConverter();
if(result.verbose)
binaryConverter->setReportMode(PxConverterReportMode::eVERBOSE);
else
binaryConverter->setReportMode(PxConverterReportMode::eNORMAL);
PxDefaultFileInputData srcMetaDataStream(result.srcMetadata);
PxDefaultFileInputData dstMetaDataStream(result.dstMetadata);
bret = binaryConverter->setMetaData(srcMetaDataStream, dstMetaDataStream);
if(!bret)
{
printf("setMetaData failed\n");
}
else
{
PxDefaultFileInputData srcBinaryDataStream(result.srcBinFile);
PxDefaultFileOutputStream dstBinaryDataStream(result.dstBinFile);
binaryConverter->convert(srcBinaryDataStream, srcBinaryDataStream.getLength(), dstBinaryDataStream);
}
binaryConverter->release();
}
cleanupPhysics();
return !bret;
}

View File

@ -0,0 +1,178 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet creates convex meshes with different cooking settings
// and shows how these settings affect the convex mesh creation performance and
// the size of the resulting cooked meshes.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
float rand(float loVal, float hiVal)
{
return loVal + (float(rand())/float(RAND_MAX))*(hiVal - loVal);
}
template<PxConvexMeshCookingType::Enum convexMeshCookingType, bool directInsertion, PxU32 gaussMapLimit>
void createRandomConvex(PxU32 numVerts, const PxVec3* verts)
{
PxCookingParams params = gCooking->getParams();
// Use the new (default) PxConvexMeshCookingType::eQUICKHULL
params.convexMeshCookingType = convexMeshCookingType;
// If the gaussMapLimit is chosen higher than the number of output vertices, no gauss map is added to the convex mesh data (here 256).
// If the gaussMapLimit is chosen lower than the number of output vertices, a gauss map is added to the convex mesh data (here 16).
params.gaussMapLimit = gaussMapLimit;
gCooking->setParams(params);
// Setup the convex mesh descriptor
PxConvexMeshDesc desc;
// We provide points only, therefore the PxConvexFlag::eCOMPUTE_CONVEX flag must be specified
desc.points.data = verts;
desc.points.count = numVerts;
desc.points.stride = sizeof(PxVec3);
desc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
PxU32 meshSize = 0;
PxConvexMesh* convex = NULL;
PxU64 startTime = SnippetUtils::getCurrentTimeCounterValue();
if(directInsertion)
{
// Directly insert mesh into PhysX
convex = gCooking->createConvexMesh(desc, gPhysics->getPhysicsInsertionCallback());
PX_ASSERT(convex);
}
else
{
// Serialize the cooked mesh into a stream.
PxDefaultMemoryOutputStream outStream;
bool res = gCooking->cookConvexMesh(desc, outStream);
PX_UNUSED(res);
PX_ASSERT(res);
meshSize = outStream.getSize();
// Create the mesh from a stream.
PxDefaultMemoryInputData inStream(outStream.getData(), outStream.getSize());
convex = gPhysics->createConvexMesh(inStream);
PX_ASSERT(convex);
}
// Print the elapsed time for comparison
PxU64 stopTime = SnippetUtils::getCurrentTimeCounterValue();
float elapsedTime = SnippetUtils::getElapsedTimeInMilliseconds(stopTime - startTime);
printf("\t -----------------------------------------------\n");
printf("\t Create convex mesh with %d triangles: \n", numVerts);
directInsertion ? printf("\t\t Direct mesh insertion enabled\n") : printf("\t\t Direct mesh insertion disabled\n");
printf("\t\t Gauss map limit: %d \n", gaussMapLimit);
printf("\t\t Created hull number of vertices: %d \n", convex->getNbVertices());
printf("\t\t Created hull number of polygons: %d \n", convex->getNbPolygons());
printf("\t Elapsed time in ms: %f \n", double(elapsedTime));
if (!directInsertion)
{
printf("\t Mesh size: %d \n", meshSize);
}
convex->release();
}
void createConvexMeshes()
{
const PxU32 numVerts = 64;
PxVec3* vertices = new PxVec3[numVerts];
// Prepare random verts
for(PxU32 i = 0; i < numVerts; i++)
{
vertices[i] = PxVec3(rand(-20.0f, 20.0f), rand(-20.0f, 20.0f), rand(-20.0f, 20.0f));
}
// Create convex mesh using the quickhull algorithm with different settings
printf("-----------------------------------------------\n");
printf("Create convex mesh using the quickhull algorithm: \n\n");
// The default convex mesh creation serializing to a stream, useful for offline cooking.
createRandomConvex<PxConvexMeshCookingType::eQUICKHULL, false, 16>(numVerts, vertices);
// The default convex mesh creation without the additional gauss map data.
createRandomConvex<PxConvexMeshCookingType::eQUICKHULL, false, 256>(numVerts, vertices);
// Convex mesh creation inserting the mesh directly into PhysX.
// Useful for runtime cooking.
createRandomConvex<PxConvexMeshCookingType::eQUICKHULL, true, 16>(numVerts, vertices);
// Convex mesh creation inserting the mesh directly into PhysX, without gauss map data.
// Useful for runtime cooking.
createRandomConvex<PxConvexMeshCookingType::eQUICKHULL, true, 256>(numVerts, vertices);
delete [] vertices;
}
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
}
void cleanupPhysics()
{
gPhysics->release();
gCooking->release();
gFoundation->release();
printf("SnippetConvexMeshCreate done.\n");
}
int snippetMain(int, const char*const*)
{
initPhysics();
createConvexMeshes();
cleanupPhysics();
return 0;
}

View File

@ -0,0 +1,231 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "PulleyJoint.h"
#include <assert.h>
#include "PxConstraint.h"
using namespace physx;
PxConstraintShaderTable PulleyJoint::sShaderTable = { &PulleyJoint::solverPrep, &PulleyJoint::project, &PulleyJoint::visualize, PxConstraintFlag::Enum(0) };
PulleyJoint::PulleyJoint(PxPhysics& physics, PxRigidBody& body0, const PxTransform& localFrame0, const PxVec3& attachment0,
PxRigidBody& body1, const PxTransform& localFrame1, const PxVec3& attachment1)
{
mConstraint = physics.createConstraint(&body0, &body1, *this, PulleyJoint::sShaderTable, sizeof(PulleyJointData));
mBody[0] = &body0;
mBody[1] = &body1;
// keep these around in case the CoM gets relocated
mLocalPose[0] = localFrame0.getNormalized();
mLocalPose[1] = localFrame1.getNormalized();
// the data which will be fed to the joint solver and projection shaders
mData.attachment0 = attachment0;
mData.attachment1 = attachment1;
mData.distance = 1.0f;
mData.ratio = 1.0f;
mData.c2b[0] = body0.getCMassLocalPose().transformInv(mLocalPose[0]);
mData.c2b[1] = body1.getCMassLocalPose().transformInv(mLocalPose[1]);
}
void PulleyJoint::release()
{
mConstraint->release();
}
///////////////////////////////////////////// attribute accessors and mutators
void PulleyJoint::setAttachment0(const PxVec3& pos)
{
mData.attachment0 = pos;
mConstraint->markDirty();
}
PxVec3 PulleyJoint::getAttachment0() const
{
return mData.attachment0;
}
void PulleyJoint::setAttachment1(const PxVec3& pos)
{
mData.attachment1 = pos;
mConstraint->markDirty();
}
PxVec3 PulleyJoint::getAttachment1() const
{
return mData.attachment1;
}
void PulleyJoint::setDistance(float totalDistance)
{
mData.distance = totalDistance;
mConstraint->markDirty();
}
float PulleyJoint::getDistance() const
{
return mData.distance;
}
void PulleyJoint::setRatio(float ratio)
{
mData.ratio = ratio;
mConstraint->markDirty();
}
float PulleyJoint::getRatio() const
{
return mData.ratio;
}
///////////////////////////////////////////// PxConstraintConnector methods
void* PulleyJoint::prepareData()
{
return &mData;
}
void PulleyJoint::onConstraintRelease()
{
delete this;
}
void PulleyJoint::onComShift(PxU32 actor)
{
mData.c2b[actor] = mBody[actor]->getCMassLocalPose().transformInv(mLocalPose[actor]);
mConstraint->markDirty();
}
void PulleyJoint::onOriginShift(const PxVec3& shift)
{
mData.attachment0 -= shift;
mData.attachment1 -= shift;
}
void* PulleyJoint::getExternalReference(PxU32& typeID)
{
typeID = TYPE_ID;
return this;
}
///////////////////////////////////////////// work functions
PxU32 PulleyJoint::solverPrep(Px1DConstraint* constraints,
PxVec3& body0WorldOffset,
PxU32 maxConstraints,
PxConstraintInvMassScale&,
const void* constantBlock,
const PxTransform& bA2w,
const PxTransform& bB2w,
bool /*useExtendedLimits*/,
PxVec3& cA2wOut, PxVec3& cB2wOut)
{
PX_UNUSED(maxConstraints);
const PulleyJointData& data = *reinterpret_cast<const PulleyJointData*>(constantBlock);
PxTransform cA2w = bA2w.transform(data.c2b[0]);
PxTransform cB2w = bB2w.transform(data.c2b[1]);
cA2wOut = cA2w.p;
cB2wOut = cB2w.p;
body0WorldOffset = cB2w.p - bA2w.p;
PxVec3 directionA = data.attachment0 - cA2w.p;
PxReal distanceA = directionA.normalize();
PxVec3 directionB = data.attachment1 - cB2w.p;
PxReal distanceB = directionB.normalize();
directionB *= data.ratio;
PxReal totalDistance = distanceA + distanceB;
// compute geometric error:
PxReal geometricError = (data.distance - totalDistance);
Px1DConstraint *c = constraints;
// constraint is breakable, so we need to output forces
c->flags = Px1DConstraintFlag::eOUTPUT_FORCE;
if (geometricError < 0.0f)
{
c->maxImpulse = PX_MAX_F32;
c->minImpulse = 0;
c->geometricError = geometricError;
}
else if(geometricError > 0.0f)
{
c->maxImpulse = 0;
c->minImpulse = -PX_MAX_F32;
c->geometricError = geometricError;
}
c->linear0 = directionA; c->angular0 = (cA2w.p - bA2w.p).cross(c->linear0);
c->linear1 = -directionB; c->angular1 = (cB2w.p - bB2w.p).cross(c->linear1);
return 1;
}
void PulleyJoint::project(const void* constantBlock,
PxTransform& bodyAToWorld,
PxTransform& bodyBToWorld,
bool projectToA)
{
PX_UNUSED(constantBlock);
PX_UNUSED(bodyAToWorld);
PX_UNUSED(bodyBToWorld);
PX_UNUSED(projectToA);
}
void PulleyJoint::visualize(PxConstraintVisualizer& viz,
const void* constantBlock,
const PxTransform& body0Transform,
const PxTransform& body1Transform,
PxU32 flags)
{
PX_UNUSED(flags);
const PulleyJointData& data = *reinterpret_cast<const PulleyJointData*>(constantBlock);
PxTransform cA2w = body0Transform * data.c2b[0];
PxTransform cB2w = body1Transform * data.c2b[1];
viz.visualizeJointFrames(cA2w, cB2w);
viz.visualizeJointFrames(PxTransform(data.attachment0), PxTransform(data.attachment1));
}

View File

@ -0,0 +1,141 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PULLEY_JOINT_H
#define PULLEY_JOINT_H
#include "PxPhysicsAPI.h"
// a pulley joint constrains two actors such that the sum of their distances from their respective anchor points at their attachment points
// is a fixed value (the parameter 'distance'). Only dynamic actors are supported.
//
// The constraint equation is as follows:
//
// |anchor0 - attachment0| + |anchor1 - attachment1| * ratio = distance
//
// where 'ratio' provides mechanical advantage.
//
// The above equation results in a singularity when the anchor point is coincident with the attachment point; for simplicity
// the constraint does not attempt to handle this case robustly.
class PulleyJoint : public physx::PxConstraintConnector
{
public:
static const physx::PxU32 TYPE_ID = physx::PxConcreteType::eFIRST_USER_EXTENSION;
PulleyJoint(physx::PxPhysics& physics,
physx::PxRigidBody& body0, const physx::PxTransform& localFrame0, const physx::PxVec3& attachment0,
physx::PxRigidBody& body1, const physx::PxTransform& localFrame1, const physx::PxVec3& attachment1);
void release();
// attribute accessor and mutators
void setAttachment0(const physx::PxVec3& pos);
physx::PxVec3 getAttachment0() const;
void setAttachment1(const physx::PxVec3& pos);
physx::PxVec3 getAttachment1() const;
void setDistance(physx::PxReal totalDistance);
physx::PxReal getDistance() const;
void setRatio(physx::PxReal ratio);
physx::PxReal getRatio() const;
// PxConstraintConnector boilerplate
void* prepareData();
void onConstraintRelease();
void onComShift(physx::PxU32 actor);
void onOriginShift(const physx::PxVec3& shift);
void* getExternalReference(physx::PxU32& typeID);
bool updatePvdProperties(physx::pvdsdk::PvdDataStream&,
const physx::PxConstraint*,
physx::PxPvdUpdateType::Enum) const { return true; }
physx::PxBase* getSerializable() { return NULL; }
virtual physx::PxConstraintSolverPrep getPrep() const { return sShaderTable.solverPrep; }
virtual const void* getConstantBlock() const { return &mData; }
private:
static physx::PxU32 solverPrep(physx::Px1DConstraint* constraints,
physx::PxVec3& body0WorldOffset,
physx::PxU32 maxConstraints,
physx::PxConstraintInvMassScale&,
const void* constantBlock,
const physx::PxTransform& bA2w,
const physx::PxTransform& bB2w,
bool useExtendedLimits,
physx::PxVec3& cA2wOut, physx::PxVec3& cB2wOut);
static void visualize(physx::PxConstraintVisualizer& viz,
const void* constantBlock,
const physx::PxTransform& body0Transform,
const physx::PxTransform& body1Transform,
physx::PxU32 flags);
static void project(const void* constantBlock,
physx::PxTransform& bodyAToWorld,
physx::PxTransform& bodyBToWorld,
bool projectToA);
struct PulleyJointData
{
physx::PxTransform c2b[2];
physx::PxVec3 attachment0;
physx::PxVec3 attachment1;
physx::PxReal distance;
physx::PxReal ratio;
physx::PxReal tolerance;
};
physx::PxRigidBody* mBody[2];
physx::PxTransform mLocalPose[2];
physx::PxConstraint* mConstraint;
PulleyJointData mData;
static physx::PxConstraintShaderTable
sShaderTable;
~PulleyJoint() {}
};
#endif

View File

@ -0,0 +1,144 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the implementation and use of a pulley joint
// using physx' custom constraint framework.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
#include "PulleyJoint.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
// two boxes connected by the pulley, one twice the density of the other
PxBoxGeometry boxGeom(1.0f, 1.0f, 1.0f);
PxRigidDynamic* box0 = PxCreateDynamic(*gPhysics, PxTransform(PxVec3(5,5,0)), boxGeom, *gMaterial, 1.0f);
PxRigidDynamic* box1 = PxCreateDynamic(*gPhysics, PxTransform(PxVec3(0,5,0)), boxGeom, *gMaterial, 2.0f);
PulleyJoint* joint = new PulleyJoint(*gPhysics, *box0, PxTransform(PxVec3(0.0f,1.0f,0.0f)), PxVec3(5.0f,10.0f,0.0f),
*box1, PxTransform(PxVec3(0.0f,1.0f,0.0f)), PxVec3(0.0f,10.0f,0.0f));
joint->setDistance(8.0f);
gScene->addActor(*box0);
gScene->addActor(*box1);
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetCustomJoint done.\n");
}
void keyPress(unsigned char, const PxTransform&)
{
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet HelloWorld");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,225 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates how to setup a custom profiler, and potentially
// re-route it to PVD's profiling functions.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxReal stackZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
static const bool gCallPVDProfilingFunctions = false;
class CustomProfilerCallback : public PxProfilerCallback
{
public:
virtual ~CustomProfilerCallback() {}
virtual void* zoneStart(const char* eventName, bool detached, uint64_t contextId)
{
// Option 1: add your own profiling code here (before calling the PVD function).
// If you call the PVD profiling function below, adding your own profiling code here
// means it will capture the cost of the PVD zoneStart function.
// NB: we don't have an actual profiler implementation in the snippet so we just call printf instead
printf("start: %s\n", eventName);
// Optional: call the PVD function if you want to see the profiling results in PVD.
void* profilerData = gCallPVDProfilingFunctions ? gPvd->zoneStart(eventName, detached, contextId) : NULL;
// Option 2: add your own profiling code here (after calling the PVD function).
// If you call the PVD profiling function above, adding your own profiling code here
// means its cost will be captured by the PVD profiler.
return profilerData;
}
virtual void zoneEnd(void* profilerData, const char* eventName, bool detached, uint64_t contextId)
{
// Option 2: add your own profiling code here (before calling the PVD function).
// If you call the PVD profiling function below, adding your own profiling code here
// means its cost will be captured by the PVD profiler.
// Optional: call the PVD function if you want to see the profiling results in PVD.
if(gCallPVDProfilingFunctions)
gPvd->zoneEnd(profilerData, eventName, detached, contextId);
// Option 1: add your own profiling code here (after calling the PVD function).
// If you call the PVD profiling function above, adding your own profiling code here
// means it will capture the cost of the PVD zoneEnd function.
// NB: we don't have an actual profiler implementation in the snippet so we just call printf instead
printf("end: %s\n", eventName);
}
}gCustomProfilerCallback;
void initPhysics(bool interactive)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
// During the "connect" call, PVD sets itself up as the profiler if PxPvdInstrumentationFlag::ePROFILE is used.
// That is, it internally calls PxSetProfilerCallback() to setup its own profiling callback. Any calls to
// PxSetProfilerCallback() prior to calling "connect" is thus lost.
gPvd->connect(*transport, PxPvdInstrumentationFlag::eALL);
// This call should be performed after PVD is initialized, otherwise it will have no effect.
PxSetProfilerCallback(&gCustomProfilerCallback);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<5;i++)
createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f);
if(!interactive)
createDynamic(PxTransform(PxVec3(0,40,100)), PxSphereGeometry(10), PxVec3(0,-50,-100));
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{ PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
#if (PX_DEBUG || PX_CHECKED || PX_PROFILE)
printf("SnippetCustomProfiler done.\n");
#else
printf("Warning: SnippetCustomProfiler does not capture the profiler timings in release build.\n");
#endif
}
void keyPress(unsigned char key, const PxTransform& camera)
{
switch(toupper(key))
{
case 'B': createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f); break;
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet CustomProfiler");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,271 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet shows how to use deformable meshes in PhysX.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxTriangleMesh* gMesh = NULL;
PxRigidStatic* gActor = NULL;
PxReal stackZ = 10.0f;
static const PxU32 gGridSize = 8;
static const PxReal gGridStep = 512.0f / PxReal(gGridSize-1);
static float gTime = 0.0f;
static PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0), PxReal density=1.0f)
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, density);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
static void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
struct Triangle
{
PxU32 ind0, ind1, ind2;
};
static void updateVertices(PxVec3* verts, float amplitude=0.0f)
{
const PxU32 gridSize = gGridSize;
const PxReal gridStep = gGridStep;
for(PxU32 a=0; a<gridSize; a++)
{
const float coeffA = float(a)/float(gridSize);
for(PxU32 b=0; b<gridSize; b++)
{
const float coeffB = float(b)/float(gridSize);
const float y = 20.0f + sinf(coeffA*PxTwoPi)*cosf(coeffB*PxTwoPi)*amplitude;
verts[a * gridSize + b] = PxVec3(-400.0f + b*gridStep, y, -400.0f + a*gridStep);
}
}
}
static PxTriangleMesh* createMeshGround()
{
const PxU32 gridSize = gGridSize;
PxVec3 verts[gridSize * gridSize];
const PxU32 nbTriangles = 2 * (gridSize - 1) * (gridSize-1);
Triangle indices[nbTriangles];
updateVertices(verts);
for (PxU32 a = 0; a < (gridSize-1); ++a)
{
for (PxU32 b = 0; b < (gridSize-1); ++b)
{
Triangle& tri0 = indices[(a * (gridSize-1) + b) * 2];
Triangle& tri1 = indices[((a * (gridSize-1) + b) * 2) + 1];
tri0.ind0 = a * gridSize + b + 1;
tri0.ind1 = a * gridSize + b;
tri0.ind2 = (a + 1) * gridSize + b + 1;
tri1.ind0 = (a + 1) * gridSize + b + 1;
tri1.ind1 = a * gridSize + b;
tri1.ind2 = (a + 1) * gridSize + b;
}
}
PxTriangleMeshDesc meshDesc;
meshDesc.points.data = verts;
meshDesc.points.count = gridSize * gridSize;
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.count = nbTriangles;
meshDesc.triangles.data = indices;
meshDesc.triangles.stride = sizeof(Triangle);
PxTriangleMesh* triMesh = gCooking->createTriangleMesh(meshDesc, gPhysics->getPhysicsInsertionCallback());
return triMesh;
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxCookingParams cookingParams(gPhysics->getTolerancesScale());
// Deformable meshes are only supported with PxMeshMidPhase::eBVH33.
cookingParams.midphaseDesc.setToDefault(PxMeshMidPhase::eBVH33);
// We need to disable the mesh cleaning part so that the vertex mapping remains untouched.
cookingParams.meshPreprocessParams = PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH;
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, cookingParams);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxTriangleMesh* mesh = createMeshGround();
gMesh = mesh;
PxTriangleMeshGeometry geom(mesh);
PxRigidStatic* groundMesh = gPhysics->createRigidStatic(PxTransform(PxVec3(0, 2, 0)));
gActor = groundMesh;
PxShape* shape = gPhysics->createShape(geom, *gMaterial);
{
shape->setContactOffset(0.02f);
// A negative rest offset helps to avoid jittering when the deformed mesh moves away from objects resting on it.
shape->setRestOffset(-0.5f);
}
groundMesh->attachShape(*shape);
gScene->addActor(*groundMesh);
createStack(PxTransform(PxVec3(0,22,0)), 10, 2.0f);
}
void stepPhysics(bool /*interactive*/)
{
{
PxVec3* verts = gMesh->getVerticesForModification();
gTime += 0.01f;
updateVertices(verts, sinf(gTime)*20.0f);
PxBounds3 newBounds = gMesh->refitBVH();
PX_UNUSED(newBounds);
// Reset filtering to tell the broadphase about the new mesh bounds.
gScene->resetFiltering(*gActor);
}
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
PX_RELEASE(gCooking);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetDeformableMesh done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
switch(toupper(key))
{
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200, 3.0f); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,121 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet DeformableMesh");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,321 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of the dll delay load hooks in physx.
//
// The hooks are needed if the application executable either doesn't reside
// in the same directory as the PhysX dlls, or if the PhysX dlls have been renamed.
// Some PhysX dlls delay load the PhysXFoundation, PhysXCommon or PhysXGpu dlls and
// the non-standard names or loactions of these dlls need to be communicated so the
// delay loading can succeed.
//
// This snippet shows how this can be done using the delay load hooks.
//
// In order to show functionality with the renamed dlls some basic physics
// simulation is performed.
// ****************************************************************************
#include <ctype.h>
#include <wtypes.h>
#include "PxPhysicsAPI.h"
// Include the delay load hook headers
#include "common/windows/PxWindowsDelayLoadHook.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
// This snippet uses the default PhysX distro dlls, making the example here somewhat artificial,
// as default locations and default naming makes implementing delay load hooks unnecessary.
#define APP_BIN_DIR "..\\"
#if PX_WIN64
#define DLL_NAME_BITS "64"
#else
#define DLL_NAME_BITS "32"
#endif
#if PX_DEBUG
#define DLL_DIR "debug\\"
#elif PX_CHECKED
#define DLL_DIR "checked\\"
#elif PX_PROFILE
#define DLL_DIR "profile\\"
#else
#define DLL_DIR "release\\"
#endif
const char* foundationLibraryPath = APP_BIN_DIR DLL_DIR "PhysXFoundation_" DLL_NAME_BITS ".dll";
const char* commonLibraryPath = APP_BIN_DIR DLL_DIR "PhysXCommon_" DLL_NAME_BITS ".dll";
const char* physxLibraryPath = APP_BIN_DIR DLL_DIR "PhysX_" DLL_NAME_BITS ".dll";
const char* gpuLibraryPath = APP_BIN_DIR DLL_DIR "PhysXGpu_" DLL_NAME_BITS ".dll";
HMODULE foundationLibrary = NULL;
HMODULE commonLibrary = NULL;
HMODULE physxLibrary = NULL;
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
// typedef the PhysX entry points
typedef PxFoundation*(PxCreateFoundation_FUNC)(PxU32, PxAllocatorCallback&, PxErrorCallback&);
typedef PxPhysics* (PxCreatePhysics_FUNC)(PxU32,PxFoundation&,const PxTolerancesScale& scale,bool,PxPvd*);
typedef void (PxSetPhysXDelayLoadHook_FUNC)(const PxDelayLoadHook* hook);
typedef void (PxSetPhysXCommonDelayLoadHook_FUNC)(const PxDelayLoadHook* hook);
typedef void (PxSetPhysXGpuLoadHook_FUNC)(const PxGpuLoadHook* hook);
typedef int (PxGetSuggestedCudaDeviceOrdinal_FUNC)(PxErrorCallback& errc);
typedef PxCudaContextManager* (PxCreateCudaContextManager_FUNC)(PxFoundation& foundation, const PxCudaContextManagerDesc& desc, physx::PxProfilerCallback* profilerCallback);
// set the function pointers to NULL
PxCreateFoundation_FUNC* s_PxCreateFoundation_Func = NULL;
PxCreatePhysics_FUNC* s_PxCreatePhysics_Func = NULL;
PxSetPhysXDelayLoadHook_FUNC* s_PxSetPhysXDelayLoadHook_Func = NULL;
PxSetPhysXCommonDelayLoadHook_FUNC* s_PxSetPhysXCommonDelayLoadHook_Func = NULL;
PxSetPhysXGpuLoadHook_FUNC* s_PxSetPhysXGpuLoadHook_Func = NULL;
PxGetSuggestedCudaDeviceOrdinal_FUNC* s_PxGetSuggestedCudaDeviceOrdinal_Func = NULL;
PxCreateCudaContextManager_FUNC* s_PxCreateCudaContextManager_Func = NULL;
bool loadPhysicsExplicitely()
{
// load the dlls
foundationLibrary = LoadLibraryA(foundationLibraryPath);
if(!foundationLibrary)
return false;
commonLibrary = LoadLibraryA(commonLibraryPath);
if(!commonLibrary)
{
FreeLibrary(foundationLibrary);
return false;
}
physxLibrary = LoadLibraryA(physxLibraryPath);
if(!physxLibrary)
{
FreeLibrary(foundationLibrary);
FreeLibrary(commonLibrary);
return false;
}
// get the function pointers
s_PxCreateFoundation_Func = (PxCreateFoundation_FUNC*)GetProcAddress(foundationLibrary, "PxCreateFoundation");
s_PxCreatePhysics_Func = (PxCreatePhysics_FUNC*)GetProcAddress(physxLibrary, "PxCreateBasePhysics");
s_PxSetPhysXDelayLoadHook_Func = (PxSetPhysXDelayLoadHook_FUNC*)GetProcAddress(physxLibrary, "PxSetPhysXDelayLoadHook");
s_PxSetPhysXCommonDelayLoadHook_Func = (PxSetPhysXCommonDelayLoadHook_FUNC*)GetProcAddress(commonLibrary, "PxSetPhysXCommonDelayLoadHook");
s_PxSetPhysXGpuLoadHook_Func = (PxSetPhysXGpuLoadHook_FUNC*)GetProcAddress(physxLibrary, "PxSetPhysXGpuLoadHook");
s_PxGetSuggestedCudaDeviceOrdinal_Func = (PxGetSuggestedCudaDeviceOrdinal_FUNC*)GetProcAddress(physxLibrary, "PxGetSuggestedCudaDeviceOrdinal");
s_PxCreateCudaContextManager_Func = (PxCreateCudaContextManager_FUNC*)GetProcAddress(physxLibrary, "PxCreateCudaContextManager");
// check if we have all required function pointers
if(s_PxCreateFoundation_Func == NULL || s_PxCreatePhysics_Func == NULL || s_PxSetPhysXDelayLoadHook_Func == NULL || s_PxSetPhysXCommonDelayLoadHook_Func == NULL)
return false;
if(s_PxSetPhysXGpuLoadHook_Func == NULL || s_PxGetSuggestedCudaDeviceOrdinal_Func == NULL || s_PxCreateCudaContextManager_Func == NULL)
return false;
return true;
}
// unload the dlls
void unloadPhysicsExplicitely()
{
FreeLibrary(physxLibrary);
FreeLibrary(commonLibrary);
FreeLibrary(foundationLibrary);
}
// Overriding the PxDelayLoadHook allows the load of a custom name dll inside PhysX, PhysXCommon and PhysXCooking dlls
struct SnippetDelayLoadHook : public PxDelayLoadHook
{
virtual const char* getPhysXFoundationDllName() const
{
return foundationLibraryPath;
}
virtual const char* getPhysXCommonDllName() const
{
return commonLibraryPath;
}
};
// Overriding the PxGpuLoadHook allows the load of a custom GPU name dll
struct SnippetGpuLoadHook : public PxGpuLoadHook
{
virtual const char* getPhysXGpuDllName() const
{
return gpuLibraryPath;
}
};
PxReal stackZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool interactive)
{
// load the explictely named dlls
const bool isLoaded = loadPhysicsExplicitely();
if (!isLoaded)
return;
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
// set PhysX and PhysXCommon delay load hook, this must be done before the create physics is called, before
// the PhysXFoundation, PhysXCommon delay load happens.
SnippetDelayLoadHook delayLoadHook;
s_PxSetPhysXDelayLoadHook_Func(&delayLoadHook);
s_PxSetPhysXCommonDelayLoadHook_Func(&delayLoadHook);
// set PhysXGpu load hook
SnippetGpuLoadHook gpuLoadHook;
s_PxSetPhysXGpuLoadHook_Func(&gpuLoadHook);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
// We setup the delay load hooks first
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<5;i++)
createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f);
if(!interactive)
createDynamic(PxTransform(PxVec3(0,40,100)), PxSphereGeometry(10), PxVec3(0,-50,-100));
}
void stepPhysics(bool /*interactive*/)
{
if (gScene)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
unloadPhysicsExplicitely();
printf("SnippetDelayLoadHook done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
switch(toupper(key))
{
case 'B': createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f); break;
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,122 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
extern PxScene* gScene;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
if (gScene)
{
PxU32 nbActors = gScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
gScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Delay Load Hook");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,208 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates simple use of physx
//
// It creates a number of box stacks on a plane, and if rendering, allows the
// user to create new stacks and fire a ball from the camera position
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxCudaContextManager* gCudaContextManager = NULL;
PxReal stackZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport, PxPvdInstrumentationFlag::ePROFILE);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxCudaContextManagerDesc cudaContextManagerDesc;
#ifdef RENDER_SNIPPET
cudaContextManagerDesc.interopMode = PxCudaInteropMode::OGL_INTEROP; //Choose interop mode. As the snippets use OGL, we select OGL_INTEROP
//when using D3D, cudaContextManagerDesc.graphicsDevice must be set as the graphics device pointer.
#else
cudaContextManagerDesc.interopMode = PxCudaInteropMode::NO_INTEROP;
#endif
gCudaContextManager = PxCreateCudaContextManager(*gFoundation, cudaContextManagerDesc, PxGetProfilerCallback()); //Create the CUDA context manager, required for GRB to dispatch CUDA kernels.
if( gCudaContextManager )
{
if( !gCudaContextManager->contextIsValid() )
{
gCudaContextManager->release();
gCudaContextManager = NULL;
}
}
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(4); //Create a CPU dispatcher using 4 worther threads
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
sceneDesc.cudaContextManager = gCudaContextManager; //Set the CUDA context manager, used by GRB.
sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS; //Enable GPU dynamics - without this enabled, simulation (contact gen and solver) will run on the CPU.
sceneDesc.flags |= PxSceneFlag::eENABLE_PCM; //Enable PCM. PCM NP is supported on GPU. Legacy contact gen will fall back to CPU
sceneDesc.flags |= PxSceneFlag::eENABLE_STABILIZATION; //Improve solver stability by enabling post-stabilization.
sceneDesc.broadPhaseType = PxBroadPhaseType::eGPU; //Enable GPU broad phase. Without this set, broad phase will run on the CPU.
sceneDesc.gpuMaxNumPartitions = 8; //Defines the maximum number of partitions used by the solver. Only power-of-2 values are valid.
//A value of 8 generally gives best balance between performance and stability.
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if (pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, false);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, false);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, false);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<40;i++)
createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 20, 1.0f);
PxRigidDynamic* ball = createDynamic(PxTransform(PxVec3(0,20,100)), PxSphereGeometry(5), PxVec3(0,-25,-100));
PxRigidBodyExt::updateMassAndInertia(*ball, 1000.f);
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gCudaContextManager);
PX_RELEASE(gFoundation);
printf("SnippetHelloWorld done.\n");
}
void keyPress(const char key, const PxTransform& camera)
{
switch(toupper(key))
{
case 'B': createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f); break;
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(const char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, (PxActor**)&actors[0], nbActors);
Snippets::renderActors(&actors[0], (PxU32)actors.size(), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet HelloWorld");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
cleanupPhysics(true);
}
#endif

View File

@ -0,0 +1,169 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates simple use of physx
//
// It creates a number of box stacks on a plane, and if rendering, allows the
// user to create new stacks and fire a ball from the camera position
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxReal stackZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool interactive)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<5;i++)
createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f);
if(!interactive)
createDynamic(PxTransform(PxVec3(0,40,100)), PxSphereGeometry(10), PxVec3(0,-50,-100));
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetHelloWorld done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
switch(toupper(key))
{
case 'B': createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f); break;
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet HelloWorld");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "PxImmediateMode.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
extern PxU32 getNbGeoms();
extern const PxGeometryHolder* getGeoms();
extern const PxTransform* getGeomPoses();
extern PxU32 getNbContacts();
extern const Gu::ContactPoint* getContacts();
extern PxU32 getNbArticulations();
extern Dy::ArticulationV** getArticulations();
extern PxU32 getNbBounds();
extern const PxBounds3* getBounds();
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void keyboardCallback2(int key, int /*x*/, int /*y*/)
{
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
static void DrawLine(const PxVec3& p0, const PxVec3& p1, const PxVec3& color)
{
glDisable(GL_LIGHTING);
glColor4f(color.x, color.y, color.z, 1.0f);
const PxVec3 Pts[] = { p0, p1 };
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), &Pts[0].x);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_LIGHTING);
}
static void DrawFrame(const PxVec3& pt, float scale=1.0f)
{
DrawLine(pt, pt + PxVec3(scale, 0.0f, 0.0f), PxVec3(1.0f, 0.0f, 0.0f));
DrawLine(pt, pt + PxVec3(0.0f, scale, 0.0f), PxVec3(0.0f, 1.0f, 0.0f));
DrawLine(pt, pt + PxVec3(0.0f, 0.0f, scale), PxVec3(0.0f, 0.0f, 1.0f));
}
static void DrawBounds(const PxBounds3& box)
{
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), PxVec3(box.maximum.x, box.minimum.y, box.minimum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.maximum.x, box.minimum.y, box.minimum.z), PxVec3(box.maximum.x, box.maximum.y, box.minimum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.maximum.x, box.maximum.y, box.minimum.z), PxVec3(box.minimum.x, box.maximum.y, box.minimum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.minimum.x, box.maximum.y, box.minimum.z), PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), PxVec3(box.maximum.x, box.minimum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.maximum.x, box.minimum.y, box.maximum.z), PxVec3(box.maximum.x, box.maximum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.maximum.x, box.maximum.y, box.maximum.z), PxVec3(box.minimum.x, box.maximum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.minimum.x, box.maximum.y, box.maximum.z), PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.maximum.x, box.minimum.y, box.minimum.z), PxVec3(box.maximum.x, box.minimum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.maximum.x, box.maximum.y, box.minimum.z), PxVec3(box.maximum.x, box.maximum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
DrawLine(PxVec3(box.minimum.x, box.maximum.y, box.minimum.z), PxVec3(box.minimum.x, box.maximum.y, box.maximum.z), PxVec3(1.0f, 1.0f, 0.0f));
}
static void InitLighting()
{
glEnable(GL_COLOR_MATERIAL);
const float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, zero);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zero);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zero);
glEnable(GL_LIGHTING);
PxVec3 Dir(-1.0f, 1.0f, 0.5f);
// PxVec3 Dir(0.0f, 1.0f, 0.0f);
Dir.normalize();
const float AmbientValue = 0.3f;
const float ambientColor0[] = { AmbientValue, AmbientValue, AmbientValue, 0.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor0);
const float specularColor0[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor0);
const float diffuseColor0[] = { 0.7f, 0.7f, 0.7f, 0.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor0);
const float position0[] = { Dir.x, Dir.y, Dir.z, 0.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position0);
glEnable(GL_LIGHT0);
// glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
if(0)
{
glEnable(GL_FOG);
glFogi(GL_FOG_MODE,GL_LINEAR);
//glFogi(GL_FOG_MODE,GL_EXP);
//glFogi(GL_FOG_MODE,GL_EXP2);
glFogf(GL_FOG_START, 0.0f);
glFogf(GL_FOG_END, 100.0f);
glFogf(GL_FOG_DENSITY, 0.005f);
// glClearColor(0.2f, 0.2f, 0.2f, 1.0);
// const PxVec3 FogColor(0.2f, 0.2f, 0.2f);
const PxVec3 FogColor(1.0f);
glFogfv(GL_FOG_COLOR, &FogColor.x);
}
}
void renderCallback()
{
stepPhysics(true);
/* if(0)
{
PxVec3 camPos = sCamera->getEye();
PxVec3 camDir = sCamera->getDir();
printf("camPos: (%ff, %ff, %ff)\n", camPos.x, camPos.y, camPos.z);
printf("camDir: (%ff, %ff, %ff)\n", camDir.x, camDir.y, camDir.z);
}*/
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
InitLighting();
const PxVec3 color(0.6f, 0.8f, 1.0f);
// const PxVec3 color(0.75f, 0.75f, 1.0f);
// const PxVec3 color(1.0f);
Snippets::renderGeoms(getNbGeoms(), getGeoms(), getGeomPoses(), true, color);
/* PxU32 getNbGeoms();
const PxGeometry* getGeoms();
const PxTransform* getGeomPoses();
Snippets::renderGeoms(getNbGeoms(), getGeoms(), getGeomPoses(), true, PxVec3(1.0f));*/
/* PxBoxGeometry boxGeoms[10];
for(PxU32 i=0;i<10;i++)
boxGeoms[i].halfExtents = PxVec3(1.0f);
PxTransform poses[10];
for(PxU32 i=0;i<10;i++)
{
poses[i] = PxTransform(PxIdentity);
poses[i].p.y += 1.5f;
poses[i].p.x = float(i)*2.5f;
}
Snippets::renderGeoms(10, boxGeoms, poses, true, PxVec3(1.0f));*/
if(1)
{
const PxU32 nbContacts = getNbContacts();
const Gu::ContactPoint* contacts = getContacts();
for(PxU32 j=0;j<nbContacts;j++)
{
DrawFrame(contacts[j].point, 1.0f);
}
}
if(0)
{
const PxU32 nbArticulations = getNbArticulations();
Dy::ArticulationV** articulations = getArticulations();
for(PxU32 j=0;j<nbArticulations;j++)
{
immediate::PxLinkData data[64];
const PxU32 nbLinks = immediate::PxGetAllLinkData(articulations[j], data);
for(PxU32 i=0;i<nbLinks;i++)
{
DrawFrame(data[i].pose.p, 1.0f);
}
}
}
const PxBounds3* bounds = getBounds();
const PxU32 nbBounds = getNbBounds();
for(PxU32 i=0;i<nbBounds;i++)
{
DrawBounds(bounds[i]);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera( PxVec3(8.526230f, 5.546278f, 5.448466f),
PxVec3(-0.784231f, -0.210605f, -0.583632f));
Snippets::setupDefaultWindow("PhysX Snippet Immediate Articulation");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutSpecialFunc(keyboardCallback2);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(const char key, const PxTransform& camera);
extern float cameraSpeed;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if (!sCamera->handleKey(key, x, y, cameraSpeed))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir(), 10.f, 100000.f);
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], PxU32(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Immediate Mode");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,204 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates simple use of joints in physx
//
// It creates a chain of objects joined by limited spherical joints, a chain
// joined by fixed joints which is breakable, and a chain of damped D6 joints
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxReal chainZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
// spherical joint limited to an angle of at most pi/4 radians (45 degrees)
PxJoint* createLimitedSpherical(PxRigidActor* a0, const PxTransform& t0, PxRigidActor* a1, const PxTransform& t1)
{
PxSphericalJoint* j = PxSphericalJointCreate(*gPhysics, a0, t0, a1, t1);
j->setLimitCone(PxJointLimitCone(PxPi/4, PxPi/4, 0.05f));
j->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED, true);
return j;
}
// revolute joint limited to an angle of at most pi/4 radians (45 degrees)
// fixed, breakable joint
PxJoint* createBreakableFixed(PxRigidActor* a0, const PxTransform& t0, PxRigidActor* a1, const PxTransform& t1)
{
PxFixedJoint* j = PxFixedJointCreate(*gPhysics, a0, t0, a1, t1);
j->setBreakForce(1000, 100000);
j->setConstraintFlag(PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES, true);
j->setConstraintFlag(PxConstraintFlag::eDISABLE_PREPROCESSING, true);
return j;
}
// D6 joint with a spring maintaining its position
PxJoint* createDampedD6(PxRigidActor* a0, const PxTransform& t0, PxRigidActor* a1, const PxTransform& t1)
{
PxD6Joint* j = PxD6JointCreate(*gPhysics, a0, t0, a1, t1);
j->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
j->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
j->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
j->setDrive(PxD6Drive::eSLERP, PxD6JointDrive(0, 1000, FLT_MAX, true));
return j;
}
typedef PxJoint* (*JointCreateFunction)(PxRigidActor* a0, const PxTransform& t0, PxRigidActor* a1, const PxTransform& t1);
// create a chain rooted at the origin and extending along the x-axis, all transformed by the argument t.
void createChain(const PxTransform& t, PxU32 length, const PxGeometry& g, PxReal separation, JointCreateFunction createJoint)
{
PxVec3 offset(separation/2, 0, 0);
PxTransform localTm(offset);
PxRigidDynamic* prev = NULL;
for(PxU32 i=0;i<length;i++)
{
PxRigidDynamic* current = PxCreateDynamic(*gPhysics, t*localTm, g, *gMaterial, 1.0f);
(*createJoint)(prev, prev ? PxTransform(offset) : t, current, PxTransform(-offset));
gScene->addActor(*current);
prev = current;
localTm.p.x += separation;
}
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true, gPvd);
PxInitExtensions(*gPhysics, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
createChain(PxTransform(PxVec3(0.0f, 20.0f, 0.0f)), 5, PxBoxGeometry(2.0f, 0.5f, 0.5f), 4.0f, createLimitedSpherical);
createChain(PxTransform(PxVec3(0.0f, 20.0f, -10.0f)), 5, PxBoxGeometry(2.0f, 0.5f, 0.5f), 4.0f, createBreakableFixed);
createChain(PxTransform(PxVec3(0.0f, 20.0f, -20.0f)), 5, PxBoxGeometry(2.0f, 0.5f, 0.5f), 4.0f, createDampedD6);
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetJoint done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
switch(toupper(key))
{
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Joint");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,434 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates loading xml or binary serialized collections and instantiating the objects in a scene.
//
// It only compiles and runs on authoring platforms (windows, osx and linux).
// The snippet supports connecting to PVD in order to display the scene.
//
// It is a simple command-line tool supporting the following options::
// SnippetLoadCollection [--pvdhost=<ip address> ] [--pvdport=<ip port> ] [--pvdtimeout=<time ms> ] [--generateExampleFiles] <filename>...
//
// --pvdhost=<ip address> Defines ip address of PVD, default is 127.0.0.1
// --pvdport=<ip port> Defines ip port of PVD, default is 5425
// --pvdtimeout=<time ms> Defines time out of PVD, default is 10
// --generateExampleFiles Generates a set of example files
// <filename>... Input files containing serialized collections (either xml or binary)
//
// Multiple collection files can be specified. The snippet is currently restricted to load a list of collections which obey
// the following rule: The first collection needs to be complete. All following collections - if any - may only maintain
// dependencies to objects in the first collection.
//
// The set of example files that can be generated consists of
// collection.xml|collection.bin: Can be used individually.
// collectionA.xml|collectionA.bin: Can also be used individually but only contain materials and shapes without actors.
// collectionB.xml|collectionB.bin: Need to be used together with collectionA files. The actors contained in collectionB
// maintain references to objects in the collectionA.
//
// ****************************************************************************
#include "PxPhysicsAPI.h"
#include <iostream>
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
#define MAX_INPUT_FILES 16
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
PxSerializationRegistry* gSerializationRegistry = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxPvd* gPvd = NULL;
PxU8* gMemBlocks[MAX_INPUT_FILES];
PxU32 gNbMemBlocks = 0;
struct CmdLineParameters
{
const char* pvdhost;
PxU32 pvdport;
PxU32 pvdtimeout;
const char* inputFiles[MAX_INPUT_FILES];
PxU32 nbFiles;
bool generateExampleFiles;
CmdLineParameters() :
pvdhost(PVD_HOST)
, pvdport(5425)
, pvdtimeout(10)
, nbFiles(0)
, generateExampleFiles(false)
{}
} gParameters;
static bool match(const char* opt, const char* ref)
{
std::string s1(opt);
std::string s2(ref);
return !s1.compare(0, s2.length(), s2);
}
static void printHelpMsg()
{
printf("SnippetLoadCollection usage:\n"
"SnippetLoadCollection "
"[--pvdhost=<ip address> ] "
"[--pvdport=<ip port> ]"
"[--pvdtimeout=<time ms> ] "
"[--generateExampleFiles]"
"<filename>...\n\n"
"Load binary or xml serialized collections and instatiate the objects in a PhysX scene.\n");
printf("--pvdhost=<ip address> \n");
printf(" Defines ip address of PVD, default is 127.0.0.1 \n");
printf("--pvdport=<ip port> \n");
printf(" Defines ip port of PVD, default is 5425\n");
printf("--pvdtimeout=<time ms> \n");
printf(" Defines timeout of PVD, default is 10\n");
printf("--generateExampleFiles\n");
printf(" Generates a set of example files\n");
printf("<filename>...\n");
printf(" Input files (xml or binary), if a collection contains shared objects, it needs to be provided with the first file. \n\n");
}
static bool parseCommandLine(CmdLineParameters& result, int argc, const char *const*argv)
{
if( argc <= 1 )
{
printHelpMsg();
return false;
}
for(int i = 1; i < argc; ++i)
{
if(argv[i][0] != '-' || argv[i][1] != '-')
{
if (result.nbFiles < MAX_INPUT_FILES)
{
result.inputFiles[result.nbFiles++] = argv[i];
}
else
printf( "[WARNING] more input files are specified than supported (maximum %d). Ignoring the file %s\n", MAX_INPUT_FILES, argv[i] );
}
else if(match(argv[i], "--pvdhost="))
{
const char* hostStr = argv[i] + strlen("--pvdhost=");
if(hostStr)
result.pvdhost = hostStr;
}
else if(match(argv[i], "--pvdport="))
{
const char* portStr = argv[i] + strlen("--pvdport=");
if (portStr)
result.pvdport = PxU32(atoi(portStr));
}
else if(match(argv[i], "--pvdtimeout="))
{
const char* timeoutStr = argv[i] + strlen("--pvdtimeout=");
if (timeoutStr)
result.pvdtimeout = PxU32(atoi(timeoutStr));
}
else if(match(argv[i], "--generateExampleFiles"))
{
result.generateExampleFiles = true;
}
else
{
printf( "[ERROR] Unknown command line parameter \"%s\"\n", argv[i] );
printHelpMsg();
return false;
}
}
if(result.nbFiles == 0 && !result.generateExampleFiles)
{
printf( "[ERROR] parameter missing.\n" );
printHelpMsg();
return false;
}
return true;
}
static bool checkFile(bool& isBinary, const char* filename)
{
PxDefaultFileInputData fileStream(filename);
if (fileStream.getLength() == 0)
{
printf( "[ERROR] input file %s can't be opened!\n", filename);
return false;
}
char testString[17];
fileStream.read(testString, 16);
testString[16] = 0;
if (strcmp("SEBD", testString) == 0)
{
isBinary = true;
return true;
}
if (strcmp("<PhysXCollection", testString) == 0)
{
isBinary = false;
return true;
}
printf( "[ERROR] input file %s seems neither an xml nor a binary serialized collection file!\n", filename);
return false;
}
static PxCollection* deserializeCollection(PxInputData& inputData, bool isBinary, PxCollection* sharedCollection, PxSerializationRegistry& sr)
{
PxCollection* collection = NULL;
if(isBinary)
{
PxU32 length = inputData.getLength();
PxU8* memBlock = static_cast<PxU8*>(malloc(length+PX_SERIAL_FILE_ALIGN-1));
gMemBlocks[gNbMemBlocks++] = memBlock;
void* alignedBlock = reinterpret_cast<void*>((size_t(memBlock)+PX_SERIAL_FILE_ALIGN-1)&~(PX_SERIAL_FILE_ALIGN-1));
inputData.read(alignedBlock, length);
collection = PxSerialization::createCollectionFromBinary(alignedBlock, sr, sharedCollection);
}
else
{
collection = PxSerialization::createCollectionFromXml(inputData, *gCooking, sr, sharedCollection);
}
return collection;
}
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxInitExtensions(*gPhysics, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
gDispatcher = PxDefaultCpuDispatcherCreate(1);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
gSerializationRegistry = PxSerialization::createSerializationRegistry(*gPhysics);
}
void cleanupPhysics()
{
PX_RELEASE(gSerializationRegistry);
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics); // releases of all objects
PX_RELEASE(gCooking);
for(PxU32 i=0; i<gNbMemBlocks; i++)
free(gMemBlocks[i]); // now that the objects have been released, it's safe to release the space they occupy
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetLoadCollection done.\n");
}
static void serializeCollection(PxCollection& collection, PxCollection* externalRefs, const char* filename, bool toBinary)
{
PxDefaultFileOutputStream outputStream(filename);
if (!outputStream.isValid())
{
printf( "[ERROR] Could not open file %s!\n", filename);
return;
}
bool bret;
if (toBinary)
{
bret = PxSerialization::serializeCollectionToBinary(outputStream, collection, *gSerializationRegistry, externalRefs);
}
else
{
bret = PxSerialization::serializeCollectionToXml(outputStream, collection, *gSerializationRegistry, NULL, externalRefs);
}
if(bret)
printf( "Generated: \"%s\"\n", filename);
else
printf( "[ERROR] Failure when generating %s!\n", filename);
}
static void generateExampleFiles()
{
PxCollection* collection = PxCreateCollection();
PxCollection* collectionA = PxCreateCollection();
PxCollection* collectionB = PxCreateCollection();
PX_ASSERT( (collection != NULL) && (collectionA != NULL) && (collectionB != NULL) );
PxMaterial *material = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PX_ASSERT( material );
PxShape* planeShape = gPhysics->createShape(PxPlaneGeometry(), *material);
PxShape* boxShape = gPhysics->createShape(PxBoxGeometry(2.f, 2.f, 2.f), *material);
PxRigidStatic* rigidStatic = PxCreateStatic(*gPhysics, PxTransform(PxVec3(0.f, 0.f, 0.f), PxQuat(PxHalfPi, PxVec3(0.f, 0.f, 1.f))), *planeShape);
PxRigidDynamic* rigidDynamic = PxCreateDynamic(*gPhysics, PxTransform(PxVec3(0.f, 2.f, 0.f)), *boxShape, 1.f);
collection->add(*material);
collection->add(*planeShape);
collection->add(*boxShape);
collection->add(*rigidStatic);
collection->add(*rigidDynamic);
PxSerialization::complete(*collection, *gSerializationRegistry);
PX_ASSERT(PxSerialization::isSerializable(*collection, *gSerializationRegistry));
collectionA->add(*material);
collectionA->add(*planeShape);
collectionA->add(*boxShape);
PxSerialization::complete(*collectionA, *gSerializationRegistry);
PxSerialization::createSerialObjectIds(*collectionA, PxSerialObjectId(1));
PX_ASSERT(PxSerialization::isSerializable(*collectionA, *gSerializationRegistry));
collectionB->add(*rigidStatic);
collectionB->add(*rigidDynamic);
PxSerialization::complete(*collectionB, *gSerializationRegistry, collectionA);
PX_ASSERT(PxSerialization::isSerializable(*collectionB, *gSerializationRegistry, collectionA));
serializeCollection(*collection, NULL, "collection.xml", false);
serializeCollection(*collectionA, NULL, "collectionA.xml", false);
serializeCollection(*collectionB, collectionA, "collectionB.xml", false);
serializeCollection(*collection, NULL, "collection.bin", true);
serializeCollection(*collectionA, NULL, "collectionA.bin", true);
serializeCollection(*collectionB, collectionA, "collectionB.bin", true);
collection->release();
collectionA->release();
collectionB->release();
}
int snippetMain(int argc, const char *const* argv)
{
if(!parseCommandLine(gParameters, argc, argv))
return 1;
initPhysics();
if(gParameters.generateExampleFiles)
generateExampleFiles();
// collection that may have shared objects
PxCollection* firstCollection = NULL;
for(PxU32 i=0; i<gParameters.nbFiles; i++)
{
const char* filename = gParameters.inputFiles[i];
bool isBinary;
bool validFile = checkFile(isBinary, filename);
if (!validFile)
break;
PxDefaultFileInputData inputStream(filename);
PxCollection* collection = deserializeCollection(inputStream, isBinary, firstCollection, *gSerializationRegistry);
if (!collection)
{
printf( "[ERROR] deserialization failure! filename: %s\n", filename);
break;
}
else
{
printf( "Loaded: \"%s\"\n", filename);
}
gScene->addCollection(*collection);
if (i == 0)
{
firstCollection = collection;
}
else
{
collection->release();
}
}
if (firstCollection)
firstCollection->release();
for (unsigned i = 0; i < 20; i++)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
cleanupPhysics();
return 0;
}

View File

@ -0,0 +1,228 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet demonstrates the use of broad phase regions (MBP).
//
// It shows the setup of MBP and its regions. In this example 4 regions are setup
// and set for the MBP. Created stacks are then simulated in multiple regions.
// Note that current regions setup is not optimal, some objects get out of regions bounds.
// In this case a warning is reported. It is possible to add PxBroadPhaseCallback
// to scene to handle such cases.
//
// ****************************************************************************
#include <ctype.h>
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxReal stackZ = 10.0f;
PxU32 gRegionHandles[4];
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
class SnippetMBPBroadPhaseCallback : public physx::PxBroadPhaseCallback
{
std::vector<PxActor*> outOfBoundsActors;
public:
virtual void onObjectOutOfBounds(PxShape& /*shape*/, PxActor& actor)
{
PxU32 i = 0;
for(; i < outOfBoundsActors.size(); ++i)
{
if(outOfBoundsActors[i] == &actor)
break;
}
if(i == outOfBoundsActors.size())
{
outOfBoundsActors.push_back(&actor);
}
}
virtual void onObjectOutOfBounds(PxAggregate& /*aggregate*/)
{
//This test does not use aggregates so no need to do anything here
}
void purgeOutOfBoundsObjects()
{
for(PxU32 i = 0; i < outOfBoundsActors.size(); ++i)
{
outOfBoundsActors[i]->release();
}
outOfBoundsActors.clear();
}
} gBroadPhaseCallback;
void initPhysics(bool interactive)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
sceneDesc.broadPhaseType = PxBroadPhaseType::eMBP;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
PxBroadPhaseRegion regions[4] =
{
{ PxBounds3(PxVec3(-100, -100, -100), PxVec3( 0, 100, 0)), reinterpret_cast<void*>(1) },
{ PxBounds3(PxVec3(-100, -100, 0), PxVec3( 0, 100, 100)), reinterpret_cast<void*>(2) },
{ PxBounds3(PxVec3( 0, -100, -100), PxVec3(100, 100, 0)), reinterpret_cast<void*>(3) },
{ PxBounds3(PxVec3( 0, -100, 0), PxVec3(100, 100, 100)), reinterpret_cast<void*>(4) }
};
for(PxU32 i=0;i<4;i++)
gScene->addBroadPhaseRegion(regions[i]);
gScene->setBroadPhaseCallback(&gBroadPhaseCallback);
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<5;i++)
createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f);
if(!interactive)
createDynamic(PxTransform(PxVec3(0,40,100)), PxSphereGeometry(10), PxVec3(0,-50,-100));
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
gBroadPhaseCallback.purgeOutOfBoundsObjects();
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetMBP done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
switch(toupper(key))
{
case 'B': createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 10, 2.0f); break;
case ' ': createDynamic(camera, PxSphereGeometry(3.0f), camera.rotate(PxVec3(0,0,-1))*200); break;
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,121 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet MBP");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,264 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet shows how to coordinate threads performing asynchronous
// work during the scene simulation. After simulate() is called, user threads
// are started that perform ray-casts against the scene. The call to
// fetchResults() is delayed until all ray-casts have completed.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
struct RaycastThread
{
SnippetUtils::Sync* mWorkReadySyncHandle;
SnippetUtils::Thread* mThreadHandle;
};
const PxU32 gNumThreads = 1;
RaycastThread gThreads[gNumThreads];
SnippetUtils::Sync* gWorkDoneSyncHandle;
const PxI32 gRayCount = 1024;
volatile PxI32 gRaysAvailable;
volatile PxI32 gRaysCompleted;
static PxVec3 randVec3()
{
return (PxVec3(float(rand())/float(RAND_MAX),
float(rand())/float(RAND_MAX),
float(rand())/float(RAND_MAX))*2.0f - PxVec3(1.0f)).getNormalized();
}
static void threadExecute(void* data)
{
RaycastThread* raycastThread = static_cast<RaycastThread*>(data);
// Perform random raycasts against the scene until stop.
for(;;)
{
// Wait here for the sync to be set then reset the sync
// to ensure that we only perform raycast work after the
// sync has been set again.
SnippetUtils::syncWait(raycastThread->mWorkReadySyncHandle);
SnippetUtils::syncReset(raycastThread->mWorkReadySyncHandle);
// If the thread has been signaled to quit then exit this function.
if (SnippetUtils::threadQuitIsSignalled(raycastThread->mThreadHandle))
break;
// Perform a fixed number of random raycasts against the scene
// and share the work between multiple threads.
while (SnippetUtils::atomicDecrement(&gRaysAvailable) >= 0)
{
PxVec3 dir = randVec3();
PxRaycastBuffer buf;
gScene->raycast(PxVec3(0.0f), dir.getNormalized(), 1000.0f, buf, PxHitFlag::eDEFAULT);
// If this is the last raycast then signal this to the main thread.
if (SnippetUtils::atomicIncrement(&gRaysCompleted) == gRayCount)
{
SnippetUtils::syncSet(gWorkDoneSyncHandle);
}
}
}
// Quit the current thread.
SnippetUtils::threadQuit(raycastThread->mThreadHandle);
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void createPhysicsAndScene()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<5;i++)
createStack(PxTransform(PxVec3(0,0,i*10.0f)), 10, 2.0f);
}
void createRaycastThreads()
{
// Create and start threads that will perform raycasts.
// Create a sync for each thread so that a signal may be sent
// from the main thread to the raycast thread that it can start
// performing raycasts.
for (PxU32 i=0; i < gNumThreads; ++i)
{
//Create a sync.
gThreads[i].mWorkReadySyncHandle = SnippetUtils::syncCreate();
//Create and start a thread.
gThreads[i].mThreadHandle = SnippetUtils::threadCreate(threadExecute, &gThreads[i]);
}
// Create another sync so that the raycast threads can signal to the main
// thread that they have finished performing their raycasts.
gWorkDoneSyncHandle = SnippetUtils::syncCreate();
}
void initPhysics()
{
createPhysicsAndScene();
createRaycastThreads();
}
void stepPhysics()
{
// Start simulation
gScene->simulate(1.0f/60.0f);
// Start ray-cast threads
gRaysAvailable = gRayCount;
gRaysCompleted = 0;
// Signal to each raycast thread that they can start performing raycasts.
for (PxU32 i=0; i < gNumThreads; ++i)
{
SnippetUtils::syncSet(gThreads[i].mWorkReadySyncHandle);
}
// Wait for raycast threads to finish.
SnippetUtils::syncWait(gWorkDoneSyncHandle);
SnippetUtils::syncReset(gWorkDoneSyncHandle);
// Fetch simulation results
gScene->fetchResults(true);
}
void cleanupPhysics()
{
// Signal threads to quit.
for (PxU32 i=0; i < gNumThreads; ++i)
{
SnippetUtils::threadSignalQuit(gThreads[i].mThreadHandle);
SnippetUtils::syncSet(gThreads[i].mWorkReadySyncHandle);
}
// Clean up raycast threads and syncs.
for (PxU32 i=0; i < gNumThreads; ++i)
{
SnippetUtils::threadWaitForQuit(gThreads[i].mThreadHandle);
SnippetUtils::threadRelease(gThreads[i].mThreadHandle);
SnippetUtils::syncRelease(gThreads[i].mWorkReadySyncHandle);
}
// Clean up the sync for the main thread.
SnippetUtils::syncRelease(gWorkDoneSyncHandle);
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetMultiThreading done.\n");
}
int snippetMain(int, const char*const*)
{
initPhysics();
for(PxU32 i=0; i<100; ++i)
stepPhysics();
cleanupPhysics();
return 0;
}

View File

@ -0,0 +1,248 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
extern PxPhysics* gPhysics;
extern PxDefaultCpuDispatcher* gDispatcher;
extern PxMaterial* gMaterial;
#ifdef RENDER_SNIPPET
void renderScene(physx::PxScene *, physx::PxRigidActor * frame, const physx::PxVec3 & color);
#endif
class NestedScene : public PxSimulationEventCallback
{
public:
NestedScene(PxRigidDynamic* containingActor) : mContainingActor(containingActor), lastLVel(PxZero), lastAVel(PxZero)
{
//create contained scene
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
sceneDesc.simulationEventCallback = this;
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
mScene = gPhysics->createScene(sceneDesc);
//create the static environment of the contained scene out of the containing actor's geometry
//this could be any other arbitrary geometry too though
{
//the truck bed
PxShape* shape = gPhysics->createShape(PxBoxGeometry(1.8f, 0.25f, 4.5f), *gMaterial);
PxRigidStatic * staticActor = gPhysics->createRigidStatic(PxTransform(PxVec3(0.0f, 1.0f, 0.0f)));
staticActor->attachShape(*shape);
mScene->addActor(*staticActor);
}
{
//the cabin of the truck
PxShape* shape = gPhysics->createShape(PxBoxGeometry(1.7f, 0.5f, 0.9f), *gMaterial);
PxRigidStatic * staticActor = gPhysics->createRigidStatic(PxTransform(PxVec3(0.0f, 1.75f, 2.5f)));
staticActor->attachShape(*shape);
mScene->addActor(*staticActor);
}
{
//some detail thingie on the cabin
PxShape* shape = gPhysics->createShape(PxSphereGeometry(0.5f), *gMaterial);
PxRigidStatic * staticActor = gPhysics->createRigidStatic(PxTransform(PxVec3(0.6f, 2.25f, 2.75f)));
staticActor->attachShape(*shape);
mScene->addActor(*staticActor);
}
{
//a trigger shape around the truck bed. If shapes leave this, they move to the main scene.
PxShape* shape = gPhysics->createShape(PxBoxGeometry(1.8f, 3.0f, 4.5f), *gMaterial);
shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
shape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
PxRigidStatic * staticActor = gPhysics->createRigidStatic(PxTransform(PxVec3(0.0f, 1.0f, 0.0f)));
staticActor->attachShape(*shape);
mScene->addActor(*staticActor);
}
}
~NestedScene()
{
}
void createBoxStack()
{
//create a box stack inside the scene
createStack(PxTransform(PxVec3(0.0f, 3.0f, 0.0f)), 3, 0.4f);
//TODO
}
void simulate(PxScene * , PxF32 timeStep)
{
//1) mirror reference actor accelerations into scene
if (!mContainingActor->isSleeping())
{
PxVec3 lvel = mContainingActor->getLinearVelocity();
PxVec3 avel = mContainingActor->getAngularVelocity();
//note that this is actually -acc.
PxVec3 lacc = lastLVel - lvel;
//PxVec3 aacc = lastAVel - avel;
lastLVel = lvel;
lastAVel = avel;
//special sauce:
//filter out vertical movement due to suspension travel, otherwise the ride is too bumpy
lacc.y = 0.0f;
//decrease the rest of the acceleration by a bit
lacc *= 0.7f;
if (lacc.magnitudeSquared() > 0.01f) //let things sleep if the accel is too small
{
PxU32 nbActors = mScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC);
if(nbActors)
{
std::vector<PxActor*> actors(nbActors);
mScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, &actors[0], nbActors);
for(PxU32 i=0;i<nbActors;i++)
{
actors[i]->is<PxRigidBody>()->addForce(lacc, PxForceMode::eVELOCITY_CHANGE);
}
}
}
}
else
{
lastLVel = PxVec3(PxZero);
lastAVel = PxVec3(PxZero);
}
//2) simulate scene
mScene->simulate(timeStep);
mScene->fetchResults(true);
//move actors that have dropped off the truck out into the main scene
for(PxU32 i=0;i<removalQueue.size();i++)
{
mScene->removeActor(*removalQueue[i]);
//transform to the parent frame:
PxTransform localPose = removalQueue[i]->getGlobalPose();
PxTransform parentFrame = mContainingActor->getGlobalPose();
removalQueue[i]->setGlobalPose(parentFrame * localPose);
mContainingActor->getScene()->addActor(*removalQueue[i]);
}
removalQueue.clear();
}
void render()
{
#ifdef RENDER_SNIPPET
renderScene(mScene, mContainingActor, PxVec3(0.54f, 0.85f, 0.1f));
#endif
}
//simulation event callback -- we only need trigger:
void onConstraintBreak(PxConstraintInfo* , PxU32 ) { }
void onWake(PxActor** , PxU32 ) { }
void onSleep(PxActor** , PxU32 ) { }
void onContact(const PxContactPairHeader& , const PxContactPair* , PxU32 ) { }
void onTrigger(PxTriggerPair* pairs, PxU32 count)
{
for(PxU32 i=0; i < count; i++)
{
// ignore pairs when shapes have been deleted
if (pairs[i].status & PxPairFlag::eNOTIFY_TOUCH_LOST)
{
//we're not allowed to make changes in the callback, so save it for later
removalQueue.push_back(pairs[i].otherActor);
}
}
}
void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
private:
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
PxFilterData simFilterData;
simFilterData.word0 = snippetvehicle::COLLISION_FLAG_OBSTACLE;
simFilterData.word1 = snippetvehicle::COLLISION_FLAG_OBSTACLE_AGAINST;
shape->setSimulationFilterData(simFilterData);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
mScene->addActor(*body);
}
}
shape->release();
}
PxScene* mScene;
PxRigidDynamic* mContainingActor;
PxVec3 lastLVel;
PxVec3 lastAVel;
std::vector<PxRigidActor*> removalQueue;
};

View File

@ -0,0 +1,627 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet shows how to work with nested scenes.
//
// It is based on SnippetVehicleTank, which creates a tank-like vehicle
// and drives it around.
//
// In this sample we add a cargo bed to the tank which contains a bunch of dynamic
// crates. These crates have their own scene in order to reduce clutter in
// the main scene and increase performance. The geometry of the cargo bed against
// which the crates collide is also only in this 'nested scene' as static geometry.
// Meanwhile the tank only uses a single dynamic box representation in the main scene.
//
// The objects in the tank's 'nested scene' are color coded green while the objects
// in the main scene are colored red in order to visualize the distinction.
//
// In this sample the crates on the tank are tossed about by the motion of the tank
// because we apply the velocity changes of the tank to the crates as external
// impulses. These impulses can be scaled by the user to tune the precise
// desired behavior.
//
// The crates can also fall off the truck bed and onto the ground. This is detected
// by the sample by means of a trigger around the cargo bed. When crates leave
// the cargo bed they are removed from the nested scene and added to the main scene.
// There they collide with the ground plane and the tank's wheels as expected.
//
// In a real game one could additionally suspend simulation of the embedded scene if
// the tank is far away from the player.
//
// ****************************************************************************
#include <vector>
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetvehiclecommon/SnippetVehicleSceneQuery.h"
#include "../snippetvehiclecommon/SnippetVehicleFilterShader.h"
#include "../snippetvehiclecommon/SnippetVehicleTireFriction.h"
#include "../snippetvehiclecommon/SnippetVehicleCreate.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
using namespace snippetvehicle;
#include "NestedScene.h"
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxCooking* gCooking = NULL;
PxMaterial* gMaterial = NULL;
VehicleSceneQueryData* gVehicleSceneQueryData = NULL;
PxBatchQuery* gBatchQuery = NULL;
PxVehicleDrivableSurfaceToTireFrictionPairs* gFrictionPairs = NULL;
PxRigidStatic* gGroundPlane = NULL;
PxPvd* gPvd = NULL;
PxF32 gTankModeLifetime = 4.0f;
PxF32 gTankModeTimer = 0.0f;
PxU32 gTankOrderProgress = 0;
bool gTankOrderComplete = false;
bool gMimicKeyInputs = false;
VehicleDesc initTankDesc();
class TankEntity
{
public:
TankEntity() : mVehicleDriveTank(NULL), mNestedScene(NULL)
{
}
~TankEntity()
{
if (mNestedScene)
{
delete mNestedScene;
mNestedScene = NULL;
}
}
void create()
{
PX_ASSERT(mVehicleDriveTank == NULL);
PX_ASSERT(mNestedScene == NULL);
VehicleDesc tankDesc = initTankDesc();
mVehicleDriveTank = createVehicleTank(tankDesc, gPhysics, gCooking);
PxTransform startTransform(PxVec3(0, (tankDesc.chassisDims.y*0.5f + tankDesc.wheelRadius + 1.0f), 0), PxQuat(PxIdentity));
mVehicleDriveTank->getRigidDynamicActor()->setGlobalPose(startTransform);
gScene->addActor(*mVehicleDriveTank->getRigidDynamicActor());
//Set the tank to rest in first gear.
//Set the tank to use auto-gears.
//Set the tank to use the standard control model
mVehicleDriveTank->setToRestState();
mVehicleDriveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
mVehicleDriveTank->mDriveDynData.setUseAutoGears(true);
mVehicleDriveTank->setDriveModel(PxVehicleDriveTankControlModel::eSTANDARD);
mNestedScene = new NestedScene(mVehicleDriveTank->getRigidDynamicActor());
mNestedScene->createBoxStack(); //can create stuff inside that scene now ... let's say this is the cargo of the vehicle.
}
void simulate(PxScene * scene, PxF32 timeStep)
{
PX_ASSERT(mNestedScene != NULL);
mNestedScene->simulate(scene, timeStep);
}
void render()
{
PX_ASSERT(mNestedScene != NULL);
mNestedScene->render();
}
void reverse()
{
mVehicleDriveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eREVERSE);
}
void forward()
{
mVehicleDriveTank->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
}
PxVehicleDriveTank* getVehicleDriveTank() { return mVehicleDriveTank; }
private:
PxVehicleDriveTank* mVehicleDriveTank;
NestedScene* mNestedScene;
} tankEntity;
PxVehicleKeySmoothingData gKeySmoothingData=
{
{
6.0f, //rise rate eANALOG_INPUT_ACCEL=0,
6.0f, //rise rate eANALOG_INPUT_BRAKE,
6.0f, //rise rate eANALOG_INPUT_HANDBRAKE,
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT,
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT,
},
{
10.0f, //fall rate eANALOG_INPUT_ACCEL=0,
10.0f, //fall rate eANALOG_INPUT_BRAKE,
10.0f, //fall rate eANALOG_INPUT_HANDBRAKE,
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT,
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT,
}
};
PxVehiclePadSmoothingData gPadSmoothingData=
{
{
6.0f, //rise rate eANALOG_INPUT_ACCEL=0,
6.0f, //rise rate eANALOG_INPUT_BRAKE,
6.0f, //rise rate eANALOG_INPUT_HANDBRAKE,
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT,
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT,
},
{
10.0f, //fall rate eANALOG_INPUT_ACCEL=0
10.0f, //fall rate eANALOG_INPUT_BRAKE_LEFT
10.0f, //fall rate eANALOG_INPUT_BRAKE_RIGHT
5.0f, //fall rate eANALOG_INPUT_THRUST_LEFT
5.0f //fall rate eANALOG_INPUT_THRUST_RIGHT
}
};
PxVehicleDriveTankRawInputData gVehicleInputData(PxVehicleDriveTankControlModel::eSTANDARD);
enum DriveMode
{
eDRIVE_MODE_ACCEL_FORWARDS=0,
eDRIVE_MODE_ACCEL_REVERSE,
eDRIVE_MODE_HARD_TURN_LEFT,
eDRIVE_MODE_SOFT_TURN_LEFT,
eDRIVE_MODE_HARD_TURN_RIGHT,
eDRIVE_MODE_SOFT_TURN_RIGHT,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_NONE
};
DriveMode gDriveModeOrder[] =
{
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_ACCEL_FORWARDS,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_ACCEL_REVERSE,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_HARD_TURN_LEFT,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_HARD_TURN_RIGHT,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_SOFT_TURN_LEFT,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_SOFT_TURN_RIGHT,
eDRIVE_MODE_NONE
};
VehicleDesc initTankDesc()
{
//Set up the chassis mass, dimensions, moment of inertia, and center of mass offset.
//The moment of inertia is just the moment of inertia of a cuboid but modified for easier steering.
//Center of mass offset is 0.65m above the base of the chassis and 0.25m towards the front.
const PxF32 chassisMass = 1500.0f;
const PxVec3 chassisDims(3.5f,2.0f,9.0f);
const PxVec3 chassisMOI
((chassisDims.y*chassisDims.y + chassisDims.z*chassisDims.z)*chassisMass/12.0f,
(chassisDims.x*chassisDims.x + chassisDims.z*chassisDims.z)*0.8f*chassisMass/12.0f,
(chassisDims.x*chassisDims.x + chassisDims.y*chassisDims.y)*chassisMass/12.0f);
const PxVec3 chassisCMOffset(0.0f, -chassisDims.y*0.5f + 0.65f, 0.25f);
//Set up the wheel mass, radius, width, moment of inertia, and number of wheels.
//Moment of inertia is just the moment of inertia of a cylinder.
const PxF32 wheelMass = 20.0f;
const PxF32 wheelRadius = 0.5f;
const PxF32 wheelWidth = 0.4f;
const PxF32 wheelMOI = 0.5f*wheelMass*wheelRadius*wheelRadius;
const PxU32 nbWheels = 14;
VehicleDesc tankDesc;
tankDesc.chassisMass = chassisMass;
tankDesc.chassisDims = chassisDims;
tankDesc.chassisMOI = chassisMOI;
tankDesc.chassisCMOffset = chassisCMOffset;
tankDesc.chassisMaterial = gMaterial;
tankDesc.wheelMass = wheelMass;
tankDesc.wheelRadius = wheelRadius;
tankDesc.wheelWidth = wheelWidth;
tankDesc.wheelMOI = wheelMOI;
tankDesc.numWheels = nbWheels;
tankDesc.wheelMaterial = gMaterial;
return tankDesc;
}
void startAccelerateForwardsMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalLeftThrust(true);
gVehicleInputData.setDigitalRightThrust(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogLeftThrust(1.0f);
gVehicleInputData.setAnalogRightThrust(1.0f);
}
}
void startAccelerateReverseMode()
{
tankEntity.reverse();
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalLeftThrust(true);
gVehicleInputData.setDigitalRightThrust(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogLeftThrust(1.0f);
gVehicleInputData.setAnalogRightThrust(1.0f);
}
}
void startBrakeMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalLeftBrake(true);
gVehicleInputData.setDigitalRightBrake(true);
}
else
{
gVehicleInputData.setAnalogLeftBrake(1.0f);
gVehicleInputData.setAnalogRightBrake(1.0f);
}
}
void startTurnHardLeftMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalLeftThrust(true);
gVehicleInputData.setDigitalRightBrake(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogLeftThrust(1.0f);
gVehicleInputData.setAnalogRightBrake(1.0f);
}
}
void startTurnHardRightMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalRightThrust(true);
gVehicleInputData.setDigitalLeftBrake(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogRightThrust(1.0f);
gVehicleInputData.setAnalogLeftBrake(1.0f);
}
}
void startTurnSoftLeftMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalLeftThrust(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogLeftThrust(1.0f);
gVehicleInputData.setAnalogRightThrust(0.3f);
}
}
void startTurnSoftRightMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalRightThrust(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogRightThrust(1.0f);
gVehicleInputData.setAnalogLeftThrust(0.3f);
}
}
void releaseAllControls()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(false);
gVehicleInputData.setDigitalRightThrust(false);
gVehicleInputData.setDigitalLeftThrust(false);
gVehicleInputData.setDigitalRightBrake(false);
gVehicleInputData.setDigitalLeftBrake(false);
}
else
{
gVehicleInputData.setAnalogAccel(0.0f);
gVehicleInputData.setAnalogRightThrust(0.0f);
gVehicleInputData.setAnalogLeftThrust(0.0f);
gVehicleInputData.setAnalogRightBrake(0.0f);
gVehicleInputData.setAnalogLeftBrake(0.0f);
}
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
PxU32 numWorkers = 1;
gDispatcher = PxDefaultCpuDispatcherCreate(numWorkers);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = VehicleFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
/////////////////////////////////////////////
PxInitVehicleSDK(*gPhysics);
PxVehicleSetBasisVectors(PxVec3(0,1,0), PxVec3(0,0,1));
PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
//Create the batched scene queries for the suspension raycasts.
gVehicleSceneQueryData = VehicleSceneQueryData::allocate(1, PX_MAX_NB_WHEELS, 1, 1, WheelSceneQueryPreFilterBlocking, NULL, gAllocator);
gBatchQuery = VehicleSceneQueryData::setUpBatchedSceneQuery(0, *gVehicleSceneQueryData, gScene);
//Create the friction table for each combination of tire and surface type.
gFrictionPairs = createFrictionPairs(gMaterial);
//Create a plane to drive on.
PxFilterData groundPlaneSimFilterData(COLLISION_FLAG_GROUND, COLLISION_FLAG_GROUND_AGAINST, 0, 0);
gGroundPlane = createDrivablePlane(groundPlaneSimFilterData, gMaterial, gPhysics);
gScene->addActor(*gGroundPlane);
//Create a tank that will drive on the plane.
tankEntity.create();
gTankModeTimer = 0.0f;
gTankOrderProgress = 0;
startBrakeMode();
}
void incrementDrivingMode(const PxF32 timestep)
{
gTankModeTimer += timestep;
if(gTankModeTimer > gTankModeLifetime)
{
//If the mode just completed was eDRIVE_MODE_ACCEL_REVERSE then switch back to forward gears.
if(eDRIVE_MODE_ACCEL_REVERSE == gDriveModeOrder[gTankOrderProgress])
{
tankEntity.forward();
}
//Increment to next driving mode.
gTankModeTimer = 0.0f;
gTankOrderProgress++;
releaseAllControls();
//If we are at the end of the list of driving modes then start again.
if(eDRIVE_MODE_NONE == gDriveModeOrder[gTankOrderProgress])
{
gTankOrderProgress = 0;
gTankOrderComplete = true;
}
//Start driving in the selected mode.
DriveMode eDriveMode = gDriveModeOrder[gTankOrderProgress];
switch(eDriveMode)
{
case eDRIVE_MODE_ACCEL_FORWARDS:
startAccelerateForwardsMode();
break;
case eDRIVE_MODE_ACCEL_REVERSE:
startAccelerateReverseMode();
break;
case eDRIVE_MODE_HARD_TURN_LEFT:
startTurnHardLeftMode();
break;
case eDRIVE_MODE_SOFT_TURN_LEFT:
startTurnSoftLeftMode();
break;
case eDRIVE_MODE_HARD_TURN_RIGHT:
startTurnHardRightMode();
break;
case eDRIVE_MODE_SOFT_TURN_RIGHT:
startTurnSoftRightMode();
break;
case eDRIVE_MODE_BRAKE:
startBrakeMode();
break;
case eDRIVE_MODE_NONE:
break;
};
//If the mode about to start is eDRIVE_MODE_ACCEL_REVERSE then switch to reverse gears.
if(eDRIVE_MODE_ACCEL_REVERSE == gDriveModeOrder[gTankOrderProgress])
{
tankEntity.reverse();
}
}
}
void stepPhysics(bool /*interactive*/)
{
const PxF32 timestep = 1.0f/60.0f;
//Cycle through the driving modes.
incrementDrivingMode(timestep);
//Update the control inputs for the tank.
if(gMimicKeyInputs)
{
PxVehicleDriveTankSmoothDigitalRawInputsAndSetAnalogInputs(gKeySmoothingData, gVehicleInputData, timestep, *tankEntity.getVehicleDriveTank());
}
else
{
PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs(gPadSmoothingData, gVehicleInputData, timestep, *tankEntity.getVehicleDriveTank());
}
//Raycasts.
PxVehicleWheels* vehicles[1] = {tankEntity.getVehicleDriveTank()};
PxVehicleSuspensionRaycasts(gBatchQuery, 1, vehicles, gVehicleSceneQueryData->getQueryResultBufferSize(), gVehicleSceneQueryData->getRaycastQueryResultBuffer(0));
//Vehicle update.
const PxVec3 grav = gScene->getGravity();
PxWheelQueryResult wheelQueryResults[PX_MAX_NB_WHEELS];
PxVehicleWheelQueryResult vehicleQueryResults[1] = {{wheelQueryResults, tankEntity.getVehicleDriveTank()->mWheelsSimData.getNbWheels()}};
PxVehicleUpdates(timestep, grav, *gFrictionPairs, 1, vehicles, vehicleQueryResults);
//Scene update.
gScene->simulate(timestep);
gScene->fetchResults(true);
tankEntity.simulate(gScene, timestep);
}
void renderPhysics()
{
#ifdef RENDER_SNIPPET
renderScene(gScene, NULL, PxVec3(0.94f, 0.25f, 0.5f));
#endif
tankEntity.render();
}
void cleanupPhysics(bool /*interactive*/)
{
gVehicleSceneQueryData->free(gAllocator);
PX_RELEASE(gFrictionPairs);
PxCloseVehicleSDK();
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
PX_RELEASE(gCooking);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetNestedScene done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
PX_UNUSED(camera);
PX_UNUSED(key);
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics(false);
while(!gTankOrderComplete)
{
stepPhysics(false);
}
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,134 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void renderPhysics();
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
extern PxScene* gScene;
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderScene(physx::PxScene * scene, physx::PxRigidActor * referenceFrame, const physx::PxVec3 & color)
{
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
glPushMatrix();
if (referenceFrame)
{
const PxMat44 actorPose( referenceFrame->getGlobalPose());
glMultMatrixf(reinterpret_cast<const float*>(&actorPose));
}
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), referenceFrame == NULL, color);
glPopMatrix();
}
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
renderPhysics();
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(10.0f, 10.0f, 10.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Nested Scene");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,268 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the usage of PxPruningStructure.
//
// It creates a box stack, then prepares a pruning structure. This structure
// together with the actors is serialized into a collection. When the collection
// is added to the scene, the actor's scene query shape AABBs are directly merged
// into the current scene query AABB tree through the precomputed pruning structure.
// This may unbalance the AABB tree but should provide significant speedup in
// case of large world scenarios where parts get streamed in on the fly.
// ****************************************************************************
#include <ctype.h>
#include <vector>
#include "PxPhysicsAPI.h"
#include "extensions/PxCollectionExt.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
#define MAX_MEMBLOCKS 10
PxU8* gMemBlocks[MAX_MEMBLOCKS];
PxU32 gMemBlockCount = 0;
PxReal stackZ = 10.0f;
/**
Allocates 128 byte aligned memory block for binary serialized data
Stores pointer to memory in gMemBlocks for later deallocation
*/
void* createAlignedBlock(PxU32 size)
{
PX_ASSERT(gMemBlockCount < MAX_MEMBLOCKS);
PxU8* baseAddr = static_cast<PxU8*>(malloc(size + PX_SERIAL_FILE_ALIGN - 1));
gMemBlocks[gMemBlockCount++] = baseAddr;
void* alignedBlock = reinterpret_cast<void*>((size_t(baseAddr) + PX_SERIAL_FILE_ALIGN - 1)&~(PX_SERIAL_FILE_ALIGN - 1));
return alignedBlock;
}
// Create a regular stack, with actors added directly into a scene.
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
// Create a stack where pruning structure is build in runtime and used to merge
// the query shapes into the AABB tree.
void createStackWithRuntimePrunerStructure(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
std::vector<PxRigidActor*> actors;
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for (PxU32 i = 0; i < size; i++)
{
for (PxU32 j = 0; j < size - i; j++)
{
PxTransform localTm(PxVec3(PxReal(j * 2) - PxReal(size - i), PxReal(i * 2 + 1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
// store the actors, will be added later
actors.push_back(body);
}
}
shape->release();
// Create pruning structure from given actors.
PxPruningStructure* ps = gPhysics->createPruningStructure(&actors[0], PxU32(actors.size()));
// Add actors into a scene together with the precomputed pruning structure.
gScene->addActors(*ps);
ps->release();
}
// Create a stack where pruning structure is build in runtime and then stored into a collection.
// The collection is stored into a stream and loaded into another stream. The loaded collection
// is added to a scene. While the collection is added to the scene the pruning structure is used.
void createStackWithSerializedPrunerStructure(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxCollection* collection = PxCreateCollection(); // collection for all the objects
PxSerializationRegistry* sr = PxSerialization::createSerializationRegistry(*gPhysics);
std::vector<PxRigidActor*> actors;
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for (PxU32 i = 0; i < size; i++)
{
for (PxU32 j = 0; j < size - i; j++)
{
PxTransform localTm(PxVec3(PxReal(j * 2) - PxReal(size - i), PxReal(i * 2 + 1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
// store the actors, will be added later
actors.push_back(body);
}
}
collection->add(*shape);
// Create pruner structure from given actors.
PxPruningStructure* ps = gPhysics->createPruningStructure(&actors[0], PxU32(actors.size()));
// Add the pruning structure into the collection. Adding the pruning structure will automatically
// add the actors from which the collection was build.
collection->add(*ps);
PxSerialization::complete(*collection, *sr);
// Store the collection into a stream.
PxDefaultMemoryOutputStream outStream;
PxSerialization::serializeCollectionToBinary(outStream, *collection, *sr);
collection->release();
// Release the used items added to the collection.
ps->release();
for (size_t i = 0; i < actors.size(); i++)
{
actors[i]->release();
}
shape->release();
// Load collection from the stream into and input stream.
PxDefaultMemoryInputData inputStream(outStream.getData(), outStream.getSize());
void* alignedBlock = createAlignedBlock(inputStream.getLength());
inputStream.read(alignedBlock, inputStream.getLength());
PxCollection* collection1 = PxSerialization::createCollectionFromBinary(alignedBlock, *sr);
// Add collection to the scene.
gScene->addCollection(*collection1);
// Release objects in collection, the pruning structure must be released before its actors
// otherwise actors will still be part of pruning structure
PxCollectionExt::releaseObjects(*collection1);
collection1->release();
}
void initPhysics(bool )
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport, PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
// Create a regular stack.
createStack(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 3, 2.0f);
// Create a stack using the runtime pruner structure usage.
createStackWithRuntimePrunerStructure(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 3, 2.0f);
// Create a stack using the serialized pruner structure usage.
createStackWithSerializedPrunerStructure(PxTransform(PxVec3(0,0,stackZ-=10.0f)), 3, 2.0f);
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
// Now that the objects have been released, it's safe to release the space they occupy.
for (PxU32 i = 0; i < gMemBlockCount; i++)
free(gMemBlocks[i]);
gMemBlockCount = 0;
PX_RELEASE(gFoundation);
printf("SnippetPrunerSerialization done.\n");
}
int snippetMain(int, const char*const*)
{
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
return 0;
}

View File

@ -0,0 +1,186 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates how to use the raycast CCD extension.
//
// It creates a simple box stack and a fast moving sphere. Without CCD the
// sphere goes through the box stack. With raycast CCD the sphere hits the
// stack and the behavior is more convincing.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "extensions/PxRaycastCCD.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
static const bool gEnableRaycastCCD = true; // Switch to false to see the sphere go through the box stack without CCD.
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
RaycastCCDManager* gRaycastCCD = NULL;
PxReal stackZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
createStack(PxTransform(PxVec3(0,0,stackZ)), 10, 2.0f);
// Create a fast moving sphere which goes through the box stack without CCD.
PxRigidDynamic* actor = createDynamic(PxTransform(PxVec3(0.0f, 20.0f, 100.0f)), PxSphereGeometry(2.0f), PxVec3(0.0f, 0.0f, -1000.0f));
if(gEnableRaycastCCD)
{
PxShape* shape;
actor->getShapes(&shape, 1);
gRaycastCCD = new RaycastCCDManager(gScene);
// Register each object for which CCD should be enabled. In this snippet we only enable it for the sphere.
gRaycastCCD->registerRaycastCCDObject(actor, shape);
}
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
// Simply call this after fetchResults to perform CCD raycasts.
if(gRaycastCCD)
gRaycastCCD->doRaycastCCD(true);
}
void cleanupPhysics(bool /*interactive*/)
{
if(gRaycastCCD)
delete gRaycastCCD;
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetRaycastCCD done.\n");
}
void keyPress(unsigned char /*key*/, const PxTransform& /*camera*/)
{
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet RaycastCCD");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,122 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "SnippetCamera.h"
#include <ctype.h>
#include "foundation/PxMat33.h"
using namespace physx;
namespace Snippets
{
Camera::Camera(const PxVec3& eye, const PxVec3& dir)
{
mEye = eye;
mDir = dir.getNormalized();
mMouseX = 0;
mMouseY = 0;
}
void Camera::handleMouse(int button, int state, int x, int y)
{
PX_UNUSED(state);
PX_UNUSED(button);
mMouseX = x;
mMouseY = y;
}
bool Camera::handleKey(unsigned char key, int x, int y, float speed)
{
PX_UNUSED(x);
PX_UNUSED(y);
PxVec3 viewY = mDir.cross(PxVec3(0,1,0)).getNormalized();
switch(toupper(key))
{
case 'W': mEye += mDir*2.0f*speed; break;
case 'S': mEye -= mDir*2.0f*speed; break;
case 'A': mEye -= viewY*2.0f*speed; break;
case 'D': mEye += viewY*2.0f*speed; break;
default: return false;
}
return true;
}
void Camera::handleAnalogMove(float x, float y)
{
PxVec3 viewY = mDir.cross(PxVec3(0,1,0)).getNormalized();
mEye += mDir*y;
mEye += viewY*x;
}
void Camera::handleMotion(int x, int y)
{
int dx = mMouseX - x;
int dy = mMouseY - y;
PxVec3 viewY = mDir.cross(PxVec3(0,1,0)).getNormalized();
PxQuat qx(PxPi * dx / 180.0f, PxVec3(0,1,0));
mDir = qx.rotate(mDir);
PxQuat qy(PxPi * dy / 180.0f, viewY);
mDir = qy.rotate(mDir);
mDir.normalize();
mMouseX = x;
mMouseY = y;
}
PxTransform Camera::getTransform() const
{
PxVec3 viewY = mDir.cross(PxVec3(0,1,0));
if(viewY.normalize()<1e-6f)
return PxTransform(mEye);
PxMat33 m(mDir.cross(viewY), viewY, -mDir);
return PxTransform(mEye, PxQuat(m));
}
PxVec3 Camera::getEye() const
{
return mEye;
}
PxVec3 Camera::getDir() const
{
return mDir;
}
}

View File

@ -0,0 +1,62 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PHYSX_SNIPPET_CAMERA_H
#define PHYSX_SNIPPET_CAMERA_H
#include "foundation/PxTransform.h"
namespace Snippets
{
class Camera
{
public:
Camera(const physx::PxVec3 &eye, const physx::PxVec3& dir);
void handleMouse(int button, int state, int x, int y);
bool handleKey(unsigned char key, int x, int y, float speed = 1.0f);
void handleMotion(int x, int y);
void handleAnalogMove(float x, float y);
physx::PxVec3 getEye() const;
physx::PxVec3 getDir() const;
physx::PxTransform getTransform() const;
private:
physx::PxVec3 mEye;
physx::PxVec3 mDir;
int mMouseX;
int mMouseY;
};
}
#endif //PHYSX_SNIPPET_CAMERA_H

View File

@ -0,0 +1,441 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "SnippetRender.h"
#define MAX_NUM_ACTOR_SHAPES 128
using namespace physx;
static float gCylinderData[]={
1.0f,0.0f,1.0f,1.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f,
0.866025f,0.500000f,1.0f,0.866025f,0.500000f,1.0f,0.866025f,0.500000f,0.0f,0.866025f,0.500000f,0.0f,
0.500000f,0.866025f,1.0f,0.500000f,0.866025f,1.0f,0.500000f,0.866025f,0.0f,0.500000f,0.866025f,0.0f,
-0.0f,1.0f,1.0f,-0.0f,1.0f,1.0f,-0.0f,1.0f,0.0f,-0.0f,1.0f,0.0f,
-0.500000f,0.866025f,1.0f,-0.500000f,0.866025f,1.0f,-0.500000f,0.866025f,0.0f,-0.500000f,0.866025f,0.0f,
-0.866025f,0.500000f,1.0f,-0.866025f,0.500000f,1.0f,-0.866025f,0.500000f,0.0f,-0.866025f,0.500000f,0.0f,
-1.0f,-0.0f,1.0f,-1.0f,-0.0f,1.0f,-1.0f,-0.0f,0.0f,-1.0f,-0.0f,0.0f,
-0.866025f,-0.500000f,1.0f,-0.866025f,-0.500000f,1.0f,-0.866025f,-0.500000f,0.0f,-0.866025f,-0.500000f,0.0f,
-0.500000f,-0.866025f,1.0f,-0.500000f,-0.866025f,1.0f,-0.500000f,-0.866025f,0.0f,-0.500000f,-0.866025f,0.0f,
0.0f,-1.0f,1.0f,0.0f,-1.0f,1.0f,0.0f,-1.0f,0.0f,0.0f,-1.0f,0.0f,
0.500000f,-0.866025f,1.0f,0.500000f,-0.866025f,1.0f,0.500000f,-0.866025f,0.0f,0.500000f,-0.866025f,0.0f,
0.866026f,-0.500000f,1.0f,0.866026f,-0.500000f,1.0f,0.866026f,-0.500000f,0.0f,0.866026f,-0.500000f,0.0f,
1.0f,0.0f,1.0f,1.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f
};
#define MAX_NUM_MESH_VEC3S 1024
static PxVec3 gVertexBuffer[MAX_NUM_MESH_VEC3S];
static void renderGeometry(const PxGeometry& geom)
{
switch(geom.getType())
{
case PxGeometryType::eBOX:
{
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
glScalef(boxGeom.halfExtents.x, boxGeom.halfExtents.y, boxGeom.halfExtents.z);
glutSolidCube(2);
}
break;
case PxGeometryType::eSPHERE:
{
const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom);
glutSolidSphere(GLdouble(sphereGeom.radius), 10, 10);
}
break;
case PxGeometryType::eCAPSULE:
{
const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom);
const PxF32 radius = capsuleGeom.radius;
const PxF32 halfHeight = capsuleGeom.halfHeight;
//Sphere
glPushMatrix();
glTranslatef(halfHeight, 0.0f, 0.0f);
glScalef(radius,radius,radius);
glutSolidSphere(1, 10, 10);
glPopMatrix();
//Sphere
glPushMatrix();
glTranslatef(-halfHeight, 0.0f, 0.0f);
glScalef(radius,radius,radius);
glutSolidSphere(1, 10, 10);
glPopMatrix();
//Cylinder
glPushMatrix();
glTranslatef(-halfHeight, 0.0f, 0.0f);
glScalef(2.0f*halfHeight, radius,radius);
glRotatef(90.0f,0.0f,1.0f,0.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gCylinderData);
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gCylinderData+3);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 13*2);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glPopMatrix();
}
break;
case PxGeometryType::eCONVEXMESH:
{
const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom);
//Compute triangles for each polygon.
const PxVec3& scale = convexGeom.scale.scale;
PxConvexMesh* mesh = convexGeom.convexMesh;
const PxU32 nbPolys = mesh->getNbPolygons();
const PxU8* polygons = mesh->getIndexBuffer();
const PxVec3* verts = mesh->getVertices();
PxU32 nbVerts = mesh->getNbVertices();
PX_UNUSED(nbVerts);
PxU32 numTotalTriangles = 0;
for(PxU32 i = 0; i < nbPolys; i++)
{
PxHullPolygon data;
mesh->getPolygonData(i, data);
const PxU32 nbTris = PxU32(data.mNbVerts - 2);
const PxU8 vref0 = polygons[data.mIndexBase + 0];
PX_ASSERT(vref0 < nbVerts);
for(PxU32 j=0;j<nbTris;j++)
{
const PxU32 vref1 = polygons[data.mIndexBase + 0 + j + 1];
const PxU32 vref2 = polygons[data.mIndexBase + 0 + j + 2];
//generate face normal:
PxVec3 e0 = verts[vref1] - verts[vref0];
PxVec3 e1 = verts[vref2] - verts[vref0];
PX_ASSERT(vref1 < nbVerts);
PX_ASSERT(vref2 < nbVerts);
PxVec3 fnormal = e0.cross(e1);
fnormal.normalize();
if(numTotalTriangles*6 < MAX_NUM_MESH_VEC3S)
{
gVertexBuffer[numTotalTriangles*6 + 0] = fnormal;
gVertexBuffer[numTotalTriangles*6 + 1] = verts[vref0];
gVertexBuffer[numTotalTriangles*6 + 2] = fnormal;
gVertexBuffer[numTotalTriangles*6 + 3] = verts[vref1];
gVertexBuffer[numTotalTriangles*6 + 4] = fnormal;
gVertexBuffer[numTotalTriangles*6 + 5] = verts[vref2];
numTotalTriangles++;
}
}
}
glPushMatrix();
glScalef(scale.x, scale.y, scale.z);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gVertexBuffer);
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gVertexBuffer+1);
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
glPopMatrix();
}
break;
case PxGeometryType::eTRIANGLEMESH:
{
const PxTriangleMeshGeometry& triGeom = static_cast<const PxTriangleMeshGeometry&>(geom);
const PxTriangleMesh& mesh = *triGeom.triangleMesh;
const PxVec3 scale = triGeom.scale.scale;
const PxU32 triangleCount = mesh.getNbTriangles();
const PxU32 has16BitIndices = mesh.getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES;
const void* indexBuffer = mesh.getTriangles();
const PxVec3* vertexBuffer = mesh.getVertices();
const PxU32* intIndices = reinterpret_cast<const PxU32*>(indexBuffer);
const PxU16* shortIndices = reinterpret_cast<const PxU16*>(indexBuffer);
PxU32 numTotalTriangles = 0;
for(PxU32 i=0; i < triangleCount; ++i)
{
PxVec3 triVert[3];
if(has16BitIndices)
{
triVert[0] = vertexBuffer[*shortIndices++];
triVert[1] = vertexBuffer[*shortIndices++];
triVert[2] = vertexBuffer[*shortIndices++];
}
else
{
triVert[0] = vertexBuffer[*intIndices++];
triVert[1] = vertexBuffer[*intIndices++];
triVert[2] = vertexBuffer[*intIndices++];
}
PxVec3 fnormal = (triVert[1] - triVert[0]).cross(triVert[2] - triVert[0]);
fnormal.normalize();
if(numTotalTriangles*6 < MAX_NUM_MESH_VEC3S)
{
gVertexBuffer[numTotalTriangles*6 + 0] = fnormal;
gVertexBuffer[numTotalTriangles*6 + 1] = triVert[0];
gVertexBuffer[numTotalTriangles*6 + 2] = fnormal;
gVertexBuffer[numTotalTriangles*6 + 3] = triVert[1];
gVertexBuffer[numTotalTriangles*6 + 4] = fnormal;
gVertexBuffer[numTotalTriangles*6 + 5] = triVert[2];
numTotalTriangles++;
}
}
glPushMatrix();
glScalef(scale.x, scale.y, scale.z);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gVertexBuffer);
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gVertexBuffer+1);
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glPopMatrix();
}
break;
case PxGeometryType::eINVALID:
case PxGeometryType::eHEIGHTFIELD:
case PxGeometryType::eGEOMETRY_COUNT:
case PxGeometryType::ePLANE:
break;
}
}
static PX_FORCE_INLINE void renderGeometryHolder(const PxGeometryHolder& h)
{
renderGeometry(h.any());
}
namespace Snippets
{
static void reshapeCallback(int width, int height)
{
glViewport(0, 0, width, height);
}
void setupDefaultWindow(const char *name)
{
char* namestr = new char[strlen(name)+1];
strcpy(namestr, name);
int argc = 1;
char* argv[1] = { namestr };
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
int mainHandle = glutCreateWindow(name);
glutSetWindow(mainHandle);
glutReshapeFunc(reshapeCallback);
delete[] namestr;
}
void setupDefaultRenderState()
{
// Setup default render states
glClearColor(0.3f, 0.4f, 0.5f, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
// Setup lighting
glEnable(GL_LIGHTING);
PxReal ambientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f };
PxReal diffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f };
PxReal specularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
PxReal position[] = { 100.0f, 100.0f, 400.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHT0);
}
void startRender(const PxVec3& cameraEye, const PxVec3& cameraDir, PxReal clipNear, PxReal clipFar)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Setup camera
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, GLdouble(glutGet(GLUT_WINDOW_WIDTH)) / GLdouble(glutGet(GLUT_WINDOW_HEIGHT)), GLdouble(clipNear), GLdouble(clipFar));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(GLdouble(cameraEye.x), GLdouble(cameraEye.y), GLdouble(cameraEye.z), GLdouble(cameraEye.x + cameraDir.x), GLdouble(cameraEye.y + cameraDir.y), GLdouble(cameraEye.z + cameraDir.z), 0.0, 1.0, 0.0);
glColor4f(0.4f, 0.4f, 0.4f, 1.0f);
}
void finishRender()
{
glutSwapBuffers();
}
void renderActors(PxRigidActor** actors, const PxU32 numActors, bool shadows, const PxVec3& color, TriggerRender* cb)
{
const PxVec3 shadowDir(0.0f, -0.7071067f, -0.7071067f);
const PxReal shadowMat[]={ 1,0,0,0, -shadowDir.x/shadowDir.y,0,-shadowDir.z/shadowDir.y,0, 0,0,1,0, 0,0,0,1 };
PxShape* shapes[MAX_NUM_ACTOR_SHAPES];
for(PxU32 i=0;i<numActors;i++)
{
const PxU32 nbShapes = actors[i]->getNbShapes();
PX_ASSERT(nbShapes <= MAX_NUM_ACTOR_SHAPES);
actors[i]->getShapes(shapes, nbShapes);
const bool sleeping = actors[i]->is<PxRigidDynamic>() ? actors[i]->is<PxRigidDynamic>()->isSleeping() : false;
for(PxU32 j=0;j<nbShapes;j++)
{
const PxMat44 shapePose(PxShapeExt::getGlobalPose(*shapes[j], *actors[i]));
const PxGeometryHolder h = shapes[j]->getGeometry();
const bool isTrigger = cb ? cb->isTrigger(shapes[j]) : shapes[j]->getFlags() & PxShapeFlag::eTRIGGER_SHAPE;
if(isTrigger)
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
// render object
glPushMatrix();
glMultMatrixf(&shapePose.column0.x);
if(sleeping)
{
const PxVec3 darkColor = color * 0.25f;
glColor4f(darkColor.x, darkColor.y, darkColor.z, 1.0f);
}
else
glColor4f(color.x, color.y, color.z, 1.0f);
renderGeometryHolder(h);
glPopMatrix();
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
if(shadows)
{
glPushMatrix();
glMultMatrixf(shadowMat);
glMultMatrixf(&shapePose.column0.x);
glDisable(GL_LIGHTING);
glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
renderGeometryHolder(h);
glEnable(GL_LIGHTING);
glPopMatrix();
}
}
}
}
/*static const PxU32 gGeomSizes[] = {
sizeof(PxSphereGeometry),
sizeof(PxPlaneGeometry),
sizeof(PxCapsuleGeometry),
sizeof(PxBoxGeometry),
sizeof(PxConvexMeshGeometry),
sizeof(PxTriangleMeshGeometry),
sizeof(PxHeightFieldGeometry),
};
void renderGeoms(const PxU32 nbGeoms, const PxGeometry* geoms, const PxTransform* poses, bool shadows, const PxVec3& color)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
const PxVec3 shadowDir(0.0f, -0.7071067f, -0.7071067f);
const PxReal shadowMat[]={ 1,0,0,0, -shadowDir.x/shadowDir.y,0,-shadowDir.z/shadowDir.y,0, 0,0,1,0, 0,0,0,1 };
const PxU8* stream = reinterpret_cast<const PxU8*>(geoms);
for(PxU32 j=0;j<nbGeoms;j++)
{
const PxMat44 shapePose(poses[j]);
const PxGeometry& geom = *reinterpret_cast<const PxGeometry*>(stream);
stream += gGeomSizes[geom.getType()];
// render object
glPushMatrix();
glMultMatrixf(&shapePose.column0.x);
glColor4f(color.x, color.y, color.z, 1.0f);
renderGeometry(geom);
glPopMatrix();
if(shadows)
{
glPushMatrix();
glMultMatrixf(shadowMat);
glMultMatrixf(&shapePose.column0.x);
glDisable(GL_LIGHTING);
glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
renderGeometry(geom);
glEnable(GL_LIGHTING);
glPopMatrix();
}
}
}*/
void renderGeoms(const PxU32 nbGeoms, const PxGeometryHolder* geoms, const PxTransform* poses, bool shadows, const PxVec3& color)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
const PxVec3 shadowDir(0.0f, -0.7071067f, -0.7071067f);
const PxReal shadowMat[]={ 1,0,0,0, -shadowDir.x/shadowDir.y,0,-shadowDir.z/shadowDir.y,0, 0,0,1,0, 0,0,0,1 };
for(PxU32 j=0;j<nbGeoms;j++)
{
const PxMat44 shapePose(poses[j]);
const PxGeometry& geom = geoms[j].any();
// render object
glPushMatrix();
glMultMatrixf(&shapePose.column0.x);
glColor4f(color.x, color.y, color.z, 1.0f);
renderGeometry(geom);
glPopMatrix();
if(shadows)
{
glPushMatrix();
glMultMatrixf(shadowMat);
glMultMatrixf(&shapePose.column0.x);
glDisable(GL_LIGHTING);
glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
renderGeometry(geom);
glEnable(GL_LIGHTING);
glPopMatrix();
}
}
}
} //namespace Snippets

View File

@ -0,0 +1,68 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PHYSX_SNIPPET_RENDER_H
#define PHYSX_SNIPPET_RENDER_H
#include "PxPhysicsAPI.h"
#include "foundation/PxPreprocessor.h"
#if PX_WINDOWS
#include <windows.h>
#pragma warning(disable: 4505)
#include <glut.h>
#elif PX_LINUX_FAMILY
#include <GL/glut.h>
#elif PX_OSX
#include <GLUT/glut.h>
#else
#error platform not supported.
#endif
namespace Snippets
{
void setupDefaultWindow(const char* name);
void setupDefaultRenderState();
void startRender(const physx::PxVec3& cameraEye, const physx::PxVec3& cameraDir, physx::PxReal nearClip = 1.f, physx::PxReal farClip = 10000.f);
void finishRender();
class TriggerRender
{
public:
virtual bool isTrigger(physx::PxShape*) const = 0;
};
void renderActors(physx::PxRigidActor** actors, const physx::PxU32 numActors, bool shadows = false, const physx::PxVec3& color = physx::PxVec3(0.0f, 0.75f, 0.0f), TriggerRender* cb=nullptr);
// void renderGeoms(const physx::PxU32 nbGeoms, const physx::PxGeometry* geoms, const physx::PxTransform* poses, bool shadows, const physx::PxVec3& color);
void renderGeoms(const physx::PxU32 nbGeoms, const physx::PxGeometryHolder* geoms, const physx::PxTransform* poses, bool shadows, const physx::PxVec3& color);
}
#endif //PHYSX_SNIPPET_RENDER_H

View File

@ -0,0 +1,312 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of binary and xml serialization
//
// It creates a chain of boxes and serializes them as two collections:
// a collection with shared objects and a collection with actors and joints
// which can be instantiated multiple times.
//
// Then physics is setup based on the serialized data. The collection with the
// actors and the joints is instantiated multiple times with different
// transforms.
//
// Finally phyics is teared down again, including deallocation of memory
// occupied by deserialized objects (in the case of binary serialization).
//
// ****************************************************************************
#include "PxPhysicsAPI.h"
#include "foundation/PxMemory.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
bool gUseBinarySerialization = false;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxPvd* gPvd = NULL;
#define MAX_MEMBLOCKS 10
PxU8* gMemBlocks[MAX_MEMBLOCKS];
PxU32 gMemBlockCount = 0;
/**
Creates two example collections:
- collection with actors and joints that can be instantiated multiple times in the scene
- collection with shared objects
*/
void createCollections(PxCollection*& sharedCollection, PxCollection*& actorCollection, PxSerializationRegistry& sr)
{
PxMaterial* material = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxReal halfLength = 2.0f, height = 25.0f;
PxVec3 offset(halfLength, 0, 0);
PxRigidActor* prevActor = PxCreateStatic(*gPhysics, PxTransform(PxVec3(0,height,0)), PxSphereGeometry(halfLength), *material, PxTransform(offset));
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfLength, 1.0f, 1.0f), *material);
for(PxU32 i=1; i<8;i++)
{
PxTransform tm(PxVec3(PxReal(i*2)* halfLength, height, 0));
PxRigidDynamic* dynamic = gPhysics->createRigidDynamic(tm);
dynamic->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*dynamic, 10.0f);
PxSphericalJointCreate(*gPhysics, prevActor, PxTransform(offset), dynamic, PxTransform(-offset));
prevActor = dynamic;
}
sharedCollection = PxCreateCollection(); // collection for all the shared objects
actorCollection = PxCreateCollection(); // collection for all the nonshared objects
sharedCollection->add(*shape);
PxSerialization::complete(*sharedCollection, sr); // chases the pointer from shape to material, and adds it
PxSerialization::createSerialObjectIds(*sharedCollection, PxSerialObjectId(77)); // arbitrary choice of base for references to shared objects
actorCollection->add(*prevActor);
PxSerialization::complete(*actorCollection, sr, sharedCollection, true); // chases all pointers and recursively adds actors and joints
}
/**
Allocates 128 byte aligned memory block for binary serialized data
Stores pointer to memory in gMemBlocks for later deallocation
*/
void* createAlignedBlock(PxU32 size)
{
PX_ASSERT(gMemBlockCount < MAX_MEMBLOCKS);
PxU8* baseAddr = static_cast<PxU8*>(malloc(size+PX_SERIAL_FILE_ALIGN-1));
gMemBlocks[gMemBlockCount++] = baseAddr;
void* alignedBlock = reinterpret_cast<void*>((size_t(baseAddr)+PX_SERIAL_FILE_ALIGN-1)&~(PX_SERIAL_FILE_ALIGN-1));
return alignedBlock;
}
/**
Create objects, add them to collections and serialize the collections to the steams gSharedStream and gActorStream
This function doesn't setup the gPhysics global as the corresponding physics object is only used locally
*/
void serializeObjects(PxOutputStream& sharedStream, PxOutputStream& actorStream)
{
PxSerializationRegistry* sr = PxSerialization::createSerializationRegistry(*gPhysics);
PxCollection* sharedCollection = NULL;
PxCollection* actorCollection = NULL;
createCollections(sharedCollection, actorCollection, *sr);
// Alternatively to using PxDefaultMemoryOutputStream it would be possible to serialize to files using
// PxDefaultFileOutputStream or a similar implementation of PxOutputStream.
if (gUseBinarySerialization)
{
PxSerialization::serializeCollectionToBinary(sharedStream, *sharedCollection, *sr);
PxSerialization::serializeCollectionToBinary(actorStream, *actorCollection, *sr, sharedCollection);
}
else
{
PxSerialization::serializeCollectionToXml(sharedStream, *sharedCollection, *sr);
PxSerialization::serializeCollectionToXml(actorStream, *actorCollection, *sr, NULL, sharedCollection);
}
actorCollection->release();
sharedCollection->release();
sr->release();
}
/**
Deserialize shared data and use resulting collection to deserialize and instance actor collections
*/
void deserializeObjects(PxInputData& sharedData, PxInputData& actorData)
{
PxSerializationRegistry* sr = PxSerialization::createSerializationRegistry(*gPhysics);
PxCollection* sharedCollection = NULL;
{
if (gUseBinarySerialization)
{
void* alignedBlock = createAlignedBlock(sharedData.getLength());
sharedData.read(alignedBlock, sharedData.getLength());
sharedCollection = PxSerialization::createCollectionFromBinary(alignedBlock, *sr);
}
else
{
sharedCollection = PxSerialization::createCollectionFromXml(sharedData, *gCooking, *sr);
}
}
// Deserialize collection and instantiate objects twice, each time with a different transform
PxTransform transforms[2] = { PxTransform(PxVec3(-5.0f, 0.0f, 0.0f)), PxTransform(PxVec3(5.0f, 0.0f, 0.0f)) };
for (PxU32 i = 0; i < 2; i++)
{
PxCollection* collection = NULL;
// If the PxInputData actorData would refer to a file, it would be better to avoid reading from it twice.
// This could be achieved by reading the file once to memory, and then working with copies.
// This is particulary practical when using binary serialization, where the data can be directly
// converted to physics objects.
actorData.seek(0);
if (gUseBinarySerialization)
{
void* alignedBlock = createAlignedBlock(actorData.getLength());
actorData.read(alignedBlock, actorData.getLength());
collection = PxSerialization::createCollectionFromBinary(alignedBlock, *sr, sharedCollection);
}
else
{
collection = PxSerialization::createCollectionFromXml(actorData, *gCooking, *sr, sharedCollection);
}
for (PxU32 o = 0; o < collection->getNbObjects(); o++)
{
PxRigidActor* rigidActor = collection->getObject(o).is<PxRigidActor>();
if (rigidActor)
{
PxTransform globalPose = rigidActor->getGlobalPose();
globalPose = globalPose.transform(transforms[i]);
rigidActor->setGlobalPose(globalPose);
}
}
gScene->addCollection(*collection);
collection->release();
}
sharedCollection->release();
PxMaterial* material;
gPhysics->getMaterials(&material,1);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *material);
gScene->addActor(*groundPlane);
sr->release();
}
/**
Initializes physics and creates a scene
*/
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
PxInitExtensions(*gPhysics, gPvd);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
}
void stepPhysics()
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
/**
Releases all physics objects, including memory blocks containing deserialized data
*/
void cleanupPhysics()
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics); // releases all objects
PX_RELEASE(gCooking);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
// Now that the objects have been released, it's safe to release the space they occupy
for (PxU32 i = 0; i < gMemBlockCount; i++)
free(gMemBlocks[i]);
gMemBlockCount = 0;
PX_RELEASE(gFoundation);
}
int snippetMain(int, const char*const*)
{
initPhysics();
// Alternatively PxDefaultFileOutputStream could be used
PxDefaultMemoryOutputStream sharedOutputStream;
PxDefaultMemoryOutputStream actorOutputStream;
serializeObjects(sharedOutputStream, actorOutputStream);
cleanupPhysics();
initPhysics();
// Alternatively PxDefaultFileInputData could be used
PxDefaultMemoryInputData sharedInputStream(sharedOutputStream.getData(), sharedOutputStream.getSize());
PxDefaultMemoryInputData actorInputStream(actorOutputStream.getData(), actorOutputStream.getSize());
deserializeObjects(sharedInputStream, actorInputStream);
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 250;
for(PxU32 i=0; i<frameCount; i++)
stepPhysics();
cleanupPhysics();
printf("SnippetSerialization done.\n");
#endif
return 0;
}

View File

@ -0,0 +1,119 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics();
extern void stepPhysics();
extern void cleanupPhysics();
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
sCamera->handleKey(key, x, y);
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
stepPhysics();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics();
printf("SnippetSerialization done.\n");
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Serialization");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,276 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of simple contact reports.
//
// It defines a filter shader function that requests touch reports for
// all pairs, and a contact callback function that saves the contact points.
// It configures the scene to use this filter and callback, and prints the
// number of contact reports each frame. If rendering, it renders each
// contact as a line whose length and direction are defined by the contact
// impulse.
//
// ****************************************************************************
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
#include "PsAtomic.h"
#include "task/PxTask.h"
#define PARALLEL_CALLBACKS 1
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
const PxI32 maxCount = 10000;
PxI32 gSharedIndex = 0;
PxVec3* gContactPositions;
PxVec3* gContactImpulses;
PxVec3* gContactVertices;
class CallbackFinishTask : public PxLightCpuTask
{
SnippetUtils::Sync* mSync;
public:
CallbackFinishTask(){ mSync = SnippetUtils::syncCreate(); }
virtual void release()
{
PxLightCpuTask::release();
SnippetUtils::syncSet(mSync);
}
void reset() { SnippetUtils::syncReset(mSync); }
void wait() { SnippetUtils::syncWait(mSync); }
virtual void run() { /*Do nothing - release the sync in the release method for thread-safety*/}
virtual const char* getName() const { return "CallbackFinishTask"; }
}
callbackFinishTask;
PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
PxFilterObjectAttributes attributes1, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{
PX_UNUSED(attributes0);
PX_UNUSED(attributes1);
PX_UNUSED(filterData0);
PX_UNUSED(filterData1);
PX_UNUSED(constantBlockSize);
PX_UNUSED(constantBlock);
// all initial and persisting reports for everything, with per-point data
pairFlags = PxPairFlag::eSOLVE_CONTACT | PxPairFlag::eDETECT_DISCRETE_CONTACT
| PxPairFlag::eNOTIFY_TOUCH_FOUND
| PxPairFlag::eNOTIFY_TOUCH_PERSISTS
| PxPairFlag::eNOTIFY_CONTACT_POINTS;
return PxFilterFlag::eDEFAULT;
}
class ContactReportCallback : public PxSimulationEventCallback
{
void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED(constraints); PX_UNUSED(count); }
void onWake(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED(actors); PX_UNUSED(count); }
void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED(pairs); PX_UNUSED(count); }
void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32) {}
void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
{
PX_UNUSED((pairHeader));
//Maximum of 64 vertices can be produced by contact gen
PxContactPairPoint contactPoints[64];
for (PxU32 i = 0; i<nbPairs; i++)
{
PxU32 contactCount = pairs[i].contactCount;
if (contactCount)
{
pairs[i].extractContacts(&contactPoints[0], contactCount);
PxI32 startIdx = physx::shdfnd::atomicAdd(&gSharedIndex, int32_t(contactCount));
for (PxU32 j = 0; j<contactCount; j++)
{
gContactPositions[startIdx+j] = contactPoints[j].position;
gContactImpulses[startIdx+j] = contactPoints[j].impulse;
gContactVertices[2*(startIdx + j)] = contactPoints[j].position;
gContactVertices[2*(startIdx + j) + 1] = contactPoints[j].position + contactPoints[j].impulse * 0.1f;
}
}
}
}
};
ContactReportCallback gContactReportCallback;
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for (PxU32 i = 0; i<size; i++)
{
for (PxU32 j = 0; j<size - i; j++)
{
PxTransform localTm(PxVec3(PxReal(j * 2) - PxReal(size - i), PxReal(i * 2 + 1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 10.0f);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool /*interactive*/)
{
gContactPositions = new PxVec3[maxCount];
gContactImpulses = new PxVec3[maxCount];
gContactVertices = new PxVec3[2*maxCount];
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport, PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxInitExtensions(*gPhysics, gPvd);
PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
sceneDesc.filterShader = contactReportFilterShader;
sceneDesc.simulationEventCallback = &gContactReportCallback;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if (pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0, 1, 0, 0), *gMaterial);
gScene->addActor(*groundPlane);
const PxU32 nbStacks = 50;
for (PxU32 i = 0; i < nbStacks; ++i)
{
createStack(PxTransform(PxVec3(0, 3.0f, 10.f - 5.f*i)), 5, 2.0f);
}
}
void stepPhysics(bool /*interactive*/)
{
gSharedIndex = 0;
gScene->simulate(1.0f / 60.0f);
#if !PARALLEL_CALLBACKS
gScene->fetchResults(true);
#else
//Call fetchResultsStart. Get the set of pair headers
const PxContactPairHeader* pairHeader;
PxU32 nbContactPairs;
gScene->fetchResultsStart(pairHeader, nbContactPairs, true);
//Set up continuation task to be run after callbacks have been processed in parallel
callbackFinishTask.setContinuation(*gScene->getTaskManager(), NULL);
callbackFinishTask.reset();
//process the callbacks
gScene->processCallbacks(&callbackFinishTask);
callbackFinishTask.removeReference();
callbackFinishTask.wait();
gScene->fetchResultsFinish();
#endif
printf("%d contact reports\n", PxU32(gSharedIndex));
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
delete gContactPositions;
delete gContactImpulses;
delete gContactVertices;
printf("SnippetSplitFetchResults done.\n");
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics(false);
for (PxU32 i = 0; i<250; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,131 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern PxVec3* gContactPositions;
extern PxVec3* gContactImpulses;
extern PxI32 gSharedIndex;
extern PxVec3* gContactVertices;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if (key == 27)
exit(0);
sCamera->handleKey(key, x, y);
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene, 1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if (nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
PxI32 count = gSharedIndex;
if (count)
{
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &gContactVertices[0]);
glDrawArrays(GL_LINES, 0, GLint(count*2));
glDisableClientState(GL_VERTEX_ARRAY);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f, -0.2f, -0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Split fetchResults");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0, 0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,385 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// *******************************************************************************************************
// In addition to the simulate() function, which performs both collision detection and dynamics update,
// the PhysX SDK provides an api for separate execution of the collision detection and dynamics update steps.
// We shall refer to this feature as "split sim". This snippet demonstrates two ways to use the split sim feature
// so that application work can be performed concurrently with the collision detection step.
// The snippet creates a list of kinematic box actors along with a number of dynamic actors that
// interact with the kinematic actors.
//The defines OVERLAP_COLLISION_AND_RENDER_WITH_NO_LAG and OVERLAP_COLLISION_AND_RENDER_WITH_ONE_FRAME_LAG
//demonstrate two distinct modes of split sim operation:
// (1)Enabling OVERLAP_COLLISION_AND_RENDER_WITH_NO_LAG allows the collision detection step to run in parallel
// with the renderer and with the update of the kinematic target poses without introducing any lag between
// application time and physics time. This is equivalent to calling simulate() and fetchResults() with the key
// difference being that the application can schedule work to run concurrently with the collision detection.
// A consequence of this approach is that the first frame is more expensive than subsequent frames because it has to
// perform blocking collision detection and dynamics update calls.
// (2)OVERLAP_COLLISION_AND_RENDER_WITH_ONE_FRAME_LAG also allows the collision to run in parallel with
// the renderer and the update of the kinematic target poses but this time with a lag between physics time and
// application time; that is, the physics is always a single timestep behind the application because the first
// frame merely starts the collision detection for the subsequent frame. A consequence of this approach is that
// the first frame is cheaper than subsequent frames.
// ********************************************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
//This will allow the split sim to overlap collision and render and game logic.
#define OVERLAP_COLLISION_AND_RENDER_WITH_NO_LAG 1
#define OVERLAP_COLLISION_AND_RENDER_WITH_ONE_FRAME_LAG 0
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
#define NB_KINE_X 16
#define NB_KINE_Y 16
#define KINE_SCALE 3.1f
static bool isFirstFrame = true;
PxRigidDynamic* gKinematics[NB_KINE_Y][NB_KINE_X];
PxQuat setRotY(PxMat33& m, const PxReal angle)
{
m = PxMat33(PxIdentity);
const PxReal cos = cosf(angle);
const PxReal sin = sinf(angle);
m[0][0] = m[2][2] = cos;
m[0][2] = -sin;
m[2][0] = sin;
return PxQuat(m);
}
void createDynamics()
{
const PxU32 NbX = 8;
const PxU32 NbY = 8;
const PxVec3 dims(0.2f, 0.1f, 0.2f);
const PxReal sphereRadius = 0.2f;
const PxReal capsuleRadius = 0.2f;
const PxReal halfHeight = 0.5f;
const PxU32 NbLayers = 3;
const float YScale = 0.4f;
const float YStart = 6.0f;
PxShape* boxShape = gPhysics->createShape(PxBoxGeometry(dims), *gMaterial);
PxShape* sphereShape = gPhysics->createShape(PxSphereGeometry(sphereRadius), *gMaterial);
PxShape* capsuleShape = gPhysics->createShape(PxCapsuleGeometry(capsuleRadius, halfHeight), *gMaterial);
PX_UNUSED(boxShape);
PX_UNUSED(sphereShape);
PX_UNUSED(capsuleShape);
PxMat33 m;
for(PxU32 j=0;j<NbLayers;j++)
{
const float angle = float(j)*0.08f;
const PxQuat rot = setRotY(m, angle);
const float ScaleX = 4.0f;
const float ScaleY = 4.0f;
for(PxU32 y=0;y<NbY;y++)
{
for(PxU32 x=0;x<NbX;x++)
{
const float xf = (float(x)-float(NbX)*0.5f)*ScaleX;
const float yf = (float(y)-float(NbY)*0.5f)*ScaleY;
PxRigidDynamic* dynamic = NULL;
PxU32 v = j&3;
PxVec3 pos = PxVec3(xf, YStart + float(j)*YScale, yf);
switch(v)
{
case 0:
{
PxTransform pose(pos, rot);
dynamic = gPhysics->createRigidDynamic(pose);
dynamic->attachShape(*boxShape);
break;
}
case 1:
{
PxTransform pose(pos, PxQuat(PxIdentity));
dynamic = gPhysics->createRigidDynamic(pose);
dynamic->attachShape(*sphereShape);
break;
}
default:
{
PxTransform pose(pos, rot);
dynamic = gPhysics->createRigidDynamic(pose);
dynamic->attachShape(*capsuleShape);
break;
}
};
PxRigidBodyExt::updateMassAndInertia(*dynamic, 10.f);
gScene->addActor(*dynamic);
}
}
}
}
void createGroudPlane()
{
PxTransform pose = PxTransform(PxVec3(0.0f, 0.0f, 0.0f),PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f)));
PxRigidStatic* actor = gPhysics->createRigidStatic(pose);
PxShape* shape = PxRigidActorExt::createExclusiveShape(*actor, PxPlaneGeometry(), *gMaterial);
PX_UNUSED(shape);
gScene->addActor(*actor);
}
void createKinematics()
{
const PxU32 NbX = NB_KINE_X;
const PxU32 NbY = NB_KINE_Y;
const PxVec3 dims(1.5f, 0.2f, 1.5f);
const PxQuat rot = PxQuat(PxIdentity);
const float YScale = 0.4f;
PxShape* shape = gPhysics->createShape(PxBoxGeometry(dims), *gMaterial);
const float ScaleX = KINE_SCALE;
const float ScaleY = KINE_SCALE;
for(PxU32 y=0;y<NbY;y++)
{
for(PxU32 x=0;x<NbX;x++)
{
const float xf = (float(x)-float(NbX)*0.5f)*ScaleX;
const float yf = (float(y)-float(NbY)*0.5f)*ScaleY;
PxTransform pose(PxVec3(xf, 0.2f + YScale, yf), rot);
PxRigidDynamic* body = gPhysics->createRigidDynamic(pose);
body->attachShape(*shape);
gScene->addActor(*body);
body->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
gKinematics[y][x] = body;
}
}
}
void updateKinematics(PxReal timeStep)
{
const float YScale = 0.4f;
PxTransform motion;
motion.q = PxQuat(PxIdentity);
static float gTime = 0.0f;
gTime += timeStep;
const PxU32 NbX = NB_KINE_X;
const PxU32 NbY = NB_KINE_Y;
const float Coeff = 0.2f;
const float ScaleX = KINE_SCALE;
const float ScaleY = KINE_SCALE;
for(PxU32 y=0;y<NbY;y++)
{
for(PxU32 x=0;x<NbX;x++)
{
const float xf = (float(x)-float(NbX)*0.5f)*ScaleX;
const float yf = (float(y)-float(NbY)*0.5f)*ScaleY;
const float h = sinf(gTime*2.0f + float(x)*Coeff + + float(y)*Coeff)*2.0f;
motion.p = PxVec3(xf, h + 2.0f + YScale, yf);
PxRigidDynamic* kine = gKinematics[y][x];
kine->setKinematicTarget(motion);
}
}
}
void initPhysics(bool /*interactive*/)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
createKinematics();
createDynamics();
}
#if OVERLAP_COLLISION_AND_RENDER_WITH_NO_LAG
void stepPhysics(bool /*interactive*/)
{
const PxReal timeStep = 1.0f/60.0f;
if(isFirstFrame)
{
//Run the first frame's collision detection
gScene->collide(timeStep);
isFirstFrame = false;
}
//update the kinematice target pose in parallel with collision running
updateKinematics(timeStep);
gScene->fetchCollision(true);
gScene->advance();
gScene->fetchResults(true);
//Run the deferred collision detection for the next frame. This will run in parallel with render.
gScene->collide(timeStep);
}
#elif OVERLAP_COLLISION_AND_RENDER_WITH_ONE_FRAME_LAG
void stepPhysics(bool /*interactive*/)
{
PxReal timeStep = 1.0/60.0f;
//update the kinematice target pose in parallel with collision running
updateKinematics(timeStep);
if(!isFirstFrame)
{
gScene->fetchCollision(true);
gScene->advance();
gScene->fetchResults(true);
}
isFirstFrame = false;
//Run the deferred collision detection for the next frame. This will run in parallel with render.
gScene->collide(timeStep);
}
#else
void stepPhysics(bool /*interactive*/)
{
PxReal timeStep = 1.0/60.0f;
//update the kinematice target pose in parallel with collision running
gScene->collide(timeStep);
updateKinematics(timeStep);
gScene->fetchCollision(true);
gScene->advance();
gScene->fetchResults(true);
}
#endif
void cleanupPhysics(bool /*interactive*/)
{
#if OVERLAP_COLLISION_AND_RENDER_WITH_NO_LAG || OVERLAP_COLLISION_AND_RENDER_WITH_ONE_FRAME_LAG
//Close out remainder of previously running scene. If we don't do this, it will be implicitly done
//in gScene->release() but a warning will be issued.
gScene->fetchCollision(true);
gScene->advance();
gScene->fetchResults(true);
#endif
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetSplitSim done.\n");
}
void keyPress(unsigned char key, const PxTransform& camer)
{
PX_UNUSED(key);
PX_UNUSED(camer);
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
static const PxU32 frameCount = 100;
initPhysics(false);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,134 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics(true);
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC);
if(nbActors)
{
PxVec3 dynColor(1.0f, 0.f, 1.f);
PxVec3 kinematicColor(0.f, 1.f, 0.f);
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
for(PxU32 i=0; i<nbActors; ++i)
{
PxRigidActor* actor = actors[i];
PxRigidDynamic* dyn = actor->is<PxRigidDynamic>();
if(dyn->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
{
Snippets::renderActors(&actor, 1, true, kinematicColor);
}
else
{
Snippets::renderActors(&actor, 1, true, dynColor);
}
}
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(50.0f, 50.0f, 50.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Split Sim");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,236 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates kinematic actor updates in a substepped simulation.
//
// It uses chained continuation tasks that call fetchResults and run simulation steps.
// The scene consists of a kinematic platform interacting with a dynamic
// sphere. The kinematic actor's target pose is updated before every substep.
// ****************************************************************************
#include <new>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
using namespace SnippetUtils;
// The usual PhysX resources.
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxMaterial* gMaterial = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxRigidDynamic* gKinematic = NULL;
// A very simple substepping policy: just take 2 60Hz substeps per step.
static const PxReal SUBSTEP_LENGTH = 1.0f/60.0f;
static const PxU32 NUM_STEPS = 1000;
static const PxI32 NUM_SUBSTEPS = 2;
PxPvd* gPvd = NULL;
// Context for keeping track of the stepper state.
struct StepContext
{
class SubstepCompletionTask* taskPool;
Sync* completionSync;
PxI32 nbSubstepsFinished;
volatile PxI32 nbTasksDestroyed;
} gStepContext;
// Completion task for running a substep.
// The following sequencing is guaranteed:
// * the section of the run() method up to the removeReference() in startNextSubstep() will execute prior
// to the run() method of the task submitted by startNextSubstep()
// * the run() method of a task will run before its release() method
//
// Any work done by a task after releasing the next task (via removeReference()) could end up running in
// parallel with that task, if simulate() completes sufficiently quickly or there is a context switch. In order
// to prevent races, it is therefore recommended that a completion task do no work after releasing the next.
class SubstepCompletionTask : public PxLightCpuTask
{
public:
SubstepCompletionTask()
{
mTm = gScene->getTaskManager();
}
void run()
{
void startNextSubstep();
gScene->fetchResults(true);
if(++gStepContext.nbSubstepsFinished < NUM_SUBSTEPS)
startNextSubstep();
}
void release()
{
this->~SubstepCompletionTask();
// If we're done with all the substeps , synchronize with the main thread. In a real application
// we would most likely run dependent tasks instead.
// We can only signal completion once all substepping resources are cleaned up.
// Release() calls may run concurrently or out of order, so we use an atomic counter.
if(atomicIncrement(&gStepContext.nbTasksDestroyed) == NUM_SUBSTEPS)
syncSet(gStepContext.completionSync);
}
const char* getName() const { return "Substep Completion Task"; }
};
// Update the sim inputs and start the next PhysX substep.
void startNextSubstep()
{
// Compute new target pose for the kinematic at the end of the substep.
static PxReal sTotalSeconds = 0.0f;
sTotalSeconds += SUBSTEP_LENGTH;
const PxReal period = 4.0f;
const PxReal amplitude = 10.0f;
const PxReal angVel = PxTwoPi/period;
PxReal yPos = PxSin(angVel * sTotalSeconds) * amplitude;
gKinematic->setKinematicTarget(PxTransform(0.0f, yPos, 0.0f));
// Create a completion task and set its reference count to 1. This way we can safely submit it to simulate()
// and, even if we get context-switched and simulate() completes before we get back, the task's run()
// method will not execute until we're ready.
SubstepCompletionTask* nextCompletion = new (gStepContext.taskPool+gStepContext.nbSubstepsFinished) SubstepCompletionTask();
nextCompletion->addReference();
// Kick off the sim with the new completion task. Once this call returns, worker threads will update the PhysX
// state in parallel with the rest of this function.
gScene->simulate(SUBSTEP_LENGTH, nextCompletion);
// We can do things here that can run in parallel with the simulation, but must happen before the next task's
// run method executes. In this snippet, there's nothing to do...
// Finally, remove the reference that prevents the next completion task running.
nextCompletion->removeReference();
}
void runPhysics()
{
// Initialize the substepping context.
syncReset(gStepContext.completionSync);
gStepContext.nbSubstepsFinished = 0;
gStepContext.nbTasksDestroyed = 0;
// Start the first substep, then wait for the last one to finish.
startNextSubstep();
syncWait(gStepContext.completionSync);
}
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreateBasePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.2f);
PxSceneDesc desc(gPhysics->getTolerancesScale());
desc.filterShader = PxDefaultSimulationFilterShader;
desc.cpuDispatcher = gDispatcher = PxDefaultCpuDispatcherCreate(2);
desc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
gScene = gPhysics->createScene(desc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gKinematic = PxCreateKinematic(*gPhysics, PxTransform(PxIdentity), PxBoxGeometry(5.0f, 1.0f, 5.0f), *gMaterial, 1.0f);
gScene->addActor(*gKinematic);
PxRigidDynamic* sphere = PxCreateDynamic(*gPhysics, PxTransform(0.0f, 5.0f, 0.0f), PxSphereGeometry(1.0f), *gMaterial, 1.0f);
gScene->addActor(*sphere);
}
void cleanupPhysics()
{
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
}
int snippetMain(int, const char*const*)
{
initPhysics();
// Storage and synchronization for substepping.
gStepContext.taskPool = reinterpret_cast<SubstepCompletionTask*>(malloc(NUM_SUBSTEPS * sizeof(SubstepCompletionTask)));
gStepContext.completionSync = syncCreate();
for(PxU32 i=0; i<NUM_STEPS; i++)
runPhysics();
syncRelease(gStepContext.completionSync);
free(gStepContext.taskPool);
cleanupPhysics();
printf("SnippetStepper done.\n");
return 0;
}

View File

@ -0,0 +1,178 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ********************************************************************************
// This snippet illustrates the concept of PxToleranceScale.
//
// It creates 2 scenes using different units for length and mass.
// Use PVD to replay the scene and see how scaling affects the simulation.
// ********************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
PxReal gStackZ = 10.0f;
PxRigidDynamic* createDynamic(const PxTransform& t, const PxGeometry& geometry, const PxReal& mass, const PxVec3& velocity=PxVec3(0))
{
PxRigidDynamic* dynamic = PxCreateDynamic(*gPhysics, t, geometry, *gMaterial, 10.0f);
dynamic->setAngularDamping(0.5f);
dynamic->setLinearVelocity(velocity);
PxRigidBodyExt::setMassAndUpdateInertia(*dynamic, mass);
gScene->addActor(*dynamic);
return dynamic;
}
void createStack(const PxTransform& t, PxU32 size, PxReal halfExtent, const PxReal& mass)
{
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent, halfExtent, halfExtent), *gMaterial);
for(PxU32 i=0; i<size;i++)
{
for(PxU32 j=0;j<size-i;j++)
{
PxTransform localTm(PxVec3(PxReal(j*2) - PxReal(size-i), PxReal(i*2+1), 0) * halfExtent);
PxRigidDynamic* body = gPhysics->createRigidDynamic(t.transform(localTm));
body->attachShape(*shape);
PxRigidBodyExt::setMassAndUpdateInertia(*body, mass);
gScene->addActor(*body);
}
}
shape->release();
}
void initPhysics(bool interactive, const PxTolerancesScale& scale, PxReal scaleMass)
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, scale, true, gPvd);
PxReal scaleLength = scale.length;
PxSceneDesc sceneDesc(scale);
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f) * scaleLength;
gDispatcher = PxDefaultCpuDispatcherCreate(2);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
for(PxU32 i=0;i<5;i++)
createStack(PxTransform(PxVec3(0,0,gStackZ-=10.0f) * scaleLength), 10, 2.0f * scaleLength, 1.0f * scaleMass);
if(!interactive)
createDynamic(PxTransform(PxVec3(0,40,100) * scaleLength), PxSphereGeometry(10 * scaleLength), 100.0f * scaleMass, PxVec3(0,-50,-100) * scaleLength);
}
void stepPhysics(bool /*interactive*/)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
void cleanupPhysics(bool /*interactive*/)
{
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
}
void runSim(const PxTolerancesScale& scale, PxReal scaleMass)
{
static const PxU32 frameCount = 150;
initPhysics(false, scale, scaleMass);
for(PxU32 i=0; i<frameCount; i++)
stepPhysics(false);
cleanupPhysics(false);
}
int snippetMain(int, const char*const*)
{
PxTolerancesScale scale;
// Default
printf("PxToleranceScale (Default).\n");
runSim(scale, 1000.0f);
// Reset position of pyramid stack z coordinate to default
gStackZ = 10.0f;
// Scaled assets
printf("PxToleranceScale (Scaled).\n");
scale.length = 100; // length in cm
scale.speed *= scale.length; // speed in cm/s
runSim(scale, 1.0f);
printf("SnippetToleranceScale done.\n");
return 0;
}

View File

@ -0,0 +1,394 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet demonstrates the possibilities of triangle mesh creation.
//
// The snippet creates triangle mesh with a different cooking settings
// and shows how these settings affect the triangle mesh creation speed.
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxCooking* gCooking = NULL;
float rand(float loVal, float hiVal)
{
return loVal + float(rand()/float(RAND_MAX))*(hiVal - loVal);
}
PxU32 rand(PxU32 loVal, PxU32 hiVal)
{
return loVal + PxU32(rand()%(hiVal - loVal));
}
void indexToCoord(PxU32& x, PxU32& z, PxU32 index, PxU32 w)
{
x = index % w;
z = index / w;
}
// Creates a random terrain data.
void createRandomTerrain(const PxVec3& origin, PxU32 numRows, PxU32 numColumns,
PxReal cellSizeRow, PxReal cellSizeCol, PxReal heightScale,
PxVec3*& vertices, PxU32*& indices)
{
PxU32 numX = (numColumns + 1);
PxU32 numZ = (numRows + 1);
PxU32 numVertices = numX*numZ;
PxU32 numTriangles = numRows*numColumns * 2;
if (vertices == NULL)
vertices = new PxVec3[numVertices];
if (indices == NULL)
indices = new PxU32[numTriangles * 3];
PxU32 currentIdx = 0;
for (PxU32 i = 0; i <= numRows; i++)
{
for (PxU32 j = 0; j <= numColumns; j++)
{
PxVec3 v(origin.x + PxReal(j)*cellSizeRow, origin.y, origin.z + PxReal(i)*cellSizeCol);
vertices[currentIdx++] = v;
}
}
currentIdx = 0;
for (PxU32 i = 0; i < numRows; i++)
{
for (PxU32 j = 0; j < numColumns; j++)
{
PxU32 base = (numColumns + 1)*i + j;
indices[currentIdx++] = base + 1;
indices[currentIdx++] = base;
indices[currentIdx++] = base + numColumns + 1;
indices[currentIdx++] = base + numColumns + 2;
indices[currentIdx++] = base + 1;
indices[currentIdx++] = base + numColumns + 1;
}
}
for (PxU32 i = 0; i < numVertices; i++)
{
PxVec3& v = vertices[i];
v.y += heightScale * rand(-1.0f, 1.0f);
}
}
// Setup common cooking params
void setupCommonCookingParams(PxCookingParams& params, bool skipMeshCleanup, bool skipEdgeData)
{
// we suppress the triangle mesh remap table computation to gain some speed, as we will not need it
// in this snippet
params.suppressTriangleMeshRemapTable = true;
// If DISABLE_CLEAN_MESH is set, the mesh is not cleaned during the cooking. The input mesh must be valid.
// The following conditions are true for a valid triangle mesh :
// 1. There are no duplicate vertices(within specified vertexWeldTolerance.See PxCookingParams::meshWeldTolerance)
// 2. There are no large triangles(within specified PxTolerancesScale.)
// It is recommended to run a separate validation check in debug/checked builds, see below.
if (!skipMeshCleanup)
params.meshPreprocessParams &= ~static_cast<PxMeshPreprocessingFlags>(PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH);
else
params.meshPreprocessParams |= PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH;
// If DISABLE_ACTIVE_EDGES_PREDOCOMPUTE is set, the cooking does not compute the active (convex) edges, and instead
// marks all edges as active. This makes cooking faster but can slow down contact generation. This flag may change
// the collision behavior, as all edges of the triangle mesh will now be considered active.
if (!skipEdgeData)
params.meshPreprocessParams &= ~static_cast<PxMeshPreprocessingFlags>(PxMeshPreprocessingFlag::eDISABLE_ACTIVE_EDGES_PRECOMPUTE);
else
params.meshPreprocessParams |= PxMeshPreprocessingFlag::eDISABLE_ACTIVE_EDGES_PRECOMPUTE;
}
// Creates a triangle mesh using BVH33 midphase with different settings.
void createBV33TriangleMesh(PxU32 numVertices, const PxVec3* vertices, PxU32 numTriangles, const PxU32* indices,
bool skipMeshCleanup, bool skipEdgeData, bool inserted, bool cookingPerformance, bool meshSizePerfTradeoff)
{
PxU64 startTime = SnippetUtils::getCurrentTimeCounterValue();
PxTriangleMeshDesc meshDesc;
meshDesc.points.count = numVertices;
meshDesc.points.data = vertices;
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.count = numTriangles;
meshDesc.triangles.data = indices;
meshDesc.triangles.stride = 3 * sizeof(PxU32);
PxCookingParams params = gCooking->getParams();
// Create BVH33 midphase
params.midphaseDesc = PxMeshMidPhase::eBVH33;
// setup common cooking params
setupCommonCookingParams(params, skipMeshCleanup, skipEdgeData);
// The COOKING_PERFORMANCE flag for BVH33 midphase enables a fast cooking path at the expense of somewhat lower quality BVH construction.
if (cookingPerformance)
params.midphaseDesc.mBVH33Desc.meshCookingHint = PxMeshCookingHint::eCOOKING_PERFORMANCE;
else
params.midphaseDesc.mBVH33Desc.meshCookingHint = PxMeshCookingHint::eSIM_PERFORMANCE;
// If meshSizePerfTradeoff is set to true, smaller mesh cooked mesh is produced. The mesh size/performance trade-off
// is controlled by setting the meshSizePerformanceTradeOff from 0.0f (smaller mesh) to 1.0f (larger mesh).
if(meshSizePerfTradeoff)
{
params.midphaseDesc.mBVH33Desc.meshSizePerformanceTradeOff = 0.0f;
}
else
{
// using the default value
params.midphaseDesc.mBVH33Desc.meshSizePerformanceTradeOff = 0.55f;
}
gCooking->setParams(params);
#if defined(PX_CHECKED) || defined(PX_DEBUG)
// If DISABLE_CLEAN_MESH is set, the mesh is not cleaned during the cooking.
// We should check the validity of provided triangles in debug/checked builds though.
if (skipMeshCleanup)
{
PX_ASSERT(gCooking->validateTriangleMesh(meshDesc));
}
#endif // DEBUG
PxTriangleMesh* triMesh = NULL;
PxU32 meshSize = 0;
// The cooked mesh may either be saved to a stream for later loading, or inserted directly into PxPhysics.
if (inserted)
{
triMesh = gCooking->createTriangleMesh(meshDesc, gPhysics->getPhysicsInsertionCallback());
}
else
{
PxDefaultMemoryOutputStream outBuffer;
gCooking->cookTriangleMesh(meshDesc, outBuffer);
PxDefaultMemoryInputData stream(outBuffer.getData(), outBuffer.getSize());
triMesh = gPhysics->createTriangleMesh(stream);
meshSize = outBuffer.getSize();
}
// Print the elapsed time for comparison
PxU64 stopTime = SnippetUtils::getCurrentTimeCounterValue();
float elapsedTime = SnippetUtils::getElapsedTimeInMilliseconds(stopTime - startTime);
printf("\t -----------------------------------------------\n");
printf("\t Create triangle mesh with %d triangles: \n",numTriangles);
cookingPerformance ? printf("\t\t Cooking performance on\n") : printf("\t\t Cooking performance off\n");
inserted ? printf("\t\t Mesh inserted on\n") : printf("\t\t Mesh inserted off\n");
!skipEdgeData ? printf("\t\t Precompute edge data on\n") : printf("\t\t Precompute edge data off\n");
!skipMeshCleanup ? printf("\t\t Mesh cleanup on\n") : printf("\t\t Mesh cleanup off\n");
printf("\t\t Mesh size/performance trade-off: %f \n", double(params.midphaseDesc.mBVH33Desc.meshSizePerformanceTradeOff));
printf("\t Elapsed time in ms: %f \n", double(elapsedTime));
if(!inserted)
{
printf("\t Mesh size: %d \n", meshSize);
}
triMesh->release();
}
// Creates a triangle mesh using BVH34 midphase with different settings.
void createBV34TriangleMesh(PxU32 numVertices, const PxVec3* vertices, PxU32 numTriangles, const PxU32* indices,
bool skipMeshCleanup, bool skipEdgeData, bool inserted, const PxU32 numTrisPerLeaf)
{
PxU64 startTime = SnippetUtils::getCurrentTimeCounterValue();
PxTriangleMeshDesc meshDesc;
meshDesc.points.count = numVertices;
meshDesc.points.data = vertices;
meshDesc.points.stride = sizeof(PxVec3);
meshDesc.triangles.count = numTriangles;
meshDesc.triangles.data = indices;
meshDesc.triangles.stride = 3 * sizeof(PxU32);
PxCookingParams params = gCooking->getParams();
// Create BVH34 midphase
params.midphaseDesc = PxMeshMidPhase::eBVH34;
// setup common cooking params
setupCommonCookingParams(params, skipMeshCleanup, skipEdgeData);
// Cooking mesh with less triangles per leaf produces larger meshes with better runtime performance
// and worse cooking performance. Cooking time is better when more triangles per leaf are used.
params.midphaseDesc.mBVH34Desc.numPrimsPerLeaf = numTrisPerLeaf;
gCooking->setParams(params);
#if defined(PX_CHECKED) || defined(PX_DEBUG)
// If DISABLE_CLEAN_MESH is set, the mesh is not cleaned during the cooking.
// We should check the validity of provided triangles in debug/checked builds though.
if (skipMeshCleanup)
{
PX_ASSERT(gCooking->validateTriangleMesh(meshDesc));
}
#endif // DEBUG
PxTriangleMesh* triMesh = NULL;
PxU32 meshSize = 0;
// The cooked mesh may either be saved to a stream for later loading, or inserted directly into PxPhysics.
if (inserted)
{
triMesh = gCooking->createTriangleMesh(meshDesc, gPhysics->getPhysicsInsertionCallback());
}
else
{
PxDefaultMemoryOutputStream outBuffer;
gCooking->cookTriangleMesh(meshDesc, outBuffer);
PxDefaultMemoryInputData stream(outBuffer.getData(), outBuffer.getSize());
triMesh = gPhysics->createTriangleMesh(stream);
meshSize = outBuffer.getSize();
}
// Print the elapsed time for comparison
PxU64 stopTime = SnippetUtils::getCurrentTimeCounterValue();
float elapsedTime = SnippetUtils::getElapsedTimeInMilliseconds(stopTime - startTime);
printf("\t -----------------------------------------------\n");
printf("\t Create triangle mesh with %d triangles: \n", numTriangles);
inserted ? printf("\t\t Mesh inserted on\n") : printf("\t\t Mesh inserted off\n");
!skipEdgeData ? printf("\t\t Precompute edge data on\n") : printf("\t\t Precompute edge data off\n");
!skipMeshCleanup ? printf("\t\t Mesh cleanup on\n") : printf("\t\t Mesh cleanup off\n");
printf("\t\t Num triangles per leaf: %d \n", numTrisPerLeaf);
printf("\t Elapsed time in ms: %f \n", double(elapsedTime));
if (!inserted)
{
printf("\t Mesh size: %d \n", meshSize);
}
triMesh->release();
}
void createTriangleMeshes()
{
const PxU32 numColumns = 128;
const PxU32 numRows = 128;
const PxU32 numVertices = (numColumns + 1)*(numRows + 1);
const PxU32 numTriangles = numColumns*numRows * 2;
PxVec3* vertices = new PxVec3[numVertices];
PxU32* indices = new PxU32[numTriangles * 3];
srand(50);
createRandomTerrain(PxVec3(0.0f, 0.0f, 0.0f), numRows, numColumns, 1.0f, 1.0f, 1.f, vertices, indices);
// Create triangle mesh using BVH33 midphase with different settings
printf("-----------------------------------------------\n");
printf("Create triangles mesh using BVH33 midphase: \n\n");
// Favor runtime speed, cleaning the mesh and precomputing active edges. Store the mesh in a stream.
// These are the default settings, suitable for offline cooking.
createBV33TriangleMesh(numVertices,vertices,numTriangles,indices, false, false, false, false, false);
// Favor mesh size, cleaning the mesh and precomputing active edges. Store the mesh in a stream.
createBV33TriangleMesh(numVertices, vertices, numTriangles, indices, false, false, false, false, true);
// Favor cooking speed, skip mesh cleanup, but precompute active edges. Insert into PxPhysics.
// These settings are suitable for runtime cooking, although selecting fast cooking may reduce
// runtime performance of simulation and queries. We still need to ensure the triangles
// are valid, so we perform a validation check in debug/checked builds.
createBV33TriangleMesh(numVertices,vertices,numTriangles,indices, true, false, true, true, false);
// Favor cooking speed, skip mesh cleanup, and don't precompute the active edges. Insert into PxPhysics.
// This is the fastest possible solution for runtime cooking, but all edges are marked as active, which can
// further reduce runtime performance, and also affect behavior.
createBV33TriangleMesh(numVertices,vertices,numTriangles,indices, false, true, true, true, false);
// Create triangle mesh using BVH34 midphase with different settings
printf("-----------------------------------------------\n");
printf("Create triangles mesh using BVH34 midphase: \n\n");
// Favor runtime speed, cleaning the mesh and precomputing active edges. Store the mesh in a stream.
// These are the default settings, suitable for offline cooking.
createBV34TriangleMesh(numVertices, vertices, numTriangles, indices, false, false, false, 4);
// Favor mesh size, cleaning the mesh and precomputing active edges. Store the mesh in a stream.
createBV34TriangleMesh(numVertices, vertices, numTriangles, indices, false, false, false, 15);
// Favor cooking speed, skip mesh cleanup, but precompute active edges. Insert into PxPhysics.
// These settings are suitable for runtime cooking, although selecting more triangles per leaf may reduce
// runtime performance of simulation and queries. We still need to ensure the triangles
// are valid, so we perform a validation check in debug/checked builds.
createBV34TriangleMesh(numVertices, vertices, numTriangles, indices, true, false, true, 15);
// Favor cooking speed, skip mesh cleanup, and don't precompute the active edges. Insert into PxPhysics.
// This is the fastest possible solution for runtime cooking, but all edges are marked as active, which can
// further reduce runtime performance, and also affect behavior.
createBV34TriangleMesh(numVertices, vertices, numTriangles, indices, false, true, true, 15);
delete [] vertices;
delete [] indices;
}
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
createTriangleMeshes();
}
void cleanupPhysics()
{
gPhysics->release();
gCooking->release();
gFoundation->release();
printf("SnippetTriangleMeshCreate done.\n");
}
int snippetMain(int, const char*const*)
{
initPhysics();
cleanupPhysics();
return 0;
}

View File

@ -0,0 +1,528 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates the use of built-in triggers, and how to emulate
// them with regular shapes if you need CCD or trigger-trigger notifications.
//
// ****************************************************************************
#include "PxPhysicsAPI.h"
#include "../snippetutils/SnippetUtils.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
using namespace physx;
enum TriggerImpl
{
// Uses built-in triggers (PxShapeFlag::eTRIGGER_SHAPE).
REAL_TRIGGERS,
// Emulates triggers using a filter shader. Needs one reserved value in PxFilterData.
FILTER_SHADER,
// Emulates triggers using a filter callback. Doesn't use PxFilterData but needs user-defined way to mark a shape as a trigger.
FILTER_CALLBACK,
};
struct ScenarioData
{
TriggerImpl mImpl;
bool mCCD;
bool mTriggerTrigger;
};
#define SCENARIO_COUNT 9
static ScenarioData gData[SCENARIO_COUNT] = {
{REAL_TRIGGERS, false, false},
{FILTER_SHADER, false, false},
{FILTER_CALLBACK, false, false},
{REAL_TRIGGERS, true, false},
{FILTER_SHADER, true, false},
{FILTER_CALLBACK, true, false},
{REAL_TRIGGERS, false, true},
{FILTER_SHADER, false, true},
{FILTER_CALLBACK, false, true},
};
static PxU32 gScenario = 0;
static PX_FORCE_INLINE TriggerImpl getImpl() { return gData[gScenario].mImpl; }
static PX_FORCE_INLINE bool usesCCD() { return gData[gScenario].mCCD; }
static PX_FORCE_INLINE bool usesTriggerTrigger() { return gData[gScenario].mTriggerTrigger; }
static PxDefaultAllocator gAllocator;
static PxDefaultErrorCallback gErrorCallback;
static PxFoundation* gFoundation = NULL;
static PxPhysics* gPhysics = NULL;
static PxDefaultCpuDispatcher* gDispatcher = NULL;
static PxScene* gScene = NULL;
static PxMaterial* gMaterial = NULL;
static PxPvd* gPvd = NULL;
static bool gPause = false;
static bool gOneFrame = false;
// Detects a trigger using the shape's simulation filter data. See createTriggerShape() function.
bool isTrigger(const PxFilterData& data)
{
if(data.word0!=0xffffffff)
return false;
if(data.word1!=0xffffffff)
return false;
if(data.word2!=0xffffffff)
return false;
if(data.word3!=0xffffffff)
return false;
return true;
}
bool isTriggerShape(PxShape* shape)
{
const TriggerImpl impl = getImpl();
// Detects native built-in triggers.
if(impl==REAL_TRIGGERS && (shape->getFlags() & PxShapeFlag::eTRIGGER_SHAPE))
return true;
// Detects our emulated triggers using the simulation filter data. See createTriggerShape() function.
if(impl==FILTER_SHADER && ::isTrigger(shape->getSimulationFilterData()))
return true;
// Detects our emulated triggers using the simulation filter callback. See createTriggerShape() function.
if(impl==FILTER_CALLBACK && shape->userData)
return true;
return false;
}
static PxFilterFlags triggersUsingFilterShader(PxFilterObjectAttributes /*attributes0*/, PxFilterData filterData0,
PxFilterObjectAttributes /*attributes1*/, PxFilterData filterData1,
PxPairFlags& pairFlags, const void* /*constantBlock*/, PxU32 /*constantBlockSize*/)
{
// printf("contactReportFilterShader\n");
PX_ASSERT(getImpl()==FILTER_SHADER);
// We need to detect whether one of the shapes is a trigger.
const bool isTriggerPair = isTrigger(filterData0) || isTrigger(filterData1);
// If we have a trigger, replicate the trigger codepath from PxDefaultSimulationFilterShader
if(isTriggerPair)
{
pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
if(usesCCD())
pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT;
return PxFilterFlag::eDEFAULT;
}
else
{
// Otherwise use the default flags for regular pairs
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
return PxFilterFlag::eDEFAULT;
}
}
static PxFilterFlags triggersUsingFilterCallback(PxFilterObjectAttributes /*attributes0*/, PxFilterData /*filterData0*/,
PxFilterObjectAttributes /*attributes1*/, PxFilterData /*filterData1*/,
PxPairFlags& pairFlags, const void* /*constantBlock*/, PxU32 /*constantBlockSize*/)
{
// printf("contactReportFilterShader\n");
PX_ASSERT(getImpl()==FILTER_CALLBACK);
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
if(usesCCD())
pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT|PxPairFlag::eNOTIFY_TOUCH_CCD;
return PxFilterFlag::eCALLBACK;
}
class TriggersFilterCallback : public PxSimulationFilterCallback
{
virtual PxFilterFlags pairFound(PxU32 /*pairID*/,
PxFilterObjectAttributes /*attributes0*/, PxFilterData /*filterData0*/, const PxActor* /*a0*/, const PxShape* s0,
PxFilterObjectAttributes /*attributes1*/, PxFilterData /*filterData1*/, const PxActor* /*a1*/, const PxShape* s1,
PxPairFlags& pairFlags)
{
// printf("pairFound\n");
if(s0->userData || s1->userData) // See createTriggerShape() function
{
pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
if(usesCCD())
pairFlags |= PxPairFlag::eDETECT_CCD_CONTACT|PxPairFlag::eNOTIFY_TOUCH_CCD;
}
else
pairFlags = PxPairFlag::eCONTACT_DEFAULT;
return PxFilterFlags();
}
virtual void pairLost(PxU32 /*pairID*/,
PxFilterObjectAttributes /*attributes0*/,
PxFilterData /*filterData0*/,
PxFilterObjectAttributes /*attributes1*/,
PxFilterData /*filterData1*/,
bool /*objectRemoved*/)
{
// printf("pairLost\n");
}
virtual bool statusChange(PxU32& /*pairID*/, PxPairFlags& /*pairFlags*/, PxFilterFlags& /*filterFlags*/)
{
// printf("statusChange\n");
return false;
}
}gTriggersFilterCallback;
class ContactReportCallback: public PxSimulationEventCallback
{
void onConstraintBreak(PxConstraintInfo* /*constraints*/, PxU32 /*count*/)
{
printf("onConstraintBreak\n");
}
void onWake(PxActor** /*actors*/, PxU32 /*count*/)
{
printf("onWake\n");
}
void onSleep(PxActor** /*actors*/, PxU32 /*count*/)
{
printf("onSleep\n");
}
void onTrigger(PxTriggerPair* pairs, PxU32 count)
{
// printf("onTrigger: %d trigger pairs\n", count);
while(count--)
{
const PxTriggerPair& current = *pairs++;
if(current.status & PxPairFlag::eNOTIFY_TOUCH_FOUND)
printf("Shape is entering trigger volume\n");
if(current.status & PxPairFlag::eNOTIFY_TOUCH_LOST)
printf("Shape is leaving trigger volume\n");
}
}
void onAdvance(const PxRigidBody*const*, const PxTransform*, const PxU32)
{
printf("onAdvance\n");
}
void onContact(const PxContactPairHeader& /*pairHeader*/, const PxContactPair* pairs, PxU32 count)
{
// printf("onContact: %d pairs\n", count);
while(count--)
{
const PxContactPair& current = *pairs++;
// The reported pairs can be trigger pairs or not. We only enabled contact reports for
// trigger pairs in the filter shader, so we don't need to do further checks here. In a
// real-world scenario you would probably need a way to tell whether one of the shapes
// is a trigger or not. You could e.g. reuse the PxFilterData like we did in the filter
// shader, or maybe use the shape's userData to identify triggers, or maybe put triggers
// in a hash-set and test the reported shape pointers against it. Many options here.
if(current.events & (PxPairFlag::eNOTIFY_TOUCH_FOUND|PxPairFlag::eNOTIFY_TOUCH_CCD))
printf("Shape is entering trigger volume\n");
if(current.events & PxPairFlag::eNOTIFY_TOUCH_LOST)
printf("Shape is leaving trigger volume\n");
if(isTriggerShape(current.shapes[0]) && isTriggerShape(current.shapes[1]))
printf("Trigger-trigger overlap detected\n");
}
}
};
static ContactReportCallback gContactReportCallback;
static PxShape* createTriggerShape(const PxGeometry& geom, bool isExclusive)
{
const TriggerImpl impl = getImpl();
PxShape* shape = nullptr;
if(impl==REAL_TRIGGERS)
{
const PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eTRIGGER_SHAPE;
shape = gPhysics->createShape(geom, *gMaterial, isExclusive, shapeFlags);
}
else if(impl==FILTER_SHADER)
{
PxShapeFlags shapeFlags = PxShapeFlag::eVISUALIZATION | PxShapeFlag::eSIMULATION_SHAPE;
shape = gPhysics->createShape(geom, *gMaterial, isExclusive, shapeFlags);
// For this method to work, you need a way to mark shapes as triggers without using PxShapeFlag::eTRIGGER_SHAPE
// (so that trigger-trigger pairs are reported), and without calling a PxShape function (so that the data is
// available in a filter shader).
//
// One way is to reserve a special PxFilterData value/mask for triggers. It may not always be possible depending
// on how you otherwise use the filter data).
const PxFilterData triggerFilterData(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff);
shape->setSimulationFilterData(triggerFilterData);
}
else if(impl==FILTER_CALLBACK)
{
// We will have access to shape pointers in the filter callback so we just mark triggers in an arbitrary way here,
// for example using the shape's userData.
shape = gPhysics->createShape(geom, *gMaterial, isExclusive);
shape->userData = shape; // Arbitrary rule: it's a trigger if non null
}
return shape;
}
static void createDefaultScene()
{
const bool ccd = usesCCD();
// Create trigger shape
{
const PxVec3 halfExtent(10.0f, ccd ? 0.01f : 1.0f, 10.0f);
PxShape* shape = createTriggerShape(PxBoxGeometry(halfExtent), false);
if(shape)
{
PxRigidStatic* body = gPhysics->createRigidStatic(PxTransform(0.0f, 10.0f, 0.0f));
body->attachShape(*shape);
gScene->addActor(*body);
shape->release();
}
}
// Create falling rigid body
{
const PxVec3 halfExtent(ccd ? 0.1f : 1.0f);
PxShape* shape = gPhysics->createShape(PxBoxGeometry(halfExtent), *gMaterial);
PxRigidDynamic* body = gPhysics->createRigidDynamic(PxTransform(0.0f, ccd ? 30.0f : 20.0f, 0.0f));
body->attachShape(*shape);
PxRigidBodyExt::updateMassAndInertia(*body, 1.0f);
gScene->addActor(*body);
shape->release();
if(ccd)
{
body->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);
body->setLinearVelocity(PxVec3(0.0f, -140.0f, 0.0f));
}
}
}
static void createTriggerTriggerScene()
{
struct Local
{
static void createSphereActor(const PxVec3& pos, const PxVec3& linVel)
{
PxShape* sphereShape = gPhysics->createShape(PxSphereGeometry(1.0f), *gMaterial, false);
PxRigidDynamic* body = gPhysics->createRigidDynamic(PxTransform(pos));
body->attachShape(*sphereShape);
PxShape* triggerShape = createTriggerShape(PxSphereGeometry(4.0f), true);
body->attachShape(*triggerShape);
const bool isTriggershape = triggerShape->getFlags() & PxShapeFlag::eTRIGGER_SHAPE;
if(!isTriggershape)
triggerShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
PxRigidBodyExt::updateMassAndInertia(*body, 1.0f);
if(!isTriggershape)
triggerShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
gScene->addActor(*body);
sphereShape->release();
triggerShape->release();
body->setLinearVelocity(linVel);
}
};
Local::createSphereActor(PxVec3(-5.0f, 1.0f, 0.0f), PxVec3( 1.0f, 0.0f, 0.0f));
Local::createSphereActor(PxVec3( 5.0f, 1.0f, 0.0f), PxVec3(-1.0f, 0.0f, 0.0f));
}
static void initScene()
{
const TriggerImpl impl = getImpl();
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
// sceneDesc.flags &= ~PxSceneFlag::eENABLE_PCM;
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.gravity = PxVec3(0, -9.81f, 0);
sceneDesc.simulationEventCallback = &gContactReportCallback;
if(impl==REAL_TRIGGERS)
{
sceneDesc.filterShader = PxDefaultSimulationFilterShader;
printf("- Using built-in triggers.\n");
}
else if(impl==FILTER_SHADER)
{
sceneDesc.filterShader = triggersUsingFilterShader;
printf("- Using regular shapes emulating triggers with a filter shader.\n");
}
else if(impl==FILTER_CALLBACK)
{
sceneDesc.filterShader = triggersUsingFilterCallback;
sceneDesc.filterCallback = &gTriggersFilterCallback;
printf("- Using regular shapes emulating triggers with a filter callback.\n");
}
if(usesCCD())
{
sceneDesc.flags |= PxSceneFlag::eENABLE_CCD;
printf("- Using CCD.\n");
}
else
{
printf("- Using no CCD.\n");
}
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
PxRigidStatic* groundPlane = PxCreatePlane(*gPhysics, PxPlane(0,1,0,0), *gMaterial);
gScene->addActor(*groundPlane);
if(usesTriggerTrigger())
createTriggerTriggerScene();
else
createDefaultScene();
}
static void releaseScene()
{
PX_RELEASE(gScene);
}
void stepPhysics(bool /*interactive*/)
{
if(gPause && !gOneFrame)
return;
gOneFrame = false;
if(gScene)
{
gScene->simulate(1.0f/60.0f);
gScene->fetchResults(true);
}
}
void initPhysics(bool /*interactive*/)
{
printf("Press keys F1 to F9 to select a scenario.\n");
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true,gPvd);
PxInitExtensions(*gPhysics,gPvd);
const PxU32 numCores = SnippetUtils::getNbPhysicalCores();
gDispatcher = PxDefaultCpuDispatcherCreate(numCores == 0 ? 0 : numCores - 1);
gMaterial = gPhysics->createMaterial(1.0f, 1.0f, 0.0f);
initScene();
}
void cleanupPhysics(bool /*interactive*/)
{
releaseScene();
PX_RELEASE(gDispatcher);
PxCloseExtensions();
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
PX_RELEASE(gPvd);
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetTriggers done.\n");
}
void keyPress(unsigned char key, const PxTransform& /*camera*/)
{
if(key=='p' || key=='P')
gPause = !gPause;
if(key=='o' || key=='O')
{
gPause = true;
gOneFrame = true;
}
if(gScene)
{
if(key>=1 && key<=SCENARIO_COUNT)
{
gScenario = key-1;
releaseScene();
initScene();
}
if(key=='r' || key=='R')
{
releaseScene();
initScene();
}
}
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics(false);
for(PxU32 i=0; i<250; i++)
stepPhysics(false);
cleanupPhysics(false);
#endif
return 0;
}

View File

@ -0,0 +1,198 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics(bool interactive);
extern void stepPhysics(bool interactive);
extern void cleanupPhysics(bool interactive);
extern void keyPress(unsigned char key, const PxTransform& camera);
bool isTrigger(const PxFilterData& data);
bool isTriggerShape(PxShape* shape);
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void keyboardCallback2(int key, int /*x*/, int /*y*/)
{
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
static void InitLighting()
{
glEnable(GL_COLOR_MATERIAL);
const float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, zero);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zero);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zero);
glEnable(GL_LIGHTING);
PxVec3 Dir(-1.0f, 1.0f, 0.5f);
// PxVec3 Dir(0.0f, 1.0f, 0.0f);
Dir.normalize();
const float AmbientValue = 0.3f;
const float ambientColor0[] = { AmbientValue, AmbientValue, AmbientValue, 0.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor0);
const float specularColor0[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor0);
const float diffuseColor0[] = { 0.7f, 0.7f, 0.7f, 0.0f };
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor0);
const float position0[] = { Dir.x, Dir.y, Dir.z, 0.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position0);
glEnable(GL_LIGHT0);
// glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
// glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
if(0)
{
glEnable(GL_FOG);
glFogi(GL_FOG_MODE,GL_LINEAR);
//glFogi(GL_FOG_MODE,GL_EXP);
//glFogi(GL_FOG_MODE,GL_EXP2);
glFogf(GL_FOG_START, 0.0f);
glFogf(GL_FOG_END, 100.0f);
glFogf(GL_FOG_DENSITY, 0.005f);
// glClearColor(0.2f, 0.2f, 0.2f, 1.0);
// const PxVec3 FogColor(0.2f, 0.2f, 0.2f);
const PxVec3 FogColor(1.0f);
glFogfv(GL_FOG_COLOR, &FogColor.x);
}
}
class MyTriggerRender : public Snippets::TriggerRender
{
public:
virtual bool isTrigger(physx::PxShape* shape) const
{
return ::isTriggerShape(shape);
}
};
void renderCallback()
{
stepPhysics(true);
if(0)
{
PxVec3 camPos = sCamera->getEye();
PxVec3 camDir = sCamera->getDir();
printf("camPos: (%ff, %ff, %ff)\n", double(camPos.x), double(camPos.y), double(camPos.z));
printf("camDir: (%ff, %ff, %ff)\n", double(camDir.x), double(camDir.y), double(camDir.z));
}
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
InitLighting();
PxScene* scene;
PxGetPhysics().getScenes(&scene,1);
PxU32 nbActors = scene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
scene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
MyTriggerRender tr;
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true, PxVec3(0.0f, 0.75f, 0.0f), &tr);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics(true);
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(8.757190f, 12.367847f, 23.541956f), PxVec3(-0.407947f, -0.042438f, -0.912019f));
Snippets::setupDefaultWindow("PhysX Snippet Triggers");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutSpecialFunc(keyboardCallback2);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics(true);
glutMainLoop();
}
#endif

View File

@ -0,0 +1,214 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#include "SnippetUtils.h"
#include "foundation/PxSimpleTypes.h"
#include "CmPhysXCommon.h"
#include "PsAtomic.h"
#include "PsString.h"
#include "PsSync.h"
#include "PsThread.h"
#include "PsTime.h"
#include "PsMutex.h"
#include "PsAllocator.h"
#include "extensions/PxDefaultAllocator.h"
namespace physx
{
namespace
{
PxDefaultAllocator gUtilAllocator;
struct UtilAllocator // since we're allocating internal classes here, make sure we align properly
{
void* allocate(size_t size,const char* file, PxU32 line) { return gUtilAllocator.allocate(size, NULL, file, int(line)); }
void deallocate(void* ptr) { gUtilAllocator.deallocate(ptr); }
};
}
namespace SnippetUtils
{
PxI32 atomicIncrement(volatile PxI32* val)
{
return Ps::atomicIncrement(val);
}
PxI32 atomicDecrement(volatile PxI32* val)
{
return Ps::atomicDecrement(val);
}
//******************************************************************************//
PxU32 getNbPhysicalCores()
{
return Ps::Thread::getNbPhysicalCores();
}
//******************************************************************************//
PxU32 getThreadId()
{
return static_cast<PxU32>(Ps::Thread::getId());
}
//******************************************************************************//
PxU64 getCurrentTimeCounterValue()
{
return Ps::Time::getCurrentCounterValue();
}
PxReal getElapsedTimeInMilliseconds(const PxU64 elapsedTime)
{
return Ps::Time::getCounterFrequency().toTensOfNanos(elapsedTime)/(100.0f * 1000.0f);
}
PxReal getElapsedTimeInMicroSeconds(const PxU64 elapsedTime)
{
return Ps::Time::getCounterFrequency().toTensOfNanos(elapsedTime)/(100.0f);
}
//******************************************************************************//
struct Sync: public Ps::SyncT<UtilAllocator> {};
Sync* syncCreate()
{
return new(gUtilAllocator.allocate(sizeof(Sync), 0, 0, 0)) Sync();
}
void syncWait(Sync* sync)
{
sync->wait();
}
void syncSet(Sync* sync)
{
sync->set();
}
void syncReset(Sync* sync)
{
sync->reset();
}
void syncRelease(Sync* sync)
{
sync->~Sync();
gUtilAllocator.deallocate(sync);
}
//******************************************************************************//
struct Thread: public Ps::ThreadT<UtilAllocator>
{
Thread(ThreadEntryPoint entryPoint, void* data):
Ps::ThreadT<UtilAllocator>(),
mEntryPoint(entryPoint),
mData(data)
{
}
virtual void execute(void)
{
mEntryPoint(mData);
}
ThreadEntryPoint mEntryPoint;
void* mData;
};
Thread* threadCreate(ThreadEntryPoint entryPoint, void* data)
{
Thread* createThread = static_cast<Thread*>(gUtilAllocator.allocate(sizeof(Thread), 0, 0, 0));
PX_PLACEMENT_NEW(createThread, Thread(entryPoint, data));
createThread->start();
return createThread;
}
void threadQuit(Thread* thread)
{
thread->quit();
}
void threadSignalQuit(Thread* thread)
{
thread->signalQuit();
}
bool threadWaitForQuit(Thread* thread)
{
return thread->waitForQuit();
}
bool threadQuitIsSignalled(Thread* thread)
{
return thread->quitIsSignalled();
}
void threadRelease(Thread* thread)
{
thread->~Thread();
gUtilAllocator.deallocate(thread);
}
//******************************************************************************//
struct Mutex: public Ps::MutexT<UtilAllocator> {};
Mutex* mutexCreate()
{
return new(gUtilAllocator.allocate(sizeof(Mutex), 0, 0, 0)) Mutex();
}
void mutexLock(Mutex* mutex)
{
mutex->lock();
}
void mutexUnlock(Mutex* mutex)
{
mutex->unlock();
}
void mutexRelease(Mutex* mutex)
{
mutex->~Mutex();
gUtilAllocator.deallocate(mutex);
}
} // namespace physXUtils
} // namespace physx

View File

@ -0,0 +1,127 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
#include "foundation/PxSimpleTypes.h"
#define PX_RELEASE(x) if(x) { x->release(); x = NULL; }
namespace physx
{
namespace SnippetUtils
{
/* Increment the specified location. Return the incremented value. */
PxI32 atomicIncrement(volatile PxI32* val);
/* Decrement the specified location. Return the decremented value. */
PxI32 atomicDecrement(volatile PxI32* val);
//******************************************************************************//
/* Return the number of physical cores (does not include hyper-threaded cores), returns 0 on failure. */
PxU32 getNbPhysicalCores();
//******************************************************************************//
/* Return the id of a thread. */
PxU32 getThreadId();
//******************************************************************************//
/* Return the current time */
PxU64 getCurrentTimeCounterValue();
/* Convert to milliseconds an elapsed time computed from the difference of the times returned from two calls to getCurrentTimeCounterValue. */
PxReal getElapsedTimeInMilliseconds(const PxU64 elapsedTime);
/* Convert to microseconds an elapsed time computed from the difference of the times returned from two calls to getCurrentTimeCounterValue. */
PxReal getElapsedTimeInMicroSeconds(const PxU64 elapsedTime);
//******************************************************************************//
struct Sync;
/* Create a sync object. Returns a unique handle to the sync object so that it may be addressed through syncWait etc. */
Sync* syncCreate();
/* Wait indefinitely until the specified sync object is signaled. */
void syncWait(Sync* sync);
/* Signal the specified synchronization object, waking all threads waiting on it. */
void syncSet(Sync* sync);
/** Reset the specified synchronization object. */
void syncReset(Sync* sync);
/* Release the specified sync object so that it may be reused with syncCreate. */
void syncRelease(Sync* sync);
//******************************************************************************//
struct Thread;
/* Prototype of callback passed to threadCreate. */
typedef void (*ThreadEntryPoint)(void*);
/* Create a thread object and return a unique handle to the thread object so that it may be addressed through threadStart etc.
entryPoint implements ThreadEntryPoint and data will be passed as a function argument, POSIX-style. */
Thread* threadCreate(ThreadEntryPoint entryPoint, void* data);
/* Cleanly shut down the specified thread. Called in the context of the spawned thread. */
void threadQuit(Thread* thread);
/* Stop the specified thread. Signals the spawned thread that it should stop, so the
thread should check regularly. */
void threadSignalQuit(Thread* thread);
/* Wait for the specified thread to stop. Should be called in the context of the spawning
thread. Returns false if the thread has not been started.*/
bool threadWaitForQuit(Thread* thread);
/* Check whether the thread is signalled to quit. Called in the context of the
spawned thread. */
bool threadQuitIsSignalled(Thread* thread);
/* Release the specified thread object so that it may be reused with threadCreate. */
void threadRelease(Thread* thread);
//******************************************************************************//
struct Mutex;
/* Create a mutex object and return a unique handle to the mutex object so that it may be addressed through mutexLock etc. */
Mutex* mutexCreate();
/* Acquire (lock) the specified mutex. If the mutex is already locked by another thread, this method blocks until the mutex is unlocked.*/
void mutexLock(Mutex* mutex);
/* Release (unlock) the specified mutex, the calling thread must have previously called lock() or method will error. */
void mutexUnlock(Mutex* mutex);
/* Release the specified mutex so that it may be reused with mutexCreate. */
void mutexRelease(Mutex* mutex);
}
}

View File

@ -0,0 +1,531 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
// ****************************************************************************
// This snippet illustrates simple use of PxVehicleDrive4W.
//
// It creates a vehicle on a plane and then controls the vehicle so that it performs a
// number of choreographed manoeuvres such as accelerate, reverse, brake, handbrake, and turn.
// It is a good idea to record and playback with pvd (PhysX Visual Debugger).
// ****************************************************************************
#include <ctype.h>
#include "PxPhysicsAPI.h"
#include "vehicle/PxVehicleUtil.h"
#include "../snippetvehiclecommon/SnippetVehicleSceneQuery.h"
#include "../snippetvehiclecommon/SnippetVehicleFilterShader.h"
#include "../snippetvehiclecommon/SnippetVehicleTireFriction.h"
#include "../snippetvehiclecommon/SnippetVehicleCreate.h"
#include "../snippetcommon/SnippetPrint.h"
#include "../snippetcommon/SnippetPVD.h"
#include "../snippetutils/SnippetUtils.h"
using namespace physx;
using namespace snippetvehicle;
PxDefaultAllocator gAllocator;
PxDefaultErrorCallback gErrorCallback;
PxFoundation* gFoundation = NULL;
PxPhysics* gPhysics = NULL;
PxDefaultCpuDispatcher* gDispatcher = NULL;
PxScene* gScene = NULL;
PxCooking* gCooking = NULL;
PxMaterial* gMaterial = NULL;
PxPvd* gPvd = NULL;
VehicleSceneQueryData* gVehicleSceneQueryData = NULL;
PxBatchQuery* gBatchQuery = NULL;
PxVehicleDrivableSurfaceToTireFrictionPairs* gFrictionPairs = NULL;
PxRigidStatic* gGroundPlane = NULL;
PxVehicleDrive4W* gVehicle4W = NULL;
bool gIsVehicleInAir = true;
PxF32 gSteerVsForwardSpeedData[2*8]=
{
0.0f, 0.75f,
5.0f, 0.75f,
30.0f, 0.125f,
120.0f, 0.1f,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32,
PX_MAX_F32, PX_MAX_F32
};
PxFixedSizeLookupTable<8> gSteerVsForwardSpeedTable(gSteerVsForwardSpeedData,4);
PxVehicleKeySmoothingData gKeySmoothingData=
{
{
6.0f, //rise rate eANALOG_INPUT_ACCEL
6.0f, //rise rate eANALOG_INPUT_BRAKE
6.0f, //rise rate eANALOG_INPUT_HANDBRAKE
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
},
{
10.0f, //fall rate eANALOG_INPUT_ACCEL
10.0f, //fall rate eANALOG_INPUT_BRAKE
10.0f, //fall rate eANALOG_INPUT_HANDBRAKE
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
}
};
PxVehiclePadSmoothingData gPadSmoothingData=
{
{
6.0f, //rise rate eANALOG_INPUT_ACCEL
6.0f, //rise rate eANALOG_INPUT_BRAKE
6.0f, //rise rate eANALOG_INPUT_HANDBRAKE
2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
},
{
10.0f, //fall rate eANALOG_INPUT_ACCEL
10.0f, //fall rate eANALOG_INPUT_BRAKE
10.0f, //fall rate eANALOG_INPUT_HANDBRAKE
5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
}
};
PxVehicleDrive4WRawInputData gVehicleInputData;
enum DriveMode
{
eDRIVE_MODE_ACCEL_FORWARDS=0,
eDRIVE_MODE_ACCEL_REVERSE,
eDRIVE_MODE_HARD_TURN_LEFT,
eDRIVE_MODE_HANDBRAKE_TURN_LEFT,
eDRIVE_MODE_HARD_TURN_RIGHT,
eDRIVE_MODE_HANDBRAKE_TURN_RIGHT,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_NONE
};
DriveMode gDriveModeOrder[] =
{
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_ACCEL_FORWARDS,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_ACCEL_REVERSE,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_HARD_TURN_LEFT,
eDRIVE_MODE_BRAKE,
eDRIVE_MODE_HARD_TURN_RIGHT,
eDRIVE_MODE_ACCEL_FORWARDS,
eDRIVE_MODE_HANDBRAKE_TURN_LEFT,
eDRIVE_MODE_ACCEL_FORWARDS,
eDRIVE_MODE_HANDBRAKE_TURN_RIGHT,
eDRIVE_MODE_NONE
};
PxF32 gVehicleModeLifetime = 4.0f;
PxF32 gVehicleModeTimer = 0.0f;
PxU32 gVehicleOrderProgress = 0;
bool gVehicleOrderComplete = false;
bool gMimicKeyInputs = false;
VehicleDesc initVehicleDesc()
{
//Set up the chassis mass, dimensions, moment of inertia, and center of mass offset.
//The moment of inertia is just the moment of inertia of a cuboid but modified for easier steering.
//Center of mass offset is 0.65m above the base of the chassis and 0.25m towards the front.
const PxF32 chassisMass = 1500.0f;
const PxVec3 chassisDims(2.5f,2.0f,5.0f);
const PxVec3 chassisMOI
((chassisDims.y*chassisDims.y + chassisDims.z*chassisDims.z)*chassisMass/12.0f,
(chassisDims.x*chassisDims.x + chassisDims.z*chassisDims.z)*0.8f*chassisMass/12.0f,
(chassisDims.x*chassisDims.x + chassisDims.y*chassisDims.y)*chassisMass/12.0f);
const PxVec3 chassisCMOffset(0.0f, -chassisDims.y*0.5f + 0.65f, 0.25f);
//Set up the wheel mass, radius, width, moment of inertia, and number of wheels.
//Moment of inertia is just the moment of inertia of a cylinder.
const PxF32 wheelMass = 20.0f;
const PxF32 wheelRadius = 0.5f;
const PxF32 wheelWidth = 0.4f;
const PxF32 wheelMOI = 0.5f*wheelMass*wheelRadius*wheelRadius;
const PxU32 nbWheels = 6;
VehicleDesc vehicleDesc;
vehicleDesc.chassisMass = chassisMass;
vehicleDesc.chassisDims = chassisDims;
vehicleDesc.chassisMOI = chassisMOI;
vehicleDesc.chassisCMOffset = chassisCMOffset;
vehicleDesc.chassisMaterial = gMaterial;
vehicleDesc.chassisSimFilterData = PxFilterData(COLLISION_FLAG_CHASSIS, COLLISION_FLAG_CHASSIS_AGAINST, 0, 0);
vehicleDesc.wheelMass = wheelMass;
vehicleDesc.wheelRadius = wheelRadius;
vehicleDesc.wheelWidth = wheelWidth;
vehicleDesc.wheelMOI = wheelMOI;
vehicleDesc.numWheels = nbWheels;
vehicleDesc.wheelMaterial = gMaterial;
vehicleDesc.chassisSimFilterData = PxFilterData(COLLISION_FLAG_WHEEL, COLLISION_FLAG_WHEEL_AGAINST, 0, 0);
return vehicleDesc;
}
void startAccelerateForwardsMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
}
}
void startAccelerateReverseMode()
{
gVehicle4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eREVERSE);
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
}
}
void startBrakeMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalBrake(true);
}
else
{
gVehicleInputData.setAnalogBrake(1.0f);
}
}
void startTurnHardLeftMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalSteerLeft(true);
}
else
{
gVehicleInputData.setAnalogAccel(true);
gVehicleInputData.setAnalogSteer(-1.0f);
}
}
void startTurnHardRightMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(true);
gVehicleInputData.setDigitalSteerRight(true);
}
else
{
gVehicleInputData.setAnalogAccel(1.0f);
gVehicleInputData.setAnalogSteer(1.0f);
}
}
void startHandbrakeTurnLeftMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalSteerLeft(true);
gVehicleInputData.setDigitalHandbrake(true);
}
else
{
gVehicleInputData.setAnalogSteer(-1.0f);
gVehicleInputData.setAnalogHandbrake(1.0f);
}
}
void startHandbrakeTurnRightMode()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalSteerRight(true);
gVehicleInputData.setDigitalHandbrake(true);
}
else
{
gVehicleInputData.setAnalogSteer(1.0f);
gVehicleInputData.setAnalogHandbrake(1.0f);
}
}
void releaseAllControls()
{
if(gMimicKeyInputs)
{
gVehicleInputData.setDigitalAccel(false);
gVehicleInputData.setDigitalSteerLeft(false);
gVehicleInputData.setDigitalSteerRight(false);
gVehicleInputData.setDigitalBrake(false);
gVehicleInputData.setDigitalHandbrake(false);
}
else
{
gVehicleInputData.setAnalogAccel(0.0f);
gVehicleInputData.setAnalogSteer(0.0f);
gVehicleInputData.setAnalogBrake(0.0f);
gVehicleInputData.setAnalogHandbrake(0.0f);
}
}
void initPhysics()
{
gFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gAllocator, gErrorCallback);
gPvd = PxCreatePvd(*gFoundation);
PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);
gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(), true, gPvd);
PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
PxU32 numWorkers = 1;
gDispatcher = PxDefaultCpuDispatcherCreate(numWorkers);
sceneDesc.cpuDispatcher = gDispatcher;
sceneDesc.filterShader = VehicleFilterShader;
gScene = gPhysics->createScene(sceneDesc);
PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
if(pvdClient)
{
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
}
gMaterial = gPhysics->createMaterial(0.5f, 0.5f, 0.6f);
gCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));
/////////////////////////////////////////////
PxInitVehicleSDK(*gPhysics);
PxVehicleSetBasisVectors(PxVec3(0,1,0), PxVec3(0,0,1));
PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
//Create the batched scene queries for the suspension raycasts.
gVehicleSceneQueryData = VehicleSceneQueryData::allocate(1, PX_MAX_NB_WHEELS, 1, 1, WheelSceneQueryPreFilterBlocking, NULL, gAllocator);
gBatchQuery = VehicleSceneQueryData::setUpBatchedSceneQuery(0, *gVehicleSceneQueryData, gScene);
//Create the friction table for each combination of tire and surface type.
gFrictionPairs = createFrictionPairs(gMaterial);
//Create a plane to drive on.
PxFilterData groundPlaneSimFilterData(COLLISION_FLAG_GROUND, COLLISION_FLAG_GROUND_AGAINST, 0, 0);
gGroundPlane = createDrivablePlane(groundPlaneSimFilterData, gMaterial, gPhysics);
gScene->addActor(*gGroundPlane);
//Create a vehicle that will drive on the plane.
VehicleDesc vehicleDesc = initVehicleDesc();
gVehicle4W = createVehicle4W(vehicleDesc, gPhysics, gCooking);
PxTransform startTransform(PxVec3(0, (vehicleDesc.chassisDims.y*0.5f + vehicleDesc.wheelRadius + 1.0f), 0), PxQuat(PxIdentity));
gVehicle4W->getRigidDynamicActor()->setGlobalPose(startTransform);
gScene->addActor(*gVehicle4W->getRigidDynamicActor());
//Set the vehicle to rest in first gear.
//Set the vehicle to use auto-gears.
gVehicle4W->setToRestState();
gVehicle4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
gVehicle4W->mDriveDynData.setUseAutoGears(true);
gVehicleModeTimer = 0.0f;
gVehicleOrderProgress = 0;
startBrakeMode();
}
void incrementDrivingMode(const PxF32 timestep)
{
gVehicleModeTimer += timestep;
if(gVehicleModeTimer > gVehicleModeLifetime)
{
//If the mode just completed was eDRIVE_MODE_ACCEL_REVERSE then switch back to forward gears.
if(eDRIVE_MODE_ACCEL_REVERSE == gDriveModeOrder[gVehicleOrderProgress])
{
gVehicle4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
}
//Increment to next driving mode.
gVehicleModeTimer = 0.0f;
gVehicleOrderProgress++;
releaseAllControls();
//If we are at the end of the list of driving modes then start again.
if(eDRIVE_MODE_NONE == gDriveModeOrder[gVehicleOrderProgress])
{
gVehicleOrderProgress = 0;
gVehicleOrderComplete = true;
}
//Start driving in the selected mode.
DriveMode eDriveMode = gDriveModeOrder[gVehicleOrderProgress];
switch(eDriveMode)
{
case eDRIVE_MODE_ACCEL_FORWARDS:
startAccelerateForwardsMode();
break;
case eDRIVE_MODE_ACCEL_REVERSE:
startAccelerateReverseMode();
break;
case eDRIVE_MODE_HARD_TURN_LEFT:
startTurnHardLeftMode();
break;
case eDRIVE_MODE_HANDBRAKE_TURN_LEFT:
startHandbrakeTurnLeftMode();
break;
case eDRIVE_MODE_HARD_TURN_RIGHT:
startTurnHardRightMode();
break;
case eDRIVE_MODE_HANDBRAKE_TURN_RIGHT:
startHandbrakeTurnRightMode();
break;
case eDRIVE_MODE_BRAKE:
startBrakeMode();
break;
case eDRIVE_MODE_NONE:
break;
};
//If the mode about to start is eDRIVE_MODE_ACCEL_REVERSE then switch to reverse gears.
if(eDRIVE_MODE_ACCEL_REVERSE == gDriveModeOrder[gVehicleOrderProgress])
{
gVehicle4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eREVERSE);
}
}
}
void stepPhysics()
{
const PxF32 timestep = 1.0f/60.0f;
//Cycle through the driving modes to demonstrate how to accelerate/reverse/brake/turn etc.
incrementDrivingMode(timestep);
//Update the control inputs for the vehicle.
if(gMimicKeyInputs)
{
PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs(gKeySmoothingData, gSteerVsForwardSpeedTable, gVehicleInputData, timestep, gIsVehicleInAir, *gVehicle4W);
}
else
{
PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(gPadSmoothingData, gSteerVsForwardSpeedTable, gVehicleInputData, timestep, gIsVehicleInAir, *gVehicle4W);
}
//Raycasts.
PxVehicleWheels* vehicles[1] = {gVehicle4W};
PxRaycastQueryResult* raycastResults = gVehicleSceneQueryData->getRaycastQueryResultBuffer(0);
const PxU32 raycastResultsSize = gVehicleSceneQueryData->getQueryResultBufferSize();
PxVehicleSuspensionRaycasts(gBatchQuery, 1, vehicles, raycastResultsSize, raycastResults);
//Vehicle update.
const PxVec3 grav = gScene->getGravity();
PxWheelQueryResult wheelQueryResults[PX_MAX_NB_WHEELS];
PxVehicleWheelQueryResult vehicleQueryResults[1] = {{wheelQueryResults, gVehicle4W->mWheelsSimData.getNbWheels()}};
PxVehicleUpdates(timestep, grav, *gFrictionPairs, 1, vehicles, vehicleQueryResults);
//Work out if the vehicle is in the air.
gIsVehicleInAir = gVehicle4W->getRigidDynamicActor()->isSleeping() ? false : PxVehicleIsInAir(vehicleQueryResults[0]);
//Scene update.
gScene->simulate(timestep);
gScene->fetchResults(true);
}
void cleanupPhysics()
{
gVehicle4W->getRigidDynamicActor()->release();
gVehicle4W->free();
PX_RELEASE(gGroundPlane);
PX_RELEASE(gBatchQuery);
gVehicleSceneQueryData->free(gAllocator);
PX_RELEASE(gFrictionPairs);
PxCloseVehicleSDK();
PX_RELEASE(gMaterial);
PX_RELEASE(gCooking);
PX_RELEASE(gScene);
PX_RELEASE(gDispatcher);
PX_RELEASE(gPhysics);
if(gPvd)
{
PxPvdTransport* transport = gPvd->getTransport();
gPvd->release(); gPvd = NULL;
PX_RELEASE(transport);
}
PX_RELEASE(gFoundation);
printf("SnippetVehicle4W done.\n");
}
void keyPress(unsigned char key, const PxTransform& camera)
{
PX_UNUSED(camera);
PX_UNUSED(key);
}
int snippetMain(int, const char*const*)
{
#ifdef RENDER_SNIPPET
extern void renderLoop();
renderLoop();
#else
initPhysics();
while(!gVehicleOrderComplete)
{
stepPhysics();
}
cleanupPhysics();
#endif
return 0;
}

View File

@ -0,0 +1,120 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifdef RENDER_SNIPPET
#include <vector>
#include "PxPhysicsAPI.h"
#include "../snippetrender/SnippetRender.h"
#include "../snippetrender/SnippetCamera.h"
using namespace physx;
extern void initPhysics();
extern void stepPhysics();
extern void cleanupPhysics();
extern void keyPress(unsigned char key, const PxTransform& camera);
extern PxScene* gScene;
namespace
{
Snippets::Camera* sCamera;
void motionCallback(int x, int y)
{
sCamera->handleMotion(x, y);
}
void keyboardCallback(unsigned char key, int x, int y)
{
if(key==27)
exit(0);
if(!sCamera->handleKey(key, x, y))
keyPress(key, sCamera->getTransform());
}
void mouseCallback(int button, int state, int x, int y)
{
sCamera->handleMouse(button, state, x, y);
}
void idleCallback()
{
glutPostRedisplay();
}
void renderCallback()
{
stepPhysics();
Snippets::startRender(sCamera->getEye(), sCamera->getDir());
PxU32 nbActors = gScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC);
if(nbActors)
{
std::vector<PxRigidActor*> actors(nbActors);
gScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC | PxActorTypeFlag::eRIGID_STATIC, reinterpret_cast<PxActor**>(&actors[0]), nbActors);
Snippets::renderActors(&actors[0], static_cast<PxU32>(actors.size()), true);
}
Snippets::finishRender();
}
void exitCallback(void)
{
delete sCamera;
cleanupPhysics();
}
}
void renderLoop()
{
sCamera = new Snippets::Camera(PxVec3(10.0f, 10.0f, 10.0f), PxVec3(-0.6f,-0.2f,-0.7f));
Snippets::setupDefaultWindow("PhysX Snippet Vehicle4W");
Snippets::setupDefaultRenderState();
glutIdleFunc(idleCallback);
glutDisplayFunc(renderCallback);
glutKeyboardFunc(keyboardCallback);
glutMouseFunc(mouseCallback);
glutMotionFunc(motionCallback);
motionCallback(0,0);
atexit(exitCallback);
initPhysics();
glutMainLoop();
}
#endif

View File

@ -0,0 +1,321 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "SnippetVehicleCreate.h"
#include "SnippetVehicleTireFriction.h"
#include "SnippetVehicleSceneQuery.h"
namespace snippetvehicle
{
using namespace physx;
namespace fourwheel
{
void computeWheelCenterActorOffsets4W(const PxF32 wheelFrontZ, const PxF32 wheelRearZ, const PxVec3& chassisDims, const PxF32 wheelWidth, const PxF32 wheelRadius, const PxU32 numWheels, PxVec3* wheelCentreOffsets)
{
//chassisDims.z is the distance from the rear of the chassis to the front of the chassis.
//The front has z = 0.5*chassisDims.z and the rear has z = -0.5*chassisDims.z.
//Compute a position for the front wheel and the rear wheel along the z-axis.
//Compute the separation between each wheel along the z-axis.
const PxF32 numLeftWheels = numWheels/2.0f;
const PxF32 deltaZ = (wheelFrontZ - wheelRearZ)/(numLeftWheels-1.0f);
//Set the outside of the left and right wheels to be flush with the chassis.
//Set the top of the wheel to be just touching the underside of the chassis.
//Begin by setting the rear-left/rear-right/front-left,front-right wheels.
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + 0*deltaZ*0.5f);
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + 0*deltaZ*0.5f);
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + (numLeftWheels-1)*deltaZ);
wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + (numLeftWheels-1)*deltaZ);
//Set the remaining wheels.
for(PxU32 i = 2, wheelCount = 4; i < numWheels-2; i+=2, wheelCount+=2)
{
wheelCentreOffsets[wheelCount + 0] = PxVec3((-chassisDims.x + wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
wheelCentreOffsets[wheelCount + 1] = PxVec3((+chassisDims.x - wheelWidth)*0.5f, -(chassisDims.y/2 + wheelRadius), wheelRearZ + i*deltaZ*0.5f);
}
}
void setupWheelsSimulationData
(const PxF32 wheelMass, const PxF32 wheelMOI, const PxF32 wheelRadius, const PxF32 wheelWidth,
const PxU32 numWheels, const PxVec3* wheelCenterActorOffsets,
const PxVec3& chassisCMOffset, const PxF32 chassisMass,
PxVehicleWheelsSimData* wheelsSimData)
{
//Set up the wheels.
PxVehicleWheelData wheels[PX_MAX_NB_WHEELS];
{
//Set up the wheel data structures with mass, moi, radius, width.
for(PxU32 i = 0; i < numWheels; i++)
{
wheels[i].mMass = wheelMass;
wheels[i].mMOI = wheelMOI;
wheels[i].mRadius = wheelRadius;
wheels[i].mWidth = wheelWidth;
}
//Enable the handbrake for the rear wheels only.
wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxHandBrakeTorque=4000.0f;
wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxHandBrakeTorque=4000.0f;
//Enable steering for the front wheels only.
wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxSteer=PxPi*0.3333f;
wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxSteer=PxPi*0.3333f;
}
//Set up the tires.
PxVehicleTireData tires[PX_MAX_NB_WHEELS];
{
//Set up the tires.
for(PxU32 i = 0; i < numWheels; i++)
{
tires[i].mType = TIRE_TYPE_NORMAL;
}
}
//Set up the suspensions
PxVehicleSuspensionData suspensions[PX_MAX_NB_WHEELS];
{
//Compute the mass supported by each suspension spring.
PxF32 suspSprungMasses[PX_MAX_NB_WHEELS];
PxVehicleComputeSprungMasses
(numWheels, wheelCenterActorOffsets,
chassisCMOffset, chassisMass, 1, suspSprungMasses);
//Set the suspension data.
for(PxU32 i = 0; i < numWheels; i++)
{
suspensions[i].mMaxCompression = 0.3f;
suspensions[i].mMaxDroop = 0.1f;
suspensions[i].mSpringStrength = 35000.0f;
suspensions[i].mSpringDamperRate = 4500.0f;
suspensions[i].mSprungMass = suspSprungMasses[i];
}
//Set the camber angles.
const PxF32 camberAngleAtRest=0.0;
const PxF32 camberAngleAtMaxDroop=0.01f;
const PxF32 camberAngleAtMaxCompression=-0.01f;
for(PxU32 i = 0; i < numWheels; i+=2)
{
suspensions[i + 0].mCamberAtRest = camberAngleAtRest;
suspensions[i + 1].mCamberAtRest = -camberAngleAtRest;
suspensions[i + 0].mCamberAtMaxDroop = camberAngleAtMaxDroop;
suspensions[i + 1].mCamberAtMaxDroop = -camberAngleAtMaxDroop;
suspensions[i + 0].mCamberAtMaxCompression = camberAngleAtMaxCompression;
suspensions[i + 1].mCamberAtMaxCompression = -camberAngleAtMaxCompression;
}
}
//Set up the wheel geometry.
PxVec3 suspTravelDirections[PX_MAX_NB_WHEELS];
PxVec3 wheelCentreCMOffsets[PX_MAX_NB_WHEELS];
PxVec3 suspForceAppCMOffsets[PX_MAX_NB_WHEELS];
PxVec3 tireForceAppCMOffsets[PX_MAX_NB_WHEELS];
{
//Set the geometry data.
for(PxU32 i = 0; i < numWheels; i++)
{
//Vertical suspension travel.
suspTravelDirections[i] = PxVec3(0,-1,0);
//Wheel center offset is offset from rigid body center of mass.
wheelCentreCMOffsets[i] =
wheelCenterActorOffsets[i] - chassisCMOffset;
//Suspension force application point 0.3 metres below
//rigid body center of mass.
suspForceAppCMOffsets[i] =
PxVec3(wheelCentreCMOffsets[i].x,-0.3f,wheelCentreCMOffsets[i].z);
//Tire force application point 0.3 metres below
//rigid body center of mass.
tireForceAppCMOffsets[i] =
PxVec3(wheelCentreCMOffsets[i].x,-0.3f,wheelCentreCMOffsets[i].z);
}
}
//Set up the filter data of the raycast that will be issued by each suspension.
PxFilterData qryFilterData;
setupNonDrivableSurface(qryFilterData);
//Set the wheel, tire and suspension data.
//Set the geometry data.
//Set the query filter data
for(PxU32 i = 0; i < numWheels; i++)
{
wheelsSimData->setWheelData(i, wheels[i]);
wheelsSimData->setTireData(i, tires[i]);
wheelsSimData->setSuspensionData(i, suspensions[i]);
wheelsSimData->setSuspTravelDirection(i, suspTravelDirections[i]);
wheelsSimData->setWheelCentreOffset(i, wheelCentreCMOffsets[i]);
wheelsSimData->setSuspForceAppPointOffset(i, suspForceAppCMOffsets[i]);
wheelsSimData->setTireForceAppPointOffset(i, tireForceAppCMOffsets[i]);
wheelsSimData->setSceneQueryFilterData(i, qryFilterData);
wheelsSimData->setWheelShapeMapping(i, PxI32(i));
}
//Add a front and rear anti-roll bar
PxVehicleAntiRollBarData barFront;
barFront.mWheel0 = PxVehicleDrive4WWheelOrder::eFRONT_LEFT;
barFront.mWheel1 = PxVehicleDrive4WWheelOrder::eFRONT_RIGHT;
barFront.mStiffness = 10000.0f;
wheelsSimData->addAntiRollBarData(barFront);
PxVehicleAntiRollBarData barRear;
barRear.mWheel0 = PxVehicleDrive4WWheelOrder::eREAR_LEFT;
barRear.mWheel1 = PxVehicleDrive4WWheelOrder::eREAR_RIGHT;
barRear.mStiffness = 10000.0f;
wheelsSimData->addAntiRollBarData(barRear);
}
} //namespace fourwheel
PxVehicleDrive4W* createVehicle4W(const VehicleDesc& vehicle4WDesc, PxPhysics* physics, PxCooking* cooking)
{
const PxVec3 chassisDims = vehicle4WDesc.chassisDims;
const PxF32 wheelWidth = vehicle4WDesc.wheelWidth;
const PxF32 wheelRadius = vehicle4WDesc.wheelRadius;
const PxU32 numWheels = vehicle4WDesc.numWheels;
const PxFilterData& chassisSimFilterData = vehicle4WDesc.chassisSimFilterData;
const PxFilterData& wheelSimFilterData = vehicle4WDesc.wheelSimFilterData;
//Construct a physx actor with shapes for the chassis and wheels.
//Set the rigid body mass, moment of inertia, and center of mass offset.
PxRigidDynamic* veh4WActor = NULL;
{
//Construct a convex mesh for a cylindrical wheel.
PxConvexMesh* wheelMesh = createWheelMesh(wheelWidth, wheelRadius, *physics, *cooking);
//Assume all wheels are identical for simplicity.
PxConvexMesh* wheelConvexMeshes[PX_MAX_NB_WHEELS];
PxMaterial* wheelMaterials[PX_MAX_NB_WHEELS];
//Set the meshes and materials for the driven wheels.
for(PxU32 i = PxVehicleDrive4WWheelOrder::eFRONT_LEFT; i <= PxVehicleDrive4WWheelOrder::eREAR_RIGHT; i++)
{
wheelConvexMeshes[i] = wheelMesh;
wheelMaterials[i] = vehicle4WDesc.wheelMaterial;
}
//Set the meshes and materials for the non-driven wheels
for(PxU32 i = PxVehicleDrive4WWheelOrder::eREAR_RIGHT + 1; i < numWheels; i++)
{
wheelConvexMeshes[i] = wheelMesh;
wheelMaterials[i] = vehicle4WDesc.wheelMaterial;
}
//Chassis just has a single convex shape for simplicity.
PxConvexMesh* chassisConvexMesh = createChassisMesh(chassisDims, *physics, *cooking);
PxConvexMesh* chassisConvexMeshes[1] = {chassisConvexMesh};
PxMaterial* chassisMaterials[1] = {vehicle4WDesc.chassisMaterial};
//Rigid body data.
PxVehicleChassisData rigidBodyData;
rigidBodyData.mMOI = vehicle4WDesc.chassisMOI;
rigidBodyData.mMass = vehicle4WDesc.chassisMass;
rigidBodyData.mCMOffset = vehicle4WDesc.chassisCMOffset;
veh4WActor = createVehicleActor
(rigidBodyData,
wheelMaterials, wheelConvexMeshes, numWheels, wheelSimFilterData,
chassisMaterials, chassisConvexMeshes, 1, chassisSimFilterData,
*physics);
}
//Set up the sim data for the wheels.
PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(numWheels);
{
//Compute the wheel center offsets from the origin.
PxVec3 wheelCenterActorOffsets[PX_MAX_NB_WHEELS];
const PxF32 frontZ = chassisDims.z*0.3f;
const PxF32 rearZ = -chassisDims.z*0.3f;
fourwheel::computeWheelCenterActorOffsets4W(frontZ, rearZ, chassisDims, wheelWidth, wheelRadius, numWheels, wheelCenterActorOffsets);
//Set up the simulation data for all wheels.
fourwheel::setupWheelsSimulationData
(vehicle4WDesc.wheelMass, vehicle4WDesc.wheelMOI, wheelRadius, wheelWidth,
numWheels, wheelCenterActorOffsets,
vehicle4WDesc.chassisCMOffset, vehicle4WDesc.chassisMass,
wheelsSimData);
}
//Set up the sim data for the vehicle drive model.
PxVehicleDriveSimData4W driveSimData;
{
//Diff
PxVehicleDifferential4WData diff;
diff.mType=PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
driveSimData.setDiffData(diff);
//Engine
PxVehicleEngineData engine;
engine.mPeakTorque=500.0f;
engine.mMaxOmega=600.0f;//approx 6000 rpm
driveSimData.setEngineData(engine);
//Gears
PxVehicleGearsData gears;
gears.mSwitchTime=0.5f;
driveSimData.setGearsData(gears);
//Clutch
PxVehicleClutchData clutch;
clutch.mStrength=10.0f;
driveSimData.setClutchData(clutch);
//Ackermann steer accuracy
PxVehicleAckermannGeometryData ackermann;
ackermann.mAccuracy=1.0f;
ackermann.mAxleSeparation=
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).z-
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).z;
ackermann.mFrontWidth=
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_RIGHT).x-
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eFRONT_LEFT).x;
ackermann.mRearWidth=
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_RIGHT).x -
wheelsSimData->getWheelCentreOffset(PxVehicleDrive4WWheelOrder::eREAR_LEFT).x;
driveSimData.setAckermannGeometryData(ackermann);
}
//Create a vehicle from the wheels and drive sim data.
PxVehicleDrive4W* vehDrive4W = PxVehicleDrive4W::allocate(numWheels);
vehDrive4W->setup(physics, veh4WActor, *wheelsSimData, driveSimData, numWheels - 4);
//Configure the userdata
configureUserData(vehDrive4W, vehicle4WDesc.actorUserData, vehicle4WDesc.shapeUserDatas);
//Free the sim data because we don't need that any more.
wheelsSimData->free();
return vehDrive4W;
}
} //namespace snippetvehicle

View File

@ -0,0 +1,122 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef SNIPPET_VEHICLE_CONCURRENCY_H
#define SNIPPET_VEHICLE_CONCURRENCY_H
#include "PxPhysicsAPI.h"
#include <new>
namespace snippetvehicle
{
using namespace physx;
//Data structure for quick setup of wheel query data structures.
class VehicleConcurrency
{
public:
VehicleConcurrency()
: mMaxNumVehicles(0),
mMaxNumWheelsPerVehicle(0),
mVehicleConcurrentUpdates(NULL)
{
}
~VehicleConcurrency()
{
}
static VehicleConcurrency* allocate(const PxU32 maxNumVehicles, const PxU32 maxNumWheelsPerVehicle, PxAllocatorCallback& allocator)
{
const PxU32 byteSize =
sizeof(VehicleConcurrency) +
sizeof(PxVehicleConcurrentUpdateData)*maxNumVehicles +
sizeof(PxVehicleWheelConcurrentUpdateData)*maxNumWheelsPerVehicle*maxNumVehicles;
PxU8* buffer = static_cast<PxU8*>(allocator.allocate(byteSize, NULL, NULL, 0));
VehicleConcurrency* vc = reinterpret_cast<VehicleConcurrency*>(buffer);
new(vc) VehicleConcurrency();
buffer += sizeof(VehicleConcurrency);
vc->mMaxNumVehicles = maxNumVehicles;
vc->mMaxNumWheelsPerVehicle = maxNumWheelsPerVehicle;
vc->mVehicleConcurrentUpdates = reinterpret_cast<PxVehicleConcurrentUpdateData*>(buffer);
buffer += sizeof(PxVehicleConcurrentUpdateData)*maxNumVehicles;
for(PxU32 i=0;i<maxNumVehicles;i++)
{
new(vc->mVehicleConcurrentUpdates + i) PxVehicleConcurrentUpdateData();
vc->mVehicleConcurrentUpdates[i].nbConcurrentWheelUpdates = maxNumWheelsPerVehicle;
vc->mVehicleConcurrentUpdates[i].concurrentWheelUpdates = reinterpret_cast<PxVehicleWheelConcurrentUpdateData*>(buffer);
buffer += sizeof(PxVehicleWheelConcurrentUpdateData)*maxNumWheelsPerVehicle;
for(PxU32 j = 0; j < maxNumWheelsPerVehicle; j++)
{
new(vc->mVehicleConcurrentUpdates[i].concurrentWheelUpdates + j) PxVehicleWheelConcurrentUpdateData();
}
}
return vc;
}
//Free allocated buffer for scene queries of suspension raycasts.
void free(PxAllocatorCallback& allocator)
{
allocator.deallocate(this);
}
//Return the PxVehicleConcurrentUpdate for a vehicle specified by an index.
PxVehicleConcurrentUpdateData* getVehicleConcurrentUpdate(const PxU32 id)
{
return (mVehicleConcurrentUpdates + id);
}
//Return the entire array of PxVehicleConcurrentUpdates
PxVehicleConcurrentUpdateData* getVehicleConcurrentUpdateBuffer()
{
return mVehicleConcurrentUpdates;
}
private:
PxU32 mMaxNumVehicles;
PxU32 mMaxNumWheelsPerVehicle;
PxVehicleConcurrentUpdateData* mVehicleConcurrentUpdates;
};
} // namespace snippetvehicle
#endif //SNIPPET_VEHICLE_CONCURRENCY_H

View File

@ -0,0 +1,339 @@
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include <new>
#include "SnippetVehicleCreate.h"
#include "SnippetVehicleSceneQuery.h"
#include "SnippetVehicleFilterShader.h"
#include "SnippetVehicleTireFriction.h"
#include "PxPhysicsAPI.h"
namespace snippetvehicle
{
using namespace physx;
PxRigidStatic* createDrivablePlane(const PxFilterData& simFilterData, PxMaterial* material, PxPhysics* physics)
{
//Add a plane to the scene.
PxRigidStatic* groundPlane = PxCreatePlane(*physics, PxPlane(0,1,0,0), *material);
//Get the plane shape so we can set query and simulation filter data.
PxShape* shapes[1];
groundPlane->getShapes(shapes, 1);
//Set the query filter data of the ground plane so that the vehicle raycasts can hit the ground.
PxFilterData qryFilterData;
setupDrivableSurface(qryFilterData);
shapes[0]->setQueryFilterData(qryFilterData);
//Set the simulation filter data of the ground plane so that it collides with the chassis of a vehicle but not the wheels.
shapes[0]->setSimulationFilterData(simFilterData);
return groundPlane;
}
static PxConvexMesh* createConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
{
// Create descriptor for convex mesh
PxConvexMeshDesc convexDesc;
convexDesc.points.count = numVerts;
convexDesc.points.stride = sizeof(PxVec3);
convexDesc.points.data = verts;
convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
PxConvexMesh* convexMesh = NULL;
PxDefaultMemoryOutputStream buf;
if(cooking.cookConvexMesh(convexDesc, buf))
{
PxDefaultMemoryInputData id(buf.getData(), buf.getSize());
convexMesh = physics.createConvexMesh(id);
}
return convexMesh;
}
PxConvexMesh* createChassisMesh(const PxVec3 dims, PxPhysics& physics, PxCooking& cooking)
{
const PxF32 x = dims.x*0.5f;
const PxF32 y = dims.y*0.5f;
const PxF32 z = dims.z*0.5f;
PxVec3 verts[8] =
{
PxVec3(x,y,-z),
PxVec3(x,y,z),
PxVec3(x,-y,z),
PxVec3(x,-y,-z),
PxVec3(-x,y,-z),
PxVec3(-x,y,z),
PxVec3(-x,-y,z),
PxVec3(-x,-y,-z)
};
return createConvexMesh(verts,8,physics,cooking);
}
PxConvexMesh* createWheelMesh(const PxF32 width, const PxF32 radius, PxPhysics& physics, PxCooking& cooking)
{
PxVec3 points[2*16];
for(PxU32 i = 0; i < 16; i++)
{
const PxF32 cosTheta = PxCos(i*PxPi*2.0f/16.0f);
const PxF32 sinTheta = PxSin(i*PxPi*2.0f/16.0f);
const PxF32 y = radius*cosTheta;
const PxF32 z = radius*sinTheta;
points[2*i+0] = PxVec3(-width/2.0f, y, z);
points[2*i+1] = PxVec3(+width/2.0f, y, z);
}
return createConvexMesh(points,32,physics,cooking);
}
PxRigidDynamic* createVehicleActor
(const PxVehicleChassisData& chassisData,
PxMaterial** wheelMaterials, PxConvexMesh** wheelConvexMeshes, const PxU32 numWheels, const PxFilterData& wheelSimFilterData,
PxMaterial** chassisMaterials, PxConvexMesh** chassisConvexMeshes, const PxU32 numChassisMeshes, const PxFilterData& chassisSimFilterData,
PxPhysics& physics)
{
//We need a rigid body actor for the vehicle.
//Don't forget to add the actor to the scene after setting up the associated vehicle.
PxRigidDynamic* vehActor = physics.createRigidDynamic(PxTransform(PxIdentity));
//Wheel and chassis query filter data.
//Optional: cars don't drive on other cars.
PxFilterData wheelQryFilterData;
setupNonDrivableSurface(wheelQryFilterData);
PxFilterData chassisQryFilterData;
setupNonDrivableSurface(chassisQryFilterData);
//Add all the wheel shapes to the actor.
for(PxU32 i = 0; i < numWheels; i++)
{
PxConvexMeshGeometry geom(wheelConvexMeshes[i]);
PxShape* wheelShape=PxRigidActorExt::createExclusiveShape(*vehActor, geom, *wheelMaterials[i]);
wheelShape->setQueryFilterData(wheelQryFilterData);
wheelShape->setSimulationFilterData(wheelSimFilterData);
wheelShape->setLocalPose(PxTransform(PxIdentity));
}
//Add the chassis shapes to the actor.
for(PxU32 i = 0; i < numChassisMeshes; i++)
{
PxShape* chassisShape=PxRigidActorExt::createExclusiveShape(*vehActor, PxConvexMeshGeometry(chassisConvexMeshes[i]), *chassisMaterials[i]);
chassisShape->setQueryFilterData(chassisQryFilterData);
chassisShape->setSimulationFilterData(chassisSimFilterData);
chassisShape->setLocalPose(PxTransform(PxIdentity));
}
vehActor->setMass(chassisData.mMass);
vehActor->setMassSpaceInertiaTensor(chassisData.mMOI);
vehActor->setCMassLocalPose(PxTransform(chassisData.mCMOffset,PxQuat(PxIdentity)));
return vehActor;
}
void configureUserData(PxVehicleWheels* vehicle, ActorUserData* actorUserData, ShapeUserData* shapeUserDatas)
{
if(actorUserData)
{
vehicle->getRigidDynamicActor()->userData = actorUserData;
actorUserData->vehicle = vehicle;
}
if(shapeUserDatas)
{
PxShape* shapes[PX_MAX_NB_WHEELS + 1];
vehicle->getRigidDynamicActor()->getShapes(shapes, PX_MAX_NB_WHEELS + 1);
for(PxU32 i = 0; i < vehicle->mWheelsSimData.getNbWheels(); i++)
{
const PxI32 shapeId = vehicle->mWheelsSimData.getWheelShapeMapping(i);
shapes[shapeId]->userData = &shapeUserDatas[i];
shapeUserDatas[i].isWheel = true;
shapeUserDatas[i].wheelId = i;
}
}
}
void customizeVehicleToLengthScale(const PxReal lengthScale, PxRigidDynamic* rigidDynamic, PxVehicleWheelsSimData* wheelsSimData, PxVehicleDriveSimData* driveSimData)
{
//Rigid body center of mass and moment of inertia.
{
PxTransform t = rigidDynamic->getCMassLocalPose();
t.p *= lengthScale;
rigidDynamic->setCMassLocalPose(t);
PxVec3 moi = rigidDynamic->getMassSpaceInertiaTensor();
moi *= (lengthScale*lengthScale);
rigidDynamic->setMassSpaceInertiaTensor(moi);
}
//Wheels, suspensions, wheel centers, tire/susp force application points.
{
for(PxU32 i = 0; i < wheelsSimData->getNbWheels(); i++)
{
PxVehicleWheelData wheelData = wheelsSimData->getWheelData(i);
wheelData.mRadius *= lengthScale;
wheelData.mWidth *= lengthScale;
wheelData.mDampingRate *= lengthScale*lengthScale;
wheelData.mMaxBrakeTorque *= lengthScale*lengthScale;
wheelData.mMaxHandBrakeTorque *= lengthScale*lengthScale;
wheelData.mMOI *= lengthScale*lengthScale;
wheelsSimData->setWheelData(i, wheelData);
PxVehicleSuspensionData suspData = wheelsSimData->getSuspensionData(i);
suspData.mMaxCompression *= lengthScale;
suspData.mMaxDroop *= lengthScale;
wheelsSimData->setSuspensionData(i, suspData);
PxVec3 v = wheelsSimData->getWheelCentreOffset(i);
v *= lengthScale;
wheelsSimData->setWheelCentreOffset(i,v);
v = wheelsSimData->getSuspForceAppPointOffset(i);
v *= lengthScale;
wheelsSimData->setSuspForceAppPointOffset(i,v);
v = wheelsSimData->getTireForceAppPointOffset(i);
v *= lengthScale;
wheelsSimData->setTireForceAppPointOffset(i,v);
}
}
//Slow forward speed correction.
{
wheelsSimData->setSubStepCount(5.0f*lengthScale, 3, 1);
wheelsSimData->setMinLongSlipDenominator(4.0f*lengthScale);
}
//Engine
if(driveSimData)
{
PxVehicleEngineData engineData = driveSimData->getEngineData();
engineData.mMOI *= lengthScale*lengthScale;
engineData.mPeakTorque *= lengthScale*lengthScale;
engineData.mDampingRateFullThrottle *= lengthScale*lengthScale;
engineData.mDampingRateZeroThrottleClutchEngaged *= lengthScale*lengthScale;
engineData.mDampingRateZeroThrottleClutchDisengaged *= lengthScale*lengthScale;
driveSimData->setEngineData(engineData);
}
//Clutch.
if(driveSimData)
{
PxVehicleClutchData clutchData = driveSimData->getClutchData();
clutchData.mStrength *= lengthScale*lengthScale;
driveSimData->setClutchData(clutchData);
}
//Scale the collision meshes too.
{
PxShape* shapes[16];
const PxU32 nbShapes = rigidDynamic->getShapes(shapes, 16);
for(PxU32 i = 0; i < nbShapes; i++)
{
switch(shapes[i]->getGeometryType())
{
case PxGeometryType::eSPHERE:
{
PxSphereGeometry sphere;
shapes[i]->getSphereGeometry(sphere);
sphere.radius *= lengthScale;
shapes[i]->setGeometry(sphere);
}
break;
case PxGeometryType::ePLANE:
PX_ASSERT(false);
break;
case PxGeometryType::eCAPSULE:
{
PxCapsuleGeometry capsule;
shapes[i]->getCapsuleGeometry(capsule);
capsule.radius *= lengthScale;
capsule.halfHeight*= lengthScale;
shapes[i]->setGeometry(capsule);
}
break;
case PxGeometryType::eBOX:
{
PxBoxGeometry box;
shapes[i]->getBoxGeometry(box);
box.halfExtents *= lengthScale;
shapes[i]->setGeometry(box);
}
break;
case PxGeometryType::eCONVEXMESH:
{
PxConvexMeshGeometry convexMesh;
shapes[i]->getConvexMeshGeometry(convexMesh);
convexMesh.scale.scale *= lengthScale;
shapes[i]->setGeometry(convexMesh);
}
break;
case PxGeometryType::eTRIANGLEMESH:
{
PxTriangleMeshGeometry triMesh;
shapes[i]->getTriangleMeshGeometry(triMesh);
triMesh.scale.scale *= lengthScale;
shapes[i]->setGeometry(triMesh);
}
break;
case PxGeometryType::eHEIGHTFIELD:
{
PxHeightFieldGeometry hf;
shapes[i]->getHeightFieldGeometry(hf);
hf.columnScale *= lengthScale;
hf.heightScale *= lengthScale;
hf.rowScale *= lengthScale;
shapes[i]->setGeometry(hf);
}
break;
case PxGeometryType::eINVALID:
case PxGeometryType::eGEOMETRY_COUNT:
break;
}
}
}
}
void customizeVehicleToLengthScale(const PxReal lengthScale, PxRigidDynamic* rigidDynamic, PxVehicleWheelsSimData* wheelsSimData, PxVehicleDriveSimData4W* driveSimData)
{
customizeVehicleToLengthScale(lengthScale, rigidDynamic, wheelsSimData, static_cast<PxVehicleDriveSimData*>(driveSimData));
//Ackermann geometry.
if(driveSimData)
{
PxVehicleAckermannGeometryData ackermannData = driveSimData->getAckermannGeometryData();
ackermannData.mAxleSeparation *= lengthScale;
ackermannData.mFrontWidth *= lengthScale;
ackermannData.mRearWidth *= lengthScale;
driveSimData->setAckermannGeometryData(ackermannData);
}
}
} // namespace snippetvehicle

Some files were not shown because too many files have changed in this diff Show More