Changing Method Parameter to ByRef correctly transmits value?

Here is a weird logical error that I would like help to understand. I pass a value into the parameter (p1) of a method and the double value changes from a -5 to a +5.

The coordinate structure is shown below

Structure Coordinate
  x as double
  y as double
  z as double
End Structure

Here is the call to the method

If RayPlane(0, 0, 1, RayStart.x, RayStart.y, RayStart.z, 0, 0, -1, p1, p2, p3, p4) Then

The value of p1.z changes from -5 to +5 at the start of the RayPlane method when I stopped it in the debugger. Here is the RayPlane method with the p1 parameter highlighted.

Public Function RayPlane(nx as Double, ny as Double, nz as Double, xs as Double, ys as Double, zs as Double, xd as Double, yd as Double, zd as Double, **p1 as Coordinate**, p2 as Coordinate, p3 as Coordinate, p4 as Coordinate) As Boolean
  //Determine if the ray has 
  Dim a as Double =xd*nx+yd*ny+zd*nz
  If (a=0) then
    Return False
  End If
  
  Dim t as Double =((p1.x*nx+p1.y*ny+p1.z*nz-nx*xs-ny*ys-nz*zs)/a)
  If (t<0) then
    Return False
  End If
  
  Dim cp as Coordinate
  cp.x = xs+t*xd
  cp.y = ys+t*yd
  cp.z = zs+t*zd
  
  If ((abs(TriangleArea(p1,p3,p4)-TriangleArea(p1,p4,cp)-trianglearea(p1,p3,cp)-trianglearea(p3,p4,cp))<0.000001) or (abs(trianglearea(p1,p2,p3)-trianglearea(p1,p2,cp)-trianglearea(p2,p3,cp)-trianglearea(p1,p3,cp))<0.000001)) Then
    Return True //Yes it intersects
  Else
    Return False  //No intersect
  End If
End Function

I don’t know why, and adding the ByRef prefix in front of the p1 parameter prevents the sign reversal (this is how I believe it should work?):

Public Function RayPlane(nx as Double, ny as Double, nz as Double, xs as Double, ys as Double, zs as Double, xd as Double, yd as Double, zd as Double, **ByRef p1 as Coordinate**, p2 as Coordinate, p3 as Coordinate, p4 as Coordinate) As Boolean
  //Determine if the ray has 
  Dim a as Double =xd*nx+yd*ny+zd*nz
  If (a=0) then
    Return False
  End If
  
  Dim t as Double =((p1.x*nx+p1.y*ny+p1.z*nz-nx*xs-ny*ys-nz*zs)/a)
  If (t<0) then
    Return False
  End If
  
  Dim cp as Coordinate
  cp.x = xs+t*xd
  cp.y = ys+t*yd
  cp.z = zs+t*zd
  
  If ((abs(TriangleArea(p1,p3,p4)-TriangleArea(p1,p4,cp)-trianglearea(p1,p3,cp)-trianglearea(p3,p4,cp))<0.000001) or (abs(trianglearea(p1,p2,p3)-trianglearea(p1,p2,cp)-trianglearea(p2,p3,cp)-trianglearea(p1,p3,cp))<0.000001)) Then
    Return True //Yes it intersects
  Else
    Return False  //No intersect
  End If
End Function

Maybe I am tired, and could someone help me understand why adding ByRef to a parameter allows a double value to be sent to the method with the correct number sign, and why removing ByRef does not?

Thank you!

Edit: added clarification
Windows 11
Xojo 2022 r3.1

Rather than putting your code in a quote block you should use the </> button. If formats the code nicely.

I can’t see why ByRef would make a difference, aren’t structures passed by reference anyway?

What happens if you use a Class, rather than a Structure.

Thanks Ian,

I just edited the above code to include your suggestion.

What seems to be really weird is that the other parameters (p2, p3, and p4) that have the same structure, all pass the correct sign for their structure. Is there maybe a limit to the number of parameters I can use in Xojo? Just thinking-out-loud.

I could try using a class instead. I guess there are a large number of issues with Xojo and structures. I had to make many workarounds with C++ and Declares in Xojo, and this is the first time I have seen this issue with a Xojo-made structure, that’s all. :slight_smile:

I’ve just tried you code out on Mac (M1) and if I’m understanding the issue correctly, it seems to work OK.

You are sending a negative value for p1.x (or .y or .z) and it is becoming positive inside the RayPlane function? The values I pass in maintain their sign.

My calling code:

Var RayStart As Coordinate
Var p1 As Coordinate
Var p2 As Coordinate
Var p3 As Coordinate
Var p4 As Coordinate
RayStart.x = 0
RayStart.y = 0
RayStart.z = 0
p1.x = -10
p1.y = 10
p1.z = 10
If RayPlane(0, 0, 1, RayStart.x, RayStart.y, RayStart.z, 0, 0, -1, p1, p2, p3, p4) Then
End If

Thanks for testing it on a Mac,

This works on Xojo API 1, but reverses the sign on API 2 on windows. To be more specific, this was was code from 2018 that works properly.

Sounds like a bug. Should be fairly simple to create a trivial demo to attach to a bug report.

I’m not sure how API1 / API2 come in to a simple function call? What would the difference look like?

could you replace this 3 parameters normal,start and direction as Coordinate?
you have 3 instead of 9 values.

No. It’s a quirk of structures that they are copied, not referenced, so this code will create two independent structures:

var s1 as MyStructure
var s2 as MyStructure = s1 // Two copies

If you pass it into a function, you are passing a copy unless you use ByRef.

1 Like

I can’t imagine a bug in copying a structure that would invert or drop the sign! It seems like an odd issue. It certainly doesn’t happen on macOS.

Agreed.

I will answer your questions when I am at my development computer later tonight :slight_smile:

Don’t forget to file the issues found. https://xojo.com/issues

It has been insane how things that we all take for granted forever suddenly get broken in Xojo.

For example:

Var cur As Currency = -0.09

cur = cur.ToString.Val * 100 + 1

// Correct: -8 (e.g Xojo 2021r3.1)
// Broken:   1 (e.g Xojo 2022r3.1)

break

Here is a link to a youtube video that I made showing the issue when running on Windows 11, Xojo 2022 r3.1

YouTube Video of Structure Parameter with ByRef

Any other thoughts?

Sure, I could make a workaround to change the number of values. My curiosity would like to understand what is happening with this. Thanks for the suggestion :slight_smile:

I have written a few plugins for 64-bit Windows 11 to maximize the OpenGL speed and quality of graphics. I couldn’t seem to make it work in a simple example. You have a good idea about building an example though.

Can you replicate the bug in a small sample?

Like keeping the structure and 2 fake methods, one calling by value and another byref, calling both, and showing that byval messes the value, and byref shows what you expect (messagebox in both), and share the sample in an Issue Report?

I made my own.

Will report it for you. Done. https://tracker.xojo.com/xojoinc/xojo/-/issues/70682

1 Like

Confirming again, that this works correctly on macOS, no errors. Would appear to be Windows only +/- Linux.

1 Like

As I was attempting to make an example program to recreate the error, the example program then crashed and I created this issue:

https://tracker.xojo.com/xojoinc/xojo/-/issues/70697

Seems like you could put your IDE into some unstable state. I couldn’t crash mine with your example. No plugins here.