JSFiddle - React, Tailwind, and code Playground

by Michael Prosser

HTML

<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<canvas id="renderCanvas" touch-action="none"></canvas>
<div class="status">
  Forest Generator Ready...
</div>
<div class="controls">

<label>leafSize:</label>
<input type="number" step="0.1" min="0.01" max="1" value="0.1" id="control-leafSize" /><br />
<label>leafCount:</label>
<input type="number" step="1" min="0" max="20" value="0" id="control-leafCount" /><br />
<label>leafRange:</label>
<input type="number" step="0.1" min="0.1" max="5" value="1" id="control-leafRange" /><br />
<label>leafColor:</label>
<input type="color" value="#4A230F" id="control-leafColor" /><br />
<label>leafShape:</label>
<select id="control-leafShape">
  <option value="plane" selected>Plane</option>
  <option value="box">Box</option>
  <option value="0">Tetrahedron</option>
  <option value="1">Octahedron</option>
  <option value="2">Dodecahedron</option>
  <option value="3">Icosahedron</option>
  <option value="4">Rhombicuboctahedron</option>
  <option value="5">Triangular Prism</option>
  <option value="6">Pentagonal Prism</option>
  <option value="7">Hexagonal Prism</option>
  <option value="8">Square Pyramid (J1)</option>
  <option value="9">Pentagonal Pyramid (J2)</option>
  <option value="10">Triangular Dipyramid (J12)</option>
  <option value="11">Pentagonal Dipyramid (J13)</option>
  <option value="12">Elongated Square Dipyramid (J15)</option>
  <option value="13">Elongated Pentagonal Dipyramid (J16)</option>
  <option value="14">Elongated Pentagonal Cupola (J20)</option>
</select>
<br />

  <label>hasSubBranches: <input type="checkbox" id="control-hasSubBranches" value="1" checked /></label>
   <label>subBranchesBase:...

CSS

html,body{
  height:100%;
  margin:0px;
}
canvas{
  width:100%;
  height:100%;
}
select{
  max-width:160px;
}
.controls{
  position: fixed;
    z-index: 99;
    top: 0px;
    width: 160px;
    left: 0px;
    bottom: 0px;
    background-color: rgba(0,0,0,0.6);
    padding: 20px;
    color:#fff;
    line-height:32px;
    font-family:helvetica;
    font-size:11px;
}
.controls:hover{
  overflow-x:hidden;
  overflow-y:auto;
}
.status{
  position:fixed;
  z-index:999;
  bottom:0px;
  left:40%;
  right:40%;
  text-align:center;
  color:#ccc;
  background-color:#000;
  padding:4px;
  font-size:10px;
  font-family:helvetica;
}

JavaScript

PROCEDURALTREE = function(options,scene){

console.log("Creating Tree");

  var cached_this = this;
	
	function randomFloatFromInterval(min, max) { // min and max included 
	  return Math.random() * (max - min + 1) + min;
	}
  
  
  
  function applyLeaves(position,numberofleaves,size,range,shape){
  
  	if(!numberofleaves){ return false; }
  	if(!shape){ shape = 'plane'; }
  	if(!range){ range = 1; }
  
    
    var leaves = Array();
  
  	for(var i=0;i<numberofleaves;i++){
    	
      switch(shape){
      
      	case 'box':
        var mesh = new BABYLON.MeshBuilder.CreateBox("box", { height: size, width: size, depth: size }, scene);
        break;
      
      	case 'plane':
        var mesh = new BABYLON.MeshBuilder.CreatePlane("plane", { height: size, width: size, sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene);
        break;
        
        default:
        var mesh = new BABYLON.MeshBuilder.CreatePolyhedron("polyhedron", {type: parseInt(shape), size: size}, scene);
        break;
        
      }
      
      
      var offset = sphericalCoordinates(randomFloatFromInterval(range*-1, range),randomFloatFromInterval(1, 360),randomFloatFromInterval(1, 360));
    	
      mesh.position = new BABYLON.Vector3(position.x+offset.x,position.y+offset.y,position.z+offset.z);
      mesh.rotation = new BABYLON.Vector3(randomFloatFromInterval(Math.PI*-1, Math.PI),randomFloatFromInterval(Math.PI*-1, Math.PI),randomFloatFromInterval(Math.PI*-1, Math.PI));
      mesh.scaling = new BABYLON.Vector3(randomFloatFromInterval(size/2, size*2),randomFloatFromInterval(size/2, size*2),randomFloatFromInterval(size/2, size*2));
    	
      mesh.material = options.leafMaterial;
      
      
      leaves.push(mesh);
    
    }
    
    var merge = BABYLON.Mesh.MergeMeshes(leaves, true, true);
  
  
  }
  
  function sphericalCoordinates(r,O,o){
		
    "use strict";

    O = O * Math.PI / 180.0;
    o = o * Math.PI / 180.0;

    var x = r * Math.sin(o) * Math.cos(O);
    var y = r *...