Browse Source

mod hue and clamp saturation and lightness

This makes it similar to rotation. With rotation you can do things
like

    someObj.rotation.x += speed * deltaTime;

You don't have to keep the result in the 0 to 2*PI or -PI to PI range.

Similarly by modding hue you can cycle through hues with

    someObj.hue += speed * deltaTime;
    someColor.setHSL(someObj.hue, 1, 0.5);

That helps several use cases like tweening libaries

    tween.fromTo(someObj, 5, { hue: 0 }, { hue: 5 });

It's also useful for random color selection from a given hue, saturation, lightness

    var hsl = someColor.getHSL();
    hsl.h += Math.random();
    hsl.s += Math.random() * 0.2 - 0.1;  // make it slightly more or less saturated
    someColor.setHSL(hsl.h, hsl.s, hsl.l);

Also updated `THREE.ColorConverter.setHSV`
Gregg Tavares 10 years ago
parent
commit
a1d3430b22
3 changed files with 42 additions and 21 deletions
  1. 5 0
      examples/js/math/ColorConverter.js
  2. 28 21
      src/math/Color.js
  3. 9 0
      src/math/Math.js

+ 5 - 0
examples/js/math/ColorConverter.js

@@ -8,6 +8,11 @@ THREE.ColorConverter = {
 	setHSV: function ( color, h, s, v ) {
 
 		// https://gist.github.com/xpansive/1337890#file-index-js
+
+		h = THREE.Math.euclideanModulo( h, 1 );
+		s = THREE.Math.clamp( s, 0, 1 );
+		v = THREE.Math.clamp( v, 0, 1 );
+
 		return color.setHSL( h, ( s * v ) / ( ( h = ( 2 - s ) * v ) < 1 ? h : ( 2 - h ) ), h * 0.5 );
 
 	},

+ 28 - 21
src/math/Color.js

@@ -62,39 +62,46 @@ THREE.Color.prototype = {
 
 	},
 
-	setHSL: function ( h, s, l ) {
+	setHSL: function () {
 
-		// h,s,l ranges are in 0.0 - 1.0
+		function hue2rgb ( p, q, t ) {
 
-		if ( s === 0 ) {
+			if ( t < 0 ) t += 1;
+			if ( t > 1 ) t -= 1;
+			if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
+			if ( t < 1 / 2 ) return q;
+			if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
+			return p;
 
-			this.r = this.g = this.b = l;
+		};
 
-		} else {
+		return function ( h, s, l ) {
 
-			var hue2rgb = function ( p, q, t ) {
+			// h,s,l ranges are in 0.0 - 1.0
+			h = THREE.Math.euclideanModulo( h, 1 );
+			s = THREE.Math.clamp( s, 0, 1 );
+			l = THREE.Math.clamp( l, 0, 1 );
 
-				if ( t < 0 ) t += 1;
-				if ( t > 1 ) t -= 1;
-				if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
-				if ( t < 1 / 2 ) return q;
-				if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
-				return p;
+			if ( s === 0 ) {
 
-			};
+				this.r = this.g = this.b = l;
 
-			var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
-			var q = ( 2 * l ) - p;
+			} else {
 
-			this.r = hue2rgb( q, p, h + 1 / 3 );
-			this.g = hue2rgb( q, p, h );
-			this.b = hue2rgb( q, p, h - 1 / 3 );
+				var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
+				var q = ( 2 * l ) - p;
 
-		}
+				this.r = hue2rgb( q, p, h + 1 / 3 );
+				this.g = hue2rgb( q, p, h );
+				this.b = hue2rgb( q, p, h - 1 / 3 );
 
-		return this;
+			}
 
-	},
+			return this;
+
+		};
+
+	}(),
 
 	setStyle: function ( style ) {
 

+ 9 - 0
src/math/Math.js

@@ -57,6 +57,15 @@ THREE.Math = {
 
 	},
 
+	// compute euclidian modulo of m % n
+	// https://en.wikipedia.org/wiki/Modulo_operation
+
+	euclideanModulo: function ( n, m ) {
+
+		return ( ( n % m ) + m ) % m;
+
+	},
+
 	// Linear mapping from range <a1, a2> to range <b1, b2>
 
 	mapLinear: function ( x, a1, a2, b1, b2 ) {