I'm in the process of adapting some code from the following page: https://github.com/thefryscorer/GodotPaintDemo/blob/master/world.gd (Special thanks to thefryscorer for sharing their code, and to TwistedTwigleg for showing me this repo!)

The following lines are where I discovered a peculiar behavior:

	var alpha = factor_alpha/det
	var beta = factor_beta/det
	var gamma = 1.0 - alpha - beta
	return Vector3(alpha, beta, gamma)

When the return Vector3(alpha, beta, gamma) line is commented out, the code executes without issue. I can even print out factor_alpha, factor_beta, gamma, and det and see that they are all floats not equal to zero.

However, when I allow the return Vector3(alpha, beta, gamma) line to execute, it causes the game to stop with a "Error: Division by zero in operator /" error, and points to the line where alpha was set. (If I use constants instead of vars in the line for alpha, beta becomes the problem instead)

I tried static typing to make sure GDScript knows that the variables are floats, but this did not help.

What's going on? Does returning a Vector3 somehow change how GDScript interprets the previous variables?

I'm not certain of this, but it is possible that if in that return statement is the only time you're calling alpha, beta, and gamma and you comment it out, so you're effectively never calling them, that those variables are just skipped as they aren't technically being used. I would suggest setting a breakpoint right at the alpha line and stepping through the code to see exactly what line the error happens at. Just commenting out lines can help you find the general area of an error, but in my experience the best way to find the exact line of an error is with breakpoints.

I commented out several lines and tried several things before realizing the it was the Vector3 line that was causing the issue. (I'm not sure if it actually is, all I know is that the error only happens if I allow it to run)

Putting a breakpoint on line 1 revealed the following values: det = -0.117 factor_alpha = -0.009 factor_beta = 0.66 alpha = -0.009

So the error itself is still confusing. None of these values are 0. They are close to zero, however, so maybe it's a floating point precision issue?

I actually never thought to use a breakpoint, so thank you for that suggestion!

Edit: Here's the entire method:


func barycentric(P, A, B, C):
	var det = matrix3x3_determinant(A, B, C)
	var factor_alpha = matrix3x3_determinant(P, B, C)
	var factor_beta = matrix3x3_determinant(P, C, A)
	var alpha = factor_alpha / det
	var beta = factor_beta / det
	var gamma = 1.0 - alpha - beta
	return Vector3(alpha, beta, gamma)

Using a breakpoint, I can see that somehow the Y value of P, A, B and C are all getting set to zero, which is what's causing the divide by zero error. That only happens when the Vector3 line is in? Again, I'm just so confused as to how constructing a new Vector3 is affecting old variables that were already set

My hunch is that it is not the function itself that is crashing, but rather somewhere in the code it is being called and that is where the divide by zero error is occurring. If you comment out line 8 and add print (Vector3(alpha, beta, gamma)) do you still get the same issue? That might help narrow down if the return itself is causing the issue, or the construction of a new Vector3 is causing the issue.

@TwistedTwigleg said: If you comment out line 8 and add print (Vector3(alpha, beta, gamma)) do you still get the same issue? That might help narrow down if the return itself is causing the issue, or the construction of a new Vector3 is causing the issue.

So it seems its the return that's creating the issue, because I've tried printing Vector3(alpha, beta, gamma) and it prints without issue... I'm not sure why the return would affect things

Edit: I should also add that this method is the only instance of division in the entire code

@Azedaxen said:

@TwistedTwigleg said: If you comment out line 8 and add print (Vector3(alpha, beta, gamma)) do you still get the same issue? That might help narrow down if the return itself is causing the issue, or the construction of a new Vector3 is causing the issue.

So it seems its the return that's creating the issue, because I've tried printing Vector3(alpha, beta, gamma) and it prints without issue... I'm not sure why the return would affect things

Edit: I should also add that this method is the only instance of division in the entire code

It sounds the code that uses the barycentric function is the problem then. Since printing the vector is not the issue, it means the return is the issue and therefore code using the function is the issue rather than the function itself. I'd look and see where the function is used, and then see if there is anywhere that looks like it might use division or uses a function like cross on the results of the vector returned by the function. Hopefully the code is only used a few places, which will make debugging easier. If it is used heavily in the code base, it could be difficult to narrow down which function call is causing the issue.

Edit: Looking at the code linked in the OP, it looks like it is only used in the is_point_in_triangle function. I'm not sure why that would be causing the issue though...

So earlier I found out that the Y values of P, A, B, C were all getting set to zero, (and thus causing the matrix determinants to be 0, which became the divisor that causes the error) but only when trying to return a Vector3. Stranger yet, returning a Vector3 constant, such as Vector3.ZERO, does not cause the same issue.

As a temporary solution, I've made it so that the barycentric function adds Vector3.UP * 0.00001 to P, A, B and C, and the rest of the code works as expected. (Albeit with a bug that is most likely unrelated to this)

I'm still going to keep looking into what's causing this, because this is so far the most mysterious thing I've ever encountered with GDScript.

3 years later