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.
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/package.json +47 -0
- package/src/lib/assets/bark/README.md +8 -0
- package/src/lib/assets/bark/birch_ao_1k.jpg +0 -0
- package/src/lib/assets/bark/birch_color_1k.jpg +0 -0
- package/src/lib/assets/bark/birch_normal_1k.jpg +0 -0
- package/src/lib/assets/bark/birch_roughness_1k.jpg +0 -0
- package/src/lib/assets/bark/oak_ao_1k.jpg +0 -0
- package/src/lib/assets/bark/oak_color_1k.jpg +0 -0
- package/src/lib/assets/bark/oak_normal_1k.jpg +0 -0
- package/src/lib/assets/bark/oak_roughness_1k.jpg +0 -0
- package/src/lib/assets/bark/pine_ao_1k.jpg +0 -0
- package/src/lib/assets/bark/pine_color_1k.jpg +0 -0
- package/src/lib/assets/bark/pine_normal_1k.jpg +0 -0
- package/src/lib/assets/bark/pine_roughness_1k.jpg +0 -0
- package/src/lib/assets/bark/willow_ao_1k.jpg +0 -0
- package/src/lib/assets/bark/willow_color_1k.jpg +0 -0
- package/src/lib/assets/bark/willow_normal_1k.jpg +0 -0
- package/src/lib/assets/bark/willow_roughness_1k.jpg +0 -0
- package/src/lib/assets/leaves/ash_color.png +0 -0
- package/src/lib/assets/leaves/aspen_color.png +0 -0
- package/src/lib/assets/leaves/oak_color.png +0 -0
- package/src/lib/assets/leaves/pine_color.png +0 -0
- package/src/lib/branch.js +28 -0
- package/src/lib/enums.js +23 -0
- package/src/lib/index.js +4 -0
- package/src/lib/options.js +198 -0
- package/src/lib/presets/ash_large.json +96 -0
- package/src/lib/presets/ash_medium.json +96 -0
- package/src/lib/presets/ash_small.json +96 -0
- package/src/lib/presets/aspen_large.json +96 -0
- package/src/lib/presets/aspen_medium.json +96 -0
- package/src/lib/presets/aspen_small.json +96 -0
- package/src/lib/presets/bush_1.json +96 -0
- package/src/lib/presets/bush_2.json +96 -0
- package/src/lib/presets/bush_3.json +96 -0
- package/src/lib/presets/index.js +47 -0
- package/src/lib/presets/oak_large.json +96 -0
- package/src/lib/presets/oak_medium.json +96 -0
- package/src/lib/presets/oak_small.json +96 -0
- package/src/lib/presets/pine_large.json +96 -0
- package/src/lib/presets/pine_medium.json +96 -0
- package/src/lib/presets/pine_small.json +96 -0
- package/src/lib/presets/trellis.json +112 -0
- package/src/lib/rng.js +22 -0
- package/src/lib/textures.js +105 -0
- package/src/lib/tree.js +1062 -0
- package/src/lib/trellis.js +135 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Trellis structure for guiding tree branch growth
|
|
5
|
+
* Creates a grid of cylinders that branches can be attracted to
|
|
6
|
+
*/
|
|
7
|
+
export class Trellis extends THREE.Group {
|
|
8
|
+
/**
|
|
9
|
+
* @param {Object} options Trellis configuration
|
|
10
|
+
*/
|
|
11
|
+
constructor(options) {
|
|
12
|
+
super();
|
|
13
|
+
this.name = 'Trellis';
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.material = null;
|
|
16
|
+
this.hCylinderGeo = null;
|
|
17
|
+
this.vCylinderGeo = null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Generate the trellis geometry
|
|
22
|
+
*/
|
|
23
|
+
generate() {
|
|
24
|
+
const t = this.options;
|
|
25
|
+
|
|
26
|
+
// Clear existing geometry
|
|
27
|
+
this.dispose();
|
|
28
|
+
|
|
29
|
+
this.material = new THREE.MeshStandardMaterial({
|
|
30
|
+
color: t.color,
|
|
31
|
+
roughness: 0.8,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Create shared cylinder geometries
|
|
35
|
+
this.hCylinderGeo = new THREE.CylinderGeometry(
|
|
36
|
+
t.cylinderRadius,
|
|
37
|
+
t.cylinderRadius,
|
|
38
|
+
t.width,
|
|
39
|
+
8
|
|
40
|
+
);
|
|
41
|
+
this.hCylinderGeo.rotateZ(Math.PI / 2);
|
|
42
|
+
|
|
43
|
+
this.vCylinderGeo = new THREE.CylinderGeometry(
|
|
44
|
+
t.cylinderRadius,
|
|
45
|
+
t.cylinderRadius,
|
|
46
|
+
t.height,
|
|
47
|
+
8
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// Horizontal lines
|
|
51
|
+
const hLineCount = Math.floor(t.height / t.spacing) + 1;
|
|
52
|
+
for (let i = 0; i < hLineCount; i++) {
|
|
53
|
+
const y = i * t.spacing;
|
|
54
|
+
const mesh = new THREE.Mesh(this.hCylinderGeo, this.material);
|
|
55
|
+
mesh.position.set(t.position.x, t.position.y + y, t.position.z);
|
|
56
|
+
this.add(mesh);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Vertical lines
|
|
60
|
+
const vLineCount = Math.floor(t.width / t.spacing) + 1;
|
|
61
|
+
for (let i = 0; i < vLineCount; i++) {
|
|
62
|
+
const x = -t.width / 2 + i * t.spacing;
|
|
63
|
+
const mesh = new THREE.Mesh(this.vCylinderGeo, this.material);
|
|
64
|
+
mesh.position.set(t.position.x + x, t.position.y + t.height / 2, t.position.z);
|
|
65
|
+
this.add(mesh);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Find the nearest point on the trellis grid to a given position
|
|
71
|
+
* @param {THREE.Vector3} position
|
|
72
|
+
* @returns {THREE.Vector3}
|
|
73
|
+
*/
|
|
74
|
+
getNearestPoint(position) {
|
|
75
|
+
const t = this.options;
|
|
76
|
+
const trellisX = t.position.x;
|
|
77
|
+
const trellisY = t.position.y;
|
|
78
|
+
const trellisZ = t.position.z;
|
|
79
|
+
|
|
80
|
+
// Trellis bounds
|
|
81
|
+
const minX = trellisX - t.width / 2;
|
|
82
|
+
const maxX = trellisX + t.width / 2;
|
|
83
|
+
const minY = trellisY;
|
|
84
|
+
const maxY = trellisY + t.height;
|
|
85
|
+
|
|
86
|
+
// Clamp position to trellis bounds for projection
|
|
87
|
+
const clampedX = Math.max(minX, Math.min(maxX, position.x));
|
|
88
|
+
const clampedY = Math.max(minY, Math.min(maxY, position.y));
|
|
89
|
+
|
|
90
|
+
// Find nearest horizontal line (Y = constant)
|
|
91
|
+
const nearestHLineY = Math.round((clampedY - minY) / t.spacing) * t.spacing + minY;
|
|
92
|
+
const finalHLineY = Math.max(minY, Math.min(maxY, nearestHLineY));
|
|
93
|
+
|
|
94
|
+
// Find nearest vertical line (X = constant)
|
|
95
|
+
const nearestVLineX = Math.round((clampedX - minX) / t.spacing) * t.spacing + minX;
|
|
96
|
+
const finalVLineX = Math.max(minX, Math.min(maxX, nearestVLineX));
|
|
97
|
+
|
|
98
|
+
// Point on nearest horizontal line (X can vary along the line)
|
|
99
|
+
const pointOnHLine = new THREE.Vector3(clampedX, finalHLineY, trellisZ);
|
|
100
|
+
|
|
101
|
+
// Point on nearest vertical line (Y can vary along the line)
|
|
102
|
+
const pointOnVLine = new THREE.Vector3(finalVLineX, clampedY, trellisZ);
|
|
103
|
+
|
|
104
|
+
// Return whichever is closer
|
|
105
|
+
const distH = position.distanceTo(pointOnHLine);
|
|
106
|
+
const distV = position.distanceTo(pointOnVLine);
|
|
107
|
+
|
|
108
|
+
return distH < distV ? pointOnHLine : pointOnVLine;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Clean up geometry and materials
|
|
113
|
+
*/
|
|
114
|
+
dispose() {
|
|
115
|
+
this.children.forEach(child => {
|
|
116
|
+
if (child.geometry) {
|
|
117
|
+
child.geometry = null;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
this.clear();
|
|
121
|
+
|
|
122
|
+
if (this.hCylinderGeo) {
|
|
123
|
+
this.hCylinderGeo.dispose();
|
|
124
|
+
this.hCylinderGeo = null;
|
|
125
|
+
}
|
|
126
|
+
if (this.vCylinderGeo) {
|
|
127
|
+
this.vCylinderGeo.dispose();
|
|
128
|
+
this.vCylinderGeo = null;
|
|
129
|
+
}
|
|
130
|
+
if (this.material) {
|
|
131
|
+
this.material.dispose();
|
|
132
|
+
this.material = null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|