···77} from "./helper/colorgradient";
88import { biomePresets } from "./presets";
99import { Octree } from "./helper/octree";
1010+import { type VertexInfo } from "./types";
10111112export type VegetationItem = {
1213 name: string;
···6566 constructor(opts: BiomeOptions = {}) {
6667 if (opts.preset) {
6768 const preset = biomePresets[opts.preset];
6969+6870 if (preset) {
6971 opts = {
7072 ...preset,
···175177 position: Vector3,
176178 radius: number,
177179 ): (Vector3 & { data?: VegetationItem })[] {
178178- return this.vegetationPositions.query(position, radius);
180180+ return this.vegetationPositions.queryBoxXYZ(
181181+ position.x,
182182+ position.y,
183183+ position.z,
184184+ radius,
185185+ );
186186+ }
187187+188188+ maxVegetationRadius(): number {
189189+ let max = 0;
190190+ for (const item of this.options.vegetation?.items ?? []) {
191191+ if (item.ground?.radius) {
192192+ max = Math.max(max, item.ground.radius);
193193+ }
194194+ }
195195+196196+ return max;
197197+ }
198198+199199+ vegetationHeightAndColorForFace(
200200+ a: Vector3,
201201+ b: Vector3,
202202+ c: Vector3,
203203+ color: Color,
204204+ sideLength: number,
205205+ ): {
206206+ heightA: number;
207207+ heightB: number;
208208+ heightC: number;
209209+ color: Color;
210210+ } {
211211+ const maxDist = this.maxVegetationRadius();
212212+ // use a to find all vegetation items, we add sideLength so that we also find vegetation from b and c
213213+ // that otherwise would be missed, because they are too far away from a
214214+ const vegetations = this.itemsAround(a, maxDist + sideLength * 2);
215215+216216+ // go through a, b and c and add heights for all vegetation items that are close enough (distance is closer than item.ground.radius)
217217+ let heightA = 0;
218218+ let heightB = 0;
219219+ let heightC = 0;
220220+221221+ let all = [a, b, c];
222222+ for (let j = 0; j < 3; j++) {
223223+ let p = all[j];
224224+225225+ for (const vegetation of vegetations) {
226226+ if (!vegetation.data?.ground?.radius) continue;
227227+228228+ let distance = p.distanceTo(vegetation);
229229+230230+ if (distance < vegetation.data.ground?.radius) {
231231+ let amount = Math.max(
232232+ 0,
233233+ 1 - distance / vegetation.data.ground.radius,
234234+ );
235235+236236+ amount = Math.pow(amount, 0.5);
237237+238238+ let height = vegetation.data.ground?.raise ?? 0;
239239+ height *= amount;
240240+241241+ if (j === 0) heightA += height;
242242+ if (j === 1) heightB += height;
243243+ if (j === 2) heightC += height;
244244+245245+ if (!vegetation.data.ground.color) continue;
246246+247247+ let newColor = new Color(vegetation.data.ground.color);
248248+249249+ // only lerp a third of the way, because we have three vertices
250250+ // so if all vertices are close enough, we lerp 3 times
251251+ color.lerp(newColor, amount / 3);
252252+ }
253253+ }
254254+ }
255255+256256+ return {
257257+ heightA,
258258+ heightB,
259259+ heightC,
260260+ color,
261261+ };
179262 }
180263}