diff --git a/examples/canvas.html b/examples/canvas.html new file mode 100644 index 0000000..630639a --- /dev/null +++ b/examples/canvas.html @@ -0,0 +1,109 @@ + + + + + + c3r - Drawable canvas cube + + + +
Each face is a canvas element, draw on them
+ + + diff --git a/examples/cube.html b/examples/cube.html index 908d282..6b8f886 100644 --- a/examples/cube.html +++ b/examples/cube.html @@ -10,62 +10,71 @@ background-color: #000; overflow: hidden; } + + #info { + position: absolute; + z-index: 1; + top: 0; + width: 100%; + padding: 5px; + box-sizing: border-box; + color: #fff; + font: 13px monospace; + text-align: center; + } +
+ A spinning box built from CSS 3D transforms, hover to brighten +
diff --git a/examples/filters.html b/examples/filters.html new file mode 100644 index 0000000..10f1fb0 --- /dev/null +++ b/examples/filters.html @@ -0,0 +1,236 @@ + + + + + + c3r - Filter effects + + + +
+ Filter effects, in plain CSS. Hover a shape in the top row to play its + tween, the bottom row has static filters. +
+ + + + diff --git a/examples/index.html b/examples/index.html index 65f8866..061561b 100644 --- a/examples/index.html +++ b/examples/index.html @@ -3,135 +3,122 @@ - c3r examples + CSS 3D examples -

c3r examples

+
+

CSS 3D examples

-

Standalone

+

Standalone

- + -

Ported three.js examples

+

Ported three.js examples

- + +
-
- -
+ .github-corner .octo-arm { + animation: octocat-wave 560ms ease-in-out; + } + } + diff --git a/examples/node-render.mjs b/examples/node-render.mjs index 0eab8e7..e1345fe 100644 --- a/examples/node-render.mjs +++ b/examples/node-render.mjs @@ -1,24 +1,26 @@ // Prints a static HTML render, after `npm run build`: node examples/node-render.mjs > examples/static.html import { GlobalRegistrator } from "@happy-dom/global-registrator"; -GlobalRegistrator.register(); +GlobalRegistrator.register({ + url: "http://localhost/", + settings: { + enableImageFileLoading: true, + fetch: { + virtualServers: [{ url: "/", directory: import.meta.dirname }], + }, + }, +}); const THREE = await import("three"); const { C3RRenderer } = await import("c3r-three"); -const { cssText } = await import("c3r"); - -const width = 800; -const height = 600; const scene = new THREE.Scene(); -const camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000); +// Aspect unused, the view follows the window +const camera = new THREE.PerspectiveCamera(70, 1, 1, 1000); camera.position.z = 500; -// TextureLoader needs a browser -const texture = new THREE.Texture( - Object.assign(document.createElement("img"), { - src: "public/textures/crate.gif", - }), +const texture = await new THREE.TextureLoader().loadAsync( + "public/textures/crate.gif", ); const cube = new THREE.Mesh( new THREE.BoxGeometry(200, 200, 200), @@ -28,16 +30,13 @@ cube.rotation.set(0.4, 0.6, 0); scene.add(cube); const renderer = new C3RRenderer(); -renderer.setSize(width, height); renderer.render(scene, camera); +// Without head and body tags the style lands in the head process.stdout.write(` - - - C3R static render - - - ${renderer.domElement.outerHTML} - + +C3R static render + +${await renderer.toHTML()} `); diff --git a/examples/package.json b/examples/package.json index 91fbf27..1c07a61 100644 --- a/examples/package.json +++ b/examples/package.json @@ -7,8 +7,10 @@ "build": "vite build" }, "devDependencies": { + "@picocss/pico": "^2.1.1", "gl-matrix": "^3.4.4", "nipplejs": "^1.0.4", + "primitive-geometry": "^3.3.1", "three": "^0.186.1", "vite": "^8.3.5" } diff --git a/examples/public/models/obj/suzanne/suzanne.obj b/examples/public/models/obj/suzanne/suzanne.obj index 6043774..4a29814 100644 --- a/examples/public/models/obj/suzanne/suzanne.obj +++ b/examples/public/models/obj/suzanne/suzanne.obj @@ -1,550 +1,364 @@ -# Blender3D v249 OBJ File: suzanne.blend -# www.blender3d.org -v 0.437500 0.164063 0.765625 -v -0.437500 0.164063 0.765625 -v 0.500000 0.093750 0.687500 -v -0.500000 0.093750 0.687500 -v 0.546875 0.054688 0.578125 -v -0.546875 0.054688 0.578125 -v 0.351563 -0.023438 0.617188 -v -0.351563 -0.023438 0.617188 -v 0.351563 0.031250 0.718750 -v -0.351563 0.031250 0.718750 -v 0.351563 0.132813 0.781250 -v -0.351563 0.132813 0.781250 -v 0.273438 0.164063 0.796875 -v -0.273438 0.164063 0.796875 -v 0.203125 0.093750 0.742188 -v -0.203125 0.093750 0.742188 -v 0.156250 0.054688 0.648438 -v -0.156250 0.054688 0.648438 -v 0.078125 0.242188 0.656250 -v -0.078125 0.242188 0.656250 -v 0.140625 0.242188 0.742188 -v -0.140625 0.242188 0.742188 -v 0.242188 0.242188 0.796875 -v -0.242188 0.242188 0.796875 -v 0.273438 0.328125 0.796875 -v -0.273438 0.328125 0.796875 -v 0.203125 0.390625 0.742188 -v -0.203125 0.390625 0.742188 -v 0.156250 0.437500 0.648438 -v -0.156250 0.437500 0.648438 -v 0.351563 0.515625 0.617188 -v -0.351563 0.515625 0.617188 -v 0.351563 0.453125 0.718750 -v -0.351563 0.453125 0.718750 -v 0.351563 0.359375 0.781250 -v -0.351563 0.359375 0.781250 -v 0.437500 0.328125 0.765625 -v -0.437500 0.328125 0.765625 -v 0.500000 0.390625 0.687500 -v -0.500000 0.390625 0.687500 -v 0.546875 0.437500 0.578125 -v -0.546875 0.437500 0.578125 -v 0.625000 0.242188 0.562500 -v -0.625000 0.242188 0.562500 -v 0.562500 0.242188 0.671875 -v -0.562500 0.242188 0.671875 -v 0.468750 0.242188 0.757813 -v -0.468750 0.242188 0.757813 -v 0.476563 0.242188 0.773438 -v -0.476563 0.242188 0.773438 -v 0.445313 0.335938 0.781250 -v -0.445313 0.335938 0.781250 -v 0.351563 0.375000 0.804688 -v -0.351563 0.375000 0.804688 -v 0.265625 0.335938 0.820313 -v -0.265625 0.335938 0.820313 -v 0.226563 0.242188 0.820313 -v -0.226563 0.242188 0.820313 -v 0.265625 0.156250 0.820313 -v -0.265625 0.156250 0.820313 -v 0.351563 0.242188 0.828125 -v -0.351563 0.242188 0.828125 -v 0.351563 0.117188 0.804688 -v -0.351563 0.117188 0.804688 -v 0.445313 0.156250 0.781250 -v -0.445313 0.156250 0.781250 -v 0.000000 0.429688 0.742188 -v 0.000000 0.351563 0.820313 -v 0.000000 -0.679688 0.734375 -v 0.000000 -0.320313 0.781250 -v 0.000000 -0.187500 0.796875 -v 0.000000 -0.773438 0.718750 -v 0.000000 0.406250 0.601563 -v 0.000000 0.570313 0.570313 -v 0.000000 0.898438 -0.546875 -v 0.000000 0.562500 -0.851563 -v 0.000000 0.070313 -0.828125 -v 0.000000 -0.382813 -0.351563 -v 0.203125 -0.187500 0.562500 -v -0.203125 -0.187500 0.562500 -v 0.312500 -0.437500 0.570313 -v -0.312500 -0.437500 0.570313 -v 0.351563 -0.695313 0.570313 -v -0.351563 -0.695313 0.570313 -v 0.367188 -0.890625 0.531250 -v -0.367188 -0.890625 0.531250 -v 0.328125 -0.945313 0.523438 -v -0.328125 -0.945313 0.523438 -v 0.179688 -0.968750 0.554688 -v -0.179688 -0.968750 0.554688 -v 0.000000 -0.984375 0.578125 -v 0.437500 -0.140625 0.531250 -v -0.437500 -0.140625 0.531250 -v 0.632813 -0.039063 0.539063 -v -0.632813 -0.039063 0.539063 -v 0.828125 0.148438 0.445313 -v -0.828125 0.148438 0.445313 -v 0.859375 0.429688 0.593750 -v -0.859375 0.429688 0.593750 -v 0.710938 0.484375 0.625000 -v -0.710938 0.484375 0.625000 -v 0.492188 0.601563 0.687500 -v -0.492188 0.601563 0.687500 -v 0.320313 0.757813 0.734375 -v -0.320313 0.757813 0.734375 -v 0.156250 0.718750 0.757813 -v -0.156250 0.718750 0.757813 -v 0.062500 0.492188 0.750000 -v -0.062500 0.492188 0.750000 -v 0.164063 0.414063 0.773438 -v -0.164063 0.414063 0.773438 -v 0.125000 0.304688 0.765625 -v -0.125000 0.304688 0.765625 -v 0.203125 0.093750 0.742188 -v -0.203125 0.093750 0.742188 -v 0.375000 0.015625 0.703125 -v -0.375000 0.015625 0.703125 -v 0.492188 0.062500 0.671875 -v -0.492188 0.062500 0.671875 -v 0.625000 0.187500 0.648438 -v -0.625000 0.187500 0.648438 -v 0.640625 0.296875 0.648438 -v -0.640625 0.296875 0.648438 -v 0.601563 0.375000 0.664063 -v -0.601563 0.375000 0.664063 -v 0.429688 0.437500 0.718750 -v -0.429688 0.437500 0.718750 -v 0.250000 0.468750 0.757813 -v -0.250000 0.468750 0.757813 -v 0.000000 -0.765625 0.734375 -v 0.109375 -0.718750 0.734375 -v -0.109375 -0.718750 0.734375 -v 0.117188 -0.835938 0.710938 -v -0.117188 -0.835938 0.710938 -v 0.062500 -0.882813 0.695313 -v -0.062500 -0.882813 0.695313 -v 0.000000 -0.890625 0.687500 -v 0.000000 -0.195313 0.750000 -v 0.000000 -0.140625 0.742188 -v 0.101563 -0.148438 0.742188 -v -0.101563 -0.148438 0.742188 -v 0.125000 -0.226563 0.750000 -v -0.125000 -0.226563 0.750000 -v 0.085938 -0.289063 0.742188 -v -0.085938 -0.289063 0.742188 -v 0.398438 -0.046875 0.671875 -v -0.398438 -0.046875 0.671875 -v 0.617188 0.054688 0.625000 -v -0.617188 0.054688 0.625000 -v 0.726563 0.203125 0.601563 -v -0.726563 0.203125 0.601563 -v 0.742188 0.375000 0.656250 -v -0.742188 0.375000 0.656250 -v 0.687500 0.414063 0.726563 -v -0.687500 0.414063 0.726563 -v 0.437500 0.546875 0.796875 -v -0.437500 0.546875 0.796875 -v 0.312500 0.640625 0.835938 -v -0.312500 0.640625 0.835938 -v 0.203125 0.617188 0.851563 -v -0.203125 0.617188 0.851563 -v 0.101563 0.429688 0.843750 -v -0.101563 0.429688 0.843750 -v 0.125000 -0.101563 0.812500 -v -0.125000 -0.101563 0.812500 -v 0.210938 -0.445313 0.710938 -v -0.210938 -0.445313 0.710938 -v 0.250000 -0.703125 0.687500 -v -0.250000 -0.703125 0.687500 -v 0.265625 -0.820313 0.664063 -v -0.265625 -0.820313 0.664063 -v 0.234375 -0.914063 0.632813 -v -0.234375 -0.914063 0.632813 -v 0.164063 -0.929688 0.632813 -v -0.164063 -0.929688 0.632813 -v 0.000000 -0.945313 0.640625 -v 0.000000 0.046875 0.726563 -v 0.000000 0.210938 0.765625 -v 0.328125 0.476563 0.742188 -v -0.328125 0.476563 0.742188 -v 0.164063 0.140625 0.750000 -v -0.164063 0.140625 0.750000 -v 0.132813 0.210938 0.757813 -v -0.132813 0.210938 0.757813 -v 0.117188 -0.687500 0.734375 -v -0.117188 -0.687500 0.734375 -v 0.078125 -0.445313 0.750000 -v -0.078125 -0.445313 0.750000 -v 0.000000 -0.445313 0.750000 -v 0.000000 -0.328125 0.742188 -v 0.093750 -0.273438 0.781250 -v -0.093750 -0.273438 0.781250 -v 0.132813 -0.226563 0.796875 -v -0.132813 -0.226563 0.796875 -v 0.109375 -0.132813 0.781250 -v -0.109375 -0.132813 0.781250 -v 0.039063 -0.125000 0.781250 -v -0.039063 -0.125000 0.781250 -v 0.000000 -0.203125 0.828125 -v 0.046875 -0.148438 0.812500 -v -0.046875 -0.148438 0.812500 -v 0.093750 -0.156250 0.812500 -v -0.093750 -0.156250 0.812500 -v 0.109375 -0.226563 0.828125 -v -0.109375 -0.226563 0.828125 -v 0.078125 -0.250000 0.804688 -v -0.078125 -0.250000 0.804688 -v 0.000000 -0.289063 0.804688 -v 0.257813 -0.312500 0.554688 -v -0.257813 -0.312500 0.554688 -v 0.164063 -0.242188 0.710938 -v -0.164063 -0.242188 0.710938 -v 0.179688 -0.312500 0.710938 -v -0.179688 -0.312500 0.710938 -v 0.234375 -0.250000 0.554688 -v -0.234375 -0.250000 0.554688 -v 0.000000 -0.875000 0.687500 -v 0.046875 -0.867188 0.687500 -v -0.046875 -0.867188 0.687500 -v 0.093750 -0.820313 0.710938 -v -0.093750 -0.820313 0.710938 -v 0.093750 -0.742188 0.726563 -v -0.093750 -0.742188 0.726563 -v 0.000000 -0.781250 0.656250 -v 0.093750 -0.750000 0.664063 -v -0.093750 -0.750000 0.664063 -v 0.093750 -0.812500 0.640625 -v -0.093750 -0.812500 0.640625 -v 0.046875 -0.851563 0.632813 -v -0.046875 -0.851563 0.632813 -v 0.000000 -0.859375 0.632813 -v 0.171875 0.218750 0.781250 -v -0.171875 0.218750 0.781250 -v 0.187500 0.156250 0.773438 -v -0.187500 0.156250 0.773438 -v 0.335938 0.429688 0.757813 -v -0.335938 0.429688 0.757813 -v 0.273438 0.421875 0.773438 -v -0.273438 0.421875 0.773438 -v 0.421875 0.398438 0.773438 -v -0.421875 0.398438 0.773438 -v 0.562500 0.351563 0.695313 -v -0.562500 0.351563 0.695313 -v 0.585938 0.289063 0.687500 -v -0.585938 0.289063 0.687500 -v 0.578125 0.195313 0.679688 -v -0.578125 0.195313 0.679688 -v 0.476563 0.101563 0.718750 -v -0.476563 0.101563 0.718750 -v 0.375000 0.062500 0.742188 -v -0.375000 0.062500 0.742188 -v 0.226563 0.109375 0.781250 -v -0.226563 0.109375 0.781250 -v 0.179688 0.296875 0.781250 -v -0.179688 0.296875 0.781250 -v 0.210938 0.375000 0.781250 -v -0.210938 0.375000 0.781250 -v 0.234375 0.359375 0.757813 -v -0.234375 0.359375 0.757813 -v 0.195313 0.296875 0.757813 -v -0.195313 0.296875 0.757813 -v 0.242188 0.125000 0.757813 -v -0.242188 0.125000 0.757813 -v 0.375000 0.085938 0.726563 -v -0.375000 0.085938 0.726563 -v 0.460938 0.117188 0.703125 -v -0.460938 0.117188 0.703125 -v 0.546875 0.210938 0.671875 -v -0.546875 0.210938 0.671875 -v 0.554688 0.281250 0.671875 -v -0.554688 0.281250 0.671875 -v 0.531250 0.335938 0.679688 -v -0.531250 0.335938 0.679688 -v 0.414063 0.390625 0.750000 -v -0.414063 0.390625 0.750000 -v 0.281250 0.398438 0.765625 -v -0.281250 0.398438 0.765625 -v 0.335938 0.406250 0.750000 -v -0.335938 0.406250 0.750000 -v 0.203125 0.171875 0.750000 -v -0.203125 0.171875 0.750000 -v 0.195313 0.226563 0.750000 -v -0.195313 0.226563 0.750000 +v 0.351563 0.242188 0.808125 +v 0.445313 0.15625 0.76125 +v 0.476563 0.242188 0.753438 +v -0.476563 0.242188 0.753438 +v -0.445313 0.15625 0.76125 +v -0.351563 0.242188 0.808125 +v 0.351563 0.117188 0.784688 +v -0.351563 0.117188 0.784688 +v 0.265625 0.15625 0.800313 +v -0.265625 0.15625 0.800313 +v 0.226563 0.242188 0.800313 +v -0.226563 0.242188 0.800313 +v 0.265625 0.335938 0.800313 +v -0.265625 0.335938 0.800313 +v 0.351563 0.375 0.784688 +v -0.351563 0.375 0.784688 +v 0.445313 0.335938 0.76125 +v -0.445313 0.335938 0.76125 +v 0 0.429688 0.742188 v 0.109375 0.460938 0.609375 +v 0 0.570313 0.570313 +v 0 0.570313 0.570313 v -0.109375 0.460938 0.609375 -v 0.195313 0.664063 0.617188 -v -0.195313 0.664063 0.617188 -v 0.335938 0.687500 0.593750 -v -0.335938 0.687500 0.593750 -v 0.484375 0.554688 0.554688 -v -0.484375 0.554688 0.554688 -v 0.679688 0.453125 0.492188 -v -0.679688 0.453125 0.492188 -v 0.796875 0.406250 0.460938 -v -0.796875 0.406250 0.460938 -v 0.773438 0.164063 0.375000 -v -0.773438 0.164063 0.375000 -v 0.601563 0.000000 0.414063 -v -0.601563 0.000000 0.414063 -v 0.437500 -0.093750 0.468750 -v -0.437500 -0.093750 0.468750 -v 0.000000 0.898438 0.289063 -v 0.000000 0.984375 -0.078125 -v 0.000000 -0.195313 -0.671875 -v 0.000000 -0.460938 0.187500 -v 0.000000 -0.976563 0.460938 -v 0.000000 -0.804688 0.343750 -v 0.000000 -0.570313 0.320313 -v 0.000000 -0.484375 0.281250 -v 0.851563 0.234375 0.054688 -v -0.851563 0.234375 0.054688 -v 0.859375 0.320313 -0.046875 -v -0.859375 0.320313 -0.046875 -v 0.773438 0.265625 -0.437500 -v -0.773438 0.265625 -0.437500 -v 0.460938 0.437500 -0.703125 -v -0.460938 0.437500 -0.703125 -v 0.734375 -0.046875 0.070313 -v -0.734375 -0.046875 0.070313 -v 0.593750 -0.125000 -0.164063 -v -0.593750 -0.125000 -0.164063 -v 0.640625 -0.007813 -0.429688 -v -0.640625 -0.007813 -0.429688 -v 0.335938 0.054688 -0.664063 -v -0.335938 0.054688 -0.664063 -v 0.234375 -0.351563 0.406250 -v -0.234375 -0.351563 0.406250 -v 0.179688 -0.414063 0.257813 -v -0.179688 -0.414063 0.257813 -v 0.289063 -0.710938 0.382813 -v -0.289063 -0.710938 0.382813 -v 0.250000 -0.500000 0.390625 -v -0.250000 -0.500000 0.390625 -v 0.328125 -0.914063 0.398438 -v -0.328125 -0.914063 0.398438 -v 0.140625 -0.757813 0.367188 -v -0.140625 -0.757813 0.367188 -v 0.125000 -0.539063 0.359375 -v -0.125000 -0.539063 0.359375 -v 0.164063 -0.945313 0.437500 -v -0.164063 -0.945313 0.437500 -v 0.218750 -0.281250 0.429688 -v -0.218750 -0.281250 0.429688 -v 0.210938 -0.226563 0.468750 -v -0.210938 -0.226563 0.468750 -v 0.203125 -0.171875 0.500000 -v -0.203125 -0.171875 0.500000 +v 0 0.429688 0.742188 +v 0.21875 -0.28125 0.429688 v 0.210938 -0.390625 0.164063 +v 0.59375 -0.125 -0.164063 +v -0.59375 -0.125 -0.164063 v -0.210938 -0.390625 0.164063 -v 0.296875 -0.312500 -0.265625 -v -0.296875 -0.312500 -0.265625 -v 0.343750 -0.148438 -0.539063 -v -0.343750 -0.148438 -0.539063 -v 0.453125 0.867188 -0.382813 -v -0.453125 0.867188 -0.382813 -v 0.453125 0.929688 -0.070313 -v -0.453125 0.929688 -0.070313 -v 0.453125 0.851563 0.234375 -v -0.453125 0.851563 0.234375 -v 0.460938 0.523438 0.429688 -v -0.460938 0.523438 0.429688 -v 0.726563 0.406250 0.335938 -v -0.726563 0.406250 0.335938 -v 0.632813 0.453125 0.281250 -v -0.632813 0.453125 0.281250 -v 0.640625 0.703125 0.054688 -v -0.640625 0.703125 0.054688 -v 0.796875 0.562500 0.125000 -v -0.796875 0.562500 0.125000 -v 0.796875 0.617188 -0.117188 -v -0.796875 0.617188 -0.117188 -v 0.640625 0.750000 -0.195313 -v -0.640625 0.750000 -0.195313 -v 0.640625 0.679688 -0.445313 -v -0.640625 0.679688 -0.445313 -v 0.796875 0.539063 -0.359375 -v -0.796875 0.539063 -0.359375 -v 0.617188 0.328125 -0.585938 -v -0.617188 0.328125 -0.585938 -v 0.484375 0.023438 -0.546875 -v -0.484375 0.023438 -0.546875 -v 0.820313 0.328125 -0.203125 -v -0.820313 0.328125 -0.203125 -v 0.406250 -0.171875 0.148438 -v -0.406250 -0.171875 0.148438 -v 0.429688 -0.195313 -0.210938 -v -0.429688 -0.195313 -0.210938 -v 0.890625 0.406250 -0.234375 -v -0.890625 0.406250 -0.234375 -v 0.773438 -0.140625 -0.125000 -v -0.773438 -0.140625 -0.125000 -v 1.039063 -0.101563 -0.328125 -v -1.039063 -0.101563 -0.328125 -v 1.281250 0.054688 -0.429688 -v -1.281250 0.054688 -0.429688 -v 1.351563 0.320313 -0.421875 -v -1.351563 0.320313 -0.421875 -v 1.234375 0.507813 -0.421875 -v -1.234375 0.507813 -0.421875 -v 1.023438 0.476563 -0.312500 -v -1.023438 0.476563 -0.312500 -v 1.015625 0.414063 -0.289063 -v -1.015625 0.414063 -0.289063 -v 1.187500 0.437500 -0.390625 -v -1.187500 0.437500 -0.390625 -v 1.265625 0.289063 -0.406250 -v -1.265625 0.289063 -0.406250 -v 1.210938 0.078125 -0.406250 -v -1.210938 0.078125 -0.406250 -v 1.031250 -0.039063 -0.304688 -v -1.031250 -0.039063 -0.304688 -v 0.828125 -0.070313 -0.132813 -v -0.828125 -0.070313 -0.132813 -v 0.921875 0.359375 -0.218750 -v -0.921875 0.359375 -0.218750 +v -0.21875 -0.28125 0.429688 +v 0.4375 -0.09375 0.46875 +v 0.203125 -0.171875 0.5 +v 0.210938 -0.226563 0.46875 +v -0.210938 -0.226563 0.46875 +v -0.203125 -0.171875 0.5 +v -0.4375 -0.09375 0.46875 v 0.945313 0.304688 -0.289063 -v -0.945313 0.304688 -0.289063 -v 0.882813 -0.023438 -0.210938 -v -0.882813 -0.023438 -0.210938 -v 1.039063 0.000000 -0.367188 -v -1.039063 0.000000 -0.367188 -v 1.187500 0.093750 -0.445313 -v -1.187500 0.093750 -0.445313 -v 1.234375 0.250000 -0.445313 -v -1.234375 0.250000 -0.445313 -v 1.171875 0.359375 -0.437500 -v -1.171875 0.359375 -0.437500 -v 1.023438 0.343750 -0.359375 -v -1.023438 0.343750 -0.359375 -v 0.843750 0.289063 -0.210938 -v -0.843750 0.289063 -0.210938 -v 0.835938 0.171875 -0.273438 -v -0.835938 0.171875 -0.273438 -v 0.757813 0.093750 -0.273438 -v -0.757813 0.093750 -0.273438 -v 0.820313 0.085938 -0.273438 -v -0.820313 0.085938 -0.273438 -v 0.843750 0.015625 -0.273438 -v -0.843750 0.015625 -0.273438 -v 0.812500 -0.015625 -0.273438 -v -0.812500 -0.015625 -0.273438 -v 0.726563 0.000000 -0.070313 -v -0.726563 0.000000 -0.070313 -v 0.718750 -0.023438 -0.171875 -v -0.718750 -0.023438 -0.171875 -v 0.718750 0.039063 -0.187500 -v -0.718750 0.039063 -0.187500 -v 0.796875 0.203125 -0.210938 -v -0.796875 0.203125 -0.210938 -v 0.890625 0.242188 -0.265625 -v -0.890625 0.242188 -0.265625 -v 0.890625 0.234375 -0.320313 -v -0.890625 0.234375 -0.320313 -v 0.812500 -0.015625 -0.320313 -v -0.812500 -0.015625 -0.320313 -v 0.851563 0.015625 -0.320313 -v -0.851563 0.015625 -0.320313 -v 0.828125 0.078125 -0.320313 -v -0.828125 0.078125 -0.320313 -v 0.765625 0.093750 -0.320313 -v -0.765625 0.093750 -0.320313 -v 0.843750 0.171875 -0.320313 -v -0.843750 0.171875 -0.320313 -v 1.039063 0.328125 -0.414063 -v -1.039063 0.328125 -0.414063 -v 1.187500 0.343750 -0.484375 -v -1.187500 0.343750 -0.484375 -v 1.257813 0.242188 -0.492188 -v -1.257813 0.242188 -0.492188 -v 1.210938 0.085938 -0.484375 -v -1.210938 0.085938 -0.484375 -v 1.046875 0.000000 -0.421875 -v -1.046875 0.000000 -0.421875 -v 0.882813 -0.015625 -0.265625 -v -0.882813 -0.015625 -0.265625 -v 0.953125 0.289063 -0.343750 -v -0.953125 0.289063 -0.343750 -v 0.890625 0.109375 -0.328125 -v -0.890625 0.109375 -0.328125 -v 0.937500 0.062500 -0.335938 -v -0.937500 0.062500 -0.335938 -v 1.000000 0.125000 -0.367188 -v -1.000000 0.125000 -0.367188 -v 0.960938 0.171875 -0.351563 -v -0.960938 0.171875 -0.351563 -v 1.015625 0.234375 -0.375000 -v -1.015625 0.234375 -0.375000 -v 1.054688 0.187500 -0.382813 -v -1.054688 0.187500 -0.382813 v 1.109375 0.210938 -0.390625 +v 1.171875 0.359375 -0.4375 +v -1.171875 0.359375 -0.4375 v -1.109375 0.210938 -0.390625 -v 1.085938 0.273438 -0.390625 -v -1.085938 0.273438 -0.390625 -v 1.023438 0.437500 -0.484375 -v -1.023438 0.437500 -0.484375 -v 1.250000 0.468750 -0.546875 -v -1.250000 0.468750 -0.546875 -v 1.367188 0.296875 -0.500000 -v -1.367188 0.296875 -0.500000 -v 1.312500 0.054688 -0.531250 -v -1.312500 0.054688 -0.531250 -v 1.039063 -0.085938 -0.492188 -v -1.039063 -0.085938 -0.492188 -v 0.789063 -0.125000 -0.328125 -v -0.789063 -0.125000 -0.328125 -v 0.859375 0.382813 -0.382813 +v -0.945313 0.304688 -0.289063 +v 1.25 0.46875 -0.546875 +v 1.351563 0.320313 -0.421875 +v 1.3125 0.054688 -0.53125 +v -1.3125 0.054688 -0.53125 +v -1.351563 0.320313 -0.421875 +v -1.25 0.46875 -0.546875 +v -0.789063 -0.125 -0.328125 +v -0.640625 -0.007813 -0.429688 +v -0.59375 -0.125 -0.164063 +v -0.773438 -0.140625 -0.125 +v 0.59375 -0.125 -0.164063 +v 0.640625 -0.007813 -0.429688 +v 0.789063 -0.125 -0.328125 +v 0.773438 -0.140625 -0.125 v -0.859375 0.382813 -0.382813 -v -1.023438 0.476563 -0.312500 +v -0.773438 0.265625 -0.4375 +v 0.773438 0.265625 -0.4375 +v 0.859375 0.382813 -0.382813 +v -0.890625 0.40625 -0.234375 +v -0.820313 0.328125 -0.203125 +v 0.820313 0.328125 -0.203125 +v 0.890625 0.40625 -0.234375 +v -1.039063 -0.085938 -0.492188 +v 1.039063 -0.085938 -0.492188 v -1.234375 0.507813 -0.421875 -v -0.890625 0.406250 -0.234375 +v 1.234375 0.507813 -0.421875 +v -1.28125 0.054688 -0.429688 +v 1.28125 0.054688 -0.429688 +v -1.039063 -0.101563 -0.328125 +v 1.039063 -0.101563 -0.328125 +v -1.234375 0.25 -0.445313 +v 1.234375 0.25 -0.445313 +v -1.210938 0.085938 -0.484375 +v 1.210938 0.085938 -0.484375 +v -0.8125 -0.015625 -0.273438 +v -0.882813 -0.015625 -0.265625 +v 0.8125 -0.015625 -0.273438 +v 0.882813 -0.015625 -0.265625 +v -0.765625 0.09375 -0.320313 +v 0.84375 0.171875 -0.320313 +v -0.726563 0 -0.070313 +v -0.859375 0.320313 -0.046875 +v 0.859375 0.320313 -0.046875 +v 0.726563 0 -0.070313 +v 0.820313 0.328125 -0.203125 +v -0.773438 -0.140625 -0.125 +v 0.773438 -0.140625 -0.125 +v -0.59375 -0.125 -0.164063 +v 0.59375 -0.125 -0.164063 +v 1.1875 0.4375 -0.390625 +v -1.351563 0.320313 -0.421875 +v 1.351563 0.320313 -0.421875 +v -1.28125 0.054688 -0.429688 +v 1.28125 0.054688 -0.429688 +v -1.039063 -0.101563 -0.328125 +v 1.039063 -0.101563 -0.328125 +v 1.234375 0.507813 -0.421875 +v 0.890625 0.40625 -0.234375 +v -0.34375 -0.148438 -0.539063 +v -0.640625 -0.007813 -0.429688 +v 0.34375 -0.148438 -0.539063 +v 0.640625 -0.007813 -0.429688 +v -0.460938 0.4375 -0.703125 +v -0.773438 0.265625 -0.4375 +v 0.773438 0.265625 -0.4375 +v 0.460938 0.4375 -0.703125 +v -0.726563 0 -0.070313 +v 0.726563 0 -0.070313 +v -0.796875 0.617188 -0.117188 +v -0.796875 0.539063 -0.359375 v -0.820313 0.328125 -0.203125 +v 0.796875 0.539063 -0.359375 +v 0.820313 0.328125 -0.203125 +v 0.796875 0.617188 -0.117188 +v -0.859375 0.320313 -0.046875 +v 0.859375 0.320313 -0.046875 +v -0.796875 0.40625 0.460938 +v 0.796875 0.40625 0.460938 +v -0.828125 0.148438 0.445313 +v 0.828125 0.148438 0.445313 +v -0.460938 0.523438 0.429688 +v -0.195313 0.664063 0.617188 +v 0.195313 0.664063 0.617188 +v 0.460938 0.523438 0.429688 +v -0.453125 0.851563 0.234375 +v 0 0.898438 0.289063 +v 0 0.898438 0.289063 +v 0.453125 0.851563 0.234375 +v 0 0.898438 -0.546875 +v 0 0.898438 -0.546875 +v 0 0.5625 -0.851563 +v 0 0.5625 -0.851563 +v 0 0.984375 -0.078125 +v 0 0.984375 -0.078125 +v 0 0.070313 -0.828125 +v 0 0.070313 -0.828125 +v -0.257813 -0.3125 0.554688 +v 0.257813 -0.3125 0.554688 +v 0 -0.382813 -0.351563 +v 0 -0.460938 0.1875 +v 0 -0.382813 -0.351563 +v 0 -0.460938 0.1875 +v -0.4375 -0.140625 0.53125 +v -0.203125 -0.171875 0.5 +v -0.203125 -0.1875 0.5625 +v -0.4375 -0.140625 0.53125 +v 0.203125 -0.1875 0.5625 +v 0.203125 -0.171875 0.5 +v 0.4375 -0.140625 0.53125 +v 0.4375 -0.140625 0.53125 +v -0.234375 -0.25 0.554688 +v -0.234375 -0.25 0.554688 +v 0.234375 -0.25 0.554688 +v 0.234375 -0.25 0.554688 +v -0.289063 -0.710938 0.382813 +v -0.367188 -0.890625 0.53125 +v 0.367188 -0.890625 0.53125 +v 0.25 -0.5 0.390625 +v 0.328125 -0.945313 0.523438 +v 0 -0.804688 0.34375 +v 0 -0.984375 0.578125 +v -0.328125 -0.945313 0.523438 +v 0 -0.804688 0.34375 +v 0 -0.984375 0.578125 +v -0.632813 -0.039063 0.539063 +v 0.632813 -0.039063 0.539063 +v -0.859375 0.429688 0.59375 +v 0.859375 0.429688 0.59375 +v -0.710938 0.484375 0.625 +v 0.710938 0.484375 0.625 +v -0.15625 0.71875 0.757813 +v 0.15625 0.71875 0.757813 +v -0.0625 0.492188 0.75 +v 0.0625 0.492188 0.75 +v -0.203125 0.171875 0.75 +v -0.1875 0.15625 0.773438 +v -0.171875 0.21875 0.78125 +v -0.195313 0.226563 0.75 +v 0.171875 0.21875 0.78125 +v 0.1875 0.15625 0.773438 +v 0.203125 0.171875 0.75 +v 0.195313 0.226563 0.75 +v -0.179688 0.296875 0.78125 +v -0.195313 0.296875 0.757813 +v 0.179688 0.296875 0.78125 +v 0.195313 0.296875 0.757813 +v -0.210938 0.375 0.78125 +v -0.234375 0.359375 0.757813 +v 0.210938 0.375 0.78125 +v 0.234375 0.359375 0.757813 +v -0.242188 0.125 0.757813 +v -0.226563 0.109375 0.78125 +v 0.226563 0.109375 0.78125 +v 0.242188 0.125 0.757813 +v -0.375 0.085938 0.726563 +v -0.375 0.0625 0.742188 +v 0.375 0.0625 0.742188 +v 0.375 0.085938 0.726563 +v -0.460938 0.117188 0.703125 +v -0.476563 0.101563 0.71875 +v 0.476563 0.101563 0.71875 +v 0.460938 0.117188 0.703125 +v -0.546875 0.210938 0.671875 +v -0.578125 0.195313 0.679688 +v 0.578125 0.195313 0.679688 +v 0.546875 0.210938 0.671875 +v -0.554688 0.28125 0.671875 +v -0.585938 0.289063 0.6875 +v 0.585938 0.289063 0.6875 +v 0.554688 0.28125 0.671875 +v -0.53125 0.335938 0.679688 +v -0.5625 0.351563 0.695313 +v 0.5625 0.351563 0.695313 +v 0.53125 0.335938 0.679688 +v -0.414063 0.390625 0.75 +v -0.421875 0.398438 0.773438 +v 0.421875 0.398438 0.773438 +v 0.414063 0.390625 0.75 +v -0.335938 0.40625 0.75 +v -0.335938 0.429688 0.757813 +v 0.335938 0.429688 0.757813 +v 0.335938 0.40625 0.75 +v -0.28125 0.398438 0.765625 +v -0.273438 0.421875 0.773438 +v 0.273438 0.421875 0.773438 +v 0.28125 0.398438 0.765625 +v -0.25 0.46875 0.757813 +v 0.25 0.46875 0.757813 +v -0.726563 0.203125 0.601563 +v 0.726563 0.203125 0.601563 +v -0.398438 -0.046875 0.671875 +v 0.398438 -0.046875 0.671875 +v -0.203125 0.09375 0.742188 +v 0.203125 0.09375 0.742188 +v -0.125 0.304688 0.765625 +v 0.125 0.304688 0.765625 +v 0.09375 -0.75 0.664063 +v -0.109375 -0.71875 0.734375 +v -0.046875 -0.851563 0.632813 +v -0.0625 -0.882813 0.695313 +v 0.117188 -0.835938 0.710938 +v 0.109375 -0.71875 0.734375 +v -0.164063 -0.242188 0.710938 +v -0.125 -0.101563 0.8125 +v 0.125 -0.101563 0.8125 +v 0.164063 -0.242188 0.710938 +v -0.179688 -0.3125 0.710938 +v -0.257813 -0.3125 0.554688 +v 0.257813 -0.3125 0.554688 +v 0.179688 -0.3125 0.710938 +v 0 -0.328125 0.742188 +v -0.085938 -0.289063 0.742188 +v 0.085938 -0.289063 0.742188 +v -0.125 -0.226563 0.75 +v 0.125 -0.226563 0.75 +v -0.101563 -0.148438 0.742188 +v 0.101563 -0.148438 0.742188 +v 0 -0.140625 0.742188 +v -0.09375 -0.273438 0.78125 +v 0 -0.289063 0.804688 +v 0 -0.1875 0.796875 +v 0.09375 -0.273438 0.78125 +v 0 -0.320313 0.78125 +v -0.367188 -0.890625 0.53125 +v 0.367188 -0.890625 0.53125 +v -0.328125 -0.945313 0.523438 +v 0.328125 -0.945313 0.523438 +v 0 -0.984375 0.578125 +v -0.3125 0.640625 0.835938 +v 0.3125 0.640625 0.835938 +v 0 0.429688 0.742188 +v -0.0625 0.492188 0.75 +v 0.0625 0.492188 0.75 +v -0.15625 0.71875 0.757813 +v 0.15625 0.71875 0.757813 +v -0.710938 0.484375 0.625 +v 0.710938 0.484375 0.625 +v -0.859375 0.429688 0.59375 +v 0.859375 0.429688 0.59375 +v -0.828125 0.148438 0.445313 +v 0.828125 0.148438 0.445313 +v -0.632813 -0.039063 0.539063 +v 0.632813 -0.039063 0.539063 +v -0.46875 0.242188 0.737813 +v -0.4375 0.164063 0.745625 +v 0.4375 0.164063 0.745625 +v 0.46875 0.242188 0.737813 +v -0.351563 0.132813 0.76125 +v 0.351563 0.132813 0.76125 +v -0.273438 0.164063 0.776875 +v 0.273438 0.164063 0.776875 +v -0.242188 0.242188 0.776875 +v 0.242188 0.242188 0.776875 +v -0.273438 0.328125 0.776875 +v 0.273438 0.328125 0.776875 +v -0.351563 0.359375 0.76125 +v 0.351563 0.359375 0.76125 +v -0.4375 0.328125 0.745625 +v 0.4375 0.328125 0.745625 +v -0.5625 0.242188 0.651875 +v -0.5 0.390625 0.6675 +v 0.5 0.390625 0.6675 +v 0.5625 0.242188 0.651875 +v -0.625 0.242188 0.5425 +v -0.546875 0.4375 0.558125 +v 0.546875 0.4375 0.558125 +v 0.625 0.242188 0.5425 +v -0.351563 0.515625 0.597188 +v -0.351563 0.453125 0.69875 +v 0.351563 0.453125 0.69875 +v 0.351563 0.515625 0.597188 +v -0.203125 0.390625 0.722188 +v 0.203125 0.390625 0.722188 +v -0.15625 0.4375 0.628438 +v 0.15625 0.4375 0.628438 +v -0.078125 0.242188 0.63625 +v -0.140625 0.242188 0.722188 +v 0.140625 0.242188 0.722188 +v 0.078125 0.242188 0.63625 +v -0.203125 0.09375 0.722188 +v 0.203125 0.09375 0.722188 +v -0.15625 0.054688 0.628438 +v 0.15625 0.054688 0.628438 +v -0.351563 0.03125 0.69875 +v -0.351563 -0.023438 0.597188 +v 0.351563 0.03125 0.69875 +v 0.351563 -0.023438 0.597188 +v -0.5 0.09375 0.6675 +v 0.5 0.09375 0.6675 +v -0.546875 0.054688 0.558125 +v 0.546875 0.054688 0.558125 vt 0.315596 0.792535 vt 0.331462 0.787091 vt 0.331944 0.799704 vt 0.049262 0.798007 vt 0.050304 0.785428 -vt 0.065913 0.791570 +vt 0.065913 0.79157 vt 0.321453 0.778649 vt 0.060677 0.777438 vt 0.310368 0.778802 vt 0.071744 0.778083 -vt 0.302416 0.786560 +vt 0.302416 0.78656 vt 0.079345 0.786186 vt 0.301514 0.798474 vt 0.079717 0.798128 -vt 0.308740 0.806873 +vt 0.30874 0.806873 vt 0.072125 0.806199 vt 0.321648 0.808687 vt 0.059149 0.807438 -vt 0.048462 0.201858 -vt 0.040084 0.207259 -vt 0.043232 0.202821 -vt 0.043249 0.220655 -vt 0.040093 0.216224 -vt 0.048480 0.221607 -vt 0.563710 0.649220 +vt 0.572425 0.670929 vt 0.540594 0.657349 vt 0.547067 0.627433 vt 0.974643 0.218739 vt 0.968169 0.188824 -vt 0.991286 0.196952 +vt 1 0.175243 vt 0.166564 0.702856 vt 0.160061 0.635503 -vt 0.218800 0.643864 -vt 0.646379 0.202310 +vt 0.258456 0.593142 +vt 0.686035 0.253032 vt 0.587641 0.210669 vt 0.594146 0.143318 vt 0.231653 0.710981 @@ -553,29 +367,17 @@ vt 0.174315 0.716236 vt 0.601897 0.129938 vt 0.608704 0.118775 vt 0.659234 0.135195 -vt 0.266169 0.503056 -vt 0.270502 0.531304 -vt 0.237927 0.525958 -vt 0.665505 0.320215 -vt 0.698081 0.314870 -vt 0.693747 0.343118 -vt 0.392095 0.783569 -vt 0.421339 0.774990 -vt 0.422693 0.793271 -vt 0.628129 0.465996 -vt 0.613733 0.456434 -vt 0.634389 0.436387 -vt 0.501778 0.870396 -vt 0.507486 0.857499 -vt 0.528577 0.865850 -vt 0.643384 0.583025 -vt 0.644052 0.562152 -vt 0.656465 0.561923 +vt 0.467321 0.8712 +vt 0.51102 0.84743 +vt 0.528822 0.875551 +vt 0.651887 0.586528 +vt 0.634422 0.561399 +vt 0.669345 0.535984 vt 0.766386 0.787223 -vt 0.745292 0.810963 +vt 0.756895 0.826983 vt 0.708792 0.802136 vt 0.769147 0.634951 -vt 0.732033 0.641034 +vt 0.719538 0.655221 vt 0.711181 0.618495 vt 0.849461 0.545148 vt 0.823375 0.497849 @@ -586,211 +388,97 @@ vt 0.643837 0.668801 vt 0.623443 0.718088 vt 0.572425 0.724426 vt 0.726607 0.540494 -vt 0.753364 0.518460 +vt 0.753364 0.51846 vt 0.715449 0.680462 vt 0.749227 0.698466 -vt 0.695922 0.534580 +vt 0.695922 0.53458 vt 0.693526 0.510498 vt 0.772837 0.655221 -vt 0.784620 0.679820 -vt 0.718163 0.580185 +vt 0.78462 0.67982 vt 0.809389 0.599417 -vt 0.761761 0.743313 -vt 0.667750 0.767676 -vt 0.693110 0.564191 -vt 0.797155 0.722534 +vt 0.66775 0.767676 vt 0.682009 0.616616 vt 0.795802 0.787304 -vt 0.719538 0.655221 -vt 0.756895 0.826983 vt 0.782765 0.655221 -vt 0.695179 0.821970 +vt 0.695179 0.82197 vt 0.843059 0.610497 vt 0.635588 0.780626 -vt 0.634422 0.561399 -vt 0.628274 0.581967 -vt 0.511020 0.847430 -vt 0.533908 0.850607 -vt 0.633815 0.551490 +vt 0.627145 0.592333 +vt 0.544318 0.85362 vt 0.613046 0.571327 vt 0.530368 0.831407 -vt 0.501394 0.842435 -vt 0.626589 0.538875 -vt 0.604527 0.544684 -vt 0.508929 0.810914 -vt 0.492547 0.829318 -vt 0.618247 0.522587 +vt 0.612569 0.491986 vt 0.602583 0.501781 -vt 0.480939 0.813120 +vt 0.45471 0.792385 vt 0.469234 0.787943 -vt 0.616652 0.502716 -vt 0.613925 0.497595 -vt 0.459358 0.796431 -vt 0.462840 0.801566 -vt 0.644899 0.511966 -vt 0.630336 0.517087 -vt 0.628893 0.504351 vt 0.635735 0.498392 -vt 0.458270 0.813966 -vt 0.469630 0.821874 vt 0.457144 0.833207 -vt 0.449054 0.817297 -vt 0.637359 0.534149 -vt 0.654293 0.524569 -vt 0.464258 0.849211 -vt 0.482600 0.837505 -vt 0.644187 0.548520 -vt 0.659377 0.540935 -vt 0.478087 0.863369 -vt 0.493557 0.851414 -vt 0.597230 0.539263 -vt 0.595257 0.495349 -vt 0.466971 0.777596 -vt 0.507407 0.801398 -vt 0.605628 0.572478 -vt 0.534801 0.825096 -vt 0.627145 0.592333 -vt 0.544318 0.853620 -vt 0.651887 0.586528 -vt 0.528822 0.875551 -vt 0.665532 0.557472 -vt 0.492878 0.878439 -vt 0.669345 0.535984 -vt 0.467321 0.871200 -vt 0.612569 0.491986 -vt 0.454710 0.792385 -vt 0.619277 0.495381 -vt 0.454636 0.800448 -vt 0.628580 0.496763 -vt 0.451294 0.809743 -vt 0.636682 0.490206 -vt 0.440853 0.813605 -vt 0.652342 0.504728 -vt 0.446182 0.836397 -vt 0.664409 0.519225 -vt 0.453285 0.856119 -vt 0.666191 0.492411 +vt 0.634389 0.436387 vt 0.717596 0.474672 vt 0.382398 0.879324 -vt 0.427166 0.842398 -vt 0.681733 0.511408 +vt 0.392095 0.783569 vt 0.427493 0.877628 -vt 0.435523 0.867805 -vt 0.685777 0.532869 -vt 0.453231 0.887054 -vt 0.588528 0.478377 -vt 0.454313 0.762782 -vt 0.446975 0.900429 -vt 0.713425 0.237886 -vt 0.709019 0.215724 -vt 0.755152 0.224403 -vt 0.762923 0.242445 -vt 0.327574 0.621771 -vt 0.281440 0.630451 -vt 0.285847 0.608289 -vt 0.335345 0.603729 vt 0.576794 0.465515 +vt 0.448347 0.745304 vt 0.583867 0.423087 vt 0.405805 0.730353 -vt 0.448347 0.745304 -vt 0.686035 0.253032 -vt 0.258456 0.593142 -vt 0.683851 0.556229 -vt 0.482266 0.899349 -vt 0.670531 0.597684 -vt 0.532990 0.898426 -vt 0.630909 0.604157 -vt 0.553941 0.861896 -vt 0.596864 0.576275 -vt 0.542184 0.818594 -vt 0.585561 0.529242 -vt 0.503791 0.785451 -vt 0.572425 0.529736 -vt 0.510638 0.773572 -vt 0.587548 0.588270 -vt 0.557294 0.815416 +vt 0.53299 0.898426 vt 0.629961 0.623919 vt 0.572425 0.868524 +vt 0.587548 0.58827 +vt 0.557294 0.815416 +vt 0.572425 0.529736 +vt 0.510638 0.773572 vt 0.548104 0.914571 -vt 0.488130 0.914571 -vt 0.658830 0.266292 -vt 0.631691 0.281488 -vt 0.204112 0.564686 -vt 0.231252 0.579881 +vt 0.446975 0.900429 +vt 0.665505 0.320215 vt 0.706402 0.288928 +vt 0.237927 0.525958 vt 0.278823 0.557246 -vt 0.743528 0.317934 -vt 0.752264 0.346660 -vt 0.324686 0.499513 -vt 0.315950 0.528240 -vt 0.743309 0.289810 +vt 0.752264 0.34666 +vt 0.743309 0.28981 vt 0.315731 0.556363 -vt 0.700326 0.147967 -vt 0.272746 0.698208 +vt 0.324686 0.499513 +vt 0.713425 0.237886 +vt 0.285847 0.608289 vt 0.795874 0.266472 -vt 0.775660 0.289442 +vt 0.77566 0.289442 vt 0.757507 0.263314 vt 0.348083 0.556732 -vt 0.329929 0.582860 +vt 0.329929 0.58286 vt 0.368297 0.579702 -vt 0.804056 0.232825 -vt 0.376478 0.613349 -vt 0.810124 0.179100 -vt 0.382547 0.667075 -vt 0.753847 0.157090 +vt 0.762923 0.242445 +vt 0.335345 0.603729 vt 0.811201 0.146834 vt 0.383624 0.699341 -vt 0.326269 0.689085 +vt 0.757541 0.138176 +vt 0.329963 0.708 vt 0.879685 0.183943 -vt 0.888071 0.157228 -vt 0.460496 0.688946 -vt 0.452109 0.662231 -vt 0.925222 0.140531 vt 0.947451 0.149372 vt 0.519876 0.696801 -vt 0.497647 0.705643 -vt 0.876420 0.258223 +vt 0.452109 0.662231 +vt 0.87642 0.258223 vt 0.946138 0.286262 -vt 0.518561 0.559910 +vt 0.518561 0.55991 vt 0.448843 0.587951 -vt 0.829953 0.196170 -vt 0.837053 0.152275 -vt 0.409477 0.693900 -vt 0.402377 0.650004 -vt 0.829888 0.255993 -vt 0.402311 0.590181 -vt 0.852096 0.297194 -vt 0.813695 0.289418 -vt 0.424519 0.548979 -vt 0.386117 0.556756 -vt 0.820842 0.328587 -vt 0.789451 0.311961 -vt 0.393264 0.517587 -vt 0.361873 0.534212 vt 0.840465 0.403536 -vt 0.762603 0.423087 vt 0.412887 0.442637 +vt 0.762603 0.423087 vt 0.335024 0.423087 vt 0.909248 0.345901 -vt 0.481670 0.500271 -vt 0.676670 0.402805 +vt 0.48167 0.500271 +vt 0.67667 0.402805 vt 0.249092 0.443369 -vt 0.573469 0.193539 -vt 0.579214 0.151927 -vt 0.151632 0.694246 -vt 0.145888 0.652633 -vt 0.546919 0.227092 -vt 0.536510 0.214419 -vt 0.119340 0.619080 -vt 0.108931 0.631753 +vt 0.578472 0.119429 +vt 0.15089 0.726744 vt 0.588792 0.317539 +vt 0.546919 0.227092 vt 0.161214 0.528634 -vt 0.630429 0.371564 -vt 0.202851 0.474609 +vt 0.11934 0.61908 vt 0.657494 0.118541 vt 0.164237 0.319427 vt 0.169464 0.304721 -vt 0.210459 0.345510 +vt 0.210459 0.34551 vt 0.169574 0.118572 vt 0.164356 0.103821 vt 0.210731 0.077759 @@ -799,56 +487,26 @@ vt 0.589956 0.115821 vt 0.153468 0.300432 vt 0.153526 0.122857 vt 0.162374 0.730353 -vt 0.578472 0.119429 -vt 0.553653 0.120209 -vt 0.126070 0.725964 -vt 0.150890 0.726744 -vt 0.546510 0.159800 -vt 0.509384 0.119033 -vt 0.081800 0.727137 -vt 0.118929 0.686371 -vt 0.534072 0.185482 -vt 0.106492 0.660689 -vt 0.462352 0.161885 -vt 0.478174 0.145123 -vt 0.493641 0.175543 -vt 0.505521 0.150780 -vt 0.077939 0.695390 -vt 0.050592 0.701044 -vt 0.066060 0.670626 -vt 0.034770 0.684282 +vt 0.505521 0.15078 vt 0.476706 0.124129 vt 0.049122 0.722039 -vt 0.465324 0.131169 +vt 0.118929 0.686371 vt 0.037741 0.714998 -vt 0.446348 0.149671 -vt 0.018765 0.696495 -vt 0.445483 0.184898 -vt 0.427581 0.175095 -vt 0.000000 0.671069 -vt 0.017903 0.661268 -vt 0.480167 0.198327 vt 0.052588 0.647841 -vt 0.521714 0.207472 -vt 0.094135 0.638699 +vt 0 0.671069 +vt 0.465324 0.131169 +vt 0.480167 0.198327 +vt 0.427581 0.175095 vt 0.701979 0.120236 -vt 0.274400 0.725940 -vt 0.757541 0.138176 -vt 0.329963 0.708000 +vt 0.2744 0.72594 vt 0.817327 0.117813 vt 0.389751 0.728363 vt 0.844767 0.126748 vt 0.417191 0.719428 -vt 0.893893 0.126476 -vt 0.466319 0.719698 -vt 0.936543 0.115821 -vt 0.508970 0.730353 vt 0.965717 0.128368 vt 0.538144 0.717805 vt 0.989276 0.166159 vt 0.561701 0.680013 -vt 1.000000 0.175243 -vt 0.572425 0.670929 vt 0.289028 0.269037 vt 0.283878 0.263049 vt 0.299187 0.258321 @@ -862,10 +520,10 @@ vt 0.316733 0.267304 vt 0.318078 0.163079 vt 0.317052 0.156521 vt 0.335398 0.269583 -vt 0.330421 0.276220 +vt 0.330421 0.27622 vt 0.335777 0.154335 vt 0.330824 0.147649 -vt 0.278552 0.277080 +vt 0.278552 0.27708 vt 0.273734 0.272912 vt 0.273975 0.150706 vt 0.278818 0.146548 @@ -873,13 +531,13 @@ vt 0.271078 0.306358 vt 0.264864 0.305818 vt 0.265194 0.117691 vt 0.271427 0.117166 -vt 0.278613 0.324240 +vt 0.278613 0.32424 vt 0.274006 0.327477 vt 0.274436 0.095993 vt 0.279049 0.099253 vt 0.298062 0.342565 -vt 0.294660 0.349561 -vt 0.295240 0.073895 +vt 0.29466 0.349561 +vt 0.29524 0.073895 vt 0.298634 0.080932 vt 0.312476 0.342961 vt 0.315033 0.350198 @@ -888,12 +546,12 @@ vt 0.313108 0.080584 vt 0.323281 0.337709 vt 0.328696 0.344302 vt 0.329405 0.079293 -vt 0.323940 0.085897 +vt 0.32394 0.085897 vt 0.335361 0.313857 vt 0.339396 0.315576 vt 0.340031 0.108187 vt 0.335968 0.109893 -vt 0.339920 0.298303 +vt 0.33992 0.298303 vt 0.345292 0.298556 vt 0.345869 0.125306 vt 0.340471 0.125531 @@ -901,158 +559,63 @@ vt 0.339277 0.286081 vt 0.344398 0.284332 vt 0.344895 0.139582 vt 0.339764 0.137799 -vt 0.345671 0.260159 vt 0.355483 0.280619 vt 0.356003 0.143373 -vt 0.346021 0.163854 -vt 0.356162 0.297750 -vt 0.356783 0.126174 -vt 0.349494 0.319809 -vt 0.350195 0.103982 -vt 0.333524 0.354692 -vt 0.334295 0.068869 -vt 0.317323 0.364551 -vt 0.318050 0.058911 -vt 0.293154 0.361782 -vt 0.293765 0.061619 -vt 0.263750 0.335417 -vt 0.264168 0.087998 -vt 0.251373 0.309082 -vt 0.251676 0.114380 +vt 0.296951 0.385966 +vt 0.29765 0.037339 +vt 0.236517 0.317748 +vt 0.236802 0.105655 vt 0.264926 0.265507 vt 0.265122 0.158092 -vt 0.278030 0.255522 -vt 0.278212 0.168150 vt 0.320744 0.246538 vt 0.320956 0.177355 -vt 0.296570 0.247318 -vt 0.296748 0.176443 -vt 0.038845 0.211743 -vt 0.047440 0.211734 -vt 0.055230 0.211728 -vt 0.057303 0.228458 -vt 0.057278 0.194991 -vt 0.041287 0.229096 -vt 0.041253 0.194380 -vt 0.032564 0.220061 -vt 0.032546 0.203437 -vt 0.030743 0.211752 +vt 0.048462 0.201858 +vt 0.061533 0.231825 +vt 0.040093 0.216224 vt 0.029931 0.223131 -vt 0.028053 0.211756 -vt 0.029906 0.200372 -vt 0.038587 0.233067 vt 0.038544 0.190412 -vt 0.061533 0.231825 vt 0.061505 0.191616 -vt 0.057382 0.211726 vt 0.168191 0.258703 vt 0.213958 0.246887 -vt 0.214040 0.176591 +vt 0.21404 0.176591 vt 0.168236 0.164676 vt 0.148297 0.258447 vt 0.138777 0.299079 vt 0.138791 0.124216 vt 0.148319 0.164919 -vt 0.115455 0.259296 -vt 0.109657 0.296761 -vt 0.109611 0.126556 -vt 0.115440 0.164070 -vt 0.119233 0.228698 -vt 0.156540 0.233552 +vt 0.148476 0.211699 +vt 0.15654 0.233552 vt 0.156556 0.189842 -vt 0.119230 0.194690 vt 0.173998 0.244074 vt 0.174035 0.179329 -vt 0.195860 0.238258 +vt 0.19586 0.238258 vt 0.195909 0.185188 vt 0.203534 0.211734 -vt 0.252997 0.211802 -vt 0.171285 0.225095 -vt 0.164455 0.211704 -vt 0.180017 0.211713 -vt 0.177113 0.227468 -vt 0.171300 0.198319 -vt 0.177134 0.195952 -vt 0.185539 0.227013 -vt 0.187516 0.221322 -vt 0.187531 0.202116 -vt 0.185563 0.196419 -vt 0.176585 0.232500 vt 0.165993 0.229894 -vt 0.176611 0.190916 -vt 0.166011 0.193512 -vt 0.189406 0.230672 -vt 0.189438 0.192766 -vt 0.193574 0.221791 -vt 0.193592 0.201656 +vt 0.164455 0.211704 vt 0.186479 0.211718 +vt 0.166011 0.193512 vt 0.156919 0.211701 -vt 0.148476 0.211699 -vt 0.427853 0.115821 -vt 0.427581 0.104121 -vt 0.441185 0.104121 -vt 0.427581 0.011703 -vt 0.427581 0.000000 -vt 0.441181 0.011386 -vt 0.067509 0.234045 -vt 0.071465 0.211716 -vt 0.067479 0.189385 -vt 0.119764 0.211696 -vt 0.060932 0.261035 -vt 0.038121 0.261699 -vt 0.038025 0.161756 -vt 0.060860 0.162382 -vt 0.019864 0.255578 -vt 0.019760 0.167921 -vt 0.016617 0.242679 -vt 0.016537 0.180842 -vt 0.014466 0.211775 -vt 0.297831 0.211892 -vt 0.340508 0.212027 -vt 0.356498 0.241635 -vt 0.356742 0.182510 -vt 0.236517 0.317748 -vt 0.236802 0.105655 -vt 0.264789 0.363401 -vt 0.265286 0.059917 -vt 0.296951 0.385966 -vt 0.297650 0.037339 -vt 0.337996 0.385300 -vt 0.338890 0.038126 -vt 0.349401 0.368365 -vt 0.350300 0.055183 -vt 0.377282 0.319664 -vt 0.378129 0.104260 +vt 0.014495 0.288026 +vt 0.014318 0.135436 +vt 0.003828 0.279132 +vt 0.00365 0.144368 +vt 0 0.211799 vt 0.394788 0.292204 vt 0.395576 0.131978 -vt 0.391029 0.270263 -vt 0.391643 0.154015 vt 0.368661 0.212151 vt 0.379482 0.228055 vt 0.379686 0.196331 vt 0.420379 0.261837 vt 0.421104 0.162716 -vt 0.426533 0.298960 -vt 0.427581 0.125377 -vt 0.396664 0.342212 -vt 0.397734 0.081667 vt 0.365156 0.387054 vt 0.366203 0.036443 vt 0.346744 0.416452 vt 0.347768 0.006839 vt 0.278009 0.423087 -vt 0.278714 0.000000 +vt 0.278714 0 vt 0.241964 0.376122 vt 0.242399 0.047096 -vt 0.055563 0.291878 -vt 0.055443 0.131506 -vt 0.014495 0.288026 -vt 0.014318 0.135436 -vt 0.003828 0.279132 -vt 0.003650 0.144368 -vt 0.000113 0.248111 -vt 0.000000 0.175447 -vt 0.000000 0.211799 vt 0.046962 0.798865 vt 0.047306 0.784561 vt 0.334495 0.786358 @@ -1073,7 +636,7 @@ vt 0.024988 0.807478 vt 0.047717 0.829014 vt 0.332112 0.830749 vt 0.355774 0.810244 -vt 0.000000 0.817350 +vt 0 0.81735 vt 0.033121 0.852785 vt 0.345638 0.855146 vt 0.380299 0.821215 @@ -1082,12 +645,12 @@ vt 0.078555 0.829097 vt 0.301299 0.829463 vt 0.295318 0.855146 vt 0.100718 0.807888 -vt 0.280100 0.807291 +vt 0.2801 0.807291 vt 0.123146 0.821929 -vt 0.257070 0.820323 -vt 0.127501 0.768220 +vt 0.25707 0.820323 +vt 0.127501 0.76822 vt 0.103229 0.776171 -vt 0.279000 0.775494 +vt 0.279 0.775494 vt 0.255105 0.766472 vt 0.079351 0.756089 vt 0.303746 0.756492 @@ -1097,9 +660,9 @@ vt 0.049398 0.755271 vt 0.035422 0.733227 vt 0.333706 0.757005 vt 0.348646 0.735604 -vt 0.026877 0.776230 +vt 0.026877 0.77623 vt 0.355274 0.778943 -vt 0.000000 0.770061 +vt 0 0.770061 vt 0.382398 0.773973 vn 0.189764 -0.003571 0.981811 vn 0.646809 -0.758202 0.082095 @@ -1111,59 +674,43 @@ vn -0.085788 -0.982971 0.162389 vn 0.085788 -0.982971 0.162389 vn -0.744835 -0.623768 0.236824 vn 0.744835 -0.623768 0.236824 -vn -0.870968 -0.014710 0.491104 -vn 0.870968 -0.014710 0.491104 +vn -0.870968 -0.01471 0.491104 +vn 0.870968 -0.01471 0.491104 vn -0.758354 0.606128 0.239692 vn 0.758354 0.606128 0.239692 vn -0.085788 0.982513 0.165105 vn 0.085788 0.982513 0.165105 vn 0.655141 0.750633 0.085574 vn -0.655141 0.750633 0.085574 -vn -0.349284 -0.719932 0.599719 -vn -0.173681 0.215735 0.960845 -vn -0.809839 0.388287 0.439741 -vn 0.809839 0.388287 0.439741 -vn 0.173681 0.215735 0.960845 -vn 0.349284 -0.719932 0.599719 -vn 0.000000 0.794183 0.607654 +vn 0 0.970214 0.242164 vn -0.508652 0.858119 -0.069887 -vn 0.000000 0.487075 0.873348 +vn 0 0.487075 0.873348 +vn 0 0.487075 0.873348 vn 0.508652 0.858119 -0.069887 +vn 0 0.970214 0.242164 vn 0.981414 -0.186682 0.043947 vn 0.569811 -0.821711 0.007813 -vn 0.563463 -0.814570 0.137669 -vn -0.563463 -0.814570 0.137669 +vn 0.330546 -0.943236 0.031281 +vn -0.330546 -0.943236 0.031281 vn -0.569811 -0.821711 0.007813 vn -0.981414 -0.186682 0.043947 vn 0.475845 -0.876247 0.075381 -vn 0.850520 -0.525529 -0.020692 +vn 0.85052 -0.525529 -0.020692 vn 0.876949 -0.163823 0.451766 vn -0.876949 -0.163823 0.451766 -vn -0.850520 -0.525529 -0.020692 +vn -0.85052 -0.525529 -0.020692 vn -0.475845 -0.876247 0.075381 -vn 0.448286 -0.367870 -0.814661 -vn 0.530534 -0.539445 -0.653829 -vn 0.513077 -0.674673 -0.530595 -vn -0.513077 -0.674673 -0.530595 -vn -0.530534 -0.539445 -0.653829 -vn -0.448286 -0.367870 -0.814661 -vn 0.888180 -0.439955 -0.132389 -vn 0.588519 0.226966 0.775933 -vn 0.911527 -0.115268 0.394665 -vn -0.911527 -0.115268 0.394665 -vn -0.588519 0.226966 0.775933 -vn -0.888180 -0.439955 -0.132389 -vn 0.468886 -0.304727 0.829005 -vn 0.251564 0.260781 0.932005 -vn -0.003082 -0.330882 0.943632 -vn 0.003082 -0.330882 0.943632 -vn -0.251564 0.260781 0.932005 -vn -0.468886 -0.304727 0.829005 +vn 0.690054 -0.553209 0.466628 +vn 0.437483 0.001221 0.899197 +vn -0.200934 -0.758141 0.62035 +vn 0.200934 -0.758141 0.62035 +vn -0.437483 0.001221 0.899197 +vn -0.690054 -0.553209 0.466628 vn 0.473067 0.578997 -0.664022 -vn 0.992462 0.028626 -0.118900 +vn 0.716392 0.204474 0.667043 vn 0.459975 -0.380261 -0.802362 vn -0.459975 -0.380261 -0.802362 -vn -0.992462 0.028626 -0.118900 +vn -0.716392 0.204474 0.667043 vn -0.473067 0.578997 -0.664022 vn -0.059908 -0.804712 -0.590594 vn -0.346141 -0.637287 -0.688498 @@ -1178,224 +725,126 @@ vn -0.626057 -0.002686 -0.779748 vn 0.626057 -0.002686 -0.779748 vn -0.593738 0.595264 -0.541368 vn 0.127689 0.703757 0.698843 -vn -0.713828 0.382183 0.586810 -vn 0.713828 0.382183 0.586810 +vn -0.713828 0.382183 0.58681 +vn 0.713828 0.382183 0.58681 vn -0.127689 0.703757 0.698843 -vn 0.378063 0.560045 -0.737144 vn 0.036805 -0.708457 -0.704764 -vn -0.378063 0.560045 -0.737144 vn -0.036805 -0.708457 -0.704764 -vn -0.031556 0.838710 0.543626 -vn 0.031556 0.838710 0.543626 vn -0.361156 0.848689 0.386303 vn 0.361156 0.848689 0.386303 -vn -0.716392 0.204474 0.667043 -vn 0.716392 0.204474 0.667043 -vn -0.662038 -0.413770 0.624866 -vn 0.662038 -0.413770 0.624866 -vn -0.530229 -0.655751 0.537370 -vn 0.530229 -0.655751 0.537370 -vn -0.437483 0.001221 0.899197 -vn 0.550981 -0.138096 0.822993 -vn 0.437483 0.001221 0.899197 -vn -0.550981 -0.138096 0.822993 -vn -0.315958 -0.102298 0.943205 +vn -0.662038 -0.41377 0.624866 +vn 0.662038 -0.41377 0.624866 +vn -0.530229 -0.655751 0.53737 +vn 0.530229 -0.655751 0.53737 +vn 0.99469 -0.078005 0.067019 +vn -0.99469 -0.078005 0.067019 vn 0.608539 0.296121 0.736167 vn -0.608539 0.296121 0.736167 -vn 0.315958 -0.102298 0.943205 -vn -0.445479 -0.088778 0.890866 -vn -0.257698 0.600024 0.757317 -vn 0.257698 0.600024 0.757317 -vn 0.445479 -0.088778 0.890866 -vn -0.327799 0.169927 0.929319 -vn 0.041780 0.927213 0.372112 -vn 0.327799 0.169927 0.929319 -vn -0.041780 0.927213 0.372112 -vn -0.277932 0.260201 0.924680 -vn -0.750725 0.111545 0.651112 -vn 0.750725 0.111545 0.651112 -vn 0.277932 0.260201 0.924680 -vn -0.437910 -0.293985 0.849574 -vn -0.183782 0.036836 0.982269 -vn -0.554216 0.387219 0.736808 -vn -0.814325 0.253426 0.522111 -vn 0.554216 0.387219 0.736808 -vn 0.183782 0.036836 0.982269 -vn 0.437910 -0.293985 0.849574 -vn 0.814325 0.253426 0.522111 -vn -0.326670 -0.001617 0.945128 -vn -0.704337 -0.526872 0.475692 -vn 0.704337 -0.526872 0.475692 -vn 0.326670 -0.001617 0.945128 -vn -0.308786 0.134617 0.941527 -vn -0.629170 -0.371441 0.682730 -vn 0.629170 -0.371441 0.682730 -vn 0.308786 0.134617 0.941527 -vn 0.146184 0.948637 0.280465 -vn -0.137516 0.905820 0.400708 -vn 0.137516 0.905820 0.400708 -vn -0.146184 0.948637 0.280465 -vn 0.723746 0.690023 -0.005219 -vn -0.723746 0.690023 -0.005219 -vn 0.994690 -0.078005 0.067019 -vn -0.994690 -0.078005 0.067019 -vn 0.200934 -0.758141 0.620350 -vn -0.200934 -0.758141 0.620350 -vn -0.541246 -0.672658 0.504501 -vn 0.541246 -0.672658 0.504501 -vn -0.690054 -0.553209 0.466628 -vn 0.690054 -0.553209 0.466628 vn -0.464003 0.686666 0.559557 +vn 0.04178 0.927213 0.372112 vn 0.464003 0.686666 0.559557 -vn -0.827448 -0.135899 0.544786 -vn 0.827448 -0.135899 0.544786 -vn -0.466231 0.808863 0.358196 -vn 0.466231 0.808863 0.358196 -vn -0.743980 -0.022919 0.667776 -vn 0.743980 -0.022919 0.667776 -vn -0.711295 -0.638325 0.294137 -vn 0.711295 -0.638325 0.294137 -vn -0.709769 -0.501999 0.494125 -vn 0.709769 -0.501999 0.494125 -vn -0.818903 -0.425520 0.385113 +vn -0.04178 0.927213 0.372112 +vn -0.814325 0.253426 0.522111 +vn 0.43791 -0.293985 0.849574 +vn -0.88818 -0.439955 -0.132389 vn -0.992523 -0.071444 -0.098758 vn 0.992523 -0.071444 -0.098758 -vn 0.818903 -0.425520 0.385113 -vn -0.439192 -0.273568 0.855708 -vn 0.439192 -0.273568 0.855708 -vn -0.414686 -0.059877 0.907956 -vn 0.414686 -0.059877 0.907956 -vn -0.341563 0.452132 0.823939 -vn 0.341563 0.452132 0.823939 -vn -0.724509 -0.684927 0.076632 -vn -0.987548 -0.123020 0.097995 -vn 0.987548 -0.123020 0.097995 -vn 0.724509 -0.684927 0.076632 -vn -0.572741 -0.088443 0.814936 -vn 0.572741 -0.088443 0.814936 -vn -0.291818 -0.152104 0.944273 +vn 0.88818 -0.439955 -0.132389 +vn 0.713828 0.382183 0.58681 +vn -0.073672 -0.594989 0.800317 +vn 0.073672 -0.594989 0.800317 +vn -0.330546 -0.943236 0.031281 +vn 0.330546 -0.943236 0.031281 vn 0.291818 -0.152104 0.944273 -vn 0.239662 -0.128605 0.962279 -vn -0.239662 -0.128605 0.962279 -vn 0.187017 0.370678 0.909696 -vn -0.187017 0.370678 0.909696 -vn -0.455794 0.423170 0.783044 -vn 0.455794 0.423170 0.783044 -vn -0.543504 -0.813379 -0.207343 -vn -0.560045 -0.814417 -0.151738 -vn 0.560045 -0.814417 -0.151738 -vn 0.543504 -0.813379 -0.207343 -vn -0.615375 -0.087649 -0.783319 -vn -0.447310 0.229530 -0.864406 -vn 0.447310 0.229530 -0.864406 -vn 0.615375 -0.087649 -0.783319 -vn -0.547166 -0.832179 -0.089785 -vn 0.547166 -0.832179 -0.089785 +vn -0.716392 0.204474 0.667043 +vn 0.716392 0.204474 0.667043 +vn -0.662038 -0.41377 0.624866 +vn 0.662038 -0.41377 0.624866 +vn -0.530229 -0.655751 0.53737 +vn 0.530229 -0.655751 0.53737 +vn 0.361156 0.848689 0.386303 +vn -0.127689 0.703757 0.698843 +vn -0.513077 -0.674673 -0.530595 +vn -0.346141 -0.637287 -0.688498 +vn 0.513077 -0.674673 -0.530595 +vn 0.346141 -0.637287 -0.688498 +vn -0.44731 0.22953 -0.864406 +vn -0.626057 -0.002686 -0.779748 +vn 0.626057 -0.002686 -0.779748 +vn 0.44731 0.22953 -0.864406 +vn -0.88818 -0.439955 -0.132389 +vn 0.88818 -0.439955 -0.132389 vn -0.873135 0.486984 -0.020264 vn -0.865352 0.331217 -0.376049 +vn -0.713828 0.382183 0.58681 vn 0.865352 0.331217 -0.376049 +vn 0.713828 0.382183 0.58681 vn 0.873135 0.486984 -0.020264 -vn -0.748741 0.518387 0.413038 -vn 0.748741 0.518387 0.413038 -vn -0.766167 0.634816 0.099612 -vn 0.766167 0.634816 0.099612 -vn -0.953185 -0.248299 -0.172430 +vn -0.992523 -0.071444 -0.098758 +vn 0.992523 -0.071444 -0.098758 vn -0.665639 0.602496 -0.440321 vn 0.665639 0.602496 -0.440321 -vn 0.953185 -0.248299 -0.172430 +vn -0.890988 -0.423261 -0.164037 +vn 0.890988 -0.423261 -0.164037 vn -0.322642 0.847713 0.421033 -vn -0.188574 0.788934 -0.584765 -vn 0.188574 0.788934 -0.584765 -vn 0.322642 0.847713 0.421033 -vn -0.239784 0.745262 -0.622120 vn 0.494247 0.520585 -0.696158 vn -0.494247 0.520585 -0.696158 -vn 0.239784 0.745262 -0.622120 +vn 0.322642 0.847713 0.421033 vn -0.480697 0.731223 0.483932 -vn 0.000000 0.758690 0.651418 +vn 0 0.75869 0.651418 +vn 0 0.75869 0.651418 vn 0.480697 0.731223 0.483932 -vn -0.489242 0.762963 0.422498 -vn -0.363109 0.908567 -0.206458 -vn 0.363109 0.908567 -0.206458 -vn 0.489242 0.762963 0.422498 -vn -0.645039 0.694540 0.318613 -vn 0.645039 0.694540 0.318613 -vn -0.492843 0.869015 0.043062 -vn -0.679434 0.728965 -0.083468 -vn 0.492843 0.869015 0.043062 -vn 0.679434 0.728965 -0.083468 -vn -0.391736 0.826014 -0.405225 -vn -0.644398 0.527207 -0.553880 -vn 0.391736 0.826014 -0.405225 -vn 0.644398 0.527207 -0.553880 -vn 0.000000 0.800714 -0.599017 -vn 0.000000 0.330729 -0.943693 -vn 0.000000 0.999664 0.025636 -vn 0.000000 -0.271462 -0.962432 -vn -0.685293 -0.583148 -0.436232 -vn -0.907224 0.252602 -0.336253 -vn 0.907224 0.252602 -0.336253 -vn 0.685293 -0.583148 -0.436232 -vn 0.000000 -0.984344 -0.176214 -vn 0.000000 -0.736351 -0.676565 -vn 0.000000 -0.948759 -0.315928 -vn 0.000000 -0.648244 -0.761406 +vn 0 0.800714 -0.599017 +vn 0 0.800714 -0.599017 +vn 0 0.330729 -0.943693 +vn 0 0.330729 -0.943693 +vn 0 0.999664 0.025636 +vn 0 0.999664 0.025636 +vn 0 -0.271462 -0.962432 +vn 0 -0.271462 -0.962432 +vn -0.930631 0.340159 0.13477 +vn 0.930631 0.340159 0.13477 +vn 0 -0.948759 -0.315928 +vn 0 -0.984344 -0.176214 +vn 0 -0.948759 -0.315928 +vn 0 -0.984344 -0.176214 vn -0.317362 -0.946959 -0.049959 +vn -0.85052 -0.525529 -0.020692 vn -0.838282 -0.408155 0.361461 +vn -0.317362 -0.946959 -0.049959 vn 0.838282 -0.408155 0.361461 +vn 0.85052 -0.525529 -0.020692 vn 0.317362 -0.946959 -0.049959 -vn -0.939360 0.325999 0.106113 -vn 0.939360 0.325999 0.106113 -vn -0.930631 0.340159 0.134770 -vn -0.960143 0.231361 0.156774 -vn 0.960143 0.231361 0.156774 -vn 0.930631 0.340159 0.134770 -vn -0.812555 -0.001068 -0.582842 -vn -0.979583 0.093387 0.177862 -vn 0.979583 0.093387 0.177862 -vn 0.812555 -0.001068 -0.582842 -vn -0.272530 -0.301157 -0.913785 -vn 0.272530 -0.301157 -0.913785 -vn -0.090915 -0.776330 -0.623707 -vn -0.506851 -0.488144 -0.710471 -vn -0.142521 -0.147282 -0.978759 +vn 0.317362 -0.946959 -0.049959 +vn -0.93936 0.325999 0.106113 +vn -0.93936 0.325999 0.106113 +vn 0.93936 0.325999 0.106113 +vn 0.93936 0.325999 0.106113 vn -0.637257 0.093326 -0.764946 -vn 0.637257 0.093326 -0.764946 -vn 0.506851 -0.488144 -0.710471 -vn 0.142521 -0.147282 -0.978759 -vn 0.090915 -0.776330 -0.623707 -vn -0.937284 -0.254250 0.238350 -vn 0.937284 -0.254250 0.238350 -vn -0.430525 -0.895260 0.114597 -vn 0.430525 -0.895260 0.114597 -vn -0.158391 -0.974822 0.156774 -vn 0.158391 -0.974822 0.156774 -vn 0.000000 -0.915860 -0.401440 -vn 0.000000 -0.946440 0.322855 -vn 0.000000 -0.336802 -0.941557 -vn 0.000000 -0.175726 -0.984436 -vn -0.599231 -0.773980 0.204566 -vn 0.599231 -0.773980 0.204566 -vn -0.890988 -0.423261 -0.164037 -vn 0.890988 -0.423261 -0.164037 +vn -0.937284 -0.25425 0.23835 +vn 0.937284 -0.25425 0.23835 +vn 0.812555 -0.001068 -0.582842 +vn 0.430525 -0.89526 0.114597 +vn 0 -0.336802 -0.941557 +vn 0 -0.94644 0.322855 +vn -0.430525 -0.89526 0.114597 +vn 0 -0.336802 -0.941557 +vn 0 -0.94644 0.322855 +vn -0.599231 -0.77398 0.204566 +vn 0.599231 -0.77398 0.204566 vn -0.851985 0.219275 0.475387 vn 0.851985 0.219275 0.475387 vn -0.509171 0.852229 0.119999 vn 0.509171 0.852229 0.119999 -vn -0.610431 0.759148 0.225867 -vn 0.610431 0.759148 0.225867 -vn -0.182470 0.981780 0.052492 -vn 0.182470 0.981780 0.052492 vn 0.520371 0.770348 0.368389 vn -0.520371 0.770348 0.368389 vn 0.852718 0.504257 0.136204 vn -0.852718 0.504257 0.136204 -vn 0.000000 0.970214 0.242164 vn -0.709647 0.261818 0.654042 vn 0.067293 -0.064272 0.995636 -vn -0.246590 -0.034089 0.968505 +vn -0.24659 -0.034089 0.968505 vn -0.809717 -0.010224 0.586688 -vn 0.246590 -0.034089 0.968505 +vn 0.24659 -0.034089 0.968505 vn -0.067293 -0.064272 0.995636 vn 0.709647 0.261818 0.654042 vn 0.809717 -0.010224 0.586688 @@ -1407,21 +856,21 @@ vn -0.211951 -0.085971 0.973479 vn -0.367504 -0.376476 0.850398 vn 0.211951 -0.085971 0.973479 vn 0.367504 -0.376476 0.850398 -vn -0.430280 0.556597 0.710624 +vn -0.43028 0.556597 0.710624 vn -0.020081 -0.072939 0.997131 vn 0.020081 -0.072939 0.997131 -vn 0.430280 0.556597 0.710624 +vn 0.43028 0.556597 0.710624 vn -0.090976 0.597339 0.796777 vn -0.187933 -0.091617 0.977874 vn 0.187933 -0.091617 0.977874 vn 0.090976 0.597339 0.796777 vn 0.165929 0.609363 0.775292 -vn -0.203314 0.092532 0.974700 -vn 0.203314 0.092532 0.974700 +vn -0.203314 0.092532 0.9747 +vn 0.203314 0.092532 0.9747 vn -0.165929 0.609363 0.775292 vn 0.269295 0.241676 0.932218 -vn -0.314219 -0.132420 0.940062 -vn 0.314219 -0.132420 0.940062 +vn -0.314219 -0.13242 0.940062 +vn 0.314219 -0.13242 0.940062 vn -0.269295 0.241676 0.932218 vn 0.420057 -0.118992 0.899625 vn -0.119755 -0.070925 0.990234 @@ -1431,135 +880,75 @@ vn 0.226142 -0.606586 0.762139 vn -0.320841 0.040712 0.946226 vn 0.320841 0.040712 0.946226 vn -0.226142 -0.606586 0.762139 -vn 0.232612 -0.746055 0.623890 +vn 0.232612 -0.746055 0.62389 vn -0.074557 -0.391644 0.917081 vn 0.074557 -0.391644 0.917081 -vn -0.232612 -0.746055 0.623890 -vn -0.121250 -0.313883 0.941679 +vn -0.232612 -0.746055 0.62389 +vn -0.12125 -0.313883 0.941679 vn -0.146702 -0.035707 0.988525 vn 0.146702 -0.035707 0.988525 -vn 0.121250 -0.313883 0.941679 -vn -0.216834 -0.273721 0.937010 -vn -0.187445 0.001160 0.982269 -vn 0.187445 0.001160 0.982269 -vn 0.216834 -0.273721 0.937010 -vn -0.303018 -0.201941 0.931333 -vn -0.253090 -0.161809 0.953795 -vn 0.253090 -0.161809 0.953795 -vn 0.303018 -0.201941 0.931333 -vn -0.140110 -0.091189 0.985900 -vn 0.140110 -0.091189 0.985900 -vn -0.237983 0.050172 0.969939 -vn 0.237983 0.050172 0.969939 -vn -0.312662 -0.237922 0.919553 -vn 0.312662 -0.237922 0.919553 -vn -0.373791 -0.105197 0.921506 -vn 0.373791 -0.105197 0.921506 -vn -0.470595 -0.164647 0.866817 -vn 0.470595 -0.164647 0.866817 -vn -0.439222 -0.376141 0.815821 -vn 0.439222 -0.376141 0.815821 -vn -0.219611 -0.540635 0.812037 -vn 0.219611 -0.540635 0.812037 +vn 0.12125 -0.313883 0.941679 +vn -0.216834 -0.273721 0.93701 +vn -0.187445 0.00116 0.982269 +vn 0.187445 0.00116 0.982269 +vn 0.216834 -0.273721 0.93701 +vn -0.25309 -0.161809 0.953795 +vn 0.25309 -0.161809 0.953795 +vn -0.543474 -0.308603 0.780602 +vn 0.543474 -0.308603 0.780602 +vn -0.336283 -0.512833 0.78985 +vn 0.336283 -0.512833 0.78985 vn 0.166967 -0.374828 0.911893 vn -0.166967 -0.374828 0.911893 -vn 0.201849 -0.277596 0.939238 -vn -0.201849 -0.277596 0.939238 -vn 0.001160 -0.165563 0.986175 -vn -0.001160 -0.165563 0.986175 -vn 0.292917 -0.174108 0.940123 -vn -0.292917 -0.174108 0.940123 -vn 0.000000 0.732200 0.681051 -vn 0.000000 -0.603626 0.797266 -vn 0.000000 -0.971740 0.235908 -vn 0.131779 -0.608295 0.782678 -vn -0.131779 -0.608295 0.782678 -vn 0.759117 0.068392 0.647298 -vn -0.759117 0.068392 0.647298 -vn 0.405957 0.643605 0.648793 -vn -0.405957 0.643605 0.648793 -vn 0.000000 0.598346 0.801202 +vn 0.00116 -0.165563 0.986175 +vn -0.00116 -0.165563 0.986175 +vn -0.349284 -0.719932 0.599719 +vn -0.141881 -0.14835 0.978698 +vn 0.173681 0.215735 0.960845 vn 0.073855 -0.330546 0.940855 -vn 0.000000 -0.124516 0.992187 -vn -0.073855 -0.330546 0.940855 -vn -0.085116 -0.339244 0.936827 vn 0.085116 -0.339244 0.936827 -vn -0.141881 -0.148350 0.978698 -vn 0.141881 -0.148350 0.978698 -vn 0.000000 -0.482803 0.875698 +vn 0.141881 -0.14835 0.978698 vn -0.692984 -0.001343 0.720908 -vn -0.095523 -0.326090 0.940489 -vn 0.095523 -0.326090 0.940489 +vn -0.095523 -0.32609 0.940489 +vn 0.095523 -0.32609 0.940489 vn 0.692984 -0.001343 0.720908 vn -0.646687 0.162603 0.745201 +vn -0.930631 0.340159 0.13477 +vn 0.930631 0.340159 0.13477 vn 0.646687 0.162603 0.745201 -vn -0.593463 0.121860 0.795556 -vn 0.593463 0.121860 0.795556 -vn -0.124363 0.009674 0.992187 +vn 0 -0.336772 0.941557 vn -0.509995 -0.457717 0.728233 vn 0.509995 -0.457717 0.728233 -vn 0.124363 0.009674 0.992187 vn -0.972137 -0.167882 0.163549 vn 0.972137 -0.167882 0.163549 vn -0.715995 0.572161 0.399945 vn 0.715995 0.572161 0.399945 -vn 0.000000 0.430525 0.902554 -vn 0.000000 0.010865 0.999939 -vn -0.221839 -0.606037 0.763848 -vn 0.000000 -0.492935 0.870022 -vn 0.000000 0.010315 0.999939 -vn -0.294320 -0.184484 0.937712 -vn 0.221839 -0.606037 0.763848 -vn 0.294320 -0.184484 0.937712 -vn -0.396924 0.534989 0.745781 -vn 0.247780 0.568224 0.784661 -vn -0.247780 0.568224 0.784661 -vn 0.396924 0.534989 0.745781 -vn -0.868221 -0.261330 0.421735 +vn 0 0.430525 0.902554 vn -0.555986 -0.690695 0.462355 -vn 0.868221 -0.261330 0.421735 +vn 0 -0.492935 0.870022 +vn 0 0.788965 0.614399 vn 0.555986 -0.690695 0.462355 -vn -0.753075 0.649892 0.102298 -vn 0.753075 0.649892 0.102298 -vn 0.194189 0.935697 0.294473 -vn -0.194189 0.935697 0.294473 -vn 0.000000 0.788965 0.614399 -vn 0.000000 -0.888638 0.458571 -vn 0.000000 -0.336772 0.941557 -vn 0.000000 -0.251991 0.967711 -vn -0.188360 -0.040132 0.981262 -vn 0.000000 -0.032899 0.999451 -vn 0.188360 -0.040132 0.981262 -vn 0.000000 0.000000 1.000000 -vn -0.572039 -0.018708 0.820002 -vn -0.536332 -0.212409 0.816828 -vn 0.536332 -0.212409 0.816828 -vn 0.572039 -0.018708 0.820002 -vn -0.357707 -0.638325 0.681570 -vn 0.357707 -0.638325 0.681570 -vn -0.154302 -0.754112 0.638325 -vn 0.154302 -0.754112 0.638325 -vn 0.000000 -0.743461 0.668752 -vn 0.000000 -0.189123 0.981933 -vn 0.000000 -0.114475 0.993408 -vn 0.001404 -0.055635 0.998444 -vn -0.001404 -0.055635 0.998444 -vn -0.336283 -0.512833 0.789850 -vn 0.336283 -0.512833 0.789850 -vn -0.454543 -0.337077 0.824458 -vn 0.454543 -0.337077 0.824458 -vn -0.543474 -0.308603 0.780602 -vn 0.543474 -0.308603 0.780602 -vn -0.387158 -0.187811 0.902646 -vn 0.387158 -0.187811 0.902646 -vn -0.430647 -0.144902 0.890805 -vn 0.430647 -0.144902 0.890805 -vn -0.234016 -0.120548 0.964721 -vn 0.234016 -0.120548 0.964721 +vn 0 -0.888638 0.458571 +vn -0.937284 -0.25425 0.23835 +vn 0.937284 -0.25425 0.23835 +vn -0.430525 -0.89526 0.114597 +vn 0.430525 -0.89526 0.114597 +vn 0 -0.94644 0.322855 vn -0.263833 0.168798 0.949675 vn 0.263833 0.168798 0.949675 -vn 0.196722 0.141881 0.970122 -vn -0.196722 0.141881 0.970122 +vn 0 0.970214 0.242164 +vn 0.852718 0.504257 0.136204 +vn -0.852718 0.504257 0.136204 +vn 0.520371 0.770348 0.368389 +vn -0.520371 0.770348 0.368389 +vn -0.509171 0.852229 0.119999 +vn 0.509171 0.852229 0.119999 +vn -0.851985 0.219275 0.475387 +vn 0.851985 0.219275 0.475387 +vn -0.890988 -0.423261 -0.164037 +vn 0.890988 -0.423261 -0.164037 +vn -0.599231 -0.77398 0.204566 +vn 0.599231 -0.77398 0.204566 vn -0.906766 -0.008332 0.421522 vn -0.744133 -0.640919 0.188269 vn 0.744133 -0.640919 0.188269 @@ -1570,24 +959,24 @@ vn 0.639943 -0.761498 0.102786 vn -0.639943 -0.761498 0.102786 vn 0.955504 -0.011444 0.294717 vn -0.955504 -0.011444 0.294717 -vn 0.649678 0.754387 0.093570 -vn -0.649678 0.754387 0.093570 +vn 0.649678 0.754387 0.09357 +vn -0.649678 0.754387 0.09357 vn -0.037049 0.978881 0.200903 vn 0.037049 0.978881 0.200903 vn -0.752342 0.635395 0.173742 vn 0.752342 0.635395 0.173742 -vn -0.811792 -0.002777 0.583880 -vn -0.596942 0.486770 0.637684 -vn 0.596942 0.486770 0.637684 -vn 0.811792 -0.002777 0.583880 +vn -0.811792 -0.002777 0.58388 +vn -0.596942 0.48677 0.637684 +vn 0.596942 0.48677 0.637684 +vn 0.811792 -0.002777 0.58388 vn -0.868221 -0.005829 0.496109 vn -0.719504 0.473006 0.508469 vn 0.719504 0.473006 0.508469 vn 0.868221 -0.005829 0.496109 -vn -0.204260 0.828761 0.520951 +vn -0.20426 0.828761 0.520951 vn -0.095767 0.717277 0.690146 vn 0.095767 0.717277 0.690146 -vn 0.204260 0.828761 0.520951 +vn 0.20426 0.828761 0.520951 vn 0.451704 0.459883 0.764458 vn -0.451704 0.459883 0.764458 vn 0.450362 0.693899 0.561815 @@ -1608,973 +997,499 @@ vn -0.597949 -0.496475 0.629231 vn 0.597949 -0.496475 0.629231 vn -0.723197 -0.488907 0.487747 vn 0.723197 -0.488907 0.487747 -usemtl Material_ray.png -s 1 -f 61/1/1 65/2/2 49/3/3 -f 50/4/4 66/5/5 62/6/6 -f 63/7/7 65/2/2 61/1/1 -f 62/6/6 66/5/5 64/8/8 -f 61/1/1 59/9/9 63/7/7 -f 64/8/8 60/10/10 62/6/6 -f 61/1/1 57/11/11 59/9/9 -f 60/10/10 58/12/12 62/6/6 -f 61/1/1 55/13/13 57/11/11 -f 58/12/12 56/14/14 62/6/6 -f 61/1/1 53/15/15 55/13/13 -f 56/14/14 54/16/16 62/6/6 -f 61/1/1 51/17/17 53/15/15 -f 54/16/16 52/18/18 62/6/6 -f 61/1/1 49/3/3 51/17/17 -f 52/18/18 50/4/4 62/6/6 -f 225/19/19 229/20/20 227/21/21 -f 228/22/22 230/23/23 226/24/24 -f 73/25/25 284/26/26 74/27/27 -f 74/28/27 285/29/28 73/30/25 -f 342/31/29 348/32/30 384/33/31 -f 385/34/32 349/35/33 343/36/34 -f 300/37/35 346/38/36 344/39/37 -f 345/40/38 347/41/39 301/42/40 -f 324/43/41 380/44/42 352/45/43 -f 353/46/44 381/47/45 325/48/46 -f 442/49/47 444/50/48 446/51/49 -f 447/52/50 445/53/51 443/54/52 -f 464/55/53 492/56/54 466/57/55 -f 467/58/56 493/59/57 465/60/58 -f 496/61/59 498/62/60 500/63/61 -f 501/64/62 499/65/63 497/66/64 -f 505/67/65 323/68/66 321/69/67 -f 505/67/65 321/69/67 391/70/68 -f 320/71/69 322/72/70 504/73/71 -f 320/71/69 504/73/71 390/74/72 -f 505/67/65 507/75/73 315/76/74 -f 505/67/65 315/76/74 323/68/66 -f 314/77/75 506/78/76 504/73/71 -f 314/77/75 504/73/71 322/72/70 -f 389/79/77 383/80/78 507/75/73 -f 383/80/78 315/76/74 507/75/73 -f 314/77/75 382/81/79 506/78/76 -f 382/81/79 388/82/80 506/78/76 -f 501/64/62 497/66/64 495/83/81 -f 501/64/62 495/83/81 503/84/82 -f 494/85/83 496/61/59 500/63/61 -f 494/85/83 500/63/61 502/86/84 -f 505/67/65 503/84/82 507/75/73 -f 503/84/82 495/83/81 507/75/73 -f 494/85/83 502/86/84 506/78/76 -f 502/86/84 504/73/71 506/78/76 -f 495/83/81 401/87/85 507/75/73 -f 401/87/85 389/79/77 507/75/73 -f 388/82/80 400/88/86 506/78/76 -f 400/88/86 494/85/83 506/78/76 -f 497/66/64 399/89/87 495/83/81 -f 399/89/87 401/87/85 495/83/81 -f 400/88/86 398/90/88 494/85/83 -f 398/90/88 496/61/59 494/85/83 -f 499/65/63 397/91/89 497/66/64 -f 397/91/89 399/89/87 497/66/64 -f 398/90/88 396/92/90 496/61/59 -f 396/92/90 498/62/60 496/61/59 -f 501/64/62 395/93/91 499/65/63 -f 395/93/91 397/91/89 499/65/63 -f 396/92/90 394/94/92 498/62/60 -f 394/94/92 500/63/61 498/62/60 -f 503/84/82 393/95/93 395/93/91 -f 503/84/82 395/93/91 501/64/62 -f 394/94/92 392/96/94 502/86/84 -f 394/94/92 502/86/84 500/63/61 -f 505/67/65 391/70/68 393/95/93 -f 505/67/65 393/95/93 503/84/82 -f 392/96/94 390/74/72 504/73/71 -f 392/96/94 504/73/71 502/86/84 -f 491/97/95 493/59/57 467/58/56 -f 491/97/95 467/58/56 469/98/96 -f 466/57/55 492/56/54 490/99/97 -f 466/57/55 490/99/97 468/100/98 -f 489/101/99 491/97/95 471/102/100 -f 491/97/95 469/98/96 471/102/100 -f 468/100/98 490/99/97 470/103/101 -f 490/99/97 488/104/102 470/103/101 -f 483/105/103 489/101/99 473/106/104 -f 489/101/99 471/102/100 473/106/104 -f 470/103/101 488/104/102 472/107/105 -f 488/104/102 482/108/106 472/107/105 -f 481/109/107 483/105/103 473/106/104 -f 481/109/107 473/106/104 475/110/108 -f 472/107/105 482/108/106 480/111/109 -f 472/107/105 480/111/109 474/112/110 -f 481/109/107 475/110/108 457/113/111 -f 475/110/108 455/114/112 457/113/111 -f 454/115/113 474/112/110 456/116/114 -f 474/112/110 480/111/109 456/116/114 -f 463/117/115 479/118/116 459/119/117 -f 463/117/115 459/119/117 461/120/118 -f 458/121/119 478/122/120 462/123/121 -f 458/121/119 462/123/121 460/124/122 -f 479/118/116 463/117/115 485/125/123 -f 463/117/115 453/126/124 485/125/123 -f 452/127/125 462/123/121 484/128/126 -f 462/123/121 478/122/120 484/128/126 -f 487/129/127 485/125/123 477/130/128 -f 485/125/123 453/126/124 477/130/128 -f 452/127/125 484/128/126 476/131/129 -f 484/128/126 486/132/130 476/131/129 -f 487/129/127 477/130/128 465/60/58 -f 487/129/127 465/60/58 493/59/57 -f 464/55/53 476/131/129 486/132/130 -f 464/55/53 486/132/130 492/56/54 -f 491/97/95 489/101/99 493/59/57 -f 489/101/99 487/129/127 493/59/57 -f 486/132/130 488/104/102 492/56/54 -f 488/104/102 490/99/97 492/56/54 -f 489/101/99 483/105/103 485/125/123 -f 489/101/99 485/125/123 487/129/127 -f 484/128/126 482/108/106 488/104/102 -f 484/128/126 488/104/102 486/132/130 -f 483/105/103 481/109/107 485/125/123 -f 481/109/107 479/118/116 485/125/123 -f 478/122/120 480/111/109 484/128/126 -f 480/111/109 482/108/106 484/128/126 -f 481/109/107 457/113/111 479/118/116 -f 457/113/111 459/119/117 479/118/116 -f 458/121/119 456/116/114 478/122/120 -f 456/116/114 480/111/109 478/122/120 -f 473/106/104 421/133/131 475/110/108 -f 421/133/131 419/134/132 475/110/108 -f 418/135/133 420/136/134 474/112/110 -f 420/136/134 472/107/105 474/112/110 -f 471/102/100 423/137/135 473/106/104 -f 423/137/135 421/133/131 473/106/104 -f 420/136/134 422/138/136 472/107/105 -f 422/138/136 470/103/101 472/107/105 -f 469/98/96 425/139/137 471/102/100 -f 425/139/137 423/137/135 471/102/100 -f 422/138/136 424/140/138 470/103/101 -f 424/140/138 468/100/98 470/103/101 -f 467/58/56 427/141/139 425/139/137 -f 467/58/56 425/139/137 469/98/96 -f 424/140/138 426/142/140 466/57/55 -f 424/140/138 466/57/55 468/100/98 -f 465/60/58 429/143/141 427/141/139 -f 465/60/58 427/141/139 467/58/56 -f 426/142/140 428/144/142 464/55/53 -f 426/142/140 464/55/53 466/57/55 -f 477/130/128 417/145/143 429/143/141 -f 477/130/128 429/143/141 465/60/58 -f 428/144/142 416/146/144 476/131/129 -f 428/144/142 476/131/129 464/55/53 -f 475/110/108 419/134/132 441/147/145 -f 475/110/108 441/147/145 455/114/112 -f 440/148/146 418/135/133 474/112/110 -f 440/148/146 474/112/110 454/115/113 -f 455/114/112 441/147/145 439/149/147 -f 455/114/112 439/149/147 457/113/111 -f 438/150/148 440/148/146 454/115/113 -f 438/150/148 454/115/113 456/116/114 -f 457/113/111 439/149/147 459/119/117 -f 439/149/147 437/151/149 459/119/117 -f 436/152/150 438/150/148 458/121/119 -f 438/150/148 456/116/114 458/121/119 -f 459/119/117 437/151/149 461/120/118 -f 437/151/149 435/153/151 461/120/118 -f 434/154/152 436/152/150 460/124/122 -f 436/152/150 458/121/119 460/124/122 -f 461/120/118 435/153/151 433/155/153 -f 461/120/118 433/155/153 463/117/115 -f 432/156/154 434/154/152 460/124/122 -f 432/156/154 460/124/122 462/123/121 -f 463/117/115 433/155/153 453/126/124 -f 433/155/153 451/157/155 453/126/124 -f 450/158/156 432/156/154 452/127/125 -f 432/156/154 462/123/121 452/127/125 -f 453/126/124 451/157/155 417/145/143 -f 453/126/124 417/145/143 477/130/128 -f 416/146/144 450/158/156 452/127/125 -f 416/146/144 452/127/125 476/131/129 -f 447/52/50 443/54/52 449/159/157 -f 443/54/52 313/160/158 449/159/157 -f 312/161/159 442/49/47 448/162/160 -f 442/49/47 446/51/49 448/162/160 -f 431/163/161 449/159/157 383/80/78 -f 449/159/157 313/160/158 383/80/78 -f 312/161/159 448/162/160 382/164/79 -f 448/162/160 430/165/162 382/164/79 -f 451/157/155 431/163/161 417/145/143 -f 431/163/161 415/166/163 417/145/143 -f 414/167/164 430/165/162 416/146/144 -f 430/165/162 450/158/156 416/146/144 -f 433/155/153 449/159/157 451/157/155 -f 449/159/157 431/163/161 451/157/155 -f 430/165/162 448/162/160 450/158/156 -f 448/162/160 432/156/154 450/158/156 -f 447/52/50 449/159/157 435/153/151 -f 449/159/157 433/155/153 435/153/151 -f 432/156/154 448/162/160 434/154/152 -f 448/162/160 446/51/49 434/154/152 -f 439/149/147 447/52/50 435/153/151 -f 439/149/147 435/153/151 437/151/149 -f 434/154/152 446/51/49 438/150/148 -f 434/154/152 438/150/148 436/152/150 -f 445/53/51 447/52/50 441/147/145 -f 447/52/50 439/149/147 441/147/145 -f 438/150/148 446/51/49 440/148/146 -f 446/51/49 444/50/48 440/148/146 -f 441/147/145 419/134/132 413/168/165 -f 441/147/145 413/168/165 445/53/51 -f 412/169/166 418/135/133 440/148/146 -f 412/169/166 440/148/146 444/50/48 -f 415/166/163 431/163/161 383/80/78 -f 415/166/163 383/80/78 389/79/77 -f 382/164/79 430/165/162 414/167/164 -f 382/164/79 414/167/164 388/170/80 -f 443/171/52 319/172/167 311/173/168 -f 443/171/52 311/173/168 313/174/158 -f 310/175/169 318/176/170 442/177/47 -f 310/175/169 442/177/47 312/178/159 -f 413/168/165 391/179/68 445/53/51 -f 391/179/68 321/180/67 445/53/51 -f 320/181/69 390/182/72 444/50/48 -f 390/182/72 412/169/166 444/50/48 -f 445/53/51 321/180/67 443/54/52 -f 321/183/67 319/172/167 443/171/52 -f 318/176/170 320/184/69 442/177/47 -f 320/181/69 444/50/48 442/49/47 -f 417/145/143 415/166/163 403/185/171 -f 417/145/143 403/185/171 429/143/141 -f 402/186/172 414/167/164 416/146/144 -f 402/186/172 416/146/144 428/144/142 -f 427/141/139 429/143/141 405/187/173 -f 429/143/141 403/185/171 405/187/173 -f 402/186/172 428/144/142 404/188/174 -f 428/144/142 426/142/140 404/188/174 -f 425/139/137 427/141/139 407/189/175 -f 427/141/139 405/187/173 407/189/175 -f 404/188/174 426/142/140 406/190/176 -f 426/142/140 424/140/138 406/190/176 -f 423/137/135 425/139/137 409/191/177 -f 425/139/137 407/189/175 409/191/177 -f 406/190/176 424/140/138 408/192/178 -f 424/140/138 422/138/136 408/192/178 -f 421/133/131 423/137/135 409/191/177 -f 421/133/131 409/191/177 411/193/179 -f 408/192/178 422/138/136 420/136/134 -f 408/192/178 420/136/134 410/194/180 -f 419/134/132 421/133/131 411/193/179 -f 419/134/132 411/193/179 413/168/165 -f 410/194/180 420/136/134 418/135/133 -f 410/194/180 418/135/133 412/169/166 -f 413/168/165 411/193/179 393/195/93 -f 413/168/165 393/195/93 391/179/68 -f 392/196/94 410/194/180 412/169/166 -f 392/196/94 412/169/166 390/182/72 -f 411/193/179 409/191/177 393/195/93 -f 409/191/177 395/197/91 393/195/93 -f 394/198/92 408/192/178 392/196/94 -f 408/192/178 410/194/180 392/196/94 -f 409/191/177 407/189/175 395/197/91 -f 407/189/175 397/199/89 395/197/91 -f 396/200/90 406/190/176 394/198/92 -f 406/190/176 408/192/178 394/198/92 -f 407/189/175 405/187/173 397/199/89 -f 405/187/173 399/89/87 397/199/89 -f 398/201/88 404/188/174 396/200/90 -f 404/188/174 406/190/176 396/200/90 -f 405/187/173 403/185/171 401/87/85 -f 405/187/173 401/87/85 399/89/87 -f 400/202/86 402/186/172 404/188/174 -f 400/202/86 404/188/174 398/201/88 -f 415/166/163 389/79/77 403/185/171 -f 389/79/77 401/87/85 403/185/171 -f 400/202/86 388/170/80 402/186/172 -f 388/170/80 414/167/164 402/186/172 -f 381/47/45 353/46/44 387/203/181 -f 353/46/44 351/204/182 387/203/181 -f 350/205/183 352/45/43 386/206/184 -f 352/45/43 380/44/42 386/206/184 -f 381/47/45 387/203/181 323/207/66 -f 387/203/181 321/183/67 323/207/66 -f 320/184/69 386/206/184 322/208/70 -f 386/206/184 380/44/42 322/208/70 -f 381/47/45 379/209/185 325/48/46 -f 379/209/185 317/210/186 325/48/46 -f 316/211/187 378/212/188 324/43/41 -f 378/212/188 380/44/42 324/43/41 -f 381/47/45 323/207/66 379/209/185 -f 323/207/66 315/213/74 379/209/185 -f 314/214/75 322/208/70 378/212/188 -f 322/208/70 380/44/42 378/212/188 -f 343/36/34 345/40/38 301/42/40 -f 343/36/34 301/42/40 385/34/32 -f 300/37/35 344/39/37 342/31/29 -f 300/37/35 342/31/29 384/33/31 -f 385/34/32 301/42/40 299/215/189 -f 385/34/32 299/215/189 319/172/167 -f 298/216/190 300/37/35 384/33/31 -f 298/216/190 384/33/31 318/176/170 -f 387/203/181 385/34/32 321/183/67 -f 385/34/32 319/172/167 321/183/67 -f 318/176/170 384/33/31 320/184/69 -f 384/33/31 386/206/184 320/184/69 -f 387/203/181 351/204/182 385/34/32 -f 351/204/182 349/35/33 385/34/32 -f 348/32/30 350/205/183 384/33/31 -f 350/205/183 386/206/184 384/33/31 -f 371/217/191 377/218/192 383/219/78 -f 377/218/192 315/213/74 383/219/78 -f 314/214/75 376/220/193 382/221/79 -f 376/220/193 370/222/194 382/221/79 -f 371/217/191 383/219/78 313/174/158 -f 371/217/191 313/174/158 369/223/195 -f 312/178/159 382/221/79 370/222/194 -f 312/178/159 370/222/194 368/224/196 -f 369/223/195 313/174/158 311/173/168 -f 369/223/195 311/173/168 363/225/197 -f 310/175/169 312/178/159 368/224/196 -f 310/175/169 368/224/196 362/226/198 -f 311/173/168 297/227/199 363/225/197 -f 297/227/199 295/228/200 363/225/197 -f 294/229/201 296/230/202 362/226/198 -f 296/230/202 310/175/169 362/226/198 -f 361/231/203 291/232/204 285/29/28 -f 361/231/203 285/29/28 74/28/27 -f 284/26/26 290/233/205 360/234/206 -f 284/26/26 360/234/206 74/27/27 -f 289/235/207 287/236/208 291/232/204 -f 287/236/208 285/29/28 291/232/204 -f 284/26/26 286/237/209 290/233/205 -f 286/237/209 288/238/210 290/233/205 -f 359/239/211 361/231/203 302/240/212 -f 361/231/203 74/28/27 302/240/212 -f 74/27/27 360/234/206 302/241/212 -f 360/234/206 358/242/213 302/241/212 -f 365/243/214 293/244/215 361/231/203 -f 293/244/215 291/232/204 361/231/203 -f 290/233/205 292/245/216 360/234/206 -f 292/245/216 364/246/217 360/234/206 -f 365/243/214 361/231/203 359/239/211 -f 365/243/214 359/239/211 367/247/218 -f 358/242/213 360/234/206 364/246/217 -f 358/242/213 364/246/217 366/248/219 -f 367/247/218 359/239/211 357/249/220 -f 367/247/218 357/249/220 373/250/221 -f 356/251/222 358/242/213 366/248/219 -f 356/251/222 366/248/219 372/252/223 -f 373/250/221 357/249/220 355/253/224 -f 373/250/221 355/253/224 375/254/225 -f 354/255/226 356/251/222 372/252/223 -f 354/255/226 372/252/223 374/256/227 -f 375/254/225 355/253/224 317/210/186 -f 375/254/225 317/210/186 379/209/185 -f 316/211/187 354/255/226 374/256/227 -f 316/211/187 374/256/227 378/212/188 -f 375/254/225 379/209/185 377/218/192 -f 379/209/185 315/213/74 377/218/192 -f 314/214/75 378/212/188 376/220/193 -f 378/212/188 374/256/227 376/220/193 -f 377/218/192 371/217/191 373/250/221 -f 377/218/192 373/250/221 375/254/225 -f 372/252/223 370/222/194 376/220/193 -f 372/252/223 376/220/193 374/256/227 -f 371/217/191 369/223/195 367/247/218 -f 371/217/191 367/247/218 373/250/221 -f 366/248/219 368/224/196 370/222/194 -f 366/248/219 370/222/194 372/252/223 -f 369/223/195 363/225/197 365/243/214 -f 369/223/195 365/243/214 367/247/218 -f 364/246/217 362/226/198 368/224/196 -f 364/246/217 368/224/196 366/248/219 -f 363/225/197 295/228/200 293/244/215 -f 363/225/197 293/244/215 365/243/214 -f 292/245/216 294/229/201 362/226/198 -f 292/245/216 362/226/198 364/246/217 -f 317/210/186 355/253/224 75/257/228 -f 317/210/186 75/257/228 76/258/229 -f 75/259/228 354/255/226 316/211/187 -f 75/259/228 316/211/187 76/260/229 -f 355/253/224 357/249/220 303/261/230 -f 355/253/224 303/261/230 75/257/228 -f 303/262/230 356/251/222 354/255/226 -f 303/262/230 354/255/226 75/259/228 -f 357/249/220 359/239/211 303/261/230 -f 359/239/211 302/240/212 303/261/230 -f 302/241/212 358/242/213 303/262/230 -f 358/242/213 356/251/222 303/262/230 -f 325/48/46 317/210/186 77/263/231 -f 317/210/186 76/258/229 77/263/231 -f 76/260/229 316/211/187 77/264/231 -f 316/211/187 324/43/41 77/264/231 -f 319/172/167 299/215/189 297/227/199 -f 319/172/167 297/227/199 311/173/168 -f 296/230/202 298/216/190 318/176/170 -f 296/230/202 318/176/170 310/175/169 -f 349/35/33 329/265/232 343/36/34 -f 329/265/232 327/266/233 343/36/34 -f 326/267/234 328/268/235 342/31/29 -f 328/268/235 348/32/30 342/31/29 -f 329/265/232 349/35/33 305/269/236 -f 329/265/232 305/269/236 309/270/237 -f 305/271/236 348/32/30 328/268/235 -f 305/271/236 328/268/235 309/272/237 -f 349/35/33 351/204/182 78/273/238 -f 349/35/33 78/273/238 305/269/236 -f 78/274/238 350/205/183 348/32/30 -f 78/274/238 348/32/30 305/271/236 -f 351/204/182 353/46/44 78/273/238 -f 353/46/44 304/275/239 78/273/238 -f 304/276/239 352/45/43 78/274/238 -f 352/45/43 350/205/183 78/274/238 -f 353/46/44 325/48/46 304/275/239 -f 325/48/46 77/263/231 304/275/239 -f 77/264/231 324/43/41 304/276/239 -f 324/43/41 352/45/43 304/276/239 -f 301/42/40 347/41/39 93/277/240 -f 347/278/39 80/279/241 93/280/240 -f 79/281/242 346/282/36 92/283/243 -f 346/38/36 300/37/35 92/284/243 -f 345/40/38 216/285/244 347/41/39 -f 216/286/244 80/279/241 347/278/39 -f 79/281/242 215/287/245 346/282/36 -f 215/288/245 344/39/37 346/38/36 -f 343/36/34 327/266/233 210/289/246 -f 327/266/233 82/290/247 210/289/246 -f 81/291/248 326/267/234 209/292/249 -f 326/267/234 342/31/29 209/292/249 -f 345/40/38 343/36/34 216/285/244 -f 343/36/34 210/289/246 216/285/244 -f 209/292/249 342/31/29 215/288/245 -f 342/31/29 344/39/37 215/288/245 -f 333/293/250 84/294/251 82/290/247 -f 333/293/250 82/290/247 327/266/233 -f 81/291/248 83/295/252 332/296/253 -f 81/291/248 332/296/253 326/267/234 -f 339/297/254 333/293/250 329/265/232 -f 333/293/250 327/266/233 329/265/232 -f 326/267/234 332/296/253 328/268/235 -f 332/296/253 338/298/255 328/268/235 -f 341/299/256 335/300/257 337/301/258 -f 335/300/257 331/302/259 337/301/258 -f 330/303/260 334/304/261 336/305/262 -f 334/304/261 340/306/263 336/305/262 -f 339/297/254 337/301/258 331/302/259 -f 339/297/254 331/302/259 333/293/250 -f 330/303/260 336/305/262 338/298/255 -f 330/303/260 338/298/255 332/296/253 -f 331/302/259 86/307/264 84/294/251 -f 331/302/259 84/294/251 333/293/250 -f 83/295/252 85/308/265 330/303/260 -f 83/295/252 330/303/260 332/296/253 -f 335/300/257 88/309/266 86/307/264 -f 335/300/257 86/307/264 331/302/259 -f 85/308/265 87/310/267 334/304/261 -f 85/308/265 334/304/261 330/303/260 -f 341/299/256 90/311/268 88/309/266 -f 341/299/256 88/309/266 335/300/257 -f 87/310/267 89/312/269 340/306/263 -f 87/310/267 340/306/263 334/304/261 -f 306/313/270 91/314/271 90/311/268 -f 306/313/270 90/311/268 341/299/256 -f 89/312/269 91/315/271 306/316/270 -f 89/312/269 306/316/270 340/306/263 -f 337/301/258 307/317/272 341/299/256 -f 307/317/272 306/313/270 341/299/256 -f 306/316/270 307/318/272 340/306/263 -f 307/318/272 336/305/262 340/306/263 -f 339/297/254 308/319/273 337/301/258 -f 308/319/273 307/317/272 337/301/258 -f 307/318/272 308/320/273 336/305/262 -f 308/320/273 338/298/255 336/305/262 -f 329/265/232 309/270/237 339/297/254 -f 309/270/237 308/319/273 339/297/254 -f 308/320/273 309/272/237 338/298/255 -f 309/272/237 328/268/235 338/298/255 -f 301/42/40 93/277/240 95/321/274 -f 301/42/40 95/321/274 299/215/189 -f 94/322/275 92/284/243 300/37/35 -f 94/322/275 300/37/35 298/216/190 -f 299/215/189 95/321/274 97/323/276 -f 299/215/189 97/323/276 297/227/199 -f 96/324/277 94/322/275 298/216/190 -f 96/324/277 298/216/190 296/230/202 -f 297/227/199 97/323/276 295/228/200 -f 97/323/276 99/325/278 295/228/200 -f 98/326/279 96/324/277 294/229/201 -f 96/324/277 296/230/202 294/229/201 -f 295/228/200 99/325/278 101/327/280 -f 295/228/200 101/327/280 293/244/215 -f 100/328/281 98/326/279 294/229/201 -f 100/328/281 294/229/201 292/245/216 -f 293/244/215 101/327/280 291/232/204 -f 101/327/280 103/329/282 291/232/204 -f 102/330/283 100/328/281 290/233/205 -f 100/328/281 292/245/216 290/233/205 -f 291/232/204 103/329/282 289/235/207 -f 103/329/282 105/331/284 289/235/207 -f 104/332/285 102/330/283 288/238/210 -f 102/330/283 290/233/205 288/238/210 -f 289/235/207 105/331/284 287/236/208 -f 105/331/284 107/333/286 287/236/208 -f 106/334/287 104/332/285 286/237/209 -f 104/332/285 288/238/210 286/237/209 -f 287/236/208 107/333/286 109/335/288 -f 287/236/208 109/335/288 285/29/28 -f 108/336/289 106/334/287 286/237/209 -f 108/336/289 286/237/209 284/26/26 -f 285/29/28 109/335/288 67/337/290 -f 285/29/28 67/337/290 73/30/25 -f 67/338/290 108/336/289 284/26/26 -f 67/338/290 284/26/26 73/25/25 -f 281/339/291 235/340/292 233/341/293 -f 281/339/291 233/341/293 283/342/294 -f 232/343/295 234/344/296 280/345/297 -f 232/343/295 280/345/297 282/346/298 -f 283/342/294 233/341/293 255/347/299 -f 283/342/294 255/347/299 261/348/300 -f 254/349/301 232/343/295 282/346/298 -f 254/349/301 282/346/298 260/350/302 -f 261/348/300 255/347/299 257/351/303 -f 261/348/300 257/351/303 259/352/304 -f 256/353/305 254/349/301 260/350/302 -f 256/353/305 260/350/302 258/354/306 -f 263/355/307 253/356/308 235/340/292 -f 263/355/307 235/340/292 281/339/291 -f 234/344/296 252/357/309 262/358/310 -f 234/344/296 262/358/310 280/345/297 -f 265/359/311 251/360/312 263/355/307 -f 251/360/312 253/356/308 263/355/307 -f 252/357/309 250/361/313 262/358/310 -f 250/361/313 264/362/314 262/358/310 -f 267/363/315 249/364/316 265/359/311 -f 249/364/316 251/360/312 265/359/311 -f 250/361/313 248/365/317 264/362/314 -f 248/365/317 266/366/318 264/362/314 -f 269/367/319 247/368/320 249/364/316 -f 269/367/319 249/364/316 267/363/315 -f 248/365/317 246/369/321 268/370/322 -f 248/365/317 268/370/322 266/366/318 -f 271/371/323 245/372/324 269/367/319 -f 245/372/324 247/368/320 269/367/319 -f 246/369/321 244/373/325 268/370/322 -f 244/373/325 270/374/326 268/370/322 -f 273/375/327 243/376/328 245/372/324 -f 273/375/327 245/372/324 271/371/323 -f 244/373/325 242/377/329 272/378/330 -f 244/373/325 272/378/330 270/374/326 -f 275/379/331 241/380/332 273/375/327 -f 241/380/332 243/376/328 273/375/327 -f 242/377/329 240/381/333 272/378/330 -f 240/381/333 274/382/334 272/378/330 -f 279/383/335 237/384/336 275/379/331 -f 237/384/336 241/380/332 275/379/331 -f 240/381/333 236/385/337 274/382/334 -f 236/385/337 278/386/338 274/382/334 -f 277/387/339 239/388/340 237/384/336 -f 277/387/339 237/384/336 279/383/335 -f 236/385/337 238/389/341 276/390/342 -f 236/385/337 276/390/342 278/386/338 -f 259/352/304 257/351/303 239/388/340 -f 259/352/304 239/388/340 277/387/339 -f 238/389/341 256/353/305 258/354/306 -f 238/389/341 258/354/306 276/390/342 -f 257/351/303 111/391/343 129/392/344 -f 257/351/303 129/392/344 239/388/340 -f 128/393/345 110/394/346 256/353/305 -f 128/393/345 256/353/305 238/389/341 -f 239/388/340 129/392/344 180/395/347 -f 239/388/340 180/395/347 237/384/336 -f 179/396/348 128/393/345 238/389/341 -f 179/396/348 238/389/341 236/385/337 -f 237/384/336 180/395/347 127/397/349 -f 237/384/336 127/397/349 241/380/332 -f 126/398/350 179/396/348 236/385/337 -f 126/398/350 236/385/337 240/381/333 -f 241/380/332 127/397/349 243/376/328 -f 127/397/349 125/399/351 243/376/328 -f 124/400/352 126/398/350 242/377/329 -f 126/398/350 240/381/333 242/377/329 -f 243/376/328 125/399/351 245/372/324 -f 125/399/351 123/401/353 245/372/324 -f 122/402/354 124/400/352 244/373/325 -f 124/400/352 242/377/329 244/373/325 -f 245/372/324 123/401/353 121/403/355 -f 245/372/324 121/403/355 247/368/320 -f 120/404/356 122/402/354 244/373/325 -f 120/404/356 244/373/325 246/369/321 -f 247/368/320 121/403/355 119/405/357 -f 247/368/320 119/405/357 249/364/316 -f 118/406/358 120/404/356 246/369/321 -f 118/406/358 246/369/321 248/365/317 -f 249/364/316 119/405/357 117/407/359 -f 249/364/316 117/407/359 251/360/312 -f 116/408/360 118/406/358 248/365/317 -f 116/408/360 248/365/317 250/361/313 -f 251/360/312 117/407/359 115/409/361 -f 251/360/312 115/409/361 253/356/308 -f 114/410/362 116/408/360 250/361/313 -f 114/410/362 250/361/313 252/357/309 -f 253/356/308 115/409/361 235/340/292 -f 115/409/361 182/411/363 235/340/292 -f 181/412/364 114/410/362 234/344/296 -f 114/410/362 252/357/309 234/344/296 -f 255/347/299 113/413/365 257/351/303 -f 113/413/365 111/391/343 257/351/303 -f 110/394/346 112/414/366 256/353/305 -f 112/414/366 254/349/301 256/353/305 -f 233/341/293 184/415/367 113/413/365 -f 233/341/293 113/413/365 255/347/299 -f 112/414/366 183/416/368 232/343/295 -f 112/414/366 232/343/295 254/349/301 -f 235/340/292 182/411/363 184/415/367 -f 235/340/292 184/415/367 233/341/293 -f 183/416/368 181/412/364 234/344/296 -f 183/416/368 234/344/296 232/343/295 -f 230/23/23 231/417/369 224/418/370 -f 230/23/23 224/418/370 226/24/24 -f 224/418/370 231/417/369 229/20/20 -f 224/418/370 229/20/20 225/19/19 -f 224/418/370 72/419/371 226/24/24 -f 72/419/371 223/420/372 226/24/24 -f 222/421/373 72/419/371 225/19/19 -f 72/419/371 224/418/370 225/19/19 -f 226/24/24 223/420/372 221/422/374 -f 226/24/24 221/422/374 228/22/22 -f 220/423/375 222/421/373 225/19/19 -f 220/423/375 225/19/19 227/21/21 -f 228/22/22 221/422/374 219/424/376 -f 228/22/22 219/424/376 230/23/23 -f 218/425/377 220/423/375 227/21/21 -f 218/425/377 227/21/21 229/20/20 -f 230/23/23 219/424/376 231/417/369 -f 219/424/376 217/426/378 231/417/369 -f 217/426/378 218/425/377 231/417/369 -f 218/425/377 229/20/20 231/417/369 -f 219/424/376 136/427/379 137/428/380 -f 219/424/376 137/428/380 217/426/378 -f 137/428/380 135/429/381 218/425/377 -f 137/428/380 218/425/377 217/426/378 -f 221/422/374 134/430/382 136/427/379 -f 221/422/374 136/427/379 219/424/376 -f 135/429/381 133/431/383 220/423/375 -f 135/429/381 220/423/375 218/425/377 -f 223/420/372 132/432/384 134/430/382 -f 223/420/372 134/430/382 221/422/374 -f 133/431/383 131/433/385 222/421/373 -f 133/431/383 222/421/373 220/423/375 -f 72/419/371 130/434/386 223/420/372 -f 130/434/386 132/432/384 223/420/372 -f 131/433/385 130/434/386 222/421/373 -f 130/434/386 72/419/371 222/421/373 -f 212/435/387 165/436/388 80/279/241 -f 212/435/387 80/279/241 216/286/244 -f 79/281/242 164/437/389 211/438/390 -f 79/281/242 211/438/390 215/287/245 -f 212/435/387 216/286/244 214/439/391 -f 216/286/244 210/440/246 214/439/391 -f 209/441/249 215/287/245 213/442/392 -f 215/287/245 211/438/390 213/442/392 -f 214/439/391 210/440/246 167/443/393 -f 210/440/246 82/444/247 167/443/393 -f 81/445/248 209/441/249 166/446/394 -f 209/441/249 213/442/392 166/446/394 -f 167/443/393 188/447/395 214/439/391 -f 188/447/395 145/448/396 214/439/391 -f 144/449/397 187/450/398 213/442/392 -f 187/450/398 166/446/394 213/442/392 -f 214/439/391 145/448/396 212/435/387 -f 145/448/396 143/451/399 212/435/387 -f 142/452/400 144/449/397 211/438/390 -f 144/449/397 213/442/392 211/438/390 -f 212/435/387 143/451/399 141/453/401 -f 212/435/387 141/453/401 165/436/388 -f 140/454/402 142/452/400 211/438/390 -f 140/454/402 211/438/390 164/437/389 -f 165/436/388 141/453/401 139/455/403 -f 165/436/388 139/455/403 177/456/404 -f 139/455/403 140/454/402 164/437/389 -f 139/455/403 164/437/389 177/456/404 -f 207/457/405 208/458/406 199/459/407 -f 207/457/405 199/459/407 205/460/408 -f 199/459/407 208/458/406 206/461/409 -f 199/459/407 206/461/409 204/462/410 -f 203/463/411 205/460/408 201/464/412 -f 205/460/408 199/459/407 201/464/412 -f 199/459/407 204/462/410 200/465/413 -f 204/462/410 202/466/414 200/465/413 -f 207/457/405 205/460/408 194/467/415 -f 207/457/405 194/467/415 192/468/416 -f 193/469/417 204/462/410 206/461/409 -f 193/469/417 206/461/409 191/470/418 -f 205/460/408 203/463/411 194/467/415 -f 203/463/411 196/471/419 194/467/415 -f 195/472/420 202/466/414 193/469/417 -f 202/466/414 204/462/410 193/469/417 -f 203/463/411 201/464/412 198/473/421 -f 203/463/411 198/473/421 196/471/419 -f 197/474/422 200/465/413 202/466/414 -f 197/474/422 202/466/414 195/472/420 -f 201/464/412 199/459/407 71/475/423 -f 201/464/412 71/475/423 198/473/421 -f 71/475/423 199/459/407 200/465/413 -f 71/475/423 200/465/413 197/474/422 -f 207/457/405 192/468/416 208/458/406 -f 192/468/416 70/476/424 208/458/406 -f 70/476/424 191/470/418 208/458/406 -f 191/470/418 206/461/409 208/458/406 -f 192/468/416 145/448/396 70/476/424 -f 145/448/396 190/477/425 70/476/424 -f 190/477/425 144/449/397 70/476/424 -f 144/449/397 191/470/418 70/476/424 -f 198/473/421 71/475/423 139/455/403 -f 71/478/423 138/479/426 139/480/403 -f 138/481/426 71/482/423 139/483/403 -f 71/475/423 197/474/422 139/455/403 -f 196/471/419 198/473/421 141/453/401 -f 198/473/421 139/455/403 141/453/401 -f 139/455/403 197/474/422 140/454/402 -f 197/474/422 195/472/420 140/454/402 -f 194/467/415 196/471/419 143/451/399 -f 196/471/419 141/453/401 143/451/399 -f 140/454/402 195/472/420 142/452/400 -f 195/472/420 193/469/417 142/452/400 -f 192/468/416 194/467/415 143/451/399 -f 192/468/416 143/451/399 145/448/396 -f 142/452/400 193/469/417 191/470/418 -f 142/452/400 191/470/418 144/449/397 -f 186/484/427 132/432/384 69/485/428 -f 132/432/384 130/434/386 69/485/428 -f 130/434/386 131/433/385 69/485/428 -f 131/433/385 185/486/429 69/485/428 -f 189/487/430 188/447/395 69/485/428 -f 188/447/395 186/484/427 69/485/428 -f 185/486/429 187/450/398 69/485/428 -f 187/450/398 189/487/430 69/485/428 -f 189/487/430 190/477/425 188/447/395 -f 190/477/425 145/448/396 188/447/395 -f 144/449/397 190/477/425 187/450/398 -f 190/477/425 189/487/430 187/450/398 -f 169/488/431 171/489/432 132/432/384 -f 169/488/431 132/432/384 186/484/427 -f 131/433/385 170/490/433 168/491/434 -f 131/433/385 168/491/434 185/486/429 -f 186/484/427 188/447/395 167/443/393 -f 186/484/427 167/443/393 169/488/431 -f 166/446/394 187/450/398 185/486/429 -f 166/446/394 185/486/429 168/491/434 -f 173/492/435 134/430/382 171/489/432 -f 134/430/382 132/432/384 171/489/432 -f 131/433/385 133/431/383 170/490/433 -f 133/431/383 172/493/436 170/490/433 -f 175/494/437 136/427/379 134/430/382 -f 175/494/437 134/430/382 173/492/435 -f 133/431/383 135/429/381 174/495/438 -f 133/431/383 174/495/438 172/493/436 -f 176/496/439 137/428/380 136/427/379 -f 176/496/439 136/427/379 175/494/437 -f 135/429/381 137/428/380 176/496/439 -f 135/429/381 176/496/439 174/495/438 -f 184/415/367 182/411/363 178/497/440 -f 182/411/363 177/456/404 178/497/440 -f 177/456/404 181/412/364 178/497/440 -f 181/412/364 183/416/368 178/497/440 -f 178/497/440 68/498/441 113/413/365 -f 178/497/440 113/413/365 184/415/367 -f 112/414/366 68/498/441 178/497/440 -f 112/414/366 178/497/440 183/416/368 -f 68/498/441 163/499/442 113/413/365 -f 163/499/442 111/391/343 113/413/365 -f 110/394/346 162/500/443 112/414/366 -f 162/500/443 68/498/441 112/414/366 -f 177/456/404 182/411/363 115/409/361 -f 177/456/404 115/409/361 165/436/388 -f 114/410/362 181/412/364 177/456/404 -f 114/410/362 177/456/404 164/437/389 -f 147/501/444 165/436/388 115/409/361 -f 147/501/444 115/409/361 117/407/359 -f 114/410/362 164/437/389 146/502/445 -f 114/410/362 146/502/445 116/408/360 -f 149/503/446 147/501/444 119/405/357 -f 147/501/444 117/407/359 119/405/357 -f 116/408/360 146/502/445 118/406/358 -f 146/502/445 148/504/447 118/406/358 -f 151/505/448 149/503/446 121/403/355 -f 149/503/446 119/405/357 121/403/355 -f 118/406/358 148/504/447 120/404/356 -f 148/504/447 150/506/449 120/404/356 -f 153/507/450 151/505/448 123/401/353 -f 151/505/448 121/403/355 123/401/353 -f 120/404/356 150/506/449 122/402/354 -f 150/506/449 152/508/451 122/402/354 -f 155/509/452 153/507/450 125/399/351 -f 153/507/450 123/401/353 125/399/351 -f 122/402/354 152/508/451 124/400/352 -f 152/508/451 154/510/453 124/400/352 -f 157/511/454 155/509/452 127/397/349 -f 155/509/452 125/399/351 127/397/349 -f 124/400/352 154/510/453 126/398/350 -f 154/510/453 156/512/455 126/398/350 -f 159/513/456 157/511/454 180/395/347 -f 157/511/454 127/397/349 180/395/347 -f 126/398/350 156/512/455 179/396/348 -f 156/512/455 158/514/457 179/396/348 -f 159/513/456 180/395/347 129/392/344 -f 159/513/456 129/392/344 161/515/458 -f 128/393/345 179/396/348 158/514/457 -f 128/393/345 158/514/457 160/516/459 -f 161/515/458 129/392/344 163/499/442 -f 129/392/344 111/391/343 163/499/442 -f 110/394/346 128/393/345 162/500/443 -f 128/393/345 160/516/459 162/500/443 -f 68/498/441 67/517/290 163/499/442 -f 67/517/290 109/518/288 163/499/442 -f 108/519/289 67/517/290 162/500/443 -f 67/517/290 68/498/441 162/500/443 -f 163/499/442 109/518/288 161/515/458 -f 109/518/288 107/520/286 161/515/458 -f 106/521/287 108/519/289 160/516/459 -f 108/519/289 162/500/443 160/516/459 -f 161/515/458 107/520/286 159/513/456 -f 107/520/286 105/522/284 159/513/456 -f 104/523/285 106/521/287 158/514/457 -f 106/521/287 160/516/459 158/514/457 -f 159/513/456 105/522/284 103/524/282 -f 159/513/456 103/524/282 157/511/454 -f 102/525/283 104/523/285 158/514/457 -f 102/525/283 158/514/457 156/512/455 -f 157/511/454 103/524/282 155/509/452 -f 103/524/282 101/526/280 155/509/452 -f 100/527/281 102/525/283 154/510/453 -f 102/525/283 156/512/455 154/510/453 -f 155/509/452 101/526/280 153/507/450 -f 101/526/280 99/528/278 153/507/450 -f 98/529/279 100/527/281 152/508/451 -f 100/527/281 154/510/453 152/508/451 -f 153/507/450 99/528/278 151/505/448 -f 99/528/278 97/530/276 151/505/448 -f 96/531/277 98/529/279 150/506/449 -f 98/529/279 152/508/451 150/506/449 -f 151/505/448 97/530/276 95/532/274 -f 151/505/448 95/532/274 149/503/446 -f 94/533/275 96/531/277 150/506/449 -f 94/533/275 150/506/449 148/504/447 -f 149/503/446 95/532/274 147/501/444 -f 95/532/274 93/280/240 147/501/444 -f 92/283/243 94/533/275 146/502/445 -f 94/533/275 148/504/447 146/502/445 -f 147/501/444 93/280/240 80/279/241 -f 147/501/444 80/279/241 165/436/388 -f 79/281/242 92/283/243 146/502/445 -f 79/281/242 146/502/445 164/437/389 -f 169/488/431 167/443/393 82/444/247 -f 169/488/431 82/444/247 84/534/251 -f 81/445/248 166/446/394 168/491/434 -f 81/445/248 168/491/434 83/535/252 -f 171/489/432 169/488/431 84/534/251 -f 171/489/432 84/534/251 86/536/264 -f 83/535/252 168/491/434 170/490/433 -f 83/535/252 170/490/433 85/537/265 -f 173/492/435 171/489/432 86/536/264 -f 173/492/435 86/536/264 88/538/266 -f 85/537/265 170/490/433 172/493/436 -f 85/537/265 172/493/436 87/539/267 -f 175/494/437 173/492/435 90/540/268 -f 173/492/435 88/538/266 90/540/268 -f 87/539/267 172/493/436 89/541/269 -f 172/493/436 174/495/438 89/541/269 -f 176/496/439 175/494/437 91/542/271 -f 175/494/437 90/540/268 91/542/271 -f 89/541/269 174/495/438 91/542/271 -f 174/495/438 176/496/439 91/542/271 -f 50/4/4 48/543/460 2/544/461 -f 50/4/4 2/544/461 66/5/5 -f 1/545/462 47/546/463 49/3/3 -f 1/545/462 49/3/3 65/2/2 -f 66/5/5 2/544/461 12/547/464 -f 66/5/5 12/547/464 64/8/8 -f 11/548/465 1/545/462 65/2/2 -f 11/548/465 65/2/2 63/7/7 -f 64/8/8 12/547/464 14/549/466 -f 64/8/8 14/549/466 60/10/10 -f 13/550/467 11/548/465 63/7/7 -f 13/550/467 63/7/7 59/9/9 -f 60/10/10 14/549/466 24/551/468 -f 60/10/10 24/551/468 58/12/12 -f 23/552/469 13/550/467 59/9/9 -f 23/552/469 59/9/9 57/11/11 -f 58/12/12 24/551/468 56/14/14 -f 24/551/468 26/553/470 56/14/14 -f 25/554/471 23/552/469 55/13/13 -f 23/552/469 57/11/11 55/13/13 -f 56/14/14 26/553/470 54/16/16 -f 26/553/470 36/555/472 54/16/16 -f 35/556/473 25/554/471 53/15/15 -f 25/554/471 55/13/13 53/15/15 -f 54/16/16 36/555/472 52/18/18 -f 36/555/472 38/557/474 52/18/18 -f 37/558/475 35/556/473 51/17/17 -f 35/556/473 53/15/15 51/17/17 -f 52/18/18 38/557/474 50/4/4 -f 38/557/474 48/543/460 50/4/4 -f 47/546/463 37/558/475 49/3/3 -f 37/558/475 51/17/17 49/3/3 -f 46/559/476 48/543/460 40/560/477 -f 48/543/460 38/557/474 40/560/477 -f 37/558/475 47/546/463 39/561/478 -f 47/546/463 45/562/479 39/561/478 -f 44/563/480 46/559/476 42/564/481 -f 46/559/476 40/560/477 42/564/481 -f 39/561/478 45/562/479 41/565/482 -f 45/562/479 43/566/483 41/565/482 -f 42/564/481 40/560/477 32/567/484 -f 40/560/477 34/568/485 32/567/484 -f 33/569/486 39/561/478 31/570/487 -f 39/561/478 41/565/482 31/570/487 -f 40/560/477 38/557/474 34/568/485 -f 38/557/474 36/555/472 34/568/485 -f 35/556/473 37/558/475 33/569/486 -f 37/558/475 39/561/478 33/569/486 -f 34/568/485 36/555/472 28/571/488 -f 36/555/472 26/553/470 28/571/488 -f 25/554/471 35/556/473 27/572/489 -f 35/556/473 33/569/486 27/572/489 -f 32/567/484 34/568/485 30/573/490 -f 34/568/485 28/571/488 30/573/490 -f 27/572/489 33/569/486 29/574/491 -f 33/569/486 31/570/487 29/574/491 -f 30/573/490 28/571/488 20/575/492 -f 28/571/488 22/576/493 20/575/492 -f 21/577/494 27/572/489 19/578/495 -f 27/572/489 29/574/491 19/578/495 -f 28/571/488 26/553/470 24/551/468 -f 28/571/488 24/551/468 22/576/493 -f 23/552/469 25/554/471 27/572/489 -f 23/552/469 27/572/489 21/577/494 -f 22/576/493 24/551/468 16/579/496 -f 24/551/468 14/549/466 16/579/496 -f 13/550/467 23/552/469 15/580/497 -f 23/552/469 21/577/494 15/580/497 -f 20/575/492 22/576/493 18/581/498 -f 22/576/493 16/579/496 18/581/498 -f 15/580/497 21/577/494 17/582/499 -f 21/577/494 19/578/495 17/582/499 -f 18/581/498 16/579/496 10/583/500 -f 18/581/498 10/583/500 8/584/501 -f 9/585/502 15/580/497 17/582/499 -f 9/585/502 17/582/499 7/586/503 -f 16/579/496 14/549/466 12/547/464 -f 16/579/496 12/547/464 10/583/500 -f 11/548/465 13/550/467 15/580/497 -f 11/548/465 15/580/497 9/585/502 -f 10/583/500 12/547/464 2/544/461 -f 10/583/500 2/544/461 4/587/504 -f 1/545/462 11/548/465 9/585/502 -f 1/545/462 9/585/502 3/588/505 -f 8/584/501 10/583/500 4/587/504 -f 8/584/501 4/587/504 6/589/506 -f 3/588/505 9/585/502 7/586/503 -f 3/588/505 7/586/503 5/590/507 -f 6/589/506 4/587/504 46/559/476 -f 6/589/506 46/559/476 44/563/480 -f 45/562/479 3/588/505 5/590/507 -f 45/562/479 5/590/507 43/566/483 -f 4/587/504 2/544/461 48/543/460 -f 4/587/504 48/543/460 46/559/476 -f 47/546/463 1/545/462 3/588/505 -f 47/546/463 3/588/505 45/562/479 \ No newline at end of file +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 5/5/5 6/6/6 +f 7/7/7 2/2/2 1/1/1 +f 6/6/6 5/5/5 8/8/8 +f 1/1/1 9/9/9 7/7/7 +f 8/8/8 10/10/10 6/6/6 +f 1/1/1 11/11/11 9/9/9 +f 10/10/10 12/12/12 6/6/6 +f 1/1/1 13/13/13 11/11/11 +f 12/12/12 14/14/14 6/6/6 +f 1/1/1 15/15/15 13/13/13 +f 14/14/14 16/16/16 6/6/6 +f 1/1/1 17/17/17 15/15/15 +f 16/16/16 18/18/18 6/6/6 +f 1/1/1 3/3/3 17/17/17 +f 18/18/18 4/4/4 6/6/6 +f 19/19/19 20/20/20 21/21/21 +f 22/22/22 23/23/23 24/24/24 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 29/29/29 30/30/30 +f 31/31/31 32/32/32 33/33/33 +f 34/34/34 35/35/35 36/36/36 +f 37/37/37 38/38/38 39/39/39 +f 40/40/40 41/41/41 42/42/42 +f 43/43/43 44/44/44 45/45/45 +f 46/46/46 47/47/47 48/48/48 +f 49/49/49 50/50/50 51/51/51 +f 49/49/49 51/51/51 52/52/52 +f 53/53/53 54/54/54 55/55/55 +f 53/53/53 55/55/55 56/56/56 +f 49/49/49 57/57/57 58/58/58 +f 49/49/49 58/58/58 50/50/50 +f 59/59/59 60/60/60 55/55/55 +f 59/59/59 55/55/55 54/54/54 +f 61/61/61 62/62/62 57/57/57 +f 62/62/62 58/58/58 57/57/57 +f 59/59/59 63/63/63 60/60/60 +f 63/63/63 64/64/64 60/60/60 +f 46/46/46 48/48/48 57/57/57 +f 46/46/46 57/57/57 65/65/65 +f 60/60/60 43/43/43 45/45/45 +f 60/60/60 45/45/45 66/66/66 +f 49/49/49 65/65/65 57/57/57 +f 66/66/66 55/55/55 60/60/60 +f 48/48/48 67/67/67 57/57/57 +f 67/67/67 61/61/61 57/57/57 +f 64/64/64 68/68/68 60/60/60 +f 68/68/68 43/43/43 60/60/60 +f 47/47/47 67/67/67 48/48/48 +f 68/68/68 44/44/44 43/43/43 +f 46/46/46 69/69/69 47/47/47 +f 70/70/70 45/45/45 44/44/44 +f 65/65/65 71/71/71 69/69/69 +f 65/65/65 69/69/69 46/46/46 +f 70/70/70 72/72/72 66/66/66 +f 70/70/70 66/66/66 45/45/45 +f 49/49/49 52/52/52 71/71/71 +f 49/49/49 71/71/71 65/65/65 +f 72/72/72 56/56/56 55/55/55 +f 72/72/72 55/55/55 66/66/66 +f 41/41/41 40/40/40 73/73/73 +f 39/39/39 38/38/38 74/74/74 +f 41/41/41 73/73/73 75/75/75 +f 74/74/74 38/38/38 76/76/76 +f 77/77/77 41/41/41 75/75/75 +f 77/77/77 75/75/75 78/78/78 +f 76/76/76 38/38/38 79/79/79 +f 76/76/76 79/79/79 80/80/80 +f 81/81/81 42/42/42 41/41/41 +f 37/37/37 82/82/82 38/38/38 +f 41/41/41 77/77/77 81/81/81 +f 79/79/79 38/38/38 82/82/82 +f 83/83/83 84/84/84 62/62/62 +f 85/85/85 86/86/86 82/82/82 +f 85/85/85 82/82/82 87/87/87 +f 81/81/81 62/62/62 42/42/42 +f 87/87/87 82/82/82 37/37/37 +f 83/83/83 62/62/62 81/81/81 +f 82/82/82 86/86/86 79/79/79 +f 77/77/77 83/83/83 81/81/81 +f 77/77/77 78/78/78 88/88/88 +f 77/77/77 88/88/88 83/83/83 +f 89/89/89 80/80/80 79/79/79 +f 89/89/89 79/79/79 86/86/86 +f 88/88/88 90/90/90 83/83/83 +f 91/91/91 89/89/89 86/86/86 +f 92/92/92 87/87/87 37/37/37 +f 42/42/42 62/62/62 40/40/40 +f 37/37/37 39/39/39 92/92/92 +f 73/73/73 40/40/40 93/93/93 +f 92/92/92 39/39/39 94/94/94 +f 39/39/39 74/74/74 94/94/94 +f 75/75/75 73/73/73 95/95/95 +f 73/73/73 93/93/93 95/95/95 +f 94/94/94 74/74/74 96/96/96 +f 74/74/74 76/76/76 96/96/96 +f 78/78/78 75/75/75 95/95/95 +f 78/78/78 95/95/95 97/97/97 +f 96/96/96 76/76/76 80/80/80 +f 96/96/96 80/80/80 98/98/98 +f 78/78/78 97/97/97 88/88/88 +f 98/98/98 80/80/80 89/89/89 +f 40/40/40 67/67/67 93/93/93 +f 99/99/99 92/92/92 94/94/94 +f 40/40/40 62/62/62 61/61/61 +f 40/40/40 61/61/61 67/67/67 +f 100/100/100 92/92/92 99/99/99 +f 100/100/100 87/87/87 92/92/92 +f 101/101/101 28/28/28 102/102/102 +f 27/27/27 103/103/103 104/104/104 +f 101/101/101 102/102/102 105/105/105 +f 102/102/102 106/106/106 105/105/105 +f 107/107/107 104/104/104 108/108/108 +f 104/104/104 103/103/103 108/108/108 +f 30/30/30 34/34/34 36/36/36 +f 30/30/30 36/36/36 28/28/28 +f 31/31/31 33/33/33 25/25/25 +f 31/31/31 25/25/25 27/27/27 +f 28/28/28 36/36/36 109/109/109 +f 31/31/31 27/27/27 110/110/110 +f 101/101/101 29/29/29 28/28/28 +f 26/26/26 103/103/103 27/27/27 +f 111/111/111 112/112/112 113/113/113 +f 112/112/112 106/106/106 113/113/113 +f 107/107/107 114/114/114 115/115/115 +f 114/114/114 116/116/116 115/115/115 +f 111/111/111 113/113/113 117/117/117 +f 118/118/118 115/115/115 116/116/116 +f 111/111/111 117/117/117 119/119/119 +f 118/118/118 116/116/116 120/120/120 +f 117/117/117 121/121/121 119/119/119 +f 122/122/122 118/118/118 120/120/120 +f 123/123/123 124/124/124 23/23/23 +f 123/123/123 23/23/23 22/22/22 +f 20/20/20 125/125/125 126/126/126 +f 20/20/20 126/126/126 21/21/21 +f 127/127/127 123/123/123 128/128/128 +f 123/123/123 22/22/22 128/128/128 +f 21/21/21 126/126/126 129/129/129 +f 126/126/126 130/130/130 129/129/129 +f 119/119/119 124/124/124 123/123/123 +f 125/125/125 120/120/120 126/126/126 +f 123/123/123 127/127/127 111/111/111 +f 130/130/130 126/126/126 116/116/116 +f 111/111/111 127/127/127 131/131/131 +f 111/111/111 131/131/131 112/112/112 +f 132/132/132 130/130/130 116/116/116 +f 132/132/132 116/116/116 114/114/114 +f 112/112/112 131/131/131 105/105/105 +f 108/108/108 132/132/132 114/114/114 +f 105/105/105 106/106/106 112/112/112 +f 107/107/107 108/108/108 114/114/114 +f 111/111/111 119/119/119 123/123/123 +f 126/126/126 120/120/120 116/116/116 +f 105/105/105 131/131/131 133/133/133 +f 132/132/132 108/108/108 134/134/134 +f 131/131/131 127/127/127 135/135/135 +f 136/136/136 130/130/130 132/132/132 +f 127/127/127 128/128/128 135/135/135 +f 129/129/129 130/130/130 136/136/136 +f 101/101/101 105/105/105 137/137/137 +f 105/105/105 133/133/133 137/137/137 +f 134/134/134 108/108/108 138/138/138 +f 108/108/108 103/103/103 138/138/138 +f 109/109/109 36/36/36 121/121/121 +f 109/109/109 121/121/121 117/117/117 +f 122/122/122 31/31/31 110/110/110 +f 122/122/122 110/110/110 118/118/118 +f 29/29/29 139/139/139 30/30/30 +f 140/140/140 26/26/26 25/25/25 +f 29/29/29 101/101/101 141/141/141 +f 29/29/29 141/141/141 142/142/142 +f 143/143/143 103/103/103 26/26/26 +f 143/143/143 26/26/26 144/144/144 +f 101/101/101 137/137/137 141/141/141 +f 138/138/138 103/103/103 143/143/143 +f 36/36/36 35/35/35 145/145/145 +f 146/146/146 147/147/147 148/148/148 +f 149/149/149 150/150/150 151/151/151 +f 32/32/32 31/31/31 152/152/152 +f 34/34/34 153/153/153 35/35/35 +f 154/154/154 147/147/147 146/146/146 +f 149/149/149 155/155/155 150/150/150 +f 156/156/156 33/33/33 32/32/32 +f 34/34/34 30/30/30 153/153/153 +f 30/30/30 139/139/139 153/153/153 +f 140/140/140 25/25/25 156/156/156 +f 25/25/25 33/33/33 156/156/156 +f 157/157/157 158/158/158 139/139/139 +f 140/140/140 159/159/159 160/160/160 +f 157/157/157 139/139/139 29/29/29 +f 140/140/140 160/160/160 26/26/26 +f 160/160/160 161/161/161 162/162/162 +f 161/161/161 163/163/163 162/162/162 +f 164/164/164 158/158/158 157/157/157 +f 159/159/159 161/161/161 160/160/160 +f 157/157/157 165/165/165 164/164/164 +f 165/165/165 166/166/166 164/164/164 +f 29/29/29 142/142/142 157/157/157 +f 142/142/142 165/165/165 157/157/157 +f 162/162/162 144/144/144 160/160/160 +f 144/144/144 26/26/26 160/160/160 +f 36/36/36 145/145/145 167/167/167 +f 168/168/168 152/152/152 31/31/31 +f 36/36/36 167/167/167 121/121/121 +f 122/122/122 168/168/168 31/31/31 +f 121/121/121 169/169/169 119/119/119 +f 170/170/170 122/122/122 120/120/120 +f 119/119/119 169/169/169 171/171/171 +f 172/172/172 170/170/170 120/120/120 +f 119/119/119 171/171/171 124/124/124 +f 172/172/172 120/120/120 125/125/125 +f 171/171/171 173/173/173 124/124/124 +f 174/174/174 172/172/172 125/125/125 +f 124/124/124 173/173/173 175/175/175 +f 124/124/124 175/175/175 23/23/23 +f 176/176/176 174/174/174 125/125/125 +f 176/176/176 125/125/125 20/20/20 +f 23/23/23 175/175/175 24/24/24 +f 19/19/19 176/176/176 20/20/20 +f 177/177/177 178/178/178 179/179/179 +f 177/177/177 179/179/179 180/180/180 +f 181/181/181 182/182/182 183/183/183 +f 181/181/181 183/183/183 184/184/184 +f 180/180/180 179/179/179 185/185/185 +f 180/180/180 185/185/185 186/186/186 +f 187/187/187 181/181/181 184/184/184 +f 187/187/187 184/184/184 188/188/188 +f 186/186/186 185/185/185 189/189/189 +f 186/186/186 189/189/189 190/190/190 +f 191/191/191 187/187/187 188/188/188 +f 191/191/191 188/188/188 192/192/192 +f 193/193/193 194/194/194 178/178/178 +f 193/193/193 178/178/178 177/177/177 +f 182/182/182 195/195/195 196/196/196 +f 182/182/182 196/196/196 183/183/183 +f 197/197/197 198/198/198 193/193/193 +f 198/198/198 194/194/194 193/193/193 +f 195/195/195 199/199/199 196/196/196 +f 199/199/199 200/200/200 196/196/196 +f 201/201/201 202/202/202 197/197/197 +f 202/202/202 198/198/198 197/197/197 +f 199/199/199 203/203/203 200/200/200 +f 203/203/203 204/204/204 200/200/200 +f 205/205/205 206/206/206 202/202/202 +f 205/205/205 202/202/202 201/201/201 +f 203/203/203 207/207/207 208/208/208 +f 203/203/203 208/208/208 204/204/204 +f 209/209/209 210/210/210 205/205/205 +f 210/210/210 206/206/206 205/205/205 +f 207/207/207 211/211/211 208/208/208 +f 211/211/211 212/212/212 208/208/208 +f 213/213/213 214/214/214 210/210/210 +f 213/213/213 210/210/210 209/209/209 +f 211/211/211 215/215/215 216/216/216 +f 211/211/211 216/216/216 212/212/212 +f 217/217/217 218/218/218 213/213/213 +f 218/218/218 214/214/214 213/213/213 +f 215/215/215 219/219/219 216/216/216 +f 219/219/219 220/220/220 216/216/216 +f 221/221/221 222/222/222 217/217/217 +f 222/222/222 218/218/218 217/217/217 +f 219/219/219 223/223/223 220/220/220 +f 223/223/223 224/224/224 220/220/220 +f 225/225/225 226/226/226 222/222/222 +f 225/225/225 222/222/222 221/221/221 +f 223/223/223 227/227/227 228/228/228 +f 223/223/223 228/228/228 224/224/224 +f 190/190/190 189/189/189 226/226/226 +f 190/190/190 226/226/226 225/225/225 +f 227/227/227 191/191/191 192/192/192 +f 227/227/227 192/192/192 228/228/228 +f 189/189/189 229/229/229 226/226/226 +f 230/230/230 191/191/191 227/227/227 +f 226/226/226 229/229/229 222/222/222 +f 230/230/230 227/227/227 223/223/223 +f 222/222/222 229/229/229 214/214/214 +f 222/222/222 214/214/214 218/218/218 +f 215/215/215 230/230/230 223/223/223 +f 215/215/215 223/223/223 219/219/219 +f 214/214/214 231/231/231 210/210/210 +f 232/232/232 215/215/215 211/211/211 +f 210/210/210 231/231/231 206/206/206 +f 207/207/207 232/232/232 211/211/211 +f 206/206/206 233/233/233 202/202/202 +f 234/234/234 207/207/207 203/203/203 +f 202/202/202 233/233/233 198/198/198 +f 199/199/199 234/234/234 203/203/203 +f 198/198/198 235/235/235 194/194/194 +f 236/236/236 199/199/199 195/195/195 +f 194/194/194 235/235/235 178/178/178 +f 236/236/236 195/195/195 182/182/182 +f 185/185/185 237/237/237 189/189/189 +f 238/238/238 187/187/187 191/191/191 +f 179/179/179 237/237/237 185/185/185 +f 238/238/238 181/181/181 187/187/187 +f 178/178/178 235/235/235 237/237/237 +f 178/178/178 237/237/237 179/179/179 +f 238/238/238 236/236/236 182/182/182 +f 238/238/238 182/182/182 181/181/181 +f 239/239/239 240/240/240 241/241/241 +f 241/241/241 240/240/240 242/242/242 +f 243/243/243 244/244/244 239/239/239 +f 243/243/243 239/239/239 241/241/241 +f 242/242/242 243/243/243 241/241/241 +f 239/239/239 244/244/244 240/240/240 +f 245/245/245 246/246/246 147/147/147 +f 245/245/245 147/147/147 154/154/154 +f 149/149/149 247/247/247 248/248/248 +f 149/149/149 248/248/248 155/155/155 +f 245/245/245 154/154/154 249/249/249 +f 154/154/154 250/250/250 249/249/249 +f 251/251/251 155/155/155 252/252/252 +f 155/155/155 248/248/248 252/252/252 +f 253/253/253 254/254/254 249/249/249 +f 255/255/255 253/253/253 252/252/252 +f 249/249/249 254/254/254 245/245/245 +f 254/254/254 256/256/256 245/245/245 +f 257/257/257 255/255/255 248/248/248 +f 255/255/255 252/252/252 248/248/248 +f 245/245/245 256/256/256 258/258/258 +f 245/245/245 258/258/258 246/246/246 +f 259/259/259 257/257/257 248/248/248 +f 259/259/259 248/248/248 247/247/247 +f 246/246/246 258/258/258 260/260/260 +f 260/260/260 259/259/259 247/247/247 +f 261/261/261 262/262/262 263/263/263 +f 263/263/263 262/262/262 264/264/264 +f 258/258/258 261/261/261 263/263/263 +f 264/264/264 259/259/259 263/263/263 +f 261/261/261 265/265/265 262/262/262 +f 265/265/265 264/264/264 262/262/262 +f 261/261/261 254/254/254 265/265/265 +f 254/254/254 253/253/253 265/265/265 +f 253/253/253 255/255/255 265/265/265 +f 255/255/255 264/264/264 265/265/265 +f 263/263/263 260/260/260 258/258/258 +f 260/260/260 263/263/263 259/259/259 +f 261/261/261 258/258/258 256/256/256 +f 259/259/259 264/264/264 257/257/257 +f 261/261/261 256/256/256 254/254/254 +f 257/257/257 264/264/264 255/255/255 +f 244/244/244 253/253/253 240/240/240 +f 240/240/240 253/253/253 249/249/249 +f 240/240/240 249/249/249 266/266/266 +f 252/252/252 253/253/253 244/244/244 +f 252/252/252 244/244/244 267/267/267 +f 268/268/268 242/242/242 266/266/266 +f 242/242/242 240/240/240 266/266/266 +f 244/244/244 243/243/243 267/267/267 +f 243/243/243 269/269/269 267/267/267 +f 270/270/270 242/242/242 268/268/268 +f 243/243/243 242/242/242 270/270/270 +f 243/243/243 270/270/270 269/269/269 +f 235/235/235 260/260/260 237/237/237 +f 260/260/260 236/236/236 237/237/237 +f 236/236/236 238/238/238 237/237/237 +f 191/191/191 237/237/237 238/238/238 +f 260/260/260 235/235/235 246/246/246 +f 236/236/236 260/260/260 247/247/247 +f 233/233/233 246/246/246 235/235/235 +f 233/233/233 235/235/235 198/198/198 +f 236/236/236 247/247/247 234/234/234 +f 236/236/236 234/234/234 199/199/199 +f 231/231/231 233/233/233 206/206/206 +f 234/234/234 232/232/232 207/207/207 +f 271/271/271 214/214/214 229/229/229 +f 215/215/215 272/272/272 230/230/230 +f 271/271/271 229/229/229 189/189/189 +f 230/230/230 272/272/272 191/191/191 +f 237/237/237 273/273/273 189/189/189 +f 273/273/273 274/274/274 189/189/189 +f 275/275/275 273/273/273 191/191/191 +f 273/273/273 237/237/237 191/191/191 +f 189/189/189 274/274/274 271/271/271 +f 274/274/274 276/276/276 271/271/271 +f 277/277/277 275/275/275 272/272/272 +f 275/275/275 191/191/191 272/272/272 +f 271/271/271 276/276/276 278/278/278 +f 279/279/279 277/277/277 272/272/272 +f 271/271/271 278/278/278 214/214/214 +f 279/279/279 272/272/272 215/215/215 +f 278/278/278 280/280/280 214/214/214 +f 281/281/281 279/279/279 215/215/215 +f 214/214/214 280/280/280 231/231/231 +f 280/280/280 282/282/282 231/231/231 +f 283/283/283 281/281/281 232/232/232 +f 281/281/281 215/215/215 232/232/232 +f 231/231/231 282/282/282 284/284/284 +f 285/285/285 283/283/283 232/232/232 +f 231/231/231 284/284/284 233/233/233 +f 284/284/284 148/148/148 233/233/233 +f 151/151/151 285/285/285 234/234/234 +f 285/285/285 232/232/232 234/234/234 +f 233/233/233 148/148/148 147/147/147 +f 233/233/233 147/147/147 246/246/246 +f 149/149/149 151/151/151 234/234/234 +f 149/149/149 234/234/234 247/247/247 +f 266/266/266 249/249/249 250/250/250 +f 251/251/251 252/252/252 267/267/267 +f 4/4/4 286/286/286 287/287/287 +f 4/4/4 287/287/287 5/5/5 +f 288/288/288 289/289/289 3/3/3 +f 288/288/288 3/3/3 2/2/2 +f 5/5/5 287/287/287 290/290/290 +f 5/5/5 290/290/290 8/8/8 +f 291/291/291 288/288/288 2/2/2 +f 291/291/291 2/2/2 7/7/7 +f 8/8/8 290/290/290 292/292/292 +f 8/8/8 292/292/292 10/10/10 +f 293/293/293 291/291/291 7/7/7 +f 293/293/293 7/7/7 9/9/9 +f 10/10/10 292/292/292 294/294/294 +f 10/10/10 294/294/294 12/12/12 +f 295/295/295 293/293/293 9/9/9 +f 295/295/295 9/9/9 11/11/11 +f 12/12/12 294/294/294 14/14/14 +f 294/294/294 296/296/296 14/14/14 +f 297/297/297 295/295/295 13/13/13 +f 295/295/295 11/11/11 13/13/13 +f 14/14/14 296/296/296 16/16/16 +f 296/296/296 298/298/298 16/16/16 +f 299/299/299 297/297/297 15/15/15 +f 297/297/297 13/13/13 15/15/15 +f 16/16/16 298/298/298 18/18/18 +f 298/298/298 300/300/300 18/18/18 +f 301/301/301 299/299/299 17/17/17 +f 299/299/299 15/15/15 17/17/17 +f 18/18/18 300/300/300 4/4/4 +f 300/300/300 286/286/286 4/4/4 +f 289/289/289 301/301/301 3/3/3 +f 301/301/301 17/17/17 3/3/3 +f 302/302/302 286/286/286 303/303/303 +f 286/286/286 300/300/300 303/303/303 +f 301/301/301 289/289/289 304/304/304 +f 289/289/289 305/305/305 304/304/304 +f 306/306/306 302/302/302 307/307/307 +f 302/302/302 303/303/303 307/307/307 +f 304/304/304 305/305/305 308/308/308 +f 305/305/305 309/309/309 308/308/308 +f 307/307/307 303/303/303 310/310/310 +f 303/303/303 311/311/311 310/310/310 +f 312/312/312 304/304/304 313/313/313 +f 304/304/304 308/308/308 313/313/313 +f 303/303/303 300/300/300 311/311/311 +f 300/300/300 298/298/298 311/311/311 +f 299/299/299 301/301/301 312/312/312 +f 301/301/301 304/304/304 312/312/312 +f 311/311/311 298/298/298 314/314/314 +f 298/298/298 296/296/296 314/314/314 +f 297/297/297 299/299/299 315/315/315 +f 299/299/299 312/312/312 315/315/315 +f 310/310/310 311/311/311 316/316/316 +f 311/311/311 314/314/314 316/316/316 +f 315/315/315 312/312/312 317/317/317 +f 312/312/312 313/313/313 317/317/317 +f 316/316/316 314/314/314 318/318/318 +f 314/314/314 319/319/319 318/318/318 +f 320/320/320 315/315/315 321/321/321 +f 315/315/315 317/317/317 321/321/321 +f 314/314/314 296/296/296 294/294/294 +f 314/314/314 294/294/294 319/319/319 +f 295/295/295 297/297/297 315/315/315 +f 295/295/295 315/315/315 320/320/320 +f 319/319/319 294/294/294 322/322/322 +f 294/294/294 292/292/292 322/322/322 +f 293/293/293 295/295/295 323/323/323 +f 295/295/295 320/320/320 323/323/323 +f 318/318/318 319/319/319 324/324/324 +f 319/319/319 322/322/322 324/324/324 +f 323/323/323 320/320/320 325/325/325 +f 320/320/320 321/321/321 325/325/325 +f 324/324/324 322/322/322 326/326/326 +f 324/324/324 326/326/326 327/327/327 +f 328/328/328 323/323/323 325/325/325 +f 328/328/328 325/325/325 329/329/329 +f 322/322/322 292/292/292 290/290/290 +f 322/322/322 290/290/290 326/326/326 +f 291/291/291 293/293/293 323/323/323 +f 291/291/291 323/323/323 328/328/328 +f 326/326/326 290/290/290 287/287/287 +f 326/326/326 287/287/287 330/330/330 +f 288/288/288 291/291/291 328/328/328 +f 288/288/288 328/328/328 331/331/331 +f 327/327/327 326/326/326 330/330/330 +f 327/327/327 330/330/330 332/332/332 +f 331/331/331 328/328/328 329/329/329 +f 331/331/331 329/329/329 333/333/333 +f 332/332/332 330/330/330 302/302/302 +f 332/332/332 302/302/302 306/306/306 +f 305/305/305 331/331/331 333/333/333 +f 305/305/305 333/333/333 309/309/309 +f 330/330/330 287/287/287 286/286/286 +f 330/330/330 286/286/286 302/302/302 +f 289/289/289 288/288/288 331/331/331 +f 289/289/289 331/331/331 305/305/305 diff --git a/examples/public/textures/can-label.jpg b/examples/public/textures/can-label.jpg new file mode 100644 index 0000000..5bd5445 Binary files /dev/null and b/examples/public/textures/can-label.jpg differ diff --git a/examples/public/textures/can-lid.jpg b/examples/public/textures/can-lid.jpg new file mode 100644 index 0000000..2c244ed Binary files /dev/null and b/examples/public/textures/can-lid.jpg differ diff --git a/examples/public/textures/dirt.jpg b/examples/public/textures/dirt.jpg new file mode 100644 index 0000000..09f499c Binary files /dev/null and b/examples/public/textures/dirt.jpg differ diff --git a/examples/public/textures/lifebuoy.jpg b/examples/public/textures/lifebuoy.jpg new file mode 100644 index 0000000..f5d9e34 Binary files /dev/null and b/examples/public/textures/lifebuoy.jpg differ diff --git a/examples/public/textures/mountain.jpg b/examples/public/textures/mountain.jpg new file mode 100644 index 0000000..2efd781 Binary files /dev/null and b/examples/public/textures/mountain.jpg differ diff --git a/examples/public/textures/ornament.jpg b/examples/public/textures/ornament.jpg new file mode 100644 index 0000000..49fa0b4 Binary files /dev/null and b/examples/public/textures/ornament.jpg differ diff --git a/examples/public/textures/sprite0.png b/examples/public/textures/sprite0.png deleted file mode 100644 index 35538a6..0000000 Binary files a/examples/public/textures/sprite0.png and /dev/null differ diff --git a/examples/public/textures/sprite1.png b/examples/public/textures/sprite1.png deleted file mode 100644 index d78fbbe..0000000 Binary files a/examples/public/textures/sprite1.png and /dev/null differ diff --git a/examples/public/textures/sprite2.png b/examples/public/textures/sprite2.png deleted file mode 100644 index a1202d2..0000000 Binary files a/examples/public/textures/sprite2.png and /dev/null differ diff --git a/examples/three_fps.html b/examples/three_fps.html index ababbdf..af587f9 100644 --- a/examples/three_fps.html +++ b/examples/three_fps.html @@ -6,21 +6,21 @@ c3r - FPS -
three.js - - platformer demo. cubemap by + - platformer. Cubemap by Jochum Skoglund.
Click to look around with the mouse, WASD to move, SHIFT to run @@ -74,6 +75,7 @@ diff --git a/examples/three_geometry_cube.html b/examples/three_geometry_cube.html index 406caa1..a87b127 100644 --- a/examples/three_geometry_cube.html +++ b/examples/three_geometry_cube.html @@ -6,49 +6,51 @@ c3r - Cube geometry +
+ three.js + - cube geometry. Drag to spin the cube. +
+ diff --git a/examples/three_geometry_earth.html b/examples/three_geometry_earth.html index 406faf4..b9e0827 100644 --- a/examples/three_geometry_earth.html +++ b/examples/three_geometry_earth.html @@ -6,22 +6,22 @@ c3r - Earth -
three.js - - earth demo + - earth. Move the pointer to orbit.
diff --git a/examples/three_interactive_cubes_tween.html b/examples/three_interactive_cubes_tween.html index ec74ae4..dfd9ea2 100644 --- a/examples/three_interactive_cubes_tween.html +++ b/examples/three_interactive_cubes_tween.html @@ -6,25 +6,40 @@ c3r - Interactive cubes +
+ three.js + - interactive cubes. Click a cube to move it. +
+ diff --git a/examples/three_loader_obj.html b/examples/three_loader_obj.html index d7c9dc0..3664264 100644 --- a/examples/three_loader_obj.html +++ b/examples/three_loader_obj.html @@ -6,45 +6,42 @@ c3r - OBJ loader -
three.js - - OBJLoader test + - OBJ loader. Move the pointer to orbit.
diff --git a/examples/three_materials_texture_canvas.html b/examples/three_materials_texture_canvas.html deleted file mode 100644 index 3a2c35a..0000000 --- a/examples/three_materials_texture_canvas.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - c3r - Canvas material - - - -
- three.js - - webgl - canvas as a texture -
click and draw in the white box
-
- - - - - diff --git a/examples/three_periodictable.html b/examples/three_periodictable.html index 618d02e..8aa8b97 100644 --- a/examples/three_periodictable.html +++ b/examples/three_periodictable.html @@ -5,36 +5,32 @@ c3r - Periodic table
- three.js css3d - - sprites. + three.js + - css3d sprites. Drag to rotate, scroll to zoom.
-
diff --git a/examples/three_sprites2.html b/examples/three_sprites2.html deleted file mode 100644 index b70f18d..0000000 --- a/examples/three_sprites2.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - c3r - Sprites 2 - - - - - - - diff --git a/package-lock.json b/package-lock.json index ffef5f9..45b383e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,8 +29,10 @@ "examples": { "name": "c3r-examples", "devDependencies": { + "@picocss/pico": "^2.1.1", "gl-matrix": "^3.4.4", "nipplejs": "^1.0.4", + "primitive-geometry": "^3.3.1", "three": "^0.186.1", "vite": "^8.3.5" } @@ -101,6 +103,13 @@ "url": "https://github.com/sponsors/oxc-project" } }, + "node_modules/@picocss/pico": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@picocss/pico/-/pico-2.1.1.tgz", + "integrity": "sha512-kIDugA7Ps4U+2BHxiNHmvgPIQDWPDU4IeU6TNRdvXQM1uZX+FibqDQT2xUOnnO2yq/LUHcwnGlu1hvf4KfXnMg==", + "dev": true, + "license": "MIT" + }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -1629,6 +1638,27 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/primitive-geometry": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/primitive-geometry/-/primitive-geometry-3.3.1.tgz", + "integrity": "sha512-bwXzk3ziGfPN+2dKcIVILTdYbK1vu3Ni4Avi9qzPCyw3HXKLa0KjZ2pJ2hH3rPTaOqd1wSnqFHZgbaFEt9Bbmg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paypal.me/dmnsgn" + }, + { + "type": "individual", + "url": "https://commerce.coinbase.com/checkout/56cbdf28-e323-48d8-9c98-7019e72c97f3" + } + ], + "license": "MIT", + "engines": { + "node": ">=24.0.0", + "snowdev": ">=3.0.0-alpha.3" + } + }, "node_modules/rolldown": { "version": "1.2.15", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz", @@ -2035,20 +2065,21 @@ } }, "packages/c3r": { - "version": "0.2.1", + "version": "0.3.0", "license": "MIT", "dependencies": { "gl-matrix": "^3.4.4" }, "devDependencies": { + "primitive-geometry": "^3.3.1", "vite": "^8.3.5" } }, "packages/c3r-three": { - "version": "0.2.1", + "version": "0.3.0", "license": "MIT", "dependencies": { - "c3r": "^0.2.1" + "c3r": "^0.3.0" }, "devDependencies": { "@types/three": "^0.186.0", diff --git a/packages/c3r-three/README.md b/packages/c3r-three/README.md index fc5087d..0e26129 100644 --- a/packages/c3r-three/README.md +++ b/packages/c3r-three/README.md @@ -20,14 +20,16 @@ document.body.appendChild(renderer.domElement); renderer.render(scene, camera); ``` +Until `setSize()` the scenes fill the window and follow it, like a C3R `Container`. An orthographic camera needs `setSize()`. + `CSS3DObject` and `CSS3DSprite` are re-exported from `three/addons`, so their elements receive pointer events as with three's renderer. -Perspective and orthographic cameras are supported, including `zoom`. Material `color`, `map` (image or canvas, with `repeat` and `offset`), `opacity` and map alpha (when `transparent`) and `side` (`BackSide` shows both sides) are applied, and a material's style is removed on its `dispose()`. `renderer.dispose()` removes every rendered scene. +Perspective and orthographic cameras are supported, including `zoom`. Material `color`, `map` (image or canvas, with `repeat` and `offset`, its alpha always; a `color` tints it with `Filter.tint`), `opacity` (when `transparent`) and `side` (`BackSide` shows both sides) are applied, and a material's style is removed on its `dispose()`. `renderer.dispose()` removes every rendered scene, and `renderer.toHTML()` (async) exports them. Not supported yet: `ImageBitmap` maps such as GLTFLoader's, `flipY: false`, and map `rotation` and `center`. ## Node -Set up a DOM and inline `cssText()` as described in [c3r](../c3r/README.md#node), then render and serialize `renderer.domElement.outerHTML`. `TextureLoader` needs a browser, so set the image directly: `new Texture(Object.assign(document.createElement("img"), { src }))`. See [node-render.mjs](../../examples/node-render.mjs). +Set up a DOM with image loading as described in [c3r](../c3r/README.md#node), render, then export with `await renderer.toHTML()`. See [node-render.mjs](../../examples/node-render.mjs). See the [examples](https://k-adam.github.io/CSS3D-Renderer/). diff --git a/packages/c3r-three/package.json b/packages/c3r-three/package.json index 6693755..00f0996 100644 --- a/packages/c3r-three/package.json +++ b/packages/c3r-three/package.json @@ -1,6 +1,6 @@ { "name": "c3r-three", - "version": "0.2.1", + "version": "0.3.0", "description": "three.js CSS3DRenderer built on C3R, with geometry and texture support", "keywords": [ "three", @@ -34,7 +34,7 @@ "prepublishOnly": "npm run build" }, "dependencies": { - "c3r": "^0.2.1" + "c3r": "^0.3.0" }, "peerDependencies": { "@types/three": ">=0.160.0", diff --git a/packages/c3r-three/src/C3RRenderer.ts b/packages/c3r-three/src/C3RRenderer.ts index 91487e8..711ca0e 100644 --- a/packages/c3r-three/src/C3RRenderer.ts +++ b/packages/c3r-three/src/C3RRenderer.ts @@ -48,6 +48,8 @@ interface MaterialState { material: C3R.Material; map: Texture | null | undefined; version: number; + // The canvas map's data url, encoding it is slow + canvasSrc: string; } const DEFAULT_CENTER = { x: 0.5, y: 0.5 }; @@ -111,7 +113,12 @@ export class C3RRenderer { this.#syncCamera(container, camera); this.#syncObject(scene, container.root, container); - container.fitUnitScale(); + void container.bake(); + } + + async toHTML(): Promise { + await Promise.all([...this.#containers.values()].map((c) => c.bake())); + return C3R.styleHTML() + this.domElement.outerHTML; } #syncCamera(container: C3R.Container, camera: Camera): void { @@ -142,7 +149,7 @@ export class C3RRenderer { } } - container.camera.matrix = camera.matrixWorldInverse.elements; + container.camera.matrix = camera.matrixWorld.elements; } #syncObject( @@ -181,11 +188,7 @@ export class C3RRenderer { container: C3R.Container, ): number[] { // Billboard in world space - _matrix.fromArray(container.camera.matrix).transpose(); - - const e = _matrix.elements; - e[3] = e[7] = e[11] = 0; - e[15] = 1; + _matrix.extractRotation(_matrix.fromArray(container.camera.matrix)); object.matrixWorld.decompose(_position, _quaternion, _scale); _matrix.setPosition(_position).scale(_scale); @@ -200,7 +203,7 @@ export class C3RRenderer { node.center = [x, y]; } - return e; + return _matrix.elements; } #syncChildren( @@ -324,6 +327,7 @@ export class C3RRenderer { material: new C3R.Material(), map: undefined, version: -1, + canvasSrc: "", }; // Not this.#materials, the listener would keep the renderer alive const materials = this.#materials; @@ -343,24 +347,40 @@ export class C3RRenderer { const image: unknown = map?.image; let src: string | null = null; if (image instanceof HTMLImageElement) { - src = image.src; + // As written, a server-side DOM resolves it against its own origin + src = image.getAttribute("src") ?? image.src; } else if (image instanceof HTMLCanvasElement && map) { - const cached = state.map === map && state.version === map.version; - src = cached ? target.backgroundImageSrc : image.toDataURL(); - state.map = map; - state.version = map.version; + if (state.map !== map || state.version !== map.version) { + state.canvasSrc = image.toDataURL(); + state.map = map; + state.version = map.version; + } + src = state.canvasSrc; } - target.backgroundImageSrc = src; - if (material.color) { + // A map without a url, like a bitmap or one still loading, shows the color + let tint = 0xffffff; + if (src) { + target.background = src; + // getHex clamps, a tint takes no color beyond white + tint = material.color?.getHex() ?? tint; + } else if (material.color) { material.color.getRGB(_rgb, SRGBColorSpace); - target.backgroundColor = [_rgb.r, _rgb.g, _rgb.b, 1]; + target.background = [_rgb.r, _rgb.g, _rgb.b, 1]; } else { - target.backgroundColor = null; + target.background = null; } - target.opacity = material.transparent ? material.opacity : 1; - target.transparent = material.transparent; + // Unclamped in three.js + const opacity = + material.transparent && material.opacity < 1 + ? Math.max(0, material.opacity) + : 1; + const [r, g, b] = [tint >> 16, (tint >> 8) & 255, tint & 255]; + target.filter = [ + tint === 0xffffff ? null : C3R.Filter.tint([r / 255, g / 255, b / 255]), + opacity < 1 ? C3R.Filter.opacity(opacity) : null, + ].filter((f) => f !== null); target.doubleSided = material.side !== FrontSide; return map; @@ -414,11 +434,13 @@ function createNode(object: Object3D): C3R.Group { } if (object instanceof Sprite) { + // Painted like a polygon, so its map takes the color's tint const element = document.createElement("div"); + element.style.backgroundImage = + "var(--c3r-tween-layers,) var(--c3r-layers,) var(--c3r-background-image, none)"; element.style.backgroundBlendMode = "multiply"; - element.style.maskImage = "var(--c3r-background-image, none)"; - element.style.maskSize = "100% 100%"; - + element.style.mask = + "var(--c3r-tween-layered, var(--c3r-layered)) var(--c3r-alpha-mask, none) 0 0 / 100% 100%"; const node = new C3R.ElementObject(element); node.setSize(128, 128); node.scale = [1 / 128, 1 / 128]; diff --git a/packages/c3r-three/test/C3RRenderer.test.ts b/packages/c3r-three/test/C3RRenderer.test.ts index b6a2178..198f083 100644 --- a/packages/c3r-three/test/C3RRenderer.test.ts +++ b/packages/c3r-three/test/C3RRenderer.test.ts @@ -11,11 +11,19 @@ import { Scene, Sprite, SpriteMaterial, + Texture, Vector3, } from "three"; -import { cssText } from "c3r"; +import { cssText, styleHTML } from "c3r"; import { C3RRenderer, CSS3DObject } from "../src/C3RRenderer.js"; +const materialRule = (element: Element) => { + const name = /c3r-material-\d+/.exec(element.className)![0]; + return cssText() + .split("\n") + .find((r) => r.startsWith(`.${name} `))!; +}; + const setup = () => { const renderer = new C3RRenderer(); renderer.setSize(800, 600); @@ -30,7 +38,7 @@ const setup = () => { const cssMatrix = (element: Element) => { const match = /matrix3d\(([^)]*)\)/.exec( - (element as HTMLElement).style.transform, + (element as HTMLElement).style.getPropertyValue("--c3r-matrix"), ); return mat4.clone(match![1].split(",").map(Number) as unknown as mat4); }; @@ -167,19 +175,80 @@ it("applies the camera zoom", () => { expect(cssText()).toMatch(/--c3r-camera-fov: ?53\.13/); }); -it("ignores opacity and map alpha unless the material is transparent, as WebGL", () => { +it("tints a map by its color", () => { + const { renderer, scene, camera, root } = setup(); + const rule = () => + materialRule(root().querySelector("[class*=c3r-material-]")!); + + const image = document.createElement("img"); + image.src = "crate.png"; + const material = new MeshBasicMaterial({ map: new Texture(image) }); + scene.add(new Mesh(new BoxGeometry(), material)); + renderer.render(scene, camera); + expect(rule()).toMatch(/--c3r-background-color: ?transparent/); + expect(rule()).not.toContain("--c3r-layers"); + + material.color.set(0xff0000); + renderer.render(scene, camera); + expect(rule()).toMatch(/--c3r-layers: ?linear-gradient\(rgb\(100% 0% 0%\)/); + + // Beyond white in HDR, clamped like getHex rather than rejected + material.color.setRGB(2, 0, 0); + renderer.render(scene, camera); + expect(rule()).toMatch(/--c3r-layers: ?linear-gradient\(rgb\(100% 0% 0%\)/); + + material.transparent = true; + material.opacity = 0.4; + renderer.render(scene, camera); + expect(rule()).toMatch(/--c3r-filter: ?opacity\(0\.4\)/); + expect(rule()).toMatch(/--c3r-layers: ?linear-gradient/); + expect(rule()).toContain('url("crate.png")'); + material.dispose(); +}); + +it("keeps a canvas map's url across a swap", () => { + const { renderer, scene, camera, root } = setup(); + const rule = () => + materialRule(root().querySelector("[class*=c3r-material-]")!); + const canvas = document.createElement("canvas"); + canvas.toDataURL = () => "data:image/png;base64,AA"; + const map = new Texture(canvas); + const material = new MeshBasicMaterial({ map, color: 0xff0000 }); + scene.add(new Mesh(new BoxGeometry(), material)); + for (const next of [map, null, map]) { + material.map = next; + renderer.render(scene, camera); + } + expect(rule()).toContain("data:image/png;base64,AA"); + material.dispose(); +}); + +it("paints a white sprite without a map", () => { + const { renderer, scene, camera, root } = setup(); + const material = new SpriteMaterial(); + scene.add(new Sprite(material)); + renderer.render(scene, camera); + + const rule = materialRule(root().querySelector("[class*=c3r-material-]")!); + expect(rule).toMatch(/--c3r-background-color: ?rgba\(255, ?255, ?255/); + material.dispose(); +}); + +it("ignores opacity unless the material is transparent, as WebGL", () => { const { renderer, scene, camera } = setup(); const material = new MeshBasicMaterial({ opacity: 0.5 }); scene.add(new Mesh(new BoxGeometry(), material)); renderer.render(scene, camera); - expect(cssText()).not.toMatch(/--c3r-opacity:/); - expect(cssText()).not.toMatch(/--c3r-mask-image:/); + expect(cssText()).not.toMatch(/--c3r-filter:/); material.transparent = true; renderer.render(scene, camera); - expect(cssText()).toMatch(/--c3r-opacity: ?0\.5/); - expect(cssText()).toMatch(/--c3r-mask-image: ?var\(--c3r-background-image/); + expect(cssText()).toMatch(/--c3r-filter: ?opacity\(0\.5\)/); + + material.opacity = -0.1; + renderer.render(scene, camera); + expect(cssText()).toMatch(/--c3r-filter: ?opacity\(0\)/); material.dispose(); }); @@ -233,14 +302,9 @@ it("shows back faces unless the material is FrontSide", () => { scene.add(new Mesh(new BoxGeometry(), double)); renderer.render(scene, camera); - const [frontRule, doubleRule] = [...root().children].map((mesh) => { - const className = /c3r-material-\d+/.exec( - mesh.firstElementChild!.className, - )![0]; - return cssText() - .split("\n") - .find((r) => r.startsWith(`.${className} `))!; - }); + const [frontRule, doubleRule] = [...root().children].map((mesh) => + materialRule(mesh.firstElementChild!), + ); expect(frontRule).not.toContain("backface-visibility"); expect(doubleRule).toMatch(/backface-visibility: ?visible/); @@ -263,6 +327,28 @@ it("removes the scenes and camera rules on dispose", () => { expect(renderer.domElement.children).toHaveLength(1); }); +it("fills the window until setSize()", () => { + const { scene, camera } = setup(); + const renderer = new C3RRenderer(); + renderer.render(scene, camera); + const container = renderer.domElement.firstElementChild as HTMLElement; + const viewport = () => + container.style.getPropertyValue("--c3r-viewport-height"); + expect(renderer.domElement.style.height).toBe(""); + expect(viewport()).toBe(""); + + renderer.setSize(400, 300); + expect(viewport()).toBe("300px"); +}); + +it("exports the scenes as static html", async () => { + const { renderer, scene, camera } = setup(); + renderer.render(scene, camera); + const html = await renderer.toHTML(); + expect(html).toBe(styleHTML() + renderer.domElement.outerHTML); + expect(html).toContain("c3r-container"); +}); + it("scales the view by its densest polygon, flat faces stay small", () => { const { renderer, scene, camera } = setup(); const mesh = new Mesh( diff --git a/packages/c3r-three/test/earth.browser.test.ts b/packages/c3r-three/test/earth.browser.test.ts index 5a658e0..51cae53 100644 --- a/packages/c3r-three/test/earth.browser.test.ts +++ b/packages/c3r-three/test/earth.browser.test.ts @@ -11,6 +11,8 @@ import { PlaneGeometry, Scene, SphereGeometry, + Sprite, + SpriteMaterial, SRGBColorSpace, TextureLoader, WebGLRenderer, @@ -134,3 +136,22 @@ it("renders the earth example like WebGLRenderer", async () => { } expect(ratio).toBeLessThan(LIMIT); }); + +it("tints a sprite's map by its color", () => { + const canvas = canvas2d().canvas; + const scene = new Scene(); + scene.add( + new Sprite( + new SpriteMaterial({ map: new CanvasTexture(canvas), color: 0xff0000 }), + ), + ); + const c3r = new C3RRenderer(); + c3r.setSize(WIDTH, HEIGHT); + document.body.appendChild(c3r.domElement); + c3r.render(scene, new PerspectiveCamera()); + const sprite = c3r.domElement.querySelector(".c3r-element")!; + const { backgroundImage, maskImage } = getComputedStyle(sprite); + expect(backgroundImage).toMatch(/^linear-gradient\(rgb\(255, 0, 0\)/); + expect(maskImage).toMatch(/^url\("data:/); + c3r.domElement.remove(); +}); diff --git a/packages/c3r/README.md b/packages/c3r/README.md index 6821aae..07a5789 100644 --- a/packages/c3r/README.md +++ b/packages/c3r/README.md @@ -17,7 +17,7 @@ import { Container, Polygon } from "c3r"; Or with a script tag, using [GitHub Releases](https://github.com/K-Adam/CSS3D-Renderer/releases) or a CDN: ```html - + ``` It bundles gl-matrix and exposes a `C3R` global. @@ -29,39 +29,43 @@ TypeScript declarations are included. ```js import { Container, Group, Material } from "c3r"; import { mat4 } from "gl-matrix"; +import { cube } from "primitive-geometry"; const container = new Container(); // fills the window until setSize() document.body.append(container.domElement); -const cube = new Group(); -container.root.addChild(cube); -cube.addPolygon([ - { position: [-100, 100, 100], uv: [0, 1] }, - { position: [-100, -100, 100], uv: [0, 0] }, - { position: [100, -100, 100], uv: [1, 0] }, - { position: [100, 100, 100], uv: [1, 1] }, -]); +const box = new Group(); +container.root.addChild(box); +box.addMesh(cube({ sx: 200 })); -cube.material = new Material(); -cube.material.backgroundImageSrc = "crate.jpg"; +box.material = new Material(); +box.material.background = "crate.jpg"; -container.camera.matrix = mat4.fromTranslation(mat4.create(), [0, 0, -400]); +container.camera.matrix = mat4.fromTranslation(mat4.create(), [0, 0, 400]); ``` -| Class | What it is | -| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `Container` | The viewport: `domElement`, `root` group, `camera`, `setSize()`, `toHTML()` | -| `Group` | A transformed node: `matrix`, `addChild()`, `addPolygon()`, `addTriangles()` merges into polygons | -| `Polygon` | A flat, convex or concave textured polygon from CCW vertices, with `uvScale`, `uvOffset` | -| `ElementObject` | Any HTML element in the scene, centered on the origin, with `scale`, `center`, `rotation` | -| `Material` | `backgroundColor`, `backgroundImageSrc`, `opacity`, `transparent`, `doubleSided`, inherited by the object's descendants; on an `ElementObject`, its element only | -| `PerspectiveCamera`, `OrthographicCamera` | `matrix` (inverse world) and `fov`, or `left`, `right`, `top`, `bottom` | +| Class | What it is | +| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Container` | The viewport: `domElement`, `root` group, `camera`, `setSize()`, `unitScale`, `bake()` fits it, `toHTML()` (async) | +| `Group` | A transformed node: `matrix`, `tween` (one or an array), `addChild()`, `addPolygon()`, `addTriangles()` merges into polygons, `addMesh()` takes flat `positions`, `uvs`, `cells` | +| `Polygon` | A flat, convex or concave textured polygon from CCW vertices, with `uvScale`, `uvOffset`, `textureSize` (set it for a data url, otherwise `bake()` measures it) | +| `ElementObject` | Any HTML element in the scene, centered on the origin, with `scale`, `center`, `rotation` | +| `Tween` | A CSS animation of a group or camera: `keyframes` of `Transform` and `Filter` steps, `from`, `duration`, `delay`, `easing`, `loop`, `alternate`, `paused`, `hover` | +| `Transform`, `Filter` | Steps from factories: `translate` (scene units), `rotateX`, `rotateY`, `rotateZ`, `scale`; `opacity`, `brightness`, `contrast`, `saturate`, `grayscale`, `sepia`, `invert`, `hueRotate`, `tint` | +| `Material` | `background` (`[r, g, b, a]` in 0-1, or an image URL), `filter` (one or an array of `Filter` steps, before a tween's), `doubleSided`, inherited by the object's descendants; on an `ElementObject`, its element only | +| `PerspectiveCamera`, `OrthographicCamera` | `matrix` (pose), `viewMatrix` (read-only inverse), `tween`, and `fov`, or `left`, `right`, `top`, `bottom` | -A `transparent` material's image alpha also cuts out its color. Every property applies on assignment; there is no `update()` to call. A polygon is laid out from its vertices on construction, so put it in a group to move it. +An image's alpha shows through. A color and an image don't combine, tint either with `Filter.tint`; a color hides an inherited image and an image hides an inherited color. Every property applies on assignment; there is no `update()` to call. A polygon is laid out from its vertices on construction, so put it in a group to move it. -A `Material` or camera is a class rule in one shared stylesheet, so the objects using it share one style. The rule stays until `[Symbol.dispose]()` is called, or the owner leaves a `using` block; otherwise it is removed once the owner and its elements are garbage-collected. +A `Material`, `Tween` or camera is a class rule in one shared stylesheet, so the objects using it share one style. The rule stays until `[Symbol.dispose]()` is called, or the owner leaves a `using` block; otherwise it is removed once the owner and its elements are garbage-collected. -On a live page, call `container.fitUnitScale()` after building or heavily scaling the scene; `toHTML()` calls it for you. +A tween animates a group after its `matrix`, from rest or from the `from` steps, and a group's tweens apply in array order. Its keyframes play in sequence, `duration` seconds each unless written as `{ steps, duration }`, and `easing` applies to each; a keyframe is one step or an array of steps, and what it doesn't list holds. Transforms apply in the order they first appear, `from` first. Angles are radians and may exceed a half turn. `Filter` steps apply to the polygons and `ElementObject` elements, and a nested group's filters replace its parent's. With `hover`, a `loop` plays only while hovered; any other tween takes one keyframe and eases to it and back. Setting `paused` later pauses everything using the tween; a hover transition can't pause, so it stops responding to hover instead. It runs on the main thread and `bake()` ignores its scale. Use a negative `delay`, in seconds, to offset the phase. + +`Filter.tint(color)` multiplies each pixel by an sRGB color in 0-1, like a sprite tint. It applies to polygons only, before the other filters, and semi-transparent pixels take a slight tint halo. + +Aim a camera with `mat4.targetTo(mat4.create(), eye, target, [0, 1, 0])`. Its tween moves it after its `matrix` (`translate([0, 0, 400])` backs away) and can't `hover` or scale by zero or less; its filters apply to every group without its own, and `bake()` ignores it. + +On a live page, call `container.bake()` after building, heavily scaling or changing textures; `toHTML()` awaits it for you. It also sizes polygons to their image's texels, loading each url once. An orthographic camera needs `setSize()`: without it the container takes the window size at construction and does not follow resizes. @@ -69,7 +73,9 @@ The stylesheet is adopted by `document` only, so a container inside a shadow roo ## Node -C3R builds plain DOM elements, so it runs on a server-side DOM like [happy-dom](https://github.com/capricorn86/happy-dom). Stylesheets are not serialized, so export with `toHTML()`: the container markup after a ``; diff --git a/packages/c3r/src/dom/Container.ts b/packages/c3r/src/dom/Container.ts index 422cfef..0418cba 100644 --- a/packages/c3r/src/dom/Container.ts +++ b/packages/c3r/src/dom/Container.ts @@ -1,12 +1,14 @@ import { mat4, type ReadonlyMat4 } from "gl-matrix"; import type { Camera } from "../css/Camera.js"; +import { imageInfo, loadImage } from "../css/images.js"; import { PerspectiveCamera } from "../css/PerspectiveCamera.js"; -import { cssText } from "../css/styles.js"; +import { styleHTML } from "../css/styles.js"; +import { ElementObject } from "./ElementObject.js"; import { Group } from "./Group.js"; import type { Object3D } from "./Object3D.js"; -import { Polygon } from "./Polygon.js"; +import { measurePolygon, Polygon } from "./Polygon.js"; // Keeps a Camera, and its rules, alive while its element is const elementCameras = new WeakMap(); @@ -21,6 +23,7 @@ export class Container { #width = 0; #height = 0; #unitScale = 1; + #refit: Promise | null = null; constructor() { this.domElement.classList.add( @@ -81,12 +84,38 @@ export class Container { this.domElement.style.setProperty("--c3r-unit-scale", String(scale)); } - // The densest polygon at one view pixel per DOM pixel, a power of two scales - // exactly and holds still while objects move - fitUnitScale(): void { + bake(): Promise { + const loading = this.#fit(); + if (!loading.length) return Promise.resolve(); + // One refit at a time, c3r-three bakes every frame + this.#refit ??= Promise.all(loading) + .finally(() => (this.#refit = null)) + .then(() => this.bake()); + return this.#refit; + } + + // Fits the unit scale: the densest polygon at one view pixel per DOM pixel, a + // power of two scales exactly and holds still while objects move + #fit(): Promise[] { let density = 0; - const visit = (node: Object3D, parent: ReadonlyMat4) => { + const loading: Promise[] = []; + const visit = ( + node: Object3D, + parent: ReadonlyMat4, + image: string | null, + ) => { if (node.domElement.style.display === "none") return; + // Like the CSS variables: an image or a color replaces, null inherits + const background = node.material?.background; + if (background != null && !(node instanceof ElementObject)) + image = typeof background === "string" ? background : null; + if (node instanceof Polygon) { + const info = image === null ? null : imageInfo(image); + // Keeps the old size while a new image loads + if (info === undefined) loading.push(loadImage(image!)); + else measurePolygon(node, info?.size ?? null); + } + // Measuring refits the matrix const m = mat4.mul(mat4.create(), parent, node.matrix); if (node instanceof Polygon) { const scale = Math.min( @@ -95,17 +124,18 @@ export class Container { ); if (scale > 0) density = Math.max(density, 1 / scale); } else if (node instanceof Group) { - for (const child of node.children) visit(child, m); + for (const child of node.children) visit(child, m, image); } }; - visit(this.#root, this.#camera.matrix); + visit(this.#root, this.#camera.viewMatrix, null); const exponent = Math.ceil(Math.log2(density || 1)); this.unitScale = 2 ** Math.min(Math.max(exponent, -20), 20); + return loading; } - toHTML(): string { - this.fitUnitScale(); - return `${this.domElement.outerHTML}`; + async toHTML(): Promise { + await this.bake(); + return styleHTML() + this.domElement.outerHTML; } setSize(width: number, height: number): void { diff --git a/packages/c3r/src/dom/Group.ts b/packages/c3r/src/dom/Group.ts index 4dcb803..bee9bae 100644 --- a/packages/c3r/src/dom/Group.ts +++ b/packages/c3r/src/dom/Group.ts @@ -1,6 +1,11 @@ import type { ReadonlyMat4 } from "gl-matrix"; -import { MeshBuilder, type MeshFace } from "../math/MeshBuilder.js"; +import { setTweens, type Tween } from "../css/Tween.js"; +import { + MeshBuilder, + type MeshFace, + type TriangleList, +} from "../math/MeshBuilder.js"; import type { Vertex } from "../math/Vertex.js"; import { Object3D } from "./Object3D.js"; @@ -8,8 +13,18 @@ import { Polygon, type PolygonOptions } from "./Polygon.js"; const parents = new WeakMap(); +// Keeps the tweens, and their rules, alive while their element is +const elementTweens = new WeakMap(); + +export interface IndexedMesh { + positions: ArrayLike; + uvs: ArrayLike; + cells: ArrayLike; +} + export class Group extends Object3D { readonly #children: Object3D[] = []; + #tween: Tween | readonly Tween[] | null = null; constructor() { super(); @@ -25,6 +40,20 @@ export class Group extends Object3D { this.setMatrix(matrix); } + get tween(): Tween | readonly Tween[] | null { + return this.#tween; + } + + set tween(tween: Tween | readonly Tween[] | null) { + const { classList, style } = this.domElement; + const tweens = setTweens(style, tween); + for (const old of elementTweens.get(this.domElement) ?? []) + classList.remove(old.className); + for (const { className } of tweens) classList.add(className); + elementTweens.set(this.domElement, tweens); + this.#tween = Array.isArray(tween) ? tweens : tween; + } + get children(): readonly Object3D[] { return this.#children; } @@ -62,10 +91,26 @@ export class Group extends Object3D { } // Merges coplanar neighbours, e.g. two triangles into a quad - addTriangles( - triangles: readonly (readonly Vertex[])[], + addTriangles(triangles: TriangleList, options?: PolygonOptions): Polygon[] { + return this.addFaces(new MeshBuilder([triangles]).faces(0), options); + } + + addMesh( + { positions, uvs, cells }: IndexedMesh, options?: PolygonOptions, ): Polygon[] { - return this.addFaces(new MeshBuilder([triangles]).faces(0), options); + const vertex = (i: number): Vertex => ({ + position: [positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]], + uv: [uvs[i * 2], uvs[i * 2 + 1]], + }); + const triangles: Vertex[][] = []; + for (let i = 0; i + 2 < cells.length; i += 3) { + triangles.push([ + vertex(cells[i]), + vertex(cells[i + 1]), + vertex(cells[i + 2]), + ]); + } + return this.addTriangles(triangles, options); } } diff --git a/packages/c3r/src/dom/Object3D.ts b/packages/c3r/src/dom/Object3D.ts index f16ffd0..57888d1 100644 --- a/packages/c3r/src/dom/Object3D.ts +++ b/packages/c3r/src/dom/Object3D.ts @@ -22,7 +22,10 @@ export abstract class Object3D { protected setMatrix(matrix: ReadonlyMat4): void { if (mat4.exactEquals(matrix, this.#matrix)) return; mat4.copy(this.#matrix, matrix); - this.domElement.style.transform = `matrix3d(${[...matrix].join()})`; + this.domElement.style.setProperty( + "--c3r-matrix", + `matrix3d(${[...matrix].join()})`, + ); } get material(): Material | null { diff --git a/packages/c3r/src/dom/Polygon.ts b/packages/c3r/src/dom/Polygon.ts index affda91..ce32e1d 100644 --- a/packages/c3r/src/dom/Polygon.ts +++ b/packages/c3r/src/dom/Polygon.ts @@ -31,6 +31,9 @@ const newellNormal = (vertices: readonly Vertex[]): vec3 => { const MITER_LIMIT = 4; +// Keeps the miter divisions finite for parallel edges +const NEAR_ZERO = 1e-6; + interface Edge { offset: number; sides: [ReadonlyVec2 | null, ReadonlyVec2 | null]; @@ -46,7 +49,7 @@ const cap = ( if (side) { const u = vec2.normalize(vec2.create(), vec2.sub(vec2.create(), side, p)); const k = vec2.dot(u, n); - if (k > 1e-6) + if (k > NEAR_ZERO) return vec2.scaleAndAdd(u, p, u, Math.min(d / k, MITER_LIMIT * d)); } return vec2.scaleAndAdd(vec2.create(), p, n, d); @@ -74,8 +77,20 @@ const dilate = (points: ReadonlyVec2[], edges: Edge[]): vec2[] => { const d2 = edges[i].offset; if (!d1 && !d2) return [vec2.clone(p)]; + // cap() returns the plain offset for a side along the normal + const along = (side: ReadonlyVec2 | null, dir: ReadonlyVec2) => { + if (!side) return true; + const u = vec2.sub(vec2.create(), side, p); + return vec2.dot(vec2.normalize(u, u), dir) > 1 - NEAR_ZERO; + }; + const c = vec2.dot(n1, n2); + const square = + Math.abs(c) < NEAR_ZERO && + along(edges[prev].sides[1], n1) && + along(edges[i].sides[0], n2); + // A miter at a convex corner pokes out of the mesh where the corner is on its border - if (cross2(p, points[next], points[prev]) * sign > 0) { + if (!square && cross2(p, points[next], points[prev]) * sign > 0) { const c1 = d1 ? cap(p, n1, d1, edges[prev].sides[1]) : vec2.clone(p); const c2 = d2 ? cap(p, n2, d2, edges[i].sides[0]) : vec2.clone(p); if (vec2.equals(c1, c2)) return [c1]; @@ -84,8 +99,7 @@ const dilate = (points: ReadonlyVec2[], edges: Edge[]): vec2[] => { return cut ? [c1, vec2.clone(p), c2] : [c1, c2]; } - const c = vec2.dot(n1, n2); - const det = Math.max(1 - c * c, 1e-6); + const det = Math.max(1 - c * c, NEAR_ZERO); const m = vec2.scale(vec2.create(), n1, (d1 - d2 * c) / det); vec2.scaleAndAdd(m, m, n2, (d2 - d1 * c) / det); @@ -114,6 +128,15 @@ export interface PolygonOptions { edges?: readonly EdgeNeighbour[]; } +const sameSize = (a: ReadonlyVec2 | null, b: ReadonlyVec2 | null) => + a === b || (!!a && !!b && vec2.exactEquals(a, b)); + +// Friend access for Container.bake(), a public setter would be API +export let measurePolygon: ( + polygon: Polygon, + size: ReadonlyVec2 | null, +) => void; + export class Polygon extends Object3D { readonly vertices: readonly Vertex[]; // vertices in CCW readonly contentElement: HTMLElement; @@ -123,6 +146,7 @@ export class Polygon extends Object3D { #uvScale: ReadonlyVec2 = [1, 1]; #uvOffset: ReadonlyVec2 = [0, 0]; #textureSize: ReadonlyVec2 | null = null; + #measuredSize: ReadonlyVec2 | null = null; #pixelRatio = globalThis.devicePixelRatio || 1; #getDomSize: (size: number) => number; @@ -197,7 +221,7 @@ export class Polygon extends Object3D { set uvScale(scale: ReadonlyVec2) { if (vec2.exactEquals(scale, this.#uvScale)) return; this.#uvScale = vec2.clone(scale); - if (this.#textureSize) this.#fit(); + if (this.#size) this.#fit(); this.#updateContent(); } @@ -207,13 +231,28 @@ export class Polygon extends Object3D { } set textureSize(size: ReadonlyVec2 | null) { - const old = this.#textureSize; - if (size === old || (size && old && vec2.exactEquals(size, old))) return; + if (sameSize(size, this.#textureSize)) return; this.#textureSize = size && vec2.clone(size); this.#fit(); this.#updateContent(); } + get #size(): ReadonlyVec2 | null { + return this.#textureSize ?? this.#measuredSize; + } + + static { + measurePolygon = (polygon, size) => polygon.#measure(size); + } + + #measure(size: ReadonlyVec2 | null): void { + if (sameSize(size, this.#measuredSize)) return; + this.#measuredSize = size && vec2.clone(size); + if (this.#textureSize) return; + this.#fit(); + this.#updateContent(); + } + // The devicePixelRatio, update it after zoom or a screen change get pixelRatio(): number { return this.#pixelRatio; @@ -222,7 +261,7 @@ export class Polygon extends Object3D { set pixelRatio(ratio: number) { if (ratio === this.#pixelRatio) return; this.#pixelRatio = ratio; - if (!this.#textureSize) return; + if (!this.#size) return; this.#fit(); this.#updateContent(); } @@ -252,10 +291,16 @@ export class Polygon extends Object3D { this.#fitPolygon(tri); } + // A path on the element's box clips nothing + const box = + this.#clipPath.length === 4 && + this.#clipPath.every(([x, y]) => + [x, y].every((v) => Math.abs(v - Math.round(v)) < NEAR_ZERO), + ); const clip = this.#clipPath .map((p) => `${p[0] * 100}% ${p[1] * 100}%`) .join(); - this.#clipElement.style.clipPath = `polygon(${clip})`; + this.#clipElement.style.clipPath = box ? "" : `polygon(${clip})`; // As variables, the content follows a resize without updateContent @@ -319,10 +364,11 @@ export class Polygon extends Object3D { // Texels per world unit in the most stretched direction #texelDensity(tri: Triangle): number { - if (!this.#textureSize) return 0; + const size = this.#size; + if (!size) return 0; const M = uvTransform(this.vertices, tri.norm); if (!M) return 0; - const [sx, sy] = vec2.mul(vec2.create(), this.#uvScale, this.#textureSize); + const [sx, sy] = vec2.mul(vec2.create(), this.#uvScale, size); const L = mat2.fromValues(M[0] * sx, M[1] * sy, M[3] * sx, M[4] * sy); // Largest singular value, from σ1² + σ2² = frob² and σ1·σ2 = |det| const frob2 = mat2.frob(L) ** 2; diff --git a/packages/c3r/src/math/MeshBuilder.ts b/packages/c3r/src/math/MeshBuilder.ts index 3bd7830..23be68e 100644 --- a/packages/c3r/src/math/MeshBuilder.ts +++ b/packages/c3r/src/math/MeshBuilder.ts @@ -12,6 +12,8 @@ import type { EdgeNeighbour, NeighbourSide } from "./planar.js"; import { Triangle } from "./Triangle.js"; import type { Vertex } from "./Vertex.js"; +export type TriangleList = readonly (readonly Vertex[])[]; + export interface MeshFace { vertices: Vertex[]; edges: EdgeNeighbour[]; @@ -23,6 +25,15 @@ const SMOOTH_FOLD = 0.7; // Weld distance as a share of the mesh size, models round their coordinates const WELD = 1e-3; +// For a mesh with no extent +const MIN_WELD = 1e-9; + +const SLIVER = 1e-6; + +const COPLANAR = 1 - 1e-6; + +const UV_TOLERANCE = 1e-3; + // A separate polygon costs a layer and a seam, worth some rasterized area const MERGE_SLACK = 1.25; @@ -73,8 +84,8 @@ export class MeshBuilder { #borders = new Map(); constructor( - groups: readonly (readonly (readonly Vertex[])[])[], - { uvTolerance = 1e-3 } = {}, + groups: readonly TriangleList[], + { uvTolerance = UV_TOLERANCE } = {}, ) { const tris = this.#weld(groups); const ownersOf = () => @@ -102,13 +113,13 @@ export class MeshBuilder { .map((face) => this.#output(face)); } - #weld(groups: readonly (readonly (readonly Vertex[])[])[]): Tri[] { + #weld(groups: readonly TriangleList[]): Tri[] { const points = groups.flat(2).map((v) => v.position); const span = [0, 1, 2].map((k) => { const values = points.map((p) => p[k]); return Math.max(...values) - Math.min(...values); }); - this.#eps = WELD * Math.hypot(...span) || 1e-9; + this.#eps = WELD * Math.hypot(...span) || MIN_WELD; const weld = (p: ReadonlyVec3) => { const id = this.#positions.findIndex((q) => vec3.dist(p, q) <= this.#eps); @@ -121,7 +132,7 @@ export class MeshBuilder { const triangle = new Triangle(p, q, r); const ids = corners.map((v) => weld(v.position)); const longest = Math.max(...triangle.calculateEdgeLengths()); - const sliver = triangle.calculateArea() <= 1e-6 * longest ** 2; + const sliver = triangle.calculateArea() <= SLIVER * longest ** 2; if (sliver || new Set(ids).size < 3) return []; return [{ corners, ids, triangle, group }]; }), @@ -155,7 +166,7 @@ export class MeshBuilder { minRect(convexHull(ids.map((id) => plane(this.#positions[id])))).area; const fits = (t: Tri) => t.group === seed.group && - vec3.dot(t.triangle.norm, seed.triangle.norm) > 1 - 1e-6 && + vec3.dot(t.triangle.norm, seed.triangle.norm) > COPLANAR && t.corners.every((v) => vec2.dist(toUV(v.position), v.uv) <= uvTolerance); const face: Face = { seed, tris: [seed], ids: seed.ids }; diff --git a/packages/c3r/test/c3r.test.ts b/packages/c3r/test/c3r.test.ts index a3b3e1e..0368c44 100644 --- a/packages/c3r/test/c3r.test.ts +++ b/packages/c3r/test/c3r.test.ts @@ -1,15 +1,20 @@ import { describe, expect, it, vi } from "vitest"; import { mat4, vec3, vec4 } from "gl-matrix"; +import { cube, cylinder } from "primitive-geometry"; import { Container, cssText, ElementObject, + Filter, Group, Material, MeshBuilder, OrthographicCamera, PerspectiveCamera, Polygon, + styleHTML, + Transform, + Tween, type Vertex, } from "c3r"; @@ -215,15 +220,10 @@ describe("Group.addTriangles", () => { parseFloat(poly.domElement.style.getPropertyValue(p)), ); - // From examples/cube.html - const cube = () => { - // prettier-ignore - const positions = [100, 100, 100, 100, 100, -100, 100, -100, 100, 100, -100, -100, -100, 100, -100, -100, 100, 100, -100, -100, -100, -100, -100, 100, -100, 100, -100, 100, 100, -100, -100, 100, 100, 100, 100, 100, -100, -100, 100, 100, -100, 100, -100, -100, -100, 100, -100, -100, -100, 100, 100, 100, 100, 100, -100, -100, 100, 100, -100, 100, 100, 100, -100, -100, 100, -100, 100, -100, -100, -100, -100, -100]; - // prettier-ignore - const indices = [0, 2, 1, 2, 3, 1, 4, 6, 5, 6, 7, 5, 8, 10, 9, 10, 11, 9, 12, 14, 13, 14, 15, 13, 16, 18, 17, 18, 19, 17, 20, 22, 21, 22, 23, 21]; - // prettier-ignore - const uvs = [0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0]; + const box = cube({ sx: 200 }); + const triangles = () => { + const { positions, uvs, cells } = box; const at = (i: number) => vertex( positions[i * 3], @@ -233,30 +233,43 @@ describe("Group.addTriangles", () => { uvs[i * 2 + 1], ); - const triangles = []; - for (let i = 0; i < indices.length; i += 3) { - triangles.push([at(indices[i]), at(indices[i + 1]), at(indices[i + 2])]); - } - return triangles; + return Array.from({ length: cells.length / 3 }, (_, i) => [ + at(cells[i * 3]), + at(cells[i * 3 + 1]), + at(cells[i * 3 + 2]), + ]); }; it("merges the triangles of each cube face into a quad", () => { const group = new Group(); - group.addTriangles(cube()); + group.addTriangles(triangles()); expect(group.children).toHaveLength(6); for (const child of group.children) { const poly = child as Polygon; + const { style } = poly.contentElement.parentElement!; expect(poly.vertices).toHaveLength(4); for (const length of size(poly)) expect(length).toBeCloseTo(250.8); + expect(style.clipPath).toBe(""); poly.overlapFolds = false; expect(size(poly)).toEqual([250, 250]); + expect(style.clipPath).toBe(""); + } + }); + + it("builds the same quads from flat indexed arrays", () => { + const group = new Group(); + group.addMesh(box); + + expect(group.children).toHaveLength(6); + for (const child of group.children) { + expect((child as Polygon).vertices).toHaveLength(4); } }); it("merges the faces of a cube in any triangle order", () => { const group = new Group(); - const [a, b, ...rest] = cube(); + const [a, b, ...rest] = triangles(); group.addTriangles([a, ...rest.reverse(), b]); expect(group.children).toHaveLength(6); @@ -264,7 +277,7 @@ describe("Group.addTriangles", () => { it("overlaps concave folds unless told not to", () => { const group = new Group(); - group.addTriangles(cube().map((tri) => tri.reverse())); + group.addTriangles(triangles().map((tri) => tri.reverse())); for (const child of group.children) { const poly = child as Polygon; @@ -289,6 +302,20 @@ describe("Group.addTriangles", () => { } }); + it("does not clip the sides of a cylinder", () => { + const group = new Group(); + group.addMesh(cylinder({ nx: 16 })); + + const sides = group.children.filter( + (child) => (child as Polygon).vertices.length === 4, + ); + expect(sides).toHaveLength(16); + for (const side of sides) { + const clip = side.domElement.firstElementChild as HTMLElement; + expect(clip.style.clipPath).toBe(""); + } + }); + it("does not poke out of the mesh at a sharp corner on its border", () => { const group = new Group(); // The texture mapping breaks between the triangles, so they stay apart @@ -498,23 +525,25 @@ describe("ElementObject", () => { }); }); +// A class rule's declarations, or "" once it is gone +const ruleOf = (className: string) => + new RegExp(String.raw`\.${className}(, \.c3r-view)? \{[^}]*`).exec( + cssText(), + )?.[0] ?? ""; + describe("Material", () => { it("styles objects through a class rule, removed on dispose", () => { const group = new Group(); { using material = new Material(); - material.backgroundColor = [1, 0, 0, 1]; + material.background = [1, 0, 0, 1]; group.material = material; expect(group.domElement.classList).toContain(material.className); expect( group.domElement.style.getPropertyValue("--c3r-background-color"), ).toBe(""); - expect(cssText()).toMatch( - new RegExp( - `\\.${material.className} \\{[^}]*rgba\\(255, ?0, ?0, ?1\\)`, - ), - ); + expect(ruleOf(material.className)).toMatch(/rgba\(255, ?0, ?0, ?1\)/); using other = new Material(); group.material = other; @@ -525,15 +554,12 @@ describe("Material", () => { group.material = material; } - expect(cssText()).not.toContain(`.${group.material.className} `); + expect(ruleOf(group.material.className)).toBe(""); }); it("shows back faces when double-sided", () => { using material = new Material(); - const rule = () => - cssText() - .split("\n") - .find((r) => r.startsWith(`.${material.className} `)); + const rule = () => ruleOf(material.className); material.doubleSided = true; expect(rule()).toMatch(/backface-visibility: ?visible/); @@ -541,27 +567,456 @@ describe("Material", () => { material.doubleSided = false; expect(rule()).not.toContain("backface-visibility"); }); + + it("paints a color or an image, hiding the other from a parent", () => { + using material = new Material(); + const vars = () => + ["--c3r-background-color", "--c3r-background-image"].map( + (name) => + new RegExp(`${name}: ?([^;]+)`).exec( + ruleOf(material.className), + )?.[1] ?? null, + ); + + expect(vars()).toEqual([null, null]); + material.background = "leaf.png"; + expect(vars()).toEqual(["transparent", 'url("leaf.png")']); + material.background = [1, 0, 0, 1]; + expect(vars()[0]).toMatch(/rgba\(255, ?0, ?0, ?1\)/); + expect(vars()[1]).toBe("none"); + material.background = ""; + expect(vars()).toEqual([null, null]); + expect(material.background).toBe(null); + }); + + it("paints a color opaque and fades it, so a tint stays exact", () => { + using material = new Material(); + const rule = () => ruleOf(material.className); + material.background = [1, 0, 0, 0.5]; + expect(rule()).toMatch(/--c3r-background-opaque: ?rgb\(255, ?0, ?0\)/); + expect(rule()).toMatch(/--c3r-background-alpha: ?0\.5/); + expect(rule()).toMatch(/--c3r-alpha-mask: ?none/); + }); + + it("keeps an image's mask when it can't read the pixels", async () => { + using material = new Material(); + material.background = "leaf.png"; + const container = new Container(); + container.root.material = material; + container.root.addPolygon([ + vertex(0, 0, 0), + vertex(1, 0, 0), + vertex(0, 1, 0), + ]); + await container.bake(); + expect(ruleOf(material.className)).toContain( + '--c3r-alpha-mask: url("leaf.png")', + ); + }); + + it("filters with Filter steps only", () => { + using material = new Material(); + const rule = () => ruleOf(material.className); + + const filter = [Filter.grayscale(1), Filter.brightness(1.2)]; + material.filter = filter; + expect(material.filter).toEqual(filter); + expect(rule()).toContain("--c3r-filter: grayscale(1) brightness(1.2)"); + + material.filter = null; + expect(rule()).not.toContain("--c3r-filter"); + expect(() => (material.filter = Transform.scale(2) as never)).toThrow( + TypeError, + ); + }); + + it("tints by a multiplied color layer, replacing a parent's filters", () => { + using material = new Material(); + const rule = () => ruleOf(material.className); + material.filter = [Filter.tint([1, 0.8, 0.6]), Filter.opacity(0.5)]; + expect(rule()).toContain( + "--c3r-layers: linear-gradient(rgb(100% 80% 60%), rgb(100% 80% 60%)),", + ); + expect(rule()).toContain("--c3r-layered: alpha"); + expect(rule()).toContain("--c3r-filter: opacity(0.5)"); + // Only the tint changes, which must not be skipped + material.filter = [Filter.tint([0, 0, 1]), Filter.opacity(0.5)]; + expect(rule()).toContain("rgb(0% 0% 100%)"); + // A tint alone still hides the parent's filters + material.filter = Filter.tint([0, 0, 1]); + expect(rule()).toContain("--c3r-filter: initial"); + material.filter = Filter.sepia(1); + expect(rule()).toMatch(/--c3r-layers: initial;.*--c3r-layered: initial/); + material.filter = null; + expect(rule()).not.toMatch(/--c3r-(filter|layer)/); + + expect(() => Filter.tint([1, 0, 1.5])).toThrow(RangeError); + expect(() => Filter.tint([NaN, 0, 0])).toThrow(RangeError); + }); +}); + +describe("Tween", () => { + const turn = 2 * Math.PI; + + it("animates groups through class rules, removed on dispose", () => { + const group = new Group(); + group.matrix = mat4.fromTranslation(mat4.create(), [1, 2, 3]); + expect(group.domElement.style.getPropertyValue("--c3r-matrix")).toBe( + "matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,1,2,3,1)", + ); + + let className; + { + using spin = new Tween({ + keyframes: [ + [ + Transform.rotateX(turn), + Transform.rotateZ(turn), + Transform.translate([0, 20, 0]), + ], + ], + duration: 2, + loop: true, + }); + className = spin.className; + const track = `--${className}`; + group.tween = spin; + + expect(group.domElement.classList).toContain(className); + expect(cssText()).toContain( + `@property ${track}-translate3d-y { syntax: ""; inherits: false; initial-value: 0px; }`, + ); + expect(cssText()).toContain( + `100% { ${track}-rotateX: ${turn}rad; ${track}-rotateZ: ${turn}rad; ${track}-translate3d-x: 0px; ${track}-translate3d-y: 20px; ${track}-translate3d-z: 0px; }`, + ); + expect(ruleOf(spin.className)).toContain( + `${track}-animation: ${className} 2s linear 0s infinite normal both var(${track}-state)`, + ); + const { style } = group.domElement; + const t = (axis: string) => `var(${track}-translate3d-${axis}, 0px)`; + expect(style.getPropertyValue("--c3r-tween-transform")).toBe( + `rotateX(var(${track}-rotateX, 0rad)) rotateZ(var(${track}-rotateZ, 0rad)) translate3d(${t("x")},${t("y")},${t("z")})`, + ); + expect(style.animation).toBe(`var(${track}-animation, none)`); + + spin.paused = true; + expect(ruleOf(spin.className)).toMatch(`${track}-state: paused`); + + using other = new Tween({ keyframes: [Transform.scale(0.5)] }); + expect(cssText()).toContain(`--${other.className}-scale3d-z: 0.5`); + group.tween = other; + expect([...group.domElement.classList]).toEqual([ + "c3r-group", + other.className, + ]); + } + expect(cssText()).not.toContain(`${className} `); + }); + + it("composes several tweens on one group", () => { + const group = new Group(); + using spin = new Tween({ + keyframes: [Transform.rotateY(turn)], + loop: true, + }); + using fade = new Tween({ keyframes: [Filter.opacity(0.5)], hover: true }); + using tint = new Tween({ keyframes: [Filter.sepia(1)] }); + const tweens = [spin, fade, tint]; + group.tween = tweens; + expect(group.tween).toEqual(tweens); + + const { classList, style } = group.domElement; + expect([...classList]).toEqual([ + "c3r-group", + ...tweens.map((t) => t.className), + ]); + expect(style.getPropertyValue("--c3r-tween-transform")).toBe( + `rotateY(var(--${spin.className}-rotateY, 0rad))`, + ); + expect(style.animation).toBe( + `var(--${spin.className}-animation, none), var(--${tint.className}-animation, none)`, + ); + expect(style.transition).toBe( + `var(--${fade.className}-transition, --${fade.className} 0s)`, + ); + expect(style.getPropertyValue("--c3r-tween-filter")).toBe( + `opacity(var(--${fade.className}-opacity, 1)) sepia(var(--${tint.className}-sepia, 0))`, + ); + + tweens.pop(); + group.tween = tweens; + expect(classList).not.toContain(tint.className); + group.tween = [spin, spin]; + expect(style.animation).toBe(`var(--${spin.className}-animation, none)`); + + group.tween = null; + expect([...classList]).toEqual(["c3r-group"]); + expect(style.cssText).toBe(""); + }); + + it("plays keyframes in sequence, holding what they don't list", () => { + using sequence = new Tween({ + from: Filter.opacity(0.5), + keyframes: [ + Transform.translate([0, 50, 0]), + { steps: Transform.rotateY(turn), duration: 2 }, + [], + Filter.opacity(0), + ], + }); + const track = `--${sequence.className}`; + const stop = (offset: number, y: number, angle: number, opacity: number) => + `${offset}% { ${track}-opacity: ${opacity}; ${track}-translate3d-x: 0px; ${track}-translate3d-y: ${y}px; ${track}-translate3d-z: 0px; ${track}-rotateY: ${angle}rad; }`; + for (const block of [ + stop(0, 0, 0, 0.5), + stop(20, 50, 0, 0.5), + stop(60, 50, turn, 0.5), + stop(80, 50, turn, 0.5), + stop(100, 50, turn, 0), + ]) + expect(cssText()).toContain(block); + expect(ruleOf(sequence.className)).toContain(`${sequence.className} 5s`); + }); + + it("plays a loop on hover only, removed on dispose", () => { + let selector; + { + using pulse = new Tween({ + keyframes: [Transform.scale(2)], + loop: true, + hover: true, + }); + selector = `.${pulse.className}:not(:hover)`; + expect(ruleOf(pulse.className)).toMatch(/pointer-events: ?auto/); + expect(cssText()).toContain( + `${selector} { --${pulse.className}-state: paused; }`, + ); + } + expect(cssText()).not.toContain(selector); + }); + + it("transitions to its end while hovered, disabled when paused", () => { + let className; + { + using fade = new Tween({ + keyframes: [Filter.opacity(0.5)], + duration: 2, + hover: true, + }); + className = fade.className; + const opacity = `--${className}-opacity`; + expect(cssText()).not.toContain(`@keyframes ${className}`); + const rule = ruleOf(fade.className); + expect(rule).toContain( + `--${className}-transition: ${opacity} 2s linear 0s`, + ); + expect(rule).toMatch(/pointer-events: ?auto/); + expect(rule).not.toContain("animation"); + + const hovered = `.${className}:hover { ${opacity}: 0.5; }`; + expect(cssText()).toContain(hovered); + fade.paused = true; + expect(cssText()).not.toContain(hovered); + fade.paused = false; + expect(cssText()).toContain(hovered); + } + expect(cssText()).not.toContain(className); + }); + + it("moves a camera by the inverse, last tween first", () => { + using camera = new PerspectiveCamera(); + using move = new Tween({ + keyframes: [[Transform.translate([1, 2, 3]), Transform.rotateY(1)]], + }); + using grow = new Tween({ keyframes: [Transform.scale(2)] }); + camera.tween = [move, grow]; + const p = (tween: Tween) => `--${tween.className}`; + const t = (axis: string) => + `calc(-1 * var(${p(move)}-translate3d-${axis}, 0px))`; + const s = (axis: string) => `calc(1 / var(${p(grow)}-scale3d-${axis}, 1))`; + const rule = () => ruleOf(`${camera.className} > \\.c3r-view`); + expect(rule()).toContain( + `--c3r-tween-transform: scale3d(${s("x")},${s("y")},${s("z")}) rotateY(calc(-1 * var(${p(move)}-rotateY, 0rad))) translate3d(${t("x")},${t("y")},${t("z")})`, + ); + + using hover = new Tween({ keyframes: [Transform.scale(2)], hover: true }); + expect(() => (camera.tween = [move, hover])).toThrow(RangeError); + expect(cssText()).not.toContain(`.${hover.className}, .c3r-view`); + expect(camera.tween).toEqual([move, grow]); + for (const keyframes of [ + [Transform.scale(0)], + [Transform.scale([1, -1, 1])], + [Transform.scale(-1), Transform.scale(1)], + ]) { + using flat = new Tween({ keyframes }); + expect(() => (camera.tween = flat)).toThrow(RangeError); + } + expect(camera.tween).toEqual([move, grow]); + camera.tween = null; + expect(rule()).not.toContain("tween"); + }); + + it("rejects invalid steps and timing", () => { + expect(() => new Tween({ keyframes: [] })).toThrow(RangeError); + expect(() => new Tween({ keyframes: [[]] })).toThrow(RangeError); + expect(() => new Tween({ keyframes: [{} as Transform] })).toThrow( + TypeError, + ); + const from = Filter.opacity(0); + expect(() => new Tween({ from, keyframes: [[]] })).toThrow(RangeError); + expect(() => new Tween({ from: [from, from], keyframes: [from] })).toThrow( + "opacity twice in from", + ); + expect(() => Transform.translate([0, NaN, 0])).toThrow(RangeError); + expect(() => Transform.scale([1, 1] as never)).toThrow(RangeError); + expect(() => Transform.rotateY(Infinity)).toThrow(RangeError); + expect(() => Filter.brightness(-1)).toThrow(RangeError); + expect(() => Filter.sepia(NaN)).toThrow(RangeError); + expect( + () => new Tween({ keyframes: [[Filter.sepia(1), Filter.sepia(0.5)]] }), + ).toThrow(RangeError); + const scale = Transform.scale(2); + expect( + () => new Tween({ keyframes: [{ steps: scale, duration: 0 }] }), + ).toThrow(RangeError); + expect(() => new Tween({ keyframes: [scale, scale], hover: true })).toThrow( + RangeError, + ); + for (const timing of [ + { duration: NaN }, + { duration: -1 }, + { easing: "ease-in, ease-out" }, + { easing: " inherit " }, + { easing: "var(--ease)" }, + { easing: "ease; } body { display: none } .x {" }, + { easing: "steps(2" }, + { easing: "ease)(" }, + { delay: NaN }, + { alternate: true }, + ]) + expect(() => new Tween({ keyframes: [scale], ...timing })).toThrow( + RangeError, + ); + const easing = "cubic-bezier(0.2, 0, 0.4, 1)"; + new Tween({ keyframes: [scale], easing })[Symbol.dispose](); + }); + + it("chains filters in order, each through its own property", () => { + using look = new Tween({ + keyframes: [ + [Filter.brightness(2), Filter.hueRotate(turn), Filter.sepia(0.5)], + ], + }); + const p = `--${look.className}`; + expect(cssText()).toContain( + `0% { ${p}-brightness: 1; ${p}-hue-rotate: 0rad; ${p}-sepia: 0; }`, + ); + expect(cssText()).toContain( + `100% { ${p}-brightness: 2; ${p}-hue-rotate: ${turn}rad; ${p}-sepia: 0.5; }`, + ); + expect(cssText()).toContain( + `@property ${p}-hue-rotate { syntax: ""; inherits: false; initial-value: 0rad; }`, + ); + const group = new Group(); + group.tween = look; + expect(group.domElement.style.getPropertyValue("--c3r-tween-filter")).toBe( + `brightness(var(${p}-brightness, 1)) hue-rotate(var(${p}-hue-rotate, 0rad)) sepia(var(${p}-sepia, 0))`, + ); + }); + + it("tweens a tint as one color, with any easing or hover", () => { + using change = new Tween({ + keyframes: [Filter.tint([1, 0.8, 0.6])], + easing: "ease", + }); + const p = `--${change.className}-tint`; + expect(cssText()).toMatch( + new RegExp(`@property ${p} ?\{ ?syntax: ?""`), + ); + expect(cssText()).toContain(`${p}: rgb(100% 80% 60%)`); + const group = new Group(); + group.tween = change; + const { style } = group.domElement; + expect(style.getPropertyValue("--c3r-tween-layers")).toBe( + `linear-gradient(var(${p}, white), var(${p}, white)),`, + ); + expect(style.getPropertyValue("--c3r-tween-filter")).toBe("initial"); + group.tween = null; + expect(style.getPropertyValue("--c3r-tween-layers")).toBe(""); + expect(() => + new Tween({ keyframes: [Filter.tint([0, 0, 1])], hover: true })[ + Symbol.dispose + ](), + ).not.toThrow(); + }); }); describe("server-side rendering", () => { it("exports the stylesheet for static html", () => { expect(cssText()).toContain(".c3r-polygon"); + expect(cssText()).toContain("@property --c3r-matrix"); }); - it("exports the scene as static html", () => { + it("exports the scene as static html", async () => { const container = new Container(); const group = new Group(); group.matrix = mat4.fromScaling(mat4.create(), [0.01, 0.01, 0.01]); group.addPolygon([vertex(0, 0, 0), vertex(1, 0, 0), vertex(0, 1, 0)]); container.root.addChild(group); - const html = container.toHTML(); + const html = await container.toHTML(); const { outerHTML } = container.domElement; - expect(html).toBe(`${outerHTML}`); + expect(html).toBe(styleHTML() + outerHTML); expect(outerHTML).toContain("--c3r-unit-scale"); }); + it("keeps every value inside the exported style element", async () => { + const container = new Container(); + const group = new Group(); + group.material = new Material(); + group.material.background = "a"; + container.root.addChild(group); + + expect(await container.toHTML()).not.toContain("