From 832f4c087df17d3e61967f4db42564c4b7eec8d8 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 11:47:48 +0800 Subject: [PATCH 01/15] update faq and ggui --- docs/lang/articles/faqs/faq.md | 16 ++++----- docs/lang/articles/visualization/ggui.md | 42 ++++++++++++++---------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/docs/lang/articles/faqs/faq.md b/docs/lang/articles/faqs/faq.md index c1b6d2570cc00..b5f425faadedc 100755 --- a/docs/lang/articles/faqs/faq.md +++ b/docs/lang/articles/faqs/faq.md @@ -14,7 +14,7 @@ You may have a Python interpreter with an unsupported version. Currently, Taichi ### Outer-most loops in Taichi kernels are by default parallel. How can I **serialize** one of them? -A solution is to add an additional *ghost* loop with only one iteration outside the loop you want to serialize. +A solution is to add an additional _ghost_ loop with only one iteration outside the loop you want to serialize. ```python {1} for _ in range(1): # This "ghost" loop will be "parallelized", but with only one thread. Therefore, the containing loop below is serialized. @@ -28,7 +28,6 @@ You can call `ti.sync()`, which is similar to CUDA's `cudaStreamSynchronize()`, `__syncthreads()` is a block-level synchronization barrier, and Taichi provides a synonymous API `ti.simt.block.sync()`, which for now supports CUDA and Vulkan backends only. However, all block-level APIs are still experimental, and you should use this API only when it relates to SIMT operation synchronization and `SharedArray` reads and writes. - ## Data structures ### How do I declare a field with a **dynamic length**? @@ -72,6 +71,9 @@ for i in x: ret = ti.atomic_min(ret, x[i]) ``` +### Does Taichi support `bool` type? + +Currently, Taichi does not support the `bool` type. ### How do I program on less structured data structures (such as graphs and tetrahedral meshes) in Taichi? @@ -92,6 +94,7 @@ Yes, Taichi's Python user-facing APIs should work natively with any language ser Take VSCode as an example, you can install `Python` or `Pylance` extensions to get language support like signature help with type information, code completion etc. If it doesn't work out of box after installing the extension, please make sure the right Python interpreter is selected by: + - invoke command palette (`Shift + Command + P (Mac) / Ctrl + Shift + P (Windows/Linux)`) - find `Python: Select Interpreter` - make sure you select the path to the Python interpreter you're using with a `taichi` package installed @@ -106,15 +109,14 @@ Follow these steps to install Taichi on a server without Internet access. pip download taichi ``` -*This command downloads the wheel package of Taichi and all its dependencies.* +_This command downloads the wheel package of Taichi and all its dependencies._ -2. Copy the downloaded *.whl packages to your local server and install each with the following command. Note that you *must* complete all dependency installation before installing Taichi. +2. Copy the downloaded *.whl packages to your local server and install each with the following command. Note that you *must\* complete all dependency installation before installing Taichi. ``` python -m pip install xxxx.whl ``` - ## Integration with other libs/softwares ### What is the most convenient way to load images into Taichi fields? @@ -147,14 +149,12 @@ while gui.running: Besides, you can also pass numpy arrays or torch tensors into a Taichi kernel as arguments. See [Interacting with external arrays](../basic/external.md) for more details. - ### Can I integrate Taichi and Houdini? The answer is an unequivocal Yes! Our contributors managed to embed [taichi_elements](https://github.com/taichi-dev/taichi_elements), a multi-material continuum physics engine, into Houdini as an extension, combining Houdini's flexibility in preprocessing with Taichi's strength in high-performance computation. You can follow the instructions provided [here](https://github.com/taichi-dev/taichi_houdini). - ## Precision related ### How do I accurately initialize a vector or matrix with `f64` precision when my default floating-point precision (`default_fp`) is `f32`? @@ -328,7 +328,7 @@ And data in fields `x` and `y` can be found in files **x.txt** and **y.txt**, re Taichi fields adopt a different coordinate system from NumPy's arrays for storing images. In a Taichi field, [0,0] denotes the pixel at the lower left corner of the image; the first axis extends to the right of the image; the second axis extends to the top. -This is different from the usual convention taken by popular third-party libs like `matplotlib` or `opencv`, where [0, 0] denotes the pixel at the top left corner, the first axis extends down to the bottom of the image, and the second axis extends to the right. +This is different from the usual convention taken by popular third-party libs like `matplotlib` or `opencv`, where [0, 0] denotes the pixel at the top left corner, the first axis extends down to the bottom of the image, and the second axis extends to the right. Therefore, to display a NumPy array using `matplotlb`'s `imshow()`, you must rotate it 90 degrees clockwise. diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index edf166162c7a9..464dcbdd04725 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -4,10 +4,10 @@ sidebar_position: 2 # A New UI system: GGUI -| **Category** | **Prerequisites** | -| ------------ | ------------------------------------------------------------ | -| OS | Windows / Linux / Mac OS X | -| Backend | x64 / CUDA / Vulkan | +| **Category** | **Prerequisites** | +| ------------ | -------------------------- | +| OS | Windows / Linux / Mac OS X | +| Backend | x64 / CUDA / Vulkan | Starting from v0.8.0, Taichi adds a new UI system GGUI. The new system uses GPU for rendering, making it much faster to render 3D scenes. That is why this new system gets its name as GGUI. This document describes the APIs that it provides. @@ -15,7 +15,6 @@ Starting from v0.8.0, Taichi adds a new UI system GGUI. The new system uses GPU If you choose Vulkan as backend, ensure that you [install the Vulkan environment](https://vulkan.lunarg.com/sdk/home). ::: - :::note It is recommended that you familiarize yourself with GGUI through the examples in `examples/ggui_examples`. ::: @@ -25,15 +24,18 @@ It is recommended that you familiarize yourself with GGUI through the examples i `ti.ui.Window(name, res)` creates a window. ```python -window = ti.ui.Window('Window Title', res = (640, 360), pos = (150, 150)) +window = ti.ui.Window(name='Window Title', res = (640, 360), fps_limit=200, pos = (150, 150)) ``` -The argument `res` means resulotion(width and height) of the window, `pos` means the position of the window which origins from the left-top of your main screen. -The following three types of objects can be displayed on a `ti.ui.Window`: +- The `name` parameter sets the title of the window. +- The `res` parameter specifies the resolution (width and height) of the window. +- The `fps_limit` parameter sets the maximum frames per second (FPS) for the window. +- The `pos` parameter specifies the position of the window with respect to the top-left corner of the main screen. + +A ti.ui.Window can display three types of objects: -- 2D Canvas, which can be used to draw simple 2D geometries such as circles and triangles. -- 3D Scene, which can be used to render 3D meshes and particles, with a configurable camera and light sources. -- Immediate mode GUI components, for example buttons and textboxes. +- 2D Canvas, which is used to draw simple 2D geometries like circles and triangles.+ 3D Scene, which is used to render 3D meshes and particles, and provides configurable camera and light sources. +- Immediate mode GUI components, such as buttons and textboxes. ## 2D Canvas @@ -106,7 +108,7 @@ The positions/centers of geometries should be in the world-space coordinates. :::note -If a mesh has `num` triangles, the `indices` should be a 1D scalar field with a shape `(num * 3)`, *not* a vector field. +If a mesh has `num` triangles, the `indices` should be a 1D scalar field with a shape `(num * 3)`, _not_ a vector field. `normals` is an optional parameter for `scene.mesh()`. @@ -196,7 +198,9 @@ 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 @@ -249,6 +253,7 @@ while window.running: ``` 3. Details of mesh instancing + ```python num_instance = 100 m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance) @@ -281,7 +286,9 @@ m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance) # 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) @@ -309,21 +316,20 @@ while window.running: 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 @@ -348,6 +354,7 @@ After rendering the current scene, you can fetch the color and depth information :::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") @@ -362,6 +369,7 @@ 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) @@ -405,7 +413,7 @@ Call `show()` to show a window. window.show() ``` -Call this method *only* at the end of the render loop for each frame. +Call this method _only_ at the end of the render loop for each frame. ## User input processing From 566a015d00ec67d4a2d4b79b29a7781c35333770 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 11:53:27 +0800 Subject: [PATCH 02/15] update faq and ggui --- docs/lang/articles/visualization/ggui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 464dcbdd04725..7266316a1f035 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -467,7 +467,7 @@ To write the current frame in the window to an image file: window.save_image(filename) ``` -Note that you must call `window.save_image()` before calling `window.show()`. +Note that you _must_ call `window.save_image()` before calling `window.show()`. ## Off-screen rendering From 528d6a8383d0c5d8271e46add2208488a6cfbf19 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 12:05:52 +0800 Subject: [PATCH 03/15] update faq and ggui --- docs/cover-in-ci.lst | 2 ++ docs/lang/articles/faqs/faq.md | 2 +- docs/lang/articles/visualization/ggui.md | 32 ++++++++++++------------ 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/docs/cover-in-ci.lst b/docs/cover-in-ci.lst index bb633530f520a..420ae0ee214c6 100644 --- a/docs/cover-in-ci.lst +++ b/docs/cover-in-ci.lst @@ -26,6 +26,8 @@ docs/lang/articles/kernels/kernel_sync.md docs/lang/articles/performance_tuning/performance.md docs/lang/articles/performance_tuning/profiler.md docs/lang/articles/reference/global_settings.md +docs/lang/articles/faqs/faq.md +docs/lang/articles/visualization/ggui.md docs/lang/articles/visualization/gui_system.md docs/rfcs/20220410-rfc-process.md docs/rfcs/yyyymmdd-rfc-template.md diff --git a/docs/lang/articles/faqs/faq.md b/docs/lang/articles/faqs/faq.md index b5f425faadedc..9c9ae7ccfe2d7 100755 --- a/docs/lang/articles/faqs/faq.md +++ b/docs/lang/articles/faqs/faq.md @@ -196,7 +196,7 @@ A Taichi kernel **cannot** take a Python list directly. You need to use NumPy ar For example, the following code snippet does not work: -```python +```python skip-ci:Error import taichi as ti import numpy as np ti.init() diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 7266316a1f035..479561232e6c7 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -43,13 +43,13 @@ A ti.ui.Window can display three types of objects: The following code retrieves a `Canvas` object that covers the entire window. -```python +```python cont canvas = window.get_canvas() ``` ### Draw on the canvas -```python +```python cont canvas.set_background_color(color) canvas.triangles(vertices, color, indices, per_vertex_color) canvas.circles(vertices, radius, color, per_vertex_color) @@ -73,7 +73,7 @@ scene = ti.ui.Scene() ### Configure camera -```python +```python cont camera = ti.ui.Camera() camera.position(pos) camera.lookat(pos) @@ -88,7 +88,7 @@ scene.set_camera(camera) Call `point_light()` to add a point light to the scene. -```python +```python cont scene.point_light(pos, color) ``` @@ -96,7 +96,7 @@ Note that you need to call `point_light()` for every frame. Similar to the `canv ### 3D Geometries -```python +```python cont 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) @@ -155,7 +155,7 @@ while window.running: ### Advanced 3d Geometries -```python +```python cont 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) @@ -171,7 +171,7 @@ The additional arguments `vertex_offset`, `vertex_count`, `index_offset` and `in 1. Example of drawing a part of the mesh/particles -```python +```python cont # For particles # draw the 2-th to 7-th particles scene.particles(center, radius, @@ -254,7 +254,7 @@ while window.running: 3. Details of mesh instancing -```python +```python cont num_instance = 100 m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance) @@ -289,7 +289,7 @@ scene.mesh_instance(vertices, indices, transforms = m_transforms, instance_offse 4. Example of setting wireframe mode -```python +```python cont window = ti.ui.Window("Display Mesh", (1024, 1024), vsync=True) canvas = window.get_canvas() @@ -320,13 +320,13 @@ while window.running: If `indices` is not provided, consider using like this: -```python +```python cont scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset, vertex_count, wireframe) ``` If `indices` is provided, consider using like this: -```python +```python cont scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, index_offset, index_count, wireframe) ``` @@ -336,13 +336,13 @@ scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, i You can render a scene on a canvas. -```python +```python cont canvas.scene(scene) ``` ### Fetching Color/Depth information -```python +```python cont img = window.get_image_buffer_as_numpy() window.get_depth_buffer(scene_depth) depth = window.get_depth_buffer_as_numpy() @@ -395,7 +395,7 @@ while window.running: The design of GGUI's GUI components follows the [Dear ImGui](https://github.com/ocornut/imgui) APIs. -```python +```python cont gui = window.get_gui() with gui.sub_window(name, x, y, width, height): gui.text(text) @@ -409,7 +409,7 @@ with gui.sub_window(name, x, y, width, height): Call `show()` to show a window. ```python -... +... cont window.show() ``` @@ -463,7 +463,7 @@ while window.running: To write the current frame in the window to an image file: -```python +```python skip-ci window.save_image(filename) ``` From 496821c1e4a62d50b2981a30bfd4478ef666403b Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 16:54:34 +0800 Subject: [PATCH 04/15] fix-ci --- docs/conftest.py | 17 +++++--- docs/lang/articles/faqs/faq.md | 23 ++++++++--- docs/lang/articles/visualization/ggui.md | 50 +++++++++++------------- 3 files changed, 52 insertions(+), 38 deletions(-) diff --git a/docs/conftest.py b/docs/conftest.py index 206c49e362aaf..ef694ba52d0ea 100644 --- a/docs/conftest.py +++ b/docs/conftest.py @@ -1,20 +1,20 @@ # -*- coding: utf-8 -*- # -- stdlib -- -import linecache -import sys -import uuid -import warnings from dataclasses import dataclass from functools import wraps from itertools import count from typing import List, Optional +import linecache +import sys +import uuid +import warnings # -- third party -- +from pytest import ExceptionInfo import marko +import matplotlib.pyplot as plt import pytest -from pytest import ExceptionInfo - import taichi as ti # -- own -- @@ -103,6 +103,11 @@ def show(orig, self, *args, **kwargs): return orig(self, *args, *kwargs) +@hook(plt) +def show(orig): + return + + ti.GUI._frames_remaining = 10 ti.GUI.running = property(lambda self: self._frames_remaining <= 0) ti.ui.Window._frames_remaining = 10 diff --git a/docs/lang/articles/faqs/faq.md b/docs/lang/articles/faqs/faq.md index 9c9ae7ccfe2d7..1eca799465263 100755 --- a/docs/lang/articles/faqs/faq.md +++ b/docs/lang/articles/faqs/faq.md @@ -48,6 +48,9 @@ Direct value assignments lead to semantic ambiguity. For example, `a = b` can me You can swap two fields in the Taichi scope using a struct for: ```python +a = ti.field(ti.i32, 32) +b = ti.field(ti.i32, 32) + @ti.func def field_copy(src: ti.template(), dst: ti.template()): for I in ti.grouped(src): @@ -64,11 +67,21 @@ test() ### How do I compute the minimum/maximum of a field? -Use `ti.automic.min/max` instead of `ti.min/max`. For example: +Use `ti.atomic_min/atomic_max` instead of `ti.min/max`. For example: ```python -for i in x: - ret = ti.atomic_min(ret, x[i]) +x = ti.field(ti.f32, 32) + +@ti.kernel +def x_min() -> ti.f32: + ret: ti.f32 = x[0] + + for i in x: + ret = ti.atomic_min(ret, x[i]) + + return ret + +x_min() ``` ### Does Taichi support `bool` type? @@ -234,12 +247,12 @@ Taichi's GUI system can display colors when the field it accepts is a 3D vector To enable color mapping, convert `ti.field` into a NumPy array and call Matplotlib's colormap (`cm`), as shown in the following example: ```python -gui = ti.GUI(f'Re = {un * lx / mu:4.0f} V_mag', (nx+1, ny+1)) +gui = ti.GUI(f'Re = {un * lx / mu:4.0f} V_mag', (nx+1, ny+1)) step = 0 while gui.running: # Main loop print(f'>>> step : {step:<6d}, time : {step*dt:<6.3f} sec') substep() - if step % 10 = 1: + if step % 10 == 1: V_np = V_mag.to_numpy() V_img = cm.jet(V_np) gui.set_image(V_img) # Plot the velocity magnitude contour diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 479561232e6c7..70b5ca6e8f954 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -32,7 +32,7 @@ window = ti.ui.Window(name='Window Title', res = (640, 360), fps_limit=200, pos - The `fps_limit` parameter sets the maximum frames per second (FPS) for the window. - The `pos` parameter specifies the position of the window with respect to the top-left corner of the main screen. -A ti.ui.Window can display three types of objects: +A `ti.ui.Window` can display three types of objects: - 2D Canvas, which is used to draw simple 2D geometries like circles and triangles.+ 3D Scene, which is used to render 3D meshes and particles, and provides configurable camera and light sources. - Immediate mode GUI components, such as buttons and textboxes. @@ -73,7 +73,7 @@ scene = ti.ui.Scene() ### Configure camera -```python cont +```python skip-ci camera = ti.ui.Camera() camera.position(pos) camera.lookat(pos) @@ -96,7 +96,7 @@ Note that you need to call `point_light()` for every frame. Similar to the `canv ### 3D Geometries -```python cont +```python skip-ci 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) @@ -155,7 +155,7 @@ while window.running: ### Advanced 3d Geometries -```python cont +```python skip-ci 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) @@ -171,32 +171,29 @@ The additional arguments `vertex_offset`, `vertex_count`, `index_offset` and `in 1. Example of drawing a part of the mesh/particles -```python cont +```python skip-ci # For particles # draw the 2-th to 7-th particles -scene.particles(center, radius, -index_offset = 1, -index_count = 6) +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) - +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) +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) +scene.mesh( + vertices, + vertex_offset=user_defined_first_vertex_index, + vertex_count=user_defined_vertex_count + ) ``` 2. An example of drawing part of lines @@ -320,13 +317,13 @@ while window.running: If `indices` is not provided, consider using like this: -```python cont +```python skip-ci scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset, vertex_count, wireframe) ``` If `indices` is provided, consider using like this: -```python cont +```python skip-ci scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, index_offset, index_count, wireframe) ``` @@ -395,7 +392,7 @@ while window.running: The design of GGUI's GUI components follows the [Dear ImGui](https://github.com/ocornut/imgui) APIs. -```python cont +```python skip-ci gui = window.get_gui() with gui.sub_window(name, x, y, width, height): gui.text(text) @@ -408,8 +405,7 @@ with gui.sub_window(name, x, y, width, height): Call `show()` to show a window. -```python -... cont +```python cont window.show() ``` @@ -419,7 +415,7 @@ Call this method _only_ at the end of the render loop for each frame. To retrieve the events that have occurred since the last method call: -```python +```python cont events = window.get_events() ``` From 59ec5cb3a6d065ec0f5cd2154fc557819a09bd2f Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 17:27:39 +0800 Subject: [PATCH 05/15] fix-ci --- docs/lang/articles/faqs/faq.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/lang/articles/faqs/faq.md b/docs/lang/articles/faqs/faq.md index 1eca799465263..a0fa93d8a23c8 100755 --- a/docs/lang/articles/faqs/faq.md +++ b/docs/lang/articles/faqs/faq.md @@ -246,18 +246,16 @@ Taichi's GUI system can display colors when the field it accepts is a 3D vector To enable color mapping, convert `ti.field` into a NumPy array and call Matplotlib's colormap (`cm`), as shown in the following example: -```python -gui = ti.GUI(f'Re = {un * lx / mu:4.0f} V_mag', (nx+1, ny+1)) +```python skip-ci +pixels = ti.Vector.field(3, shape=(w, h)) +gui = ti.GUI(f'Window title', (w, h)) step = 0 while gui.running: # Main loop - print(f'>>> step : {step:<6d}, time : {step*dt:<6.3f} sec') - substep() - if step % 10 == 1: - V_np = V_mag.to_numpy() - V_img = cm.jet(V_np) - gui.set_image(V_img) # Plot the velocity magnitude contour - gui.show() - step += 1 + simulate_one_substep(pixels) + img = pixels.to_numpy() + img = cm.jet(img) + gui.set_image(img) + gui.show() ``` ## Objective-oriented programming From 0f5fb38272561bd82ecbe54cc58eaca754f03490 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 17:42:54 +0800 Subject: [PATCH 06/15] fix-ci --- docs/lang/articles/visualization/ggui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 70b5ca6e8f954..5024b1264b3ab 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -49,7 +49,7 @@ canvas = window.get_canvas() ### Draw on the canvas -```python cont +```python skip-ci canvas.set_background_color(color) canvas.triangles(vertices, color, indices, per_vertex_color) canvas.circles(vertices, radius, color, per_vertex_color) From eeea41df02aa6609324eeec66ade0e451fa74726 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 17:47:15 +0800 Subject: [PATCH 07/15] fix-ci --- docs/lang/articles/faqs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/lang/articles/faqs/faq.md b/docs/lang/articles/faqs/faq.md index a0fa93d8a23c8..2938afc06895e 100755 --- a/docs/lang/articles/faqs/faq.md +++ b/docs/lang/articles/faqs/faq.md @@ -246,7 +246,7 @@ Taichi's GUI system can display colors when the field it accepts is a 3D vector To enable color mapping, convert `ti.field` into a NumPy array and call Matplotlib's colormap (`cm`), as shown in the following example: -```python skip-ci +```python skip-ci:Trivial pixels = ti.Vector.field(3, shape=(w, h)) gui = ti.GUI(f'Window title', (w, h)) step = 0 From 3a2f8b463f39f6d2e04c07e4761e3fd942316f78 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 18:08:35 +0800 Subject: [PATCH 08/15] fix-ci --- docs/lang/articles/visualization/ggui.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 5024b1264b3ab..474e54c31ff94 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -73,7 +73,7 @@ scene = ti.ui.Scene() ### Configure camera -```python skip-ci +```python skip-ci:Trivial camera = ti.ui.Camera() camera.position(pos) camera.lookat(pos) @@ -96,7 +96,7 @@ Note that you need to call `point_light()` for every frame. Similar to the `canv ### 3D Geometries -```python skip-ci +```python skip-ci:Trivial 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) @@ -155,7 +155,7 @@ while window.running: ### Advanced 3d Geometries -```python skip-ci +```python skip-ci:Trivial 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) From 27a0b8fafba81e9baf577100caa622dd1ae2c9bd Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 18:10:31 +0800 Subject: [PATCH 09/15] fix-ci --- docs/lang/articles/visualization/ggui.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 474e54c31ff94..eb0f91ac398b8 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -49,7 +49,7 @@ canvas = window.get_canvas() ### Draw on the canvas -```python skip-ci +```python skip-ci:Trivial canvas.set_background_color(color) canvas.triangles(vertices, color, indices, per_vertex_color) canvas.circles(vertices, radius, color, per_vertex_color) @@ -171,7 +171,7 @@ The additional arguments `vertex_offset`, `vertex_count`, `index_offset` and `in 1. Example of drawing a part of the mesh/particles -```python skip-ci +```python skip-ci:Trivial # For particles # draw the 2-th to 7-th particles scene.particles(center, radius, index_offset = 1, index_count = 6) @@ -317,13 +317,13 @@ while window.running: If `indices` is not provided, consider using like this: -```python skip-ci +```python skip-ci:Trivial scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset, vertex_count, wireframe) ``` If `indices` is provided, consider using like this: -```python skip-ci +```python skip-ci:Trivial scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, index_offset, index_count, wireframe) ``` @@ -392,7 +392,7 @@ while window.running: The design of GGUI's GUI components follows the [Dear ImGui](https://github.com/ocornut/imgui) APIs. -```python skip-ci +```python skip-ci:Trivial gui = window.get_gui() with gui.sub_window(name, x, y, width, height): gui.text(text) @@ -459,7 +459,7 @@ while window.running: To write the current frame in the window to an image file: -```python skip-ci +```python skip-ci:Trivial window.save_image(filename) ``` From ca54164eadf1e364e4ace822a896bf84fca9063c Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 18:16:40 +0800 Subject: [PATCH 10/15] fix-ci --- docs/lang/articles/visualization/ggui.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index eb0f91ac398b8..c29f9203c547c 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -251,7 +251,7 @@ while window.running: 3. Details of mesh instancing -```python cont +```python skip-ci:Trivial num_instance = 100 m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance) @@ -352,7 +352,7 @@ After rendering the current scene, you can fetch the color and depth information 1. Example of fetching color information -```python +```python skip-ci:Trivial window = ti.ui.Window("Test for getting image buffer from ggui", (768, 768), vsync=True) video_manager = ti.tools.VideoManager("OutputDir") From 5f54bc218ed69c6dbc1daacf636a2802d23e5330 Mon Sep 17 00:00:00 2001 From: neozhaoliang Date: Fri, 21 Apr 2023 18:24:41 +0800 Subject: [PATCH 11/15] fix-ci --- docs/lang/articles/visualization/ggui.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index c29f9203c547c..a6c1ba7b2ea96 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -434,7 +434,7 @@ To check if a key is pressed: The following is a user input processing example from [**mpm128**](https://github.com/taichi-dev/taichi/blob/master/python/taichi/examples/ggui_examples/mpm128_ggui.py): -```python +```python cont while window.running: # keyboard event processing if window.get_event(ti.ui.PRESS): From 82ef981d38bf860ca7249ae28d6c0389d3c9dbee Mon Sep 17 00:00:00 2001 From: Proton Date: Sun, 23 Apr 2023 14:23:46 +0800 Subject: [PATCH 12/15] wip --- docs/conftest.py | 26 ++++- docs/lang/articles/visualization/ggui.md | 118 +++++++++++++++-------- 2 files changed, 97 insertions(+), 47 deletions(-) diff --git a/docs/conftest.py b/docs/conftest.py index ef694ba52d0ea..c6830d7157376 100644 --- a/docs/conftest.py +++ b/docs/conftest.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from functools import wraps from itertools import count -from typing import List, Optional +from typing import List, Optional, Dict import linecache import sys import uuid @@ -95,7 +95,7 @@ def show(orig, self, *args, **kwargs): @hook(ti.ui.Window) def show(orig, self, *args, **kwargs): if not self.running: - self.close() + self.destroy() return self._frames_remaining -= 1 @@ -119,6 +119,7 @@ class PythonSnippet: name: str code: str skip: Optional[str] + per_file_preludes: Dict[str, str] known_error: bool = False preludes: Optional[List[str]] = None @@ -136,13 +137,21 @@ def collect(self): if bad_tags: raise ValueError(f"Invalid language tag {bad_tags} in markdown file") + per_file_preludes = {} + spec = None for name, c in codes: if not c.lang == "python": continue extra = dict((v.split(":", 1) + [None])[:2] for v in c.extra.split()) code = c.children[0].children - if "cont" in extra: + if "as-prelude" in extra: + assert "cont" not in extra + assert "preludes" not in extra + prelude_name = extra["as-prelude"] + assert prelude_name not in per_file_preludes, f"Duplicate prelude {prelude_name}" + per_file_preludes[prelude_name] = code + elif "cont" in extra: assert spec is not None spec.code += code else: @@ -158,6 +167,7 @@ def collect(self): code=code, skip=extra.get("skip-ci"), known_error="known-error" in extra, + per_file_preludes=per_file_preludes, preludes=preludes, ) @@ -220,8 +230,14 @@ def runtest(self): else: preludes.insert(0, "init") - source = [PRELUDES[p] for p in preludes] + [spec.code] - source = "".join(source) + snippets = [] + for p in preludes: + c = spec.per_file_preludes.get(p) + c = c or PRELUDES.get(p) + assert c is not None, f"Unknown prelude {p}" + snippets.append(c) + snippets.append(spec.code) + source = "".join(snippets) fn = f"" code = compile(source, fn, "exec") linecache.cache[fn] = ( diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index a6c1ba7b2ea96..e504357adf14d 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -19,11 +19,25 @@ If you choose Vulkan as backend, ensure that you [install the Vulkan environment It is recommended that you familiarize yourself with GGUI through the examples in `examples/ggui_examples`. ::: +:::note +The variables referenced in code snippets below are define like this: + +```python as-prelude:vars +vertices = ti.Vector.field(2, ti.f32, shape=200) +vertices_3d = ti.Vector.field(3, ti.f32, shape=200) +indices = ti.field(ti.i32, shape=200 * 3) +normals = ti.Vector.field(3, ti.f32, shape=200) +per_vertex_color = ti.Vector.field(3, ti.f32, shape=200) + +color = (0.5, 0.5, 0.5) +``` +::: + ## Create a window `ti.ui.Window(name, res)` creates a window. -```python +```python preludes:vars window = ti.ui.Window(name='Window Title', res = (640, 360), fps_limit=200, pos = (150, 150)) ``` @@ -49,12 +63,16 @@ canvas = window.get_canvas() ### Draw on the canvas -```python skip-ci:Trivial +```python cont canvas.set_background_color(color) canvas.triangles(vertices, color, indices, per_vertex_color) + +radius = 5 canvas.circles(vertices, radius, color, per_vertex_color) + +width = 2 canvas.lines(vertices, width, indices, color, per_vertex_color) -canvas.set_image(image) +canvas.set_image(window.get_image_buffer_as_numpy()) ``` The arguments `vertices`, `indices`, `per_vertex_color`, and `image` must be Taichi fields. If `per_vertex_color` is provided, `color` is ignored. @@ -67,18 +85,18 @@ The canvas is cleared after every frame. Always call these methods within the re ### Create a scene -```python +```python cont scene = ti.ui.Scene() ``` ### Configure camera -```python skip-ci:Trivial +```python cont camera = ti.ui.Camera() -camera.position(pos) -camera.lookat(pos) -camera.up(dir) -camera.projection_mode(mode) +camera.position(1, 2, 3) # x, y, z +camera.lookat(4, 5, 6) +camera.up(0, 1, 0) +camera.projection_mode(ti.ui.ProjectionMode.Perspective) scene.set_camera(camera) ``` @@ -89,16 +107,16 @@ scene.set_camera(camera) Call `point_light()` to add a point light to the scene. ```python cont -scene.point_light(pos, color) +scene.point_light(pos=(1, 2, 3), color=(0.5, 0.5, 0.5)) ``` Note that you need to call `point_light()` for every frame. Similar to the `canvas()` methods, call this method within your render loop. ### 3D Geometries -```python skip-ci:Trivial +```python cont scene.lines(vertices, width, indices, color, per_vertex_color) -scene.mesh(vertices, indices, normals, color, per_vertex_color) +scene.mesh(vertices_3d, indices, normals, color, per_vertex_color) scene.particles(vertices, radius, color, per_vertex_color) ``` @@ -155,14 +173,18 @@ while window.running: ### Advanced 3d Geometries -```python skip-ci:Trivial -scene.lines(vertices, width, indices, color, per_vertex_color, vertex_offset, vertex_count, index_offset, index_count) +```python preludes:vars +scene = ti.ui.Scene() +width = 2 +radius = 5 + +scene.lines(vertices, width, indices, color, per_vertex_color, vertex_offset=0, vertex_count=10, index_offset=0, index_count=10) -scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, vertex_count, index_offset, index_count, show_wireframe) +scene.mesh(vertices_3d, indices, normals, color, per_vertex_color, vertex_offset=0, vertex_count=10, index_offset=0, index_count=10, show_wireframe=True) -scene.particles(vertices, radius, color, per_vertex_color, index_offset, index_count) +scene.particles(vertices, radius, color, per_vertex_color, index_offset=0, index_count=10) -scene.mesh_instance(vertices, indices, normals, color, per_vertex_color, vertex_offset, vertex_count, index_offset, index_count, show_wireframe) +scene.mesh_instance(vertices_3d, indices, normals, color, per_vertex_color, vertex_offset=0, vertex_count=10, index_offset=0, index_count=10, show_wireframe=True) ``` 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`. @@ -171,28 +193,33 @@ The additional arguments `vertex_offset`, `vertex_count`, `index_offset` and `in 1. Example of drawing a part of the mesh/particles -```python skip-ci:Trivial +```python preludes:vars +scene = ti.ui.Scene() + +center = ti.Vector.field(3, ti.f32, shape=10) + # For particles # draw the 2-th to 7-th particles -scene.particles(center, radius, index_offset = 1, index_count = 6) +scene.particles(center, radius=1, 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, + vertices_3d, indices, index_offset=1, index_count=3, # 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 + vertex_offset = 1 ) + # usually used as below: # draw the 11-th to 111-th mesh vertexes -scene.mesh(vertices, indices, index_offset=10, index_count=100) +scene.mesh(vertices_3d, 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 + vertices_3d, + vertex_offset=2, # user defined first vertex index + vertex_count=3, # user defined vertex count ) ``` @@ -251,8 +278,10 @@ while window.running: 3. Details of mesh instancing -```python skip-ci:Trivial -num_instance = 100 +```python preludes:vars +scene = ti.ui.Scene() + +num_instance = 100 m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance) @@ -281,13 +310,12 @@ m_transforms = ti.Matrix.field(4, 4, dtype = ti.f32, shape = num_instance) ... # Draw mesh instances (from the 1st instance) -scene.mesh_instance(vertices, indices, transforms = m_transforms, instance_offset = 1) +scene.mesh_instance(vertices_3d, indices, transforms = m_transforms, instance_offset = 1) ``` 4. Example of setting wireframe mode -```python cont - +```python preludes:vars window = ti.ui.Window("Display Mesh", (1024, 1024), vsync=True) canvas = window.get_canvas() scene = ti.ui.Scene() @@ -306,7 +334,7 @@ while window.running: ... # if to show wireframe - scene.mesh_instance(vertices, indices, instance_count = 100 , show_wireframe = True) + scene.mesh_instance(vertices_3d, indices, instance_count = 100 , show_wireframe = True) canvas.scene(scene) show_options() @@ -317,14 +345,15 @@ while window.running: If `indices` is not provided, consider using like this: -```python skip-ci:Trivial -scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset, vertex_count, wireframe) +```python preludes:vars +scene = ti.ui.Scene() +scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset=0, vertex_count=50, show_wireframe=True) ``` If `indices` is provided, consider using like this: -```python skip-ci:Trivial -scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, index_offset, index_count, wireframe) +```python cont +scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset=0, index_offset=0, index_count=50, show_wireframe=True) ``` ::: @@ -334,6 +363,8 @@ scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset, i You can render a scene on a canvas. ```python cont +window = ti.ui.Window(name='Title', res=(640, 360)) +canvas = window.get_canvas() canvas.scene(scene) ``` @@ -392,13 +423,16 @@ while window.running: The design of GGUI's GUI components follows the [Dear ImGui](https://github.com/ocornut/imgui) APIs. -```python skip-ci:Trivial +```python +window = ti.ui.Window("Test for GUI", res=(512, 512)) gui = window.get_gui() -with gui.sub_window(name, x, y, width, height): - gui.text(text) - is_clicked = gui.button(name) - new_value = gui.slider_float(name, old_value, min_value, max_value) - new_color = gui.color_edit_3(name, old_color) +value = 0 +color = (1.0, 1.0, 1.0) +with gui.sub_window("Sub Window", x=10, y=10, width=300, height=100): + gui.text("text") + is_clicked = gui.button("name") + value = gui.slider_float("name1", value, minimum=0, maximum=100) + color = gui.color_edit_3("name2", color) ``` ## Show a window @@ -459,7 +493,7 @@ while window.running: To write the current frame in the window to an image file: -```python skip-ci:Trivial +```python cont window.save_image(filename) ``` From a6b739673679f11f42bc4f6e2484845bb53ec5e4 Mon Sep 17 00:00:00 2001 From: Proton Date: Sun, 23 Apr 2023 15:42:02 +0800 Subject: [PATCH 13/15] wip --- docs/conftest.py | 26 ++++++++++++++++++++++-- docs/lang/articles/visualization/ggui.md | 11 +++++++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/docs/conftest.py b/docs/conftest.py index c6830d7157376..132e34a280bc0 100644 --- a/docs/conftest.py +++ b/docs/conftest.py @@ -92,6 +92,9 @@ def show(orig, self, *args, **kwargs): return orig(self, *args, *kwargs) +GGUI_WINDOW = None + + @hook(ti.ui.Window) def show(orig, self, *args, **kwargs): if not self.running: @@ -103,15 +106,34 @@ def show(orig, self, *args, **kwargs): return orig(self, *args, *kwargs) +@hook(ti.ui.Window) +def __init__(orig, self, *args, **kwargs): + global GGUI_WINDOW + if GGUI_WINDOW: + GGUI_WINDOW.destroy() + + assert not GGUI_WINDOW + orig(self, *args, **kwargs) + GGUI_WINDOW = self + + +@hook(ti.ui.Window) +def destroy(orig, self): + global GGUI_WINDOW + assert self is GGUI_WINDOW + GGUI_WINDOW = None + return orig(self) + + @hook(plt) def show(orig): return ti.GUI._frames_remaining = 10 -ti.GUI.running = property(lambda self: self._frames_remaining <= 0) +ti.GUI.running = property(lambda self: self._frames_remaining > 0) ti.ui.Window._frames_remaining = 10 -ti.ui.Window.running = property(lambda self: self._frames_remaining <= 0) +ti.ui.Window.running = property(lambda self: self._frames_remaining > 0) @dataclass diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index e504357adf14d..1acc02e453db4 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -388,7 +388,7 @@ window = ti.ui.Window("Test for getting image buffer from ggui", (768, 768), vsy video_manager = ti.tools.VideoManager("OutputDir") while window.running: - render_scene() + # render_scene() img = window.get_image_buffer_as_numpy() video_manager.write_frame(img) window.show() @@ -413,7 +413,7 @@ scene_depth = ti.ndarray(ti.f32, shape = (w, h)) # scene_depth = ti.field(ti.f32, shape = (w, h)) while window.running: - render() + # render() canvas.scene(scene) window.get_depth_buffer(scene_depth) window.show() @@ -469,6 +469,9 @@ To check if a key is pressed: The following is a user input processing example from [**mpm128**](https://github.com/taichi-dev/taichi/blob/master/python/taichi/examples/ggui_examples/mpm128_ggui.py): ```python cont +gravity = ti.Vector.field(2, ti.f32, shape=()) +attractor_strength = ti.field(ti.f32, shape=()) + while window.running: # keyboard event processing if window.get_event(ti.ui.PRESS): @@ -487,6 +490,8 @@ while window.running: attractor_strength[None] = 1 if window.is_pressed(ti.ui.RMB): attractor_strength[None] = -1 + + window.show() ``` ## Image I/O @@ -494,7 +499,7 @@ while window.running: To write the current frame in the window to an image file: ```python cont -window.save_image(filename) +window.save_image('frame.png') ``` Note that you _must_ call `window.save_image()` before calling `window.show()`. From bba3387f7106c70c99bfef36102c1a682669b1df Mon Sep 17 00:00:00 2001 From: Proton Date: Sun, 23 Apr 2023 16:26:26 +0800 Subject: [PATCH 14/15] wip --- docs/conftest.py | 51 ++++++++++++++----- docs/lang/articles/faqs/faq.md | 14 +++-- .../lang/articles/visualization/gui_system.md | 14 +++-- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/docs/conftest.py b/docs/conftest.py index 132e34a280bc0..71b4ec0c98e6e 100644 --- a/docs/conftest.py +++ b/docs/conftest.py @@ -4,6 +4,7 @@ from dataclasses import dataclass from functools import wraps from itertools import count +from re import M from typing import List, Optional, Dict import linecache import sys @@ -58,12 +59,6 @@ M = 8 """ -PRELUDES[ - "gui" -] = """ -gui = ti.GUI('Title', res=(400, 400)) -""" - def hook(module, name=None): def inner(hooker): @@ -81,6 +76,9 @@ def real_hooker(*args, **kwargs): return inner +GUI_WINDOW = None + + @hook(ti.GUI) def show(orig, self, *args, **kwargs): if not self.running: @@ -92,6 +90,22 @@ def show(orig, self, *args, **kwargs): return orig(self, *args, *kwargs) +@hook(ti.GUI) +def __init__(orig, self, *args, **kwargs): + global GUI_WINDOW + assert not GUI_WINDOW + orig(self, *args, **kwargs) + GUI_WINDOW = self + + +@hook(ti.GUI) +def close(orig, self): + global GUI_WINDOW + assert not GUI_WINDOW or self is GUI_WINDOW + GUI_WINDOW = None + return orig(self) + + GGUI_WINDOW = None @@ -109,9 +123,6 @@ def show(orig, self, *args, **kwargs): @hook(ti.ui.Window) def __init__(orig, self, *args, **kwargs): global GGUI_WINDOW - if GGUI_WINDOW: - GGUI_WINDOW.destroy() - assert not GGUI_WINDOW orig(self, *args, **kwargs) GGUI_WINDOW = self @@ -120,7 +131,7 @@ def __init__(orig, self, *args, **kwargs): @hook(ti.ui.Window) def destroy(orig, self): global GGUI_WINDOW - assert self is GGUI_WINDOW + assert not GGUI_WINDOW or self is GGUI_WINDOW GGUI_WINDOW = None return orig(self) @@ -130,10 +141,26 @@ def show(orig): return +@hook(plt) +def imshow(orig, img): + return + + +_prop_running = property( + (lambda self: self._frames_remaining > 0), + (lambda self, v: None), +) + ti.GUI._frames_remaining = 10 -ti.GUI.running = property(lambda self: self._frames_remaining > 0) +ti.GUI.running = _prop_running ti.ui.Window._frames_remaining = 10 -ti.ui.Window.running = property(lambda self: self._frames_remaining > 0) +ti.ui.Window.running = _prop_running + + +def pytest_runtest_teardown(item, nextitem): + global GUI_WINDOW, GGUI_WINDOW + GUI_WINDOW and GUI_WINDOW.close() + GGUI_WINDOW and GGUI_WINDOW.destroy() @dataclass diff --git a/docs/lang/articles/faqs/faq.md b/docs/lang/articles/faqs/faq.md index 2938afc06895e..210a5466cf22f 100755 --- a/docs/lang/articles/faqs/faq.md +++ b/docs/lang/articles/faqs/faq.md @@ -142,17 +142,23 @@ Yes, Taichi supports many popular Python packages. Taichi provides helper functi ```python import taichi as ti -pixels = ti.field(ti.f32, (1024, 512)) import numpy as np -arr = np.random.rand(1024, 512) -pixels.from_numpy(arr) # load numpy data into taichi fields import matplotlib.pyplot as plt + +pixels = ti.field(ti.f32, (512, 512)) + +def render_pixels(): + arr = np.random.rand(512, 512) + pixels.from_numpy(arr) # load numpy data into taichi fields + +render_pixels() arr = pixels.to_numpy() # store taichi data into numpy arrays plt.imshow(arr) plt.show() import matplotlib.cm as cm cmap = cm.get_cmap('magma') -gui = ti.GUI('Color map') +gui = ti.GUI('Color map', (512, 512)) + while gui.running: render_pixels() arr = pixels.to_numpy() diff --git a/docs/lang/articles/visualization/gui_system.md b/docs/lang/articles/visualization/gui_system.md index a67edf11ab0d3..34cea85a4ac4c 100644 --- a/docs/lang/articles/visualization/gui_system.md +++ b/docs/lang/articles/visualization/gui_system.md @@ -8,10 +8,15 @@ Taichi has a built-in GUI system for visualizing simulation data in data contain ## Create and display a window -The following code creates a `640x360` window with a "Hello World!" title, and displays it by calling `gui.show()`: +The following code creates a `640x360` window with a "Hello World!" title: -```python +```python as-prelude:gui gui = ti.GUI('Hello World!', (640, 360)) +``` + +Displays it by calling `gui.show()`: + +```python preludes:gui while gui.running: gui.show() ``` @@ -28,8 +33,10 @@ You can set `gui.running=False` in the `while` loop to close the GUI: ```python gui = ti.GUI('Window Title', (640, 360)) +some_events_happend = lambda: random.random() < 0.8 + while gui.running: - if some_events_happend: + if some_events_happend(): gui.running = False gui.show() ``` @@ -331,6 +338,7 @@ while gui.running: print('Go left!') elif gui.is_pressed('d', ti.GUI.RIGHT): print('Go right!') + gui.show() ``` :::caution From a05b1cf7c97d4027b22b242587192969c8878e05 Mon Sep 17 00:00:00 2001 From: Proton Date: Sun, 23 Apr 2023 16:35:24 +0800 Subject: [PATCH 15/15] meh --- docs/lang/articles/visualization/ggui.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/lang/articles/visualization/ggui.md b/docs/lang/articles/visualization/ggui.md index 1acc02e453db4..ba5e833b8d2aa 100644 --- a/docs/lang/articles/visualization/ggui.md +++ b/docs/lang/articles/visualization/ggui.md @@ -345,15 +345,15 @@ while window.running: If `indices` is not provided, consider using like this: -```python preludes:vars +```python preludes:vars skip-ci:Taichi-Bug scene = ti.ui.Scene() -scene.mesh(vertices, normals, color, per_vertex_color, vertex_offset=0, vertex_count=50, show_wireframe=True) +scene.mesh(vertices_3d, normals, color, per_vertex_color, vertex_offset=0, vertex_count=50, show_wireframe=True) ``` If `indices` is provided, consider using like this: ```python cont -scene.mesh(vertices, indices, normals, color, per_vertex_color, vertex_offset=0, index_offset=0, index_count=50, show_wireframe=True) +scene.mesh(vertices_3d, indices, normals, color, per_vertex_color, vertex_offset=0, index_offset=0, index_count=50, show_wireframe=True) ``` :::