1

I was trying to write a program that can calculate barycentric coordinates, here is the code:

#include <iostream>

class Vector3 {
    public:
    float x = 0, y = 0, z = 0;
    Vector3() = default;
    Vector3(float x, float y, float z) : x(x), y(y), z(z) { }
};

class Triangle {
    public:
    Vector3 &v1,&v2,&v3;
    Triangle(Vector3 v1, Vector3 v2, Vector3 v3) : v1(v1), v2(v2), v3(v3) { }

    Vector3 to_barycentric(const Vector3& point) const {
        const float
            x1 = v1.x, x2 = v2.x, x3 = v3.x,
            y1 = v1.y, y2 = v2.y, y3 = v3.y;
        float
            xp = point.x, yp = point.y,
            detT = (x1 - x3) * (y2 - y3) - (y1 - y3) * (x2 - x3),
            u1 = ((y2 - y3) * (xp - x3) + (x3 - x2) * (yp - y3)) / detT,
            u2 = ((y3 - y1) * (xp - x3) + (x1 - x3) * (yp - y3)) / detT;
        return {u1, u2, 1 - u1 - u2};   //THIS LINE IS CAUSING THE ISSUE
    }

    Vector3 to_cartesian(const Vector3& b) const {
        return Vector3(
            b.x * v1.x + b.y * v2.x + b.z * v3.x,
            b.x * v1.y + b.y * v2.y + b.z * v3.y,
            0
        );
    }
};

std::ostream& operator << (std::ostream& o, const Vector3& v) {
    o << '(' << v.x << ',' << v.y << ',' << v.z << ')';
    return o; 
}

int main(void) {
    Triangle t(
        Vector3(0,0,0),
        Vector3(1,0,0),
        Vector3(0,1,0)
    );
    Vector3 c0, b, c1;
    c0 = Vector3(0.3, 0.3, 0);
    b = t.to_barycentric(c0);
    c1 = t.to_cartesian(b);
    std::cout << c0 << std::endl << b << std::endl << c1 << std::endl;
}

The problem is that - as far as I can see with my debugging tools - when the tagged line (the one with the comment) is executed through the to_barycentric method in main, the member v3 of the Triangle object t is changed even though there are no changes being made on it. I tried to rewrite the code using pointers instead of references for the Vector3 members of the Triangle and it seemed to work, but I really cannot wrap my head around it not working with references. Are there any explanations as to what is going on? Thank you!

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Kitsuinox
  • 11
  • 1
  • ot: your way of declaring several variables and intendation is rather uncommon and difficult to read. – 463035818_is_not_an_ai Feb 10 '23 at 10:16
  • 3
    The `Triangle` constructor arguments are *local* variables. As soon as the constructor function ends, so does the life-time of the argument variables, and the references you save will become dangling and invalid. Why are you using references? – Some programmer dude Feb 10 '23 at 10:16
  • You're initializing all three `v` member references with automatic variables that will expire as soon as the `Triangle` constructor exits. Referring to them after is a recipe for *undefined behavior*. Use values for your `v` member vars; not references. `Vector3 &v1,&v2,&v3;` ==> `Vector3 v1, v2, v3;` – WhozCraig Feb 10 '23 at 10:16
  • 1
    +1 for using a debugger, though before debugging pay attention to errors **and** warnings https://godbolt.org/z/KqGdxv4YE – 463035818_is_not_an_ai Feb 10 '23 at 10:17
  • btw you shouldnt be sorry for posting a [mcve] :) – 463035818_is_not_an_ai Feb 10 '23 at 10:19
  • Oh dangling references... Sorry for my oversight, haha. I am on VSCode right now as I had some issues with my usual CLion and didn't see the warnings, thank you very much, everyone. – Kitsuinox Feb 10 '23 at 10:29

0 Answers0