godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.88k stars 20.15k forks source link

A question about Camera's method "unproject_position" #61079

Open bengliezina opened 2 years ago

bengliezina commented 2 years ago

Godot version

v3.4.stable.mono.win64

System information

Windows 10

Issue description

For some reason,I need the detailed process of the method "unproject_position",so I find out and copy the code from C++ source code to my C# project.Then I got a question in the function Vector3 XformInv(Vector3 p_vector, Transform t): in the source code,the function is

_FORCE_INLINE_ Vector3 Transform::xform_inv(const Vector3 &p_vector) const {
    Vector3 v = p_vector - origin;

return Vector3(
            (basis.elements[0][0] * v.x) + (basis.elements[1][0] * v.y) + (basis.elements[2][0] * v.z),
            (basis.elements[0][1] * v.x) + (basis.elements[1][1] * v.y) + (basis.elements[2][1] * v.z),
            (basis.elements[0][2] * v.x) + (basis.elements[1][2] * v.y) + (basis.elements[2][2] * v.z));
}

in my project,I have to use the code

public Vector3 XformInv(Vector3 p_vector, Transform t)
    {

        Vector3 v = p_vector - t.origin;

        return new Vector3(
                 (t.basis[0][0] * v.x) + (t.basis[0][1] * v.y) + (t.basis[0][2] * v.z),
                (t.basis[1][0] * v.x) + (t.basis[1][1] * v.y) + (t.basis[1][2] * v.z),
                (t.basis[2][0] * v.x) + (t.basis[2][1] * v.y) + (t.basis[2][2] * v.z));
    }

to get the same result as the method unproject_position of Godot C#

So the question is when I tried to override the method "unproject_position" of Godot C# by copying the detailed code from C++ source code,I have to inverse the basis matrix in camera's transform to get the right result.Is this a bug or I did something wrong?

Hope someone can help me,thx.

Steps to reproduce

Here's the demo I use

Minimal reproduction project

demo1.zip

Zireael07 commented 2 years ago

IIRC the basis in c++ is stored differently to the bindings but I can't find the correct issue where this was discussed

bengliezina commented 2 years ago

@Zireael07 thx for your reply. But I check out the source code about how the basis constructed,and is here(from basis.h)

_FORCE_INLINE_ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
        elements[0][0] = xx;
        elements[0][1] = xy;
        elements[0][2] = xz;
        elements[1][0] = yx;
        elements[1][1] = yy;
        elements[1][2] = yz;
        elements[2][0] = zx;
        elements[2][1] = zy;
        elements[2][2] = zz;
    }

Then I check my C#'s transform,and I got image So the basis of C#'s transform,its basis[0] means the column of xAxis,does that mean that the C#'s basis.x.y is the same meaning as the C++'s xy?If the answer is yes,it may mean that the stored between C++ and C# is not different?

bengliezina commented 2 years ago

looks like the function _FORCE_INLINE_ void set(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) is different with _FORCE_INLINE_ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz):

_FORCE_INLINE_ void set(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) {
        set_axis(0, p_x);
        set_axis(1, p_y);
        set_axis(2, p_z);
    }
_FORCE_INLINE_ void set_axis(int p_axis, const Vector3 &p_value) {
        // get actual basis axis (elements is transposed for performance)
        elements[0][p_axis] = p_value.x;
        elements[1][p_axis] = p_value.y;
        elements[2][p_axis] = p_value.z;
    }

if use this set function to construct basis,,it will be:

                elements[0][0] = xx;
        elements[1][0] = xy;
        elements[2][0] = xz;
        elements[0][1] = yx;
        elements[1][1] = yy;
        elements[2][1] = yz;
        elements[0][2] = zx;
        elements[1][2] = zy;
        elements[2][2] = zz;

Now I'm a little confused about the C++'s basis contruct