Repository: godot
Issue: Curve3D: `sample_baked_with_rotation` returns `Basis()` for a curve section's middle point when its control1==end and control2==begin
Labels: bug,topic:3d

### Tested versions

- Reproducible in: v4.0.4.stable.official [fc0b241c9], v4.1.1.stable.official [bd6af8e0e], v4.2.1.stable.official [b09f793f5], v4.3.dev3.official [36e943b6b]

### System information

Godot v4.2.1.stable - Ubuntu 23.10 23.10 - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 (nvidia; 545.29.06) - AMD Ryzen 7 5800X3D 8-Core Processor (16 Threads)

### Issue description

When using `sample_baked_with_rotation` with an offset that corresponds to the middle point of a curve section where `out` of the first point equals the second point and `in` of the second point equals the first point, it triggers an error [here](https://github.com/godotengine/godot/blob/bb6b06c81343073f10cbbd2af515cf0dac1e6549/core/math/basis.cpp#L1044) with `The target vector can't be zero.` and returns a transform with the default `Basis()`.

With an offset that corresponds to the next baked point right after the middle point, the error occurs as well, but the transform's basis is correct. 

#### Details

The call to `looking_at` happens [here](https://github.com/godotengine/godot/blob/fb10e67fefb85af3b8f5abd30db561588d8456c6/scene/resources/curve.cpp#L1826) in `_compose_posture`, which is called twice by `_sample_posture` [here](https://github.com/godotengine/godot/blob/fb10e67fefb85af3b8f5abd30db561588d8456c6/scene/resources/curve.cpp#L1840), which, in turn, is called by `sample_baked_with_rotation` [here](https://github.com/godotengine/godot/blob/fb10e67fefb85af3b8f5abd30db561588d8456c6/scene/resources/curve.cpp#L1926).

The problem: The baked forward vector that `_compose_posture` gets from `baked_forward_vector_cache` for the affected middle points is zero. That's because, in the call-chain [_bake](https://github.com/godotengine/godot/blob/15a03ed98e63590c85dac62405d785e1b7ca7fed/scene/resources/curve.cpp#L1545) -> [p_begin.bezier_derivative(...](https://github.com/godotengine/godot/blob/15a03ed98e63590c85dac62405d785e1b7ca7fed/scene/resources/curve.cpp#L1542) in `_calculate_tangent` -> [Math::bezier_derivative](https://github.com/godotengine/godot/blob/bb6b06c81343073f10cbbd2af515cf0dac1e6549/core/math/math_funcs.h#L397), the result of the formula in the latter function equals `0` if the following conditions are met: `p_control_1` equals `p_end`, `p_control_2` equals `p_start` and `p_t` equals `0.5`.

The `0.5` passed to it in our case corresponds to the middle of the curve segment between two curve points, and is the "most middle" for each of the middlepoint `RBMap` key-value maps initialized [here](https://github.com/godotengine/godot/blob/15a03ed98e63590c85dac62405d785e1b7ca7fed/scene/resources/curve.cpp#L1593) in `_bake` using `_tessellate_even_length` (down that call-chain, this happens [here](https://github.com/godotengine/godot/blob/15a03ed98e63590c85dac62405d785e1b7ca7fed/scene/resources/curve.cpp#L1523) in `_bake_segment3d_even_length` for our `0.5`, since for the first recursion `p_begin` is `0` and `p_end` is `1`).

Thus, if we don't count its initial call to `_bake`, the bug isn't caused by something in the `sample_baked_with_rotation` call-chain, but earlier when the forward vectors are baked. `sample_baked_with_rotation` (or rather, `_compose_posture`) simply trips over it.

The reason that the next point right after the middle point triggers the error as well, but without the basis being wrong, is this: `_compose_posture` is called twice in `_sample_posture` [here](https://github.com/godotengine/godot/blob/15a03ed98e63590c85dac62405d785e1b7ca7fed/scene/resources/curve.cpp#L1837), creating an `idx`-and-`idx+1` "moving window", which, naturally, features each problem-idx twice. The actual problem with the default basis only occurs the first time when it's used for `frame_end`, which causes `sample_posture` to `slerp` to it, since `frac`, in the cases I've explored, always seems to be `1.0`.

### Steps to reproduce

The vectors with two-digit coordinates aren't relevant, they're just set to something else than `Vector3()` to make it less likely for other corner cases to be triggered by accident.
```gdscript
var curve := Curve3D.new()
curve.add_point(Vector3(), Vector3(23, 87, -15), Vector3(1, 0, 0))
curve.add_point(Vector3(1, 0, 0), Vector3(-1, 0, 0), Vector3(19, -22, 56))

var baked_points := curve.get_baked_points()
var middle_point_idx := int(len(baked_points) / 2.0)

for idx in range(middle_point_idx, middle_point_idx + 2):
    var offset := curve.get_closest_offset(baked_points[idx])
    # Error will trigger here.
    curve.sample_baked_with_rotation(offset)
```

### Minimal reproduction project (MRP)

- MRP: [linear-curve-zero-vector-bug-mrp.zip](https://github.com/godotengine/godot/files/14422935/linear-curve-zero-vector-bug-mrp.zip)
- [Exploratory project](https://github.com/Aziroshin/godot-linear-curve-zero-vector-bug-exploration)