Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into python-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
mtheall committed May 16, 2024
2 parents f5eff70 + 25b27d7 commit 6f09d44
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,21 @@ void _UpdateCellsStatic(btRSBroadphase* _this, btRSBroadphaseProxy* proxy) {
for (int i = iMin; i <= iMax; i++) {
for (int j = jMin; j <= jMax; j++) {
for (int k = kMin; k <= kMax; k++) {
auto& cell = _this->GetCell(i, j, k);

#if 0 // TODO: This check misses certain cells for some reason
std::vector<btRSBroadphase::Cell*> cells = {};
for (int i1 = -1; i1 <= 1; i1++) {
for (int j1 = -1; j1 <= 1; j1++) {
for (int k1 = -1; k1 <= 1; k1++) {
int ci = i + i1;
int cj = j + j1;
int ck = k + k1;
if (ci < 0 || cj < 0 || ck < 0)
continue;
if (ci >= _this->cellsX || cj >= _this->cellsY || ck >= _this->cellsZ)
continue;
cells.push_back(&_this->GetCell(ci, cj, ck));
}
}
}

if (isTriMesh) {
auto triMeshShape = (btTriangleMeshShape*)colObj->m_collisionShape;
Expand All @@ -148,12 +160,21 @@ void _UpdateCellsStatic(btRSBroadphase* _this, btRSBroadphaseProxy* proxy) {
}
}
}
#endif

if (ADD) {
cell.staticHandles.push_back(proxy);
} else {
cell.RemoveStatic(proxy);
for (auto cell : cells) {
if (ADD) {
bool alreadyExists = false;
for (auto staticHandle : cell->staticHandles) {
if (staticHandle == proxy) {
alreadyExists = true;
break;
}
}
if (!alreadyExists)
cell->staticHandles.push_back(proxy);
} else {
cell->RemoveStatic(proxy);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void btStaticPlaneShape::getAabb(const btTransform& t, btVector3& aabbMin, btVec
aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));

constexpr float PLANE_CONSTANT_OFFSET = 0.01f;
constexpr float PLANE_CONSTANT_OFFSET = 0.2f;

if (m_isSingleAxis) {
aabbMin[m_singleAxisIdx] = t.getOrigin()[m_singleAxisIdx] + (m_planeConstant - PLANE_CONSTANT_OFFSET);
Expand Down
7 changes: 3 additions & 4 deletions src/CollisionMeshFile/CollisionMeshFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@

RS_NS_START

void CollisionMeshFile::ReadFromFile(std::string filePath) {
constexpr char ERROR_PREFIX_STR[] = " > CollisionMeshFile::ReadFromFile(): ";

DataStreamIn in = DataStreamIn(filePath, false);
void CollisionMeshFile::ReadFromStream(DataStreamIn& in, std::string filePath) {
constexpr char ERROR_PREFIX_STR[] = " > CollisionMeshFile::ReadFromStream(): ";

// If you have more verts or tris then this, I have no idea what you are doing, godspeed
constexpr int MAX_VERT_OR_TRI_COUNT = 1000 * 1000;

// Read triangle/vertex counts
Expand Down
4 changes: 3 additions & 1 deletion src/CollisionMeshFile/CollisionMeshFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "../Framework.h"
#include "../BulletLink.h"

#include "../DataStream/DataStreamIn.h"

#define COLLISION_MESH_BASE_PATH "./collision_meshes/"
#define COLLISION_MESH_FILE_EXTENSION ".cmf"

Expand Down Expand Up @@ -30,7 +32,7 @@ struct CollisionMeshFile {

uint32_t hash;

void ReadFromFile(std::string filePath);
void ReadFromStream(DataStreamIn& in, std::string filePath = "<NO FILE PATH>");
btTriangleMesh* MakeBulletMesh();
void UpdateHash();
};
Expand Down
112 changes: 73 additions & 39 deletions src/RocketSim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,42 @@ static SuspensionCollisionGrid

void RocketSim::Init(std::filesystem::path collisionMeshesFolder) {

std::map<GameMode, std::vector<FileData>> meshFileMap = {};

for (int i = 0; i < 2; i++) { // Load collision meshes for soccar and hoops
GameMode gameMode = (i > 0) ? GameMode::HOOPS : GameMode::SOCCAR;
auto& meshes = GetArenaCollisionShapes(gameMode);

std::filesystem::path basePath = collisionMeshesFolder;
std::filesystem::path soccarMeshesFolder = basePath / GAMEMODE_STRS[(int)gameMode];

if (!std::filesystem::exists(soccarMeshesFolder))
continue;

MeshHashSet targetHashes = MeshHashSet(gameMode);

// Load collision meshes
auto dirItr = std::filesystem::directory_iterator(soccarMeshesFolder);
for (auto& entry : dirItr) {
auto entryPath = entry.path();
if (entryPath.has_extension() && entryPath.extension() == COLLISION_MESH_FILE_EXTENSION) {
DataStreamIn streamIn = DataStreamIn(entryPath, false);
meshFileMap[gameMode].push_back(streamIn.data);
}
}
}

RocketSim::InitFromMem(meshFileMap);

_collisionMeshesFolder = collisionMeshesFolder;
}

void RocketSim::InitFromMem(const std::map<GameMode, std::vector<FileData>>& meshFilesMap) {

constexpr char MSG_PREFIX[] = "RocketSim::Init(): ";

_collisionMeshesFolder = "<MESH FILES LOADED FROM MEMORY>";

_beginInitMutex.lock();
{
if (stage != RocketSimStage::UNINITIALIZED) {
Expand All @@ -81,56 +115,56 @@ void RocketSim::Init(std::filesystem::path collisionMeshesFolder) {

RS_LOG("Initializing RocketSim version " RS_VERSION ", created by ZealanL...");

_collisionMeshesFolder = collisionMeshesFolder;

stage = RocketSimStage::INITIALIZING;

uint64_t startMS = RS_CUR_MS();

for (int i = 0; i < 2; i++) { // Load collision meshes for soccar and hoops
GameMode gameMode = (i > 0) ? GameMode::HOOPS : GameMode::SOCCAR;
auto& meshes = GetArenaCollisionShapes(gameMode);

std::filesystem::path basePath = collisionMeshesFolder;
std::filesystem::path soccarMeshesFolder = basePath / GAMEMODE_STRS[(int)gameMode];
for (auto& mapPair : meshFilesMap) { // Load collision meshes for soccar and hoops
GameMode gameMode = mapPair.first;
auto& meshFiles = mapPair.second;

RS_LOG("Loading arena meshes from " << soccarMeshesFolder << "...");
RS_LOG("Loading arena meshes for " << GAMEMODE_STRS[(int)gameMode] << "...");

if (!std::filesystem::exists(soccarMeshesFolder)) {
RS_LOG("No arena meshes for " << GAMEMODE_STRS[(int)gameMode] << ", skipping...");
if (meshFiles.empty()) {
RS_LOG(" > No meshes, skipping");
continue;
}

auto& meshes = GetArenaCollisionShapes(gameMode);

MeshHashSet targetHashes = MeshHashSet(gameMode);

// Load collision meshes
auto dirItr = std::filesystem::directory_iterator(soccarMeshesFolder);
for (auto& entry : dirItr) {
auto entryPath = entry.path();
if (entryPath.has_extension() && entryPath.extension() == COLLISION_MESH_FILE_EXTENSION) {
CollisionMeshFile meshFile = {};
meshFile.ReadFromFile(entryPath.string());
int& hashCount = targetHashes[meshFile.hash];

if (hashCount > 0) {
RS_WARN(MSG_PREFIX << "Collision mesh " << entryPath << " is a duplicate (0x" << std::hex << meshFile.hash << "), " <<
"already loaded a mesh with the same hash."
);
} else if (targetHashes.hashes.count(meshFile.hash) == 0) {
RS_WARN(MSG_PREFIX <<
"Collision mesh " << entryPath << " does not match any known soccar collision file (0x" << std::hex << meshFile.hash << "), " <<
"make sure they were dumped from a normal soccar arena."
)
}
hashCount++;

btTriangleMesh* triMesh = meshFile.MakeBulletMesh();

auto bvtMesh = new btBvhTriangleMeshShape(triMesh, true);
btTriangleInfoMap* infoMap = new btTriangleInfoMap();
btGenerateInternalEdgeInfo(bvtMesh, infoMap);
bvtMesh->setTriangleInfoMap(infoMap);
meshes.push_back(bvtMesh);
int idx = 0;
for (auto& entry : meshFiles) {
DataStreamIn dataStream = {};
dataStream.data = entry;
CollisionMeshFile meshFile = {};
meshFile.ReadFromStream(dataStream);
int& hashCount = targetHashes[meshFile.hash];

if (hashCount > 0) {
RS_WARN(MSG_PREFIX << "Collision mesh [" << idx << "] is a duplicate (0x" << std::hex << meshFile.hash << "), " <<
"already loaded a mesh with the same hash."
);
} else if (targetHashes.hashes.count(meshFile.hash) == 0) {
RS_WARN(MSG_PREFIX <<
"Collision mesh [" << idx << "] does not match any known " << GAMEMODE_STRS[(int)gameMode] << " collision mesh (0x" << std::hex << meshFile.hash << "), " <<
"make sure they were dumped from a normal " << GAMEMODE_STRS[(int)gameMode] << " arena."
)
}
hashCount++;

btTriangleMesh* triMesh = meshFile.MakeBulletMesh();

auto bvtMesh = new btBvhTriangleMeshShape(triMesh, true);
btTriangleInfoMap* infoMap = new btTriangleInfoMap();
btGenerateInternalEdgeInfo(bvtMesh, infoMap);
bvtMesh->setTriangleInfoMap(infoMap);
meshes.push_back(bvtMesh);

idx++;
}
}

Expand All @@ -151,8 +185,8 @@ void RocketSim::Init(std::filesystem::path collisionMeshesFolder) {
auto& grid = GetDefaultSuspColGrid(gameMode, j);
grid.Allocate();
grid.SetupWorldCollision(meshes);
}
}
}
}
}
}
#endif
Expand Down
9 changes: 9 additions & 0 deletions src/RocketSim.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,19 @@ namespace RocketSim {
INITIALIZED
};

typedef std::vector<byte> FileData;

extern std::filesystem::path _collisionMeshesFolder;
extern std::mutex _beginInitMutex;


void Init(std::filesystem::path collisionMeshesFolder);

// Instead of loading a collision meshes folder, you can pass in the meshes in this memory-only format
// The map sorts mesh files to their respective game modes, where each game mode has a list of mesh files
// The mesh files themselves are just byte arrays
void InitFromMem(const std::map<GameMode, std::vector<FileData>>& meshFilesMap);

void AssertInitialized(const char* errorMsgPrefix);

RocketSimStage GetStage();
Expand Down
1 change: 1 addition & 0 deletions src/Sim/Car/Car.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct CarState : public PhysState {
// Not serialized
uint64_t updateCounter = 0;

// True if 3 or more wheels have contact
bool isOnGround = true;

// Whether each of the 4 wheels have contact
Expand Down

0 comments on commit 6f09d44

Please sign in to comment.