Skip to content

Debug renderer#755

Draft
NickHu wants to merge 3 commits into
masterfrom
debug
Draft

Debug renderer#755
NickHu wants to merge 3 commits into
masterfrom
debug

Conversation

@NickHu
Copy link
Copy Markdown
Collaborator

@NickHu NickHu commented Aug 27, 2022

Far too frequently we need to get into the nitty gritty of a diagram, and this involves lots of tedious drawing by hand when we have a perfectly good 3D renderer already!

This is my attempt to add a function that can be called anywhere within homotopy-core, which when called will hijack the app and display a rotatable debug model of the diagram passed in:
image

It's a rough prototype, and I definitely need some help with the graphics stuff, but it's a decent way there.

Note that this is a debugging tool, so there is nothing to play with in the release version that the PR preview generates. To test it out, apply this patch:

diff --git a/homotopy-core/src/diagram.rs b/homotopy-core/src/diagram.rs
index 8e8081e..06b6092 100644
--- a/homotopy-core/src/diagram.rs
+++ b/homotopy-core/src/diagram.rs
@@ -89,6 +89,11 @@ impl Diagram {
 
     #[must_use]
     pub fn identity(&self) -> DiagramN {
+        #[cfg(debug_assertions)]
+        let (_sig, d) = crate::examples::two_monoid();
+        #[cfg(debug_assertions)]
+        crate::debug::debug_diagram(d.into());
+
         DiagramN::new_unsafe(self.clone(), vec![])
     }

and trigger the construction of an identity.

@NickHu
Copy link
Copy Markdown
Collaborator Author

NickHu commented Aug 27, 2022

TODO:

  • Make text not blurry and scale correctly
  • Make arrow tips not computed in the stupidest way possible
  • Programatically strip diagram boundaries (currently hardcoded - that's why the tests fail too) - this will require a refactor
  • Maybe generate the geometry separately from how it's generated for normal 3D mode

@NickHu
Copy link
Copy Markdown
Collaborator Author

NickHu commented Aug 27, 2022

@DoctorN would love a review on this, I'm for sure doing some things incorrectly GL-wise.

In particular, I'm almost certain this is wrong in some way:

ctx.with_state((), 15, |_, local| {
for (k, (p, q)) in [(0, 1), (1, 2), (0, 2)].iter().copied().enumerate() {
let delta = 0.2 * (geom.verts[tri[q]].position - geom.verts[tri[p]].position);
let begin = geom.verts[tri[p]].position + delta;
let end = geom.verts[tri[q]].position - delta;
// as each drawn vertex is offset, relative to this triangle and edge, the
// vertex index is just a counter
let s = local.push_vert(Vert::new(15 * n + 5 * k), begin.xyz());
let t = local.push_vert(Vert::new(15 * n + 5 * k + 1), end.xyz());
local.inner.push_line(s, t);
// draw arrow tip
let head_x = local.push_vert(
Vert::new(15 * n + 5 * k + 2),
(end - delta + Vec4::new(0.1, 0.0, 0.0, 0.0)).xyz(),
);
let head_y = local.push_vert(
Vert::new(15 * n + 5 * k + 3),
(end - delta + Vec4::new(0.0, 0.1, 0.0, 0.0)).xyz(),
);
let head_z = local.push_vert(
Vert::new(15 * n + 5 * k + 4),
(end - delta + Vec4::new(0.0, 0.0, 0.1, 0.0)).xyz(),
);
local.inner.push_line(head_x, t);
local.inner.push_line(head_y, t);
local.inner.push_line(head_z, t);
local.inner.push_line(head_x, head_y);
local.inner.push_line(head_y, head_z);
local.inner.push_line(head_z, head_x);
}
})?;

And the way I'm initializing the 2D Canvas context is maybe not all there (could explain why the text is so pixelated).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Aug 27, 2022

Visit the preview URL for this PR (updated for commit 5af98eb):

https://homotopy-rs--homotopy-io-debug-ek5ikvjk.web.app

(expires Fri, 28 Oct 2022 12:02:37 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

@jamievicary
Copy link
Copy Markdown
Collaborator

Very interesting idea Nick. How deep will this go into the scaffold?

@NickHu
Copy link
Copy Markdown
Collaborator Author

NickHu commented Aug 28, 2022

This currently just uses the geometry you would get if you projected any diagram into 3D, but the intention is that this can be changed on the fly in order to draw any DAG representation of the fully exploded diagram. For instance, we might want to debug a 4D diagram by drawing all its 3D slices in the standard way, but in 3D space offset in the Z-axis (like the 'stack diagrams' we draw sometimes).


impl DebugScene {
pub fn new(ctx: &GlCtx, diagram: &Diagram) -> Result<Self> {
let cubical = match diagram.dimension() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CubicalGeometry::new isn't really designed for this. What you want is a different constructor that makes a geometry containing all the points/lines but none of areas/volumes. That would be easy to write, and you wouldn't even need to use the Mesh, you can just use the exploded graph (and configure that to ignore the boundary).

}

fn buffer(ctx: &mut BufferingCtx<Self>) -> Result<()> {
for (n, (tri, _)) in ctx.geom.areas.values().copied().enumerate() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use a different geometry which contains all the points/lines (see my earlier comment about), you wouldn't need this horrible hack.

Copy link
Copy Markdown
Collaborator Author

@NickHu NickHu Aug 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason this is here is because in what gets drawn, for each edge, the endpoints are pushed together (to make a gap for the node label). This means that there's no longer a one-to-one correspondence between logical points in the geometry and points that get drawn by the renderer, rather each logical point spawns a cloud of rendered points, one for each edge touching it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I get that. What I meant is you're using the triangles to construct the points/lines (which is ugly) and you won't need to do once you do what I said in my comment above.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh you were talking about the areas part rather than the enumerate part. Yeah, I see that. I think keeping these indices is probably a hack too but I'm not too sure how to fix it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the correct way to do this is to "inflate" the geometry before you pass it to the bufferer, like Nathan did for cylinders and spheres.

@cofibrant
Copy link
Copy Markdown
Collaborator

I'll take a look tomorrow!

@NickHu
Copy link
Copy Markdown
Collaborator Author

NickHu commented Aug 29, 2022

I fixed the resolution problems with the text by making the 2D canvas which is drawn on top get rescaled. I also added some basic occlusion of text labels:
image
Unfortunately, this occludes over everything in the 3D scene, which is unavoidable with this method of text rendering. I'm not really sure if this occlusion is worthwhile as a result.

Pictured is the associator; it looks a bit yikes but it's a lot nicer interactively rotating around the scene.

@calintat calintat force-pushed the master branch 2 times, most recently from 25c6a8d to 09c00e9 Compare February 7, 2024 13:55
@NickHu NickHu force-pushed the master branch 6 times, most recently from fa70da2 to 4dfe07f Compare February 19, 2024 12:59
@calintat calintat force-pushed the master branch 2 times, most recently from 8059097 to 6c94846 Compare March 7, 2024 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants