我正在尝试遵循 C++ 和 OpenGL 中的 Sebastian Lague 的流体模拟 视频。我现在正在计算
propertyGradient
值(时间戳是 14:15)。
我将尝试在下面提供所有相关的代码。
float CalculatePropertyGradient(Vector2 samplePoint, const std::vector<Vector2>& positions, const std::vector<float>& particleProperties, float smoothingRadius, float mass)
{
float propertyGradient = 0.0f;
DensityCalculator calculator(positions, smoothingRadius);
for (int i = 0; i < positions.size(); i++)
{
float dst = (positions[i] - samplePoint).magnitude();
Vector2 dir = (positions[i] - samplePoint) / dst;
float slope = SmoothingKernelDerivative(dst, smoothingRadius);
float density = calculator.CalculateDensity(positions[i]);
Vector2 scaledDir = dir * particleProperties[i];
propertyGradient += -(scaledDir) * slope * mass / density;
}
return propertyGradient;
}
但是我在该行中遇到语法错误:
propertyGradient += -(scaledDir) * slope * mass / density;
在 += 运算符下,我的 Vector2 类不支持涉及 float 和 vector2 的此操作
我的向量2类:
class Vector2 {
public:
float X;
float Y;
Vector2(float x, float y) : X(x), Y(y) {}
float magnitude() const {
return sqrt(X * X + Y * Y);
}
Vector2 operator-(const Vector2& other) const {
return Vector2(X - other.X, Y - other.Y);
}
Vector2 operator/(const float& scalar) const {
return Vector2(X / scalar, Y / scalar);
}
Vector2 operator*(const float& right) const {
return Vector2(X * right, Y * right);
}
Vector2 operator-(const float& scalar) const {
return Vector2(X - scalar, Y - scalar);
}
Vector2 operator*(const Vector2& other) const {
return Vector2(X * other.X, Y * other.Y);
}
Vector2 Zero() {
return Vector2(0.0f, 0.0f);
}
Vector2 operator-() const {
return Vector2(-X, -Y);
}
Vector2& operator+=(const float& scalar) {
X += scalar;
Y += scalar;
return *this;
}
};
我的密度等级:
class DensityCalculator {
private:
std::vector<float> densities;
std::vector<Vector2> positions;
float smoothingRadius;
public:
DensityCalculator(const std::vector<Vector2>& positions, float smoothingRadius)
: positions(positions), smoothingRadius(smoothingRadius) {}
void PreCalculateDensities() {
densities.clear();
for (const auto& position : positions) {
densities.push_back(CalculateDensity(position));
}
}
float CalculateDensity(Vector2 position) const {
float density = 0;
const float mass = 1;
for (const auto& p : positions) {
float dst = (p - position).magnitude();
if (dst <= smoothingRadius) {
float influence = SmoothingKernel(smoothingRadius, dst);
density += mass * influence;
}
}
return density;
}
float GetDensity(int index) const {
return densities[index];
}
};
SmoothingKernel 和 SmoothingKernel 导数函数:
float SmoothingKernel(float radius, float dst)
{
if (dst < radius)
{
float volume = M_PI * pow(radius, 8) / 4;
float v = std::max(radius * radius - dst * dst, 0.0f);
return ((v * v * v) / volume);
}
else
{
return 0;
}
}
static float SmoothingKernelDerivative(float dst, float radius)
{
if (dst >= radius)
return 0;
float f = radius * radius - dst * dst;
float scale = -24 / (M_PI * pow(radius, 8));
return scale * dst * f * f;
}
这是我的主函数中的函数调用:
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j) {
float x = distX(mt);
float y = distY(mt);
balls.emplace_back(x, y, 0.0, 0.0, radius);
// Calculate the value of ExampleFunction at the particle's location and store it in particleProperties
float propertyValue = ExampleFunction(Vector2(x, y));
particleProperties.push_back(propertyValue);
}
}
ExampleFunction 就是
static float ExampleFunction(Vector2(pos))
{
return cos(pos.Y - 3 + sin(pos.X));
}
我已经尝试过将vector2的运算符+=声明为作用于const对象,如另一篇文章所建议的,但我收到一个错误,X和Y必须是可修改的值。
您没有接线员
float += Vector2
在
Vector2
类中实现以下内容
friend constexpr Vector2 operator += (float lhs, const Vector2& rhs) { /*...*/ }
或室外
constexpr Vector2 operator += (float lhs, const Vector2& rhs) { /*...*/ }