283 lines
7.0 KiB
C++
283 lines
7.0 KiB
C++
#include "MPFW_Physics.h"
|
|
#include <algorithm>
|
|
#include <print>
|
|
#include <thread>
|
|
#include <mutex>
|
|
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
|
|
#include "MPFW_Utils.h"
|
|
|
|
|
|
// simple aabb
|
|
bool __collides(MPFW::Physics::Box a, MPFW::Physics::Box b) {
|
|
return
|
|
a.min.x <= b.max.x &&
|
|
a.max.x >= b.min.x &&
|
|
a.min.y <= b.max.y &&
|
|
a.max.y >= b.min.y &&
|
|
a.min.z <= b.max.z &&
|
|
a.max.z >= b.min.z;
|
|
}
|
|
|
|
|
|
MPFW::Physics::Box MPFW::Physics::GenerateBoundingBoxPolygon(Polygon poly)
|
|
{
|
|
Polygon polyCopy = poly;
|
|
std::vector<float> x;
|
|
std::vector<float> y;
|
|
std::vector<float> z;
|
|
|
|
for (int i = 0; i < polyCopy.size(); i++) {
|
|
x.push_back(polyCopy[i].x);
|
|
y.push_back(polyCopy[i].y);
|
|
z.push_back(polyCopy[i].z);
|
|
}
|
|
|
|
std::sort(x.begin(), x.end());
|
|
std::sort(y.begin(), y.end());
|
|
std::sort(z.begin(), z.end());
|
|
|
|
Box retval;
|
|
retval.min.x = x[0];
|
|
retval.min.y = y[0];
|
|
retval.min.z = z[0];
|
|
|
|
retval.max.x = x[x.size()-1];
|
|
retval.max.y = y[y.size()-1];
|
|
retval.max.z = z[z.size()-1];
|
|
return retval;
|
|
}
|
|
|
|
std::mutex collSetMutex;
|
|
|
|
void PolygonCalcThread(MPFW::Physics::CollisionSet* collSet, std::vector<MPFW::Physics::CollisionFace> pStructs, int v) {
|
|
for (int p = 0; p < pStructs.size(); p++) {
|
|
if (collSet->collisionFaces.size() - 1 != p) {
|
|
collSet->collisionFaces = std::vector<MPFW::Physics::CollisionFace>(0);
|
|
p = 0;
|
|
}
|
|
if (__collides(MPFW::Physics::GenerateBoundingBoxPolygon(pStructs[p].polygon), collSet->size)) {
|
|
std::lock_guard<std::mutex> guard(collSetMutex);
|
|
collSet->collisionFaces.push_back(pStructs[p]);
|
|
}
|
|
std::print("v:{},p:{}\n", v, p);
|
|
}
|
|
}
|
|
|
|
MPFW::Physics::CollisionMap MPFW::Physics::GenerateCollisionMap(std::vector<Polygon> polygons, std::vector<Vector3> totalVertices, CollisionMapGenParams cmgp, std::string cacheName)
|
|
{
|
|
|
|
|
|
if (std::filesystem::exists(std::string("data/cache/collisiondata/" + cacheName))) {
|
|
|
|
|
|
std::ifstream fileHandle(std::string("data/cache/collisiondata/" + cacheName), std::ios::binary);
|
|
|
|
|
|
if (fileHandle.good() && fileHandle.is_open()) {
|
|
std::stringstream fileStringStream; fileStringStream << fileHandle.rdbuf();
|
|
std::string file = fileStringStream.str();
|
|
|
|
|
|
if (Utils::Strings::StringIndexToInteger_4b_le(file, 0) == 0x01) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CachedCollisionMap ccm;
|
|
|
|
ccm.cachedCollisionMapVersion = Utils::Strings::StringIndexToInteger_4b_le(file, 0);
|
|
ccm.collisionSetCount = Utils::Strings::StringIndexToInteger_4b_le(file, 4);
|
|
|
|
|
|
|
|
CollisionMap retval;
|
|
|
|
ccm.collisionSets.resize(ccm.collisionSetCount);
|
|
|
|
std::memcpy(
|
|
ccm.collisionSets.data(),
|
|
Utils::Strings::IterativeStringExcerpt(file, 8, ccm.collisionSetCount * sizeof(CachedCollisionSet)).data(),
|
|
ccm.collisionSetCount * sizeof(CachedCollisionSet));
|
|
|
|
for (int i = 0; i < ccm.collisionSets.size(); i++) {
|
|
CollisionSet cs;
|
|
cs.size.max.x = ccm.collisionSets[i].maxx;
|
|
cs.size.max.y = ccm.collisionSets[i].maxy;
|
|
cs.size.max.z = ccm.collisionSets[i].maxz;
|
|
cs.size.min.x = ccm.collisionSets[i].minx;
|
|
cs.size.min.y = ccm.collisionSets[i].miny;
|
|
cs.size.min.z = ccm.collisionSets[i].minz;
|
|
|
|
|
|
|
|
|
|
|
|
// std::string subbuffer =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
retval.collisionSets.push_back(cs);
|
|
|
|
}
|
|
|
|
|
|
return retval;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
std::vector<Polygon> polygonsCopy = polygons;
|
|
std::vector<std::thread> polygonCalculationsThreads;
|
|
std::vector<CollisionFace> pStructs(polygons.size());
|
|
|
|
for (int cFCount = 0; cFCount < polygons.size(); cFCount++) {
|
|
CollisionFace cface;
|
|
cface.polygon = polygonsCopy[cFCount]; // assuming polygonsCopy == polygons, because it should be.
|
|
|
|
|
|
|
|
// calculating normals (if polygon has 3 vertices or more)
|
|
if(cface.polygon.size() >= 3){
|
|
|
|
// according to: https://titan.csit.rmit.edu.au/~e20068/teaching/i3dg&a/2012/normals/normals.xhtml
|
|
|
|
Vector3 a, b;
|
|
|
|
a = Vector3Subtract(cface.polygon[1], cface.polygon[0]);
|
|
|
|
b = Vector3Subtract(cface.polygon[2], cface.polygon[0]);
|
|
cface.normal = Vector3Normalize(Vector3CrossProduct(a,b)); // does that actually work? I can't believe it would
|
|
cface.normalCalculated = true;
|
|
|
|
}
|
|
|
|
|
|
pStructs[cFCount] = cface;
|
|
|
|
}
|
|
|
|
Box mapBoundingBox = GenerateBoundingBoxPolygon(totalVertices);
|
|
|
|
Vector3 sizeOfMap = mapBoundingBox.max - mapBoundingBox.min;
|
|
Vector3 sizeOfVoxel = sizeOfMap / cmgp.voxelLateralCount;
|
|
|
|
CollisionMap retval;
|
|
int vCount = 0;
|
|
for (int z = 0; z < cmgp.voxelLateralCount; z++) {
|
|
for (int y = 0; y < cmgp.voxelLateralCount; y++) {
|
|
for (int x = 0; x < cmgp.voxelLateralCount; x++) {
|
|
CollisionSet cs;
|
|
|
|
cs.size.min =
|
|
{
|
|
mapBoundingBox.min.x + sizeOfVoxel.x * x,
|
|
mapBoundingBox.min.y + sizeOfVoxel.y * y,
|
|
mapBoundingBox.min.z + sizeOfVoxel.z * z
|
|
};
|
|
|
|
cs.size.max =
|
|
{
|
|
mapBoundingBox.min.x + sizeOfVoxel.x * (x + 1),
|
|
mapBoundingBox.min.y + sizeOfVoxel.y * (y + 1),
|
|
mapBoundingBox.min.z + sizeOfVoxel.z * (z + 1)
|
|
};
|
|
cs.collisionFaces = std::vector<CollisionFace>(0);
|
|
retval.collisionSets.push_back(cs);
|
|
// polygonCalculationsThreads.push_back(std::thread(PolygonCalcThread, &retval.collisionSets[vCount], pStructs, vCount));
|
|
|
|
for(int p = 0; p < pStructs.size(); p++){
|
|
if (__collides(MPFW::Physics::GenerateBoundingBoxPolygon(pStructs[p].polygon), retval.collisionSets[vCount].size)) {
|
|
// std::lock_guard<std::mutex> guard(collSetMutex);
|
|
retval.collisionSets[vCount].collisionFaces.push_back(pStructs[p]);
|
|
}
|
|
std::print("v:{},p:{}\n", vCount, p);
|
|
}
|
|
vCount++;
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*for (int i = 0; i < polygonCalculationsThreads.size(); i++) {
|
|
if(polygonCalculationsThreads[i].joinable())polygonCalculationsThreads[i].join();
|
|
}*/
|
|
|
|
/*
|
|
std::ofstream cacheFile(std::string("data/cache/collisiondata/" + cacheName), std::ios::binary);
|
|
|
|
|
|
CachedCollisionMap cache;
|
|
cache.cachedCollisionMapVersion = 0x01;
|
|
cache.collisionSetCount = retval.collisionSets.size();
|
|
cacheFile.write((char*)&cache.cachedCollisionMapVersion, 4);
|
|
cacheFile.write((char*)&cache.collisionSetCount, 4);
|
|
|
|
|
|
int headerSize = retval.collisionSets.size() * 36 + 8;
|
|
|
|
int currentFileSize = 0;
|
|
|
|
|
|
std::string subfile = "";
|
|
|
|
|
|
for (int i = 0; i < retval.collisionSets.size(); i++) {
|
|
|
|
|
|
std::string collsetsubfile = "";
|
|
|
|
for (int j = 0; j < retval.collisionSets[i].collisionFaces.size(); j++) {
|
|
using namespace std::string_literals;
|
|
collsetsubfile += retval.collisionSets[i].collisionFaces[j].
|
|
}
|
|
|
|
|
|
|
|
unsigned long fileOffset = headerSize + currentFileSize;
|
|
unsigned long size = retval.
|
|
|
|
cacheFile.write((char*)& n, 4);
|
|
cacheFile.write((char*)& n, 4);
|
|
int collsize = retval.collisionSets[i].collisionFaces.size();
|
|
cacheFile.write((char*)&collsize, 4);
|
|
cacheFile.write((char*)&retval.collisionSets[i].size.min.x, 4);
|
|
cacheFile.write((char*)&retval.collisionSets[i].size.min.y, 4);
|
|
cacheFile.write((char*)&retval.collisionSets[i].size.min.z, 4);
|
|
cacheFile.write((char*)&retval.collisionSets[i].size.max.x, 4);
|
|
cacheFile.write((char*)&retval.collisionSets[i].size.max.y, 4);
|
|
cacheFile.write((char*)&retval.collisionSets[i].size.max.z, 4);
|
|
|
|
}
|
|
|
|
|
|
cacheFile.close();
|
|
|
|
*/
|
|
return retval;
|
|
|
|
|
|
|
|
}
|