Skip to content

Commit

Permalink
[Doc] Add docs for GGUI's new features (#5647)
Browse files Browse the repository at this point in the history
* improve docs about new features of GGUI

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* rename wareframe to wireframe

* update some docs

* update docs

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* Update docs/lang/articles/visualization/ggui.md

Co-authored-by: Vissidarte-Herman <[email protected]>

* rename  to

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Vissidarte-Herman <[email protected]>
  • Loading branch information
3 people authored Aug 10, 2022
1 parent 7017c6d commit db3c17d
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 13 deletions.
264 changes: 264 additions & 0 deletions docs/lang/articles/visualization/ggui.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Note that you need to call `point_light()` for every frame. Similar to the `canv
### 3D Geometries

```python
scene.lines(vertices, width, indices, color, per_vertex_color)
scene.mesh(vertices, indices, normals, color, per_vertex_color)
scene.particles(vertices, radius, color, per_vertex_color)
```
Expand All @@ -108,6 +109,220 @@ If a mesh has `num` triangles, the `indices` should be a 1D scalar field with a

`normals` is an optional parameter for `scene.mesh()`.

:::example

1. An example of drawing 3d-lines

```python
import taichi as ti

ti.init(arch=ti.cuda)

N = 10

particles_pos = ti.Vector.field(3, dtype=ti.f32, shape = N)
points_pos = ti.Vector.field(3, dtype=ti.f32, shape = N)

@ti.kernel
def init_points_pos(points : ti.template()):
for i in range(points.shape[0]):
points[i] = [i for j in ti.static(range(3))]

init_points_pos(particles_pos)
init_points_pos(points_pos)

window = ti.ui.Window("Test for Drawing 3d-lines", (768, 768))
canvas = window.get_canvas()
scene = ti.ui.Scene()
camera = ti.ui.make_camera()
camera.position(5, 2, 2)

while window.running:
camera.track_user_inputs(window, movement_speed=0.03, hold_key=ti.ui.RMB)
scene.set_camera(camera)
scene.ambient_light((0.8, 0.8, 0.8))
scene.point_light(pos=(0.5, 1.5, 1.5), color=(1, 1, 1))

scene.particles(particles_pos, color = (0.68, 0.26, 0.19), radius = 0.1)
# Draw 3d-lines in the scene
scene.lines(points_pos, color = (0.28, 0.68, 0.99), width = 5.0)
canvas.scene(scene)
window.show()
```

### Advanced 3d Geometries

```python
scene.lines(vertices, width, indices, color, per_vertex_color, vertex_offset, vertex_count, index_offset, index_count)

scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, vertex_count, index_offset, index_count, show_wireframe)

scene.particles(vertices, radius, color, per_vertex_color, index_offset, index_count)

scene.mesh_instance(vertices, indices, normals, color, per_vertex_color, vertex_offset, vertex_count, index_offset, index_count, show_wireframe)
```

The additional arguments `vertex_offset`, `vertex_count`, `index_offset` and `index_count` control the visible part of the particles and mesh. For the `mesh()` and `mesh_instance()` methods, set whether to show wireframe mode through setting `show_wireframe`.

:::example

1. Example of drawing a part of the mesh/particles

```python
# For particles
# draw the 2-th to 7-th particles
scene.particles(center, radius,
index_offset = 1,
index_count = 6)

# For mesh
# 1. with indices
scene.mesh(vertices, indices,
index_offset = user_defined_first_indices_index,
index_count = user_defined_index_count,
# vertex_offset is set to 0 by default, and it is not necessary
# to assign vertex_offset a value that otherwise you must.
vertex_offset = user_defined_vertex_offset)

# usually used as below:
# draw the 11-th to 111-th mesh vertexes
scene.mesh(vertices, indices,
index_offset = 10,
index_count = 100)

# 2. without indices (similar to the particles' example above)
scene.mesh(vertices,
vertex_offset = user_defined_first_vertex_index,
vertex_count = user_defined_vertex_count)
```
2. An example of drawing part of lines
```python
import taichi as ti

ti.init(arch=ti.cuda)

N = 10

particles_pos = ti.Vector.field(3, dtype=ti.f32, shape = N)
points_pos = ti.Vector.field(3, dtype=ti.f32, shape = N)
points_indices = ti.Vector.field(1, dtype=ti.i32, shape = N)

@ti.kernel
def init_points_pos(points : ti.template()):
for i in range(points.shape[0]):
points[i] = [i for j in range(3)]
# points[i] = [ti.sin(i * 1.0), i * 0.2, ti.cos(i * 1.0)]

@ti.kernel
def init_points_indices(points_indices : ti.template()):
for i in range(N):
points_indices[i][0] = i // 2 + i % 2

init_points_pos(particles_pos)
init_points_pos(points_pos)
init_points_indices(points_indices)

window = ti.ui.Window("Test for Drawing 3d-lines", (768, 768))
canvas = window.get_canvas()
scene = ti.ui.Scene()
camera = ti.ui.make_camera()
camera.position(5, 2, 2)

while window.running:
camera.track_user_inputs(window, movement_speed=0.03, hold_key=ti.ui.RMB)
scene.set_camera(camera)
scene.ambient_light((0.8, 0.8, 0.8))
scene.point_light(pos=(0.5, 1.5, 1.5), color=(1, 1, 1))

scene.particles(particles_pos, color = (0.68, 0.26, 0.19), radius = 0.1)
# Here you will get visible part from the 3rd point with (N - 4) points.
scene.lines(points_pos, color = (0.28, 0.68, 0.99), width = 5.0, vertex_count = N - 4, vertex_offset = 2)
# Using indices to indicate which vertex to use
# scene.lines(points_pos, color = (0.28, 0.68, 0.99), width = 5.0, indices = points_indices)
# Case 1, vertex_count will be changed to N - 2 when drawing.
# scene.lines(points_pos, color = (0.28, 0.68, 0.99), width = 5.0, vertex_count = N - 1, vertex_offset = 0)
# Case 2, vertex_count will be changed to N - 2 when drawing.
# scene.lines(points_pos, color = (0.28, 0.68, 0.99), width = 5.0, vertex_count = N, vertex_offset = 2)
canvas.scene(scene)
window.show()
```

3. Details of mesh instancing
```python
num_instance = 100
m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance)


# For example: An object is scaled by 2, rotated by rotMat, and translated by t = [1, 2, 3], then
#
# The ScaleMatrix is:
# 2, 0, 0, 0
# 0, 2, 0, 0
# 0, 0, 2, 0
# 0, 0, 0, 1
#
# The RotationMatrix is:
# https://en.wikipedia.org/wiki/Rotation_matrix#General_rotations
#
# The TranslationMatrix is:
# 1, 0, 0, 1
# 0, 1, 0, 2
# 0, 0, 1, 3
# 0, 0, 0, 1
#
# Let TransformMatrix = TranslationMatrix @ RotationMatrix @ ScaleMatrix, then the final TransformMatrix is:
# 2 * rotMat00, rotMat01, rotMat02, 1
# rotMat10, 2 * rotMat11, rotMat12, 2
# rotMat20, rotMat21, 2 * rotMat22, 3
# 0, 0, 0, 1
...

# Draw mesh instances (from the 1st instance)
scene.mesh_instance(vertices, indices, transforms = m_transforms, instance_offset = 1)
```
4. Example of setting wireframe mode
```python

window = ti.ui.Window("Display Mesh", (1024, 1024), vsync=True)
canvas = window.get_canvas()
scene = ti.ui.Scene()
camera = ti.ui.make_camera()

# slider_int usage
some_int_type_value = 0
def show_options():
global some_int_type_value

window.GUI.begin("Display Panel", 0.05, 0.1, 0.2, 0.15)
display_mode = window.GUI.slider_int("Value Range", some_int_type_value, 0, 5)
window.GUI.end()

while window.running:

...
# if to show wireframe
scene.mesh_instance(vertices, indices, instance_count = 100 , show_wireframe = True)

canvas.scene(scene)
show_options()
window.show()
```



:::note

If `indices` is not provided, consider using like this:
```python
scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset, vertex_count, wireframe)
```
If `indices` is provided, consider using like this:
```python
scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, index_offset, index_count, wireframe)
```



:::

### Rendering the scene
Expand All @@ -118,6 +333,55 @@ You can render a scene on a canvas.
canvas.scene(scene)
```

### Fetching Color/Depth information

```python
img = window.get_image_buffer()
window.get_depth_buffer(scene_depth)
depth = window.get_depth_buffer_as_numpy()
```

After rendering the current scene, you can fetch the color and depth information of the current scene using `get_image_buffer()` and `get_depth_buffer_as_numpy()`, which copy the gpu data to a NumPy array(cpu).
`get_depth_buffer()` copies the GPU data to a Taichi field (depend on the `arch` you choose) or copies data from GPU to GPU.

:::example

1. Example of fetching color information
```python
window = ti.ui.Window("Test for getting image buffer from ggui", (768, 768), vsync=True)
video_manager = ti.tools.VideoManager("OutputDir")

while window.running:
render_scene()
img = window.get_image_buffer()
video_manager.write_frame(img)
window.show()

video_manager.make_video(gif=True, mp4=True)
```

2. An example of fetching the depth data
```python
window_shape = (720, 1080)
window = ti.ui.Window("Test for copy depth data", window_shape)
canvas = window.get_canvas()
scene = ti.ui.Scene()
camera = ti.ui.make_camera()

# Get the shape of the window
w, h = window.get_window_shape()
# The field/ndarray stores the depth information, and must be of the ti.f32 data type and have a 2d shape.
# or, in other words, the shape must equal the window's shape
scene_depth = ti.ndarray(ti.f32, shape = (w, h))
# scene_depth = ti.field(ti.f32, shape = (w, h))

while window.running:
render()
canvas.scene(scene)
window.get_depth_buffer(scene_depth)
window.show()
```

## GUI components

The design of GGUI's GUI components follows the [Dear ImGui](https://github.com/ocornut/imgui) APIs.
Expand Down
12 changes: 6 additions & 6 deletions python/taichi/ui/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def mesh(self,
vertex_count: int = None,
index_offset: int = 0,
index_count: int = None,
show_wareframe: bool = False):
show_wireframe: bool = False):
"""Declare a mesh inside the scene.
if you indicate the index_offset and index_count, the normals will also
Expand Down Expand Up @@ -206,7 +206,7 @@ def mesh(self,
index_count (int, optional):
only available when `indices` is provided, which is the the number
of vertices to draw.
show_wareframe (bool, optional):
show_wireframe (bool, optional):
turn on/off WareFrame mode.
"""
vbo = get_vbo_field(vertices)
Expand All @@ -229,7 +229,7 @@ def mesh(self,

self.scene.mesh(vbo_info, has_per_vertex_color, indices_info, color,
two_sided, index_count, index_offset, vertex_count,
vertex_offset, show_wareframe)
vertex_offset, show_wireframe)

def mesh_instance(self,
vertices,
Expand All @@ -245,7 +245,7 @@ def mesh_instance(self,
vertex_count: int = None,
index_offset: int = 0,
index_count: int = None,
show_wareframe: bool = False):
show_wireframe: bool = False):
"""Declare mesh instances inside the scene.
If transforms is given, then according to the shape of transforms, it will
Expand Down Expand Up @@ -290,7 +290,7 @@ def mesh_instance(self,
index_count (int, optional):
only available when `indices` is provided, which is the the number
of indices to draw.
show_wareframe (bool, optional):
show_wireframe (bool, optional):
turn on/off WareFrame mode.
"""
vbo = get_vbo_field(vertices)
Expand Down Expand Up @@ -319,7 +319,7 @@ def mesh_instance(self,
color, two_sided, transform_info,
instance_count, instance_offset, index_count,
index_offset, vertex_count, vertex_offset,
show_wareframe)
show_wireframe)

def particles(self,
centers,
Expand Down
4 changes: 2 additions & 2 deletions python/taichi/ui/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,13 @@ def get_depth_buffer_as_numpy(self):
arr_vulkan_layout_to_arr_normal_layout(tmp_depth, depth_numpy_arr)
return depth_numpy_arr

def get_image_buffer(self):
def get_image_buffer_as_numpy(self):
"""Get the window content to numpy array.
Returns:
3d numpy array: [width, height, channels] with (0.0~1.0) float-format color.
"""
return self.window.get_image_buffer()
return self.window.get_image_buffer_as_numpy()

def destroy(self):
"""Destroy this window. The window will be unavailable then.
Expand Down
10 changes: 5 additions & 5 deletions taichi/python/export_ggui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ struct PyScene {
float draw_first_index,
float draw_vertex_count,
float draw_first_vertex,
bool show_wareframe) {
bool show_wireframe) {
RenderableInfo renderable_info;
renderable_info.vbo = vbo;
renderable_info.has_per_vertex_color = has_per_vertex_color;
Expand All @@ -186,7 +186,7 @@ struct PyScene {
renderable_info.draw_first_index = (int)draw_first_index;
renderable_info.draw_vertex_count = (int)draw_vertex_count;
renderable_info.draw_first_vertex = (int)draw_first_vertex;
renderable_info.display_mode = show_wareframe
renderable_info.display_mode = show_wireframe
? taichi::lang::PolygonMode::Line
: taichi::lang::PolygonMode::Fill;

Expand Down Expand Up @@ -231,7 +231,7 @@ struct PyScene {
float draw_first_index,
float draw_vertex_count,
float draw_first_vertex,
bool show_wareframe) {
bool show_wireframe) {
RenderableInfo renderable_info;
renderable_info.vbo = vbo;
renderable_info.has_per_vertex_color = has_per_vertex_color;
Expand All @@ -241,7 +241,7 @@ struct PyScene {
renderable_info.draw_first_index = (int)draw_first_index;
renderable_info.draw_vertex_count = (int)draw_vertex_count;
renderable_info.draw_first_vertex = (int)draw_first_vertex;
renderable_info.display_mode = show_wareframe
renderable_info.display_mode = show_wireframe
? taichi::lang::PolygonMode::Line
: taichi::lang::PolygonMode::Fill;

Expand Down Expand Up @@ -484,7 +484,7 @@ void export_ggui(py::module &m) {
.def("write_image", &PyWindow::write_image)
.def("copy_depth_buffer_to_ndarray",
&PyWindow::copy_depth_buffer_to_ndarray)
.def("get_image_buffer", &PyWindow::get_image_buffer)
.def("get_image_buffer_as_numpy", &PyWindow::get_image_buffer)
.def("is_pressed", &PyWindow::is_pressed)
.def("get_cursor_pos", &PyWindow::py_get_cursor_pos)
.def("is_running", &PyWindow::is_running)
Expand Down

0 comments on commit db3c17d

Please sign in to comment.