Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added color/alpha cycling #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 175 additions & 9 deletions js/recursion.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,102 @@ var RENDER_MODES = {
Sketched: 'sketched'
};

var DEFAULTS = {

// Hue
START_HUE: {
MIN: 0,
MAX: 360,
DEF: 0,
STEP: 0.1,
NAME: 'Hue (start)'
},
END_HUE: {
MIN: 0,
MAX: 360,
DEF: 0,
STEP: 0.1,
NAME: 'Hue (end)'
},
STEP_HUE: {
MIN: 0.00001,
MAX: 10.0,
DEF: 1,
STEP: 0.00001,
NAME: 'Hue (step)'
},

// Saturation
START_SATURATION: {
MIN: 0,
MAX: 100,
DEF: 0,
STEP: 0.01,
NAME: 'Saturation (start)'
},
END_SATURATION: {
MIN: 0,
MAX: 100,
DEF: 0,
STEP: 0.01,
NAME: 'Saturation (end)'
},
STEP_SATURATION: {
MIN: 0.00001,
MAX: 10.0,
DEF: 0.1,
STEP: 0.00001,
NAME: 'Saturation (step)'
},

// Lightness
START_LIGHTNESS: {
MIN: 0,
MAX: 100,
DEF: 0,
STEP: 0.01,
NAME: 'Lightness (start)'
},
END_LIGHTNESS: {
MIN: 0,
MAX: 100,
DEF: 0,
STEP: 0.01,
NAME: 'Lightness (end)'
},
STEP_LIGHTNESS: {
MIN: 0.00001,
MAX: 10.0,
DEF: 0.1,
STEP: 0.00001,
NAME: 'Lightness (step)'
},

// Alpha
START_ALPHA: {
MIN: 0,
MAX: 1,
DEF: 1,
STEP: 0.0001,
NAME: 'Opacity (start)'
},
END_ALPHA: {
MIN: 0,
MAX: 1,
DEF: 1,
STEP: 0.0001,
NAME: 'Opacity (end)'
},
STEP_ALPHA: {
MIN: 0.00001,
MAX: 0.1,
DEF: 0.001,
STEP: 0.00001,
NAME: 'Opacity (step)'
}
};


PRESETS['Vines'] = {RENDER_MODE:RENDER_MODES.Darkness,BRANCH_PROBABILITY:0.2572,MAX_CONCURRENT:388,NUM_BRANCHES:4,MIN_RADIUS:0.1,MAX_RADIUS:69,MIN_WANDER_STEP:1.0184,MAX_WANDER_STEP:0.1702,MIN_GROWTH_RATE:10.6214,MAX_GROWTH_RATE:11.8251,MIN_SHRINK_RATE:0.99656,MAX_SHRINK_RATE:0.91265,MIN_DIVERGENCE:0.5101,MAX_DIVERGENCE:0.37466};
PRESETS['Fibrous'] = {RENDER_MODE:RENDER_MODES.Segmented,BRANCH_PROBABILITY:0.05,MAX_CONCURRENT:800,NUM_BRANCHES:3,MIN_RADIUS:0.1,MAX_RADIUS:50,MIN_WANDER_STEP:0.28,MAX_WANDER_STEP:0.7,MIN_GROWTH_RATE:5,MAX_GROWTH_RATE:9,MIN_SHRINK_RATE:0.98,MAX_SHRINK_RATE:0.99,MIN_DIVERGENCE:0.01,MAX_DIVERGENCE:0.05};
PRESETS['Graffiti'] = {RENDER_MODE:RENDER_MODES.Sketched,BRANCH_PROBABILITY:0.05,MAX_CONCURRENT:500,NUM_BRANCHES:6,MIN_RADIUS:0.15,MAX_RADIUS:70,MIN_WANDER_STEP:0.1197,MAX_WANDER_STEP:1.8269,MIN_GROWTH_RATE:13.66,MAX_GROWTH_RATE:17.35,MIN_SHRINK_RATE:0.95,MAX_SHRINK_RATE:0.98,MIN_DIVERGENCE:1.3268,MAX_DIVERGENCE:1.3885};
Expand All @@ -46,6 +142,15 @@ PRESETS['Vegetable Root'] = {RENDER_MODE:RENDER_MODES.Darkness,BRANCH_PROBABILIT
PRESETS['Hairball'] = {RENDER_MODE:RENDER_MODES.Sketched,BRANCH_PROBABILITY:0.6,MAX_CONCURRENT:800,MAX_DIVERGENCE:2.1,MAX_GROWTH_RATE:4.5,MAX_RADIUS:30,MAX_SHRINK_RATE:0.992,MAX_WANDER_STEP:0.2,MIN_DIVERGENCE:2,MIN_GROWTH_RATE:3.5,MIN_RADIUS:0.5,MIN_SHRINK_RATE:0.992,MIN_WANDER_STEP:0.1,NUM_BRANCHES:7};
PRESETS['Intenstines'] = {RENDER_MODE:RENDER_MODES.Darkness,BRANCH_PROBABILITY:1,MAX_CONCURRENT:350,NUM_BRANCHES:3,MIN_RADIUS:0.1,MAX_RADIUS:100,MIN_WANDER_STEP:0.1,MAX_WANDER_STEP:0.72,MIN_GROWTH_RATE:0.9,MAX_GROWTH_RATE:6.15,MIN_SHRINK_RATE:0.935,MAX_SHRINK_RATE:0.999,MIN_DIVERGENCE:0.01,MAX_DIVERGENCE:0.05};

// Make sure defaults are set in presets (easy to add new props)
for(var preset_prop in PRESETS) {
for(var default_prop in DEFAULTS) {
if (typeof PRESETS[preset_prop][default_prop] == 'undefined') {
PRESETS[preset_prop][default_prop] = DEFAULTS[default_prop].DEF;
}
}
}

function configure(settings) {
for(var prop in settings) {
CONFIG[prop] = settings[prop];
Expand Down Expand Up @@ -96,6 +201,12 @@ var Branch = function(x, y, theta, radius, scale, generation) {
this.wanderStep = random(CONFIG.MIN_WANDER_STEP, CONFIG.MAX_WANDER_STEP);
this.growthRate = random(CONFIG.MIN_GROWTH_RATE, CONFIG.MAX_GROWTH_RATE);
this.shrinkRate = random(CONFIG.MIN_SHRINK_RATE, CONFIG.MAX_SHRINK_RATE);

// Store these in each branch to cycle
this.hue = CONFIG.START_HUE;
this.saturation = CONFIG.START_SATURATION;
this.lightness = CONFIG.START_LIGHTNESS;
this.alpha = CONFIG.START_ALPHA;
}

Branch.prototype = {
Expand Down Expand Up @@ -126,6 +237,12 @@ Branch.prototype = {

branch.generation = this.generation + 1;

// Copy parents color settings
branch.hue = this.hue;
branch.saturation = this.saturation;
branch.lightness = this.lightness;
branch.alpha = this.alpha;

BRANCHES.push(branch);
}

Expand All @@ -138,13 +255,37 @@ Branch.prototype = {
}
},

// Steps up/down a value to the min or max by 1 step
step: function(value, min, max, step) {
if (min < max) {
value += step;
if (value > max) value = max;
} else if (min > max) {
value -= step;
if (value < max) value = max;
}
return value;
},

render: function(context) {

if(this.growing) {

var x1, x2, y1, y2;
var x1, x2, y1, y2, color;
var scale = this.scale;
var radius = this.radius * scale;

if (CONFIG.ENABLE_COLOR) {
// Cycle the colors and alpha
this.hue = this.step(this.hue, CONFIG.START_HUE, CONFIG.END_HUE, CONFIG.STEP_HUE);
this.saturation = this.step(this.saturation, CONFIG.START_SATURATION, CONFIG.END_SATURATION, CONFIG.STEP_SATURATION);
this.lightness = this.step(this.lightness, CONFIG.START_LIGHTNESS, CONFIG.END_LIGHTNESS, CONFIG.STEP_LIGHTNESS);
this.alpha = this.step(this.alpha, CONFIG.STEP_ALPHA, CONFIG.END_ALPHA, CONFIG.STEP_ALPHA);

color = 'hsla('+this.hue+','+this.saturation+'%,'+this.lightness+'%,'+this.alpha+')';
} else {
color = false;
}

context.save();

Expand All @@ -165,7 +306,7 @@ Branch.prototype = {
}

context.lineWidth = radius + scale;
context.strokeStyle = '#000';
context.strokeStyle = color ? color: '#000';
context.lineCap = 'round';
context.stroke();
context.closePath();
Expand All @@ -176,7 +317,7 @@ Branch.prototype = {
context.lineTo(this.x, this.y);

context.lineWidth = radius;
context.strokeStyle = '#FFF';
context.strokeStyle = color ? color: '#FFF';
context.lineCap = 'round';
context.stroke();

Expand All @@ -196,8 +337,8 @@ Branch.prototype = {
y2 = this.y + Math.sin(this.theta + HALF_PI) * radius;

context.lineWidth = 0.5 + scale;
context.strokeStyle = '#000';
context.fillStyle = '#FFF';
context.strokeStyle = color ? color: '#000';
context.fillStyle = color ? color: '#FFF';
context.lineCap = 'round';

// Starting point
Expand Down Expand Up @@ -246,9 +387,9 @@ Branch.prototype = {
y2 = this.y + Math.sin(this.theta + HALF_PI) * radius;

context.lineWidth = scale;
context.strokeStyle = 'rgba(255,255,255,0.9)';
context.strokeStyle = color ? color: 'rgba(255,255,255,0.9)';
context.lineCap = 'round';
context.fillStyle = '#111';
context.fillStyle = color ? color: '#111';

// Starting point
if(this.generation === 1 && this.age === 1) {
Expand All @@ -264,7 +405,7 @@ Branch.prototype = {
context.shadowOffsetX = scale;
context.shadowOffsetY = scale;
context.shadowBlur = scale;
context.shadowColor = '#111';
context.shadowColor = color ? color: '#111';
}

// Draw ribbon
Expand Down Expand Up @@ -454,6 +595,19 @@ function randomise() {
CONFIG.MAX_SHRINK_RATE = random(CONFIG.MIN_SHRINK_RATE,0.999);
CONFIG.MIN_DIVERGENCE = random(0.0,PI);
CONFIG.MAX_DIVERGENCE = random(CONFIG.MIN_DIVERGENCE,PI);

for(var prop in DEFAULTS) {
CONFIG[prop] = random(DEFAULTS[prop].MIN, DEFAULTS[prop].MAX);
}

// Get a random render mode
var render_modes = [];
for(var render_prop in RENDER_MODES) {
render_modes.push(RENDER_MODES[render_prop]);
}
var render_mode = Math.floor(random(0, render_modes.length));
CONFIG.RENDER_MODE = render_modes[render_mode];

Recursion.init();
GUI.listenAll();
}
Expand All @@ -476,6 +630,19 @@ GUI.add(CONFIG, 'MAX_SHRINK_RATE').name('Shrink (Max)').min(0.9).max(0.999).step
GUI.add(CONFIG, 'MIN_DIVERGENCE').name('Divergeence (Min)').min(0.0).max(PI).step(0.01);
GUI.add(CONFIG, 'MAX_DIVERGENCE').name('Divergeence (Max)').min(0.0).max(PI).step(0.01);

// Add GUI for props
for(var prop in DEFAULTS) {
GUI.add(CONFIG, prop).
name(DEFAULTS[prop].NAME).
min(DEFAULTS[prop].MIN).
max(DEFAULTS[prop].MAX).
step(DEFAULTS[prop].STEP);
}

// Add enable color checkbox
CONFIG.ENABLE_COLOR = false;
GUI.add(CONFIG, 'ENABLE_COLOR').name('Enable Color');

GUI.add(preset, 'key').name('Preset Behaviors').options(keys).onChange(function(){
configure(PRESETS[preset.key]);
Recursion.init();
Expand All @@ -494,5 +661,4 @@ GUI.add(Recursion, 'init').name('Clear & Regenerate');
* INIT
* --------------------
*/

Recursion.init();