This commit is contained in:
Gaël committed 2026-10-19 20:59:15 +02:00
commit 87bff164f1
416 files changed
+279512

No files matched your search

+61
View File
@@ -0,0 +1,61 @@
#include "rigid_fracture.h"
#include <algorithm>
#include <limits>
#include <stdexcept>
namespace noita::cpu {
FracturePartition partition_fracture(int width, int height,
std::vector<CellIdentity> cells, bool old_body_static, int static_selector) {
if(width<0 || height<0 || std::size_t(width)*std::size_t(height)!=cells.size() ||
cells.size()>std::size_t(std::numeric_limits<int>::max()))
throw std::invalid_argument("invalid fracture matrix");
FracturePartition result;
std::size_t largest=0;
for(int seed=0; seed<int(cells.size()); ++seed) {
if(!cells[seed]) continue;
const auto identity=cells[seed];
FractureIsland island; island.min_y=island.max_y=seed/width;
island.indices.push_back(seed); cells[seed]=0;
for(std::size_t next=0; next<island.indices.size(); ++next) {
const int index=island.indices[next], x=index%width, y=index/width;
island.min_y=std::min(island.min_y,y); island.max_y=std::max(island.max_y,y);
// Assembly enqueue order: left, up, right, down; marked at enqueue time.
const int adjacent[]={x>0?index-1:-1, y>0?index-width:-1,
x+1<width?index+1:-1, y+1<height?index+width:-1};
for(int candidate:adjacent) if(candidate>=0 && cells[candidate]) {
cells[candidate]=0; island.indices.push_back(candidate);
}
}
if(island.indices.size()<2) result.singletons.push_back(identity);
else {
if(result.bodies.empty() || island.indices.size()>result.bodies[largest].indices.size())
largest=result.bodies.size();
result.bodies.push_back(std::move(island));
}
}
if(result.bodies.empty()) return result;
std::swap(result.bodies[0],result.bodies[largest]);
if(old_body_static && (static_selector==3 || static_selector==5)) {
std::size_t retained=0;
for(std::size_t i=1; i<result.bodies.size(); ++i)
if((static_selector==3 && result.bodies[i].max_y>result.bodies[retained].max_y) ||
(static_selector==5 && result.bodies[i].min_y<result.bodies[retained].min_y))
retained=i;
std::swap(result.bodies[0],result.bodies[retained]);
}
return result;
}
bool restore_fracture_joint(bool enabled, bool disabled, CellIdentity a, CellIdentity b,
const std::vector<CellIdentity>& removed) {
return enabled && !disabled && (a || b) &&
std::find(removed.begin(),removed.end(),a)==removed.end() &&
std::find(removed.begin(),removed.end(),b)==removed.end();
}
Vec2d fracture_local_anchor(Vec2d p, Vec2d origin, Vec2d scale, Vec2d body,
double c, double s) {
if(scale.x==0 || scale.y==0) throw std::invalid_argument("zero body coordinate scale");
const double dx=(p.x-origin.x)/scale.x-body.x;
const double dy=(p.y-origin.y)/scale.y-body.y;
return {c*dx+s*dy,c*dy-s*dx};
}
}