(i, count)
| 362 | } |
| 363 | |
| 364 | function createFractalTree(i, count) { |
| 365 | // Fractal Tree parameters |
| 366 | const trunkLength = 35; // Initial trunk length |
| 367 | const branchRatio = 0.67; // Each branch is this ratio of parent length |
| 368 | const maxDepth = 6; // Maximum branching depth |
| 369 | const branchAngle = Math.PI / 5; // Angle between branches (36 degrees) |
| 370 | |
| 371 | // Pre-calculate the total particles needed per depth level |
| 372 | // Distribute particles more towards deeper levels |
| 373 | const particlesPerLevel = []; |
| 374 | let totalWeight = 0; |
| 375 | |
| 376 | for (let depth = 0; depth <= maxDepth; depth++) { |
| 377 | // More branches at deeper levels, distribute particles accordingly |
| 378 | // Each level has 2^depth branches |
| 379 | const branches = Math.pow(2, depth); |
| 380 | const weight = branches * Math.pow(branchRatio, depth); |
| 381 | totalWeight += weight; |
| 382 | particlesPerLevel.push(weight); |
| 383 | } |
| 384 | |
| 385 | // Normalize to get actual count per level |
| 386 | let cumulativeCount = 0; |
| 387 | const particleCount = []; |
| 388 | |
| 389 | for (let depth = 0; depth <= maxDepth; depth++) { |
| 390 | const levelCount = Math.floor((particlesPerLevel[depth] / totalWeight) * count); |
| 391 | particleCount.push(levelCount); |
| 392 | cumulativeCount += levelCount; |
| 393 | } |
| 394 | |
| 395 | // Adjust the last level to ensure we use exactly count particles |
| 396 | particleCount[maxDepth] += (count - cumulativeCount); |
| 397 | |
| 398 | // Determine which depth level this particle belongs to |
| 399 | let depth = 0; |
| 400 | let levelStartIndex = 0; |
| 401 | |
| 402 | while (depth < maxDepth && i >= levelStartIndex + particleCount[depth]) { |
| 403 | levelStartIndex += particleCount[depth]; |
| 404 | depth++; |
| 405 | } |
| 406 | |
| 407 | // Calculate the relative index within this depth level |
| 408 | const indexInLevel = i - levelStartIndex; |
| 409 | const levelCount = particleCount[depth]; |
| 410 | |
| 411 | // Calculate position parameters |
| 412 | const t = indexInLevel / (levelCount || 1); // Normalized position in level |
| 413 | |
| 414 | // For the trunk (depth 0) |
| 415 | if (depth === 0) { |
| 416 | // Simple line for the trunk |
| 417 | return new THREE.Vector3( |
| 418 | (Math.random() * 2 - 1) * 0.5, // Small random spread for thickness |
| 419 | -trunkLength / 2 + t * trunkLength, |
| 420 | (Math.random() * 2 - 1) * 0.5 // Small random spread for thickness |
| 421 | ); |
nothing calls this directly
no outgoing calls
no test coverage detected