-
-
Notifications
You must be signed in to change notification settings - Fork 119
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
Add navigation cube #1573
Add navigation cube #1573
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @erenoku, this is awesome! #15 is one of the oldest open issues we have in this repository, and it's great that you're addressing it!
I've only taken a cursory look at your code, as I don't know how ready for review it is. My priority was to answer your questions, but I left comments where things stood out to me.
The code structure. Should the navigation_cube.rs file be located in the folder named
graphics
or should a new folder be created for this and the other files likemodel.rs
which handles the loading of models.
Since that code seems to use wgpu
heavily, I think graphics
is the appropriate place to put it.
In general, I think these kinds of code structure issues are not critical. If you're unsure, just choose whatever works. If it becomes clear later that another structure is better, we can always change it.
The textures and the model in the
assests
directory should somehow be bundled with the application when installing. I don't think this is possible without an installer script as these files should somehow be downloaded into a specific directory in the users computer.
Can we instead bundle them directly into the binary using include_bytes!
?
We might want to use a perspective camera to render the cube. In spite of my tries for some reason I could not get it working and decided to use an orthographic camera. Although this not a huge problem as the cube is really small and it is almost impossible to notice anything seeming off it would be good if this was fixed before merging.
I have a large screen in my office, and the cube does look really weird 😄
But don't sweat it. If you come up with a solution before merging, then great. But having the navigation cube at all is such a great improvement that having it look a bit weird is not a big problem. We can just open an issue after merging and leave fixing it for later.
Other notes:
- Since the assets are used within
fj-viewer
, wouldn't it be more appropriate to move the directory tocrates/fj-viewer
? - If I had done this, I would have tried a different approach: Create a cube "manually" (by specifying vertices and indices directly in the code) and render the text on it programmatically (using egui, if possible; or using whatever text rendering library egui uses, if not). I don't know if that would actually be better, and I'm definitely not asking you to change it! I just wanted to mention this approach as a possible future change, as it has the advantage of being more flexible and not requiring any external assets (beyond a font, which we already need to bundle anyway).
How close do you think this pull request is to being merge-ready? As I said above, I have looked at the code in detail yet, but it seems like the navigation cube works great as-is, and I'd like to merge it as soon as possible. The only real blocker I see is the bundling of assets. But if my include_bytes!
suggestion works, that shouldn't be a problem.
crates/fj-viewer/Cargo.toml
Outdated
@@ -11,18 +11,26 @@ keywords.workspace = true | |||
categories.workspace = true | |||
|
|||
[dependencies] | |||
anyhow = "1.0.68" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only a small issue, but Anyhow isn't really the appropriate library to use here, as it's optimized for applications, not for libraries where users might want to handle the specific errors differently. The better choice is its sibling library, thiserror, which fj-viewer
already depends on (aee Anyhow README).
Thank you for the review. I think computing the vertices of the cube manually isn't really a good idea as the cube.obj file is just a 1130 byte file that stores the vertices and the indices that we would normally calculate and storing the navigation cube as a model would allow us to easily create more complex cube designs for example with chamfered edges and corners to allow the user to change the camera angle. But I found the idea of writing the text programmatically a good idea and it would also allow us get rid of embedding the png files into the binary and make it possible to implement translation to other languages. Using let texture_data: &[u8] = match m.diffuse_texture.as_str() {
"front.png" => {
include_bytes!("../../../../assets/navigation_cube/front.png")
}
"right.png" => {
include_bytes!("../../../../assets/navigation_cube/right.png")
}
// and so on
_ => return LoadModelError::MaterialNotFound,
}; But as I will try to render the text programmatically this won't be a problem and only embedding I am not completely sure how sure how to render the text using egui so I cannot comment on how long it will take before attempting to do it. But if you want to merge this PR as soon as possible the code should be quickly merge-ready after I change the code to load the textures using |
That makes sense 👍
Also makes sense! Mixing both approaches, as you suggest, might be the best option.
I honestly don't know if using egui for this makes any sense. I think it should be practical, as egui just uses whatever render pass we give it. So I don't see a reason why we couldn't just render it to a texture and draw it on the cube. But I might be missing something, since I'm a total wgpu/egui amateur. If egui causes trouble, we can use whatever text rendering library egui uses under the hood to render the text instead. (Or any other library, really, but using the one egui already uses means we don't need an additional dependency.) I have a secret hope though that makes me want to use egui to draw on the cube: maybe we can draw interactive UI elements on the cube. That would require some transform magic, but maybe it's doable. But in any case, that's just me dreaming. If egui works for this, fine. If not, using something else (or staying with the PNGs) is totally acceptable.
Yeah, I'd like to merge this as soon as we can. Having the navigation cube at all is already such a great improvement. And pull requests that stay open for too long just collect merge conflicts, which causes extra work. As I said before, the only real blocker are the assets, as we don't have the infrastructure (i.e. installers) right now to distribute them. (And even if we built that infrastructure, we'd permanently lose the ability to just |
e6e76d2
to
e941184
Compare
This PR should now be ready for merging. I will retry using a perspective projection later.
This is probably not relevant for now but if later bundling assets becomes necessary we can check every time the fj-app is started whether a specific directory in the users computer exists and if not start downloading the assets into that directory. Edit: I managed to get perspective camera working. |
Thank you, @erenoku! I'll take a look tomorrow. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again, @erenoku, this looks great!
I've left a few comments were I noticed potential problems, but none of those are critical, and none of those change that this is a great addition. I'm going to merge this pull request now.
Feel free to address any comments you find worth addressing in a follow-up pull request, if you want.
@@ -3,9 +3,12 @@ | |||
mod draw_config; | |||
mod drawables; | |||
mod geometries; | |||
mod model; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the naming of this module and some of the types in it is not ideal. It makes sense when viewed in isolation, but in the larger context of Fornjot, it could be confusing. Someone might search for the code that draws CAD models, and then think they found it here.
It's not a critical issue, and I don't have any better ideas right now. Just making a note, hoping that someone will come with with something better at some point.
let vertices = (0..m.mesh.positions.len() / 3) | ||
.map(|i| ModelVertex { | ||
position: [ | ||
m.mesh.positions[i * 3], | ||
m.mesh.positions[i * 3 + 1], | ||
m.mesh.positions[i * 3 + 2], | ||
], | ||
tex_coords: [ | ||
m.mesh.texcoords[i * 2], | ||
1.0 - m.mesh.texcoords[i * 2 + 1], | ||
], | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those magic numbers here (specifically, the 3
used for vertex position and the 2
used for texture coordinates) aren't great. It's easy enough to figure out why they are here (number of vertices in a triangle and number of texture coordinates in 2 dimensions, respectively), but it gave me pause and looks a bit iffy.
It might make sense to extract them into appropriately named constants, and extract the i * 3
/i * 2
into variables. Although I don't have ideas on what to name those.
Anyway, I'm nitpicking!
pub trait DrawModel<'a> { | ||
fn draw_mesh(&mut self, mesh: &'a Mesh, material: &'a Material); | ||
fn draw_mesh_instanced( | ||
&mut self, | ||
mesh: &'a Mesh, | ||
material: &'a Material, | ||
instances: Range<u32>, | ||
); | ||
|
||
fn draw_model(&mut self, model: &'a Model); | ||
fn draw_model_instanced(&mut self, model: &'a Model, instances: Range<u32>); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a trait and then implementing it for wgpu::RenderPass
might be a bit too clever, and therefore potentially confusing. I think I would prefer just having functions that accept all the necessary parameters.
const SCALE_FACTOR: f64 = 0.13; | ||
const CUBE_TRANSLATION: [f64; 3] = [0.8, 0.7, 0.0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems those constants are used only in a single method. Maybe it makes more sense to move them into the local scope of that method. That would make their meaning a bit clearer, I think, as they would be closer to the code that uses them.
&device, | ||
&queue, | ||
&surface_config, | ||
800.0 / 600.0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why we need to pass an aspect ratio here, and why it is set to this value specifically.
Everything seems to work fine, so it's not too much of a problem, but I figure this could be made clearer. Since the aspect ratio is set to a constant anyway, maybe we should move this value to where it's actually used and add a comment there, explaining why that specific value was chosen.
eb2ad39
to
533f6c2
Compare
I opened this PR as a draft as I have some questions.
The code structure. Should the navigation_cube.rs file be located in the folder named
graphics
or should a new folder be created for this and the other files likemodel.rs
which handles the loading of models. Btw most of the boilerplate handling the loading of the model, textures and meshes are copied from learn-wgpu's github repository.The textures and the model in the
assests
directory should somehow be bundled with the application when installing. I don't think this is possible without an installer script as these files should somehow be downloaded into a specific directory in the users computer.We might want to use a perspective camera to render the cube. In spite of my tries for some reason I could not get it working and decided to use an orthographic camera. Although this not a huge problem as the cube is really small and it is almost impossible to notice anything seeming off it would be good if this was fixed before merging.
Here is a photo showing how it looks.
Closes #15