Skip to content

Commit

Permalink
Implemented a basic collision listener class
Browse files Browse the repository at this point in the history
Made sure API import also defines default visibility and added pool setting

Tweaked Jolt build settings and warning options for the thrive lib

Started on a few various files, tweaked some stuff, setup clang tidy rules more sensibly
  • Loading branch information
hhyyrylainen committed Oct 27, 2023
1 parent 324a6fa commit 4edd032
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 14 deletions.
4 changes: 3 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
---
Checks: '*,-llvmlibc-implementation-in-namespace,-llvm-header-guard,-modernize-use-trailing-return-type'
Checks: '-*,boost-*,bugprone-*,cert-*,clang-analyzer-*,concurrency-*,cppcoreguidelines-*,hicpp-*,
llvm-*,-llvm-header-guard,misc-*,-misc-no-recursion,modernize-*,-modernize-use-trailing-return-type,
performance-*,portability-*,readability-*'
ShortStatementLines: 1
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@ project(Thrive)
# If you want to get compile commands run cmake with
# "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"

# Options
option(USE_OBJECT_POOLS
"Use object pools instead of direct memory allocation (can be turned off for memory debugging)"
ON)

option(WARNINGS_AS_ERRORS "When on treat compiler warnings as errors" ON)

# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/CMake")

# static building
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
SET(BUILD_SHARED_LIBS OFF)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(BUILD_SHARED_LIBS OFF)

# Common options
if(CMAKE_BUILD_TYPE STREQUAL "")
Expand Down
32 changes: 25 additions & 7 deletions src/native/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
# Main library of the native side of things (non-Godot using)
add_library(thrive_native SHARED
interop/CInterop.h interop/CInterop.cpp
"${PROJECT_BINARY_DIR}/Include.h" core/ForwardDefinitions.hpp
interop/CInterop.cpp interop/CInterop.h
interop/CStructures.h
physics/PhysicalWorld.hpp physics/PhysicalWorld.cpp
"${PROJECT_BINARY_DIR}/Include.h"
)
physics/PhysicalWorld.cpp physics/PhysicalWorld.hpp
physics/Layers.hpp
core/TaskSystem.cpp core/TaskSystem.hpp
physics/ContactListener.cpp physics/ContactListener.hpp
core/Mutex.hpp)

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_options(thrive_native PRIVATE /W4 /wd4068)

if(WARNINGS_AS_ERRORS)
target_compile_options(thrive_native PRIVATE /WX)
endif()
else()
target_compile_options(thrive_native PRIVATE -Wall -Wextra -Wpedantic -Werror
-Wno-unknown-pragmas)

if(WARNINGS_AS_ERRORS)
target_compile_options(thrive_native PRIVATE -Werror)
endif()
endif()


target_compile_definitions(thrive_native PRIVATE THRIVE_NATIVE_BUILD)

Expand All @@ -16,13 +35,12 @@ target_include_directories(thrive_native PUBLIC ${CMAKE_CURRENT_LIST_DIR})
# target_include_directories(thrive_native PUBLIC "../../third_party/JoltPhysics/")

target_precompile_headers(thrive_native PUBLIC "${PROJECT_BINARY_DIR}/Include.h"
PRIVATE "../../third_party/JoltPhysics/Jolt/Jolt.h")
PRIVATE "../../third_party/JoltPhysics/Jolt/Jolt.h" "core/ForwardDefinitions.hpp")

set_target_properties(thrive_native PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
INTERPROCEDURAL_OPTIMIZATION ON
)
INTERPROCEDURAL_OPTIMIZATION ON)

message(STATUS "TODO: static standard lib for easier distributing")
# # Static standard lib
Expand Down
3 changes: 3 additions & 0 deletions src/native/Include.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
#ifdef WIN32
#define THRIVE_NATIVE_API __declspec(dllimport)
#else
#define THRIVE_NATIVE_API __attribute__((visibility("default")))
#endif // WIN32
#endif // THRIVE_NATIVE_BUILD

#cmakedefine USE_OBJECT_POOLS
13 changes: 13 additions & 0 deletions src/native/core/ForwardDefinitions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

/// \file Forward definitions for various important classes in this library for reducing header include amounts

namespace Thrive
{
class TaskSystem;

namespace Physics
{
class ContactListener;
} // namespace Physics
} // namespace Thrive
14 changes: 14 additions & 0 deletions src/native/core/Mutex.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <mutex>
#include <shared_mutex>

// Jolt says the mutex is not fast for all platforms so here's some flexibility to allow redefining it

namespace Thrive
{
using Mutex = std::mutex;
using SharedMutex = std::shared_mutex;
using Lock = std::lock_guard<Mutex>;
using SharedLock = std::lock_guard<SharedMutex>;
} // namespace Thrive
3 changes: 2 additions & 1 deletion src/native/interop/CInterop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#pragma clang diagnostic push
#pragma ide diagnostic ignored "cppcoreguidelines-pro-type-reinterpret-cast"

// ------------------------------------ //
int32_t CheckAPIVersion()
{
Expand All @@ -21,6 +22,7 @@ void ShutdownThriveLibrary()
{
// TODO: shutdown actions
}

// ------------------------------------ //
PhysicalWorld* CreatePhysicalWorld()
{
Expand All @@ -35,5 +37,4 @@ void DestroyPhysicalWorld(PhysicalWorld* physicalWorld)
delete reinterpret_cast<Thrive::Physics::PhysicalWorld*>(physicalWorld);
}


#pragma clang diagnostic pop
5 changes: 3 additions & 2 deletions src/native/interop/CInterop.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <cstdint>

#include "Include.h"

#include "interop/CStructures.h"

/// \file Defines all of the API methods that can be called from C#
Expand All @@ -13,10 +14,10 @@ extern "C"
/// used
[[maybe_unused]] THRIVE_NATIVE_API int32_t CheckAPIVersion();

/// \summary Prepares the native library for use, must be called first (right after the version check)
/// \brief Prepares the native library for use, must be called first (right after the version check)
[[maybe_unused]] THRIVE_NATIVE_API int32_t InitThriveLibrary();

/// \summary Prepares the native library for shutdown should be called before the process is ended and after all
/// \brief Prepares the native library for shutdown should be called before the process is ended and after all
/// other calls to the library have been performed
[[maybe_unused]] THRIVE_NATIVE_API void ShutdownThriveLibrary();

Expand Down
74 changes: 74 additions & 0 deletions src/native/physics/ContactListener.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// ------------------------------------ //
#include "ContactListener.hpp"

#include <Jolt/Physics/Body/Body.h>
// ------------------------------------ //
using namespace Thrive::Physics;

JPH::ValidateResult ContactListener::OnContactValidate(const JPH::Body& body1, const JPH::Body& body2,
JPH::RVec3Arg baseOffset, const JPH::CollideShapeResult& collisionResult)
{
JPH::ValidateResult result;
if (chainedListener != nullptr)
{
result = chainedListener->OnContactValidate(body1, body2, baseOffset, collisionResult);
}
else
{
result = JPH::ContactListener::OnContactValidate(body1, body2, baseOffset, collisionResult);
}

return result;
}

void ContactListener::OnContactAdded(const JPH::Body& body1, const JPH::Body& body2,
const JPH::ContactManifold& manifold, JPH::ContactSettings& settings)
{
// Note the bodies are sorted (at least the sample Jolt code has asserts to verify it, so we can probably safely
// always assume that) `body1.GetID() < body2.GetID()`

// Add the new collision
{
Lock lock(currentCollisionsMutex);
JPH::SubShapeIDPair key(body1.GetID(), manifold.mSubShapeID1, body2.GetID(), manifold.mSubShapeID2);
currentCollisions[key] = CollisionPair(manifold.mBaseOffset, manifold.mRelativeContactPointsOn1);
}

if (chainedListener != nullptr)
chainedListener->OnContactAdded(body1, body2, manifold, settings);
}

void ContactListener::OnContactPersisted(const JPH::Body& body1, const JPH::Body& body2,
const JPH::ContactManifold& manifold, JPH::ContactSettings& settings)
{
// Update existing collision info
{
Lock lock(currentCollisionsMutex);

JPH::SubShapeIDPair key(body1.GetID(), manifold.mSubShapeID1, body2.GetID(), manifold.mSubShapeID2);

const auto iter = currentCollisions.find(key);
if (iter != currentCollisions.end())
{
iter->second = CollisionPair(manifold.mBaseOffset, manifold.mRelativeContactPointsOn1);
}
}

if (chainedListener != nullptr)
chainedListener->OnContactPersisted(body1, body2, manifold, settings);
}

void ContactListener::OnContactRemoved(const JPH::SubShapeIDPair& subShapePair)
{
// Remove the contact
{
Lock lock(currentCollisionsMutex);

const auto iter = currentCollisions.find(subShapePair);
if (iter != currentCollisions.end())
currentCollisions.erase(iter);
}

if (chainedListener != nullptr)
chainedListener->OnContactRemoved(subShapePair);
}
40 changes: 40 additions & 0 deletions src/native/physics/ContactListener.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <Jolt/Physics/Collision/ContactListener.h>

#include "core/Mutex.hpp"

namespace Thrive::Physics
{
/// \brief Contact listener implementation
class ContactListener : public JPH::ContactListener
{
using CollisionPair = std::pair<JPH::RVec3, JPH::ContactPoints>;

public:
JPH::ValidateResult OnContactValidate(const JPH::Body& body1, const JPH::Body& body2, JPH::RVec3Arg baseOffset,
const JPH::CollideShapeResult& collisionResult) override;

void OnContactAdded(const JPH::Body& body1, const JPH::Body& body2, const JPH::ContactManifold& manifold,
JPH::ContactSettings& settings) override;

void OnContactPersisted(const JPH::Body& body1, const JPH::Body& body2, const JPH::ContactManifold& manifold,
JPH::ContactSettings& settings) override;

void OnContactRemoved(const JPH::SubShapeIDPair& subShapePair) override;

inline void SetNextListener(JPH::ContactListener* listener)
{
chainedListener = listener;
}

private:
Mutex currentCollisionsMutex;

// TODO: JPH seems to use a custom allocator here so we might need to do so as well (for performance)
std::unordered_map<JPH::SubShapeIDPair, CollisionPair> currentCollisions;

JPH::ContactListener* chainedListener = nullptr;
};

} // namespace Thrive::Physics
9 changes: 8 additions & 1 deletion third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# Native third party module references
message(STATUS "TODO: do these native third party modules")

# JoltPhysics

# Might as well get used to double precision impact now as we'll want that eventually anyway
set(DOUBLE_PRECISION ON)

# TODO: do we need to turn this off (requiring too new AMD CPUs)?
set(USE_AVX2 ON)

# This is way too unsupported to enable in a general build
set(USE_AVX512 OFF)

add_subdirectory(JoltPhysics/Build)

0 comments on commit 4edd032

Please sign in to comment.