Skip to content

Commit

Permalink
Added GaussianBoxBlur smoothing
Browse files Browse the repository at this point in the history
Minor optimizations to smoothing algorithms
Added a multiplier parameter to SmoothConservative
Removed smoothing from the generation functions; smoothing should be applied separately
Added a smoothing type option to the demo
Upgraded three.js from r67 to r69 for demo
  • Loading branch information
IceCreamYou committed Nov 16, 2014
1 parent 01885e5 commit f1b25e2
Show file tree
Hide file tree
Showing 15 changed files with 19,131 additions and 20,553 deletions.
4 changes: 4 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = function(grunt) {
'src/images.js',
'src/filters.js',
//'src/gaussian.js',
//'src/weightedBoxBlurGaussian.js',
'src/generators.js',
'src/materials.js',
'src/scatter.js',
Expand Down Expand Up @@ -61,6 +62,7 @@ module.exports = function(grunt) {
'src/images.js',
'src/filters.js',
'src/gaussian.js',
'src/weightedBoxBlurGaussian.js',
'src/generators.js',
'src/materials.js',
'src/scatter.js',
Expand All @@ -81,6 +83,7 @@ module.exports = function(grunt) {
'src/images.js',
'src/filters.js',
'src/gaussian.js',
'src/weightedBoxBlurGaussian.js',
'src/generators.js',
'src/materials.js',
'src/scatter.js',
Expand All @@ -96,6 +99,7 @@ module.exports = function(grunt) {
'src/images.js',
'src/filters.js',
'src/gaussian.js',
'src/weightedBoxBlurGaussian.js',
'src/generators.js',
'src/materials.js',
'src/scatter.js',
Expand Down
56 changes: 36 additions & 20 deletions build/THREE.Terrain.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* THREE.Terrain.js 1.1.0-20141113
* THREE.Terrain.js 1.1.0-20141116
*
* @author Isaac Sukin (http://www.isaacsukin.com/)
* @license MIT
Expand Down Expand Up @@ -765,9 +765,9 @@ THREE.Terrain.Edges = function(g, options, direction, distance, easing) {
* neighbors.
*/
THREE.Terrain.Smooth = function(g, options, weight) {
var heightmap = new Float32Array(g.length);
for (var i = 0, xl = options.xSegments + 1; i < xl; i++) {
for (var j = 0; j < options.ySegments + 1; j++) {
var heightmap = new Float64Array(g.length);
for (var i = 0, xl = options.xSegments + 1, yl = options.ySegments + 1; i < xl; i++) {
for (var j = 0; j < yl; j++) {
var sum = 0, c = 0;
for (var n = -1; n <= 1; n++) {
for (var m = -1; m <= 1; m++) {
Expand All @@ -794,14 +794,14 @@ THREE.Terrain.Smooth = function(g, options, weight) {
* Parameters are the same as those for {@link THREE.Terrain.DiamondSquare}.
*/
THREE.Terrain.SmoothMedian = function(g, options) {
var heightmap = new Float32Array(g.length),
var heightmap = new Float64Array(g.length),
neighborValues = [],
neighborKeys = [],
sortByValue = function(a, b) {
return neighborValues[a] - neighborValues[b];
};
for (var i = 0, xl = options.xSegments + 1; i < xl; i++) {
for (var j = 0; j < options.ySegments + 1; j++) {
for (var i = 0, xl = options.xSegments + 1, yl = options.ySegments + 1; i < xl; i++) {
for (var j = 0; j < yl; j++) {
neighborValues.length = 0;
neighborKeys.length = 0;
for (var n = -1; n <= 1; n++) {
Expand Down Expand Up @@ -833,26 +833,42 @@ THREE.Terrain.SmoothMedian = function(g, options) {
/**
* Smooth the terrain by clamping each point within its neighbors' extremes.
*
* Parameters are the same as those for {@link THREE.Terrain.DiamondSquare}.
* @param {THREE.Vector3[]} g
* The vertex array for plane geometry to modify with heightmap data. This
* method sets the `z` property of each vertex.
* @param {Object} options
* A map of settings that control how the terrain is constructed and
* displayed. Valid values are the same as those for the `options` parameter
* of {@link THREE.Terrain}().
* @param {Number} [multiplier=1]
* By default, this filter clamps each point within the highest and lowest
* value of its neighbors. This parameter is a multiplier for the range
* outside of which the point will be clamped. Higher values mean that the
* point can be farther outside the range of its neighbors.
*/
THREE.Terrain.SmoothConservative = function(g, options) {
var heightmap = new Float32Array(g.length);
for (var i = 0, xl = options.xSegments + 1; i < xl; i++) {
for (var j = 0; j < options.ySegments + 1; j++) {
THREE.Terrain.SmoothConservative = function(g, options, multiplier) {
var heightmap = new Float64Array(g.length);
for (var i = 0, xl = options.xSegments + 1, yl = options.ySegments + 1; i < xl; i++) {
for (var j = 0; j < yl; j++) {
var max = -Infinity,
min = Infinity;
for (var n = -1; n <= 1; n++) {
for (var m = -1; m <= 1; m++) {
var key = (j+n)*xl + i + m;
if (typeof g[key] !== 'undefined' && n && m) {
if (g[key].z < min) min = g[key].z;
else if (g[key].z > max) max = g[key].z;
if (g[key].z > max) max = g[key].z;
}
}
}
var kk = j*xl + i;
if (typeof multiplier === 'number') {
var halfdiff = (max - min) * 0.5,
middle = min + halfdiff;
max = middle + halfdiff * multiplier;
min = middle - halfdiff * multiplier;
}
heightmap[kk] = g[kk].z > max ? max : (g[kk].z < min ? min : g[kk].z);
if (heightmap[kk] === Infinity || heightmap[kk] === -Infinity) heightmap[kk] = g[kk].z;
}
}
for (var k = 0, l = g.length; k < l; k++) {
Expand Down Expand Up @@ -1024,7 +1040,7 @@ THREE.Terrain.DiamondSquare = function(g, options) {
xl = options.xSegments + 1,
yl = options.ySegments + 1;
for (i = 0; i <= segments; i++) {
heightmap[i] = new Float32Array(segments+1);
heightmap[i] = new Float64Array(segments+1);
}

// Generate heightmap
Expand Down Expand Up @@ -1068,7 +1084,7 @@ THREE.Terrain.DiamondSquare = function(g, options) {
}
}

THREE.Terrain.SmoothConservative(g, options);
//THREE.Terrain.SmoothConservative(g, options);
};

/**
Expand Down Expand Up @@ -1106,7 +1122,7 @@ THREE.Terrain.Fault = function(g, options) {
}
}
}
THREE.Terrain.Smooth(g, options);
//THREE.Terrain.Smooth(g, options);
};

/**
Expand Down Expand Up @@ -1278,7 +1294,7 @@ THREE.Terrain.HillIsland = (function() {
j = Math.floor(options.ySegments*(0.5+yDeviation) + Math.sin(d) * Math.random() * options.ySegments*(0.5-Math.abs(yDeviation)));
}
}
THREE.Terrain.Smooth(g, options, 3);
//THREE.Terrain.Smooth(g, options, 3);
};
})();

Expand Down Expand Up @@ -1441,7 +1457,7 @@ THREE.Terrain.SimplexLayers = function(g, options) {
// Store the array of white noise outside of the WhiteNoise function to
// avoid allocating a bunch of unnecessary arrays; we can just
// overwrite old data each time WhiteNoise() is called.
var data = new Float32Array((segments+1)*(segments+1));
var data = new Float64Array((segments+1)*(segments+1));

// Layer white noise at different resolutions.
var range = options.maxHeight - options.minHeight;
Expand All @@ -1450,7 +1466,7 @@ THREE.Terrain.SimplexLayers = function(g, options) {
}

// White noise creates some weird artifacts; fix them.
THREE.Terrain.Smooth(g, options, 1);
//THREE.Terrain.Smooth(g, options, 1);
THREE.Terrain.Clamp(g, {
maxHeight: options.maxHeight,
minHeight: options.minHeight,
Expand Down
4 changes: 2 additions & 2 deletions build/THREE.Terrain.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/THREE.Terrain.min.map

Large diffs are not rendered by default.

31 changes: 30 additions & 1 deletion demo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ if (/&?webgl=0\b/g.test(location.hash)) {
// Workaround: in Chrome, if a page is opened with window.open(), window.innerWidth and window.innerHeight will be zero.
if ( window.innerWidth === 0 ) { window.innerWidth = parent.innerWidth; window.innerHeight = parent.innerHeight; }

var camera, scene, renderer, clock, player, terrainScene, decoScene, controls = {}, fpsCamera, skyDome, skyLight, sand, water;
var camera, scene, renderer, clock, player, terrainScene, decoScene, lastOptions, controls = {}, fpsCamera, skyDome, skyLight, sand, water;
var INV_MAX_FPS = 1 / 100,
frameDelta = 0,
paused = true,
Expand Down Expand Up @@ -152,6 +152,7 @@ function setupDatGui() {
});
this.easing = 'Linear';
this.heightmap = 'PerlinDiamond';
this.smoothing = 'None';
this.maxHeight = 200;
this.segments = webglExists ? 63 : 31;
this.steps = 1;
Expand Down Expand Up @@ -198,6 +199,7 @@ function setupDatGui() {
};
scene.remove(terrainScene);
terrainScene = THREE.Terrain(o);
applySmoothing(that.smoothing, o);
scene.add(terrainScene);
skyDome.visible = sand.visible = water.visible = that.texture != 'Wireframe';
var he = document.getElementById('heightmap');
Expand All @@ -206,6 +208,7 @@ function setupDatGui() {
THREE.Terrain.toHeightmap(terrainScene.children[0].geometry.vertices, o);
}
that['Scatter meshes']();
lastOptions = o;
};
function altitudeProbability(z) {
if (z > -80 && z < -50) return THREE.Terrain.EaseInOut((z + 80) / (-50 + 80)) * that.spread * 0.002;
Expand Down Expand Up @@ -284,6 +287,13 @@ function setupDatGui() {
var heightmapFolder = gui.addFolder('Heightmap');
heightmapFolder.add(settings, 'heightmap', ['Cosine', 'CosineLayers', 'DiamondSquare', 'Fault', 'heightmap.png', 'Hill', 'HillIsland', 'influences', 'Particles', 'Perlin', 'PerlinDiamond', 'PerlinLayers', 'Simplex', 'SimplexLayers', 'Value', 'Weierstrass', 'Worley']).onFinishChange(settings.Regenerate);
heightmapFolder.add(settings, 'easing', ['Linear', 'EaseIn', 'EaseOut', 'EaseInOut', 'InEaseOut']).onFinishChange(settings.Regenerate);
heightmapFolder.add(settings, 'smoothing', ['Conservative (0.5)', 'Conservative (1)', 'Conservative (10)', 'Gaussian (0.5, 7)', 'Gaussian (1.0, 7)', 'Gaussian (1.5, 7)', 'Gaussian (1.0, 5)', 'Gaussian (1.0, 11)', 'GaussianBox', 'Mean (0)', 'Mean (1)', 'Mean (8)', 'Median', 'None']).onChange(function (val) {
applySmoothing(val, lastOptions);
settings['Scatter meshes']();
if (lastOptions.heightmap) {
THREE.Terrain.toHeightmap(terrainScene.children[0].geometry.vertices, lastOptions);
}
});
heightmapFolder.add(settings, 'segments', 7, 127).step(1).onFinishChange(settings.Regenerate);
heightmapFolder.add(settings, 'steps', 1, 8).step(1).onFinishChange(settings.Regenerate);
heightmapFolder.add(settings, 'turbulent').onFinishChange(settings.Regenerate);
Expand Down Expand Up @@ -394,6 +404,25 @@ function __printCameraData() {
console.log(s);
}

function applySmoothing(smoothing, o) {
var m = terrainScene.children[0];
var g = m.geometry.vertices;
if (smoothing === 'Conservative (0.5)') THREE.Terrain.SmoothConservative(g, o, 0.5);
if (smoothing === 'Conservative (1)') THREE.Terrain.SmoothConservative(g, o, 1);
if (smoothing === 'Conservative (10)') THREE.Terrain.SmoothConservative(g, o, 10);
else if (smoothing === 'Gaussian (0.5, 7)') THREE.Terrain.Gaussian(g, o, 0.5, 7);
else if (smoothing === 'Gaussian (1.0, 7)') THREE.Terrain.Gaussian(g, o, 1, 7);
else if (smoothing === 'Gaussian (1.5, 7)') THREE.Terrain.Gaussian(g, o, 1.5, 7);
else if (smoothing === 'Gaussian (1.0, 5)') THREE.Terrain.Gaussian(g, o, 1, 5);
else if (smoothing === 'Gaussian (1.0, 11)') THREE.Terrain.Gaussian(g, o, 1, 11);
else if (smoothing === 'GaussianBox') THREE.Terrain.GaussianBoxBlur(g, o, 1, 3);
else if (smoothing === 'Mean (0)') THREE.Terrain.Smooth(g, o, 0);
else if (smoothing === 'Mean (1)') THREE.Terrain.Smooth(g, o, 1);
else if (smoothing === 'Mean (8)') THREE.Terrain.Smooth(g, o, 8);
else if (smoothing === 'Median') THREE.Terrain.SmoothMedian(g, o);
THREE.Terrain.Normalize(m, o);
}

function buildTree() {
var material = new THREE.MeshFaceMaterial([
new THREE.MeshLambertMaterial({ color: 0x3d2817 }), // brown
Expand Down
Loading

0 comments on commit f1b25e2

Please sign in to comment.