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

Proper handling of offset and scale in metadata picking #12237

Merged
merged 27 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e24a897
Proper handling of offset and scale in metadata picking
javagl Oct 6, 2024
97ae9db
Towards handling offset/scale overrides - WIP
javagl Oct 8, 2024
13eaedd
Additional comments and JSDoc
javagl Oct 9, 2024
ed6ad00
Comments and specs
javagl Oct 9, 2024
5d08966
Omit spec with error from unrelated issue
javagl Oct 10, 2024
bf53387
TSDoc fixes
javagl Oct 10, 2024
198f06a
Remove debug output
javagl Oct 10, 2024
b99daf9
Removed debug logs
javagl Oct 10, 2024
d546d39
Integrate offset/scale in class property
javagl Oct 10, 2024
a246145
Merge remote-tracking branch 'origin/main' into metadata-picking-offs…
javagl Oct 11, 2024
ffd67c3
Update CHANGES.md
javagl Oct 11, 2024
1a7dbb6
Do not try to pick property attributes
javagl Oct 12, 2024
f824410
Add JDoc for parameter
javagl Oct 29, 2024
c4c9453
Throw error for invalid type
javagl Oct 29, 2024
5c64039
Fix copy and paste error. Handle endianness. JSDoc.
javagl Oct 29, 2024
225be9c
First part of MetadataPickingSpec
javagl Oct 29, 2024
8cb917c
Fix typo in JSDoc
javagl Oct 29, 2024
cc3412d
Add error handling and documentation
javagl Oct 29, 2024
49bd80e
More specs for MetadataPicking
javagl Oct 29, 2024
ada213e
Merge remote-tracking branch 'origin/main' into metadata-picking-offs…
javagl Oct 29, 2024
76a8149
Removed specs for errors that are not thrown
javagl Oct 29, 2024
fe5da32
Updated JSDoc
javagl Oct 30, 2024
13ac596
No JSDoc link to private classes
javagl Nov 17, 2024
a0a4394
Merge remote-tracking branch 'origin/main' into metadata-picking-offs…
javagl Nov 17, 2024
4599ab0
More specific types for picked metadata
javagl Nov 19, 2024
40525b3
Fix typo in comment
javagl Nov 19, 2024
209ce6e
Merge branch 'main' into metadata-picking-offset-scale
ggetz Nov 21, 2024
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
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
- Fixed `ImageBasedLighting.imageBasedLightingFactor` not affecting lighting. [#12129](https://github.com/CesiumGS/cesium/pull/12129)
- Fix error with normalization of corner points for lines and corridors with collinear points. [#12255](https://github.com/CesiumGS/cesium/pull/12255)

##### Fixes :wrench:

- Properly handle `offset` and `scale` properties when picking metadata from property textures. [#12237](https://github.com/CesiumGS/cesium/pull/12237)

### 1.122 - 2024-10-01

#### @cesium/engine
Expand Down
125 changes: 109 additions & 16 deletions packages/engine/Source/Scene/DerivedCommand.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MetadataComponentType } from "@cesium/engine";
import defined from "../Core/defined.js";
import DrawCommand from "../Renderer/DrawCommand.js";
import RenderState from "../Renderer/RenderState.js";
Expand Down Expand Up @@ -416,6 +417,98 @@ function getGlslType(classProperty) {
return `ivec${componentCount}`;
}

/**
* Returns a shader statement that applies the inverse of the
* value transform to the given value, based on the given offset
* and scale.
*
* @param {string} input The input value
* @param {string} offset The offset
* @param {string} scale The scale
* @returns {string} The statement
*/
function unapplyValueTransform(input, offset, scale) {
return `((${input} - float(${offset})) / float(${scale}))`;
}

/**
* Returns a shader statement that applies the inverse of the
* normalization, based on the given component type
*
* @param {string} input The input value
* @param {string} componentType The component type
* @returns {string} The statement
*/
function unnormalize(input, componentType) {
const max = MetadataComponentType.getMaximum(componentType);
return `(${input}) / float(${max})`;
}

/**
* Creates a shader statement that returns the value of the specified
* property, normalized to the range [0, 1].
*
* @param {MetadataClassProperty} classProperty The class property
* @param {object} metadataProperty The metadata property, either
* a `PropertyTextureProperty` or a `PropertyAttributeProperty`
* @returns {string} The string
*/
function getSourceValueStringScalar(classProperty, metadataProperty) {
let result = `float(value)`;

// The 'hasValueTransform' indicates whether the property
// (or its class property) did define an 'offset' or 'scale'.
// Even when they had not been defined in the JSON, they are
// defined in the object, with default values.
if (metadataProperty.hasValueTransform) {
const offset = metadataProperty.offset;
const scale = metadataProperty.scale;
result = unapplyValueTransform(result, offset, scale);
}
if (!classProperty.normalized) {
result = unnormalize(result, classProperty.componentType);
}
return result;
}

/**
* Creates a shader statement that returns the value of the specified
* component of the given property, normalized to the range [0, 1].
*
* @param {MetadataClassProperty} classProperty The class property
* @param {object} metadataProperty The metadata property, either
* a `PropertyTextureProperty` or a `PropertyAttributeProperty`
* @param {string} componentName The name, in ["x", "y", "z", "w"]
* @returns {string} The string
*/
function getSourceValueStringComponent(
classProperty,
metadataProperty,
componentName,
) {
const valueString = `value.${componentName}`;
let result = `float(${valueString})`;

// The 'hasValueTransform' indicates whether the property
// (or its class property) did define an 'offset' or 'scale'.
// Even when they had not been defined in the JSON, they are
// defined in the object, with default values
// Note that in the 'PropertyTextureProperty' and the
// 'PropertyAttributeProperty', these values are
// stored as "object types" (like 'Cartesian2'), whereas
// in the 'MetadataClassProperty', they are stored as
// "array types", e.g. a `[number, number]`
if (metadataProperty.hasValueTransform) {
const offset = metadataProperty.offset[componentName];
const scale = metadataProperty.scale[componentName];
result = unapplyValueTransform(result, offset, scale);
}
if (!classProperty.normalized) {
result = unnormalize(result, classProperty.componentType);
}
return result;
}

/**
* Creates a new `ShaderProgram` from the given input that renders metadata
* values into the frame buffer, according to the given picked metadata info.
Expand Down Expand Up @@ -452,34 +545,34 @@ function getPickMetadataShaderProgram(
return shader;
}

const metadataProperty = pickedMetadataInfo.metadataProperty;
const classProperty = pickedMetadataInfo.classProperty;
const glslType = getGlslType(classProperty);

// Define the components that will go into the output `metadataValues`.
// This will be the 'color' that is written into the frame buffer,
// meaning that the values should be in [0.0, 1.0], and will become
// values in [0, 255] in the frame buffer.
// By default, all of them are 0.0.
const sourceValueStrings = ["0.0", "0.0", "0.0", "0.0"];
const componentCount = getComponentCount(classProperty);
if (componentCount === 1) {
// When the property is a scalar, store its value directly
// in `metadataValues.x`
sourceValueStrings[0] = `float(value)`;
// When the property is a scalar, store the source value
// string directly in `metadataValues.x`
sourceValueStrings[0] = getSourceValueStringScalar(
classProperty,
metadataProperty,
);
} else {
// When the property is an array, store the array elements
// in `metadataValues.x/y/z/w`
const components = ["x", "y", "z", "w"];
for (let i = 0; i < componentCount; i++) {
const component = components[i];
const valueString = `value.${component}`;
sourceValueStrings[i] = `float(${valueString})`;
}
}

// Make sure that the `metadataValues` components are all in
// the range [0, 1] (which will result in RGBA components
// in [0, 255] during rendering)
if (!classProperty.normalized) {
const componentNames = ["x", "y", "z", "w"];
for (let i = 0; i < componentCount; i++) {
sourceValueStrings[i] += " / 255.0";
sourceValueStrings[i] = getSourceValueStringComponent(
classProperty,
metadataProperty,
componentNames[i],
);
}
}

Expand Down
26 changes: 26 additions & 0 deletions packages/engine/Source/Scene/MetadataClassProperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ Object.defineProperties(MetadataClassProperty.prototype, {
/**
* The offset to be added to property values as part of the value transform.
*
* This is always defined, even when `hasValueTransform` is `false`. If
* the class property JSON itself did not define it, then it will be
* initialized to the default value.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
Expand All @@ -451,6 +455,10 @@ Object.defineProperties(MetadataClassProperty.prototype, {
/**
* The scale to be multiplied to property values as part of the value transform.
*
* This is always defined, even when `hasValueTransform` is `false`. If
* the class property JSON itself did not define it, then it will be
* initialized to the default value.
*
* @memberof MetadataClassProperty.prototype
* @type {number|number[]|number[][]}
* @readonly
Expand Down Expand Up @@ -1139,6 +1147,24 @@ function normalizeInPlace(values, valueType, normalizeFunction) {
}

/**
* Applies the value transform that is defined with the given offsets
* and scales to the given values.
*
* If the given values are not an array, then the given transformation
* function will be applied directly.
*
* If the values are an array, then this function will be called recursively
* with the array elements, boiling down to a component-wise application
* of the transformation function to the innermost array elements.
*
* @param {number|number[]|number[][]} values The input values
* @param {number|number[]|number[][]} offsets The offsets
* @param {number|number[]|number[][]} scales The scales
javagl marked this conversation as resolved.
Show resolved Hide resolved
* @param {Function} transformationFunction The function with the signature
* `(value:number, offset:number, scale:number) : number` that will be
* applied to the innermost elements
* @returns The input values (or the result of applying the transformation
* function to a single value if the values have not been an array).
* @private
*/
MetadataClassProperty.valueTransformInPlace = function (
Expand Down
Loading