From cd259c2db38115c7db92947de7e318fc0ee157ae Mon Sep 17 00:00:00 2001 From: Ryoichi Ando Date: Fri, 27 Dec 2024 10:54:06 +0900 Subject: [PATCH] cone mesh creation improved --- .github/workflows/example_cards.yml | 15 ++++ .github/workflows/example_curtain.yml | 15 ++++ .github/workflows/example_drape.yml | 15 ++++ .github/workflows/example_friction.yml | 15 ++++ .github/workflows/example_hang.yml | 15 ++++ .github/workflows/example_needle.yml | 15 ++++ .github/workflows/example_stack.yml | 15 ++++ .github/workflows/example_trampoline.yml | 15 ++++ .github/workflows/example_trapped.yml | 15 ++++ .../workflows/template/example_template.yml | 15 ++++ examples/cards.ipynb | 2 +- examples/curtain.ipynb | 2 +- examples/drape.ipynb | 4 +- examples/friction.ipynb | 2 +- examples/frontend/_mesh_.py | 81 ++++++++++++++++++- examples/frontend/_scene_.py | 11 ++- examples/hang.ipynb | 5 +- examples/headless.py | 2 +- examples/needle.ipynb | 12 +-- examples/stack.ipynb | 2 +- examples/trampoline.ipynb | 4 +- examples/trapped.ipynb | 2 +- 22 files changed, 258 insertions(+), 21 deletions(-) diff --git a/.github/workflows/example_cards.yml b/.github/workflows/example_cards.yml index 765fe2a..043a8bd 100644 --- a/.github/workflows/example_cards.yml +++ b/.github/workflows/example_cards.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_curtain.yml b/.github/workflows/example_curtain.yml index 0def0b6..219a249 100644 --- a/.github/workflows/example_curtain.yml +++ b/.github/workflows/example_curtain.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_drape.yml b/.github/workflows/example_drape.yml index 92f88ff..fbf0fff 100644 --- a/.github/workflows/example_drape.yml +++ b/.github/workflows/example_drape.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_friction.yml b/.github/workflows/example_friction.yml index f80eed0..6ca870c 100644 --- a/.github/workflows/example_friction.yml +++ b/.github/workflows/example_friction.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_hang.yml b/.github/workflows/example_hang.yml index 626d1d2..391a27f 100644 --- a/.github/workflows/example_hang.yml +++ b/.github/workflows/example_hang.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_needle.yml b/.github/workflows/example_needle.yml index bc83936..94e1661 100644 --- a/.github/workflows/example_needle.yml +++ b/.github/workflows/example_needle.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_stack.yml b/.github/workflows/example_stack.yml index 2431a18..e747896 100644 --- a/.github/workflows/example_stack.yml +++ b/.github/workflows/example_stack.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_trampoline.yml b/.github/workflows/example_trampoline.yml index 069ffcf..3e8cca0 100644 --- a/.github/workflows/example_trampoline.yml +++ b/.github/workflows/example_trampoline.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/example_trapped.yml b/.github/workflows/example_trapped.yml index 0a059d3..23f81ae 100644 --- a/.github/workflows/example_trapped.yml +++ b/.github/workflows/example_trapped.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/.github/workflows/template/example_template.yml b/.github/workflows/template/example_template.yml index e9e0c56..6633183 100644 --- a/.github/workflows/template/example_template.yml +++ b/.github/workflows/template/example_template.yml @@ -48,6 +48,21 @@ jobs: - name: 5th run run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: 6th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 7th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 8th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 9th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + + - name: 10th run + run: bash $HELPER_PATH run ${EXAMPLE_NAME}.py + - name: shutdown if: always() run: bash $HELPER_PATH delete diff --git a/examples/cards.ipynb b/examples/cards.ipynb index 9df3289..21e9363 100644 --- a/examples/cards.ipynb +++ b/examples/cards.ipynb @@ -47,7 +47,7 @@ "for i in reversed(range(n_stack)):\n", " _x, _y = make_row(i+1, _x, _y)\n", "\n", - "scene.add(\"sphere\").at(-2,1,0).velocity(2.3,0,0)\n", + "scene.add(\"sphere\").at(-2,1,0).jitter().velocity(2.3,0,0)\n", "scene.add_invisible_wall([0,0,0],[0,1,0])\n", "\n", "fixed = scene.build().report()\n", diff --git a/examples/curtain.ipynb b/examples/curtain.ipynb index cb40c44..b5deaea 100644 --- a/examples/curtain.ipynb +++ b/examples/curtain.ipynb @@ -26,7 +26,7 @@ " obj.direction([0,1,0],[0,0,1])\n", " obj.pin(obj.grab([0, 1, 0]))\n", "\n", - "scene.add(\"sphere\").at(-1, 0, 0).pin().move_by([8,0,0],5)\n", + "scene.add(\"sphere\").at(-1, 0, 0).jitter().pin().move_by([8,0,0],5)\n", "\n", "fixed = scene.build().report()\n", "fixed.preview();" diff --git a/examples/drape.ipynb b/examples/drape.ipynb index dc8a407..5a45fd2 100644 --- a/examples/drape.ipynb +++ b/examples/drape.ipynb @@ -45,8 +45,8 @@ " # set fiber directions required for Baraff-Witkin\n", " obj.direction([1, 0, 0], [0, 0, 1])\n", "\n", - "# add a sphere mesh at a lower position and set it static collider\n", - "scene.add(\"sphere\").at(0, -0.5 - gap, 0).pin()\n", + "# add a sphere mesh at a lower position with jitter and set it static collider\n", + "scene.add(\"sphere\").at(0, -0.5 - gap, 0).jitter().pin()\n", "\n", "# compile the scene and report stats\n", "fixed = scene.build().report()\n", diff --git a/examples/friction.ipynb b/examples/friction.ipynb index 5d7c857..10a7b30 100644 --- a/examples/friction.ipynb +++ b/examples/friction.ipynb @@ -20,7 +20,7 @@ "\n", "scene = app.scene.create(\"friction\")\n", "armadillo = scene.add(\"armadillo\")\n", - "armadillo.rotate(180,\"y\").rotate(-90,\"x\").rotate(-30,\"z\").at(-5,3,-0.25)\n", + "armadillo.rotate(180,\"y\").rotate(-90,\"x\").rotate(-30,\"z\").at(-5,3,-0.25).jitter()\n", "\n", "deg = 180*np.arctan(0.5)/np.pi\n", "scene.add(\"slope\").rotate(-deg,\"z\").pin()\n", diff --git a/examples/frontend/_mesh_.py b/examples/frontend/_mesh_.py index 2f1aaaa..9ac8cf2 100644 --- a/examples/frontend/_mesh_.py +++ b/examples/frontend/_mesh_.py @@ -103,10 +103,85 @@ def cylinder(self, r: float = 1, height: float = 2, n: int = 32) -> "TriMesh": return self._from_o3d(o3d.geometry.TriangleMesh.create_cylinder(r, height, n)) - def cone(self, r: float = 1, height: float = 2, n: int = 32) -> "TriMesh": - import open3d as o3d + def cone( + self, + Nr: int = 16, + Ny: int = 16, + Nb: int = 4, + radius: float = 0.5, + height: float = 2, + ) -> "TriMesh": + V = [[0, 0, height], [0, 0, 0]] + T = [] + ind_btm_center = 0 + ind_tip = 1 + offset = [] + offset_btm = len(V) + + for k in reversed(range(Ny)): + if k > 0: + r = k / (Ny - 1) + r = r * r + offset.append(len(V)) + for i in range(Nr): + t = 2 * np.pi * i / Nr + x, y = radius * r * np.cos(t), radius * r * np.sin(t) + V.append([x, y, height * r]) + + for j in offset[0:-1]: + for i in range(Nr): + ind00, ind10 = i, (i + 1) % Nr + ind01, ind11 = ind00 + Nr, ind10 + Nr + if i % 2 == 0: + T.append([ind00 + j, ind01 + j, ind10 + j]) + T.append([ind10 + j, ind01 + j, ind11 + j]) + else: + T.append([ind00 + j, ind11 + j, ind10 + j]) + T.append([ind00 + j, ind01 + j, ind11 + j]) + + j = offset[-1] + for i in range(Nr): + ind0, ind1 = i, (i + 1) % Nr + T.append([ind0 + j, ind_tip, ind1 + j]) + + offset = [] + for k in reversed(range(Nb)): + if k > 0: + r = k / Nb + offset.append(len(V)) + for i in range(Nr): + t = 2 * np.pi * i / Nr + x, y = radius * r * np.cos(t), radius * r * np.sin(t) + V.append([x, y, height]) + + for j in offset[0:-1]: + for i in range(Nr): + ind00, ind10 = i, (i + 1) % Nr + ind01, ind11 = ind00 + Nr, ind10 + Nr + if i % 2 == 0: + T.append([ind00 + j, ind10 + j, ind01 + j]) + T.append([ind10 + j, ind11 + j, ind01 + j]) + else: + T.append([ind00 + j, ind10 + j, ind11 + j]) + T.append([ind00 + j, ind11 + j, ind01 + j]) + + j = offset[-1] + for i in range(Nr): + ind0, ind1 = i, (i + 1) % Nr + T.append([ind0 + j, ind1 + j, ind_btm_center]) + + j0, j1 = offset_btm, offset[0] + for i in range(Nr): + ind00, ind10 = i + j0, (i + 1) % Nr + j0 + ind01, ind11 = i + j1, (i + 1) % Nr + j1 + if i % 2 == 0: + T.append([ind00, ind10, ind01]) + T.append([ind10, ind11, ind01]) + else: + T.append([ind00, ind10, ind11]) + T.append([ind00, ind11, ind01]) - return self._from_o3d(o3d.geometry.TriangleMesh.create_cone(r, height, n)) + return TriMesh.create(np.array(V), np.array(T), self._cache_dir) def torus(self, r: float = 1, R: float = 0.25, n: int = 32) -> "TriMesh": import open3d as o3d diff --git a/examples/frontend/_scene_.py b/examples/frontend/_scene_.py index 8742646..da90425 100644 --- a/examples/frontend/_scene_.py +++ b/examples/frontend/_scene_.py @@ -794,7 +794,7 @@ def __init__(self, asset: AssetManager, name: str): def clear(self): self._param = {} - self._at = [0, 0, 0] + self._at = [0.0, 0.0, 0.0] self._scale = 1.0 self._rotation = np.eye(3) self._color = [] @@ -896,6 +896,15 @@ def at(self, x: float, y: float, z: float) -> "Object": self._at = [x, y, z] return self + def jitter(self, r: float = 1e-2) -> "Object": + dx = np.random.random() + dy = np.random.random() + dz = np.random.random() + self._at[0] += r * dx + self._at[1] += r * dy + self._at[2] += r * dz + return self + def atop(self, object: "Object", margin: float = 0.0) -> "Object": a_bbox, a_center = self.bbox() b_bbox, b_center = object.bbox() diff --git a/examples/hang.ipynb b/examples/hang.ipynb index 5dc8325..75261f5 100644 --- a/examples/hang.ipynb +++ b/examples/hang.ipynb @@ -30,10 +30,13 @@ "metadata": {}, "outputs": [], "source": [ + "import random\n", + "jitter_time = 0.1 + 0.5 * random.random()\n", + "\n", "param = app.session.param().set(\"dt\",0.001)\n", "param.set(\"strain-limit-eps\", 0.005).set(\"strain-limit-tau\", 0.005)\n", "param.set(\"frames\",200)\n", - "param.dyn(\"gravity\").time(1).hold().time(1.1).change(9.8).time(2.0).change(-9.8);" + "param.dyn(\"gravity\").time(1).hold().time(1+jitter_time).change(9.8).time(2.0).change(-9.8);" ] }, { diff --git a/examples/headless.py b/examples/headless.py index 4b66e89..4f21477 100644 --- a/examples/headless.py +++ b/examples/headless.py @@ -17,7 +17,7 @@ obj.direction([0, 1, 0], [0, 0, 1]) obj.pin(obj.grab([0, 1, 0])) -scene.add("sphere").at(-1, 0, 0).pin().move_by([8, 0, 0], 5) +scene.add("sphere").at(-1, 0, 0).jitter().pin().move_by([8, 0, 0], 5) fixed = scene.build() param = app.session.param() diff --git a/examples/needle.ipynb b/examples/needle.ipynb index 06420a7..d8622ba 100644 --- a/examples/needle.ipynb +++ b/examples/needle.ipynb @@ -14,22 +14,22 @@ "V, F = app.mesh.square(res=129)\n", "app.asset.add.tri(\"sheet\", V, F)\n", "\n", - "V, F = app.mesh.cone(height=5,n=5).subdivide(n=5)\n", + "V, F = app.mesh.cone(height=5,Nr=24,Ny=24,Nb=8,radius=1)\n", "app.asset.add.tri(\"cone\", V, F)\n", "\n", "V, F, T = app.mesh.icosphere(r=0.25, subdiv_count=4).tetrahedralize()\n", "app.asset.add.tet(\"sphere\", V, F, T)\n", "\n", - "scene = app.scene.create(\"smash-vel-5\")\n", - "scene.add(\"cone\").scale(0.2).rotate(-90,\"x\").at(0,-1.25,0).pin()\n", - "scene.add(\"sphere\").at(0,1,0).pull_pin().hold(1.0).unpin()\n", + "scene = app.scene.create(\"needle-sphere\")\n", + "scene.add(\"cone\").scale(0.2).rotate(90,\"x\").at(0,-0.25,0).jitter().pin()\n", + "scene.add(\"sphere\").at(0,1,0).jitter().pull_pin().hold(1.0).unpin()\n", "\n", "n, space = 5, 0.05\n", "for i in range(n):\n", " y = (i + 1) * space\n", " deg = i * 90 / n\n", " obj = scene.add(\"sheet\").direction([1,0,0],[0,1,0])\n", - " obj.at(0, y, 0).rotate(90,\"x\").rotate(deg,\"y\")\n", + " obj.at(0, y, 0).jitter().rotate(90,\"x\").rotate(deg,\"y\")\n", "\n", "fixed = scene.build().report()\n", "fixed.preview();" @@ -44,7 +44,7 @@ "source": [ "session = app.session.create(\"sphere-needle\").init(fixed)\n", "param = app.session.param()\n", - "param.set(\"frames\", 100);\n", + "param.set(\"frames\", 180);\n", "param.set(\"area-density\", 1e3).set(\"volume-density\", 1e5);\n", "\n", "session.start(param).preview();\n", diff --git a/examples/stack.ipynb b/examples/stack.ipynb index abb0516..121bfa0 100644 --- a/examples/stack.ipynb +++ b/examples/stack.ipynb @@ -25,7 +25,7 @@ " y = (i + 1) * space\n", " deg = i * 90 / n\n", " obj = scene.add(\"sheet\").direction([1,0,0],[0,0,1])\n", - " obj.at(0, y, 0).rotate(deg,\"y\")\n", + " obj.at(0, y, 0).jitter().rotate(deg,\"y\")\n", "\n", "scene.add(\"sphere\").at(0,1,0).velocity(0,-5,0)\n", "\n", diff --git a/examples/trampoline.ipynb b/examples/trampoline.ipynb index 276aab9..35c03e4 100644 --- a/examples/trampoline.ipynb +++ b/examples/trampoline.ipynb @@ -23,7 +23,7 @@ "sheet.pin(sheet.grab([-1,0,0])+sheet.grab([1,0,0]))\n", "\n", "armadillo = scene.add(\"armadillo\").scale(0.75).rotate(180,\"y\")\n", - "armadillo.at(0,1,0).velocity(0,-5,0)\n", + "armadillo.at(0,1,0).jitter().velocity(0,-5,0)\n", "\n", "gap = 0.025\n", "scene.add_invisible_wall([1+gap,0,0],[-1,0,0])\n", @@ -47,7 +47,7 @@ "param.set(\"area-density\", 1e3).set(\"volume-density\", 6e3);\n", "param.set(\"area-young-mod\", 10000.0);\n", "param.set(\"bend\", 1.0);\n", - "param.set(\"frames\", 200);\n", + "param.set(\"frames\", 120);\n", "\n", "session = app.session.create(\"drop-trampoline\").init(fixed)\n", "session.start(param).preview();\n", diff --git a/examples/trapped.ipynb b/examples/trapped.ipynb index fa54032..b29c8e4 100644 --- a/examples/trapped.ipynb +++ b/examples/trapped.ipynb @@ -17,7 +17,7 @@ "scene = app.scene.create(\"sphere-trap\")\n", "\n", "scene.add_invisible_sphere([0,0,0],0.7).invert().radius(0.15,3).radius(100,4)\n", - "scene.add(\"armadillo\").rotate(180,\"y\")\n", + "scene.add(\"armadillo\").jitter().rotate(180,\"y\")\n", "\n", "fixed = scene.build().report()\n", "fixed.preview();"