From 250eaaf59c25c17f7b07303aeed7ca3119552c3b Mon Sep 17 00:00:00 2001 From: bk_office <2680813175@qq.com> Date: Mon, 27 Apr 2026 21:41:16 +0800 Subject: [PATCH] bool and smooth --- konabot/plugins/marchtoy/__init__.py | 4 +- konabot/plugins/marchtoy/gl_render.py | 5 ++- konabot/plugins/marchtoy/obj.py | 51 ++++++++++++++++++++-- konabot/plugins/marchtoy/op.py | 16 ++++--- konabot/plugins/marchtoy/scene.py | 4 +- konabot/plugins/marchtoy/shaders/frag.glsl | 2 +- 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/konabot/plugins/marchtoy/__init__.py b/konabot/plugins/marchtoy/__init__.py index f2e5fb0..5d254c6 100644 --- a/konabot/plugins/marchtoy/__init__.py +++ b/konabot/plugins/marchtoy/__init__.py @@ -11,11 +11,11 @@ cmd_marchtoy = on_command("march") async def _(args: Message = CommandArg()): if cmd := args.extract_plain_text(): try: - img = await render.render(cmd, (256, 256)) + img = await render.render(cmd, (512, 512)) buffer = io.BytesIO() # img.show() # img.save("/mnt/d/output.png", format="GIF") - img.save(buffer, format="GIF") + img.save(buffer, format="PNG") buffer.seek(0) await cmd_marchtoy.send(await UniMessage().image(raw=buffer).export()) except Exception as e: diff --git a/konabot/plugins/marchtoy/gl_render.py b/konabot/plugins/marchtoy/gl_render.py index 68ad2d5..e54468f 100644 --- a/konabot/plugins/marchtoy/gl_render.py +++ b/konabot/plugins/marchtoy/gl_render.py @@ -24,7 +24,10 @@ async def render(command: str, res: tuple[int, int]): ) except Exception as e: raise Exception(f"cannot compile glsl: {e}") from e - uniform = program["u_resolution"] + try: + uniform = program["u_resolution"] + except Exception as e: + raise Exception("无法获取 uniform,可能相机位于物体内部?") uniform.write(np.array(res, dtype=np.float32)) vertices = np.array([-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0], dtype=np.float32) indices = np.array([0, 1, 2, 1, 2, 3], dtype=np.int32) diff --git a/konabot/plugins/marchtoy/obj.py b/konabot/plugins/marchtoy/obj.py index e50bcad..32d023f 100644 --- a/konabot/plugins/marchtoy/obj.py +++ b/konabot/plugins/marchtoy/obj.py @@ -81,6 +81,7 @@ class Object: def __init__(self) -> None: self.transform: Transform = Transform() self.texture: Texture = Texture() + self.round_corner: float = 0.0 def parse_args(self, args: list[str]): raise NotImplementedError @@ -172,7 +173,7 @@ class Capsule(Object): @make_obj("smoothed", "mix") class Smoothed(Object): - def __init__(self, _k: float = 0.25): + def __init__(self, _k: float = 12.00): super().__init__() self.block_a: str = "INF" self.block_b: str = "INF" @@ -196,12 +197,56 @@ class Smoothed(Object): def sdf_block_glsl(self): return f"smin({self.block_a}, {self.block_b}, {self.k})" +@make_obj("intersect", "bool") +class BoolIntersect(Object): + def __init__(self): + super().__init__() + + def parse_args(self, args: list[str]): + from konabot.plugins.marchtoy.scene import Scene + try: + if not len(args) >= 2: + raise Exception("expecting at least 2 args") + scene_a = Scene(args[0]) + scene_b = Scene(args[1]) + self.block_a = scene_a.canvas_objs[0][1] + self.block_b = scene_b.canvas_objs[0][1] + if len(args) > 2: + self.k = ArgParser.as_float(args[2], 0.25) + except Exception as e: + raise Exception(f"cannot build bool object over {args}: {e}") + + def sdf_block_glsl(self): + return f"max({self.block_a}, {self.block_b})" + +@make_obj("substract", "minus") +class BoolSubstract(Object): + def __init__(self): + super().__init__() + + def parse_args(self, args: list[str]): + from konabot.plugins.marchtoy.scene import Scene + try: + if not len(args) >= 2: + raise Exception("expecting at least 2 args") + scene_a = Scene(args[0]) + scene_b = Scene(args[1]) + self.block_a = scene_a.canvas_objs[0][1] + self.block_b = scene_b.canvas_objs[0][1] + if len(args) > 2: + self.k = ArgParser.as_float(args[2], 0.25) + except Exception as e: + raise Exception(f"cannot build bool object over {args}: {e}") + + def sdf_block_glsl(self): + return f"max({self.block_a}, -{self.block_b})" + @make_obj("camera", "cam") class Camera(Object): - def __init__(self, _focus: float = 1.0) -> None: + def __init__(self, _focus: float = 2.0) -> None: super().__init__() self.focus = _focus - self.transform.translate(5.0, 5.0, 5.0).lookat(0.0, 0.0, 0.0) + self.transform.translate(8.0, 8.0, 8.0).lookat(0.0, 0.0, 0.0) def parse_args(self, args: list[str]): self.focus = ArgParser.as_float(args) diff --git a/konabot/plugins/marchtoy/op.py b/konabot/plugins/marchtoy/op.py index 2d82c1e..c9cb7b6 100644 --- a/konabot/plugins/marchtoy/op.py +++ b/konabot/plugins/marchtoy/op.py @@ -3,7 +3,7 @@ from konabot.plugins.marchtoy.utilities import ArgParser OPERATION_ENTRIES = {} -def make_operation(*name: str): +def make_op(*name: str): def decorator(op): # OPERATION_ENTRIES[name] = op for alias in [*name]: @@ -13,25 +13,25 @@ def make_operation(*name: str): return decorator -@make_operation("pos", "translate", "position", "p") +@make_op("pos", "translate", "position", "p") def translate(obj: Object, args: list[str]): pos = ArgParser.as_vec3(args) obj.transform.translate(pos[0], pos[1], pos[2]) -@make_operation("rot", "rotate", "r") +@make_op("rot", "rotate", "r") def rotate(obj: Object, args: list[str]): pos = ArgParser.as_vec3(args) obj.transform.rotate(pos[0], pos[1], pos[2]) -@make_operation("lookat", "look", "l") +@make_op("lookat", "look", "l") def lookat(obj: Object, args: list[str]): pos = ArgParser.as_vec3(args) obj.transform.lookat(pos[0], pos[1], pos[2]) -@make_operation("color", "col", "texture") +@make_op("color", "col", "texture") def color(obj: Object, args: list[str]): try: if len(args) == 1: @@ -48,3 +48,9 @@ def color(obj: Object, args: list[str]): except: raise Exception("unknown color") + +@make_op("rounded", "round_corner", "corner") +def rounded(obj: Object, args: list[str]): + if len(args) >= 1: + obj.round_corner = ArgParser.as_float(args[0]) + \ No newline at end of file diff --git a/konabot/plugins/marchtoy/scene.py b/konabot/plugins/marchtoy/scene.py index 9954a9d..2162872 100644 --- a/konabot/plugins/marchtoy/scene.py +++ b/konabot/plugins/marchtoy/scene.py @@ -71,7 +71,9 @@ class Scene: obj, sdf_expr = canvas_item sdf_block += f"float sd{index} = {sdf_expr};" sdf_block += f"if(sd{index} < qry.value)" - sdf_block += "{" + f"qry.value = sd{index}; qry.obj_id = {index}; " + "}\n" + # 1e-8 最好换成某个 epsilon + round_corner = f"- {obj.round_corner}" if obj.round_corner > 1e-8 else "" + sdf_block += "{" + f"qry.value = sd{index} {round_corner}; qry.obj_id = {index}; " + "}\n" color = obj.texture.color color_block += ( f"if(obj_id == {index}) return vec4(" diff --git a/konabot/plugins/marchtoy/shaders/frag.glsl b/konabot/plugins/marchtoy/shaders/frag.glsl index b006fff..550d768 100644 --- a/konabot/plugins/marchtoy/shaders/frag.glsl +++ b/konabot/plugins/marchtoy/shaders/frag.glsl @@ -1,6 +1,6 @@ #version 330 const float EPS = 0.001; -const int MAX_ITER = 64; +const int MAX_ITER = 128; uniform vec2 u_resolution; out vec4 fragColor;