{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "71aa43d6-98c9-4552-a9cd-d65784eef882", "metadata": {}, "outputs": [], "source": [ "# File: noodle.ipynb\n", "# Code: Claude Code and Codex\n", "# Review: Ryoichi Ando (ryoichi.ando@zozo.com)\n", "# License: Apache v2.0" ] }, { "cell_type": "code", "execution_count": null, "id": "33a15148-7429-4f33-8445-9487b0d9180e", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from frontend import App\n", "\n", "# create an app\n", "app = App.create(\"noodle\")\n", "\n", "# create a 1D rod strand mesh (long vertical line)\n", "V, E = app.mesh.line([0, 0.01, 0], [0.01, 15, 0], 960)\n", "app.asset.add.rod(\"strand\", V, E)\n", "\n", "# create a scene\n", "scene = app.scene.create()\n", "\n", "# add invisible hemisphere bowl to collect noodles\n", "scene.add.invisible.sphere([0, 1, 0], 1.1).invert().hemisphere()\n", "\n", "# add grid of noodle strands falling into bowl\n", "N, scale = 11, 0.05\n", "for i, j in np.ndindex((N, N)):\n", " x, y = scale * (i - N / 2), scale * (j - N / 2)\n", " obj = scene.add(\"strand\").at(x, 0, y).jitter()\n", " # set material properties for flexible noodles\n", " (\n", " obj.param.set(\"bend\", 10)\n", " .set(\"contact-gap\", 3e-3)\n", " .set(\"contact-offset\", 3e-3)\n", " .set(\"friction\", 0.05)\n", " )\n", "\n", "# set preview options for close-up view\n", "opts = {\"lookat\": [0, 0.25, 0], \"eye\": [4, 15, 15], \"fov\": 4}\n", "\n", "# compile the scene and report stats\n", "scene = scene.build().report()\n", "\n", "# preview the initial scene\n", "scene.preview(options=opts)" ] }, { "cell_type": "code", "execution_count": null, "id": "fed21b38-09ee-4557-8d19-6c413ab5872c", "metadata": {}, "outputs": [], "source": [ "# create a new session with the compiled scene\n", "session = app.session.create(scene)\n", "\n", "# set session parameters with air friction to slow falling\n", "(\n", " session.param.set(\"frames\", 240)\n", " .set(\"fix-xz\", 1.0)\n", " .set(\"isotropic-air-friction\", 1e-5)\n", " .set(\"friction-mode\", \"max\")\n", ")\n", "\n", "# build this session\n", "session = session.build()" ] }, { "cell_type": "code", "execution_count": null, "id": "a0b681a5-02ca-4211-acb6-51ca3aa74363", "metadata": {}, "outputs": [], "source": [ "# start the simulation and live-preview the results\n", "session.start().preview(options=opts)\n", "\n", "# also show simulation logs in realtime\n", "session.stream()" ] }, { "cell_type": "code", "execution_count": null, "id": "06dfc048-e0c5-49a5-b2b8-b9ff26d08766", "metadata": {}, "outputs": [], "source": [ "# create an animation from the simulation results\n", "session.animate(options=opts)" ] }, { "cell_type": "code", "execution_count": null, "id": "1e4e3a0e-abda-4695-900d-48db50b03f34", "metadata": {}, "outputs": [], "source": [ "# export the animation to file\n", "session.export.animation()" ] }, { "cell_type": "code", "execution_count": null, "id": "c8e2432d-7328-4d73-afbb-159ae5cff76d", "metadata": {}, "outputs": [], "source": [ "# this is for CI\n", "if app.ci:\n", " assert session.finished()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }