mpfw/mpfw/MPFW_Physics.cpp

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;
}