-
-
Notifications
You must be signed in to change notification settings - Fork 663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom Layer Interface is missing a mercatorMatrix3d #3797
Comments
Here is a flowchart of how existing matrices are calculated: flowchart TD
S[START] --> |scale by 1, 1, _pixelPerMeter| T[temp]
S --> |scale by worldSize, worldSize, worldSize| MM[mercatorMatrix]
T --> |translate by 0, 0, -elevation| PR[projMatrix]
T --> |multiply by labelPlaneMatrix| PI[pixelMatrix]
PR --> |multiply by labelPlaneMatrix| PI3[pixelMatrix3D]
And here is a table of which matrices exist, and what is missing:
The description of these matrices is from the comments in the code - to be honest I'm still a bit vague on the details eg are mercator-coords the same as world-space (I believe they are very similar but they might not be exactly the same). Hopefully, someone familiar with the MapLibre matrices can weigh in on what the appropriate way to construct a mercatorMatrix3D is, again it will be similar to what I have done but perhaps not exactly the same. |
Can you try use mermaid to draw the diagrams? |
Maybe @maxammann can shred some light, I always find these matrices confusing... |
Also, there's a problem with the custom layer interface as there seems to be a lot of different requirements to enhance it, but they don't "scale" well, i.e. adding more parameters to the method is not a good approach, I guess an input object should be used and thus allowing it to grow without breaking the interface... |
This is still waiting on a ML matrices / CustomLayer expert to weigh in on what an appropriate fix would be. In the meantime, if you are experiencing this issue and you want to work around it, you can do the following in your Custom Layer, as I have:
should be changed to the following: +const mercatorMatrix3D = new Array(16) as mat4;
...
render(gl, matrix) {
+ // This workaround can go away once there is a proper fix for https://github.com/maplibre/maplibre-gl-js/issues/3797
+ const tr = map.transform;
+ const zOffset = (-tr.elevation * tr._pixelPerMeter) / tr.worldSize;
+ mat4.translate(mercatorMatrix3D, matrix, [0, 0, zOffset]);
gl.useProgram(this.program);
- gl.uniformMatrix4fv(gl.getUniformLocation(this.program, "u_matrix"), false, matrix);
+ gl.uniformMatrix4fv(gl.getUniformLocation(this.program, "u_matrix"), false, mercatorMatrix3D);
gl.drawArrays(gl.POINTS, 0, 1);
} |
This seems to have stalled - I've diagnosed it and found a possible fix, but somebody in ML will have to decide what is appropriate here:
@prozessor13 maybe you can help? |
This would be fixed by #3854, which someone is already working on, so that is now my preferred fix |
(I wrote a followup on this issue in the other discussion - copying it here for completeness. Since I wrote up this issue I've become a bit more familiar with MapLibre, I would write it differently now.
So to sum up:
This means, there's no need to provide custom layer authors two matrices for them to choose between - one would be sufficient. However, for backwards compatibility reasons, it might be useful to keep providing the old matrix in some way, even though it is (IMO) strictly less useful than the fixed matrix (again, see #3854) |
The Custom Layer Interface documentation gives an example of how to make a custom 2D layer.
It documents that you can choose whether the layer is 2D or 3D - but the effects of that choice are quite limited, possibly only enabling or disabling the depth buffer.
Different transformational matrices are used for 2D and 3D rendering, but the Custom Layer Interface is always provided with a matrix called
mercatorMatrix
. This matrix is appropriate, I believe, for 2D rendering, but not for 3D rendering, since it is missing one of the translate steps that the matrices used for 3D rendering have. Specifically, it doesn't have this line of code, or any equivalent:mat4.translate(m, m, [0, 0, -this.elevation]); // elevate camera over terrain
Because it is missing this translation - which is not always the same amount, and depends in some way on the terrain height at the center of the camera - using this matrix to render a point in a 3D context causes the point to appear too high, by a small amount when the camera-center-terrain-height is near sea level, and by a large amount when the camera-center-terrain-height is high altitude.
maplibre-gl-js version:
4.1.0 or main @ 3345713
browser:
Brave, but this logic is not browser dependent.
Steps to Trigger Behavior
Use a CustomLayerInterface to render points / objects in a 3D view, with terrain enabled, in a place with hilly terrain (effects of the bug will be minimal if the terrain is close to sea level).
Link to Demonstration
#3796 - which is still a draft - shows the issue (the red point is too high), and shows a basic fix (the green point is in the correct location). To try it out, checkout these changes, run build-dev, and open
test/examples/custom-layer-interface-bug.html
Moving the view around will cause the red dot's height to jump to some other value whenever
recalculateZoom
is called, which happens at the end of each panning movement.Here is a screenshot of the issue as shown by the #3796
![Screenshot 2024-03-06 at 10 47 25 AM](https://private-user-images.githubusercontent.com/7425442/310315064-6f7c1d73-c6e4-4ee7-b2e2-a3927472f845.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjEyNDQyMTAsIm5iZiI6MTcyMTI0MzkxMCwicGF0aCI6Ii83NDI1NDQyLzMxMDMxNTA2NC02ZjdjMWQ3My1jNmU0LTRlZTctYjJlMi1hMzkyNzQ3MmY4NDUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MDcxNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDA3MTdUMTkxODMwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NjBkZjI4ZmY5ZDE5MTJkZTcyYzdhODk1Y2JhOGY4MjUzZmRkNjdlYWQ3ZTIwZTg3MzlkYTA5MGZhMzNhYzRlNiZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QmYWN0b3JfaWQ9MCZrZXlfaWQ9MCZyZXBvX2lkPTAifQ.JJ6Nn3S3UJVktgB7_SIezW2CpTgr-pUi8W7EEUE2Fns)
Note that the green point has the right position, this is possible since I've modified
src/geo/transform.ts
to expose another matrix calledmercatorMatrix3D
.Expected Behavior
Actual Behavior
The text was updated successfully, but these errors were encountered: