├── .gitignore ├── .idea ├── .gitignore ├── misc.xml ├── modules.xml ├── vcs.xml └── zdogXperiments.iml ├── LICENSE ├── README.md ├── assets ├── cube.obj.txt ├── diamond.obj.txt ├── dodecahedron.obj.txt ├── elk.json ├── fox.json ├── gem.obj.txt ├── hand.obj.txt ├── hand2.obj.txt ├── head.obj.txt ├── horse.json ├── humanoid.obj.txt ├── icosahedron.obj.txt ├── icosphere.obj.txt ├── lamp.obj.txt ├── magnolia.obj.txt ├── ninja2_grey_head.jpg ├── shuttle.obj.txt ├── skyscraper.obj.txt ├── teapot.obj.txt ├── tetrahedron.obj.txt ├── toroid.obj.txt ├── torusknot.obj.txt ├── twistedtorus.obj.txt ├── wolf.json └── worldmap-small_bw9sas.png ├── complements └── xwing_converter.js ├── css ├── main.css └── w3.css ├── index.html ├── js ├── bezier.js ├── bezier.min.js ├── chroma.js ├── chroma.min.js ├── csg.js ├── csg_library.js ├── csg_old.js ├── csg_tools.js ├── dat.gui.min.js ├── delaunay.js ├── leap-0.6.4.js ├── leap-0.6.4.min.js ├── leap-1.0.0.js ├── leap-1.0.0.min.js ├── math.js ├── mathFx.js ├── nbody.js ├── parametricalSurfaces.js ├── segment.js ├── segment3D.js ├── shapeCalabiYau.js ├── shapes3dToolbox.js ├── simplexnoise.js ├── slider.js ├── starwarsArtefacts.js ├── tgraph.js ├── utils.js ├── w3color.js ├── zdog.dist.js └── zdog.dist.min.js ├── jsdatas ├── zdog_tunnel_data0.js ├── zdog_tunnel_data1.js ├── zdog_tunnel_data1b.js ├── zdog_tunnel_data2.js ├── zdog_tunnel_data2b.js ├── zdog_tunnel_data3.js └── zdog_tunnel_data3b.js ├── jstools ├── addslider.js ├── colorPicker.js └── quaternion.js ├── screenshots ├── default.png ├── scr0001.PNG ├── scr0002.PNG ├── scr0003.PNG ├── scr0004.PNG ├── scr0005.PNG ├── scr0006.PNG ├── scr0007.PNG ├── scr0008.PNG ├── scr0009.PNG ├── scr0010.PNG ├── scr0011.PNG ├── scr0012.PNG ├── scr0013.PNG ├── scr0014.PNG ├── scr0015.PNG ├── scr0016.PNG ├── scr0017.PNG ├── scr0018.PNG ├── scr0019.PNG ├── scr0020.PNG ├── scr0021.PNG ├── scr0022.PNG ├── scr0023.PNG ├── scr0024.PNG ├── scr0025.PNG ├── scr0026.PNG ├── scr0027.PNG ├── scr0028.PNG ├── scr0029.PNG ├── scr0030.PNG ├── scr0031.PNG ├── scr0032.PNG └── scr0033.PNG └── sources ├── zdog_8cubes.html ├── zdog_8cubes.js ├── zdog_8cubes_click.html ├── zdog_8cubes_click.js ├── zdog_animals.html ├── zdog_animals.js ├── zdog_boxman.html ├── zdog_boxman.js ├── zdog_calabiyau.html ├── zdog_calabiyau.js ├── zdog_csg1.html ├── zdog_csg1.js ├── zdog_csg2.html ├── zdog_csg2.js ├── zdog_csg3.html ├── zdog_csg3.js ├── zdog_cube.html ├── zdog_cube.js ├── zdog_cuboid_delaunay.html ├── zdog_cuboid_delaunay.js ├── zdog_flake.html ├── zdog_flake.js ├── zdog_leap_v1.html ├── zdog_leap_v1.js ├── zdog_leap_v2.html ├── zdog_leap_v2.js ├── zdog_magnetcubes.html ├── zdog_magnetcubes.js ├── zdog_obj.html ├── zdog_obj.js ├── zdog_obj_v2.html ├── zdog_obj_v2.js ├── zdog_obj_v3.html ├── zdog_obj_v3.js ├── zdog_segment1.html ├── zdog_segment1.js ├── zdog_segment2.html ├── zdog_segment2.js ├── zdog_segment3.html ├── zdog_segment3.js ├── zdog_segment4.html ├── zdog_segment4.js ├── zdog_segment5.html ├── zdog_segment5.js ├── zdog_segment_bezier.html ├── zdog_segment_bezier.js ├── zdog_shapegenerator.html ├── zdog_shapegenerator.js ├── zdog_shapes.html ├── zdog_shapes.js ├── zdog_shapes_xcav.html ├── zdog_shapes_xcav.js ├── zdog_solarsystem.html ├── zdog_solarsystem.js ├── zdog_sponge.html ├── zdog_sponge.js ├── zdog_surf_param.html ├── zdog_surf_param.js ├── zdog_surf_param2.html ├── zdog_surf_param2.js ├── zdog_surf_param3.html ├── zdog_surf_param3.js ├── zdog_swingcubes.html ├── zdog_swingcubes.js ├── zdog_tunnel.html ├── zdog_tunnel.js ├── zdog_xshapes.html ├── zdog_xshapes.js ├── zdog_xshapes2.html ├── zdog_xshapes2.js ├── zdog_xwing.html └── zdog_xwing.js /.gitignore: -------------------------------------------------------------------------------- 1 | .directory 2 | draft 3 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/zdogXperiments.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Gregory Jarrige 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zdogXperiments 2 | experiments with zdog 3 | 4 | I discovered Zdog in the beginning of june 2019 and I liked it immediately. 5 | It's a really cool project, so I decided to make some experiments with it. 6 | This github repository is the result of those experiments. 7 | It's just the beginning, I have a lot of other ideas to test ;) 8 | 9 | Note that for all shapes, it's possible to zoom with arrow keys, to reset the zoom with the escape key, and to "click & drag" to rotate the shape. 10 | 11 | To test the algorithms, just download the zip of this repository, unzip it, double-click on "index.html", and follow the links. 12 | 13 | Follow this link to watch the live demo of this project : 14 | 15 | http://ledefrichoir.com/labo/zdogXperiments/ 16 | 17 | The content of the project : 18 | 19 | - 3D Cube : cube generated programmatically, with two types of render : "wireframe" and "paint" (for the "paint" mode, colors are generated by Chroma.js) 20 | 21 | - 3D shapes : shapes generated programmatically => cube, pyramid, icosahedron, cone, 2 spheres, 2 cuboïds, 2 cylinders, tube, diamond and double diamond (both generated with tube shape), calices (2 variants generated with tube shape), strange fruits (2 variants) 22 | 23 | - Load wavefront obj files V1 (*) : cube, dodecahedron, icosahedron, and a lot of other objects, found on this site : http://people.sc.fsu.edu/~jburkardt/data/obj/obj.html 24 | 25 | - Load wavefront obj files V2 (*) : V1 with asynchronuous loading of the 3D objects (better practice using the Fetch API) 26 | 27 | - Load wavefront obj files V3 (*) : V2 with a "paint" mode (the same used for "3D Cube" and "3D shapes") 28 | 29 | - Menger Sponge & Flake generators : adaptation of algorithms of Frido Verweij (https://library.fridoverweij.com/codelab/menger_fractals/) 30 | 31 | - Tunnel 3D : shape generated using an algorithm of Niklas Knaack, found on this pen : https://codepen.io/NiklasKnaack/pen/WyWqja 32 | 33 | - 8 cubes linked 34 | 35 | - 8 cubes linked and clickable : how to set a list of clickables shapes with Zdog and a ghost canvas (*2) 36 | 37 | - Parametrical surfaces : (big update the 2020-01-01) 38 | Ellipsoid, Sphere, Torus, Hyperboloid, Cone, Pseudo-sphere, Helicoid, Katenoid, Möbius ribbon, Klein bottle, 39 | Limpet torus, triaxial hexatorus, saddle torus, triaxial tritorus, bow curve, and a lot of new 40 | weird creatures 41 | 42 | - Parametrical surfaces customizable (NEW) 43 | 44 | - Magnetic cubes 45 | 46 | - Solar system (n-body algorithm) (=> experimental, for fun, not finalized) 47 | 48 | - XWing 49 | 50 | - Complex 3D object created with 3 primitives (*3) 51 | 52 | - 3D animals running (*4) 53 | 54 | - 3D shape generator (*5) 55 | 56 | - Boxman, a robot walking (*6) 57 | 58 | - Grid of cubes swinging 59 | 60 | - Calabi-Yau manifold (*7) 61 | 62 | - Segments for puppets - 5 examples (*8) 63 | 64 | - Leap Motion with Zdog - draw hands (*9) 65 | 66 | - Cuboid generated with Delaunay Triangulation (*10) 67 | 68 | - 3D Objects excavated (*11) 69 | 70 | - Constructive Solid Geometry with csg.js (new) (*12) 71 | 72 | 73 | ------------------- 74 | 75 | (*) Note that the import OBJ algorithm is largely inspired by a similar algorithm found on Phoria.js, of Kevin Roast : http://www.kevs3d.co.uk/dev/phoria/ 76 | 77 | (*2) see improved version by José (thank's José): 78 | https://codepen.io/ncodefun/pen/aggZKP 79 | 80 | (*3) recreation with zdog of : https://library.fridoverweij.com/codelab/3d_wireframe/ 81 | 82 | (*4) recreation with zdog of : https://codepen.io/hankuro/pen/QMVLJZ 83 | 84 | (*5) inspired by an example excerpt of the book of Nikolaus Gradwohl : "Processing 2: Creative Programming Hotshot", Packt Publishing 2013 85 | 86 | (*6) inspired by a pen of Hankuro : https://codepen.io/hankuro/pen/LrbVrx 87 | 88 | (*7) inspired by this tutorial : https://observablehq.com/@sw1227/calabi-yau-manifold-3d 89 | 90 | (*8) inspired by the book : "Foundation HTML5 Animation with JavaScript" of Billy Lamberta and Keith Peters (ed. Apress), http://lamberta.github.io/html5-animation/ 91 | 92 | (*9) you'll find different links (docs and tutorials) in the beginning of the JS code 93 | 94 | (*10) Source of the Delaunay algorithm : https://github.com/ironwallaby/delaunay.git 95 | 96 | (*11) Adaptation for Javascript of an algorithm excerpt from the book : 97 | "Graphisme 3D en Turbo Pascal", Gérald Grandpierre and Richard Cotté, édiTests 1988 98 | 99 | (*12) Link to the project csg.js : http://evanw.github.io/csg.js/ 100 | 101 | ------------------ 102 | 103 | A lot of examples of this project are visible on my pens : 104 | https://codepen.io/gregja/ 105 | 106 | Link to this github repository : 107 | https://github.com/gregja/zdogXperiments 108 | 109 | Link to the official site of Zdog : 110 | https://zzz.dog/ 111 | -------------------------------------------------------------------------------- /assets/cube.obj.txt: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib cube.mtl 4 | o Cube 5 | v -1.000000 -1.000000 1.000000 6 | v -1.000000 -1.000000 -1.000000 7 | v 1.000000 -1.000000 -1.000000 8 | v 1.000000 -1.000000 1.000000 9 | v -1.000000 1.000000 1.000000 10 | v -1.000000 1.000000 -1.000000 11 | v 1.000000 1.000000 -1.000000 12 | v 1.000000 1.000000 1.000000 13 | usemtl None 14 | s off 15 | f 6 2 1 16 | f 7 3 2 17 | f 8 4 3 18 | f 5 1 4 19 | f 2 3 4 20 | f 7 6 5 21 | f 5 6 1 22 | f 6 7 2 23 | f 7 8 3 24 | f 8 5 4 25 | f 1 2 4 26 | f 8 7 5 27 | -------------------------------------------------------------------------------- /assets/diamond.obj.txt: -------------------------------------------------------------------------------- 1 | # diamond.obj 2 | 3 | g Object001 4 | 5 | v 0.000000E+00 0.000000E+00 78.0000 6 | v 45.0000 45.0000 0.000000E+00 7 | v 45.0000 -45.0000 0.000000E+00 8 | v -45.0000 -45.0000 0.000000E+00 9 | v -45.0000 45.0000 0.000000E+00 10 | v 0.000000E+00 0.000000E+00 -78.0000 11 | 12 | f 1 2 3 13 | f 1 3 4 14 | f 1 4 5 15 | f 1 5 2 16 | f 6 5 4 17 | f 6 4 3 18 | f 6 3 2 19 | f 6 2 1 20 | f 6 1 5 21 | -------------------------------------------------------------------------------- /assets/dodecahedron.obj.txt: -------------------------------------------------------------------------------- 1 | # OBJ file created by ply_to_obj.c 2 | # 3 | g Object001 4 | 5 | v -0.57735 -0.57735 0.57735 6 | v 0.934172 0.356822 0 7 | v 0.934172 -0.356822 0 8 | v -0.934172 0.356822 0 9 | v -0.934172 -0.356822 0 10 | v 0 0.934172 0.356822 11 | v 0 0.934172 -0.356822 12 | v 0.356822 0 -0.934172 13 | v -0.356822 0 -0.934172 14 | v 0 -0.934172 -0.356822 15 | v 0 -0.934172 0.356822 16 | v 0.356822 0 0.934172 17 | v -0.356822 0 0.934172 18 | v 0.57735 0.57735 -0.57735 19 | v 0.57735 0.57735 0.57735 20 | v -0.57735 0.57735 -0.57735 21 | v -0.57735 0.57735 0.57735 22 | v 0.57735 -0.57735 -0.57735 23 | v 0.57735 -0.57735 0.57735 24 | v -0.57735 -0.57735 -0.57735 25 | 26 | f 19 3 2 27 | f 12 19 2 28 | f 15 12 2 29 | f 8 14 2 30 | f 18 8 2 31 | f 3 18 2 32 | f 20 5 4 33 | f 9 20 4 34 | f 16 9 4 35 | f 13 17 4 36 | f 1 13 4 37 | f 5 1 4 38 | f 7 16 4 39 | f 6 7 4 40 | f 17 6 4 41 | f 6 15 2 42 | f 7 6 2 43 | f 14 7 2 44 | f 10 18 3 45 | f 11 10 3 46 | f 19 11 3 47 | f 11 1 5 48 | f 10 11 5 49 | f 20 10 5 50 | f 20 9 8 51 | f 10 20 8 52 | f 18 10 8 53 | f 9 16 7 54 | f 8 9 7 55 | f 14 8 7 56 | f 12 15 6 57 | f 13 12 6 58 | f 17 13 6 59 | f 13 1 11 60 | f 12 13 11 61 | f 19 12 11 62 | -------------------------------------------------------------------------------- /assets/gem.obj.txt: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib gem.mtl 4 | o Gem 5 | v 0.000000 -0.800000 0.000000 6 | v 0.000000 0.350000 0.000000 7 | v 0.000000 -0.400000 -0.541196 8 | v 0.382683 0.000000 -0.923880 9 | v 0.000000 0.175000 -0.865914 10 | v 0.229610 0.350000 -0.554328 11 | v 0.382683 -0.400000 -0.382683 12 | v 0.923880 0.000000 -0.382683 13 | v 0.612293 0.175000 -0.612293 14 | v 0.554328 0.350000 -0.229610 15 | v 0.541196 -0.400000 -0.000000 16 | v 0.923880 0.000000 0.382683 17 | v 0.865914 0.175000 -0.000000 18 | v 0.554328 0.350000 0.229610 19 | v 0.382683 -0.400000 0.382683 20 | v 0.382683 0.000000 0.923880 21 | v 0.612293 0.175000 0.612293 22 | v 0.229610 0.350000 0.554328 23 | v 0.000000 -0.400000 0.541196 24 | v -0.382683 0.000000 0.923880 25 | v 0.000000 0.175000 0.865914 26 | v -0.229610 0.350000 0.554328 27 | v -0.382683 -0.400000 0.382683 28 | v -0.923880 0.000000 0.382683 29 | v -0.612293 0.175000 0.612293 30 | v -0.554328 0.350000 0.229610 31 | v -0.541196 -0.400000 0.000000 32 | v -0.923880 0.000000 -0.382683 33 | v -0.865914 0.175000 0.000000 34 | v -0.554328 0.350000 -0.229610 35 | v -0.382683 -0.400000 -0.382683 36 | v -0.382683 0.000000 -0.923880 37 | v -0.612293 0.175000 -0.612293 38 | v -0.229610 0.350000 -0.554328 39 | usemtl None 40 | s off 41 | f 1 3 4 42 | f 7 4 8 43 | f 8 4 9 44 | f 9 4 5 45 | f 9 6 10 46 | f 1 7 8 47 | f 11 8 12 48 | f 12 8 13 49 | f 13 8 9 50 | f 13 10 14 51 | f 1 11 12 52 | f 15 12 16 53 | f 16 12 17 54 | f 17 12 13 55 | f 17 14 18 56 | f 1 15 16 57 | f 19 16 20 58 | f 20 16 21 59 | f 21 16 17 60 | f 21 18 22 61 | f 1 19 20 62 | f 23 20 24 63 | f 24 20 25 64 | f 25 20 21 65 | f 25 22 26 66 | f 1 23 24 67 | f 27 24 28 68 | f 28 24 29 69 | f 29 24 25 70 | f 29 26 30 71 | f 1 27 28 72 | f 31 28 32 73 | f 32 28 33 74 | f 33 28 29 75 | f 33 30 34 76 | f 1 31 32 77 | f 3 32 4 78 | f 4 32 5 79 | f 5 32 33 80 | f 5 34 6 81 | f 6 2 34 82 | f 2 6 10 83 | f 2 10 14 84 | f 2 14 18 85 | f 2 18 22 86 | f 2 22 26 87 | f 2 26 30 88 | f 2 30 34 89 | f 7 1 4 90 | f 6 9 5 91 | f 11 1 8 92 | f 10 13 9 93 | f 15 1 12 94 | f 14 17 13 95 | f 19 1 16 96 | f 18 21 17 97 | f 23 1 20 98 | f 22 25 21 99 | f 27 1 24 100 | f 26 29 25 101 | f 31 1 28 102 | f 30 33 29 103 | f 3 1 32 104 | f 34 5 33 105 | -------------------------------------------------------------------------------- /assets/humanoid.obj.txt: -------------------------------------------------------------------------------- 1 | # humanoid_quad.obj 2 | # created by TEC_TO_OBJ.F90. 3 | 4 | g Group001 5 | 6 | v 3.25000 -2.48000 14.0000 1.00000 7 | v 3.25000 -2.48000 9.01000 1.00000 8 | v 3.25000 2.48000 9.01000 1.00000 9 | v 3.25000 2.48000 14.0000 1.00000 10 | v 0.773000 -2.48000 14.0000 1.00000 11 | v 0.773000 -2.48000 9.01000 1.00000 12 | v 0.773000 2.48000 14.0000 1.00000 13 | v 0.773000 2.48000 9.01000 1.00000 14 | v 3.47000 -1.29000 17.4000 1.00000 15 | v 3.47000 -1.29000 15.0000 1.00000 16 | v 3.47000 1.19000 15.0000 1.00000 17 | v 3.47000 1.19000 17.4000 1.00000 18 | v 0.601000 -1.29000 17.4000 1.00000 19 | v 0.601000 -1.29000 15.0000 1.00000 20 | v 0.601000 1.19000 17.4000 1.00000 21 | v 0.601000 1.19000 15.0000 1.00000 22 | v 3.15000 -2.47000 8.01000 1.00000 23 | v 3.15000 -2.47000 3.05000 1.00000 24 | v 3.15000 -0.486000 3.05000 1.00000 25 | v 3.15000 -0.486000 8.01000 1.00000 26 | v 0.892000 -2.47000 8.01000 1.00000 27 | v 0.892000 -2.47000 3.05000 1.00000 28 | v 0.892000 -0.486000 8.01000 1.00000 29 | v 0.892000 -0.486000 3.05000 1.00000 30 | v 3.23000 -3.96000 14.0000 1.00000 31 | v 3.23000 -3.96000 9.01000 1.00000 32 | v 3.23000 -2.48000 9.01000 1.00000 33 | v 3.23000 -2.48000 14.0000 1.00000 34 | v 0.747000 -3.96000 14.0000 1.00000 35 | v 0.747000 -3.96000 9.01000 1.00000 36 | v 0.747000 -2.48000 14.0000 1.00000 37 | v 0.747000 -2.48000 9.01000 1.00000 38 | v 3.27000 2.46000 14.0000 1.00000 39 | v 3.27000 2.46000 9.01000 1.00000 40 | v 3.27000 3.95000 9.01000 1.00000 41 | v 3.27000 3.95000 14.0000 1.00000 42 | v 0.795000 2.46000 14.0000 1.00000 43 | v 0.795000 2.46000 9.01000 1.00000 44 | v 0.795000 3.95000 14.0000 1.00000 45 | v 0.795000 3.95000 9.01000 1.00000 46 | v 2.49000 -0.498000 15.0000 1.00000 47 | v 2.49000 -0.498000 14.0000 1.00000 48 | v 2.49000 0.493000 14.0000 1.00000 49 | v 2.49000 0.493000 15.0000 1.00000 50 | v 1.50000 -0.498000 15.0000 1.00000 51 | v 1.50000 -0.498000 14.0000 1.00000 52 | v 1.50000 0.493000 15.0000 1.00000 53 | v 1.50000 0.493000 14.0000 1.00000 54 | v 3.25000 -2.50000 9.01000 1.00000 55 | v 3.25000 -2.50000 8.01000 1.00000 56 | v 3.25000 2.45000 8.01000 1.00000 57 | v 3.25000 2.45000 9.01000 1.00000 58 | v 0.771000 -2.50000 9.01000 1.00000 59 | v 0.771000 -2.50000 8.01000 1.00000 60 | v 0.771000 2.45000 9.01000 1.00000 61 | v 0.771000 2.45000 8.01000 1.00000 62 | v 3.27000 0.465000 8.01000 1.00000 63 | v 3.27000 0.465000 3.05000 1.00000 64 | v 3.27000 2.45000 3.05000 1.00000 65 | v 3.27000 2.45000 8.01000 1.00000 66 | v 0.795000 0.465000 8.01000 1.00000 67 | v 0.795000 0.465000 3.05000 1.00000 68 | v 0.795000 2.45000 8.01000 1.00000 69 | v 0.795000 2.45000 3.05000 1.00000 70 | 71 | f 1 2 3 4 72 | f 5 6 2 1 73 | f 7 8 6 5 74 | f 4 3 8 7 75 | f 7 5 1 4 76 | f 2 6 8 3 77 | f 9 10 11 12 78 | f 13 14 10 9 79 | f 15 16 14 13 80 | f 12 11 16 15 81 | f 15 13 9 12 82 | f 10 14 16 11 83 | f 17 18 19 20 84 | f 21 22 18 17 85 | f 23 24 22 21 86 | f 20 19 24 23 87 | f 23 21 17 20 88 | f 18 22 24 19 89 | f 25 26 27 28 90 | f 29 30 26 25 91 | f 31 32 30 29 92 | f 28 27 32 31 93 | f 31 29 25 28 94 | f 26 30 32 27 95 | f 33 34 35 36 96 | f 37 38 34 33 97 | f 39 40 38 37 98 | f 36 35 40 39 99 | f 39 37 33 36 100 | f 34 38 40 35 101 | f 41 42 43 44 102 | f 45 46 42 41 103 | f 47 48 46 45 104 | f 44 43 48 47 105 | f 47 45 41 44 106 | f 42 46 48 43 107 | f 49 50 51 52 108 | f 53 54 50 49 109 | f 55 56 54 53 110 | f 52 51 56 55 111 | f 55 53 49 52 112 | f 50 54 56 51 113 | f 57 58 59 60 114 | f 61 62 58 57 115 | f 63 64 62 61 116 | f 60 59 64 63 117 | f 63 61 57 60 118 | f 58 62 64 59 119 | -------------------------------------------------------------------------------- /assets/icosahedron.obj.txt: -------------------------------------------------------------------------------- 1 | # OBJ file created by ply_to_obj.c 2 | # 3 | g Object001 4 | 5 | v 0 -0.525731 0.850651 6 | v 0.850651 0 0.525731 7 | v 0.850651 0 -0.525731 8 | v -0.850651 0 -0.525731 9 | v -0.850651 0 0.525731 10 | v -0.525731 0.850651 0 11 | v 0.525731 0.850651 0 12 | v 0.525731 -0.850651 0 13 | v -0.525731 -0.850651 0 14 | v 0 -0.525731 -0.850651 15 | v 0 0.525731 -0.850651 16 | v 0 0.525731 0.850651 17 | 18 | f 2 3 7 19 | f 2 8 3 20 | f 4 5 6 21 | f 5 4 9 22 | f 7 6 12 23 | f 6 7 11 24 | f 10 11 3 25 | f 11 10 4 26 | f 8 9 10 27 | f 9 8 1 28 | f 12 1 2 29 | f 1 12 5 30 | f 7 3 11 31 | f 2 7 12 32 | f 4 6 11 33 | f 6 5 12 34 | f 3 8 10 35 | f 8 2 1 36 | f 4 10 9 37 | f 5 9 1 38 | -------------------------------------------------------------------------------- /assets/icosphere.obj.txt: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib icosphere.mtl 4 | o Icosphere 5 | v 0.000000 -1.000000 0.000000 6 | v 0.723607 -0.447220 0.525725 7 | v -0.276388 -0.447220 0.850649 8 | v -0.894426 -0.447216 0.000000 9 | v -0.276388 -0.447220 -0.850649 10 | v 0.723607 -0.447220 -0.525725 11 | v 0.276388 0.447220 0.850649 12 | v -0.723607 0.447220 0.525725 13 | v -0.723607 0.447220 -0.525725 14 | v 0.276388 0.447220 -0.850649 15 | v 0.894426 0.447216 0.000000 16 | v 0.000000 1.000000 0.000000 17 | v -0.162456 -0.850654 0.499995 18 | v 0.425323 -0.850654 0.309011 19 | v 0.262869 -0.525738 0.809012 20 | v 0.850648 -0.525736 0.000000 21 | v 0.425323 -0.850654 -0.309011 22 | v -0.525730 -0.850652 0.000000 23 | v -0.688189 -0.525736 0.499997 24 | v -0.162456 -0.850654 -0.499995 25 | v -0.688189 -0.525736 -0.499997 26 | v 0.262869 -0.525738 -0.809012 27 | v 0.951058 0.000000 0.309013 28 | v 0.951058 0.000000 -0.309013 29 | v 0.000000 0.000000 1.000000 30 | v 0.587786 0.000000 0.809017 31 | v -0.951058 0.000000 0.309013 32 | v -0.587786 0.000000 0.809017 33 | v -0.587786 0.000000 -0.809017 34 | v -0.951058 0.000000 -0.309013 35 | v 0.587786 0.000000 -0.809017 36 | v 0.000000 0.000000 -1.000000 37 | v 0.688189 0.525736 0.499997 38 | v -0.262869 0.525738 0.809012 39 | v -0.850648 0.525736 0.000000 40 | v -0.262869 0.525738 -0.809012 41 | v 0.688189 0.525736 -0.499997 42 | v 0.162456 0.850654 0.499995 43 | v 0.525730 0.850652 0.000000 44 | v -0.425323 0.850654 0.309011 45 | v -0.425323 0.850654 -0.309011 46 | v 0.162456 0.850654 -0.499995 47 | usemtl None 48 | s off 49 | f 1 14 13 50 | f 2 14 16 51 | f 1 13 18 52 | f 1 18 20 53 | f 1 20 17 54 | f 2 16 23 55 | f 3 15 25 56 | f 4 19 27 57 | f 5 21 29 58 | f 6 22 31 59 | f 2 23 26 60 | f 3 25 28 61 | f 4 27 30 62 | f 5 29 32 63 | f 6 31 24 64 | f 7 33 38 65 | f 8 34 40 66 | f 9 35 41 67 | f 10 36 42 68 | f 11 37 39 69 | f 13 15 3 70 | f 13 14 15 71 | f 14 2 15 72 | f 16 17 6 73 | f 16 14 17 74 | f 14 1 17 75 | f 18 19 4 76 | f 18 13 19 77 | f 13 3 19 78 | f 20 21 5 79 | f 20 18 21 80 | f 18 4 21 81 | f 17 22 6 82 | f 17 20 22 83 | f 20 5 22 84 | f 23 24 11 85 | f 23 16 24 86 | f 16 6 24 87 | f 25 26 7 88 | f 25 15 26 89 | f 15 2 26 90 | f 27 28 8 91 | f 27 19 28 92 | f 19 3 28 93 | f 29 30 9 94 | f 29 21 30 95 | f 21 4 30 96 | f 31 32 10 97 | f 31 22 32 98 | f 22 5 32 99 | f 26 33 7 100 | f 26 23 33 101 | f 23 11 33 102 | f 28 34 8 103 | f 28 25 34 104 | f 25 7 34 105 | f 30 35 9 106 | f 30 27 35 107 | f 27 8 35 108 | f 32 36 10 109 | f 32 29 36 110 | f 29 9 36 111 | f 24 37 11 112 | f 24 31 37 113 | f 31 10 37 114 | f 38 39 12 115 | f 38 33 39 116 | f 33 11 39 117 | f 40 38 12 118 | f 40 34 38 119 | f 34 7 38 120 | f 41 40 12 121 | f 41 35 40 122 | f 35 8 40 123 | f 42 41 12 124 | f 42 36 41 125 | f 36 9 41 126 | f 39 42 12 127 | f 39 37 42 128 | f 37 10 42 129 | -------------------------------------------------------------------------------- /assets/lamp.obj.txt: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib lamp.mtl 4 | o Cube 5 | v -2.000000 -0.100000 2.000000 6 | v -2.000000 -0.100000 -2.000000 7 | v 2.000000 -0.100000 -2.000000 8 | v 2.000000 -0.100000 2.000000 9 | v -2.000000 0.100000 2.000000 10 | v -2.000000 0.100000 -2.000000 11 | v 2.000000 0.100000 -2.000000 12 | v 2.000000 0.100000 2.000000 13 | usemtl None 14 | s off 15 | f 6 2 1 16 | f 7 3 2 17 | f 8 4 3 18 | f 5 1 4 19 | f 2 3 4 20 | f 7 6 5 21 | f 5 6 1 22 | f 6 7 2 23 | f 7 8 3 24 | f 8 5 4 25 | f 1 2 4 26 | f 8 7 5 27 | -------------------------------------------------------------------------------- /assets/ninja2_grey_head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/assets/ninja2_grey_head.jpg -------------------------------------------------------------------------------- /assets/tetrahedron.obj.txt: -------------------------------------------------------------------------------- 1 | # Blender v2.71 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib tetrahedron.mtl 4 | o Solid 5 | v 0.000000 1.332143 0.000000 6 | v 0.942809 -0.001191 0.000000 7 | v -0.471405 -0.001191 -0.816497 8 | v -0.471405 -0.001191 0.816497 9 | usemtl None 10 | s off 11 | f 1 2 3 12 | f 1 3 4 13 | f 1 4 2 14 | f 2 4 3 15 | -------------------------------------------------------------------------------- /assets/worldmap-small_bw9sas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/assets/worldmap-small_bw9sas.png -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-left: 20px; 3 | } 4 | .zdog_list { 5 | list-style-type:square; 6 | } 7 | .slidecontainer { 8 | width: 10%; 9 | } 10 | .slidecontainer label { 11 | display: inline-block; 12 | } 13 | .slider { 14 | -webkit-appearance: none; 15 | width: 100%; 16 | height: 25px; 17 | background: #d3d3d3; 18 | outline: none; 19 | opacity: 0.7; 20 | -webkit-transition: .2s; 21 | transition: opacity .2s; 22 | } 23 | 24 | .slider:hover { 25 | opacity: 1; 26 | } 27 | 28 | .slider::-webkit-slider-thumb { 29 | -webkit-appearance: none; 30 | appearance: none; 31 | width: 25px; 32 | height: 25px; 33 | background: #4CAF50; 34 | cursor: pointer; 35 | } 36 | 37 | .slider::-moz-range-thumb { 38 | width: 25px; 39 | height: 25px; 40 | background: #4CAF50; 41 | cursor: pointer; 42 | } 43 | 44 | #options { 45 | margin-left: 10px; 46 | } 47 | 48 | .button { 49 | background-color: #e7e7e7; /* Gray */ 50 | border: none; 51 | color: white; 52 | padding: 15px 32px; 53 | text-align: center; 54 | text-decoration: none; 55 | display: inline-block; 56 | font-size: 16px; 57 | border-radius: 3px; 58 | } 59 | 60 | .button-green {background-color: #4CAF50;} /* Green */ 61 | .button-blue {background-color: #008CBA;} /* Blue */ 62 | .button-red {background-color: #f44336;} /* Red */ 63 | .button-gray {background-color: #e7e7e7; color: black;} /* Gray */ 64 | .button-black {background-color: #555555;} /* Black */ 65 | 66 | .button:hover { 67 | box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24), 0 17px 50px 0 rgba(0,0,0,0.19); 68 | } 69 | -------------------------------------------------------------------------------- /js/csg_tools.js: -------------------------------------------------------------------------------- 1 | function convertCsgObjectToBlob(csgObject, format="stl") { 2 | var blob; 3 | if(format == "stl") { 4 | blob = csgObject.fixTJunctions().toStlBinary(); 5 | } 6 | else if(format == "x3d") { 7 | blob = csgObject.fixTJunctions().toX3D(); 8 | } 9 | else if(format == "dxf") { 10 | blob = csgObject.toDxf(); 11 | } else { 12 | console.error("Format not supported : "+format); 13 | return false; 14 | } 15 | return blob; 16 | }; 17 | 18 | function getWindowURL() { 19 | if(window.URL) return window.URL; 20 | else if(window.webkitURL) return window.webkitURL; 21 | else { 22 | console.error("Your browser doesn't support window.URL"); 23 | return false; 24 | } 25 | } 26 | 27 | function getExportFormatInfo(format) { 28 | let formats = { 29 | stl: { 30 | displayName: "STL", 31 | extension: "stl", 32 | mimetype: "application/sla", 33 | }, 34 | x3d: { 35 | displayName: "X3D", 36 | extension: "x3d", 37 | mimetype: "model/x3d+xml", 38 | }, 39 | dxf: { 40 | displayName: "DXF", 41 | extension: "dxf", 42 | mimetype: "application/dxf", 43 | } 44 | }; 45 | if (formats.hasOwnProperty(format)) { 46 | return formats[format]; 47 | } else { 48 | console.error("format not found => "+String(format)); 49 | } 50 | return false; 51 | } 52 | 53 | /** 54 | * Generate the Blog of the CSG object and autoclick on the downloadLink to auto download the file 55 | * @param csgObject (object created by csg.js) 56 | * @param downloadLink (DOM target of an HTML tag "a" predefined and hidden on the page) 57 | * @param format ("stl" by default) 58 | * @returns {boolean} 59 | */ 60 | export function generateOutputFileBlobUrl(csgObject, downloadLink, format="stl") { 61 | let blob = convertCsgObjectToBlob(csgObject, format); 62 | if (blob === false) return; 63 | let windowURL = getWindowURL(); 64 | if (windowURL === false) return; 65 | let outputFileBlobUrl = windowURL.createObjectURL(blob); 66 | if(!outputFileBlobUrl) { 67 | console.error("createObjectURL() failed"); 68 | return false; 69 | } 70 | downloadLink.href = outputFileBlobUrl; 71 | let ext = getExportFormatInfo(format).extension; 72 | downloadLink.setAttribute("download", "csg_shape."+ext); 73 | downloadLink.click(); 74 | } 75 | 76 | /** 77 | * Bind the user code to generate the CSG object 78 | * 79 | * @param CSG (import the CSG object in the scope to use it temporarily) 80 | * @param code (the JS code to evaluate) 81 | * @param userdata (user data or Null) 82 | * @param warningZone (Dom target to warning zone into the page, or False) 83 | * @returns {null|any} 84 | */ 85 | export function generateCSG(CSG, code, userdata=null, warningZone=undefined) { 86 | let usercode = String(code).trim(); 87 | let fnc_code; 88 | // bind the user code in the "fnc_code" function to avoid pollution of the current scope 89 | let binded_code = `fnc_code = ()=> { 90 | "use strict"; 91 | let final = null; 92 | ${usercode} 93 | return final; 94 | } 95 | fnc_code(); 96 | `; 97 | 98 | if (warningZone != undefined) { 99 | warningZone.innerHTML = ''; 100 | } 101 | 102 | try { 103 | let res = eval(binded_code); 104 | if (res == undefined || res == null) { 105 | if (warningZone != undefined) { 106 | warningZone.innerHTML = "You must always finish your code with the predefined variable 'final' like on that example :
final = your_last_var;
"; 107 | } 108 | return null; 109 | } 110 | return res; 111 | } catch(error) { 112 | console.warn(error); 113 | console.log(binded_code); 114 | if (warningZone != undefined) { 115 | warningZone.innerHTML = String(error); 116 | } 117 | return null; 118 | } 119 | } 120 | 121 | export function generateTableForm(tableTarget, definitions) { 122 | let tableparams = document.getElementById(tableTarget); 123 | if (tableparams == undefined) { 124 | console.error('Table formulary is missing in the DOM'); 125 | return false; 126 | } 127 | let dictionary = []; 128 | definitions.forEach(item => { 129 | let tr = document.createElement('tr'); 130 | let td1 = document.createElement('td'); 131 | let td2 = document.createElement('td'); 132 | tr.appendChild(td1); 133 | tr.appendChild(td2); 134 | let input = document.createElement('input'); 135 | input.setAttribute('id', item.name); 136 | input.setAttribute('value', item.default); 137 | if (item.type == 'int' || item.type == 'float') { 138 | input.setAttribute('type', 'number'); 139 | } 140 | td2.appendChild(input); 141 | dictionary.push(input); 142 | let label = document.createElement('label'); 143 | label.innerText = item.caption; 144 | label.setAttribute('for', item.name); 145 | td1.appendChild(label); 146 | tableparams.appendChild(tr); 147 | }); 148 | return dictionary; 149 | } -------------------------------------------------------------------------------- /js/nbody.js: -------------------------------------------------------------------------------- 1 | /* The Computer Language Benchmarks Game 2 | https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ 3 | contributed by Isaac Gouy */ 4 | 5 | 6 | // https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/nbody.html 7 | 8 | /* 9 | 10 | Model the orbits of Jovian planets, using the same simple symplectic-integrator. 11 | 12 | Thanks to Mark C. Lewis for suggesting this task. 13 | 14 | Useful symplectic integrators are freely available, for example the HNBody Symplectic Integration Package. 15 | 16 | https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-java-2.html 17 | https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/nbody.html#nbody 18 | */ 19 | 20 | 21 | const SOLAR_PARAMS = { 22 | SOLAR_MASS: 4 * Math.PI * Math.PI, 23 | DAYS_PER_YEAR: 365.24 24 | }; 25 | 26 | 27 | function Body(name, diameter, x,y,z,vx,vy,vz,mass, color){ 28 | this.name = name; 29 | this.diameter = diameter; 30 | this.color = color; 31 | this.x = x; 32 | this.y = y; 33 | this.z = z; 34 | this.vx = vx; 35 | this.vy = vy; 36 | this.vz = vz; 37 | this.mass = mass; 38 | } 39 | 40 | Body.prototype.offsetMomentum = function(px,py,pz) { 41 | this.vx = -px / SOLAR_PARAMS.SOLAR_MASS; 42 | this.vy = -py / SOLAR_PARAMS.SOLAR_MASS; 43 | this.vz = -pz / SOLAR_PARAMS.SOLAR_MASS; 44 | return this; 45 | } 46 | 47 | function Jupiter(){ 48 | return new Body( 49 | "Jupiter", 50 | 139820, 51 | 4.84143144246472090e+00, 52 | -1.16032004402742839e+00, 53 | -1.03622044471123109e-01, 54 | 1.66007664274403694e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 55 | 7.69901118419740425e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 56 | -6.90460016972063023e-05 * SOLAR_PARAMS.DAYS_PER_YEAR, 57 | 9.54791938424326609e-04 * SOLAR_PARAMS.SOLAR_MASS, 58 | "#ffff66" 59 | ); 60 | } 61 | 62 | function Saturn(){ 63 | return new Body( 64 | "Saturn", 65 | 116460, 66 | 8.34336671824457987e+00, 67 | 4.12479856412430479e+00, 68 | -4.03523417114321381e-01, 69 | -2.76742510726862411e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 70 | 4.99852801234917238e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 71 | 2.30417297573763929e-05 * SOLAR_PARAMS.DAYS_PER_YEAR, 72 | 2.85885980666130812e-04 * SOLAR_PARAMS.SOLAR_MASS, 73 | "#0099cc" 74 | ); 75 | } 76 | 77 | function Uranus(){ 78 | return new Body( 79 | "Uranus", 80 | 50724, 81 | 1.28943695621391310e+01, 82 | -1.51111514016986312e+01, 83 | -2.23307578892655734e-01, 84 | 2.96460137564761618e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 85 | 2.37847173959480950e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 86 | -2.96589568540237556e-05 * SOLAR_PARAMS.DAYS_PER_YEAR, 87 | 4.36624404335156298e-05 * SOLAR_PARAMS.SOLAR_MASS, 88 | "#996633" 89 | ); 90 | } 91 | 92 | function Neptune(){ 93 | return new Body( 94 | "Neptune", 95 | 49244, 96 | 1.53796971148509165e+01, 97 | -2.59193146099879641e+01, 98 | 1.79258772950371181e-01, 99 | 2.68067772490389322e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 100 | 1.62824170038242295e-03 * SOLAR_PARAMS.DAYS_PER_YEAR, 101 | -9.51592254519715870e-05 * SOLAR_PARAMS.DAYS_PER_YEAR, 102 | 5.15138902046611451e-05 * SOLAR_PARAMS.SOLAR_MASS, 103 | "#ff9966" 104 | ); 105 | } 106 | 107 | function Sun(){ 108 | return new Body("Sun", 1391000, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_PARAMS.SOLAR_MASS, "#ffff00"); 109 | } 110 | 111 | 112 | function NBodySystem(bodies){ 113 | this.bodies = bodies; 114 | var px = 0.0; 115 | var py = 0.0; 116 | var pz = 0.0; 117 | var size = this.bodies.length; 118 | for (let i=0; i 0) { 67 | context.stroke(); 68 | } 69 | //draw the 2 "pins" 70 | context.beginPath(); 71 | context.arc(0, 0, this.diameter, 0, TAU, true); 72 | context.closePath(); 73 | context.stroke(); 74 | 75 | context.beginPath(); 76 | context.arc(this.width, 0, this.diameter, 0, TAU, true); 77 | context.closePath(); 78 | context.stroke(); 79 | 80 | context.restore(); 81 | } 82 | 83 | /** 84 | * Draw the segment in a 3D context (with Zdog) 85 | * @param zdogrefer 86 | */ 87 | drawZdog(zdogrefer=undefined) { 88 | let context = zdogrefer || this.context; 89 | let h = this.height, 90 | d = this.width + h, //top-right diagonal 91 | cr = h / 2, //corner radius 92 | depth = this.depth; // depth (z position) 93 | 94 | let zoffset = this.z + this.offset * this.lineWidth; 95 | let seg = new Zdog.Shape({ 96 | addTo: context, 97 | translate: {x:this.x, y:this.y, z:zoffset}, 98 | rotate: {z:this.rotation}, 99 | scale: {x: this.scaleX, y:this.scaleY} 100 | }); 101 | 102 | let path = [ 103 | { x: 0, y: -cr, z:depth }, 104 | { x: d - 2 * cr, y: -cr, z:depth }, 105 | { arc: [ 106 | { x:-cr + d, y:-cr, z:depth }, // start control point 107 | { x: -cr + d, y:0, z:depth }, // end point 108 | ]}, 109 | { x:-cr + d, y:h - 2 * cr, z:depth }, 110 | { arc: [ 111 | { x:-cr + d, y:-cr + h, z:depth }, // start control point 112 | { x:d - 2 * cr, y:-cr + h, z:depth }, // end point 113 | ]}, 114 | { x:0, y:-cr + h, z:depth }, 115 | { arc: [ 116 | { x:-cr, y:-cr + h, z:depth }, // start control point 117 | { x:-cr, y:h - 2 * cr, z:depth }, // end point 118 | ]}, 119 | { x:-cr, y:0, z:depth}, 120 | { arc: [ 121 | { x:-cr, y:-cr, z:depth }, // start control point 122 | { x:0, y:-cr, z:depth }, // end point 123 | ]} 124 | ]; 125 | 126 | let main = new Zdog.Shape({ 127 | addTo: seg, 128 | path: path, 129 | closed: false, 130 | fill: true, 131 | stroke: this.lineWidth, 132 | color: this.color 133 | }); 134 | 135 | new Zdog.Ellipse({ 136 | addTo: main, 137 | translate: { x:0, y:0}, 138 | diameter: this.diameter, 139 | stroke: 1, 140 | color: this.outline, 141 | fill: false 142 | }); 143 | /* 144 | new Zdog.Ellipse({ 145 | addTo: main, 146 | translate: { x:0, y:0, z:this.depth+this.lineWidth+1}, 147 | diameter: this.diameter, 148 | stroke: 1, 149 | color: this.outline, 150 | fill: false 151 | }); 152 | */ 153 | new Zdog.Ellipse({ 154 | addTo: main, 155 | translate: { x:this.width, y:0}, 156 | diameter: this.diameter, 157 | stroke: 1, 158 | color: this.outline, 159 | fill: false 160 | }); 161 | /* 162 | new Zdog.Ellipse({ 163 | addTo: main, 164 | translate: { x:this.width, y:0, z:this.depth+this.lineWidth+1}, 165 | diameter: this.diameter, 166 | stroke: 1, 167 | color: this.outline, 168 | fill: false 169 | }); 170 | */ 171 | } 172 | 173 | /** 174 | * Call the good "draw" method using the engine specified 175 | * @param context 176 | */ 177 | draw(context=undefined) { 178 | if (this.engine == 'zdog') { 179 | return this.drawZdog(context); 180 | } else { 181 | return this.draw2D(context); 182 | } 183 | } 184 | 185 | getPin() { 186 | return { 187 | x: this.x + Math.cos(this.rotation) * this.width, 188 | y: this.y + Math.sin(this.rotation) * this.width 189 | }; 190 | } 191 | 192 | } 193 | -------------------------------------------------------------------------------- /js/shapeCalabiYau.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Some functions of this small toolbox are largely inspired by the project Phoria.js of Kevin Roast 3 | * => http://www.kevs3d.co.uk/dev/phoria/ 4 | * Cone, Cylinder2, Sphere2, Cuboid2 are largely inspired by algorithms of Frido Verweij 5 | * => https://librayRot.fridoverweij.com/codelab/ 6 | * Mollusc shell, great creature, great sphere and a beautiful rose 7 | * => https://echarts.apache.org/examples/en/editor.html 8 | * Functions rotateX3D, rotateXYD and rotateZ3D largely inspired by the tutorial of Peter Collingridge 9 | * https://petercollingridge.appspot.com/3D-tutorial/rotating-objects 10 | */ 11 | 12 | var shapeCalabiYau = (function (math) { 13 | "use strict"; 14 | 15 | const { 16 | cos, sin, PI 17 | } = Math; 18 | 19 | const TAU = PI * 2; 20 | const DEG_TO_RAD = PI / 180; 21 | const RAD_TO_DEG = 180 / PI; 22 | 23 | const degToRad = angle => angle * DEG_TO_RAD; 24 | const radToDeg = angle => angle * RAD_TO_DEG; 25 | 26 | var obj3d = {}; 27 | 28 | // https://github.com/d3/d3-array/blob/master/src/range.js 29 | function range (start, stop, step) { 30 | start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; 31 | 32 | var i = -1, 33 | n = Math.max(0, Math.ceil((stop - start) / step)) | 0, 34 | trange = new Array(n); 35 | 36 | while (++i < n) { 37 | trange[i] = start + i * step; 38 | } 39 | return trange; 40 | } 41 | 42 | // https://github.com/d3/d3-array/blob/master/src/cross.js 43 | function cross (...values) { 44 | function length(array) { 45 | return array.length | 0; 46 | } 47 | 48 | function empty(length) { 49 | return !(length > 0); 50 | } 51 | 52 | function arrayify(values) { 53 | return typeof values !== "object" || "length" in values ? values : Array.from(values); 54 | } 55 | 56 | function reducer(reduce) { 57 | return values => reduce(...values); 58 | } 59 | const reduce = typeof values[values.length - 1] === "function" && reducer(values.pop()); 60 | values = values.map(arrayify); 61 | const lengths = values.map(length); 62 | const j = values.length - 1; 63 | const index = new Array(j + 1).fill(0); 64 | const product = []; 65 | if (j < 0 || lengths.some(empty)) return product; 66 | while (true) { 67 | product.push(index.map((j, i) => values[i][j])); 68 | let i = j; 69 | while (++index[i] === lengths[i]) { 70 | if (i === 0) return reduce ? product.map(reduce) : product; 71 | index[i--] = 0; 72 | } 73 | } 74 | } 75 | 76 | // Make a Plane mesh with Normal Material 77 | function addNormalRect(v1, v2, v3, v4) { 78 | obj3d.points.push(v1); 79 | let a = obj3d.points.length - 1; 80 | obj3d.points.push(v2); 81 | let b = obj3d.points.length - 1; 82 | obj3d.points.push(v3); 83 | let c = obj3d.points.length - 1; 84 | obj3d.points.push(v4); 85 | let d = obj3d.points.length - 1; 86 | 87 | obj3d.polygons.push([a, b, c, d]); 88 | obj3d.edges.push({a:a, b:b}); 89 | obj3d.edges.push({a:b, b:c}); 90 | obj3d.edges.push({a:c, b:d}); 91 | obj3d.edges.push({a:d, b:a}); 92 | } 93 | 94 | function addCalabiYau (exponent, projection) { 95 | function coordinate(x, y, n, k1, k2, projection) { 96 | const z1 = math.multiply( 97 | math.exp(math.complex(0, 2*PI*k1/n)), 98 | math.pow(math.cos(math.complex(x, y)), 2/n) 99 | ); 100 | const z2 = math.multiply( 101 | math.exp(math.complex(0, 2*PI*k2/n)), 102 | math.pow(math.sin(math.complex(x, y)), 2/n) 103 | ); 104 | return {x:z1.re, y:z2.re, z:z1.im*math.cos(projection) + z2.im*math.sin(projection) }; 105 | } 106 | 107 | const dx = PI/10; 108 | const dy = PI/10; 109 | cross(range(exponent), range(exponent)).forEach(k => { 110 | range(0, PI/2, dx).forEach(x => { 111 | range(-PI/2, PI/2, dy).forEach(y => { 112 | const data = [ 113 | {"x": x, "y": y }, 114 | {"x": x+dx, "y": y }, 115 | {"x": x+dx, "y": y+dy}, 116 | {"x": x, "y": y+dy}, 117 | ]; 118 | addNormalRect( 119 | ...data.map(d => coordinate(d.x, d.y, exponent, k[0], k[1], projection)) 120 | ); 121 | }); 122 | }); 123 | }) 124 | }; 125 | 126 | /** 127 | * 128 | * @param shape_params 129 | */ 130 | function generateShape(shape_params={}) { 131 | obj3d.points = []; 132 | obj3d.edges = []; 133 | obj3d.polygons = []; 134 | 135 | var exponent = shape_params.exponent || 6; 136 | var projection = shape_params.projection || 3; 137 | var disorder = shape_params.disorder || 0; 138 | 139 | addCalabiYau(exponent, projection, disorder); 140 | 141 | if (disorder != 0) { 142 | obj3d.points.forEach(node => { 143 | let theta = disorder*Math.random(); 144 | 145 | let sinTheta = sin(theta); 146 | let cosTheta = cos(theta); 147 | 148 | node.x = node.x * cosTheta - node.y * sinTheta; 149 | node.y = node.y * cosTheta + node.x * sinTheta; 150 | node.z = node.z * cosTheta + node.x * sinTheta; 151 | }); 152 | } 153 | 154 | return obj3d; 155 | 156 | } 157 | 158 | // public functions and constants (items not declared here are private) 159 | return { 160 | generateShape: generateShape 161 | }; 162 | })(math); 163 | -------------------------------------------------------------------------------- /js/slider.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Source : http://lamberta.github.io/html5-animation/ 3 | */ 4 | 5 | function Slider (min, max, value) { 6 | this.min = (min === undefined) ? 0 : min; 7 | this.max = (max === undefined) ? 100 : max; 8 | this.value = (value === undefined) ? 100 : value; 9 | this.onchange = null; 10 | 11 | this.x = 0; 12 | this.y = 0; 13 | this.width = 16; 14 | this.height = 100; 15 | 16 | this.backColor = "#cccccc"; 17 | this.backBorderColor = "#999999"; 18 | this.backWidth = 4; 19 | this.backX = this.width / 2 - this.backWidth / 2; 20 | 21 | this.handleColor = "#eeeeee"; 22 | this.handleBorderColor = "#cccccc"; 23 | this.handleHeight = 6; 24 | this.handleY = 0; 25 | 26 | this.updatePosition(); 27 | } 28 | 29 | Slider.prototype.draw = function (context) { 30 | context.save(); 31 | context.translate(this.x, this.y); 32 | 33 | //draw back 34 | context.fillStyle = this.backColor; 35 | context.beginPath(); 36 | context.fillRect(this.backX, 0, this.backWidth, this.height); 37 | context.closePath(); 38 | 39 | //draw handle 40 | context.strokeStyle = this.handleBorderColor; 41 | context.fillStyle = this.handleColor; 42 | context.beginPath(); 43 | context.rect(0, this.handleY, this.width, this.handleHeight); 44 | context.closePath(); 45 | context.fill(); 46 | context.stroke(); 47 | 48 | context.restore(); 49 | }; 50 | 51 | Slider.prototype.updateValue = function () { 52 | var old_value = this.value, 53 | handleRange = this.height - this.handleHeight, 54 | valueRange = this.max - this.min; 55 | 56 | this.value = (handleRange - this.handleY) / handleRange * valueRange + this.min; 57 | if (typeof this.onchange === 'function' && this.value !== old_value) { 58 | this.onchange(); 59 | } 60 | }; 61 | 62 | Slider.prototype.updatePosition = function () { 63 | var handleRange = this.height - this.handleHeight, 64 | valueRange = this.max - this.min; 65 | 66 | this.handleY = handleRange - ((this.value - this.min) / valueRange) * handleRange; 67 | }; 68 | 69 | Slider.prototype.captureMouse = function (element) { 70 | var self = this, 71 | mouse = utils.captureMouse(element), 72 | bounds = {}; 73 | 74 | setHandleBounds(); 75 | 76 | element.addEventListener('mousedown', function () { 77 | if (utils.containsPoint(bounds, mouse.x, mouse.y)) { 78 | element.addEventListener('mouseup', onMouseUp, false); 79 | element.addEventListener('mousemove', onMouseMove, false); 80 | } 81 | }, false); 82 | 83 | function onMouseUp () { 84 | element.removeEventListener('mousemove', onMouseMove, false); 85 | element.removeEventListener('mouseup', onMouseUp, false); 86 | setHandleBounds(); 87 | } 88 | 89 | function onMouseMove () { 90 | var pos_y = mouse.y - self.y; 91 | self.handleY = Math.min(self.height - self.handleHeight, Math.max(pos_y, 0)); 92 | self.updateValue(); 93 | } 94 | 95 | function setHandleBounds () { 96 | bounds.x = self.x; 97 | bounds.y = self.y + self.handleY; 98 | bounds.width = self.width; 99 | bounds.height = self.handleHeight; 100 | } 101 | }; 102 | -------------------------------------------------------------------------------- /js/tgraph.js: -------------------------------------------------------------------------------- 1 | // inspired by : https://amoffat.github.io/held-karp-gpu-demo/ 2 | 3 | var tgraph = (function( ) { 4 | "use strict"; 5 | 6 | var generateTour = function(num, maxEdgeCost) { 7 | var cost, edge, edges, getCost, node, nodes, _i, _j; 8 | if (maxEdgeCost == null) { 9 | maxEdgeCost = 100; 10 | } 11 | nodes = {}; 12 | getCost = function() { 13 | return _.toInteger(Math.random() * maxEdgeCost); 14 | }; 15 | for (node = _i = 0; 0 <= num ? _i < num : _i > num; node = 0 <= num ? ++_i : --_i) { 16 | edges = {}; 17 | nodes[node] = edges; 18 | for (edge = _j = 0; 0 <= num ? _j < num : _j > num; edge = 0 <= num ? ++_j : --_j) { 19 | cost = getCost(); 20 | edges[edge] = cost; 21 | } 22 | } 23 | return nodes; 24 | }; 25 | 26 | var distance = function(a, b) { 27 | var x, y; 28 | x = b.x - a.x; 29 | y = b.y - a.y; 30 | return Math.sqrt(x * x + y * y); 31 | }; 32 | 33 | var createRndNode = function(id) { 34 | var x = Math.random(); 35 | var y = Math.random(); 36 | return { 37 | id: id, 38 | pos: { 39 | x: x, 40 | y: y 41 | } 42 | }; 43 | }; 44 | 45 | var createNode = function(id, x, y) { 46 | return { 47 | id: id, 48 | pos: { 49 | x: x, 50 | y: y 51 | } 52 | }; 53 | }; 54 | 55 | var computeEdges = function(nodes) { 56 | var d, i, key, n1, n2, _results; 57 | _results = []; 58 | for (key in nodes) { 59 | n1 = nodes[key]; 60 | n1.edges = {}; 61 | _results.push((function() { 62 | var _results1; 63 | _results1 = []; 64 | for (i in nodes) { 65 | n2 = nodes[i]; 66 | d = distance(n1.pos, n2.pos); 67 | _results1.push(n1.edges[i] = d); 68 | } 69 | return _results1; 70 | })()); 71 | } 72 | return _results; 73 | }; 74 | 75 | var pushRndNode = function(nodes) { 76 | var x = Math.round(Math.random()*100); 77 | var y = Math.round(Math.random()*100); 78 | var id = Object.keys(nodes).length; 79 | nodes[id] = createNode(id, x, y); 80 | computeEdges(nodes); 81 | return nodes; 82 | }; 83 | 84 | var pushNode = function(nodes, x, y) { 85 | var id = Object.keys(nodes).length; 86 | nodes[id] = createNode(id, x, y); 87 | computeEdges(nodes); 88 | return nodes; 89 | }; 90 | 91 | var popNode = function(nodes) { 92 | var id; 93 | id = Object.keys(nodes) - 1; 94 | delete nodes[id]; 95 | computeEdges(nodes); 96 | return nodes; 97 | }; 98 | 99 | var dropNode = function(nodes, id) { 100 | if (nodes.hasOwnProperty(id)) { 101 | delete nodes[id]; 102 | computeEdges(nodes); 103 | } else { 104 | console.error('id not found - drop failed'); 105 | } 106 | return nodes; 107 | }; 108 | 109 | var generateNodes = function(num) { 110 | var i, nodes, _i; 111 | nodes = {}; 112 | for (i = _i = 0; 0 <= num ? _i < num : _i > num; i = 0 <= num ? ++_i : --_i) { 113 | nodes[i] = createRndNode(i); 114 | } 115 | computeEdges(nodes); 116 | return nodes; 117 | }; 118 | 119 | var polygone = function(sides, radius) { 120 | var path = []; var TAU = Math.PI * 2; 121 | for ( var i=0; i < sides; i++ ) { 122 | var theta = i/sides * TAU - TAU/4; 123 | var x = Math.cos( theta ) * radius; 124 | var y = Math.sin( theta ) * radius; 125 | path.push({ x: x, y: y }); 126 | } 127 | return path; 128 | }; 129 | 130 | return { 131 | generateNodes: generateNodes, 132 | pushRndNode: pushRndNode, 133 | pushNode: pushNode, 134 | popNode: popNode, 135 | dropNode: dropNode, 136 | polygone: polygone 137 | }; 138 | 139 | })(); 140 | 141 | var nodes = tgraph.generateNodes(10); 142 | console.log(nodes); 143 | nodes = tgraph.pushRndNode(nodes); 144 | nodes = tgraph.dropNode(nodes, 10); 145 | nodes = tgraph.pushNode(nodes, 10, 30); 146 | console.log(nodes); 147 | 148 | 149 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Source : http://lamberta.github.io/html5-animation/ 4 | * 5 | * Normalize the browser animation API across implementations. This requests 6 | * the browser to schedule a repaint of the window for the next animation frame. 7 | * Checks for cross-browser support, and, failing to find it, falls back to setTimeout. 8 | * @param {function} callback Function to call when it's time to update your animation for the next repaint. 9 | * @param {HTMLElement} element Optional parameter specifying the element that visually bounds the entire animation. 10 | * @return {number} Animation frame request. 11 | */ 12 | if (!window.requestAnimationFrame) { 13 | window.requestAnimationFrame = (window.webkitRequestAnimationFrame || 14 | window.mozRequestAnimationFrame || 15 | window.msRequestAnimationFrame || 16 | window.oRequestAnimationFrame || 17 | function (callback) { 18 | return window.setTimeout(callback, 17 /*~ 1000/60*/); 19 | }); 20 | } 21 | 22 | /** 23 | * ERRATA: 'cancelRequestAnimationFrame' renamed to 'cancelAnimationFrame' to reflect an update to the W3C Animation-Timing Spec. 24 | * 25 | * Cancels an animation frame request. 26 | * Checks for cross-browser support, falls back to clearTimeout. 27 | * @param {number} Animation frame request. 28 | */ 29 | if (!window.cancelAnimationFrame) { 30 | window.cancelAnimationFrame = (window.cancelRequestAnimationFrame || 31 | window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || 32 | window.mozCancelAnimationFrame || window.mozCancelRequestAnimationFrame || 33 | window.msCancelAnimationFrame || window.msCancelRequestAnimationFrame || 34 | window.oCancelAnimationFrame || window.oCancelRequestAnimationFrame || 35 | window.clearTimeout); 36 | } 37 | 38 | /* Object that contains our utility functions. 39 | * Attached to the window object which acts as the global namespace. 40 | */ 41 | window.utils = {}; 42 | 43 | /** 44 | * Keeps track of the current mouse position, relative to an element. 45 | * @param {HTMLElement} element 46 | * @return {object} Contains properties: x, y, event 47 | */ 48 | window.utils.captureMouse = function (element) { 49 | var mouse = {x: 0, y: 0, event: null}, 50 | body_scrollLeft = document.body.scrollLeft, 51 | element_scrollLeft = document.documentElement.scrollLeft, 52 | body_scrollTop = document.body.scrollTop, 53 | element_scrollTop = document.documentElement.scrollTop, 54 | offsetLeft = element.offsetLeft, 55 | offsetTop = element.offsetTop; 56 | 57 | element.addEventListener('mousemove', function (event) { 58 | var x, y; 59 | 60 | if (event.pageX || event.pageY) { 61 | x = event.pageX; 62 | y = event.pageY; 63 | } else { 64 | x = event.clientX + body_scrollLeft + element_scrollLeft; 65 | y = event.clientY + body_scrollTop + element_scrollTop; 66 | } 67 | x -= offsetLeft; 68 | y -= offsetTop; 69 | 70 | mouse.x = x; 71 | mouse.y = y; 72 | mouse.event = event; 73 | }, false); 74 | 75 | return mouse; 76 | }; 77 | 78 | /** 79 | * Keeps track of the current (first) touch position, relative to an element. 80 | * @param {HTMLElement} element 81 | * @return {object} Contains properties: x, y, isPressed, event 82 | */ 83 | window.utils.captureTouch = function (element) { 84 | var touch = {x: null, y: null, isPressed: false, event: null}, 85 | body_scrollLeft = document.body.scrollLeft, 86 | element_scrollLeft = document.documentElement.scrollLeft, 87 | body_scrollTop = document.body.scrollTop, 88 | element_scrollTop = document.documentElement.scrollTop, 89 | offsetLeft = element.offsetLeft, 90 | offsetTop = element.offsetTop; 91 | 92 | element.addEventListener('touchstart', function (event) { 93 | touch.isPressed = true; 94 | touch.event = event; 95 | }, false); 96 | 97 | element.addEventListener('touchend', function (event) { 98 | touch.isPressed = false; 99 | touch.x = null; 100 | touch.y = null; 101 | touch.event = event; 102 | }, false); 103 | 104 | element.addEventListener('touchmove', function (event) { 105 | var x, y, 106 | touch_event = event.touches[0]; //first touch 107 | 108 | if (touch_event.pageX || touch_event.pageY) { 109 | x = touch_event.pageX; 110 | y = touch_event.pageY; 111 | } else { 112 | x = touch_event.clientX + body_scrollLeft + element_scrollLeft; 113 | y = touch_event.clientY + body_scrollTop + element_scrollTop; 114 | } 115 | x -= offsetLeft; 116 | y -= offsetTop; 117 | 118 | touch.x = x; 119 | touch.y = y; 120 | touch.event = event; 121 | }, false); 122 | 123 | return touch; 124 | }; 125 | 126 | /** 127 | * Returns a color in the format: '#RRGGBB', or as a hex number if specified. 128 | * @param {number|string} color 129 | * @param {boolean=} toNumber=false Return color as a hex number. 130 | * @return {string|number} 131 | */ 132 | window.utils.parseColor = function (color, toNumber) { 133 | if (toNumber === true) { 134 | if (typeof color === 'number') { 135 | return (color | 0); //chop off decimal 136 | } 137 | if (typeof color === 'string' && color[0] === '#') { 138 | color = color.slice(1); 139 | } 140 | return window.parseInt(color, 16); 141 | } else { 142 | if (typeof color === 'number') { 143 | color = '#' + ('00000' + (color | 0).toString(16)).substr(-6); //pad 144 | } 145 | return color; 146 | } 147 | }; 148 | 149 | /** 150 | * Converts a color to the RGB string format: 'rgb(r,g,b)' or 'rgba(r,g,b,a)' 151 | * @param {number|string} color 152 | * @param {number} alpha 153 | * @return {string} 154 | */ 155 | window.utils.colorToRGB = function (color, alpha) { 156 | //number in octal format or string prefixed with # 157 | if (typeof color === 'string' && color[0] === '#') { 158 | color = window.parseInt(color.slice(1), 16); 159 | } 160 | alpha = (alpha === undefined) ? 1 : alpha; 161 | //parse hex values 162 | var r = color >> 16 & 0xff, 163 | g = color >> 8 & 0xff, 164 | b = color & 0xff, 165 | a = (alpha < 0) ? 0 : ((alpha > 1) ? 1 : alpha); 166 | //only use 'rgba' if needed 167 | if (a === 1) { 168 | return "rgb("+ r +","+ g +","+ b +")"; 169 | } else { 170 | return "rgba("+ r +","+ g +","+ b +","+ a +")"; 171 | } 172 | }; 173 | 174 | /** 175 | * Determine if a rectangle contains the coordinates (x,y) within it's boundaries. 176 | * @param {object} rect Object with properties: x, y, width, height. 177 | * @param {number} x Coordinate position x. 178 | * @param {number} y Coordinate position y. 179 | * @return {boolean} 180 | */ 181 | window.utils.containsPoint = function (rect, x, y) { 182 | return !(x < rect.x || 183 | x > rect.x + rect.width || 184 | y < rect.y || 185 | y > rect.y + rect.height); 186 | }; 187 | 188 | /** 189 | * Determine if two rectangles overlap. 190 | * @param {object} rectA Object with properties: x, y, width, height. 191 | * @param {object} rectB Object with properties: x, y, width, height. 192 | * @return {boolean} 193 | */ 194 | window.utils.intersects = function (rectA, rectB) { 195 | return !(rectA.x + rectA.width < rectB.x || 196 | rectB.x + rectB.width < rectA.x || 197 | rectA.y + rectA.height < rectB.y || 198 | rectB.y + rectB.height < rectA.y); 199 | }; 200 | -------------------------------------------------------------------------------- /jstools/addslider.js: -------------------------------------------------------------------------------- 1 | /* 2 | Example of HTML code generated by the fonction addSlider() 3 | 6 | */ 7 | function addSlider( fieldname, domtarget, start, end, value, step, label, callback, init=null ) { 8 | let xlabel = document.createElement('label'); 9 | xlabel.innerHTML = label + ' : '; 10 | let xoutput = document.createElement('output'); 11 | xoutput.setAttribute('for', 'pjs_'+fieldname); 12 | 13 | if (init != null) { 14 | xoutput.value = init; 15 | } else { 16 | xoutput.value = value; 17 | } 18 | xlabel.append(xoutput); 19 | let xinput = document.createElement('input'); 20 | xinput.setAttribute('type', 'range'); 21 | xinput.setAttribute('min', start); 22 | xinput.setAttribute('max', end); 23 | xinput.setAttribute('step', step); 24 | xinput.setAttribute('class', 'slider'); 25 | xinput.setAttribute('id', 'pjs_'+fieldname); 26 | xinput.value = value; 27 | xlabel.append(xinput); 28 | domtarget.append(xlabel); 29 | xinput.addEventListener('change', function(evt) { 30 | //evt.preventDefault(); 31 | let output = evt.target.parentNode.querySelector('output'); 32 | let substition = callback(this); 33 | if (substition) { 34 | output.value = substition; 35 | } else { 36 | output.value = this.value; 37 | } 38 | }, false) 39 | } 40 | 41 | function multiSliders(dom_target, filters, data_form) { 42 | var form = document.getElementById(dom_target); 43 | if (form) { 44 | filters.forEach(item => { 45 | addSlider(item.field, form, item.min, item.max, item.value, item.step, item.label, item.callback, item.init || null); 46 | data_form['pjs_'+item.field] = item.value; 47 | }); 48 | } else { 49 | console.error('Dom item not found on ID : '+dom_target); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /jstools/colorPicker.js: -------------------------------------------------------------------------------- 1 | 2 | function colorPicker(fieldname, domtarget, value, label, callback ) { 3 | 4 | var xtarget = document.getElementById(domtarget); 5 | if (xtarget == undefined) { 6 | console.warn('Dom item not found for id :'+domtarget); 7 | return; 8 | } 9 | 10 | function unhex(hex) { 11 | return parseInt("0x" + hex, 16); 12 | } 13 | 14 | function convColor(color) { 15 | let col = String(color).replace('#', ''); 16 | let formcolor = {}; 17 | formcolor.rouge = unhex(col.substr(0,2)); 18 | formcolor.vert = unhex(col.substr(2,2)); 19 | formcolor.bleu = unhex(col.substr(4,2)); 20 | return formcolor; 21 | } 22 | 23 | let xlabel = document.createElement('label'); 24 | xlabel.innerHTML = label + ' : '; 25 | 26 | let xinput = document.createElement('input'); 27 | xinput.setAttribute('type', 'color'); 28 | xinput.setAttribute('id', 'pjs_'+fieldname); 29 | xinput.value = value; 30 | xlabel.append(xinput); 31 | xtarget.append(xlabel); 32 | 33 | let rgb = convColor(value); 34 | callback(rgb); 35 | 36 | xinput.addEventListener('change', function(evt) { 37 | let rgb = convColor(this.value); 38 | callback(rgb); 39 | }, false); 40 | } 41 | -------------------------------------------------------------------------------- /jstools/quaternion.js: -------------------------------------------------------------------------------- 1 | class Quaternion { 2 | constructor() { 3 | this.w = 1.0; 4 | this.x = 0.0; 5 | this.y = 0.0; 6 | this.z = 0.0; 7 | this.epsilon = 0.0001; 8 | } 9 | mult( b ) { // void mult( Quaternion b ) 10 | let res = new Quaternion(); 11 | res.w = this.w * b.w - this.x * b.x - this.y * b.y - this.z * b.z; 12 | res.x = this.w * b.x + this.x * b.w + this.y * b.z - this.z * b.y; 13 | res.y = this.w * b.y - this.x * b.z + this.y * b.w + this.z * b.x; 14 | res.z = this.w * b.z + this.x * b.y - this.y * b.x + this.z * b.w; 15 | this.setQuaternion( res ); 16 | } 17 | setCrossDot( cross, dot ) { // void set( PVector cross, float dot ) 18 | this.x = cross.x; 19 | this.y = cross.y; 20 | this.z = cross.z; 21 | this.w = dot; 22 | } 23 | setQuaternion( ref ) { // void set( Quaternion ref ) 24 | this.w = ref.w; 25 | this.x = ref.x; 26 | this.y = ref.y; 27 | this.z = ref.z; 28 | } 29 | matrix() { // float[] matrix() 30 | let res = []; 31 | let sa = Math.sqrt(1.0 - this.w * this.w); 32 | if (sa < this.epsilon) { 33 | sa = 1.0; 34 | } 35 | res[0] = Math.acos(this.w) * 2.0; 36 | res[1] = this.x / sa; 37 | res[2] = this.y / sa; 38 | res[3] = this.z / sa; 39 | return res; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /screenshots/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/default.png -------------------------------------------------------------------------------- /screenshots/scr0001.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0001.PNG -------------------------------------------------------------------------------- /screenshots/scr0002.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0002.PNG -------------------------------------------------------------------------------- /screenshots/scr0003.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0003.PNG -------------------------------------------------------------------------------- /screenshots/scr0004.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0004.PNG -------------------------------------------------------------------------------- /screenshots/scr0005.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0005.PNG -------------------------------------------------------------------------------- /screenshots/scr0006.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0006.PNG -------------------------------------------------------------------------------- /screenshots/scr0007.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0007.PNG -------------------------------------------------------------------------------- /screenshots/scr0008.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0008.PNG -------------------------------------------------------------------------------- /screenshots/scr0009.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0009.PNG -------------------------------------------------------------------------------- /screenshots/scr0010.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0010.PNG -------------------------------------------------------------------------------- /screenshots/scr0011.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0011.PNG -------------------------------------------------------------------------------- /screenshots/scr0012.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0012.PNG -------------------------------------------------------------------------------- /screenshots/scr0013.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0013.PNG -------------------------------------------------------------------------------- /screenshots/scr0014.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0014.PNG -------------------------------------------------------------------------------- /screenshots/scr0015.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0015.PNG -------------------------------------------------------------------------------- /screenshots/scr0016.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0016.PNG -------------------------------------------------------------------------------- /screenshots/scr0017.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0017.PNG -------------------------------------------------------------------------------- /screenshots/scr0018.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0018.PNG -------------------------------------------------------------------------------- /screenshots/scr0019.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0019.PNG -------------------------------------------------------------------------------- /screenshots/scr0020.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0020.PNG -------------------------------------------------------------------------------- /screenshots/scr0021.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0021.PNG -------------------------------------------------------------------------------- /screenshots/scr0022.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0022.PNG -------------------------------------------------------------------------------- /screenshots/scr0023.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0023.PNG -------------------------------------------------------------------------------- /screenshots/scr0024.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0024.PNG -------------------------------------------------------------------------------- /screenshots/scr0025.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0025.PNG -------------------------------------------------------------------------------- /screenshots/scr0026.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0026.PNG -------------------------------------------------------------------------------- /screenshots/scr0027.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0027.PNG -------------------------------------------------------------------------------- /screenshots/scr0028.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0028.PNG -------------------------------------------------------------------------------- /screenshots/scr0029.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0029.PNG -------------------------------------------------------------------------------- /screenshots/scr0030.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0030.PNG -------------------------------------------------------------------------------- /screenshots/scr0031.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0031.PNG -------------------------------------------------------------------------------- /screenshots/scr0032.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0032.PNG -------------------------------------------------------------------------------- /screenshots/scr0033.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gregja/zdogXperiments/5ad387e9c55fc6a433ac6b74a1ce0d01db545089/screenshots/scr0033.PNG -------------------------------------------------------------------------------- /sources/zdog_8cubes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - 8 cubes linked 6 | 25 | 26 | 27 |
28 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

29 | 30 |
31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /sources/zdog_8cubes.js: -------------------------------------------------------------------------------- 1 | // Made with Zdog 2 | // https://codepen.io/gregja/pen/2b14a173072a742e2e259f65bd0c7cc6 3 | 4 | let illo = new Zdog.Illustration({ 5 | element: '.zdog-canvas', 6 | dragRotate: true, 7 | }); 8 | 9 | let side = 40; 10 | let dist = 50; 11 | let mid_side = side / 2; 12 | let global_dist = dist * 2; 13 | let isSpinning = true; 14 | 15 | let boxes = []; 16 | boxes.push({x: -dist, y: -dist, z: -dist}); 17 | boxes.push({x: dist, y: dist, z: dist}); 18 | boxes.push({x: -dist, y: dist, z: dist}); 19 | boxes.push({x: dist, y: -dist, z: dist}); 20 | boxes.push({x: dist, y: dist, z: -dist}); 21 | boxes.push({x: -dist, y: -dist, z: dist}); 22 | boxes.push({x: -dist, y: dist, z: -dist}); 23 | boxes.push({x: dist, y: -dist, z: -dist}); 24 | 25 | const distance = (a, b) => { 26 | let dx = b.x - a.x; 27 | let dy = b.y - a.y; 28 | let dz = b.z - a.z; 29 | return Math.sqrt(dx * dx + dy * dy + dz * dz); 30 | } 31 | 32 | let links = []; 33 | let deja_vu = []; 34 | 35 | const search_deja_vu = (idx1, idx2) => { 36 | let criteria = String(idx1) + '-' + String(idx2); 37 | let found = deja_vu.find(function (element) { 38 | return element == criteria; 39 | }); 40 | if (!found) { 41 | criteria = String(idx2) + '-' + String(idx1); 42 | found = deja_vu.find(function (element) { 43 | return element == criteria; 44 | }); 45 | } 46 | return found; 47 | } 48 | 49 | // find dynamically the links between the wedges 50 | boxes.forEach((item1, idx1) => { 51 | boxes.forEach((item2, idx2) => { 52 | if (idx1 != idx2) { 53 | if (!search_deja_vu(idx1, idx2)) { 54 | let xdist = distance(item2, item1); 55 | if (xdist == global_dist) { 56 | links.push({a: idx1, b: idx2}); 57 | deja_vu.push(String(idx1) + '-' + String(idx2)); 58 | deja_vu.push(String(idx2) + '-' + String(idx1)); 59 | } 60 | } 61 | } 62 | }); 63 | }); 64 | 65 | links.forEach(item => { 66 | let a = boxes[item.a]; 67 | let b = boxes[item.b]; 68 | 69 | new Zdog.Shape({ 70 | addTo: illo, 71 | path: [ 72 | {x: a.x, y: a.y, z: a.z}, // start 73 | {x: b.x, y: b.y, z: b.z} // end 74 | ], 75 | closed: false, 76 | stroke: 10, 77 | color: '#636' 78 | }); 79 | 80 | }); 81 | 82 | boxes.forEach(item => { 83 | new Zdog.Box({ 84 | addTo: illo, 85 | width: side, 86 | height: side, 87 | depth: side, 88 | translate: item, 89 | stroke: false, 90 | color: '#C25', // default face color 91 | leftFace: '#EA0', 92 | rightFace: '#E62', 93 | topFace: '#ED0', 94 | bottomFace: '#636', 95 | }); 96 | }); 97 | 98 | function draw() { 99 | if (isSpinning) { 100 | illo.rotate.z += 0.003; 101 | } 102 | illo.updateRenderGraph(); 103 | } 104 | 105 | function animate() { 106 | draw(); 107 | requestAnimationFrame(animate); 108 | } 109 | 110 | function resetScale() { 111 | illo.scale.x = 1; 112 | illo.scale.y = 1; 113 | illo.scale.z = 1; 114 | } 115 | 116 | function keyPressed(e) { 117 | 118 | // Documentation about keyboard events : 119 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 120 | const DOWN_ARROW = 40; 121 | const LEFT_ARROW = 37; 122 | const RIGHT_ARROW = 39; 123 | const UP_ARROW = 38; 124 | //const BACKSPACE = 8; 125 | const ESCAPE = 27; 126 | 127 | switch (e.keyCode) { 128 | case ESCAPE: { 129 | resetScale(); 130 | break; 131 | } 132 | case LEFT_ARROW: { 133 | illo.scale.z += 0.3; 134 | break; 135 | } 136 | case RIGHT_ARROW: { 137 | illo.scale.z -= 0.3; 138 | break; 139 | } 140 | case UP_ARROW: { 141 | illo.scale.x += 0.3; 142 | illo.scale.y += 0.3; 143 | illo.scale.z += 0.3; 144 | break; 145 | } 146 | case DOWN_ARROW: { 147 | illo.scale.x -= 0.3; 148 | illo.scale.y -= 0.3; 149 | illo.scale.z -= 0.3; 150 | break; 151 | } 152 | 153 | } 154 | } 155 | 156 | 157 | document.addEventListener('keydown', keyPressed, false); 158 | //document.addEventListener('keyup', keyReleased, false); 159 | 160 | document.addEventListener("DOMContentLoaded", function (event) { 161 | console.log("DOM fully loaded and parsed"); 162 | animate(); 163 | }); 164 | -------------------------------------------------------------------------------- /sources/zdog_8cubes_click.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - 8 cubes clickable 6 | 26 | 27 | 28 |
29 |

This example shows how to set a clickable list of items in Zdog

30 |

To do this, draw 2 canvas, the second is the "ghost" of the first.
Each shape in the ghost has a unique color which enables to detect which shape has been clicked.
31 | Because I don't know - for the moment - how to synchronize the draggable mode between the vibible canvas and his ghost, I deactivated the draggable mode.
32 | It's experimental but it works fine on Chrome and Firefox

33 | 34 | 35 | 36 |

Click on cubes and cylinders + Arrow keys to zoom (or Escape to reset)

37 |
38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /sources/zdog_animals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 3D animals animated with Zdog 6 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

36 | 37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /sources/zdog_boxman.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Boxman 6 | 25 | 26 | 27 |
28 | 29 |

Click & drag to rotate + Arrow keys to change scale (or Escape to reset)

30 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /sources/zdog_calabiyau.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Calabi-Yau 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 |

33 |
35 |
37 | 39 | 40 |

Click & drag to rotate + Arrow keys to change scale (or Escape to reset)

41 | 42 | 43 |

44 | Variété de Calabi-Yau sur Wikipedia (french)
45 | Calabi-Yau manifold on Wikipedia (english)
46 | The tutorial I used and adapted to Zdog 47 |

48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /sources/zdog_csg1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Constructive Solid Geometry (CSG) 6 | 25 | 26 | 27 |
28 |
Constructive Solid Geometry (CSG) with the CSG component of OpenJSCAD

29 | 30 | 31 | 32 |

33 | 		 

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sources/zdog_csg2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Constructive Solid Geometry (CSG) 6 | 29 | 30 | 31 |
32 |
Constructive Solid Geometry (CSG) with the CSG component of OpenJSCAD
34 |
35 | 36 | 37 | 38 |
39 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

40 |
41 |
Parameters:
42 | 43 |
44 | 45 |
46 | 47 | 48 |
49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /sources/zdog_csg3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Constructive Solid Geometry (CSG) 6 | 25 | 26 | 27 |
28 |
Constructive Solid Geometry (CSG) with the CSG component of OpenJSCAD

29 | 30 | 31 | 32 |
33 |
34 |
35 | 36 |

37 | 38 |

39 | 40 | 41 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

42 | 43 | 44 |

Documentations : joostn.github.io/OpenJsCad, 45 |  evanw.github.io/csg.js, 46 |  OpenJSCAD wikibook

47 |
48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /sources/zdog_cube.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Shape Cube with Zdog 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

32 | 33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zdog_cuboid_delaunay.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cuboid with Delaunay Triangulation 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /sources/zdog_flake.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Menger Sponge Fractal Generator with Zdog 6 | 25 | 26 | 27 |
28 | 29 | 30 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sources/zdog_flake.js: -------------------------------------------------------------------------------- 1 | 2 | { 3 | var generateShape = shapes3dToolbox.flakeGenerator; 4 | var illo = undefined; // pointer to the main object (for refreshing) 5 | var list_levels = ['1', '2', '3', '4']; 6 | var level_value = list_levels[0]; 7 | var spin_modes = ['Spinning', 'Static']; 8 | var spin_mode_default = spin_modes[0]; 9 | var isSpinning = true; 10 | var tasks = []; 11 | 12 | let blocks_array = []; 13 | let block_current = -999; 14 | let block_maximum = -999; 15 | 16 | var levelselector = document.getElementById("levelselector"); 17 | if (levelselector) { 18 | list_levels.forEach(item => { 19 | let option = document.createElement('option'); 20 | option.setAttribute('value', item); 21 | option.innerHTML = item; 22 | levelselector.append(option); 23 | }); 24 | 25 | levelselector.blur(); 26 | levelselector.addEventListener('change', function(evt) { 27 | evt.preventDefault(); 28 | this.blur(); 29 | level_value = this.value; 30 | generateGraph(); 31 | 32 | }, false); 33 | } else { 34 | console.warn('level selector not found'); 35 | } 36 | 37 | illo = new Zdog.Illustration({ 38 | element: '.zdog-canvas', 39 | dragRotate: true, 40 | // pause spinning while dragging 41 | //onDragStart: () => isSpinning = false, 42 | //onDragEnd: () => isSpinning = true 43 | }); 44 | 45 | let shapemaster = function (block, num_task) { 46 | if (num_task !== false) { 47 | tasks[num_task] = false; // flag to know that the task is ended 48 | } 49 | new Zdog.Box({ 50 | addTo: illo, 51 | width: block.side, 52 | height: block.side, 53 | depth: block.side, 54 | translate: {x: block.x, y: block.y, z: block.z}, 55 | stroke: block.stroke, 56 | color: block.color, // default face color 57 | leftFace: block.leftFace, 58 | rightFace: block.rightFace, 59 | topFace: block.topFace, 60 | bottomFace: block.bottomFace, 61 | }); 62 | }; 63 | 64 | function generateGraph() { 65 | illo.children = []; // drop all children before regeneration 66 | 67 | let maxLevel = Number(level_value); 68 | if (maxLevel > 2) { 69 | if (isSpinning) { 70 | spin_mode_btn.click(); 71 | } 72 | } 73 | var shape_params = {x:0, y:0, z:0, r:250, level:1, maxLevel: maxLevel}; 74 | var blocks = generateShape(shape_params); 75 | let imax = blocks.length; 76 | console.log('Number of blocks to generate : '+imax); 77 | 78 | if (tasks.length > 0) { 79 | // stop remanining tasks before initializing a new series of tasks 80 | tasks.forEach(task => { 81 | if (task != false) { 82 | clearTimeout(task); 83 | } 84 | }); 85 | tasks = []; 86 | } 87 | 88 | blocks_array = []; 89 | block_current = -999; 90 | block_maximum = -999; 91 | 92 | if (maxLevel < 3) { 93 | let timer = 1; 94 | if (maxLevel == 2) { 95 | timer = 100; 96 | } 97 | for (let i = 0; i < imax; i++) { 98 | let block = blocks[i]; 99 | tasks[i] = setTimeout(() => { 100 | shapemaster(block, i); 101 | }, timer); 102 | } 103 | } else { 104 | block_current = -1; 105 | for (let i = 0; i < imax; i++) { 106 | blocks_array[i] = blocks[i]; 107 | } 108 | block_maximum = imax; 109 | } 110 | } 111 | 112 | generateGraph(); 113 | 114 | function draw (){ 115 | if (isSpinning) { 116 | illo.rotate.z += 0.003; 117 | } 118 | illo.updateRenderGraph(); 119 | } 120 | 121 | function animate() { 122 | 123 | if (block_current != -999) { 124 | block_current++; 125 | if (block_current < block_maximum) { 126 | let block = blocks_array[block_current]; 127 | shapemaster(block, false); 128 | } 129 | } 130 | 131 | draw(); 132 | requestAnimationFrame( animate ); 133 | } 134 | 135 | function resetScale() { 136 | illo.scale.x = 1; 137 | illo.scale.y = 1; 138 | illo.scale.z = 1; 139 | } 140 | 141 | function keyPressed (e) { 142 | 143 | // Documentation about keyboard events : 144 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 145 | const DOWN_ARROW = 40; 146 | const LEFT_ARROW = 37; 147 | const RIGHT_ARROW = 39; 148 | const UP_ARROW = 38; 149 | //const BACKSPACE = 8; 150 | const ESCAPE = 27; 151 | //const KEY_ONE = 49; 152 | //const KEY_TWO = 50; 153 | //const KEY_THREE = 51; 154 | //const KEY_FOUR = 52; 155 | //const KEY_FIVE = 53; 156 | 157 | switch (e.keyCode) { 158 | case ESCAPE:{ 159 | resetScale(); 160 | break; 161 | } 162 | case LEFT_ARROW:{ 163 | illo.scale.z += 0.3; 164 | break; 165 | } 166 | case RIGHT_ARROW:{ 167 | illo.scale.z -= 0.3; 168 | break; 169 | } 170 | case UP_ARROW:{ 171 | illo.scale.x += 0.3; 172 | illo.scale.y += 0.3; 173 | illo.scale.z += 0.3; 174 | break; 175 | } 176 | case DOWN_ARROW:{ 177 | illo.scale.x -= 0.3; 178 | illo.scale.y -= 0.3; 179 | illo.scale.z -= 0.3; 180 | break; 181 | } 182 | 183 | } 184 | } 185 | 186 | var spin_mode_btn = document.getElementById('spinning'); 187 | if (spin_mode_btn) { 188 | spin_mode_btn.innerHTML = spin_modes[1]; 189 | spin_mode_btn.addEventListener('click', function(evt) { 190 | evt.preventDefault(); 191 | let other_mode; 192 | if (spin_mode_default == spin_modes[0]) { 193 | spin_mode_default = spin_modes[1]; 194 | other_mode = spin_modes[0]; 195 | isSpinning = false; 196 | } else { 197 | spin_mode_default = spin_modes[0]; 198 | other_mode = spin_modes[1]; 199 | isSpinning = true; 200 | } 201 | spin_mode_btn.innerHTML = other_mode; 202 | }, false); 203 | } else { 204 | console.warn('spin mode button not found'); 205 | } 206 | 207 | document.addEventListener('keydown', keyPressed, false); 208 | //document.addEventListener('keyup', keyReleased, false); 209 | 210 | document.addEventListener("DOMContentLoaded", function(event) { 211 | console.log("DOM fully loaded and parsed"); 212 | animate(); 213 | }); 214 | 215 | } 216 | -------------------------------------------------------------------------------- /sources/zdog_leap_v1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leap Motion with Zdog - draw hands 6 | 25 | 26 | 27 |
28 |

Plug your Leap Motion and play with your hands

29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /sources/zdog_leap_v1.js: -------------------------------------------------------------------------------- 1 | // link to the official gallery : 2 | // https://developer-archive.leapmotion.com/gallery/tags/javascript 3 | 4 | // link to install a leap motion on Linux Fedora : 5 | // https://github.com/bugzy/leap-fedora-rpm 6 | 7 | // a good tutorial on the Leap Motion (in french): 8 | // https://slides.jmpp.io/leapjs/#/ 9 | 10 | // Link to the official documentation 11 | // https://developer-archive.leapmotion.com/documentation/javascript/api/Leap.InteractionBox.html?proglang=javascript 12 | 13 | { 14 | "use strict"; 15 | 16 | let canvas = document.getElementById('zdog-canvas'); 17 | 18 | const width = canvas.width; 19 | const height = canvas.height; 20 | 21 | let illo = new Zdog.Illustration({ 22 | element: canvas, 23 | dragRotate: true, 24 | // translate:{x:-width/2, y:-height/2}, // not apply translation here, because we need to know the version of the leap controller 25 | }); 26 | 27 | const size_palm = 30; 28 | const size_finger = 20; 29 | const size_bone = 10; 30 | const size_inch = 15; 31 | 32 | var boxes = []; 33 | var illo_translate = true; // flag to apply the translation on illo only once 34 | 35 | function getCoords(leapPoint, frame) { 36 | let mult = 0; 37 | if (frame.hasOwnProperty('interactionBox')) { 38 | // for older version of the leap motion controller 39 | let iBox = frame.interactionBox; 40 | let normalizedPoint = iBox.normalizePoint(leapPoint, true); 41 | mult = 1000; 42 | return { 43 | x: normalizedPoint[0] * mult, 44 | y: (1 - normalizedPoint[1]) * mult, 45 | z: normalizedPoint[2] * mult 46 | }; 47 | } else { 48 | // for lastest version of the leap motion controller 49 | mult = 3; 50 | return { 51 | x: leapPoint[0] * mult, 52 | y: -leapPoint[1] * mult, 53 | z: leapPoint[2] * mult 54 | }; 55 | } 56 | } 57 | 58 | function generateBox(digits, x, y, z, width, height, depth) { 59 | digits.push({width: width, height: height, depth: depth, coords: {x: x, y: y, z: z}}); 60 | } 61 | 62 | function leapmotion() { 63 | 64 | const controller = new Leap.Controller(); 65 | controller.connect(); 66 | 67 | controller.on('frame', (frame) => { 68 | 69 | if (illo_translate) { 70 | // apply the translation once only 71 | illo_translate = false; 72 | if (frame.hasOwnProperty('interactionBox')) { 73 | // for older version of the leap motion controller 74 | illo.translate = { 75 | x:(-width / 2), y:(-height / 2) 76 | } 77 | } else { 78 | // for lastest version of the leap motion controller 79 | illo.translate = { 80 | x:(width / 10) , y:(height / 2) 81 | } 82 | } 83 | } 84 | 85 | let digits = []; 86 | 87 | // for each hand 88 | frame.hands.forEach(hand => { 89 | 90 | // for drawing the palm 91 | var palmPos = getCoords(hand.palmPosition, frame); 92 | generateBox(digits, palmPos.x, palmPos.y, palmPos.z, size_palm, size_palm, size_palm); 93 | 94 | // For each finger 95 | hand.fingers.forEach((finger, id) => { 96 | /* 97 | for( var j = 0, jmax=finger.bones.length; j < jmax; j++ ){ 98 | let bone = finger.bones[j]; 99 | 100 | let pos = getCoords(bone.center(), frame); 101 | generateBox(digits, pos.x, pos.y, pos.z, size_bone, size_bone, size_bone); 102 | } 103 | */ 104 | let size_item = size_bone; 105 | if (id == 0) { 106 | size_item = size_inch; 107 | } 108 | var carpPos = getCoords(finger.carpPosition, frame); // carpal 109 | generateBox(digits, carpPos.x, carpPos.y, carpPos.z, size_finger, size_finger, size_finger); 110 | 111 | var mcpPos = getCoords(finger.mcpPosition, frame); // metacarpal 112 | generateBox(digits, mcpPos.x, mcpPos.y, mcpPos.z, size_item, size_item, size_item); 113 | 114 | var pipPos = getCoords(finger.pipPosition, frame); // proximal 115 | generateBox(digits, pipPos.x, pipPos.y, pipPos.z, size_item, size_item, size_item); 116 | 117 | var dipPos = getCoords(finger.dipPosition, frame); // intermediate phalange 118 | generateBox(digits, dipPos.x, dipPos.y, dipPos.z, size_item, size_item, size_item); 119 | 120 | var tipPos = getCoords(finger.tipPosition, frame); // distal phalange 121 | generateBox(digits, tipPos.x, tipPos.y, tipPos.z, size_item, size_item, size_item); 122 | 123 | }); 124 | 125 | }); 126 | boxes.push(digits); 127 | 128 | }); 129 | 130 | } 131 | 132 | function draw() { 133 | 134 | let digits = []; 135 | if (boxes.length > 1) { 136 | digits = boxes.shift(); 137 | } else { 138 | if (boxes.length == 1) { 139 | digits = boxes[0]; 140 | } else { 141 | digits = []; 142 | } 143 | } 144 | 145 | illo.children = []; 146 | 147 | digits.forEach(item => { 148 | new Zdog.Box({ 149 | addTo: illo, 150 | width: item.width, 151 | height: item.height, 152 | depth: item.depth, 153 | translate: item.coords, 154 | rotate: {x: 0.7, y: 0.7}, 155 | stroke: false, 156 | color: '#C25', // default face color 157 | leftFace: '#EA0', 158 | rightFace: '#E62', 159 | topFace: '#ED0', 160 | bottomFace: '#636', 161 | }); 162 | }); 163 | 164 | illo.updateRenderGraph(); 165 | } 166 | 167 | function animate() { 168 | draw(); 169 | requestAnimationFrame(animate); 170 | } 171 | 172 | document.addEventListener("DOMContentLoaded", function (event) { 173 | console.log("DOM fully loaded and parsed"); 174 | leapmotion(); 175 | animate(); 176 | }); 177 | } 178 | -------------------------------------------------------------------------------- /sources/zdog_leap_v2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leap Motion with Zdog - draw hands 6 | 25 | 26 | 27 |
28 |

Plug your Leap Motion and play with your hands

29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /sources/zdog_leap_v2.js: -------------------------------------------------------------------------------- 1 | // link to the official gallery : 2 | // https://developer-archive.leapmotion.com/gallery/tags/javascript 3 | 4 | // link to install a leap motion on Linux Fedora : 5 | // https://github.com/bugzy/leap-fedora-rpm 6 | 7 | // a good tutorial on the Leap Motion (in french): 8 | // https://slides.jmpp.io/leapjs/#/ 9 | 10 | // Link to the official documentation 11 | // https://developer-archive.leapmotion.com/documentation/javascript/api/Leap.InteractionBox.html?proglang=javascript 12 | 13 | { 14 | "use strict"; 15 | 16 | let canvas = document.getElementById('zdog-canvas'); 17 | 18 | const width = canvas.width; 19 | const height = canvas.height; 20 | 21 | let illo = new Zdog.Illustration({ 22 | element: canvas, 23 | dragRotate: true, 24 | // translate:{x:-width/2, y:-height/2}, // not apply translation here, because we need to know the version of the leap controller 25 | }); 26 | 27 | const size_palm = 30; 28 | const size_finger = 20; 29 | const size_bone = 10; 30 | const size_inch = 15; 31 | 32 | var boxes = []; 33 | var illo_translate = true; // flag to apply the translation on illo only once 34 | 35 | function getCoords(leapPoint, frame) { 36 | let mult = 0; 37 | if (frame.hasOwnProperty('interactionBox')) { 38 | // for older version of the leap motion controller 39 | let iBox = frame.interactionBox; 40 | let normalizedPoint = iBox.normalizePoint(leapPoint, true); 41 | mult = 1000; 42 | return { 43 | x: normalizedPoint[0] * mult, 44 | y: (1 - normalizedPoint[1]) * mult, 45 | z: normalizedPoint[2] * mult 46 | }; 47 | } else { 48 | // for lastest version of the leap motion controller 49 | mult = 3; 50 | return { 51 | x: leapPoint[0] * mult, 52 | y: -leapPoint[1] * mult, 53 | z: leapPoint[2] * mult 54 | }; 55 | } 56 | } 57 | 58 | function generateBox(digits, x, y, z, width, height, depth) { 59 | digits.push({width: width, height: height, depth: depth, coords: {x: x, y: y, z: z}}); 60 | } 61 | 62 | function leapmotion() { 63 | 64 | const controller = new Leap.Controller(); 65 | controller.connect(); 66 | 67 | controller.on('frame', (frame) => { 68 | 69 | if (illo_translate) { 70 | // apply the translation once only 71 | illo_translate = false; 72 | if (frame.hasOwnProperty('interactionBox')) { 73 | // for older version of the leap motion controller 74 | illo.translate = { 75 | x:(-width / 2), y:(-height / 2) 76 | } 77 | } else { 78 | // for lastest version of the leap motion controller 79 | illo.translate = { 80 | x:(width / 10) , y:(height / 2) 81 | } 82 | } 83 | } 84 | 85 | let digits = []; 86 | 87 | // for each hand 88 | frame.hands.forEach(hand => { 89 | 90 | // for drawing the palm 91 | var palmPos = getCoords(hand.palmPosition, frame); 92 | generateBox(digits, palmPos.x, palmPos.y, palmPos.z, size_palm, size_palm, size_palm); 93 | 94 | // For each finger 95 | hand.fingers.forEach((finger, id) => { 96 | /* 97 | for( var j = 0, jmax=finger.bones.length; j < jmax; j++ ){ 98 | let bone = finger.bones[j]; 99 | 100 | let pos = getCoords(bone.center(), frame); 101 | generateBox(digits, pos.x, pos.y, pos.z, size_bone, size_bone, size_bone); 102 | } 103 | */ 104 | let size_item = size_bone; 105 | if (id == 0) { 106 | size_item = size_inch; 107 | } 108 | var carpPos = getCoords(finger.carpPosition, frame); // carpal 109 | generateBox(digits, carpPos.x, carpPos.y, carpPos.z, size_finger, size_finger, size_finger); 110 | 111 | var mcpPos = getCoords(finger.mcpPosition, frame); // metacarpal 112 | generateBox(digits, mcpPos.x, mcpPos.y, mcpPos.z, size_item, size_item, size_item); 113 | 114 | var pipPos = getCoords(finger.pipPosition, frame); // proximal 115 | generateBox(digits, pipPos.x, pipPos.y, pipPos.z, size_item, size_item, size_item); 116 | 117 | var dipPos = getCoords(finger.dipPosition, frame); // intermediate phalange 118 | generateBox(digits, dipPos.x, dipPos.y, dipPos.z, size_item, size_item, size_item); 119 | 120 | var tipPos = getCoords(finger.tipPosition, frame); // distal phalange 121 | generateBox(digits, tipPos.x, tipPos.y, tipPos.z, size_item, size_item, size_item); 122 | 123 | }); 124 | 125 | }); 126 | boxes.push(digits); 127 | 128 | }); 129 | 130 | } 131 | 132 | function draw() { 133 | 134 | let digits = []; 135 | if (boxes.length > 1) { 136 | digits = boxes.shift(); 137 | } else { 138 | if (boxes.length == 1) { 139 | digits = boxes[0]; 140 | } else { 141 | digits = []; 142 | } 143 | } 144 | 145 | illo.children = []; 146 | 147 | digits.forEach(item => { 148 | new Zdog.Box({ 149 | addTo: illo, 150 | width: item.width, 151 | height: item.height, 152 | depth: item.depth, 153 | translate: item.coords, 154 | rotate: {x: 0.7, y: 0.7}, 155 | stroke: false, 156 | color: '#C25', // default face color 157 | leftFace: '#EA0', 158 | rightFace: '#E62', 159 | topFace: '#ED0', 160 | bottomFace: '#636', 161 | }); 162 | }); 163 | 164 | illo.updateRenderGraph(); 165 | } 166 | 167 | function animate() { 168 | draw(); 169 | requestAnimationFrame(animate); 170 | } 171 | 172 | document.addEventListener("DOMContentLoaded", function (event) { 173 | console.log("DOM fully loaded and parsed"); 174 | leapmotion(); 175 | animate(); 176 | }); 177 | } 178 | -------------------------------------------------------------------------------- /sources/zdog_magnetcubes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Magnetic cubes 6 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /sources/zdog_magnetcubes.js: -------------------------------------------------------------------------------- 1 | // Made with Zdog 2 | 3 | { 4 | "use strict"; 5 | 6 | let canvas = document.getElementById('zdog-canvas'); 7 | let width = canvas.width; 8 | let height = canvas.height; 9 | 10 | let illo = new Zdog.Illustration({ 11 | element: canvas, 12 | dragRotate: true, 13 | translate:{x:-width/2, y:-height/2}, 14 | // rotate:{y:100, z:100} 15 | }); 16 | 17 | var side = 40; 18 | var dist = 50; 19 | var mid_side = side / 2; 20 | var global_dist = dist * 2; 21 | var isSpinning = false; 22 | 23 | 24 | const getMousePos = function (canvas, evt) { 25 | // It's a very reliable algorithm to get mouse coordinates (don't use anything else) 26 | // it works fine on Firefox and Chrome 27 | // source : https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas 28 | var rect = canvas.getBoundingClientRect(); 29 | return { 30 | x: (evt.clientX - rect.left) / (rect.right - rect.left) * canvas.width, 31 | y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * canvas.height 32 | }; 33 | } 34 | 35 | function generateGrid(xmax, ymax, space=100) { 36 | let items = []; 37 | let xbegin = space + 10; 38 | let ybegin = space + 10; 39 | for (let x=0; x { 50 | let diffX = a.x - b.x ; 51 | let diffY = a.y - b.y; 52 | return Math.atan2(diffY, diffX); 53 | } 54 | 55 | boxes.forEach(item => { 56 | item.node = new Zdog.Box({ 57 | addTo: illo, 58 | width: side, 59 | height: side, 60 | depth: side, 61 | translate: item.coords, 62 | rotate: {x: 0.7, y:0.7}, 63 | stroke: false, 64 | color: '#C25', // default face color 65 | leftFace: '#EA0', 66 | rightFace: '#E62', 67 | topFace: '#ED0', 68 | bottomFace: '#636', 69 | }); 70 | }) 71 | 72 | function draw (){ 73 | if (isSpinning) { 74 | illo.rotate.z += 0.003; 75 | } 76 | illo.updateRenderGraph(); 77 | } 78 | 79 | function animate() { 80 | draw(); 81 | requestAnimationFrame( animate ); 82 | } 83 | 84 | const PI_ON_SEMI_CIRCLE = Math.PI / 180; 85 | const SEMI_CIRCLE_ON_PI = 180 / Math.PI; 86 | 87 | const degreesToRadians = (val) => { 88 | return val * PI_ON_SEMI_CIRCLE; 89 | } 90 | 91 | const radiandToDegrees = (val) => { 92 | return val * SEMI_CIRCLE_ON_PI; 93 | } 94 | 95 | document.addEventListener('mousemove', (e) => { 96 | let mouse = getMousePos(canvas, e); 97 | mouse.z = 0; // z doesn't existe on the mouse object, we add it for comparison with the coordinates of the cubes 98 | 99 | // Effect 1 : 100 | /* 101 | boxes.forEach(sqr => { 102 | let diff = diffHypothenuse(sqr.coords, mouse); 103 | if (diff < 200) { 104 | let angle = degreesToRadians(diff / 5); 105 | sqr.node.rotate = {x: angle, y:angle}; 106 | } 107 | }) 108 | */ 109 | 110 | // Effect 2 : 111 | boxes.forEach(sqr => { 112 | let angle = diffArctangente(mouse, sqr.coords); 113 | sqr.node.rotate = {x: angle, y:angle}; 114 | }); 115 | 116 | 117 | }) 118 | 119 | document.addEventListener("DOMContentLoaded", function(event) { 120 | console.log("DOM fully loaded and parsed"); 121 | animate(); 122 | }); 123 | } 124 | -------------------------------------------------------------------------------- /sources/zdog_obj.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 3D Object with Zdog 6 | 27 | 28 | 29 |
30 |

Click & drag to rotate

31 | 32 | 33 | 34 | 35 |

Up & Down arrow keys : same zoom+/zoom- on the X, Y and Z axes
36 | Left & Right arrow keys : zoom+/zoom- on Y axes only
37 | Escape key : reset scale to 1 on the X, Y and Z axes
38 | Others 3D objects on this site 39 |

40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sources/zdog_obj.js: -------------------------------------------------------------------------------- 1 | { 2 | "use strict"; 3 | 4 | var default_color = "#000000"; // color picker : https://www.w3schools.com/colors/colors_picker.asp 5 | var fill_value = false; 6 | var stroke_value = 1; 7 | var list_shapes = ['cube', 'diamond', 'dodecahedron', 'gem', 'humanoid', 'icosahedron', 'icosphere', 8 | 'magnolia', 'shuttle', 'skyscraper', 9 | 'teapot', 'tetrahedron', 'toroid', 'torusknot', 'twistedtorus']; 10 | var spin_modes = ['Spinning', 'Static']; 11 | var spin_mode_default = spin_modes[0]; 12 | 13 | var isSpinning = true; 14 | 15 | var shape3d = shapes3dToolbox.import3dObjSync({ 16 | url: "../assets/" + list_shapes[0] + ".obj.txt", 17 | scaleTo: 200, 18 | reorder: false, 19 | center: true 20 | }); 21 | 22 | var colpicker = document.getElementById("colorpicker"); 23 | if (colpicker) { 24 | colpicker.value = default_color; 25 | colpicker.blur(); 26 | colpicker.addEventListener('change', function (evt) { 27 | evt.preventDefault(); 28 | this.blur(); 29 | default_color = this.value; 30 | mainshape.color = default_color; 31 | }, false); 32 | } else { 33 | console.warn('color picker not found'); 34 | } 35 | 36 | var objselector = document.getElementById("objselector"); 37 | if (objselector) { 38 | list_shapes.forEach(item => { 39 | let option = document.createElement('option'); 40 | option.setAttribute('value', item); 41 | option.innerHTML = item; 42 | objselector.append(option); 43 | }); 44 | objselector.value = list_shapes[0]; 45 | objselector.blur(); 46 | objselector.addEventListener('change', function (evt) { 47 | evt.preventDefault(); 48 | this.blur(); 49 | let newshape = shapes3dToolbox.import3dObjSync({ 50 | url: "../assets/" + this.value + ".obj.txt", 51 | scaleTo: 200, 52 | reorder: false, 53 | center: true 54 | }); 55 | setTimeout(function () { 56 | stroke_value = 1; 57 | mainshape.stroke = stroke_value; 58 | mainshape.path = generatePath(newshape); 59 | mainshape.updatePath(); 60 | resetScale(); 61 | }, 1000); 62 | }, false); 63 | } else { 64 | console.warn('obj selector not found'); 65 | } 66 | 67 | function resetScale() { 68 | illo.scale.x = 1; 69 | illo.scale.y = 1; 70 | illo.scale.z = 1; 71 | } 72 | 73 | function generatePath(obj3d) { 74 | var path = []; 75 | obj3d.polygons.forEach(vertices => { 76 | vertices.forEach(vertix => { 77 | if (obj3d.points[vertix]) { 78 | path.push(obj3d.points[vertix]); 79 | } 80 | }); 81 | }); 82 | return path; 83 | } 84 | 85 | var illo = new Zdog.Illustration({ 86 | element: '.zdog-canvas', 87 | dragRotate: true, 88 | // pause spinning while dragging 89 | //onDragStart: () => isSpinning = false, 90 | //onDragEnd: () => isSpinning = true 91 | }); 92 | 93 | var mainshape = new Zdog.Shape({ 94 | addTo: illo, 95 | path: generatePath(shape3d), 96 | translate: {z: 10}, 97 | color: default_color, 98 | stroke: stroke_value, 99 | closed: false, 100 | fill: fill_value, 101 | }); 102 | 103 | function draw() { 104 | if (isSpinning) { 105 | illo.rotate.x += 0.003; 106 | illo.rotate.y += 0.003; 107 | illo.rotate.z += 0.003; 108 | } 109 | illo.updateRenderGraph(); 110 | } 111 | 112 | function animate() { 113 | draw(); 114 | requestAnimationFrame(animate); 115 | } 116 | 117 | function keyPressed(e) { 118 | 119 | // Documentation about keyboard events : 120 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 121 | const DOWN_ARROW = 40; 122 | const LEFT_ARROW = 37; 123 | const RIGHT_ARROW = 39; 124 | const UP_ARROW = 38; 125 | const BACKSPACE = 8; 126 | const ESCAPE = 27; 127 | const KEY_ONE = 49; 128 | const KEY_TWO = 50; 129 | const KEY_THREE = 51; 130 | const KEY_FOUR = 52; 131 | const KEY_FIVE = 53; 132 | 133 | switch (e.keyCode) { 134 | case ESCAPE: { 135 | resetScale(); 136 | break; 137 | } 138 | case LEFT_ARROW: { 139 | illo.scale.z += 0.3; 140 | break; 141 | } 142 | case RIGHT_ARROW: { 143 | illo.scale.z -= 0.3; 144 | break; 145 | } 146 | case UP_ARROW: { 147 | illo.scale.x += 0.3; 148 | illo.scale.y += 0.3; 149 | illo.scale.z += 0.3; 150 | break; 151 | } 152 | case DOWN_ARROW: { 153 | illo.scale.x -= 0.3; 154 | illo.scale.y -= 0.3; 155 | illo.scale.z -= 0.3; 156 | break; 157 | } 158 | case KEY_ONE: { 159 | stroke_value = 1; 160 | mainshape.stroke = stroke_value; 161 | break; 162 | } 163 | case KEY_TWO: { 164 | stroke_value = 2; 165 | mainshape.stroke = stroke_value; 166 | break; 167 | } 168 | case KEY_THREE: { 169 | stroke_value = 3; 170 | mainshape.stroke = stroke_value; 171 | break; 172 | } 173 | case KEY_FOUR: { 174 | stroke_value = 4; 175 | mainshape.stroke = stroke_value; 176 | break; 177 | } 178 | case KEY_FIVE: { 179 | stroke_value = 5; 180 | mainshape.stroke = stroke_value; 181 | break; 182 | } 183 | 184 | } 185 | } 186 | 187 | var fill_switcher = document.getElementById('fill_switcher'); 188 | if (fill_switcher) { 189 | if (fill_value) { 190 | fill_switcher.innerHTML = 'Filling Off'; 191 | } else { 192 | fill_switcher.innerHTML = 'Filling On'; 193 | } 194 | fill_switcher.addEventListener('click', function (evt) { 195 | fill_value = !fill_value; 196 | if (fill_value) { 197 | fill_switcher.innerHTML = 'Filling Off'; 198 | } else { 199 | fill_switcher.innerHTML = 'Filling On'; 200 | } 201 | mainshape.fill = fill_value; 202 | }, false); 203 | } else { 204 | console.warn('fill switcher not found'); 205 | } 206 | 207 | var spin_mode_btn = document.getElementById('spinning'); 208 | if (spin_mode_btn) { 209 | spin_mode_btn.innerHTML = spin_modes[1]; 210 | spin_mode_btn.addEventListener('click', function (evt) { 211 | evt.preventDefault(); 212 | let other_mode; 213 | if (spin_mode_default == spin_modes[0]) { 214 | spin_mode_default = spin_modes[1]; 215 | other_mode = spin_modes[0]; 216 | isSpinning = false; 217 | } else { 218 | spin_mode_default = spin_modes[0]; 219 | other_mode = spin_modes[1]; 220 | isSpinning = true; 221 | } 222 | spin_mode_btn.innerHTML = other_mode; 223 | generateGraph(); 224 | }, false); 225 | } else { 226 | console.warn('spin mode button not found'); 227 | } 228 | 229 | document.addEventListener('keydown', keyPressed, false); 230 | //document.addEventListener('keyup', keyReleased, false); 231 | 232 | document.addEventListener("DOMContentLoaded", function (event) { 233 | console.log("DOM fully loaded and parsed"); 234 | animate(); 235 | }); 236 | 237 | } 238 | -------------------------------------------------------------------------------- /sources/zdog_obj_v2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 3D Object with Zdog 6 | 27 | 28 | 29 |
30 |

Click & drag to rotate

31 | 32 | 33 | 34 | 35 |

Up & Down arrow keys : same zoom+/zoom- on the X, Y and Z axes
36 | Left & Right arrow keys : zoom+/zoom- on Y axes only
37 | Escape key : reset scale to 1 on the X, Y and Z axes
38 | Others 3D objects on this site 39 |

40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sources/zdog_obj_v3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 3D Object with Zdog 6 | 27 | 28 | 29 |
30 |

Click & drag to rotate

31 | 32 | 33 | 34 | 35 |

Up & Down arrow keys : same zoom+/zoom- on the X, Y and Z axes
36 | Left & Right arrow keys : zoom+/zoom- on Y axes only
37 | Escape key : reset scale to 1 on the X, Y and Z axes
38 | Others 3D objects on this site 39 |

40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /sources/zdog_segment1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segments with Zdog - test 1 6 | 25 | 26 | 27 |
28 |

Segments - first test with Zdog

29 |

Click & drag to rotate

30 | 31 |

Inspired by the chapter 13 of the book : Foundation HTML5 Animation with JavaScript

32 |

No mobiles segments are drawn directly with the canvas 2D API, mobiles segments are drawn with Zdog

33 |
34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /sources/zdog_segment1.js: -------------------------------------------------------------------------------- 1 | 2 | { 3 | 4 | var isSpinning = false; 5 | 6 | var canvas = document.getElementById("zdog-canvas"); 7 | var ctx = {}; 8 | var illo = {}; 9 | 10 | 11 | function config() { 12 | illo = new Zdog.Illustration({ 13 | element: canvas, 14 | dragRotate: true, 15 | // pause spinning while dragging 16 | // onDragStart: () => isSpinning = false, 17 | // onDragEnd: () => isSpinning = true 18 | }); 19 | 20 | var segment0 = new Segment({width: 100, height: 20, color: "red", engine: "zdog", lineWidth: 2}); 21 | segment0.x = 100; 22 | segment0.y = 50; 23 | segment0.draw(illo); 24 | 25 | var segment1 = new Segment({width: 200, height: 10, color: "blue", context: illo}); 26 | segment1.x = 100; 27 | segment1.y = 80; 28 | segment1.draw(); 29 | 30 | var segment2 = new Segment({width: 80, height: 40, color: "yellow", context: illo, diameter: 5}); 31 | segment2.x = 100; 32 | segment2.y = 120; 33 | segment2.draw(); 34 | } 35 | 36 | function drawFixSegments() { 37 | var engine = "canvas"; 38 | 39 | var segment0 = new Segment({width: 100, height: 20, color: "red", engine: engine, context:context, lineWidth: 2}); 40 | segment0.x = 100; 41 | segment0.y = 50; 42 | segment0.draw(); 43 | 44 | var segment1 = new Segment({width: 200, height: 10, color: "blue", engine: engine}); 45 | segment1.x = 100; 46 | segment1.y = 80; 47 | segment1.draw(context); 48 | 49 | var segment2 = new Segment({width: 80, height: 40, color: "yellow", engine: engine, context:context, diameter: 5}); 50 | segment2.x = 100; 51 | segment2.y = 120; 52 | segment2.draw(); 53 | } 54 | 55 | function draw (){ 56 | if (isSpinning) { 57 | illo.rotate.z += 0.003; 58 | } 59 | illo.updateRenderGraph(); 60 | } 61 | 62 | function animate() { 63 | draw(); 64 | drawFixSegments(); 65 | requestAnimationFrame( animate ); 66 | } 67 | 68 | function resetScale() { 69 | illo.scale.x = 1; 70 | illo.scale.y = 1; 71 | illo.scale.z = 1; 72 | } 73 | 74 | function keyPressed (e) { 75 | 76 | // Documentation about keyboard events : 77 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 78 | const DOWN_ARROW = 40; 79 | const LEFT_ARROW = 37; 80 | const RIGHT_ARROW = 39; 81 | const UP_ARROW = 38; 82 | const BACKSPACE = 8; 83 | const ESCAPE = 27; 84 | const KEY_ONE = 49; 85 | const KEY_TWO = 50; 86 | const KEY_THREE = 51; 87 | const KEY_FOUR = 52; 88 | const KEY_FIVE = 53; 89 | 90 | switch (e.keyCode) { 91 | case ESCAPE:{ 92 | resetScale(); 93 | break; 94 | } 95 | /* 96 | case LEFT_ARROW:{ 97 | illo.scale.z += 0.3; 98 | break; 99 | } 100 | case RIGHT_ARROW:{ 101 | illo.scale.z -= 0.3; 102 | break; 103 | } 104 | */ 105 | case UP_ARROW:{ 106 | illo.scale.x += 0.3; 107 | illo.scale.y += 0.3; 108 | illo.scale.z += 0.3; 109 | break; 110 | } 111 | case DOWN_ARROW:{ 112 | illo.scale.x -= 0.3; 113 | illo.scale.y -= 0.3; 114 | illo.scale.z -= 0.3; 115 | break; 116 | } 117 | 118 | } 119 | } 120 | 121 | 122 | document.addEventListener('keydown', keyPressed, false); 123 | //document.addEventListener('keyup', keyReleased, false); 124 | 125 | document.addEventListener("DOMContentLoaded", function(event) { 126 | console.log("DOM fully loaded and parsed"); 127 | if (canvas == undefined) { 128 | console.error('DOM target not found for ID zdog-canvas'); 129 | } else { 130 | context = canvas.getContext('2d'); 131 | config(); 132 | animate(); 133 | } 134 | }); 135 | 136 | } 137 | -------------------------------------------------------------------------------- /sources/zdog_segment2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segments with Zdog - test 2 6 | 25 | 26 | 27 |
28 |

Segments - second test with Zdog

29 |

Click & drag to rotate

30 | 31 | 32 |

Inspired by the chapter 13 of the book : Foundation HTML5 Animation with JavaScript

33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zdog_segment2.js: -------------------------------------------------------------------------------- 1 | 2 | { 3 | 4 | var canvas = document.getElementById("zdog-canvas"); 5 | var ctx = {}; 6 | var illo = {}; 7 | var segment = {}; 8 | var slider = {}; 9 | 10 | const PI = Math.PI; 11 | const DEG_TO_RAD = PI / 180; 12 | const RAD_TO_DEG = 180 / PI; 13 | const degToRad = angle => angle * DEG_TO_RAD; 14 | 15 | var canvas2 = document.getElementById('canvas-slider'); 16 | var context2 = canvas2.getContext('2d'); 17 | context2.imageSmoothingEnabled = true; 18 | canvas2.setAttribute('style', 'position: absolute; left: 100px; top: 200px;'); 19 | 20 | function config() { 21 | illo = new Zdog.Illustration({ 22 | zoom: 2, 23 | element: canvas, 24 | dragRotate: true, 25 | }); 26 | 27 | segment = new Segment({width: 100, height: 20, color: "red", engine: "zdog", lineWidth: 2}); 28 | segment.x = 10; 29 | segment.y = 10; 30 | segment.draw(illo); 31 | 32 | slider = new Slider(-90, 90, 0); 33 | slider.x = 100; 34 | slider.y = 20; 35 | slider.captureMouse(canvas2); 36 | slider.onchange = function() { 37 | segment.rotation = degToRad(slider.value); 38 | illo.children = []; 39 | segment.draw(illo); 40 | }; 41 | } 42 | 43 | function drawFrame () { 44 | context2.clearRect(0, 0, canvas2.width, canvas2.height); 45 | slider.draw(context2); 46 | } 47 | 48 | function draw (){ 49 | drawFrame(); 50 | illo.updateRenderGraph(); 51 | } 52 | 53 | function animate() { 54 | draw(); 55 | requestAnimationFrame( animate ); 56 | } 57 | 58 | function resetScale() { 59 | illo.scale.x = 1; 60 | illo.scale.y = 1; 61 | illo.scale.z = 1; 62 | } 63 | 64 | function keyPressed (e) { 65 | 66 | // Documentation about keyboard events : 67 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 68 | const DOWN_ARROW = 40; 69 | const LEFT_ARROW = 37; 70 | const RIGHT_ARROW = 39; 71 | const UP_ARROW = 38; 72 | const BACKSPACE = 8; 73 | const ESCAPE = 27; 74 | const KEY_ONE = 49; 75 | const KEY_TWO = 50; 76 | const KEY_THREE = 51; 77 | const KEY_FOUR = 52; 78 | const KEY_FIVE = 53; 79 | 80 | switch (e.keyCode) { 81 | case ESCAPE:{ 82 | resetScale(); 83 | break; 84 | } 85 | /* 86 | case LEFT_ARROW:{ 87 | illo.scale.z += 0.3; 88 | break; 89 | } 90 | case RIGHT_ARROW:{ 91 | illo.scale.z -= 0.3; 92 | break; 93 | } 94 | */ 95 | case UP_ARROW:{ 96 | illo.scale.x += 0.3; 97 | illo.scale.y += 0.3; 98 | illo.scale.z += 0.3; 99 | break; 100 | } 101 | case DOWN_ARROW:{ 102 | illo.scale.x -= 0.3; 103 | illo.scale.y -= 0.3; 104 | illo.scale.z -= 0.3; 105 | break; 106 | } 107 | 108 | } 109 | } 110 | 111 | document.addEventListener('keydown', keyPressed, false); 112 | //document.addEventListener('keyup', keyReleased, false); 113 | 114 | document.addEventListener("DOMContentLoaded", function(event) { 115 | console.log("DOM fully loaded and parsed"); 116 | if (canvas == undefined) { 117 | console.error('DOM target not found for ID zdog-canvas'); 118 | } else { 119 | context = canvas.getContext('2d'); 120 | config(); 121 | animate(); 122 | } 123 | }); 124 | 125 | } 126 | -------------------------------------------------------------------------------- /sources/zdog_segment3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segments with Zdog - test 3 6 | 25 | 26 | 27 |
28 |

Segments - third test with Zdog

29 |

Click & drag to rotate

30 | 31 | 32 |

Inspired by the chapter 13 of the book : Foundation HTML5 Animation with JavaScript

33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zdog_segment3.js: -------------------------------------------------------------------------------- 1 | 2 | { 3 | 4 | var canvas = document.getElementById("zdog-canvas"); 5 | var illo = {}; 6 | var segment0 = segment1 = {}; 7 | var slider0 = slider1 = {}; 8 | var top_change = false; 9 | 10 | const PI = Math.PI; 11 | const DEG_TO_RAD = PI / 180; 12 | const RAD_TO_DEG = 180 / PI; 13 | const degToRad = angle => angle * DEG_TO_RAD; 14 | 15 | var canvas2 = document.getElementById('canvas-slider'); 16 | var context2 = canvas2.getContext('2d'); 17 | context2.imageSmoothingEnabled = true; 18 | canvas2.setAttribute('style', 'position: absolute; left: 100px; top: 200px;'); 19 | 20 | function config() { 21 | illo = new Zdog.Illustration({ 22 | zoom: 2, 23 | element: canvas, 24 | dragRotate: true, 25 | }); 26 | 27 | segment0 = new Segment({width: 100, height: 20, color: "red", lineWidth: 2}); 28 | segment0.x = -10; 29 | segment0.y = -10; 30 | segment0.draw(illo); 31 | 32 | segment1 = new Segment({width: 100, height: 20, color: "green", lineWidth: 2}); 33 | segment1.draw(illo); 34 | 35 | slider0 = new Slider(-90, 90, 0); 36 | slider0.x = 100; 37 | slider0.y = 20; 38 | slider1 = new Slider(-160, 0, 0); 39 | slider1.x = 120; 40 | slider1.y = 20; 41 | 42 | top_change = true; 43 | 44 | slider0.captureMouse(canvas2); 45 | slider0.onchange = function() { 46 | top_change = true; 47 | }; 48 | slider1.captureMouse(canvas2); 49 | slider1.onchange = function() { 50 | top_change = true; 51 | }; 52 | } 53 | 54 | function drawFrame () { 55 | context2.clearRect(0, 0, canvas2.width, canvas2.height); 56 | slider0.draw(context2); 57 | slider1.draw(context2); 58 | } 59 | 60 | function draw (){ 61 | if (top_change) { 62 | top_change = false; 63 | illo.children = []; 64 | 65 | segment0.rotation = degToRad(slider0.value); 66 | segment1.rotation = segment0.rotation + degToRad(slider1.value); 67 | segment1.x = segment0.getPin().x; 68 | segment1.y = segment0.getPin().y; 69 | 70 | segment0.draw(illo); 71 | segment1.draw(illo); 72 | } 73 | drawFrame(); 74 | illo.updateRenderGraph(); 75 | } 76 | 77 | function animate() { 78 | draw(); 79 | requestAnimationFrame( animate ); 80 | } 81 | 82 | function resetScale() { 83 | illo.scale.x = 1; 84 | illo.scale.y = 1; 85 | illo.scale.z = 1; 86 | } 87 | 88 | function keyPressed (e) { 89 | 90 | // Documentation about keyboard events : 91 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 92 | const DOWN_ARROW = 40; 93 | const LEFT_ARROW = 37; 94 | const RIGHT_ARROW = 39; 95 | const UP_ARROW = 38; 96 | const BACKSPACE = 8; 97 | const ESCAPE = 27; 98 | const KEY_ONE = 49; 99 | const KEY_TWO = 50; 100 | const KEY_THREE = 51; 101 | const KEY_FOUR = 52; 102 | const KEY_FIVE = 53; 103 | 104 | switch (e.keyCode) { 105 | case ESCAPE:{ 106 | resetScale(); 107 | break; 108 | } 109 | /* 110 | case LEFT_ARROW:{ 111 | illo.scale.z += 0.3; 112 | break; 113 | } 114 | case RIGHT_ARROW:{ 115 | illo.scale.z -= 0.3; 116 | break; 117 | } 118 | */ 119 | case UP_ARROW:{ 120 | illo.scale.x += 0.3; 121 | illo.scale.y += 0.3; 122 | illo.scale.z += 0.3; 123 | break; 124 | } 125 | case DOWN_ARROW:{ 126 | illo.scale.x -= 0.3; 127 | illo.scale.y -= 0.3; 128 | illo.scale.z -= 0.3; 129 | break; 130 | } 131 | 132 | } 133 | } 134 | 135 | 136 | document.addEventListener('keydown', keyPressed, false); 137 | //document.addEventListener('keyup', keyReleased, false); 138 | 139 | document.addEventListener("DOMContentLoaded", function(event) { 140 | console.log("DOM fully loaded and parsed"); 141 | if (canvas == undefined) { 142 | console.error('DOM target not found for ID zdog-canvas'); 143 | } else { 144 | context = canvas.getContext('2d'); 145 | config(); 146 | animate(); 147 | } 148 | }); 149 | 150 | } 151 | -------------------------------------------------------------------------------- /sources/zdog_segment4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segments with Zdog - test 4 - Natural walk 6 | 30 | 31 | 32 |
33 |

Segments for Natural walk

34 |

Click & drag to rotate

35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
CurseurDescription english version
1contrôle la vitesse à laquelle le système se déplace
2contrôle la distance entre les cuisses
3contrôle l'angle de base des cuisses
4contrôle l'amplitude de mouvement des mollets
5contrôle la valeur de décalage (avec -PI / 2)
6contrôle l'épaisseur des membres et l'écartement des jambes
7joue sur les couleurs des membres (4 choix possibles)
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
SliderDescription french version
1controls the speed at which the system moves
2controls how far back and forth the thighs
3controls the base angle of the thighs
4controls how much range of motion the calves have
5controls the offset value (using -PI/2)
6controls the thickness of the limbs and the spacing of the legs
7plays on the colors of the limbs (4 choices)
115 |
116 |

Inspired by the chapter 13 of the book : Foundation HTML5 Animation with JavaScript

117 |
118 |
119 | 120 | 121 | 122 | 123 | 124 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /sources/zdog_segment5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segments with Zdog - test 5 - Natural walk (legs and arms) 6 | 30 | 31 | 32 |
33 |

Segments for Natural walk

34 |

Click & drag to rotate

35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
CurseurDescription english version
1contrôle la vitesse à laquelle le système se déplace
2contrôle la distance entre les cuisses
3contrôle l'angle de base des cuisses
4contrôle l'amplitude de mouvement des mollets
5contrôle la valeur de décalage (avec -PI / 2)
6contrôle l'épaisseur des membres et l'écartement des jambes
7joue sur les couleurs des membres (4 choix possibles)
76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
SliderDescription french version
1controls the speed at which the system moves
2controls how far back and forth the thighs
3controls the base angle of the thighs
4controls how much range of motion the calves have
5controls the offset value (using -PI/2)
6controls the thickness of the limbs and the spacing of the legs
7plays on the colors of the limbs (4 choices)
115 |
116 |

Inspired by the chapter 13 of the book : Foundation HTML5 Animation with JavaScript

117 |
118 |
119 | 120 | 121 | 122 | 123 | 124 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /sources/zdog_segment_bezier.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Segments with Zdog - test 1 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zdog_shapegenerator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Shape generator for Zdog 6 | 89 | 90 | 91 | 92 | 93 | 94 |
95 |
96 | 97 | 98 | 99 | 100 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

101 | 102 | 103 |
104 |
105 |



106 |
107 | 108 |
109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /sources/zdog_shapes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Several 3D shapes with Zdog 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

33 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /sources/zdog_shapes_xcav.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Several 3D shapes with Zdog 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

36 | 37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /sources/zdog_solarsystem.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Solar system with Zdog 6 | 25 | 26 | 27 |
28 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /sources/zdog_solarsystem.js: -------------------------------------------------------------------------------- 1 | 2 | { 3 | var default_color = "#000000"; // color picker : https://www.w3schools.com/colors/colors_picker.asp 4 | var stroke_value = 1; 5 | 6 | var constrain = function(n, low, high) { 7 | return Math.max(Math.min(n, high), low); 8 | }; 9 | 10 | var map = function(n, start1, stop1, start2, stop2, withinBounds) { 11 | var newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2; 12 | if (!withinBounds) { 13 | return newval; 14 | } 15 | if (start2 < stop2) { 16 | return constrain(newval, start2, stop2); 17 | } else { 18 | return constrain(newval, stop2, start2); 19 | } 20 | }; 21 | 22 | const PI = Math.PI; 23 | const TAU = Zdog.TAU; 24 | var isSpinning = false; 25 | 26 | var bodies = new NBodySystem( Array( 27 | Sun(),Jupiter(),Saturn(),Uranus(),Neptune() 28 | )); 29 | 30 | var illo = new Zdog.Illustration({ 31 | element: '.zdog-canvas', 32 | dragRotate: true, 33 | scale: 10, 34 | // pause spinning while dragging 35 | //onDragStart: () => isSpinning = false, 36 | //onDragEnd: () => isSpinning = true 37 | }); 38 | 39 | let planets = new Zdog.Anchor({ 40 | addTo: illo, 41 | scale: 1, 42 | //translate: { z: 40 }, 43 | // rotate: { z: -Zdog.TAU/8 }, 44 | }); 45 | 46 | let sun_diam = 0; 47 | 48 | for (let i=0, imax=bodies.bodies.length; i 2 | 3 | 4 | 5 | Menger Sponge Fractal Generator with Zdog 6 | 25 | 26 | 27 |
28 | 29 | 30 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sources/zdog_sponge.js: -------------------------------------------------------------------------------- 1 | { 2 | var generateShape = shapes3dToolbox.spongeGenerator; 3 | var illo = undefined; // pointer to the main object (for refreshing) 4 | var list_levels = ['1', '2', '3']; 5 | var level_value = list_levels[0]; 6 | var spin_modes = ['Spinning', 'Static']; 7 | var spin_mode_default = spin_modes[0]; 8 | var isSpinning = true; 9 | var tasks = []; 10 | 11 | let blocks_array = []; 12 | let block_current = -999; 13 | let block_maximum = -999; 14 | 15 | var levelselector = document.getElementById("levelselector"); 16 | if (levelselector) { 17 | list_levels.forEach(item => { 18 | let option = document.createElement('option'); 19 | option.setAttribute('value', item); 20 | option.innerHTML = item; 21 | levelselector.append(option); 22 | }); 23 | 24 | levelselector.blur(); 25 | levelselector.addEventListener('change', function (evt) { 26 | evt.preventDefault(); 27 | this.blur(); 28 | level_value = this.value; 29 | generateGraph(); 30 | 31 | }, false); 32 | } else { 33 | console.warn('level selector not found'); 34 | } 35 | 36 | illo = new Zdog.Illustration({ 37 | element: '.zdog-canvas', 38 | dragRotate: true, 39 | // pause spinning while dragging 40 | //onDragStart: () => isSpinning = false, 41 | //onDragEnd: () => isSpinning = true 42 | }); 43 | 44 | let shapemaster = function (block, num_task) { 45 | if (num_task !== false) { 46 | tasks[num_task] = false; // flag to know that the task is ended 47 | } 48 | new Zdog.Box({ 49 | addTo: illo, 50 | width: block.side, 51 | height: block.side, 52 | depth: block.side, 53 | translate: {x: block.x, y: block.y, z: block.z}, 54 | stroke: block.stroke, 55 | color: block.color, // default face color 56 | leftFace: block.leftFace, 57 | rightFace: block.rightFace, 58 | topFace: block.topFace, 59 | bottomFace: block.bottomFace, 60 | }); 61 | }; 62 | 63 | function generateGraph() { 64 | illo.children = []; // drop all children before regeneration 65 | 66 | let maxLevel = Number(level_value); 67 | if (maxLevel > 2) { 68 | if (isSpinning) { 69 | spin_mode_btn.click(); 70 | } 71 | } 72 | var shape_params = {x: 0, y: 0, z: 0, r: 250, level: 1, maxLevel: maxLevel}; 73 | var blocks = generateShape(shape_params); 74 | let imax = blocks.length; 75 | console.log('Number of blocks to generate : ' + imax); 76 | 77 | if (tasks.length > 0) { 78 | // stop remanining tasks before initializing a new series of tasks 79 | tasks.forEach(task => { 80 | if (task != false) { 81 | clearTimeout(task); 82 | } 83 | }); 84 | tasks = []; 85 | } 86 | 87 | blocks_array = []; 88 | block_current = -999; 89 | block_maximum = -999; 90 | 91 | if (maxLevel < 3) { 92 | let timer = 1; 93 | if (maxLevel == 2) { 94 | timer = 100; 95 | } 96 | for (let i = 0; i < imax; i++) { 97 | let block = blocks[i]; 98 | tasks[i] = setTimeout(() => { 99 | shapemaster(block, i); 100 | }, timer); 101 | } 102 | } else { 103 | block_current = -1; 104 | for (let i = 0; i < imax; i++) { 105 | blocks_array[i] = blocks[i]; 106 | } 107 | block_maximum = imax; 108 | } 109 | } 110 | 111 | generateGraph(); 112 | 113 | function draw() { 114 | if (isSpinning) { 115 | illo.rotate.z += 0.003; 116 | } 117 | illo.updateRenderGraph(); 118 | } 119 | 120 | function animate() { 121 | 122 | if (block_current != -999) { 123 | block_current++; 124 | if (block_current < block_maximum) { 125 | let block = blocks_array[block_current]; 126 | shapemaster(block, false); 127 | } 128 | } 129 | 130 | draw(); 131 | requestAnimationFrame(animate); 132 | } 133 | 134 | function resetScale() { 135 | illo.scale.x = 1; 136 | illo.scale.y = 1; 137 | illo.scale.z = 1; 138 | } 139 | 140 | function keyPressed(e) { 141 | 142 | // Documentation about keyboard events : 143 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 144 | const DOWN_ARROW = 40; 145 | const LEFT_ARROW = 37; 146 | const RIGHT_ARROW = 39; 147 | const UP_ARROW = 38; 148 | //const BACKSPACE = 8; 149 | const ESCAPE = 27; 150 | //const KEY_ONE = 49; 151 | //const KEY_TWO = 50; 152 | //const KEY_THREE = 51; 153 | //const KEY_FOUR = 52; 154 | //const KEY_FIVE = 53; 155 | 156 | switch (e.keyCode) { 157 | case ESCAPE: { 158 | resetScale(); 159 | break; 160 | } 161 | case LEFT_ARROW: { 162 | illo.scale.z += 0.3; 163 | break; 164 | } 165 | case RIGHT_ARROW: { 166 | illo.scale.z -= 0.3; 167 | break; 168 | } 169 | case UP_ARROW: { 170 | illo.scale.x += 0.3; 171 | illo.scale.y += 0.3; 172 | illo.scale.z += 0.3; 173 | break; 174 | } 175 | case DOWN_ARROW: { 176 | illo.scale.x -= 0.3; 177 | illo.scale.y -= 0.3; 178 | illo.scale.z -= 0.3; 179 | break; 180 | } 181 | 182 | } 183 | } 184 | 185 | function keyReleased(e) { 186 | e.preventDefault(); 187 | // TODO : find something to implement here ;) 188 | } 189 | 190 | var spin_mode_btn = document.getElementById('spinning'); 191 | if (spin_mode_btn) { 192 | spin_mode_btn.innerHTML = spin_modes[1]; 193 | spin_mode_btn.addEventListener('click', function (evt) { 194 | evt.preventDefault(); 195 | let other_mode; 196 | if (spin_mode_default == spin_modes[0]) { 197 | spin_mode_default = spin_modes[1]; 198 | other_mode = spin_modes[0]; 199 | isSpinning = false; 200 | } else { 201 | spin_mode_default = spin_modes[0]; 202 | other_mode = spin_modes[1]; 203 | isSpinning = true; 204 | } 205 | spin_mode_btn.innerHTML = other_mode; 206 | }, false); 207 | } else { 208 | console.warn('spin mode button not found'); 209 | } 210 | 211 | document.addEventListener('keydown', keyPressed, false); 212 | //document.addEventListener('keyup', keyReleased, false); 213 | 214 | document.addEventListener("DOMContentLoaded", function (event) { 215 | console.log("DOM fully loaded and parsed"); 216 | animate(); 217 | }); 218 | 219 | } 220 | -------------------------------------------------------------------------------- /sources/zdog_surf_param.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Parametric surfaces 6 | 27 | 28 | 29 |
30 | 31 |

Click & drag to rotate

32 |
33 |
34 | Tutorials 35 |

Tutorials (in french) about parametric surfaces

36 |

Tutorials (in english) about toroidal geometry

37 |
38 | <= Menu
39 |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sources/zdog_surf_param2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Parametric surfaces customizable 6 | 60 | 61 | 62 | 63 |
64 | 65 |

Click & drag to rotate

66 |
67 |   68 | 69 | 70 |

71 |
72 |
73 |
74 |

Edit Parameters

75 |
76 |
77 |
78 |
79 | Constants 80 |
81 |
82 |
83 | 84 | 85 | 86 | 87 | 88 | 89 |

90 |

91 |
92 |
93 | Limits on U 94 |
95 |
96 |
97 | 98 | 99 | 100 |

101 |

102 |
103 |
104 | Limits on V 105 |
106 |
107 |
108 | 109 | 110 | 111 |

112 |

113 |
114 |
115 | Functions 116 |
117 |
118 |
119 | 120 | 121 | 122 | 123 |

124 |
125 |
126 |
127 |
128 | Tutorials 129 |

Tutorials (in french) about parametric surfaces

130 |

Tutorials (in english) about toroidal geometry

131 |
132 | <= Menu
133 | 134 |
135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /sources/zdog_surf_param3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Parametric surfaces 6 | 27 | 28 | 29 |
30 | 31 |

Click & drag to rotate

32 |
33 |
34 | Tutorials 35 |

Tutorials (in french) about parametric surfaces

36 |

Tutorials (in english) about toroidal geometry

37 |
38 | <= Menu
39 |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sources/zdog_swingcubes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Zdog - Swinging with cubes 6 | 25 | 26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /sources/zdog_swingcubes.js: -------------------------------------------------------------------------------- 1 | // Made with Zdog 2 | { 3 | "use strict"; 4 | 5 | let canvas = document.getElementById('zdog-canvas'); 6 | let width = canvas.width; 7 | let height = canvas.height; 8 | 9 | var noise = null; 10 | var boxes = []; 11 | 12 | const radiandToDegrees = (val) => { 13 | return val * SEMI_CIRCLE_ON_PI; 14 | }; 15 | 16 | let illo = new Zdog.Illustration({ 17 | element: canvas, 18 | dragRotate: true, 19 | translate:{x:300}, 20 | rotate:{x:0.9, y:0, z:-4} 21 | }); 22 | 23 | let shape = new Zdog.Shape({ 24 | addTo: illo, 25 | // rotate:{y:100, z:100} 26 | }); 27 | 28 | var side = 40; 29 | var dist = 50; 30 | var isSpinning = false; 31 | 32 | const getMousePos = function (canvas, evt) { 33 | // It's a very reliable algorithm to get mouse coordinates (don't use anything else) 34 | // it works fine on Firefox and Chrome 35 | // source : https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas 36 | var rect = canvas.getBoundingClientRect(); 37 | return { 38 | x: (evt.clientX - rect.left) / (rect.right - rect.left) * width, 39 | y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * height 40 | }; 41 | } 42 | 43 | var valMin = Infinity; 44 | var valMax = -Infinity; 45 | 46 | function generateGrid(imax, jmax, gap=100, side=40) { 47 | let items = []; 48 | let xbegin = gap / 2; 49 | let ybegin = gap / 2; 50 | 51 | let yside = side / 2; 52 | 53 | for (let i=0; i { 75 | item.node = new Zdog.Box({ 76 | addTo: shape, 77 | width: item.coords.width, 78 | height: item.coords.height, 79 | depth: item.coords.depth, 80 | translate: {x:item.coords.x, y:item.coords.y, z: Math.abs((item.coords.depth/2) - item.coords.z) }, 81 | stroke: false, 82 | color: '#C25', // default face color 83 | leftFace: '#EA0', 84 | rightFace: '#E62', 85 | topFace: '#ED0', 86 | bottomFace: '#636', 87 | }); 88 | }); 89 | } 90 | 91 | function draw (){ 92 | if (isSpinning) { 93 | illo.rotate.z += 0.003; 94 | } 95 | illo.updateRenderGraph(); 96 | } 97 | 98 | function animate() { 99 | draw(); 100 | requestAnimationFrame( animate ); 101 | } 102 | 103 | document.addEventListener("DOMContentLoaded", function(event) { 104 | console.log("DOM fully loaded and parsed"); 105 | refreshGrid(); 106 | animate(); 107 | setInterval(function(){ 108 | refreshGrid(); 109 | //illo.updateRenderGraph(); 110 | }, 300); 111 | }); 112 | } 113 | -------------------------------------------------------------------------------- /sources/zdog_tunnel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tunnel 3D with Zdog 6 | 25 | 26 | 27 |
28 | 29 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

30 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sources/zdog_tunnel.js: -------------------------------------------------------------------------------- 1 | // to generate the 3D shape of tunnel, I used the algorithm of Niklas Knaack 2 | // found on this pen : https://codepen.io/NiklasKnaack/pen/WyWqja 3 | 4 | { 5 | var default_color = "#000000"; // color picker : https://www.w3schools.com/colors/colors_picker.asp 6 | var stroke_value = 1; 7 | 8 | var colpicker = document.getElementById("colorpicker"); 9 | if (colpicker) { 10 | colpicker.value = default_color; 11 | colpicker.addEventListener('change', function(evt) { 12 | default_color = this.value; 13 | mainshape.color = default_color; 14 | }, false); 15 | } else { 16 | console.warn('color picker not found'); 17 | } 18 | 19 | var isSpinning = true; 20 | 21 | var illo = new Zdog.Illustration({ 22 | element: '.zdog-canvas', 23 | dragRotate: true, 24 | // pause spinning while dragging 25 | onDragStart: () => isSpinning = false, 26 | onDragEnd: () => isSpinning = true 27 | }); 28 | 29 | var mainshape = new Zdog.Shape({ 30 | addTo: illo, 31 | path: tunnel_datas, 32 | color: default_color, 33 | closed: false, 34 | stroke: stroke_value, 35 | fill: false, 36 | }); 37 | 38 | function draw (){ 39 | if (isSpinning) { 40 | illo.rotate.z += 0.003; 41 | } 42 | illo.updateRenderGraph(); 43 | } 44 | 45 | function animate() { 46 | draw(); 47 | requestAnimationFrame( animate ); 48 | } 49 | 50 | function resetScale() { 51 | illo.scale.x = 1; 52 | illo.scale.y = 1; 53 | illo.scale.z = 1; 54 | } 55 | 56 | function keyPressed (e) { 57 | 58 | // Documentation about keyboard events : 59 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 60 | const DOWN_ARROW = 40; 61 | const LEFT_ARROW = 37; 62 | const RIGHT_ARROW = 39; 63 | const UP_ARROW = 38; 64 | const BACKSPACE = 8; 65 | const ESCAPE = 27; 66 | const KEY_ONE = 49; 67 | const KEY_TWO = 50; 68 | const KEY_THREE = 51; 69 | const KEY_FOUR = 52; 70 | const KEY_FIVE = 53; 71 | 72 | switch (e.keyCode) { 73 | case ESCAPE:{ 74 | resetScale(); 75 | break; 76 | } 77 | case LEFT_ARROW:{ 78 | illo.scale.z += 0.3; 79 | break; 80 | } 81 | case RIGHT_ARROW:{ 82 | illo.scale.z -= 0.3; 83 | break; 84 | } 85 | case UP_ARROW:{ 86 | illo.scale.x += 0.3; 87 | illo.scale.y += 0.3; 88 | illo.scale.z += 0.3; 89 | break; 90 | } 91 | case DOWN_ARROW:{ 92 | illo.scale.x -= 0.3; 93 | illo.scale.y -= 0.3; 94 | illo.scale.z -= 0.3; 95 | break; 96 | } 97 | case KEY_ONE:{ 98 | stroke_value = 1; 99 | mainshape.stroke = stroke_value; 100 | break; 101 | } 102 | case KEY_TWO:{ 103 | stroke_value = 2; 104 | mainshape.stroke = stroke_value; 105 | break; 106 | } 107 | case KEY_THREE:{ 108 | stroke_value = 3; 109 | mainshape.stroke = stroke_value; 110 | break; 111 | } 112 | case KEY_FOUR:{ 113 | stroke_value = 4; 114 | mainshape.stroke = stroke_value; 115 | break; 116 | } 117 | case KEY_FIVE:{ 118 | stroke_value = 5; 119 | mainshape.stroke = stroke_value; 120 | break; 121 | } 122 | 123 | } 124 | } 125 | 126 | 127 | document.addEventListener('keydown', keyPressed, false); 128 | //document.addEventListener('keyup', keyReleased, false); 129 | 130 | document.addEventListener("DOMContentLoaded", function(event) { 131 | console.log("DOM fully loaded and parsed"); 132 | animate(); 133 | }); 134 | 135 | } 136 | -------------------------------------------------------------------------------- /sources/zdog_xshapes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Complex 3D object created with 3 primitives 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

32 | 33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zdog_xshapes.js: -------------------------------------------------------------------------------- 1 | /* 2 | Example of a complex 3D object created with 3 primitives 3 | largely inspired by : https://library.fridoverweij.com/codelab/3d_wireframe/index.html 4 | */ 5 | { 6 | "use strict"; 7 | 8 | var list_shapes = shapes3dToolbox.getAssemblyObject01(); 9 | var id_shapes = Object.keys(list_shapes); 10 | 11 | var default_color = "#000000"; // color picker : https://www.w3schools.com/colors/colors_picker.asp 12 | var stroke_value = 1; 13 | var illo = undefined; // pointer to the main object (for refreshing) 14 | var shapes_wire = []; 15 | var shapes_paint = []; 16 | var draw_modes = ['Wireframe', 'Paint']; 17 | var draw_mode_default = draw_modes[1]; 18 | var spin_modes = ['Spinning', 'Static']; 19 | var spin_mode_default = spin_modes[0]; 20 | var scale_def = 1; 21 | 22 | var colpicker = document.getElementById("colorpicker"); 23 | if (colpicker) { 24 | colpicker.value = default_color; 25 | colpicker.addEventListener('change', function(evt) { 26 | default_color = this.value; 27 | if (shapes_wire.length > 0) { 28 | shapes_wire.forEach(item => { 29 | item.color = default_color; 30 | }) 31 | } 32 | }, false); 33 | } else { 34 | console.warn('color picker not found'); 35 | } 36 | 37 | // Wireframe shape 38 | function genShape1(obj3d) { 39 | var datas = []; 40 | 41 | obj3d.polygons.forEach(vertices => { 42 | 43 | vertices.forEach(item => { 44 | datas.push(obj3d.points[item]); 45 | }); 46 | 47 | }); 48 | return datas; 49 | } 50 | 51 | // filled shape 52 | function genShape2(ref, shape) { 53 | let generateShape = shapes3dToolbox[shape.fn]; 54 | let shape_params = shape.default; 55 | let obj3d = generateShape(shape_params); 56 | var colors = chroma.scale(['#9cdf7c','#2A4858']).mode('lch').colors(obj3d.polygons.length); 57 | 58 | obj3d.polygons.forEach((vertices, idx) => { 59 | let shape = []; 60 | vertices.forEach(item => { 61 | shape.push(obj3d.points[item]); 62 | }) 63 | 64 | shapes_paint.push(new Zdog.Shape({ 65 | addTo: ref, 66 | path: shape, 67 | color: colors[idx], 68 | closed: false, 69 | stroke: stroke_value, 70 | fill: true, 71 | })); 72 | }); 73 | } 74 | 75 | var isSpinning = true; 76 | 77 | illo = new Zdog.Illustration({ 78 | element: '.zdog-canvas', 79 | dragRotate: true, 80 | scale: scale_def 81 | // pause spinning while dragging 82 | //onDragStart: () => isSpinning = false, 83 | //onDragEnd: () => isSpinning = false 84 | }); 85 | 86 | function generateGraph() { 87 | illo.children = []; // drop all children before regeneration 88 | 89 | if (draw_mode_default == 'Wireframe') { 90 | shapes_wire = []; 91 | shapes_paint = []; 92 | 93 | list_shapes.forEach((item) => { 94 | let generateShape = shapes3dToolbox[item.fn]; 95 | let shape_params = item.default; 96 | 97 | shapes_wire.push(new Zdog.Shape({ 98 | addTo: illo, 99 | path: genShape1(generateShape(shape_params)), 100 | color: default_color, 101 | closed: false, 102 | stroke: stroke_value, 103 | fill: false, 104 | })); 105 | }); 106 | 107 | } else { 108 | shapes_wire = []; 109 | shapes_paint = []; 110 | 111 | list_shapes.forEach(item => { 112 | genShape2(illo, item); 113 | }); 114 | 115 | } 116 | } 117 | 118 | generateGraph(); 119 | 120 | function draw (){ 121 | if (isSpinning) { 122 | illo.rotate.z += 0.003; 123 | } 124 | illo.updateRenderGraph(); 125 | } 126 | 127 | function animate() { 128 | draw(); 129 | requestAnimationFrame( animate ); 130 | } 131 | 132 | function resetScale() { 133 | illo.scale.x = scale_def; 134 | illo.scale.y = scale_def; 135 | illo.scale.z = scale_def; 136 | } 137 | 138 | function keyPressed (e) { 139 | 140 | // Documentation about keyboard events : 141 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 142 | const DOWN_ARROW = 40; 143 | const LEFT_ARROW = 37; 144 | const RIGHT_ARROW = 39; 145 | const UP_ARROW = 38; 146 | const BACKSPACE = 8; 147 | const ESCAPE = 27; 148 | const KEY_ONE = 49; 149 | const KEY_TWO = 50; 150 | const KEY_THREE = 51; 151 | const KEY_FOUR = 52; 152 | const KEY_FIVE = 53; 153 | 154 | switch (e.keyCode) { 155 | case ESCAPE:{ 156 | resetScale(); 157 | break; 158 | } 159 | case LEFT_ARROW:{ 160 | illo.scale.z += 0.3; 161 | break; 162 | } 163 | case RIGHT_ARROW:{ 164 | illo.scale.z -= 0.3; 165 | break; 166 | } 167 | case UP_ARROW:{ 168 | illo.scale.x += 0.3; 169 | illo.scale.y += 0.3; 170 | illo.scale.z += 0.3; 171 | break; 172 | } 173 | case DOWN_ARROW:{ 174 | illo.scale.x -= 0.3; 175 | illo.scale.y -= 0.3; 176 | illo.scale.z -= 0.3; 177 | break; 178 | } 179 | 180 | } 181 | } 182 | 183 | var draw_mode_btn = document.getElementById('drawmode'); 184 | if (draw_mode_btn) { 185 | if (draw_mode_default == draw_modes[1]) { 186 | draw_mode_btn.innerHTML = draw_modes[0]; 187 | } else { 188 | draw_mode_btn.innerHTML = draw_modes[1]; 189 | } 190 | draw_mode_btn.addEventListener('click', function(evt) { 191 | let other_mode; 192 | if (draw_mode_default == draw_modes[0]) { 193 | draw_mode_default = draw_modes[1]; 194 | other_mode = draw_modes[0]; 195 | colpicker.setAttribute('disabled', 'disabled'); 196 | } else { 197 | draw_mode_default = draw_modes[0]; 198 | other_mode = draw_modes[1]; 199 | colpicker.removeAttribute('disabled'); 200 | } 201 | draw_mode_btn.innerHTML = other_mode; 202 | generateGraph(); 203 | }, false); 204 | } else { 205 | console.warn('draw mode button not found'); 206 | } 207 | 208 | var spin_mode_btn = document.getElementById('spinning'); 209 | if (spin_mode_btn) { 210 | spin_mode_btn.innerHTML = spin_modes[1]; 211 | spin_mode_btn.addEventListener('click', function(evt) { 212 | let other_mode; 213 | if (spin_mode_default == spin_modes[0]) { 214 | spin_mode_default = spin_modes[1]; 215 | other_mode = spin_modes[0]; 216 | isSpinning = false; 217 | } else { 218 | spin_mode_default = spin_modes[0]; 219 | other_mode = spin_modes[1]; 220 | isSpinning = true; 221 | } 222 | spin_mode_btn.innerHTML = other_mode; 223 | generateGraph(); 224 | }, false); 225 | } else { 226 | console.warn('spin mode button not found'); 227 | } 228 | 229 | document.addEventListener('keydown', keyPressed, false); 230 | //document.addEventListener('keyup', keyReleased, false); 231 | 232 | document.addEventListener("DOMContentLoaded", function(event) { 233 | console.log("DOM fully loaded and parsed"); 234 | animate(); 235 | }); 236 | 237 | } 238 | -------------------------------------------------------------------------------- /sources/zdog_xshapes2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 cubes linked in a mesh 6 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

32 | 33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sources/zdog_xshapes2.js: -------------------------------------------------------------------------------- 1 | { 2 | "use strict"; 3 | 4 | var list_shapes = shapes3dToolbox.getEightCubesLinked(); 5 | var id_shapes = Object.keys(list_shapes); 6 | 7 | var default_color = "#000000"; // color picker : https://www.w3schools.com/colors/colors_picker.asp 8 | var stroke_value = 1; 9 | var illo = undefined; // pointer to the main object (for refreshing) 10 | var shapes_wire = []; 11 | var shapes_paint = []; 12 | var draw_modes = ['Wireframe', 'Paint']; 13 | var draw_mode_default = draw_modes[1]; 14 | var spin_modes = ['Spinning', 'Static']; 15 | var spin_mode_default = spin_modes[0]; 16 | var scale_def = 2; 17 | 18 | var colpicker = document.getElementById("colorpicker"); 19 | if (colpicker) { 20 | colpicker.value = default_color; 21 | colpicker.addEventListener('change', function (evt) { 22 | default_color = this.value; 23 | if (shapes_wire.length > 0) { 24 | shapes_wire.forEach(item => { 25 | item.color = default_color; 26 | }) 27 | } 28 | }, false); 29 | } else { 30 | console.warn('color picker not found'); 31 | } 32 | 33 | // Wireframe shape 34 | function genShape1(obj3d) { 35 | var datas = []; 36 | 37 | obj3d.polygons.forEach(vertices => { 38 | 39 | vertices.forEach(item => { 40 | datas.push(obj3d.points[item]); 41 | }); 42 | 43 | }); 44 | return datas; 45 | } 46 | 47 | // filled shape 48 | function genShape2(ref, shape) { 49 | console.log(shape); 50 | let generateShape = shapes3dToolbox[shape.fn]; 51 | console.log(generateShape); 52 | let shape_params = shape.default; 53 | let obj3d = generateShape(shape_params); 54 | var colors = chroma.scale(['#9cdf7c', '#2A4858']).mode('lch').colors(obj3d.polygons.length); 55 | 56 | obj3d.polygons.forEach((vertices, idx) => { 57 | let shape = []; 58 | vertices.forEach(item => { 59 | shape.push(obj3d.points[item]); 60 | }); 61 | 62 | shapes_paint.push(new Zdog.Shape({ 63 | addTo: ref, 64 | path: shape, 65 | color: colors[idx], 66 | closed: false, 67 | stroke: stroke_value, 68 | fill: true, 69 | })); 70 | }); 71 | } 72 | 73 | var isSpinning = true; 74 | 75 | illo = new Zdog.Illustration({ 76 | element: '.zdog-canvas', 77 | dragRotate: true, 78 | scale: scale_def 79 | // pause spinning while dragging 80 | //onDragStart: () => isSpinning = false, 81 | //onDragEnd: () => isSpinning = false 82 | }); 83 | 84 | function generateGraph() { 85 | illo.children = []; // drop all children before regeneration 86 | 87 | if (draw_mode_default == 'Wireframe') { 88 | shapes_wire = []; 89 | shapes_paint = []; 90 | 91 | list_shapes.forEach((item) => { 92 | let generateShape = shapes3dToolbox[item.fn]; 93 | let shape_params = item.default; 94 | 95 | shapes_wire.push(new Zdog.Shape({ 96 | addTo: illo, 97 | path: genShape1(generateShape(shape_params)), 98 | color: default_color, 99 | closed: false, 100 | stroke: stroke_value, 101 | fill: false, 102 | })); 103 | }); 104 | 105 | } else { 106 | shapes_wire = []; 107 | shapes_paint = []; 108 | 109 | list_shapes.forEach(item => { 110 | genShape2(illo, item); 111 | }); 112 | 113 | } 114 | } 115 | 116 | generateGraph(); 117 | 118 | function draw() { 119 | if (isSpinning) { 120 | illo.rotate.z += 0.003; 121 | } 122 | illo.updateRenderGraph(); 123 | } 124 | 125 | function animate() { 126 | draw(); 127 | requestAnimationFrame(animate); 128 | } 129 | 130 | function resetScale() { 131 | illo.scale.x = scale_def; 132 | illo.scale.y = scale_def; 133 | illo.scale.z = scale_def; 134 | } 135 | 136 | function keyPressed(e) { 137 | 138 | // Documentation about keyboard events : 139 | // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key 140 | const DOWN_ARROW = 40; 141 | const LEFT_ARROW = 37; 142 | const RIGHT_ARROW = 39; 143 | const UP_ARROW = 38; 144 | const BACKSPACE = 8; 145 | const ESCAPE = 27; 146 | const KEY_ONE = 49; 147 | const KEY_TWO = 50; 148 | const KEY_THREE = 51; 149 | const KEY_FOUR = 52; 150 | const KEY_FIVE = 53; 151 | 152 | switch (e.keyCode) { 153 | case ESCAPE: { 154 | resetScale(); 155 | break; 156 | } 157 | case LEFT_ARROW: { 158 | illo.scale.z += 0.3; 159 | break; 160 | } 161 | case RIGHT_ARROW: { 162 | illo.scale.z -= 0.3; 163 | break; 164 | } 165 | case UP_ARROW: { 166 | illo.scale.x += 0.3; 167 | illo.scale.y += 0.3; 168 | illo.scale.z += 0.3; 169 | break; 170 | } 171 | case DOWN_ARROW: { 172 | illo.scale.x -= 0.3; 173 | illo.scale.y -= 0.3; 174 | illo.scale.z -= 0.3; 175 | break; 176 | } 177 | 178 | } 179 | } 180 | 181 | var draw_mode_btn = document.getElementById('drawmode'); 182 | if (draw_mode_btn) { 183 | if (draw_mode_default == draw_modes[1]) { 184 | draw_mode_btn.innerHTML = draw_modes[0]; 185 | } else { 186 | draw_mode_btn.innerHTML = draw_modes[1]; 187 | } 188 | draw_mode_btn.addEventListener('click', function (evt) { 189 | let other_mode; 190 | if (draw_mode_default == draw_modes[0]) { 191 | draw_mode_default = draw_modes[1]; 192 | other_mode = draw_modes[0]; 193 | colpicker.setAttribute('disabled', 'disabled'); 194 | } else { 195 | draw_mode_default = draw_modes[0]; 196 | other_mode = draw_modes[1]; 197 | colpicker.removeAttribute('disabled'); 198 | } 199 | draw_mode_btn.innerHTML = other_mode; 200 | generateGraph(); 201 | }, false); 202 | } else { 203 | console.warn('draw mode button not found'); 204 | } 205 | 206 | var spin_mode_btn = document.getElementById('spinning'); 207 | if (spin_mode_btn) { 208 | spin_mode_btn.innerHTML = spin_modes[1]; 209 | spin_mode_btn.addEventListener('click', function (evt) { 210 | let other_mode; 211 | if (spin_mode_default == spin_modes[0]) { 212 | spin_mode_default = spin_modes[1]; 213 | other_mode = spin_modes[0]; 214 | isSpinning = false; 215 | } else { 216 | spin_mode_default = spin_modes[0]; 217 | other_mode = spin_modes[1]; 218 | isSpinning = true; 219 | } 220 | spin_mode_btn.innerHTML = other_mode; 221 | generateGraph(); 222 | }, false); 223 | } else { 224 | console.warn('spin mode button not found'); 225 | } 226 | 227 | document.addEventListener('keydown', keyPressed, false); 228 | //document.addEventListener('keyup', keyReleased, false); 229 | 230 | document.addEventListener("DOMContentLoaded", function (event) { 231 | console.log("DOM fully loaded and parsed"); 232 | animate(); 233 | }); 234 | 235 | } 236 | -------------------------------------------------------------------------------- /sources/zdog_xwing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | XWing with Zdog 6 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 | 33 | 34 |

Click & drag to rotate + Arrow keys to zoom (or Escape to reset)

35 | 36 | 37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | --------------------------------------------------------------------------------