Just bear with me: I’ll get to the point. In the book, we develop a simple game engine. However, every game has a HUD (especially the FPS ones): some kind of an on-screen dashboard where some relevant info (like remaining heath/ammo) always remains visible. Apparently this dashboard must somehow be attached to the camera and rotate/move with it: no matter how you move, it always stays in front of you.
So, this is the technique I’m after, basically: how to keep something always in front of the camera, at the same location (say, bottom left corner), no matter how the camera rotates or moves. Try as I might, I could not find any example in the book, and googling for it gives me the results about Blender, Unreal Engine, and what not, which are too many and too irrelevant to deal with. I understand no one is going to rewrite the already-published book for me, but… maybe someone can at least suggest where to look for an idea?
Personally I would do a static hub with a SwiftUI view layered on top of the Metal view.
Chapter 20 code is an example of this. Not a dashboard as such, but it has toggles that control what is drawn.
Thank you for the prompt response.
I’m working on an app that lets the user preview the BVH MoCap files: as far as I know, there is no such tool for Apple platforms (only some Python source code), while there are several, including the famous BVHacker, for Windows.
So, I would dearly like to make that gizmo from the Chapter 10 to just stay in the corner, instead of spinning out of sight when the camera rotates:
I also need a camera that combines some features of both the FPS and ArcBall, but that’s by the by.
You reminded me that I meant to improve on the gizmo in Chapter 10, Lighting Fundamentals.
This project is taken from the final of that chapter, but has an improved gizmo rendering, which is fixed at the bottom left of the window.
Gizmo.zip (201.0 KB)
The gizmo is a model, but instead of being rendered with the scene models, as in the chapter, it’s rendered in Renderer
, using an orthographic camera.
Changes (as far as I can remember):
- New vertex and fragment shaders in Gizmo.metal. You don’t need light shading on the gizmo.
-
Renderer.mtkView(_:drawableSizeWillChange:)
sets up the gizmo’s orthographic camera and calculates the gizmo position to be fixed at the bottom left of the window even if the window changes size. -
Model
now has a bounding box to calculate the correct position of the gizmo. -
Renderer.draw(scene:in:)
draws the gizmo after rendering the models, setting a new pipeline state for the gizmo shaders, and changing the camera to the orthographic one. -
GameScene
doesn’t render the gizmo.
Thanks a lot:
That’s the path I’ve been considering myself, based on this: 2D HUD overlay drawing based on 3D coordinates and camera azimuth and elevation - Game Development Stack Exchange
Basically, render the thing using a separate view matrix for the gizmo, just as you say. But your reply is going to save me a lot of trial and error: unfortunately, there’s shockingly little up-to-date info about Metal on the Internet, let alone any code samples (anti-Apple anti-corporate anti-establishment anti-everything drive so common nowadays? Or everyone going multiplatform, from OpenGL to Vulkan? Perhaps both? ). Anyway, tanks again!
I guess because most people don’t use Apple. The basic principles of 3D rendering are much the same across all platforms, but I agree, when trying to come up with a solution, there are not enough code samples.
Warren Moore’s GitHub is an excellent place to go, plus his website: https://metalbyexample.com and his introduction to Metal: Thirty Days of Metal—Day 1: Devices | by Warren Moore | Medium
And thanks for the third time, Caroline: this is exactly what I was after
No matter how the ‘main’ canera rotates or moves, the gizmo stays in its corner, while reflecting the rotation relative to the ‘world’ axis.
As you probably know, the BVH ‘skeletons’ vary vastly in their size: actually, there are no ‘size’ data at all, only the offset of one bone from another, in no specific units, and with no limits to the range of values (and there may or may not also be the translation info, in which case the skeleton is disjoined). So, I must be able to re-calculate my scene’s dimensions and position the camera accordingly, to keep my doll in sight – but naturally, the gizmo should not have been affected by any of this, or by the subsequent rotations performed by the user to view the action from all sides. Your code sample greatly helped with that.
Speaking of which, I believe you mentioned that this is still work in progress so, I hope you don’t mind if I point out this strange fragment
mutating func update(deltaTime: Float) {
let input = InputController.shared
let scrollSensitivity = Settings.mouseScrollSensitivity
distance -= (input.mouseScroll.x + input.mouseScroll.y)
* scrollSensitivity
distance = min(maxDistance, distance) // ???
distance = max(minDistance, distance) // ??? What's the point of these assignemnts?
input.mouseScroll = .zero
There is at least one similar example in the boot (v3 that I have):
let input = InputController.shared
let scrollSensitivity = Settings.mouseScrollSensitivity
distance -= (input.mouseScroll.x + input.mouseScroll.y)
* scrollSensitivity
distance = min(maxDistance, distance) //????
distance = max(minDistance, distance) //???? Assigning to thesame variable more that once in a row?
input.mouseScroll = .zero
Also, working on this little tool of mine gave me a good idea of what kind of technical book I would like to see: I wonder if this is Ok to start a separate thread with some suggestions?