Dreamcast fixes, also that experimental float16/quantized uint16_t triangle mesh support

This commit is contained in:
ecker 2023-10-26 22:29:00 -05:00
parent b289487583
commit f047019d55
11 changed files with 180 additions and 21 deletions

View File

@ -1,6 +1,15 @@
# Minimum cmake version required
cmake_minimum_required(VERSION 3.8)
set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)
if(DEFINED ENV{KOS_CPPFLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os ${KOS_CPPFLAGS} ${KOS_INC_PATHS} ${KOS_LIB_PATHS} -DRP3D_NO_EXCEPTIONS -std=c++17 -w -fno-exceptions")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2b")
endif()
# Project configuration
project(ReactPhysics3D VERSION 0.9.0 LANGUAGES CXX)
@ -24,6 +33,8 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
# Enable testing
enable_testing()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os ${KOS_CPPFLAGS} ${KOS_INC_PATHS} ${KOS_LIB_PATHS} -std=c++17")
# Options
option(RP3D_COMPILE_TESTBED "Select this if you want to build the testbed application with demos" OFF)
option(RP3D_COMPILE_TESTS "Select this if you want to build the unit tests" OFF)

View File

@ -49,10 +49,30 @@ class TriangleVertexArray {
public:
/// Data type for the vertices in the array
enum class VertexDataType {VERTEX_FLOAT_TYPE, VERTEX_DOUBLE_TYPE};
enum class VertexDataType {
VERTEX_SHORT_TYPE,
VERTEX_FLOAT_TYPE,
VERTEX_DOUBLE_TYPE,
#if __STDCPP_FLOAT16_T__
VERTEX_FLOAT16_TYPE,
#endif
#if __STDCPP_BFLOAT16_T__
VERTEX_BFLOAT16_TYPE,
#endif
};
/// Data type for the vertex normals in the array
enum class NormalDataType {NORMAL_FLOAT_TYPE, NORMAL_DOUBLE_TYPE};
enum class NormalDataType {
NORMAL_SHORT_TYPE,
NORMAL_FLOAT_TYPE,
NORMAL_DOUBLE_TYPE,
#if __STDCPP_FLOAT16_T__
NORMAL_FLOAT16_TYPE,
#endif
#if __STDCPP_BFLOAT16_T__
NORMAL_BFLOAT16_TYPE,
#endif
};
/// Data type for the indices in the array
enum class IndexDataType {INDEX_INTEGER_TYPE, INDEX_SHORT_TYPE};

View File

@ -245,7 +245,7 @@ class DynamicAABBTree {
size_t endIndex, Array<Pair<int32, int32>>& outOverlappingNodes) const;
/// Report all shapes overlapping with the AABB given in parameter.
void reportAllShapesOverlappingWithAABB(const AABB& aabb, Array<int>& overlappingNodes) const;
void reportAllShapesOverlappingWithAABB(const AABB& aabb, Array<int32>& overlappingNodes) const;
/// Ray casting method
void raycast(const Ray& ray, DynamicAABBTreeRaycastCallback& callback) const;

View File

@ -29,6 +29,7 @@
// Libraries
#include <limits>
#include <cfloat>
#include <cstdint>
#include <utility>
#include <sstream>
#include <string>
@ -55,14 +56,21 @@
#define RP3D_FORCE_INLINE inline
#endif
#if defined(RP3D_NO_EXCEPTIONS)
#define THROW(...) abort()
#else
#define THROW(...) throw(__VA_ARGS__)
#endif
/// Namespace reactphysics3d
namespace reactphysics3d {
// ------------------- Type definitions ------------------- //
using uint = unsigned int;
using uchar = unsigned char;
using ushort = unsigned short;
using uint = uint32_t;
using uchar = uint8_t;
using ushort = uint16_t;
using luint = long unsigned int;
using int8 = std::int8_t;

View File

@ -383,7 +383,7 @@ class Map {
}
else {
assert(false);
throw std::runtime_error("The key and value pair already exists in the map");
THROW(std::runtime_error("The key and value pair already exists in the map"));
}
}
}
@ -569,7 +569,7 @@ class Map {
if (entry == INVALID_INDEX) {
assert(false);
throw std::runtime_error("No item with given key has been found in the map");
THROW(std::runtime_error("No item with given key has been found in the map"));
}
return mEntries[entry].second;
@ -582,7 +582,7 @@ class Map {
if (entry == INVALID_INDEX) {
assert(false);
throw std::runtime_error("No item with given key has been found in the map");
THROW(std::runtime_error("No item with given key has been found in the map"));
}
return mEntries[entry].second;

View File

@ -51,10 +51,10 @@ class AABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
public:
Array<int>& mOverlappingNodes;
Array<int32>& mOverlappingNodes;
// Constructor
AABBOverlapCallback(Array<int>& overlappingNodes) : mOverlappingNodes(overlappingNodes) {
AABBOverlapCallback(Array<int32>& overlappingNodes) : mOverlappingNodes(overlappingNodes) {
}
@ -126,7 +126,7 @@ class BroadPhaseSystem {
/// Set with the broad-phase IDs of all collision shapes that have moved (or have been
/// created) during the last simulation step. Those are the shapes that need to be tested
/// for overlapping in the next simulation step.
Set<int> mMovedShapes;
Set<int32> mMovedShapes;
/// Reference to the collision detection object
CollisionDetectionSystem& mCollisionDetection;

View File

@ -361,7 +361,7 @@ class DefaultLogger : public Logger {
mFileStream(filePath, std::ios::binary) {
if(!mFileStream.is_open()) {
throw(std::runtime_error("ReactPhysics3D Logger: Unable to open an output stream to file " + mFilePath));
THROW(std::runtime_error("ReactPhysics3D Logger: Unable to open an output stream to file " + mFilePath));
}
// Write the header
@ -385,7 +385,7 @@ class DefaultLogger : public Logger {
virtual void write(const time_t& time, const std::string& physicsWorldName, const std::string& message, Level level, Category category,
const char* filename, int lineNumber) override {
if (static_cast<int>(level) <= static_cast<int>(maxLevelFlag)) {
if (static_cast<int32>(level) <= static_cast<int32>(maxLevelFlag)) {
mFileStream << formatter->format(time, physicsWorldName, message, level, category, filename, lineNumber) << std::endl;
}
}
@ -425,7 +425,7 @@ class DefaultLogger : public Logger {
virtual void write(const time_t& time, const std::string& physicsWorldName, const std::string& message, Level level, Category category,
const char* filename, int lineNumber) override {
if (static_cast<int>(level) <= static_cast<int>(maxLevelFlag)) {
if (static_cast<int32>(level) <= static_cast<int32>(maxLevelFlag)) {
mOutputStream << formatter->format(time, physicsWorldName, message, level, category, filename, lineNumber) << std::endl << std::flush;
}
}

View File

@ -28,6 +28,38 @@
#include <reactphysics3d/mathematics/Vector3.h>
#include <cassert>
#if __STDCPP_BFLOAT16_T__ || __STDCPP_FLOAT16_T__
#include <stdfloat>
#endif
namespace {
uint16_t quantize( float v ) {
union { float f; uint32_t ui; } u = {v};
uint32_t ui = u.ui;
int s = (ui >> 16) & 0x8000;
int em = ui & 0x7fffffff;
int h = (em - (112 << 23) + (1 << 12)) >> 13;
h = (em < (113 << 23)) ? 0 : h;
h = (em >= (143 << 23)) ? 0x7c00 : h;
h = (em > (255 << 23)) ? 0x7e00 : h;
return (uint16_t)(s | h);
}
float dequantize( uint16_t h ) {
uint32_t s = unsigned(h & 0x8000) << 16;
int em = h & 0x7fff;
int r = (em + (112 << 10)) << 13;
r = (em < (1 << 10)) ? 0 : r;
r += (em >= (31 << 10)) ? (112 << 23) : 0;
union { float f; uint32_t ui; } u;
u.ui = s | r;
return u.f;
}
}
using namespace reactphysics3d;
// Constructor without vertices normals
@ -253,6 +285,28 @@ void TriangleVertexArray::getTriangleVertices(uint32 triangleIndex, Vector3* out
outTriangleVertices[k][1] = decimal(vertices[1]);
outTriangleVertices[k][2] = decimal(vertices[2]);
}
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_SHORT_TYPE) {
const uint16_t* vertices = static_cast<const uint16_t*>(vertexPointer);
outTriangleVertices[k][0] = decimal(::dequantize(vertices[0]));
outTriangleVertices[k][1] = decimal(::dequantize(vertices[1]));
outTriangleVertices[k][2] = decimal(::dequantize(vertices[2]));
}
#if __STDCPP_FLOAT16_T__
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_FLOAT16_TYPE) {
const std::float16_t* vertices = static_cast<const std::float16_t*>(vertexPointer);
outTriangleVertices[k][0] = decimal(vertices[0]);
outTriangleVertices[k][1] = decimal(vertices[1]);
outTriangleVertices[k][2] = decimal(vertices[2]);
}
#endif
#if __STDCPP_BFLOAT16_T__
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_BFLOAT16_TYPE) {
const std::bfloat16_t* vertices = static_cast<const std::bfloat16_t*>(vertexPointer);
outTriangleVertices[k][0] = decimal(vertices[0]);
outTriangleVertices[k][1] = decimal(vertices[1]);
outTriangleVertices[k][2] = decimal(vertices[2]);
}
#endif
else {
assert(false);
}
@ -291,6 +345,28 @@ void TriangleVertexArray::getTriangleVerticesNormals(uint32 triangleIndex, Vecto
outTriangleVerticesNormals[k][1] = decimal(normal[1]);
outTriangleVerticesNormals[k][2] = decimal(normal[2]);
}
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_SHORT_TYPE) {
const uint16_t* normal = static_cast<const uint16_t*>(vertexNormalPointer);
outTriangleVerticesNormals[k][0] = decimal(dequantize(normal[0]));
outTriangleVerticesNormals[k][1] = decimal(dequantize(normal[1]));
outTriangleVerticesNormals[k][2] = decimal(dequantize(normal[2]));
}
#if __STDCPP_FLOAT16_T__
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_FLOAT16_TYPE) {
const std::float16_t* normal = static_cast<const std::float16_t*>(vertexNormalPointer);
outTriangleVerticesNormals[k][0] = decimal(normal[0]);
outTriangleVerticesNormals[k][1] = decimal(normal[1]);
outTriangleVerticesNormals[k][2] = decimal(normal[2]);
}
#endif
#if __STDCPP_BFLOAT16_T__
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_BFLOAT16_TYPE) {
const std::bfloat16_t* normal = static_cast<const std::bfloat16_t*>(vertexNormalPointer);
outTriangleVerticesNormals[k][0] = decimal(normal[0]);
outTriangleVerticesNormals[k][1] = decimal(normal[1]);
outTriangleVerticesNormals[k][2] = decimal(normal[2]);
}
#endif
else {
assert(false);
}
@ -322,6 +398,28 @@ void TriangleVertexArray::getVertex(uint32 vertexIndex, Vector3* outVertex) {
(*outVertex)[1] = decimal(vertices[1]);
(*outVertex)[2] = decimal(vertices[2]);
}
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_SHORT_TYPE) {
const uint16_t* vertices = static_cast<const uint16_t*>(vertexPointer);
(*outVertex)[0] = decimal(dequantize(vertices[0]));
(*outVertex)[1] = decimal(dequantize(vertices[1]));
(*outVertex)[2] = decimal(dequantize(vertices[2]));
}
#if __STDCPP_FLOAT16_T__
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_FLOAT16_TYPE) {
const std::float16_t* vertices = static_cast<const std::float16_t*>(vertexPointer);
(*outVertex)[0] = decimal(vertices[0]);
(*outVertex)[1] = decimal(vertices[1]);
(*outVertex)[2] = decimal(vertices[2]);
}
#endif
#if __STDCPP_BFLOAT16_T__
else if (mVertexDataType == TriangleVertexArray::VertexDataType::VERTEX_BFLOAT16_TYPE) {
const std::bfloat16_t* vertices = static_cast<const std::bfloat16_t*>(vertexPointer);
(*outVertex)[0] = decimal(vertices[0]);
(*outVertex)[1] = decimal(vertices[1]);
(*outVertex)[2] = decimal(vertices[2]);
}
#endif
else {
assert(false);
}
@ -352,6 +450,28 @@ void TriangleVertexArray::getNormal(uint32 vertexIndex, Vector3* outNormal) {
(*outNormal)[1] = decimal(normal[1]);
(*outNormal)[2] = decimal(normal[2]);
}
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_SHORT_TYPE) {
const uint16_t* normal = static_cast<const uint16_t*>(vertexNormalPointer);
(*outNormal)[0] = decimal(dequantize(normal[0]));
(*outNormal)[1] = decimal(dequantize(normal[1]));
(*outNormal)[2] = decimal(dequantize(normal[2]));
}
#if __STDCPP_FLOAT16_T__
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_FLOAT16_TYPE) {
const std::float16_t* normal = static_cast<const std::float16_t*>(vertexNormalPointer);
(*outNormal)[0] = decimal(normal[0]);
(*outNormal)[1] = decimal(normal[1]);
(*outNormal)[2] = decimal(normal[2]);
}
#endif
#if __STDCPP_BFLOAT16_T__
else if (mVertexNormaldDataType == TriangleVertexArray::NormalDataType::NORMAL_BFLOAT16_TYPE) {
const std::bfloat16_t* normal = static_cast<const std::bfloat16_t*>(vertexNormalPointer);
(*outNormal)[0] = decimal(normal[0]);
(*outNormal)[1] = decimal(normal[1]);
(*outNormal)[2] = decimal(normal[2]);
}
#endif
else {
assert(false);
}

View File

@ -131,7 +131,7 @@ int32 DynamicAABBTree::allocateNode() {
}
// Release a node
void DynamicAABBTree::releaseNode(int nodeID) {
void DynamicAABBTree::releaseNode(int32 nodeID) {
assert(mNbNodes > 0);
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
@ -217,7 +217,7 @@ bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, bool force
// Insert a leaf node in the tree. The process of inserting a new leaf node
// in the dynamic tree is described in the book "Introduction to Game Physics
// with Box2D" by Ian Parberry.
void DynamicAABBTree::insertLeafNode(int nodeID) {
void DynamicAABBTree::insertLeafNode(int32 nodeID) {
// If the tree is empty
if (mRootNodeID == TreeNode::NULL_TREE_NODE) {
@ -347,7 +347,7 @@ void DynamicAABBTree::insertLeafNode(int nodeID) {
}
// Remove a leaf node from the tree
void DynamicAABBTree::removeLeafNode(int nodeID) {
void DynamicAABBTree::removeLeafNode(int32 nodeID) {
assert(nodeID >= 0 && nodeID < mNbAllocatedNodes);
assert(mNodes[nodeID].isLeaf());

View File

@ -139,7 +139,7 @@ void ConcaveMeshShape::computeOverlappingTriangles(const AABB& localAABB, Array<
aabb.applyScale(Vector3(decimal(1.0) / mScale.x, decimal(1.0) / mScale.y, decimal(1.0) / mScale.z));
// Compute the nodes of the internal AABB tree that are overlapping with the AABB
Array<int> overlappingNodes(allocator, 64);
Array<int32> overlappingNodes(allocator, 64);
mDynamicAABBTree.reportAllShapesOverlappingWithAABB(aabb, overlappingNodes);
const uint32 nbOverlappingNodes = static_cast<uint32>(overlappingNodes.size());
@ -230,7 +230,7 @@ decimal ConcaveMeshRaycastCallback::raycastBroadPhaseShape(int32 nodeId, const R
// Raycast all collision shapes that have been collected
void ConcaveMeshRaycastCallback::raycastTriangles() {
Array<int>::Iterator it;
Array<int32>::Iterator it;
decimal smallestHitFraction = mRay.maxFraction;
for (it = mHitAABBNodes.begin(); it != mHitAABBNodes.end(); ++it) {

View File

@ -214,7 +214,7 @@ void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, Arr
RP3D_PROFILE("BroadPhaseSystem::computeOverlappingPairs()", mProfiler);
// Get the array of the colliders that have moved or have been created in the last frame
Array<int> shapesToTest = mMovedShapes.toArray(memoryManager.getHeapAllocator());
Array<int32> shapesToTest = mMovedShapes.toArray(memoryManager.getHeapAllocator());
// Ask the dynamic AABB tree to report all collision shapes that overlap with the shapes to test
mDynamicAABBTree.reportAllShapesOverlappingWithShapes(shapesToTest, 0, static_cast<uint32>(shapesToTest.size()), overlappingNodes);