Skip to content
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

A mesh grid demo #2

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,53 @@ URL params:

- `tab` content to draw, options(defaults to last one):

- `quat-curve`
- `hyper-cube`
- `hyper-cube-grid`
- `fly-city`
- `lamp-tree`
- `quat-tree`
- `quat-product`
- `prime-walk`
- `quat-curve` a curve
- `hyper-cube` hyper cube
- `hyper-cube-grid` a grid of hyper cubes
- `fly-city` quternion fractal
- `lamp-tree` quternion fractal
Comment on lines +14 to +15
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in "quaternion" and differentiate fractal descriptions.

There are two issues in these lines:

  1. "quternion" is misspelled (should be "quaternion")
  2. Two different visualizations have the exact same description

Apply this diff to fix the typo and differentiate the descriptions:

-  - `fly-city` quternion fractal
-  - `lamp-tree` quternion fractal
+  - `fly-city` quaternion fractal with city-like structures
+  - `lamp-tree` quaternion fractal with tree-like branching
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `fly-city` quternion fractal
- `lamp-tree` quternion fractal
- `fly-city` quaternion fractal with city-like structures
- `lamp-tree` quaternion fractal with tree-like branching
🧰 Tools
🪛 LanguageTool

[grammar] ~14-~14: This phrase is duplicated. You should probably use “quternion fractal” only once.
Context: ...da grid of hyper cubes -fly-cityquternion fractal -lamp-treequternion fractal -quat-treequaternion tree -qu...

(PHRASE_REPETITION)

- `quat-tree` quaternion tree
- `quat-product` quaternion product curve
- `prime-walk` some walk path
- `sphere-tess` sphere tessellation folded to 2 dimensions
- `cubic-array` array and grid in cubic space
Comment on lines +19 to +20
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Enhance visualization descriptions.

The descriptions for new visualizations could be more informative:

  1. Use "into" instead of "to" in "folded into 2 dimensions"
  2. Clarify what "array and grid in cubic space" means for users

Apply this diff to improve clarity:

-  - `sphere-tess` sphere tessellation folded to 2 dimensions
-  - `cubic-array` array and grid in cubic space
+  - `sphere-tess` sphere tessellation projected into 2D space
+  - `cubic-array` 3D grid visualization in cubic space
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `sphere-tess` sphere tessellation folded to 2 dimensions
- `cubic-array` array and grid in cubic space
- `sphere-tess` sphere tessellation projected into 2D space
- `cubic-array` 3D grid visualization in cubic space
🧰 Tools
🪛 LanguageTool

[uncategorized] ~19-~19: The preposition “into” seems more likely in this position than the preposition “to”.
Context: ...sphere-tesssphere tessellation folded to 2 dimensions -cubic-array` array an...

(AI_EN_LECTOR_REPLACEMENT_PREPOSITION_TO_INTO)


[grammar] ~20-~20: Possible agreement error. The noun ‘grid’ seems to be countable.
Context: ... dimensions - cubic-array array and grid in cubic space - read to read from s...

(CD_NN)

Comment on lines +11 to +20
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Enhance parameter descriptions with usage examples.

While the basic descriptions are present, users would benefit from:

  1. Example parameter values for each visualization
  2. Expected visual outcomes
  3. Interaction possibilities

Consider expanding the documentation like this:

   - `quat-curve` a curve
+      Example: `?tab=quat-curve`
+      Displays a quaternion-based curve that can be rotated in 4D space.
   
   - `prime-walk` some walk path
+      Example: `?tab=prime-walk&times=5`
+      Visualizes a path based on prime number patterns. Use the times parameter to control complexity.
   
   - `sphere-tess` sphere tessellation folded to 2 dimensions
+      Example: `?tab=sphere-tess&times=6`
+      Projects a tessellated sphere onto 2D space. Higher times values create finer tessellation.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `quat-curve` a curve
- `hyper-cube` hyper cube
- `hyper-cube-grid` a grid of hyper cubes
- `fly-city` quternion fractal
- `lamp-tree` quternion fractal
- `quat-tree` quaternion tree
- `quat-product` quaternion product curve
- `prime-walk` some walk path
- `sphere-tess` sphere tessellation folded to 2 dimensions
- `cubic-array` array and grid in cubic space
- `quat-curve` a curve
Example: `?tab=quat-curve`
Displays a quaternion-based curve that can be rotated in 4D space.
- `hyper-cube` hyper cube
- `hyper-cube-grid` a grid of hyper cubes
- `fly-city` quternion fractal
- `lamp-tree` quternion fractal
- `quat-tree` quaternion tree
- `quat-product` quaternion product curve
- `prime-walk` some walk path
Example: `?tab=prime-walk&times=5`
Visualizes a path based on prime number patterns. Use the times parameter to control complexity.
- `sphere-tess` sphere tessellation folded to 2 dimensions
Example: `?tab=sphere-tess&times=6`
Projects a tessellated sphere onto 2D space. Higher times values create finer tessellation.
- `cubic-array` array and grid in cubic space
🧰 Tools
🪛 LanguageTool

[grammar] ~14-~14: This phrase is duplicated. You should probably use “quternion fractal” only once.
Context: ...da grid of hyper cubes -fly-cityquternion fractal -lamp-treequternion fractal -quat-treequaternion tree -qu...

(PHRASE_REPETITION)


[uncategorized] ~19-~19: The preposition “into” seems more likely in this position than the preposition “to”.
Context: ...sphere-tesssphere tessellation folded to 2 dimensions -cubic-array` array an...

(AI_EN_LECTOR_REPLACEMENT_PREPOSITION_TO_INTO)


[grammar] ~20-~20: Possible agreement error. The noun ‘grid’ seems to be countable.
Context: ... dimensions - cubic-array array and grid in cubic space - read to read from s...

(CD_NN)


- `read` to read from storage, options(defaults to `true`):

- `true`
- `false`

- `axis` to draw axis, options(defaults to `true`):

- `true`
- `false`

- `times` for expand times, only works on some demos, 0~10

Comment on lines +32 to +33
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clarify the 'times' parameter documentation.

The current description lacks crucial details about:

  1. Which specific demos support this parameter
  2. How different values affect the visualization
  3. The meaning of the range notation

Consider expanding the documentation like this:

-times` for expand times, only works on some demos, 0~10
+- `times` controls visualization complexity (default: 6)
+  - Supported demos:
+    - `sphere-tess`: controls tessellation detail (higher = finer)
+    - `cubic-array`: affects grid density
+  - Valid range: 0 to 10 (inclusive)
+  - Example: `?tab=sphere-tess&times=8`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `times` for expand times, only works on some demos, 0~10
- `times` controls visualization complexity (default: 6)
- Supported demos:
- `sphere-tess`: controls tessellation detail (higher = finer)
- `cubic-array`: affects grid density
- Valid range: 0 to 10 (inclusive)
- Example: `?tab=sphere-tess&times=8`

### Gamepad Controls

Control between XYZ:

![Gamepad Default](./assets/caterfoil-default.png)

Hold `△` to enable control between XYW:

![Gamepad W](./assets/caterfoil-W.png)
Comment on lines +34 to +42
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Expand gamepad controls documentation.

The current documentation needs additional context about:

  1. Supported gamepad models/types
  2. The significance of XYZ vs XYW controls
  3. Alternative keyboard/mouse controls

Consider adding sections for:

  • Supported devices
  • Control scheme explanation
  • Keyboard/mouse alternatives
  • How different controls affect each visualization type


### Development

Watch build MoonBit:

```bash
moon build --target js --debug --watch
```

Watch serve page:

```bash
yarn vite
```
Comment on lines +46 to +56
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add troubleshooting guide to development instructions.

While the commands are clear, users would benefit from knowing:

  • Expected output of successful execution
  • Common issues and their solutions
  • Where to find logs
  • How to verify the setup is working

Consider adding a troubleshooting section with common issues and solutions.


### Licence

Apache 2.0
Binary file added assets/caterfoil-W.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/caterfoil-default.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions moon.mod.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "tiye/caterfoil",
"version": "0.1.0",
"version": "0.0.2",
"deps": {
"tiye/quaternion": "0.0.4",
"tiye/dom-ffi": "0.0.6"
"tiye/dom-ffi": "0.0.8"
},
"readme": "README.md",
"repository": "",
"license": "Apache-2.0",
"keywords": [],
"description": "",
"source": "src"
}
}
4 changes: 2 additions & 2 deletions src/caterfoil.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ console.log("Caterfoil loaded", Caterfoil);
// load js code which Vite does not detect
import("../target/js/debug/build/main/main.js")
.then((module) => {
console.log("Main loaded", module);
console.log("mbt app loaded", module);
})
.catch((error) => {
console.error("Main error", error);
console.error("mbt app loading error", error);
});
174 changes: 172 additions & 2 deletions src/lib/caterfoil.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pub extern "js" fn initialize_context() -> Promise =
#| () => Caterfoil.initializeContext()

///|
/// Triggers a redraw of the current Caterfoil render tree. Updates the WebGPU
/// canvas with the latest state of all render objects in the scene graph.
Comment on lines +6 to +7
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add usage example to the documentation.

Consider adding a code example to demonstrate how to use paint_caterfoil_tree().

pub extern "js" fn paint_caterfoil_tree() -> Unit =
#| () => Caterfoil.paintCaterfoilTree()

Expand All @@ -14,10 +16,19 @@ pub extern "js" fn render_caterfoil_tree(
#| (el, dispatch) => Caterfoil.renderCaterfoilTree(el, dispatch)

///|
/// Adjusts the canvas size to match its display size, ensuring proper rendering
/// and preventing scaling artifacts.
///
/// Parameters:
///
/// * `canvas` : The HTML canvas element to be resized. Must be a valid DOM
/// Element object obtained through methods like `Document::query_selector`.
pub extern "js" fn reset_canvas_size(canvas : Element) -> Unit =
#| (canvas) => Caterfoil.resetCanvasSize(canvas)

///|
/// Initializes textures required for WebGPU rendering on the canvas. Sets up
/// necessary texture configurations and bindings for the rendering pipeline.
pub extern "js" fn initialize_canvas_textures() -> Unit =
#| () => Caterfoil.initializeCanvasTextures()

Expand All @@ -26,6 +37,10 @@ pub extern "js" fn setup_mouse_events() -> Unit =
#| () => Caterfoil.setupMouseEvents()

///|
/// Sets up gamepad input handling for WebGPU rendering. Initializes event
/// listeners and state management for gamepad connections, button presses, and
/// axis movements. Enables real-time input detection from connected gamepads to
/// control the WebGPU rendering viewport and scene.
Comment on lines +40 to +43
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add usage example to the documentation.

Consider adding a code example to demonstrate how to initialize and use gamepad controls.

pub extern "js" fn load_gamepad_control() -> Unit =
#| () => Caterfoil.loadGamepadControl()

Expand All @@ -34,10 +49,38 @@ pub extern "js" fn lines_wgsl() -> String =
#| () => Caterfoil.triangleWgsl

///|
/// Returns the WebGPU Shader Language (WGSL) code used for rendering polylines
/// in Caterfoil. The shader includes vertex and fragment stages necessary for
/// drawing thick lines with proper width and direction handling.
///
/// Returns a string containing the WGSL shader code for polyline rendering.
pub extern "js" fn polyline_wgsl() -> String =
#| () => Caterfoil.polylineWgsl

///| get viewer states saved in localStorage so that it can be restored
///|
/// Connects a retained atom to browser's localStorage for persistent state
/// management. The connection can be configured to enable/disable reading from
/// or writing to localStorage.
///
/// Parameters:
///
/// * `name` : A unique identifier string for the retained atom. This name is
/// used as the key in localStorage.
/// * `read` : Optional boolean flag to control loading from localStorage.
/// Defaults to `true`. When set to `false`, disables loading stored values.
/// * `write` : Optional boolean flag to control saving to localStorage. Defaults
/// to `true`. When set to `false`, disables saving values.
///
/// Example:
///
/// ```moonbit
/// test "connect_retained_atom_to_srorage" {
/// // Connect an atom named "viewer-state" with both read and write enabled
/// connect_retained_atom_to_srorage("viewer-state")
/// // Connect an atom that only reads from storage
/// connect_retained_atom_to_srorage("read-only-state", write=false)
/// }
/// ```
Comment on lines +61 to +83
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in function name.

The function name contains a typo: "srorage" should be "storage".

Apply this diff to fix the typo:

-pub fn connect_retained_atom_to_srorage(
+pub fn connect_retained_atom_to_storage(

Committable suggestion skipped: line range outside the PR's diff.

pub fn connect_retained_atom_to_srorage(
name : String,
/// false to disable loading from localStorage
Expand All @@ -61,6 +104,39 @@ extern "js" fn caterfoil_connect_retained_atom_to_srorage(
#| (name, read, write) => Caterfoil.connectRetainedAtomToStorage(name, {read, write})

///|
/// Represents the vertex data used in Caterfoil rendering objects. Provides two
/// variants for different rendering approaches:
/// basic vertices for simple shapes and polyline vertices for thick lines with
/// proper width handling.
///
/// Parameters:
///
/// For `WithPoints`:
///
/// * `vertices` : An array of basic vertices, each containing position and color
/// information.
///
/// For `WithTriangles`:
///
/// * `vertices` : An array of polyline vertices, each containing position,
/// color, direction, and side information for thick line rendering.
///
/// Example:
///
/// ```moonbit
/// test "ObjectData" {
/// let points = ObjectData::WithPoints([
/// Vertex::{
/// position: @quaternion.new(0.0, 0.0, 0.0, 1.0),
/// color: Color::red(),
/// },
/// ])
/// match points {
/// WithPoints(vertices) => inspect!(vertices.length(), content="1")
/// WithTriangles(_) => inspect!(false, content="true")
/// }
/// }
/// ```
pub(all) enum ObjectData {
WithPoints(Array[Vertex])
WithTriangles(Array[PolylineVertex])
Expand Down Expand Up @@ -89,6 +165,41 @@ fn ObjectData::to_data(
}

///|
/// Represents configuration options for creating a WebGPU render object in
/// Caterfoil. Contains essential information about the rendering pipeline,
/// including shader configuration, vertex data, and rendering topology.
///
/// Fields:
///
/// * `label` : A string identifier for the render object, useful for debugging
/// purposes.
/// * `shader` : The WebGPU shader code as a string, defining how vertices should
/// be processed and rendered.
/// * `topology` : The primitive topology type that determines how vertices are
/// interpreted (e.g., point list, line list, triangle list).
/// * `data` : The vertex data to be rendered, can be either basic vertices or
/// polyline vertices with additional attributes.
/// * `indices` : Optional array of unsigned integers specifying the vertex
/// indices for indexed rendering.
/// * `get_params` : Optional callback function that returns an array of
/// floating-point values used as shader parameters.
///
/// Example:
///
/// ```moonbit
/// test "CaterfoilObjectOptions" {
/// let options = CaterfoilObjectOptions::{
/// label: "triangle",
/// shader: @caterfoil.lines_wgsl(),
/// topology: ShaderPrimitiveTopology::TriangleList,
/// data: ObjectData::WithPoints([]),
/// indices: None,
/// get_params: None,
/// }
/// inspect!(options.label, content="\"triangle\"")
/// inspect!(options.topology, content="TriangleList")
/// }
/// ```
pub(all) struct CaterfoilObjectOptions {
label : String
shader : String
Expand Down Expand Up @@ -164,13 +275,50 @@ fn CaterfoilAttribute::as_value(self : CaterfoilAttribute) -> JsValue {
///|
type CaterfoilRenderObject

///|
///| Creates a new Caterfoil render object with the specified configuration
extern "js" fn CaterfoilRenderObject::as_value(
self : CaterfoilRenderObject
) -> JsValue =
#| (self) => self

///|
/// Creates a new WebGPU render object in the Caterfoil rendering system with
/// specified vertex data and rendering configuration.
///
/// Parameters:
///
/// * `data` : The vertex data to be rendered. Can be either basic vertices
/// (`WithPoints`) or polyline vertices (`WithTriangles`) with additional
/// attributes for thick line rendering.
/// * `shader` : Optional WebGPU shader code as a string. If not provided,
/// automatically selects an appropriate shader based on the vertex data type
/// (`lines_wgsl` for `WithPoints`, `polyline_wgsl` for `WithTriangles`).
/// * `label` : Optional string identifier for the render object, useful for
/// debugging. Defaults to "object".
/// * `topology` : Optional primitive topology type that determines how vertices
/// are interpreted (e.g., point list, line list). Defaults to `TriangleList`.
/// * `get_params` : Optional callback function that returns an array of
/// floating-point values used as shader parameters.
/// * `indices` : Optional array of unsigned integers specifying the vertex
/// indices for indexed rendering.
///
/// Returns a new `CaterfoilRenderObject` that can be used in the Caterfoil
/// rendering system.
///
/// Example:
///
/// ```moonbit
/// test "object/basic" {
/// let vertices = [
/// Vertex::{
/// position: @quaternion.new(0.0, 0.0, 0.0, 1.0),
/// color: Color::red(),
/// },
/// ]
/// let triangle = object(data=ObjectData::WithPoints(vertices))
/// inspect!(triangle, content="[object Object]")
/// }
/// ```
pub fn object(
data~ : ObjectData,
/// by default, pick the shader based on the data type
Expand Down Expand Up @@ -201,6 +349,28 @@ pub fn object(
}

///|
/// Creates a group of render objects in the Caterfoil rendering system, allowing
/// multiple render objects to be combined and managed as a single unit.
///
/// Parameters:
///
/// * `children` : An array of `CaterfoilRenderObject`s that will be grouped
/// together. These objects can be created using functions like `object()` or
/// other `group()` calls.
///
/// Returns a new `CaterfoilRenderObject` that represents the group of render
/// objects.
///
/// Example:
///
/// ```moonbit
/// test "group" {
/// let triangle = @caterfoil.object(data=ObjectData::WithPoints([]))
/// let circle = @caterfoil.object(data=ObjectData::WithPoints([]))
/// let scene = @caterfoil.group([triangle, circle])
/// inspect!(scene, content="[object Object]")
/// }
/// ```
pub fn group(children : Array[CaterfoilRenderObject]) -> CaterfoilRenderObject {
let arr = JsArray::new()
for child in children {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/ffi.mbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
///|
///| a very naive ffi implementation for JS Promise
type Promise

///|
Expand Down
40 changes: 40 additions & 0 deletions src/lib/gpu.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,46 @@ fn ShaderPrimitiveTopology::to_string(self : ShaderPrimitiveTopology) -> String
}

///|
/// Represents the format of vertex attributes in WebGPU shaders. Each variant
/// describes the data type, size, and normalization of vertex data.
///
/// The format strings follow the WebGPU specification naming convention:
///
/// * First part indicates the data type (`uint`, `sint`, `float`) and bit width
/// (8, 16, 32)
/// * Second part (if present) indicates the number of components (x2, x3, x4)
/// * Prefix `unorm` or `snorm` indicates normalized integer formats
/// * Special case `unorm10_10_10_2` for packed 32-bit format with normalized
/// components
///
/// Parameters:
///
/// * `Uint8x2`, `Uint8x4`: Two or four unsigned 8-bit integers
/// * `Sint8x2`, `Sint8x4`: Two or four signed 8-bit integers
/// * `Unorm8x2`, `Unorm8x4`: Two or four normalized unsigned 8-bit integers
/// * `Snorm8x2`, `Snorm8x4`: Two or four normalized signed 8-bit integers
/// * `Uint16x2`, `Uint16x4`: Two or four unsigned 16-bit integers
/// * `Sint16x2`, `Sint16x4`: Two or four signed 16-bit integers
/// * `Unorm16x2`, `Unorm16x4`: Two or four normalized unsigned 16-bit integers
/// * `Snorm16x2`, `Snorm16x4`: Two or four normalized signed 16-bit integers
/// * `Float16x2`, `Float16x4`: Two or four 16-bit floating point numbers
/// * `Float32`, `Float32x2`, `Float32x3`, `Float32x4`: One to four 32-bit
/// floating point numbers
/// * `Uint32`, `Uint32x2`, `Uint32x3`, `Uint32x4`: One to four unsigned 32-bit
/// integers
/// * `Sint32`, `Sint32x2`, `Sint32x3`, `Sint32x4`: One to four signed 32-bit
/// integers
/// * `Unorm10_10_10_2`: Packed format with three 10-bit normalized unsigned
/// integers and one 2-bit normalized unsigned integer
///
/// Example:
///
/// ```moonbit
/// test "GPUVertexFormat" {
/// let format = GPUVertexFormat::Float32x4
/// inspect!(format.to_string(), content="\"float32x4\"")
/// }
/// ```
pub(all) enum GPUVertexFormat {
Uint8x2
Uint8x4
Expand Down
Loading