Tree Generator V2

Developer
Size
5,891 Kb
Views
8,096

How do I make an tree generator v2?

An improved version of my random-walk tree generator, now in true 3D using THREE.js. I also added a way to export to an OBJ or an SDL file courtesy of Kevin Lubick at https://gist.github.com/kjlubick. What is a tree generator v2? How do you make a tree generator v2? This script and codes were developed by Ben Matthews on 20 December 2022, Tuesday.

Tree Generator V2 Previews

Tree Generator V2 - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>Tree Generator V2</title> <link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css'> <link rel="stylesheet" href="css/style.css">
</head>
<body> <div id="controls"> <button id="generate" class="btn btn-secondary" onclick="generateTree()">New Tree</button><br><br> <button id="saveOBJ" class="btn btn-secondary" onclick="exportSceneOBJ()">Save as OBJ file</button><br><br> <button id="saveSTL" class="btn btn-secondary" onclick="exportSceneSTL()">Save as STL file</button>
</div>
</div>
<div id="ThreeJS" style="z-index: 0; position: absolute; left:0px; top:30vh; height:70vh"></div> <!-- Trigger/Open The Modal -->
<button id="myBtn" class="btn btn-primary">

Tree Generator V2 - Script Codes CSS Codes

body
{	font-family: Monospace;	font-weight: bold;	background-color: black;	margin: 0px;	overflow: hidden;
}
#controls{ position:absolute; top:0; left:0; z-index:1; margin:20px;
}
.dg.ac{ position: absolute; z-index:2;
}
#myBtn{ position:absolute; bottom: 20px; right: 20px;
} /* The Modal (background) */
.modal { display: none; /* Hidden by default */ position: fixed; /* Stay in place */ z-index: 2; /* Sit on top */ left: 0; top: 0; width: 100%; /* Full width */ height: 100%; /* Full height */ overflow: auto; /* Enable scroll if needed */ background-color: rgb(0,0,0); /* Fallback color */ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
.modal-content { background-color: #fefefe; margin: 15% auto; /* 15% from the top and centered */ padding: 20px; border: 1px solid #888; width: 80%; /* Could be more or less, depending on screen size */
}
/* The Close Button */
.close { color: #aaa; float: right; font-size: 28px; font-weight: bold;
}
.close:hover,
.close:focus { color: black; text-decoration: none; cursor: pointer;
} 

Tree Generator V2 - Script Codes JS Codes

var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
var slices = 0;
var maxSlices = 2500;
var angleMod = 0.05;
var splitChance = .15;
var heightMod = 1;
var widthMod = .2;
var startingSize = 1;
var branchVariance = .3;
var sizeMod = 4;
var sizeDec = .03;
var sections = 10;
var objects = [];
var gui;
window.onload = function() { gui = new dat.GUI(); var controllers = []; controllers.push(gui.add(this, 'maxSlices', 100, 10000)); controllers.push(gui.add(this, 'splitChance', 0, 1, .01)); controllers.push(gui.add(this, 'angleMod', 0, .2, .01)); controllers.push(gui.add(this, 'heightMod', .1, 4, .1)); controllers.push(gui.add(this, 'widthMod', .1, 1, .05)); controllers.push(gui.add(this, 'startingSize', 0, 10, .01)); controllers.push(gui.add(this, 'sizeDec', .01, 1, .01)); controllers.push(gui.add(this, 'branchVariance', 0, 1, .01)); controllers.push(gui.add(this, 'sections', 3, 30, 1)); gui.add(this, 'randomizeVars'); gui.add(this, 'resetVars'); for (var i = 0; i < controllers.length; i++){ controllers[i].onFinishChange(function(){ generateTree(); }); }
};
function RW(x, y, z, size, tickOffset){ this.x = x; this.y = y; this.z = z; this.prevX = x; this.prevY = y; this.prevZ = z; this.prevSize = this.size; this.size = size; this.numTicks = tickOffset; this.speed = Math.random()*widthMod + .05; this.angle = Math.random()*2*Math.PI; this.angleMod = Math.random()*angleMod + .05; this.angleMod *= 2*Math.PI; this.geom = new THREE.Geometry(); this.update = function(){ slices++; this.prevX = this.x; this.prevY = this.y; this.prevZ = this.z; this.prevSize = this.size; this.x += Math.cos(this.angle)*this.speed*sizeMod; this.y += Math.sin(this.angle)*this.speed*sizeMod; this.z += heightMod; this.size -= sizeDec; if (this.size < 0) return; if (Math.random() < .5) this.angleMod *= -1; this.angle += Math.random()*this.angleMod; var vertices = []; for (var i = 0; i < sections; i++){ var mod = 0 if (this.numTicks%2 == 0) mod = .5; var ratio = (i+mod)/sections; var ratio2 = (i + .5 + mod)/sections; var a1 = ratio*2*Math.PI; var a2 = ratio2*2*Math.PI; vertices.push(new THREE.Vector3( (Math.cos(a1)*this.prevSize + this.prevX)*sizeMod, this.prevZ*sizeMod, (Math.sin(a1)*this.prevSize + this.prevY)*sizeMod )); vertices.push(new THREE.Vector3( (Math.cos(a2)*this.size + this.x)*sizeMod, this.z*sizeMod, (Math.sin(a2)*this.size + this.y)*sizeMod )); } var base = this.geom.vertices.length; for (var i = 0; i < vertices.length; i++){ this.geom.vertices.push(vertices[i]); } for (var i = 0; i < vertices.length; i++){ if (i%2 == 1){ this.geom.faces.push(new THREE.Face3( // base + i, base + (i+2)%vertices.length, base + (i+1)%vertices.length, base + i, )); } else { this.geom.faces.push(new THREE.Face3( base + i, base + (i+1)%vertices.length, base + (i+2)%vertices.length )); } } this.numTicks++; }
}
init();
animate();
function init()
{	scene = new THREE.Scene();	var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;	var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;	camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);	scene.add(camera);	camera.position.set(0,150,400);	camera.lookAt(scene.position);	//////////////	// RENDERER //	//////////////	if ( Detector.webgl ) renderer = new THREE.WebGLRenderer( {antialias:true} );	else renderer = new THREE.CanvasRenderer();	renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);	container = document.getElementById( 'ThreeJS' );	container.appendChild( renderer.domElement );	////////////	// EVENTS //	////////////	THREEx.WindowResize(renderer, camera);	THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });	//////////////	// CONTROLS //	//////////////	controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.autoRotate = true;	///////////	// STATS //	///////////	stats = new Stats();	stats.domElement.style.position = 'absolute';	stats.domElement.style.bottom = '0px';	stats.domElement.style.zIndex = 100;	container.appendChild( stats.domElement );	///////////	// LIGHT //	///////////	var light = new THREE.DirectionalLight(0xffffff);	light.position.set(200,1000,200);	scene.add(light);	var ambientLight = new THREE.AmbientLight(0x111111);	scene.add(ambientLight); //generate a tree: generateTree();
}
function clearScene(){ while(scene.children.length > 0){ scene.remove(scene.children[0]); }
}
function generateTree(){ slices = 0; for (var i = 0; i < objects.length; i++){ scene.remove(objects[i]); } objects = []; var rws = []; rws.push(new RW(0, 0, 0, startingSize, 0)); while(slices < maxSlices && rws.length > 0){ for (var i = rws.length-1; i > -1; i--){ rws[i].update(); if (rws[i].size < 0){ rws.splice(i, 0); continue; } if (slices < maxSlices && Math.random() < splitChance) rws.push(new RW( rws[i].x, rws[i].y, rws[i].z, rws[i].size*(Math.random()*branchVariance + (1 - branchVariance)), rws[i].numTicks%2 )); } } for (var i = 0; i < rws.length; i++){ rws[i].geom.computeFaceNormals(); // var material = new THREE.MeshPhongMaterial({color: 0xffffff}); var material = new THREE.MeshNormalMaterial(); // material.side = THREE.DoubleSide; material.perPixel = true; var object = new THREE.Mesh(rws[i].geom, material); object.name = "" + performance.now(); objects.push(object); scene.add(object); }
}
function animate()
{ requestAnimationFrame( animate ); render(); update();
}
function update()
{	// delta = change in time since last call (in seconds)	var delta = clock.getDelta();	// functionality provided by THREEx.KeyboardState.js	if ( keyboard.pressed("1") )	document.getElementById('message').innerHTML = ' Have a nice day! - 1';	if ( keyboard.pressed("2") )	document.getElementById('message').innerHTML = ' Have a nice day! - 2 ';	controls.update();	stats.update();
}
function randomizeVars(){ for (var i = 0; i < gui.__controllers.length - 2; i++){ var controller = gui.__controllers[i]; var range = controller.__max - controller.__min; console.log(range); var value = controller.__min + Math.random()*range; if (controller.__step > 1) value = Math.floor(value); controller.setValue(value); } generateTree();
}
function resetVars(){ for (var i = 0; i < gui.__controllers.length; i++){ gui.__controllers[i].setValue(gui.__controllers[i].initialValue); } generateTree();
}
function exportSceneOBJ(){ var date = new Date(); var exporter = new THREE.OBJExporter(); var output = exporter.parse(scene); var blob = new Blob([output], {type: "text/plain;charset=utf-8"}); saveAs(blob, "Tree_" + date.getTime() + ".obj");
}
function exportSceneSTL(){ var date = new Date(); saveSTL(scene, "TreeGeneratorSTL_" + date.getTime());
}
document.body.onmousedown = function() { controls.autoRotate = false;
}
document.body.onmouseup = function() { controls.autoRotate = true;
}
function render()
{	renderer.render( scene, camera );
}
// Get the modal
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on the button, open the modal
btn.onclick = function() { modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() { modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) { if (event.target == modal) { modal.style.display = "none"; }
}
Tree Generator V2 - Script Codes
Tree Generator V2 - Script Codes
Home Page Home
Developer Ben Matthews
Username tsuhre
Uploaded December 20, 2022
Rating 4
Size 5,891 Kb
Views 8,096
Do you need developer help for Tree Generator V2?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Ben Matthews (tsuhre) Script Codes
Create amazing web content with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!