Skip to content

Commit

Permalink
Add isNaN, isFinite, null, and undefined support to GLSL styling backend
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Feb 19, 2020
1 parent 47f7c61 commit 54f71be
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Change Log
* Added `tileset.uri`, `tileset.show`, and `tileset.maximumScreenSpaceError` properties to CZML processing for loading 3D Tiles.
* Added `Color.lerp` for linearly interpolating between two RGB colors. [#8607](https:/CesiumGS/cesium/pull/8607)
* `CesiumTerrainProvider` now supports terrain tiles using a `WebMercatorTilingScheme` by specifying `"projection": "EPSG:3857"` in `layer.json`. It also now supports numbering tiles from the North instead of the South by specifying `"scheme": "slippyMap"` in `layer.json`. [#8563](https:/CesiumGS/cesium/pull/8563)
* Added basic support for `isNaN`, `isFinite`, `null`, and `undefined` in the 3D Tiles styling GLSL backend for point clouds. [#8621](https:/CesiumGS/cesium/pull/8621)

##### Fixes :wrench:

Expand Down
14 changes: 11 additions & 3 deletions Source/Scene/Expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,8 @@ import ExpressionNodeType from './ExpressionNodeType.js';
return expressions;
}

var nullSentinel = 'czm_infinity'; // null just needs to be some sentinel value that will cause "[expression] === null" to be false in nearly all cases. GLSL doesn't have a NaN constant so use czm_infinity.

Node.prototype.getShaderExpression = function(attributePrefix, shaderState, parent) {
var color;
var left;
Expand Down Expand Up @@ -1603,7 +1605,13 @@ import ExpressionNodeType from './ExpressionNodeType.js';
return 'floor(' + left + ' + 0.5)';
} else if (defined(unaryFunctions[value])) {
return value + '(' + left + ')';
} else if ((value === 'isNaN') || (value === 'isFinite') || (value === 'String') || (value === 'isExactClass') || (value === 'isClass') || (value === 'getExactClassName')) {
} else if (value === 'isNaN') {
// In GLSL 2.0 use isnan instead
return '(' + left + ' != ' + left + ')';
} else if (value === 'isFinite') {
// In GLSL 2.0 use isinf instead. GLSL doesn't have an infinity constant so use czm_infinity which is an arbitrarily big enough number.
return '(abs(' + left + ') < czm_infinity)';
} else if ((value === 'String') || (value === 'isExactClass') || (value === 'isClass') || (value === 'getExactClassName')) {
throw new RuntimeError('Error generating style shader: "' + value + '" is not supported.');
} else if (defined(unaryFunctions[value])) {
return value + '(' + left + ')';
Expand Down Expand Up @@ -1659,7 +1667,7 @@ import ExpressionNodeType from './ExpressionNodeType.js';
case ExpressionNodeType.VARIABLE_IN_STRING:
throw new RuntimeError('Error generating style shader: Converting a variable to a string is not supported.');
case ExpressionNodeType.LITERAL_NULL:
throw new RuntimeError('Error generating style shader: null is not supported.');
return nullSentinel;
case ExpressionNodeType.LITERAL_BOOLEAN:
return value ? 'true' : 'false';
case ExpressionNodeType.LITERAL_NUMBER:
Expand Down Expand Up @@ -1745,7 +1753,7 @@ import ExpressionNodeType from './ExpressionNodeType.js';
case ExpressionNodeType.LITERAL_REGEX:
throw new RuntimeError('Error generating style shader: Regular expressions are not supported.');
case ExpressionNodeType.LITERAL_UNDEFINED:
throw new RuntimeError('Error generating style shader: undefined is not supported.');
return nullSentinel;
case ExpressionNodeType.BUILTIN_VARIABLE:
if (value === 'tiles3d_tileset_time') {
return 'u_time';
Expand Down
56 changes: 28 additions & 28 deletions Specs/Scene/ExpressionSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3546,6 +3546,34 @@ describe('Scene/Expression', function() {
expect(shaderExpression).toEqual(expected);
});

it('gets shader expression for isNaN', function() {
var expression = new Expression('isNaN(1.0)');
var shaderExpression = expression.getShaderExpression('', {});
var expected = '(1.0 != 1.0)';
expect(shaderExpression).toEqual(expected);
});

it('gets shader expression for isFinite', function() {
var expression = new Expression('isFinite(1.0)');
var shaderExpression = expression.getShaderExpression('', {});
var expected = '(abs(1.0) < czm_infinity)';
expect(shaderExpression).toEqual(expected);
});

it('gets shader expression for null', function() {
var expression = new Expression('null');
var shaderExpression = expression.getShaderExpression('', {});
var expected = 'czm_infinity';
expect(shaderExpression).toEqual(expected);
});

it('gets shader expression for undefined', function() {
var expression = new Expression('undefined');
var shaderExpression = expression.getShaderExpression('', {});
var expected = 'czm_infinity';
expect(shaderExpression).toEqual(expected);
});

it('throws when getting shader expression for regex', function() {
var expression = new Expression('regExp("a").test("abc")');
expect(function() {
Expand Down Expand Up @@ -3610,34 +3638,6 @@ describe('Scene/Expression', function() {
}).toThrowRuntimeError();
});

it('throws when getting shader expression for literal undefined', function() {
var expression = new Expression('undefined');
expect(function() {
return expression.getShaderExpression('', {});
}).toThrowRuntimeError();
});

it('throws when getting shader expression for literal null', function() {
var expression = new Expression('null');
expect(function() {
return expression.getShaderExpression('', {});
}).toThrowRuntimeError();
});

it('throws when getting shader expression for isNaN', function() {
var expression = new Expression('isNaN(1.0)');
expect(function() {
return expression.getShaderExpression('', {});
}).toThrowRuntimeError();
});

it('throws when getting shader expression for isFinite', function() {
var expression = new Expression('isFinite(1.0)');
expect(function() {
return expression.getShaderExpression('', {});
}).toThrowRuntimeError();
});

it('throws when getting shader expression for isExactClass', function() {
var expression = new Expression('isExactClass("door")');
expect(function() {
Expand Down

0 comments on commit 54f71be

Please sign in to comment.