From 1d6369028540486f2853dea87b1e99817925b197 Mon Sep 17 00:00:00 2001 From: "dunfan.lu" Date: Tue, 6 Jul 2021 05:16:02 -0400 Subject: [PATCH 1/6] begin new gui doc --- website/docs/lang/articles/misc/new_gui.md | 263 +++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 website/docs/lang/articles/misc/new_gui.md diff --git a/website/docs/lang/articles/misc/new_gui.md b/website/docs/lang/articles/misc/new_gui.md new file mode 100644 index 000000000..4681210df --- /dev/null +++ b/website/docs/lang/articles/misc/new_gui.md @@ -0,0 +1,263 @@ +--- +sidebar_position: 1 + +--- + +# New GUI system + +A new GUI system is to be added to Taichi. The new GUI system will use GPU for rendering, which will enable it to be much faster and to render 3d scenes. This doc describes the APIs to be implemented. + +## Create a window + +`ti.ui.GUI(name, res)` creates a window. If `res` is scalar, then the width will be equal to the height. + +The following codes show how to create a window of resolution `640x360`: + +```python +gui = ti.ui.GUI('Window Title', (640, 360)) +``` + + + + + +## Display a window + +`gui.show(filename)` helps display a window. If `filename` is specified, a screenshot will be saved to the file specified by the name. For example, the following saves frames of the window to `.png`s: + + for frame in range(10000): + render(img) + gui.set_image(img) + gui.show(f'{frame:06d}.png') + + + +## Paint on a window + +`gui.set_image(pixels)` sets an image to display on the window. + +The image pixels are set from the values of `img[i, j]`, where `i` indicates the horizontal coordinates (from left to right) and `j` the vertical coordinates (from bottom to top). + +If the window size is `(x, y)`, then `img` must be one of: + +- `ti.field(shape=(x, y))`, a gray-scale image + +- `ti.field(shape=(x, y, 3))`, where `3` is for `(r, g, b)` channels + +- `ti.field(shape=(x, y, 2))`, where `2` is for `(r, g)` channels + +- `ti.Vector.field(3, shape=(x, y))` `(r, g, b)` channels on each + component (see [vector](../../api/vector.md#vector-fields) for details) + +- `ti.Vector.field(2, shape=(x, y))` `(r, g)` channels on each component + +- `np.ndarray(shape=(x, y))` + +- `np.ndarray(shape=(x, y, 3))` + +- `np.ndarray(shape=(x, y, 2))` + +The data type of `img` must be one of: + +- `uint8`, range `[0, 255]` + +- `uint16`, range `[0, 65535]` + +- `uint32`, range `[0, 4294967295]` + +- `float32`, range `[0, 1]` + +- `float64`, range `[0, 1]` + + + +## Convert RGB to Hex + +`ti.rgb_to_hex(rgb)` can convert a (R, G, B) tuple of floats into a single integer value, e.g., + +```python +rgb = (0.4, 0.8, 1.0) +hex = ti.rgb_to_hex(rgb) # 0x66ccff + +rgb = np.array([[0.4, 0.8, 1.0], [0.0, 0.5, 1.0]]) +hex = ti.rgb_to_hex(rgb) # np.array([0x66ccff, 0x007fff]) +``` + +The return values can be used in GUI drawing APIs. + + + +## Event processing + +Every event have a key and type. + +_Event type_ is the type of event, for now, there are just three type of event: + + ti.GUI.RELEASE # key up or mouse button up + ti.GUI.PRESS # key down or mouse button down + ti.GUI.MOTION # mouse motion or mouse wheel + +_Event key_ is the key that you pressed on keyboard or mouse, can be one of: + + # for ti.GUI.PRESS and ti.GUI.RELEASE event: + ti.GUI.ESCAPE # Esc + ti.GUI.SHIFT # Shift + ti.GUI.LEFT # Left Arrow + 'a' # we use lowercase for alphabet + 'b' + ... + ti.GUI.LMB # Left Mouse Button + ti.GUI.RMB # Right Mouse Button + + # for ti.GUI.MOTION event: + ti.GUI.MOVE # Mouse Moved + ti.GUI.WHEEL # Mouse Wheel Scrolling + +A _event filter_ is a list combined of _key_, _type_ and _(type, key)_ tuple, e.g.: + +```python +# if ESC pressed or released: +gui.get_event(ti.GUI.ESCAPE) + +# if any key is pressed: +gui.get_event(ti.GUI.PRESS) + +# if ESC pressed or SPACE released: +gui.get_event((ti.GUI.PRESS, ti.GUI.ESCAPE), (ti.GUI.RELEASE, ti.GUI.SPACE)) +``` + +`gui.running` can help check the state of the window. `ti.GUI.EXIT` occurs when you click on the close (X) button of a window. + `gui.running` will obtain `False` when the GUI is being closed. + +For example, loop until the close button is clicked: + + while gui.running: + render() + gui.set_image(pixels) + gui.show() + +You can also close the window by manually setting `gui.running` to`False`: + + while gui.running: + if gui.get_event(ti.GUI.ESCAPE): + gui.running = False + + render() + gui.set_image(pixels) + gui.show() + +`gui.get_event(a, ...)` tries to pop an event from the queue, and stores it into `gui.event`. + +For example: + + if gui.get_event(): + print('Got event, key =', gui.event.key) + +For example, loop until ESC is pressed: + + gui = ti.GUI('Title', (640, 480)) + while not gui.get_event(ti.GUI.ESCAPE): + gui.set_image(img) + gui.show() + +`gui.get_events(a, ...)` is basically the same as `gui.get_event`, except that it returns a generator of events instead of storing into `gui.event`: + + for e in gui.get_events(): + if e.key == ti.GUI.ESCAPE: + exit() + elif e.key == ti.GUI.SPACE: + do_something() + elif e.key in ['a', ti.GUI.LEFT]: + ... + +`gui.is_pressed(key, ...)` can detect the keys you pressed. It must be used together with `gui.get_event`, or it won't be updated! For +example: + + while True: + gui.get_event() # must be called before is_pressed + if gui.is_pressed('a', ti.GUI.LEFT): + print('Go left!') + elif gui.is_pressed('d', ti.GUI.RIGHT): + print('Go right!') + +`gui.get_cursor_pos()` can return current cursor position within the window. For example: + + mouse_x, mouse_y = gui.get_cursor_pos() + +`gui.fps_limit` sets the FPS limit for a window. For example, to cap FPS at 24, simply use `gui.fps_limit = 24`. This helps reduce the overload on your hardware especially when you're using OpenGL on your integrated GPU which could make desktop slow to response. + + + +## GUI Widgets + +Sometimes it's more intuitive to use widgets like slider or button to control the program variables instead of using chaotic keyboard bindings. Taichi GUI provides a set of widgets for that reason: + +For example: + + radius = gui.slider('Radius', 1, 50) + + while gui.running: + print('The radius now is', radius.value) + ... + radius.value += 0.01 + ... + gui.show() + + + +## Image I/O + +`ti.imwrite(img, filename)` can export a `np.ndarray` or Taichi field (`ti.Matrix.field`, `ti.Vector.field`, or `ti.field`) to a specified location `filename`. + +Same as `ti.GUI.show(filename)`, the format of the exported image is determined by **the suffix of** `filename` as well. Now `ti.imwrite` supports exporting images to `png`, `img` and `jpg` and we recommend using `png`. + +Please make sure that the input image has **a valid shape**. If you want to export a grayscale image, the input shape of field should be `(height, weight)` or `(height, weight, 1)`. For example: + +```python +import taichi as ti + +ti.init() + +shape = (512, 512) +type = ti.u8 +pixels = ti.field(dtype=type, shape=shape) + +@ti.kernel +def draw(): + for i, j in pixels: + pixels[i, j] = ti.random() * 255 # integars between [0, 255] for ti.u8 + +draw() + +ti.imwrite(pixels, f"export_u8.png") +``` + +Besides, for RGB or RGBA images, `ti.imwrite` needs to receive a field which has shape `(height, width, 3)` and `(height, width, 4)` individually. + +Generally the value of the pixels on each channel of a `png` image is an integer in \[0, 255\]. For this reason, `ti.imwrite` will **cast fields** which has different data types all **into integers between \[0, 255\]**. As a result, `ti.imwrite` has the following requirements for different data types of input fields: + +- For float-type (`ti.f16`, `ti.f32`, etc) input fields, **the value of each pixel should be float between \[0.0, 1.0\]**. Otherwise `ti.imwrite` will first clip them into \[0.0, 1.0\]. Then they are multiplied by 256 and casted to integers ranging from \[0, 255\]. +- For int-type (`ti.u8`, `ti.u16`, etc) input fields, **the value of each pixel can be any valid integer in its own bounds**. These integers in this field will be scaled to \[0, 255\] by being divided over the upper bound of its basic type accordingly. + +Here is another example: + +```python +import taichi as ti + +ti.init() + +shape = (512, 512) +channels = 3 +type = ti.f32 +pixels = ti.Matrix.field(channels, dtype=type, shape=shape) + +@ti.kernel +def draw(): + for i, j in pixels: + for k in ti.static(range(channels)): + pixels[i, j][k] = ti.random() # floats between [0, 1] for ti.f32 + +draw() + +ti.imwrite(pixels, f"export_f32.png") +``` From 544dcac5ddb6ec3107e4622a592e5fba9540e58b Mon Sep 17 00:00:00 2001 From: "dunfan.lu" Date: Tue, 6 Jul 2021 23:28:57 -0400 Subject: [PATCH 2/6] wip --- website/docs/lang/articles/misc/new_gui.md | 316 ++++++++------------- 1 file changed, 113 insertions(+), 203 deletions(-) diff --git a/website/docs/lang/articles/misc/new_gui.md b/website/docs/lang/articles/misc/new_gui.md index 4681210df..b19e8193a 100644 --- a/website/docs/lang/articles/misc/new_gui.md +++ b/website/docs/lang/articles/misc/new_gui.md @@ -3,261 +3,171 @@ sidebar_position: 1 --- -# New GUI system +# New UI system -A new GUI system is to be added to Taichi. The new GUI system will use GPU for rendering, which will enable it to be much faster and to render 3d scenes. This doc describes the APIs to be implemented. +A new UI system is to be added to Taichi. The new GUI system will use GPU for rendering, which will enable it to be much faster and to render 3d scenes. This doc describes the APIs to be implemented. -## Create a window +A few design principles (to be expanded): -`ti.ui.GUI(name, res)` creates a window. If `res` is scalar, then the width will be equal to the height. +* Immediate mode GUI components. +* When rendering geometries, users will supply `taichi` fields as input. The implementation will avoid any GPU<->CPU memcpy. -The following codes show how to create a window of resolution `640x360`: +## Creating a window + +`ti.ui.Window(name, res)` creates a window. If `res` is scalar, then the width will be equal to the height.Example: ```python -gui = ti.ui.GUI('Window Title', (640, 360)) +window = ti.ui.Window('Window Title', (640, 360)) ``` +There're three types of objects that can be displayed on a `ti.ui.Window`: +* 2D Canvas, which can be used to draw simple 2D geometries such as circles, triangles, etc. +* 3D Scene, which can be used to render 3D meshes and particles, with a configurable camera and light sources. +* Immediate mode GUI components, buttons, textboxes, etc. +## 2D Canvas - -## Display a window - -`gui.show(filename)` helps display a window. If `filename` is specified, a screenshot will be saved to the file specified by the name. For example, the following saves frames of the window to `.png`s: - - for frame in range(10000): - render(img) - gui.set_image(img) - gui.show(f'{frame:06d}.png') - - - -## Paint on a window - -`gui.set_image(pixels)` sets an image to display on the window. - -The image pixels are set from the values of `img[i, j]`, where `i` indicates the horizontal coordinates (from left to right) and `j` the vertical coordinates (from bottom to top). - -If the window size is `(x, y)`, then `img` must be one of: - -- `ti.field(shape=(x, y))`, a gray-scale image - -- `ti.field(shape=(x, y, 3))`, where `3` is for `(r, g, b)` channels - -- `ti.field(shape=(x, y, 2))`, where `2` is for `(r, g)` channels - -- `ti.Vector.field(3, shape=(x, y))` `(r, g, b)` channels on each - component (see [vector](../../api/vector.md#vector-fields) for details) - -- `ti.Vector.field(2, shape=(x, y))` `(r, g)` channels on each component - -- `np.ndarray(shape=(x, y))` - -- `np.ndarray(shape=(x, y, 3))` - -- `np.ndarray(shape=(x, y, 2))` - -The data type of `img` must be one of: - -- `uint8`, range `[0, 255]` - -- `uint16`, range `[0, 65535]` - -- `uint32`, range `[0, 4294967295]` - -- `float32`, range `[0, 1]` - -- `float64`, range `[0, 1]` - - - -## Convert RGB to Hex - -`ti.rgb_to_hex(rgb)` can convert a (R, G, B) tuple of floats into a single integer value, e.g., +### Creating a canvas ```python -rgb = (0.4, 0.8, 1.0) -hex = ti.rgb_to_hex(rgb) # 0x66ccff - -rgb = np.array([[0.4, 0.8, 1.0], [0.0, 0.5, 1.0]]) -hex = ti.rgb_to_hex(rgb) # np.array([0x66ccff, 0x007fff]) +canvas = ti.ui.Canvas(x,y,width,height) ``` +where `x`,`y`,`width`,`height` are floats between 0 and 1 that indicate the relative position and size of the canvas relative to the window. -The return values can be used in GUI drawing APIs. - - - -## Event processing - -Every event have a key and type. - -_Event type_ is the type of event, for now, there are just three type of event: - - ti.GUI.RELEASE # key up or mouse button up - ti.GUI.PRESS # key down or mouse button down - ti.GUI.MOTION # mouse motion or mouse wheel - -_Event key_ is the key that you pressed on keyboard or mouse, can be one of: - - # for ti.GUI.PRESS and ti.GUI.RELEASE event: - ti.GUI.ESCAPE # Esc - ti.GUI.SHIFT # Shift - ti.GUI.LEFT # Left Arrow - 'a' # we use lowercase for alphabet - 'b' - ... - ti.GUI.LMB # Left Mouse Button - ti.GUI.RMB # Right Mouse Button - - # for ti.GUI.MOTION event: - ti.GUI.MOVE # Mouse Moved - ti.GUI.WHEEL # Mouse Wheel Scrolling - -A _event filter_ is a list combined of _key_, _type_ and _(type, key)_ tuple, e.g.: +### Drawing on the canvas ```python -# if ESC pressed or released: -gui.get_event(ti.GUI.ESCAPE) - -# if any key is pressed: -gui.get_event(ti.GUI.PRESS) - -# if ESC pressed or SPACE released: -gui.get_event((ti.GUI.PRESS, ti.GUI.ESCAPE), (ti.GUI.RELEASE, ti.GUI.SPACE)) +canvas.clear(color) +canvas.triangles(a,b,c,color) +canvas.triangles_indexed(positions,indices,color) +canvas.circles(centers,radius,colors) +canvas.lines(start_positions,end_positions,colors) ``` -`gui.running` can help check the state of the window. `ti.GUI.EXIT` occurs when you click on the close (X) button of a window. - `gui.running` will obtain `False` when the GUI is being closed. - -For example, loop until the close button is clicked: - - while gui.running: - render() - gui.set_image(pixels) - gui.show() +The positions/centers of geometries will be represented as floats between 0 and 1, which indicate relative positions on the canvas. -You can also close the window by manually setting `gui.running` to`False`: - - while gui.running: - if gui.get_event(ti.GUI.ESCAPE): - gui.running = False - - render() - gui.set_image(pixels) - gui.show() +### Drawing the canvas on the window +```python +window.render(canvas) +``` -`gui.get_event(a, ...)` tries to pop an event from the queue, and stores it into `gui.event`. -For example: +## 3D Scene - if gui.get_event(): - print('Got event, key =', gui.event.key) +### Creating a scene +```python +scene = ti.ui.Scene() +``` +### Configuring camera +```python +scene.camera_center(pos) +scene.camera_lookat(pos) +scene.camera_up(dir) +scene.camera_projection(mode) +``` +where `mode` is either `ti.ui.Scene.PROJECTION_PERSPECTIVE` or `ti.ui.Scene.PROJECTION_ORTHOGONAL` -For example, loop until ESC is pressed: - gui = ti.GUI('Title', (640, 480)) - while not gui.get_event(ti.GUI.ESCAPE): - gui.set_image(img) - gui.show() +### Configuring light sources +#### adding a light source +```python +light = scene.add_point_light(pos,color) +``` +#### removing a light source +```python +scene.remove_light(light) +``` -`gui.get_events(a, ...)` is basically the same as `gui.get_event`, except that it returns a generator of events instead of storing into `gui.event`: - for e in gui.get_events(): - if e.key == ti.GUI.ESCAPE: - exit() - elif e.key == ti.GUI.SPACE: - do_something() - elif e.key in ['a', ti.GUI.LEFT]: - ... +### 3d Geometries +```python +scene.mesh(vertices,indices,color) +scene.particles(positions,radius,color) +scene.clear() +``` -`gui.is_pressed(key, ...)` can detect the keys you pressed. It must be used together with `gui.get_event`, or it won't be updated! For -example: - while True: - gui.get_event() # must be called before is_pressed - if gui.is_pressed('a', ti.GUI.LEFT): - print('Go left!') - elif gui.is_pressed('d', ti.GUI.RIGHT): - print('Go right!') +### Rendering the scene on the window +```python +window.render(scene) +``` -`gui.get_cursor_pos()` can return current cursor position within the window. For example: - mouse_x, mouse_y = gui.get_cursor_pos() -`gui.fps_limit` sets the FPS limit for a window. For example, to cap FPS at 24, simply use `gui.fps_limit = 24`. This helps reduce the overload on your hardware especially when you're using OpenGL on your integrated GPU which could make desktop slow to response. +## GUI components +The support for GUI components will closely follow Dear IMGUI (and will likely be implemented using it..). -## GUI Widgets +```python +window.GUI.begin(name,x,y,width,height) +window.GUI.text(...) +window.GUI.button(...) +window.GUI.end() +``` -Sometimes it's more intuitive to use widgets like slider or button to control the program variables instead of using chaotic keyboard bindings. Taichi GUI provides a set of widgets for that reason: -For example: +## Clearing and showing a window +```python +window.clear(color) +... +window.show() +``` - radius = gui.slider('Radius', 1, 50) - - while gui.running: - print('The radius now is', radius.value) - ... - radius.value += 0.01 - ... - gui.show() +## Events Processing +To obtain the events that have occurred since the previous poll: +```python +events = window.get_events() +``` -## Image I/O +Each `event` in `events` is an instance of `ti.ui.Event`. It has the following properties: +* `event.action`, which could be `ti.ui.ACTION_PRESSED`, `ti.ui.ACTION_RELEASED`, ... +* `event.key`, which is `ti.ui.KEY_XXXX` -`ti.imwrite(img, filename)` can export a `np.ndarray` or Taichi field (`ti.Matrix.field`, `ti.Vector.field`, or `ti.field`) to a specified location `filename`. +To obtain mouse position: +* `window.get_mouse_position()` -Same as `ti.GUI.show(filename)`, the format of the exported image is determined by **the suffix of** `filename` as well. Now `ti.imwrite` supports exporting images to `png`, `img` and `jpg` and we recommend using `png`. -Please make sure that the input image has **a valid shape**. If you want to export a grayscale image, the input shape of field should be `(height, weight)` or `(height, weight, 1)`. For example: +## Example Application ```python import taichi as ti -ti.init() - -shape = (512, 512) -type = ti.u8 -pixels = ti.field(dtype=type, shape=shape) - -@ti.kernel -def draw(): - for i, j in pixels: - pixels[i, j] = ti.random() * 255 # integars between [0, 255] for ti.u8 - -draw() - -ti.imwrite(pixels, f"export_u8.png") -``` - -Besides, for RGB or RGBA images, `ti.imwrite` needs to receive a field which has shape `(height, width, 3)` and `(height, width, 4)` individually. - -Generally the value of the pixels on each channel of a `png` image is an integer in \[0, 255\]. For this reason, `ti.imwrite` will **cast fields** which has different data types all **into integers between \[0, 255\]**. As a result, `ti.imwrite` has the following requirements for different data types of input fields: +window = ti.ui.Window("Amazing Window",res) -- For float-type (`ti.f16`, `ti.f32`, etc) input fields, **the value of each pixel should be float between \[0.0, 1.0\]**. Otherwise `ti.imwrite` will first clip them into \[0.0, 1.0\]. Then they are multiplied by 256 and casted to integers ranging from \[0, 255\]. -- For int-type (`ti.u8`, `ti.u16`, etc) input fields, **the value of each pixel can be any valid integer in its own bounds**. These integers in this field will be scaled to \[0, 255\] by being divided over the upper bound of its basic type accordingly. +scene = ti.ui.Scene() +scene.camera_center(pos) +scene.camera_lookat(pos) +scene.camera_up(dir) +scene.camera_projection(mode) +light = scene.add_point_light(pos,color) -Here is another example: - -```python -import taichi as ti +canvas = ti.ui.Canvas(x,y,width,height) -ti.init() +while window.running: + events = window.get_event() + if ev.action == ti.ui.ACTION_PRESSED and ev.key == ti.ui.KEY_SHIFT: + ... -shape = (512, 512) -channels = 3 -type = ti.f32 -pixels = ti.Matrix.field(channels, dtype=type, shape=shape) + window.clear() -@ti.kernel -def draw(): - for i, j in pixels: - for k in ti.static(range(channels)): - pixels[i, j][k] = ti.random() # floats between [0, 1] for ti.f32 + scene.clear() + scene.mesh(...) + window.render(scene) -draw() + canvas.clear(...) + canvas.triangles(...) + window.render(canvas) + + window.GUI.begin(name,x,y,width,height) + window.GUI.text(...) + window.GUI.button(...) + window.GUI.end() -ti.imwrite(pixels, f"export_f32.png") -``` + window.show() + + +``` \ No newline at end of file From 188862c32e3d25dbd3f70d3b62046362048fb9d1 Mon Sep 17 00:00:00 2001 From: "dunfan.lu" Date: Wed, 7 Jul 2021 00:02:41 -0400 Subject: [PATCH 3/6] change camera api --- website/docs/lang/articles/misc/new_gui.md | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/website/docs/lang/articles/misc/new_gui.md b/website/docs/lang/articles/misc/new_gui.md index b19e8193a..585fa33d8 100644 --- a/website/docs/lang/articles/misc/new_gui.md +++ b/website/docs/lang/articles/misc/new_gui.md @@ -61,10 +61,12 @@ scene = ti.ui.Scene() ``` ### Configuring camera ```python -scene.camera_center(pos) -scene.camera_lookat(pos) -scene.camera_up(dir) -scene.camera_projection(mode) +camera = ti.ui.make_camera() +camera.lookat(pos) +camera.up(dir) +camera.center(pos) +camera.projection_mode(mode) +scene.set_camera(camera) ``` where `mode` is either `ti.ui.Scene.PROJECTION_PERSPECTIVE` or `ti.ui.Scene.PROJECTION_ORTHOGONAL` @@ -139,10 +141,14 @@ import taichi as ti window = ti.ui.Window("Amazing Window",res) scene = ti.ui.Scene() -scene.camera_center(pos) -scene.camera_lookat(pos) -scene.camera_up(dir) -scene.camera_projection(mode) + +camera = ti.ui.make_camera() +camera.lookat(pos) +camera.up(dir) +camera.center(pos) +camera.projection_mode(mode) +scene.set_camera(camera) + light = scene.add_point_light(pos,color) canvas = ti.ui.Canvas(x,y,width,height) From 1390bd841e0e6078455f5f16bf2f0dc8e9a93e53 Mon Sep 17 00:00:00 2001 From: "dunfan.lu" Date: Wed, 7 Jul 2021 04:00:32 -0400 Subject: [PATCH 4/6] drawing scene on canvas --- website/docs/lang/articles/misc/new_gui.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/website/docs/lang/articles/misc/new_gui.md b/website/docs/lang/articles/misc/new_gui.md index 585fa33d8..231952e03 100644 --- a/website/docs/lang/articles/misc/new_gui.md +++ b/website/docs/lang/articles/misc/new_gui.md @@ -43,6 +43,7 @@ canvas.triangles(a,b,c,color) canvas.triangles_indexed(positions,indices,color) canvas.circles(centers,radius,colors) canvas.lines(start_positions,end_positions,colors) +canvas.set_image(image) ``` The positions/centers of geometries will be represented as floats between 0 and 1, which indicate relative positions on the canvas. @@ -90,9 +91,10 @@ scene.clear() ``` -### Rendering the scene on the window +### Rendering the scene +a scene is rendered by first rendering it on a canvas. ```python -window.render(scene) +canvas.render(scene) ``` @@ -160,12 +162,13 @@ while window.running: window.clear() + canvas.clear(...) + canvas.triangles(...) + scene.clear() scene.mesh(...) - window.render(scene) + canvas.render(scene) - canvas.clear(...) - canvas.triangles(...) window.render(canvas) window.GUI.begin(name,x,y,width,height) From 1e2931bce60d31cee04a907e556c6befade7f371 Mon Sep 17 00:00:00 2001 From: "dunfan.lu" Date: Tue, 13 Jul 2021 22:10:54 -0400 Subject: [PATCH 5/6] small api changes --- website/docs/lang/articles/misc/new_gui.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/website/docs/lang/articles/misc/new_gui.md b/website/docs/lang/articles/misc/new_gui.md index 231952e03..78f481793 100644 --- a/website/docs/lang/articles/misc/new_gui.md +++ b/website/docs/lang/articles/misc/new_gui.md @@ -31,7 +31,7 @@ There're three types of objects that can be displayed on a `ti.ui.Window`: ### Creating a canvas ```python -canvas = ti.ui.Canvas(x,y,width,height) +canvas = window.make_canvas(x,y,width,height) ``` where `x`,`y`,`width`,`height` are floats between 0 and 1 that indicate the relative position and size of the canvas relative to the window. @@ -58,7 +58,7 @@ window.render(canvas) ### Creating a scene ```python -scene = ti.ui.Scene() +scene = canvas.make_scene() ``` ### Configuring camera ```python @@ -141,8 +141,8 @@ To obtain mouse position: import taichi as ti window = ti.ui.Window("Amazing Window",res) - -scene = ti.ui.Scene() +canvas = window.make_canvas(x,y,width,height) +scene = canvas.make_scene() camera = ti.ui.make_camera() camera.lookat(pos) @@ -153,8 +153,6 @@ scene.set_camera(camera) light = scene.add_point_light(pos,color) -canvas = ti.ui.Canvas(x,y,width,height) - while window.running: events = window.get_event() if ev.action == ti.ui.ACTION_PRESSED and ev.key == ti.ui.KEY_SHIFT: From da24e829d60d7c6d6029b8fd5bb7a4f739fd1107 Mon Sep 17 00:00:00 2001 From: "dunfan.lu" Date: Wed, 14 Jul 2021 02:41:50 -0400 Subject: [PATCH 6/6] wip --- website/docs/lang/articles/misc/new_gui.md | 44 +++++++--------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/website/docs/lang/articles/misc/new_gui.md b/website/docs/lang/articles/misc/new_gui.md index 78f481793..1f54da418 100644 --- a/website/docs/lang/articles/misc/new_gui.md +++ b/website/docs/lang/articles/misc/new_gui.md @@ -31,9 +31,9 @@ There're three types of objects that can be displayed on a `ti.ui.Window`: ### Creating a canvas ```python -canvas = window.make_canvas(x,y,width,height) +canvas = window.get_canvas() ``` -where `x`,`y`,`width`,`height` are floats between 0 and 1 that indicate the relative position and size of the canvas relative to the window. +this retrieves a `Canvas` object that covers the entire window. ### Drawing on the canvas @@ -48,17 +48,13 @@ canvas.set_image(image) The positions/centers of geometries will be represented as floats between 0 and 1, which indicate relative positions on the canvas. -### Drawing the canvas on the window -```python -window.render(canvas) -``` ## 3D Scene ### Creating a scene ```python -scene = canvas.make_scene() +scene = ti.ui.Scene() ``` ### Configuring camera ```python @@ -75,11 +71,7 @@ where `mode` is either `ti.ui.Scene.PROJECTION_PERSPECTIVE` or `ti.ui.Scene.PROJ ### Configuring light sources #### adding a light source ```python -light = scene.add_point_light(pos,color) -``` -#### removing a light source -```python -scene.remove_light(light) +scene.point_light(pos,color) ``` @@ -87,7 +79,6 @@ scene.remove_light(light) ```python scene.mesh(vertices,indices,color) scene.particles(positions,radius,color) -scene.clear() ``` @@ -97,9 +88,6 @@ a scene is rendered by first rendering it on a canvas. canvas.render(scene) ``` - - - ## GUI components The support for GUI components will closely follow Dear IMGUI (and will likely be implemented using it..). @@ -114,7 +102,6 @@ window.GUI.end() ## Clearing and showing a window ```python -window.clear(color) ... window.show() ``` @@ -141,33 +128,28 @@ To obtain mouse position: import taichi as ti window = ti.ui.Window("Amazing Window",res) -canvas = window.make_canvas(x,y,width,height) -scene = canvas.make_scene() - -camera = ti.ui.make_camera() -camera.lookat(pos) -camera.up(dir) -camera.center(pos) -camera.projection_mode(mode) -scene.set_camera(camera) +canvas = window.get_canvas() +scene = ti.ui.Scene() -light = scene.add_point_light(pos,color) while window.running: events = window.get_event() if ev.action == ti.ui.ACTION_PRESSED and ev.key == ti.ui.KEY_SHIFT: ... - window.clear() - canvas.clear(...) canvas.triangles(...) scene.clear() + camera = ti.ui.make_camera() + camera.lookat(pos) + camera.up(dir) + camera.center(pos) + camera.projection_mode(mode) + scene.set_camera(camera) + scene.point_light(pos,color) scene.mesh(...) canvas.render(scene) - - window.render(canvas) window.GUI.begin(name,x,y,width,height) window.GUI.text(...)