mapspinner 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -0
  3. package/package.json +47 -0
  4. package/src/lib/assets/bark/README.md +8 -0
  5. package/src/lib/assets/bark/birch_ao_1k.jpg +0 -0
  6. package/src/lib/assets/bark/birch_color_1k.jpg +0 -0
  7. package/src/lib/assets/bark/birch_normal_1k.jpg +0 -0
  8. package/src/lib/assets/bark/birch_roughness_1k.jpg +0 -0
  9. package/src/lib/assets/bark/oak_ao_1k.jpg +0 -0
  10. package/src/lib/assets/bark/oak_color_1k.jpg +0 -0
  11. package/src/lib/assets/bark/oak_normal_1k.jpg +0 -0
  12. package/src/lib/assets/bark/oak_roughness_1k.jpg +0 -0
  13. package/src/lib/assets/bark/pine_ao_1k.jpg +0 -0
  14. package/src/lib/assets/bark/pine_color_1k.jpg +0 -0
  15. package/src/lib/assets/bark/pine_normal_1k.jpg +0 -0
  16. package/src/lib/assets/bark/pine_roughness_1k.jpg +0 -0
  17. package/src/lib/assets/bark/willow_ao_1k.jpg +0 -0
  18. package/src/lib/assets/bark/willow_color_1k.jpg +0 -0
  19. package/src/lib/assets/bark/willow_normal_1k.jpg +0 -0
  20. package/src/lib/assets/bark/willow_roughness_1k.jpg +0 -0
  21. package/src/lib/assets/leaves/ash_color.png +0 -0
  22. package/src/lib/assets/leaves/aspen_color.png +0 -0
  23. package/src/lib/assets/leaves/oak_color.png +0 -0
  24. package/src/lib/assets/leaves/pine_color.png +0 -0
  25. package/src/lib/branch.js +28 -0
  26. package/src/lib/enums.js +23 -0
  27. package/src/lib/index.js +4 -0
  28. package/src/lib/options.js +198 -0
  29. package/src/lib/presets/ash_large.json +96 -0
  30. package/src/lib/presets/ash_medium.json +96 -0
  31. package/src/lib/presets/ash_small.json +96 -0
  32. package/src/lib/presets/aspen_large.json +96 -0
  33. package/src/lib/presets/aspen_medium.json +96 -0
  34. package/src/lib/presets/aspen_small.json +96 -0
  35. package/src/lib/presets/bush_1.json +96 -0
  36. package/src/lib/presets/bush_2.json +96 -0
  37. package/src/lib/presets/bush_3.json +96 -0
  38. package/src/lib/presets/index.js +47 -0
  39. package/src/lib/presets/oak_large.json +96 -0
  40. package/src/lib/presets/oak_medium.json +96 -0
  41. package/src/lib/presets/oak_small.json +96 -0
  42. package/src/lib/presets/pine_large.json +96 -0
  43. package/src/lib/presets/pine_medium.json +96 -0
  44. package/src/lib/presets/pine_small.json +96 -0
  45. package/src/lib/presets/trellis.json +112 -0
  46. package/src/lib/rng.js +22 -0
  47. package/src/lib/textures.js +105 -0
  48. package/src/lib/tree.js +1062 -0
  49. package/src/lib/trellis.js +135 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Daniel Greenheck
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.
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # MapSpinner
2
+
3
+ ![GitHub Repo stars](https://img.shields.io/github/stars/AnEntrypoint/mapspinner)
4
+
5
+ Procedural tree generator + buildless Three.js demo world.
6
+ Live: https://anentrypoint.github.io/mapspinner/
7
+
8
+ MapSpinner is derived from the original EZ-Tree library by Daniel Greenheck.
9
+
10
+ # No build step
11
+
12
+ MapSpinner ships **raw ESM source**. There is no bundler. There is no `npm run build`. The `index.html` at the repo root carries an `<script type="importmap">` that resolves `three`, `three/addons/`, `three/examples/jsm/`, and `mapspinner` to vendored ESM under `vendor/three/` and `src/lib/`.
13
+
14
+ To run locally:
15
+
16
+ ```bash
17
+ python -m http.server 8000
18
+ # open http://127.0.0.1:8000/
19
+ ```
20
+
21
+ Any static server works (Caddy, nginx, `npx serve`, etc.). Edit a `.js` file and refresh — that is the whole dev loop.
22
+
23
+ # Installing as an npm dependency
24
+
25
+ ```bash
26
+ npm install mapspinner three
27
+ ```
28
+
29
+ `three` is a peer dependency. Consumers must provide it themselves (and the matching importmap entries when running buildless in the browser).
30
+
31
+ ```js
32
+ import { Tree, TreePreset, BarkType, LeafType } from 'mapspinner';
33
+
34
+ const tree = new Tree();
35
+ tree.options.seed = 12345;
36
+ tree.options.trunk.length = 20;
37
+ tree.options.branch.levels = 3;
38
+ tree.generate();
39
+ scene.add(tree);
40
+ ```
41
+
42
+ Any time the tree parameters are changed, call `generate()` to regenerate the geometry.
43
+
44
+ # Repo layout
45
+
46
+ ```
47
+ index.html, editor.html buildless entry points (importmap inside)
48
+ *.glb, *.png, *.jpg, ... static assets served at page base URL
49
+ src/lib/ npm-published library source (raw ESM)
50
+ src/app/ demo-world source (scene, terrain, grass, UI, shaders)
51
+ vendor/three/ pinned three.js vendor (build/ + examples/jsm/)
52
+ ```
53
+
54
+ # Publishing
55
+
56
+ Pushes to `main` auto-bump patch version and publish to npm via
57
+ `.github/workflows/publish.yml` (requires `NPM_TOKEN` repo secret).
58
+ Add `[skip publish]` to a commit message to skip the auto-bump.
59
+
60
+ # Tree Parameters
61
+
62
+ The `TreeOptions` class defines an options object that controls various
63
+ parameters of a procedurally generated tree. Each property allows for
64
+ customization of the tree's appearance — bark, branches, leaves.
65
+
66
+ ## General
67
+
68
+ - **`seed`**: Initial value for random generation.
69
+ - **`type`**: One of the `TreeType` enumeration values (e.g., `TreeType.Deciduous`).
70
+
71
+ ## Bark
72
+
73
+ - **`type`** (`BarkType.Oak`, etc.)
74
+ - **`tint`** — hex color
75
+ - **`flatShading`** — boolean
76
+ - **`textured`** — boolean
77
+ - **`textureScale`** — `{ x, y }`
78
+
79
+ ## Branch
80
+
81
+ - **`levels`** — recursive branch levels
82
+ - **`angle`** — degrees
83
+ - **`children`** — count per level
84
+ - **`force`** — `{ direction: {x,y,z}, strength }`
85
+ - **`gnarliness`**, **`length`**, **`radius`**, **`sections`**, **`segments`**, **`start`**, **`taper`**, **`twist`**
86
+
87
+ ## Leaves
88
+
89
+ - **`type`** (`LeafType.Oak`, etc.)
90
+ - **`billboard`** (`Billboard.Single` / `Billboard.Double`)
91
+ - **`angle`**, **`count`**, **`start`**, **`size`**, **`sizeVariance`**, **`tint`**, **`alphaTest`**
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "mapspinner",
3
+ "author": "Daniel Greenheck",
4
+ "version": "1.1.1",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/AnEntrypoint/mapspinner.git"
9
+ },
10
+ "homepage": "https://anentrypoint.github.io/mapspinner/",
11
+ "bugs": {
12
+ "url": "https://github.com/AnEntrypoint/mapspinner/issues"
13
+ },
14
+ "type": "module",
15
+ "main": "./src/lib/index.js",
16
+ "module": "./src/lib/index.js",
17
+ "exports": {
18
+ ".": "./src/lib/index.js",
19
+ "./*": "./src/lib/*"
20
+ },
21
+ "files": [
22
+ "src/lib",
23
+ "LICENSE",
24
+ "package.json",
25
+ "README.md"
26
+ ],
27
+ "scripts": {
28
+ "serve": "python -m http.server 8000"
29
+ },
30
+ "devDependencies": {
31
+ "prettier": "3.3.3"
32
+ },
33
+ "peerDependencies": {
34
+ "three": ">=0.169"
35
+ },
36
+ "keywords": [
37
+ "threejs",
38
+ "three-js",
39
+ "procedural",
40
+ "generation",
41
+ "tree",
42
+ "mapspinner",
43
+ "buildless",
44
+ "esm"
45
+ ],
46
+ "dependencies": {}
47
+ }
@@ -0,0 +1,8 @@
1
+ # Sources
2
+
3
+ Higher resolution textures can be found from the original source
4
+
5
+ Birch - https://www.texturecan.com/details/221/
6
+ Pine - https://www.texturecan.com/details/588/
7
+ Oak - https://polyhaven.com/a/bark_brown_02
8
+ Willow - https://polyhaven.com/a/bark_willow_02
@@ -0,0 +1,28 @@
1
+ import * as THREE from 'three';
2
+
3
+ export class Branch {
4
+ /**
5
+ * Generates a new branch
6
+ * @param {THREE.Vector3} origin The starting point of the branch
7
+ * @param {THREE.Euler} orientation The starting orientation of the branch
8
+ * @param {number} length The length of the branch
9
+ * @param {number} radius The radius of the branch at its starting point
10
+ */
11
+ constructor(
12
+ origin = new THREE.Vector3(),
13
+ orientation = new THREE.Euler(),
14
+ length = 0,
15
+ radius = 0,
16
+ level = 0,
17
+ sectionCount = 0,
18
+ segmentCount = 0,
19
+ ) {
20
+ this.origin = origin.clone();
21
+ this.orientation = orientation.clone();
22
+ this.length = length;
23
+ this.radius = radius;
24
+ this.level = level;
25
+ this.sectionCount = sectionCount;
26
+ this.segmentCount = segmentCount;
27
+ }
28
+ }
@@ -0,0 +1,23 @@
1
+ export const BarkType = {
2
+ Birch: 'birch',
3
+ Oak: 'oak',
4
+ Pine: 'pine',
5
+ Willow: 'willow'
6
+ };
7
+
8
+ export const Billboard = {
9
+ Single: 'single',
10
+ Double: 'double',
11
+ };
12
+
13
+ export const LeafType = {
14
+ Ash: 'ash',
15
+ Aspen: 'aspen',
16
+ Pine: 'pine',
17
+ Oak: 'oak',
18
+ };
19
+
20
+ export const TreeType = {
21
+ Deciduous: 'deciduous',
22
+ Evergreen: 'evergreen',
23
+ };
@@ -0,0 +1,4 @@
1
+ export { Tree } from './tree.js';
2
+ export { Trellis } from './trellis.js';
3
+ export { TreePreset } from './presets/index.js';
4
+ export { BarkType, Billboard, LeafType, TreeType } from './enums.js';
@@ -0,0 +1,198 @@
1
+ import { BarkType, Billboard, LeafType, TreeType } from './enums.js';
2
+
3
+ export default class TreeOptions {
4
+ constructor() {
5
+ this.seed = 0;
6
+ this.type = TreeType.Deciduous;
7
+
8
+ // Bark parameters
9
+ this.bark = {
10
+ // The bark texture
11
+ type: BarkType.Oak,
12
+
13
+ // Tint of the tree trunk
14
+ tint: 0xffffff,
15
+
16
+ // Use face normals for shading instead of vertex normals
17
+ flatShading: false,
18
+
19
+ // Apply texture to bark
20
+ textured: true,
21
+
22
+ // Scale for the texture
23
+ textureScale: { x: 1, y: 1 },
24
+ };
25
+
26
+ // Branch parameters
27
+ this.branch = {
28
+ // Number of branch recursion levels. 0 = trunk only
29
+ levels: 3,
30
+
31
+ // Angle of the child branches relative to the parent branch (degrees)
32
+ angle: {
33
+ 1: 70,
34
+ 2: 60,
35
+ 3: 60,
36
+ },
37
+
38
+ // Number of children per branch level
39
+ children: {
40
+ 0: 7,
41
+ 1: 7,
42
+ 2: 5,
43
+ },
44
+
45
+ // External force encouraging tree growth in a particular direction
46
+ force: {
47
+ direction: { x: 0, y: 1, z: 0 },
48
+ strength: 0.01,
49
+ },
50
+
51
+ // Amount of curling/twisting at each branch level
52
+ gnarliness: {
53
+ 0: 0.15,
54
+ 1: 0.2,
55
+ 2: 0.3,
56
+ 3: 0.02,
57
+ },
58
+
59
+ // Length of each branch level
60
+ length: {
61
+ 0: 20,
62
+ 1: 20,
63
+ 2: 10,
64
+ 3: 1,
65
+ },
66
+
67
+ // Radius of each branch level
68
+ radius: {
69
+ 0: 1.5,
70
+ 1: 0.7,
71
+ 2: 0.7,
72
+ 3: 0.7,
73
+ },
74
+
75
+ // Number of sections per branch level
76
+ sections: {
77
+ 0: 12,
78
+ 1: 10,
79
+ 2: 8,
80
+ 3: 6,
81
+ },
82
+
83
+ // Number of radial segments per branch level
84
+ segments: {
85
+ 0: 8,
86
+ 1: 6,
87
+ 2: 4,
88
+ 3: 3,
89
+ },
90
+
91
+ // Defines where child branches start forming on the parent branch
92
+ start: {
93
+ 1: 0.4,
94
+ 2: 0.3,
95
+ 3: 0.3,
96
+ },
97
+
98
+ // Taper at each branch level
99
+ taper: {
100
+ 0: 0.7,
101
+ 1: 0.7,
102
+ 2: 0.7,
103
+ 3: 0.7,
104
+ },
105
+
106
+ // Amount of twist at each branch level
107
+ twist: {
108
+ 0: 0,
109
+ 1: 0,
110
+ 2: 0,
111
+ 3: 0,
112
+ },
113
+ };
114
+
115
+ // Leaf parameters
116
+ this.leaves = {
117
+ // Leaf texture to use
118
+ type: LeafType.Oak,
119
+
120
+ // Whether to use single or double/perpendicular billboards
121
+ billboard: Billboard.Double,
122
+
123
+ // Angle of leaves relative to parent branch (degrees)
124
+ angle: 10,
125
+
126
+ // Number of leaves
127
+ count: 1,
128
+
129
+ // Where leaves start to grow on the length of the branch (0 to 1)
130
+ start: 0,
131
+
132
+ // Size of the leaves
133
+ size: 2.5,
134
+
135
+ // Variance in leaf size between each instance
136
+ sizeVariance: 0.7,
137
+
138
+ // Tint color for the leaves
139
+ tint: 0xffffff,
140
+
141
+ // Controls transparency of leaf texture
142
+ alphaTest: 0.5,
143
+ };
144
+
145
+ // Trellis parameters
146
+ this.trellis = {
147
+ // Whether trellis is enabled
148
+ enabled: false,
149
+
150
+ // Position of trellis (z is distance from tree)
151
+ position: { x: 0, y: 0, z: -2 },
152
+
153
+ // Width of trellis grid (X direction)
154
+ width: 10,
155
+
156
+ // Height of trellis grid (Y direction)
157
+ height: 20,
158
+
159
+ // Distance between grid lines
160
+ spacing: 2,
161
+
162
+ // Force parameters
163
+ force: {
164
+ // How strongly branches bend toward trellis
165
+ strength: 0.02,
166
+ // Maximum distance at which trellis affects branches
167
+ maxDistance: 3,
168
+ // Distance falloff exponent (1 = linear, 2 = quadratic)
169
+ falloff: 1,
170
+ },
171
+
172
+ // Radius of trellis cylinders
173
+ cylinderRadius: 0.05,
174
+
175
+ // Whether to show trellis geometry
176
+ visible: true,
177
+
178
+ // Color of trellis
179
+ color: 0x8b4513,
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Copies the values from source into this object
185
+ * @param {TreeOptions} source
186
+ */
187
+ copy(source, target = this) {
188
+ for (let key in source) {
189
+ if (source.hasOwnProperty(key) && target.hasOwnProperty(key)) {
190
+ if (typeof source[key] === 'object' && source[key] !== null) {
191
+ this.copy(source[key], target[key]);
192
+ } else {
193
+ target[key] = source[key];
194
+ }
195
+ }
196
+ }
197
+ }
198
+ }
@@ -0,0 +1,96 @@
1
+ {
2
+ "seed": 29919,
3
+ "type": "deciduous",
4
+ "bark": {
5
+ "type": "oak",
6
+ "tint": 13552830,
7
+ "flatShading": false,
8
+ "textured": true,
9
+ "textureScale": {
10
+ "x": 0.5,
11
+ "y": 5
12
+ }
13
+ },
14
+ "branch": {
15
+ "levels": 3,
16
+ "angle": {
17
+ "1": 39,
18
+ "2": 39,
19
+ "3": 51
20
+ },
21
+ "children": {
22
+ "0": 10,
23
+ "1": 4,
24
+ "2": 3
25
+ },
26
+ "force": {
27
+ "direction": {
28
+ "x": 0,
29
+ "y": 1,
30
+ "z": 0
31
+ },
32
+ "strength": -0.010869565217391311
33
+ },
34
+ "gnarliness": {
35
+ "0": -0.05,
36
+ "1": 0.2,
37
+ "2": 0.16,
38
+ "3": 0.049999999999999996
39
+ },
40
+ "length": {
41
+ "0": 45,
42
+ "1": 29.42,
43
+ "2": 15.3,
44
+ "3": 4.6
45
+ },
46
+ "radius": {
47
+ "0": 3.03,
48
+ "1": 0.53,
49
+ "2": 0.79,
50
+ "3": 1.11
51
+ },
52
+ "sections": {
53
+ "0": 12,
54
+ "1": 8,
55
+ "2": 6,
56
+ "3": 4
57
+ },
58
+ "segments": {
59
+ "0": 8,
60
+ "1": 6,
61
+ "2": 4,
62
+ "3": 3
63
+ },
64
+ "start": {
65
+ "1": 0.32,
66
+ "2": 0.34,
67
+ "3": 0
68
+ },
69
+ "taper": {
70
+ "0": 0.7,
71
+ "1": 0.6199999999999999,
72
+ "2": 0.7599999999999999,
73
+ "3": 0
74
+ },
75
+ "twist": {
76
+ "0": 0.09,
77
+ "1": -0.07,
78
+ "2": 0,
79
+ "3": 0
80
+ }
81
+ },
82
+ "leaves": {
83
+ "type": "ash",
84
+ "billboard": "double",
85
+ "angle": 30,
86
+ "count": 10,
87
+ "start": 0.01,
88
+ "size": 4.62,
89
+ "sizeVariance": 0.72,
90
+ "tint": 16777215,
91
+ "alphaTest": 0.5
92
+ },
93
+ "trellis": {
94
+ "enabled": false
95
+ }
96
+ }
@@ -0,0 +1,96 @@
1
+ {
2
+ "seed": 36330,
3
+ "type": "deciduous",
4
+ "bark": {
5
+ "type": "oak",
6
+ "tint": 13552830,
7
+ "flatShading": false,
8
+ "textured": true,
9
+ "textureScale": {
10
+ "x": 0.5,
11
+ "y": 5.0
12
+ }
13
+ },
14
+ "branch": {
15
+ "levels": 3,
16
+ "angle": {
17
+ "1": 48,
18
+ "2": 75,
19
+ "3": 60
20
+ },
21
+ "children": {
22
+ "0": 7,
23
+ "1": 4,
24
+ "2": 3
25
+ },
26
+ "force": {
27
+ "direction": {
28
+ "x": 0,
29
+ "y": 1,
30
+ "z": 0
31
+ },
32
+ "strength": -0.06
33
+ },
34
+ "gnarliness": {
35
+ "0": 0.03,
36
+ "1": 0.25,
37
+ "2": 0.2,
38
+ "3": 0.09
39
+ },
40
+ "length": {
41
+ "0": 43.47,
42
+ "1": 27.14,
43
+ "2": 9.51,
44
+ "3": 4.6
45
+ },
46
+ "radius": {
47
+ "0": 2,
48
+ "1": 0.63,
49
+ "2": 0.76,
50
+ "3": 0.7
51
+ },
52
+ "sections": {
53
+ "0": 12,
54
+ "1": 8,
55
+ "2": 6,
56
+ "3": 4
57
+ },
58
+ "segments": {
59
+ "0": 12,
60
+ "1": 6,
61
+ "2": 4,
62
+ "3": 3
63
+ },
64
+ "start": {
65
+ "1": 0.23,
66
+ "2": 0.33,
67
+ "3": 0
68
+ },
69
+ "taper": {
70
+ "0": 0.7,
71
+ "1": 0.7,
72
+ "2": 0.7,
73
+ "3": 0.7
74
+ },
75
+ "twist": {
76
+ "0": 0.09,
77
+ "1": -0.07,
78
+ "2": 0,
79
+ "3": 0
80
+ }
81
+ },
82
+ "leaves": {
83
+ "type": "ash",
84
+ "billboard": "double",
85
+ "angle": 55,
86
+ "count": 16,
87
+ "start": 0,
88
+ "size": 2.67,
89
+ "sizeVariance": 0.72,
90
+ "tint": 16777215,
91
+ "alphaTest": 0.5
92
+ },
93
+ "trellis": {
94
+ "enabled": false
95
+ }
96
+ }