Improve physical geometry, fluid solvers, audio, and profiling

This commit is contained in:
max
2026-10-30 18:57:56 +01:00
parent bf8621ad39
commit eb2b6366c2
130 changed files with 14649 additions and 862 deletions

View File

@@ -7,8 +7,7 @@
#include <utility>
namespace fluidsim::port::desktop {
struct PipeAnchor {float distance;Vec3 position;};
// Knots are distances along the simulated pipe, in metres. Display positions
// define its schematic route; changing them never changes fluid cell lengths.
// Piecewise straight centerline; knot distances are measured from its geometry.
class PipePath {
public:
explicit PipePath(std::vector<PipeAnchor> anchors):anchors_(std::move(anchors)) {
@@ -24,10 +23,8 @@ public:
auto it=std::upper_bound(anchors_.begin(),anchors_.end(),distance,[](float s,const PipeAnchor& a){return s<a.distance;});
std::size_t i=std::clamp<std::size_t>(it-anchors_.begin(),1,anchors_.size()-1)-1;
const auto& a=anchors_[i];const auto& b=anchors_[i+1];
const float span=b.distance-a.distance,t=(distance-a.distance)/span,t2=t*t,t3=t2*t;
const auto ma=tangent_at(i),mb=tangent_at(i+1);
auto coordinate=[&](float pa,float pb,float ta,float tb){return (2*t3-3*t2+1)*pa+(t3-2*t2+t)*span*ta+(-2*t3+3*t2)*pb+(t3-t2)*span*tb;};
return {coordinate(a.position.x,b.position.x,ma.x,mb.x),coordinate(a.position.y,b.position.y,ma.y,mb.y),coordinate(a.position.z,b.position.z,ma.z,mb.z)};
const float t=(distance-a.distance)/(b.distance-a.distance);
return {std::lerp(a.position.x,b.position.x,t),std::lerp(a.position.y,b.position.y,t),std::lerp(a.position.z,b.position.z,t)};
}
Vec3 tangent(float distance) const {
const float epsilon=anchors_.back().distance*.0001f;
@@ -35,12 +32,21 @@ public:
const float x=b.x-a.x,y=b.y-a.y,z=b.z-a.z,n=std::sqrt(x*x+y*y+z*z);
return n>1e-8f?Vec3{x/n,y/n,z/n}:Vec3{1,0,0};
}
private:
Vec3 tangent_at(std::size_t i) const {
const auto& a=anchors_[i?i-1:0];const auto& b=anchors_[std::min(i+1,anchors_.size()-1)];
const float d=b.distance-a.distance;
return {(b.position.x-a.position.x)/d,(b.position.y-a.position.y)/d,(b.position.z-a.position.z)/d};
Vec3 miter_offset(float distance,Vec3 radial) const {
const auto unit=[](Vec3 v){const float n=std::sqrt(v.x*v.x+v.y*v.y+v.z*v.z);return Vec3{v.x/n,v.y/n,v.z/n};};
for(std::size_t i=1;i+1<anchors_.size();++i)if(std::abs(distance-anchors_[i].distance)<1e-6f) {
const auto a=anchors_[i-1].position,b=anchors_[i].position,c=anchors_[i+1].position;
const auto u=unit({b.x-a.x,b.y-a.y,b.z-a.z}),v=unit({c.x-b.x,c.y-b.y,c.z-b.z});
const float cosine=std::clamp(u.x*v.x+u.y*v.y+u.z*v.z,-1.f,1.f);
if(cosine>.99999f)return radial;
const auto bend=unit({u.x-v.x,u.y-v.y,u.z-v.z});
const float scale=std::min(3.f,1/std::sqrt(std::max(.0001f,(1+cosine)*.5f)));
const float extension=(radial.x*bend.x+radial.y*bend.y+radial.z*bend.z)*(scale-1);
return {radial.x+bend.x*extension,radial.y+bend.y*extension,radial.z+bend.z*extension};
}
return radial;
}
private:
std::vector<PipeAnchor> anchors_;
};
}