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