I'm trying to follow Sebastian Lague's Fluid simulation video in c++ and OpenGL. I'm at the point where we calculate a propertyGradient value (timestamp is 14:15).
I'll try to provide all the code that is relevant further down below.
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;
}
But I'm getting a syntax error in the line:
propertyGradient += -(scaledDir) * slope * mass / density;
under += operator that my Vector2 class doesn't support this operation involving float and vector2
My vector2 class:
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;
}
};
My density class:
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 and SmoothingKernelDerivative functions:
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;
}
Here's the function call in my main function:
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);
}
}
Where ExampleFunction is just
static float ExampleFunction(Vector2(pos))
{
return cos(pos.Y - 3 + sin(pos.X));
}
I've tried declaring the operator += of vector2 as acting on a const object as suggested by another post but i get an error that X and Y must be a modifiable value.
The problem is that currently the overloaded
operator+=(const float&)that you've provided takes the right hand operand which is afloatinstead ofVector2.Now, the expression
scaledDir * massis of typeVector2which means that you're trying to useoperator+=with right hand operand of typeVector2. But since you haven't provided any suchopertor+=that takes right hand operand of typeVector2, you get the mentioned error.To solve this, just provide an overload that takes an operand of type
Vector2. One way of doing this is as shown below:Working demo