mirror of https://github.com/CesiumGS/cesium.git
3071 lines
84 KiB
JavaScript
3071 lines
84 KiB
JavaScript
import {
|
|
Cartesian2,
|
|
Cartesian3,
|
|
Cartesian4,
|
|
clone,
|
|
Matrix2,
|
|
Matrix3,
|
|
Matrix4,
|
|
FeatureDetection,
|
|
MetadataClassProperty,
|
|
MetadataComponentType,
|
|
MetadataEnum,
|
|
MetadataType,
|
|
} from "../../index.js";
|
|
|
|
describe("Scene/MetadataClassProperty", function () {
|
|
it("creates property with default values", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "height",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("height");
|
|
expect(property.name).toBeUndefined();
|
|
expect(property.description).toBeUndefined();
|
|
expect(property.type).toBe(MetadataType.SCALAR);
|
|
expect(property.enumType).toBeUndefined();
|
|
expect(property.componentType).toBe(MetadataComponentType.FLOAT32);
|
|
expect(property.valueType).toBe(MetadataComponentType.FLOAT32);
|
|
expect(property.isArray).toBe(false);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.normalized).toBe(false);
|
|
expect(property.max).toBeUndefined();
|
|
expect(property.min).toBeUndefined();
|
|
expect(property.default).toBeUndefined();
|
|
expect(property.required).toBe(false);
|
|
expect(property.semantic).toBeUndefined();
|
|
expect(property.extras).toBeUndefined();
|
|
expect(property.extensions).toBeUndefined();
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
});
|
|
|
|
it("creates property", function () {
|
|
const max = [32767, 0, 100];
|
|
const min = [-32768, 0, -100];
|
|
const propertyDefault = [0, 0, 0];
|
|
const extras = {
|
|
coordinates: [0, 1, 2],
|
|
};
|
|
const extensions = {
|
|
EXT_other_extension: {},
|
|
};
|
|
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
name: "Position",
|
|
description: "Position (X, Y, Z)",
|
|
array: true,
|
|
count: 3,
|
|
type: "SCALAR",
|
|
componentType: "INT16",
|
|
normalized: true,
|
|
max: max,
|
|
min: min,
|
|
default: propertyDefault,
|
|
required: true,
|
|
semantic: "_POSITION",
|
|
extras: extras,
|
|
extensions: extensions,
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("position");
|
|
expect(property.name).toBe("Position");
|
|
expect(property.description).toBe("Position (X, Y, Z)");
|
|
expect(property.type).toBe(MetadataType.SCALAR);
|
|
expect(property.enumType).toBeUndefined();
|
|
expect(property.componentType).toBe(MetadataComponentType.INT16);
|
|
expect(property.valueType).toBe(MetadataComponentType.INT16);
|
|
expect(property.isArray).toBe(true);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).toBe(3);
|
|
expect(property.normalized).toBe(true);
|
|
expect(property.max).toEqual(max);
|
|
expect(property.min).toEqual(min);
|
|
expect(property.default).toEqual(propertyDefault);
|
|
expect(property.required).toBe(true);
|
|
expect(property.semantic).toBe("_POSITION");
|
|
expect(property.extras).toEqual(extras);
|
|
expect(property.extensions).toEqual(extensions);
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
});
|
|
|
|
it("transcodes single properties from EXT_feature_metadata", function () {
|
|
const max = [32767, 0, 100];
|
|
const min = [-32768, 0, -100];
|
|
const propertyDefault = [0, 0, 0];
|
|
const extras = {
|
|
coordinates: [0, 1, 2],
|
|
};
|
|
const extensions = {
|
|
EXT_other_extension: {},
|
|
};
|
|
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "population",
|
|
property: {
|
|
name: "Population",
|
|
description: "Population (thousands)",
|
|
type: "INT32",
|
|
normalized: true,
|
|
max: max,
|
|
min: min,
|
|
default: propertyDefault,
|
|
optional: false,
|
|
semantic: "_POSITION",
|
|
extras: extras,
|
|
extensions: extensions,
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("population");
|
|
expect(property.name).toBe("Population");
|
|
expect(property.description).toBe("Population (thousands)");
|
|
expect(property.type).toBe(MetadataType.SCALAR);
|
|
expect(property.enumType).toBeUndefined();
|
|
expect(property.componentType).toBe(MetadataComponentType.INT32);
|
|
expect(property.valueType).toBe(MetadataComponentType.INT32);
|
|
expect(property.isArray).toBe(false);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.normalized).toBe(true);
|
|
expect(property.max).toEqual(max);
|
|
expect(property.min).toEqual(min);
|
|
expect(property.default).toEqual(propertyDefault);
|
|
expect(property.required).toBe(true);
|
|
expect(property.semantic).toBe("_POSITION");
|
|
expect(property.extras).toEqual(extras);
|
|
expect(property.extensions).toEqual(extensions);
|
|
expect(property._isLegacyExtension).toBe(true);
|
|
});
|
|
|
|
it("creates enum property", function () {
|
|
const colorEnum = MetadataEnum.fromJson({
|
|
id: "color",
|
|
enum: {
|
|
values: [
|
|
{
|
|
name: "RED",
|
|
value: 0,
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const enums = {
|
|
color: colorEnum,
|
|
};
|
|
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "color",
|
|
property: {
|
|
type: "ENUM",
|
|
enumType: "color",
|
|
required: true,
|
|
},
|
|
enums: enums,
|
|
});
|
|
|
|
expect(property.required).toBe(true);
|
|
expect(property.isArray).toBe(false);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.type).toBe(MetadataType.ENUM);
|
|
expect(property.componentType).not.toBeDefined();
|
|
expect(property.enumType).toBe(colorEnum);
|
|
expect(property.valueType).toBe(MetadataComponentType.UINT16); // default enum valueType
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
});
|
|
|
|
it("creates array of enums with EXT_feature_metadata", function () {
|
|
const colorEnum = MetadataEnum.fromJson({
|
|
id: "color",
|
|
enum: {
|
|
valueType: "UINT32",
|
|
values: [
|
|
{
|
|
name: "RED",
|
|
value: 0,
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const enums = {
|
|
color: colorEnum,
|
|
};
|
|
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "color",
|
|
property: {
|
|
type: "ARRAY",
|
|
componentType: "ENUM",
|
|
componentCount: 4,
|
|
enumType: "color",
|
|
},
|
|
enums: enums,
|
|
});
|
|
|
|
expect(property.isArray).toBe(true);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).toBe(4);
|
|
expect(property.type).toBe(MetadataType.ENUM);
|
|
expect(property.componentType).not.toBeDefined();
|
|
expect(property.enumType).toBe(colorEnum);
|
|
expect(property.valueType).toBe(MetadataComponentType.UINT32);
|
|
expect(property._isLegacyExtension).toBe(true);
|
|
});
|
|
|
|
it("creates vector and matrix types", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "speed",
|
|
property: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("speed");
|
|
expect(property.type).toBe(MetadataType.VEC2);
|
|
expect(property.isArray).toBe(false);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.componentType).toBe(MetadataComponentType.FLOAT32);
|
|
expect(property.valueType).toBe(MetadataComponentType.FLOAT32);
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "scale",
|
|
property: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT64",
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("scale");
|
|
expect(property.type).toBe(MetadataType.MAT3);
|
|
expect(property.isArray).toBe(false);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.componentType).toBe(MetadataComponentType.FLOAT64);
|
|
expect(property.valueType).toBe(MetadataComponentType.FLOAT64);
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
});
|
|
|
|
it("creates arrays of BOOLEAN and STRING with EXT_feature_metadata", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "booleanArray",
|
|
property: {
|
|
type: "ARRAY",
|
|
componentType: "BOOLEAN",
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("booleanArray");
|
|
expect(property.type).toBe(MetadataType.BOOLEAN);
|
|
expect(property.isArray).toBe(true);
|
|
expect(property.isVariableLengthArray).toBe(true);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.componentType).not.toBeDefined();
|
|
expect(property.valueType).not.toBeDefined();
|
|
expect(property._isLegacyExtension).toBe(true);
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "stringArray",
|
|
property: {
|
|
type: "ARRAY",
|
|
componentType: "STRING",
|
|
componentCount: 2,
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("stringArray");
|
|
expect(property.type).toBe(MetadataType.STRING);
|
|
expect(property.isArray).toBe(true);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).toBe(2);
|
|
expect(property.componentType).not.toBeDefined();
|
|
expect(property.valueType).not.toBeDefined();
|
|
expect(property._isLegacyExtension).toBe(true);
|
|
});
|
|
|
|
it("creates arrays of vector and matrix types", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "speeds",
|
|
property: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("speeds");
|
|
expect(property.type).toBe(MetadataType.VEC2);
|
|
expect(property.isArray).toBe(true);
|
|
expect(property.isVariableLengthArray).toBe(true);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.componentType).toBe(MetadataComponentType.FLOAT32);
|
|
expect(property.valueType).toBe(MetadataComponentType.FLOAT32);
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "scaleFactors",
|
|
property: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT64",
|
|
array: true,
|
|
count: 2,
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("scaleFactors");
|
|
expect(property.type).toBe(MetadataType.MAT3);
|
|
expect(property.isArray).toBe(true);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).toBe(2);
|
|
expect(property.componentType).toBe(MetadataComponentType.FLOAT64);
|
|
expect(property.valueType).toBe(MetadataComponentType.FLOAT64);
|
|
expect(property._isLegacyExtension).toBe(false);
|
|
});
|
|
|
|
it("handles ambiguous extension gracefully", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "name",
|
|
property: {
|
|
// this is valid in both EXT_structural_metadata and EXT_feature_metadata
|
|
type: "STRING",
|
|
},
|
|
});
|
|
|
|
expect(property.id).toBe("name");
|
|
expect(property.required).toBe(false);
|
|
expect(property.type).toBe(MetadataType.STRING);
|
|
expect(property.isArray).toBe(false);
|
|
expect(property.isVariableLengthArray).toBe(false);
|
|
expect(property.arrayLength).not.toBeDefined();
|
|
expect(property.componentType).not.toBeDefined();
|
|
expect(property.valueType).not.toBeDefined();
|
|
expect(property._isLegacyExtension).not.toBeDefined();
|
|
});
|
|
|
|
it("constructor throws with invalid type definition", function () {
|
|
expect(function () {
|
|
return MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
type: "NOT_A_TYPE",
|
|
},
|
|
});
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("constructor throws without id", function () {
|
|
expect(function () {
|
|
return MetadataClassProperty.fromJson({
|
|
id: undefined,
|
|
property: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("constructor throws without property", function () {
|
|
expect(function () {
|
|
return MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: undefined,
|
|
});
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
it("constructor throws without property.type", function () {
|
|
expect(function () {
|
|
return MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
type: undefined,
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
}).toThrowDeveloperError();
|
|
});
|
|
|
|
describe("expandConstant", function () {
|
|
it("works for scalars", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.expandConstant(1)).toBe(1);
|
|
});
|
|
|
|
it("works for vectors and matrices", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
type: "VEC3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.expandConstant(1)).toEqual([1, 1, 1]);
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.expandConstant(1)).toEqual([1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
|
});
|
|
|
|
it("works for arrays of scalars", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
array: true,
|
|
count: 4,
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.expandConstant(1)).toEqual([1, 1, 1, 1]);
|
|
});
|
|
|
|
it("works for arrays of vectors and matrices", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
array: true,
|
|
count: 3,
|
|
type: "VEC3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
const isNested = false;
|
|
expect(property.expandConstant(1, isNested)).toEqual([
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
]);
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
array: true,
|
|
count: 2,
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.expandConstant(1, isNested)).toEqual([
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
]);
|
|
});
|
|
|
|
it("works for nested arrays of vectors and matrices", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
array: true,
|
|
count: 3,
|
|
type: "VEC3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
const isNested = true;
|
|
expect(property.expandConstant(1, isNested)).toEqual([
|
|
[1, 1, 1],
|
|
[1, 1, 1],
|
|
[1, 1, 1],
|
|
]);
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "propertyId",
|
|
property: {
|
|
array: true,
|
|
count: 2,
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.expandConstant(1, isNested)).toEqual([
|
|
[1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
[1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("normalize and unnormalize", function () {
|
|
let scalarProperties;
|
|
let scalarValues;
|
|
let normalizedScalarValues;
|
|
|
|
let arrayProperties;
|
|
let arrayValues;
|
|
let normalizedArrayValues;
|
|
|
|
let vectorProperties;
|
|
let vectorValues;
|
|
let normalizedVectorValues;
|
|
|
|
let arrayOfVectorProperties;
|
|
let arrayOfVectorValues;
|
|
let normalizedArrayOfVectorValues;
|
|
|
|
let myEnum;
|
|
let nonIntegerProperties;
|
|
let nonIntegerValues;
|
|
beforeAll(function () {
|
|
scalarProperties = {
|
|
propertyInt8: {
|
|
type: "SCALAR",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
},
|
|
propertyUint8: {
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
},
|
|
propertyInt16: {
|
|
type: "SCALAR",
|
|
componentType: "INT16",
|
|
normalized: true,
|
|
},
|
|
propertyUint16: {
|
|
type: "SCALAR",
|
|
componentType: "UINT16",
|
|
normalized: true,
|
|
},
|
|
propertyInt32: {
|
|
type: "SCALAR",
|
|
componentType: "INT32",
|
|
normalized: true,
|
|
},
|
|
propertyUint32: {
|
|
type: "SCALAR",
|
|
componentType: "UINT32",
|
|
normalized: true,
|
|
},
|
|
propertyInt64: {
|
|
type: "SCALAR",
|
|
componentType: "INT64",
|
|
normalized: true,
|
|
},
|
|
propertyUint64: {
|
|
type: "SCALAR",
|
|
componentType: "UINT64",
|
|
normalized: true,
|
|
},
|
|
};
|
|
|
|
scalarValues = {
|
|
propertyInt8: [-127, 0, 127],
|
|
propertyUint8: [0, 51, 255],
|
|
propertyInt16: [-32767, 0, 32767],
|
|
propertyUint16: [0, 13107, 65535],
|
|
propertyInt32: [-2147483647, 0, 2147483647],
|
|
propertyUint32: [0, 858993459, 4294967295],
|
|
propertyInt64: [
|
|
BigInt("-9223372036854775807"),
|
|
BigInt(0),
|
|
BigInt("9223372036854775807"),
|
|
],
|
|
propertyUint64: [
|
|
BigInt(0),
|
|
BigInt("3689348814741910528"),
|
|
BigInt("18446744073709551615"),
|
|
],
|
|
};
|
|
|
|
normalizedScalarValues = {
|
|
propertyInt8: [-1.0, 0, 1.0],
|
|
propertyUint8: [0.0, 0.2, 1.0],
|
|
propertyInt16: [-1.0, 0, 1.0],
|
|
propertyUint16: [0.0, 0.2, 1.0],
|
|
propertyInt32: [-1.0, 0, 1.0],
|
|
propertyUint32: [0.0, 0.2, 1.0],
|
|
propertyInt64: [-1.0, 0, 1.0],
|
|
propertyUint64: [0.0, 0.2, 1.0],
|
|
};
|
|
|
|
arrayProperties = {
|
|
propertyInt8: {
|
|
array: true,
|
|
type: "SCALAR",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
},
|
|
propertyUint8: {
|
|
array: true,
|
|
count: 2,
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
},
|
|
propertyVector: {
|
|
type: "VEC3",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyMatrix: {
|
|
type: "MAT2",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
array: true,
|
|
},
|
|
};
|
|
|
|
arrayValues = {
|
|
propertyInt8: [[-127, 0], [127], []],
|
|
propertyUint8: [
|
|
[0, 255],
|
|
[0, 51],
|
|
[255, 255],
|
|
],
|
|
propertyVector: [
|
|
[255, 0, 0],
|
|
[0, 255, 0],
|
|
[0, 0, 255],
|
|
],
|
|
propertyMatrix: [
|
|
[255, 255, 255, 255],
|
|
[51, 0, 0, 51],
|
|
],
|
|
};
|
|
|
|
normalizedArrayValues = {
|
|
propertyInt8: [[-1.0, 0.0], [1.0], []],
|
|
propertyUint8: [
|
|
[0.0, 1.0],
|
|
[0.0, 0.2],
|
|
[1.0, 1.0],
|
|
],
|
|
propertyVector: [
|
|
[1.0, 0.0, 0.0],
|
|
[0.0, 1.0, 0.0],
|
|
[0.0, 0.0, 1.0],
|
|
],
|
|
propertyMatrix: [
|
|
[1.0, 1.0, 1.0, 1.0],
|
|
[0.2, 0.0, 0.0, 0.2],
|
|
],
|
|
};
|
|
|
|
vectorProperties = {
|
|
vec4Int8: {
|
|
type: "VEC4",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
},
|
|
mat2Uint8: {
|
|
type: "MAT2",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
},
|
|
};
|
|
|
|
vectorValues = {
|
|
vec4Int8: [
|
|
[-127, 0, 127, 0],
|
|
[-127, -127, -127, 0],
|
|
[127, 127, 127, 127],
|
|
],
|
|
mat2Uint8: [
|
|
[0, 255, 0, 0],
|
|
[0, 51, 51, 0],
|
|
[255, 0, 0, 255],
|
|
],
|
|
};
|
|
|
|
normalizedVectorValues = {
|
|
vec4Int8: [
|
|
[-1.0, 0.0, 1.0, 0],
|
|
[-1.0, -1.0, -1.0, 0],
|
|
[1.0, 1.0, 1.0, 1.0],
|
|
],
|
|
mat2Uint8: [
|
|
[0.0, 1.0, 0.0, 0.0],
|
|
[0.0, 0.2, 0.2, 0.0],
|
|
[1.0, 0.0, 0.0, 1.0],
|
|
],
|
|
};
|
|
|
|
arrayOfVectorProperties = {
|
|
propertyVector: {
|
|
type: "VEC3",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
array: true,
|
|
count: 2,
|
|
},
|
|
propertyMatrix: {
|
|
type: "MAT2",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
array: true,
|
|
},
|
|
};
|
|
|
|
arrayOfVectorValues = {
|
|
propertyVector: [
|
|
[
|
|
[255, 0, 0],
|
|
[0, 255, 0],
|
|
],
|
|
[
|
|
[0, 0, 255],
|
|
[255, 255, 0],
|
|
],
|
|
],
|
|
propertyMatrix: [
|
|
[
|
|
[255, 255, 255, 255],
|
|
[51, 0, 0, 51],
|
|
],
|
|
[],
|
|
],
|
|
};
|
|
|
|
normalizedArrayOfVectorValues = {
|
|
propertyVector: [
|
|
[
|
|
[1.0, 0.0, 0.0],
|
|
[0.0, 1.0, 0.0],
|
|
],
|
|
[
|
|
[0.0, 0.0, 1.0],
|
|
[1.0, 1.0, 0.0],
|
|
],
|
|
],
|
|
propertyMatrix: [
|
|
[
|
|
[1.0, 1.0, 1.0, 1.0],
|
|
[0.2, 0.0, 0.0, 0.2],
|
|
],
|
|
[],
|
|
],
|
|
};
|
|
|
|
myEnum = MetadataEnum.fromJson({
|
|
id: "myEnum",
|
|
enum: {
|
|
values: [
|
|
{
|
|
value: 0,
|
|
name: "ValueA",
|
|
},
|
|
{
|
|
value: 1,
|
|
name: "ValueB",
|
|
},
|
|
{
|
|
value: 999,
|
|
name: "Other",
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
nonIntegerProperties = {
|
|
propertyEnum: {
|
|
type: "ENUM",
|
|
enumType: "myEnum",
|
|
},
|
|
propertyEnumArray: {
|
|
type: "ENUM",
|
|
array: true,
|
|
enumType: "myEnum",
|
|
},
|
|
propertyString: {
|
|
type: "STRING",
|
|
},
|
|
propertyBoolean: {
|
|
type: "BOOLEAN",
|
|
},
|
|
};
|
|
|
|
nonIntegerValues = {
|
|
propertyEnum: ["Other", "ValueA", "ValueB"],
|
|
propertyEnumArray: [["Other", "ValueA"], ["ValueB"], []],
|
|
propertyString: ["a", "bc", ""],
|
|
propertyBoolean: [true, false, false],
|
|
};
|
|
});
|
|
|
|
it("normalizes scalar values", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
for (const propertyId in scalarProperties) {
|
|
if (scalarProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: scalarProperties[propertyId],
|
|
});
|
|
const length = normalizedScalarValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = scalarValues[propertyId][i];
|
|
const normalizedValue = property.normalize(value);
|
|
expect(normalizedValue).toEqual(
|
|
normalizedScalarValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unnormalizes scalar values", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
for (const propertyId in scalarProperties) {
|
|
if (scalarProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: scalarProperties[propertyId],
|
|
});
|
|
const length = scalarValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const normalizedValue = normalizedScalarValues[propertyId][i];
|
|
const value = property.unnormalize(normalizedValue);
|
|
expect(value).toEqual(scalarValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("normalizes array values", function () {
|
|
for (const propertyId in arrayProperties) {
|
|
if (arrayProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayProperties[propertyId],
|
|
});
|
|
const length = normalizedArrayValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = arrayValues[propertyId][i];
|
|
const normalizedValue = property.normalize(clone(value, true));
|
|
expect(normalizedValue).toEqual(
|
|
normalizedArrayValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unnormalizes array values", function () {
|
|
for (const propertyId in arrayProperties) {
|
|
if (arrayProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayProperties[propertyId],
|
|
});
|
|
const length = arrayValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const normalizedValue = normalizedArrayValues[propertyId][i];
|
|
const value = property.unnormalize(clone(normalizedValue, true));
|
|
expect(value).toEqual(arrayValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("normalizes vector and matrix values", function () {
|
|
for (const propertyId in vectorProperties) {
|
|
if (vectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: vectorProperties[propertyId],
|
|
});
|
|
const length = normalizedVectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = vectorValues[propertyId][i];
|
|
const normalizedValue = property.normalize(clone(value, true));
|
|
expect(normalizedValue).toEqual(
|
|
normalizedVectorValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unnormalizes vector and matrix values", function () {
|
|
for (const propertyId in vectorProperties) {
|
|
if (vectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: vectorProperties[propertyId],
|
|
});
|
|
const length = vectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const normalizedValue = normalizedVectorValues[propertyId][i];
|
|
const value = property.unnormalize(clone(normalizedValue, true));
|
|
expect(value).toEqual(vectorValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("normalizes nested arrays of vectors", function () {
|
|
for (const propertyId in arrayOfVectorProperties) {
|
|
if (arrayOfVectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayOfVectorProperties[propertyId],
|
|
});
|
|
const length = normalizedArrayOfVectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = arrayOfVectorValues[propertyId][i];
|
|
const normalizedValue = property.normalize(clone(value, true));
|
|
expect(normalizedValue).toEqual(
|
|
normalizedArrayOfVectorValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unnormalizes nested arrays of vectors", function () {
|
|
for (const propertyId in arrayOfVectorProperties) {
|
|
if (arrayOfVectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayOfVectorProperties[propertyId],
|
|
});
|
|
const length = arrayOfVectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const normalizedValue =
|
|
normalizedArrayOfVectorValues[propertyId][i];
|
|
const value = property.unnormalize(clone(normalizedValue, true));
|
|
expect(value).toEqual(arrayOfVectorValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("does not normalize non integer types", function () {
|
|
for (const propertyId in nonIntegerProperties) {
|
|
if (nonIntegerProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: nonIntegerProperties[propertyId],
|
|
enums: {
|
|
myEnum: myEnum,
|
|
},
|
|
});
|
|
const length = nonIntegerValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = nonIntegerValues[propertyId][i];
|
|
const normalizedValue = property.normalize(value);
|
|
expect(normalizedValue).toEqual(value);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("does not unnormalize non integer types", function () {
|
|
for (const propertyId in nonIntegerProperties) {
|
|
if (nonIntegerProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: nonIntegerProperties[propertyId],
|
|
enums: {
|
|
myEnum: myEnum,
|
|
},
|
|
});
|
|
const length = nonIntegerValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const normalizedValue = nonIntegerValues[propertyId][i];
|
|
const value = property.unnormalize(normalizedValue);
|
|
expect(value).toEqual(normalizedValue);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("value transform", function () {
|
|
let scalarProperties;
|
|
let scalarValues;
|
|
let transformedScalarValues;
|
|
|
|
let arrayProperties;
|
|
let arrayValues;
|
|
let transformedArrayValues;
|
|
|
|
let vectorProperties;
|
|
let vectorValues;
|
|
let transformedVectorValues;
|
|
|
|
let arrayOfVectorProperties;
|
|
let arrayOfVectorValues;
|
|
let transformedArrayOfVectorValues;
|
|
|
|
let myEnum;
|
|
let otherProperties;
|
|
let otherValues;
|
|
beforeAll(function () {
|
|
scalarProperties = {
|
|
propertyInt8: {
|
|
type: "SCALAR",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
offset: 1,
|
|
scale: 2,
|
|
},
|
|
propertyUint8: {
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
offset: 2,
|
|
scale: 2,
|
|
},
|
|
propertyInt16: {
|
|
type: "SCALAR",
|
|
componentType: "INT16",
|
|
normalized: true,
|
|
scale: 2,
|
|
},
|
|
propertyUint16: {
|
|
type: "SCALAR",
|
|
componentType: "UINT16",
|
|
normalized: true,
|
|
offset: 4,
|
|
},
|
|
propertyInt32: {
|
|
type: "SCALAR",
|
|
componentType: "INT32",
|
|
normalized: true,
|
|
offset: 0,
|
|
scale: 1,
|
|
},
|
|
propertyUint32: {
|
|
type: "SCALAR",
|
|
componentType: "UINT32",
|
|
normalized: true,
|
|
scale: 2,
|
|
offset: 2,
|
|
},
|
|
propertyInt64: {
|
|
type: "SCALAR",
|
|
componentType: "INT64",
|
|
normalized: true,
|
|
offset: -1,
|
|
scale: 0.5,
|
|
},
|
|
propertyUint64: {
|
|
type: "SCALAR",
|
|
componentType: "UINT64",
|
|
normalized: true,
|
|
offset: 1,
|
|
scale: 2,
|
|
},
|
|
propertyFloat32: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
offset: 8,
|
|
scale: 4,
|
|
},
|
|
propertyFloat64: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT64",
|
|
offset: 4,
|
|
scale: 2,
|
|
},
|
|
};
|
|
|
|
scalarValues = {
|
|
// Integer properties must be normalized to use valueTransform
|
|
propertyInt8: [-1.0, 0.0, 1.0],
|
|
propertyUint8: [0.0, 0.5, 1.0],
|
|
propertyInt16: [-1.0, 0.0, 1.0],
|
|
propertyUint16: [0.0, 0.5, 1.0],
|
|
propertyInt32: [-1.0, 0.0, 1.0],
|
|
propertyUint32: [0, 0.5, 1.0],
|
|
propertyInt64: [-1.0, 0.0, 1.0],
|
|
propertyUint64: [0, 0.5, 1.0],
|
|
// Float properties do not have such restriction
|
|
propertyFloat32: [-8.0, 3.0, 256.0],
|
|
propertyFloat64: [-4.5, 0.0, 45.0],
|
|
};
|
|
|
|
transformedScalarValues = {
|
|
propertyInt8: [-1.0, 1.0, 3.0],
|
|
propertyUint8: [2.0, 3.0, 4.0],
|
|
propertyInt16: [-2.0, 0, 2.0],
|
|
propertyUint16: [4.0, 4.5, 5.0],
|
|
propertyInt32: [-1.0, 0, 1.0],
|
|
propertyUint32: [2.0, 3.0, 4.0],
|
|
propertyInt64: [-1.5, -1.0, -0.5],
|
|
propertyUint64: [1.0, 2.0, 3.0],
|
|
propertyFloat32: [-24.0, 20.0, 1032.0],
|
|
propertyFloat64: [-5.0, 4.0, 94.0],
|
|
};
|
|
|
|
arrayProperties = {
|
|
propertyInt8: {
|
|
array: true,
|
|
count: 3,
|
|
type: "SCALAR",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
offset: [1, 2, 3],
|
|
scale: [2, 2, 2],
|
|
},
|
|
propertyFloat32: {
|
|
array: true,
|
|
count: 2,
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
normalized: true,
|
|
offset: [-1, -1],
|
|
scale: [2, 1],
|
|
},
|
|
propertyDefaultOffset: {
|
|
array: true,
|
|
count: 2,
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
normalized: true,
|
|
scale: [2, 2],
|
|
},
|
|
propertyDefaultScale: {
|
|
array: true,
|
|
count: 2,
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
normalized: true,
|
|
offset: [1, 2],
|
|
},
|
|
};
|
|
|
|
arrayValues = {
|
|
propertyInt8: [
|
|
[-1.0, 0.0, 1.0],
|
|
[1.0, 1.0, 1.0],
|
|
[0.0, 0.5, 1.0],
|
|
],
|
|
propertyFloat32: [
|
|
[0.0, 1.0],
|
|
[0.0, 0.125],
|
|
[1.0, 1.0],
|
|
],
|
|
propertyDefaultOffset: [
|
|
[-1, 1],
|
|
[-2, 4],
|
|
[-0.5, 0.5],
|
|
],
|
|
propertyDefaultScale: [
|
|
[-1, 1],
|
|
[-2, 4],
|
|
[-0.5, 0.5],
|
|
],
|
|
};
|
|
|
|
transformedArrayValues = {
|
|
propertyInt8: [
|
|
[-1.0, 2.0, 5.0],
|
|
[3.0, 4.0, 5.0],
|
|
[1.0, 3.0, 5.0],
|
|
],
|
|
propertyFloat32: [
|
|
[-1.0, 0.0],
|
|
[-1.0, -0.875],
|
|
[1.0, 0.0],
|
|
],
|
|
propertyDefaultOffset: [
|
|
[-2, 2],
|
|
[-4, 8],
|
|
[-1, 1],
|
|
],
|
|
propertyDefaultScale: [
|
|
[0, 3],
|
|
[-1, 6],
|
|
[0.5, 2.5],
|
|
],
|
|
};
|
|
|
|
vectorProperties = {
|
|
vec4Int8: {
|
|
type: "VEC4",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
offset: [3, 3, 0, 1],
|
|
scale: [2, 8, 4, 1],
|
|
},
|
|
mat2Float32: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
normalized: true,
|
|
scale: [0.25, 0.25, 1.0, 1.0],
|
|
},
|
|
};
|
|
|
|
vectorValues = {
|
|
vec4Int8: [
|
|
[-1.0, 0.0, 1.0, 0],
|
|
[-1.0, -1.0, -1.0, 0],
|
|
[1.0, 1.0, 1.0, 1.0],
|
|
],
|
|
mat2Float32: [
|
|
[0.0, 1.0, 0.0, 0.0],
|
|
[0.0, 0.25, 0.25, 0.0],
|
|
[1.0, 0.0, 0.0, 1.0],
|
|
],
|
|
};
|
|
|
|
transformedVectorValues = {
|
|
vec4Int8: [
|
|
[1, 3, 4, 1],
|
|
[1, -5, -4, 1],
|
|
[5, 11, 4, 2],
|
|
],
|
|
mat2Float32: [
|
|
[0.0, 0.25, 0.0, 0.0],
|
|
[0.0, 0.0625, 0.25, 0.0],
|
|
[0.25, 0.0, 0.0, 1.0],
|
|
],
|
|
};
|
|
|
|
arrayOfVectorProperties = {
|
|
propertyVector: {
|
|
type: "VEC3",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
array: true,
|
|
count: 2,
|
|
offset: [
|
|
[2, 2, 2],
|
|
[0, 1, 2],
|
|
],
|
|
},
|
|
propertyMatrix: {
|
|
type: "MAT2",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
array: true,
|
|
count: 2,
|
|
scale: [
|
|
[2, 2, 2, 1],
|
|
[1, 1, 1, 1],
|
|
],
|
|
},
|
|
};
|
|
|
|
arrayOfVectorValues = {
|
|
propertyVector: [
|
|
[
|
|
[1.0, 0.0, 0.0],
|
|
[0.0, 1.0, 0.0],
|
|
],
|
|
[
|
|
[0.0, 0.0, 1.0],
|
|
[1.0, 1.0, 0.0],
|
|
],
|
|
],
|
|
propertyMatrix: [
|
|
[
|
|
[1.0, 1.0, 1.0, 1.0],
|
|
[0.25, 0.0, 0.0, 0.25],
|
|
],
|
|
[
|
|
[0.0, -1.0, 1.0, 0.0],
|
|
[2.0, 0.0, 0.0, 2.0],
|
|
],
|
|
],
|
|
};
|
|
|
|
transformedArrayOfVectorValues = {
|
|
propertyVector: [
|
|
[
|
|
[1.0, 0.0, 0.0],
|
|
[0.0, 1.0, 0.0],
|
|
],
|
|
[
|
|
[0.0, 0.0, 1.0],
|
|
[1.0, 1.0, 0.0],
|
|
],
|
|
],
|
|
propertyMatrix: [
|
|
[
|
|
[1.0, 1.0, 1.0, 1.0],
|
|
[0.25, 0.0, 0.0, 0.25],
|
|
],
|
|
[
|
|
[0.0, -1.0, 1.0, 0],
|
|
[2.0, 0.0, 0.0, 2.0],
|
|
],
|
|
],
|
|
};
|
|
|
|
transformedArrayOfVectorValues = {
|
|
propertyVector: [
|
|
[
|
|
[3.0, 2.0, 2.0],
|
|
[0.0, 2.0, 2.0],
|
|
],
|
|
[
|
|
[2.0, 2.0, 3.0],
|
|
[1.0, 2.0, 2.0],
|
|
],
|
|
],
|
|
propertyMatrix: [
|
|
[
|
|
[2.0, 2.0, 2.0, 1.0],
|
|
[0.25, 0.0, 0.0, 0.25],
|
|
],
|
|
[
|
|
[0.0, -2.0, 2.0, 0.0],
|
|
[2.0, 0.0, 0.0, 2.0],
|
|
],
|
|
],
|
|
};
|
|
|
|
myEnum = MetadataEnum.fromJson({
|
|
id: "myEnum",
|
|
enum: {
|
|
values: [
|
|
{
|
|
value: 0,
|
|
name: "ValueA",
|
|
},
|
|
{
|
|
value: 1,
|
|
name: "ValueB",
|
|
},
|
|
{
|
|
value: 999,
|
|
name: "Other",
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
otherProperties = {
|
|
propertyEnum: {
|
|
type: "ENUM",
|
|
enumType: "myEnum",
|
|
},
|
|
propertyEnumArray: {
|
|
type: "ENUM",
|
|
array: true,
|
|
enumType: "myEnum",
|
|
},
|
|
propertyString: {
|
|
type: "STRING",
|
|
},
|
|
propertyBoolean: {
|
|
type: "BOOLEAN",
|
|
},
|
|
propertyIntegerNotNormalized: {
|
|
type: "SCALAR",
|
|
normalized: false,
|
|
offset: 1,
|
|
scale: 2,
|
|
},
|
|
};
|
|
|
|
otherValues = {
|
|
propertyEnum: ["Other", "ValueA", "ValueB"],
|
|
propertyEnumArray: [["Other", "ValueA"], ["ValueB"], []],
|
|
propertyString: ["a", "bc", ""],
|
|
propertyBoolean: [true, false, false],
|
|
propertyIntegerNotNormalized: [1.0, 2.0, 3.0],
|
|
};
|
|
});
|
|
|
|
it("applies value transform for scalar values", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
for (const propertyId in scalarProperties) {
|
|
if (scalarProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: scalarProperties[propertyId],
|
|
});
|
|
const length = transformedScalarValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = scalarValues[propertyId][i];
|
|
const transformedValue = property.applyValueTransform(value);
|
|
expect(transformedValue).toEqual(
|
|
transformedScalarValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("un-applies value transform for scalar values", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
for (const propertyId in scalarProperties) {
|
|
if (scalarProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: scalarProperties[propertyId],
|
|
});
|
|
const length = scalarValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const transformedValue = transformedScalarValues[propertyId][i];
|
|
const value = property.unapplyValueTransform(transformedValue);
|
|
expect(value).toEqual(scalarValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unapplyValueTransform returns 0 when scale is 0", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "zeroScale",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
offset: 1,
|
|
scale: 0,
|
|
},
|
|
});
|
|
|
|
expect(property.unapplyValueTransform(35.0)).toBe(0.0);
|
|
});
|
|
|
|
it("value transformations are no-ops for identity transformations", function () {
|
|
const valueTransformInPlace = spyOn(
|
|
MetadataClassProperty,
|
|
"valueTransformInPlace",
|
|
);
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "identityTransform",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.applyValueTransform(5.0)).toBe(5.0);
|
|
expect(property.unapplyValueTransform(5.0)).toBe(5.0);
|
|
expect(valueTransformInPlace).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("applies value transform for array values", function () {
|
|
for (const propertyId in arrayProperties) {
|
|
if (arrayProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayProperties[propertyId],
|
|
});
|
|
const length = transformedArrayValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = arrayValues[propertyId][i];
|
|
const transformedValue = property.applyValueTransform(
|
|
clone(value, true),
|
|
);
|
|
expect(transformedValue).toEqual(
|
|
transformedArrayValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("un-applies value transform for array values", function () {
|
|
for (const propertyId in arrayProperties) {
|
|
if (arrayProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayProperties[propertyId],
|
|
});
|
|
const length = arrayValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const transformedValue = transformedArrayValues[propertyId][i];
|
|
const value = property.unapplyValueTransform(
|
|
clone(transformedValue, true),
|
|
);
|
|
expect(value).toEqual(arrayValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("value transforms do not transform variable length arrays", function () {
|
|
const valueTransformInPlace = spyOn(
|
|
MetadataClassProperty,
|
|
"valueTransformInPlace",
|
|
);
|
|
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "zeroScale",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
// In this case the implementation should ignore offset/scale
|
|
offset: [1, 2, 3],
|
|
scale: [2, 2, 2],
|
|
},
|
|
});
|
|
|
|
const values = [-1.0, 0.0, 5.0, 4.0];
|
|
expect(property.applyValueTransform(clone(values, true))).toEqual(values);
|
|
expect(property.unapplyValueTransform(clone(values, true))).toEqual(
|
|
values,
|
|
);
|
|
|
|
expect(valueTransformInPlace).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("applies value transform for vector and matrix values", function () {
|
|
for (const propertyId in vectorProperties) {
|
|
if (vectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: vectorProperties[propertyId],
|
|
});
|
|
const length = transformedVectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = vectorValues[propertyId][i];
|
|
const transformedValue = property.applyValueTransform(
|
|
clone(value, true),
|
|
);
|
|
expect(transformedValue).toEqual(
|
|
transformedVectorValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("un-applies value transform for vector and matrix values", function () {
|
|
for (const propertyId in vectorProperties) {
|
|
if (vectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: vectorProperties[propertyId],
|
|
});
|
|
const length = vectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const transformedValue = transformedVectorValues[propertyId][i];
|
|
const value = property.unapplyValueTransform(
|
|
clone(transformedValue, true),
|
|
);
|
|
expect(value).toEqual(vectorValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("applies value transform for arrays of vectors", function () {
|
|
for (const propertyId in arrayOfVectorProperties) {
|
|
if (arrayOfVectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayOfVectorProperties[propertyId],
|
|
});
|
|
const length = transformedArrayOfVectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = arrayOfVectorValues[propertyId][i];
|
|
const transformedValue = property.applyValueTransform(
|
|
clone(value, true),
|
|
);
|
|
expect(transformedValue).toEqual(
|
|
transformedArrayOfVectorValues[propertyId][i],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("un-applies value transform for arrays of vectors", function () {
|
|
for (const propertyId in arrayOfVectorProperties) {
|
|
if (arrayOfVectorProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: arrayOfVectorProperties[propertyId],
|
|
});
|
|
const length = arrayOfVectorValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const transformedValue =
|
|
transformedArrayOfVectorValues[propertyId][i];
|
|
const value = property.unapplyValueTransform(
|
|
clone(transformedValue, true),
|
|
);
|
|
expect(value).toEqual(arrayOfVectorValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("does not apply transform to other types", function () {
|
|
for (const propertyId in otherProperties) {
|
|
if (otherProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: otherProperties[propertyId],
|
|
enums: {
|
|
myEnum: myEnum,
|
|
},
|
|
});
|
|
const length = otherValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = otherValues[propertyId][i];
|
|
const normalizedValue = property.normalize(value);
|
|
expect(normalizedValue).toEqual(value);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("does not unaapply transform to other types", function () {
|
|
for (const propertyId in otherProperties) {
|
|
if (otherProperties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: otherProperties[propertyId],
|
|
enums: {
|
|
myEnum: myEnum,
|
|
},
|
|
});
|
|
const length = otherValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = otherValues[propertyId][i];
|
|
const normalizedValue = property.normalize(value);
|
|
expect(normalizedValue).toEqual(value);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("handleNoData", function () {
|
|
let properties;
|
|
beforeAll(function () {
|
|
properties = {
|
|
float: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT64",
|
|
noData: -1.0,
|
|
},
|
|
array: {
|
|
array: true,
|
|
count: 4,
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
noData: [255, 255, 255, 255],
|
|
},
|
|
variableLengthArray: {
|
|
array: true,
|
|
type: "STRING",
|
|
noData: [],
|
|
},
|
|
arrayOfVector: {
|
|
array: true,
|
|
count: 2,
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
noData: [
|
|
[0, 0],
|
|
[0, 0],
|
|
],
|
|
},
|
|
};
|
|
});
|
|
|
|
it("passes through valid values unchanged", function () {
|
|
const propertyValues = {
|
|
float: 1.0,
|
|
array: [0, 0, 0, 255],
|
|
variableLengthArray: ["Hello", "World"],
|
|
arrayOfVector: [
|
|
[1, 1],
|
|
[2, -1],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
const expected = propertyValues[propertyId];
|
|
const actual = property.handleNoData(expected);
|
|
expect(actual).toBe(expected);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("converts noData values to undefined", function () {
|
|
const propertyValues = {
|
|
float: -1,
|
|
array: [255, 255, 255, 255],
|
|
variableLengthArray: [],
|
|
arrayOfVector: [
|
|
[0, 0],
|
|
[0, 0],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
const value = propertyValues[propertyId];
|
|
const actual = property.handleNoData(value);
|
|
expect(actual).not.toBeDefined();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
it("packVectorAndMatrixTypes packs vectors and matrices", function () {
|
|
const properties = {
|
|
propertyVec2: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
propertyIVec3: {
|
|
type: "VEC3",
|
|
componentType: "INT32",
|
|
},
|
|
propertyDVec4: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT64",
|
|
},
|
|
propertyMat4: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
},
|
|
propertyIMat3: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
propertyDMat2: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyVec2: [
|
|
new Cartesian2(0.1, 0.8),
|
|
new Cartesian2(0.3, 0.5),
|
|
new Cartesian2(0.7, 0.2),
|
|
],
|
|
propertyIVec3: [
|
|
new Cartesian3(1, 2, 3),
|
|
new Cartesian3(4, 5, 6),
|
|
new Cartesian3(7, 8, 9),
|
|
],
|
|
propertyDVec4: [
|
|
new Cartesian4(0.1, 0.2, 0.3, 0.4),
|
|
new Cartesian4(0.3, 0.2, 0.1, 0.0),
|
|
new Cartesian4(0.1, 0.2, 0.4, 0.5),
|
|
],
|
|
propertyMat4: [
|
|
new Matrix4(1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(0, 2.5, 0, 0, 0, 0.5, 0.25, 0, 0, 0, 3.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0),
|
|
],
|
|
propertyIMat3: [
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(1, 2, 3, 2, 3, 1, 3, 1, 2),
|
|
],
|
|
propertyDMat2: [
|
|
new Matrix2(1.5, 0.0, 0.0, 2.5),
|
|
new Matrix2(1.0, 0.0, 0.0, 1.0),
|
|
new Matrix2(1.5, 2.5, 3.5, 4.5),
|
|
],
|
|
};
|
|
|
|
const packedValues = {
|
|
propertyVec2: [
|
|
[0.1, 0.8],
|
|
[0.3, 0.5],
|
|
[0.7, 0.2],
|
|
],
|
|
propertyIVec3: [
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9],
|
|
],
|
|
propertyDVec4: [
|
|
[0.1, 0.2, 0.3, 0.4],
|
|
[0.3, 0.2, 0.1, 0.0],
|
|
[0.1, 0.2, 0.4, 0.5],
|
|
],
|
|
propertyMat4: [
|
|
// the MatrixN constructor is row-major, but internally things are
|
|
// stored column-major. So these are the transpose of the above
|
|
[1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1],
|
|
[0, 0, 0, 0, 2.5, 0.5, 0, 0, 0, 0.25, 3.5, 0, 0, 0, 0, 1],
|
|
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0],
|
|
],
|
|
propertyIMat3: [
|
|
[2, 0, 0, 0, 2, 0, 0, 0, 2],
|
|
[1, 0, 0, 0, 1, 0, 0, 0, 1],
|
|
[1, 2, 3, 2, 3, 1, 3, 1, 2],
|
|
],
|
|
propertyDMat2: [
|
|
[1.5, 0.0, 0.0, 2.5],
|
|
[1.0, 0.0, 0.0, 1.0],
|
|
[1.5, 3.5, 2.5, 4.5],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
const length = propertyValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = propertyValues[propertyId][i];
|
|
const packed = property.packVectorAndMatrixTypes(value);
|
|
expect(packed).toEqual(packedValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("packVectorAndMatrixTypes packs arrays of vectors and matrices", function () {
|
|
const properties = {
|
|
propertyVec2: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIVec3: {
|
|
type: "VEC3",
|
|
componentType: "INT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDVec4: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT64",
|
|
array: true,
|
|
},
|
|
propertyMat4: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIMat3: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDMat2: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyVec2: [
|
|
new Cartesian2(0.1, 0.8),
|
|
new Cartesian2(0.3, 0.5),
|
|
new Cartesian2(0.7, 0.2),
|
|
],
|
|
propertyIVec3: [
|
|
new Cartesian3(1, 2, 3),
|
|
new Cartesian3(4, 5, 6),
|
|
new Cartesian3(7, 8, 9),
|
|
],
|
|
propertyDVec4: [
|
|
new Cartesian4(0.1, 0.2, 0.3, 0.4),
|
|
new Cartesian4(0.3, 0.2, 0.1, 0.0),
|
|
new Cartesian4(0.1, 0.2, 0.4, 0.5),
|
|
],
|
|
propertyMat4: [
|
|
new Matrix4(1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(0, 2.5, 0, 0, 0, 0.5, 0.25, 0, 0, 0, 3.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0),
|
|
],
|
|
propertyIMat3: [
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(1, 2, 3, 2, 3, 1, 3, 1, 2),
|
|
],
|
|
propertyDMat2: [
|
|
new Matrix2(1.5, 0.0, 0.0, 2.5),
|
|
new Matrix2(1.0, 0.0, 0.0, 1.0),
|
|
new Matrix2(1.5, 2.5, 3.5, 4.5),
|
|
],
|
|
};
|
|
|
|
// prettier-ignore
|
|
const packedValues = {
|
|
propertyVec2: [
|
|
0.1, 0.8,
|
|
0.3, 0.5,
|
|
0.7, 0.2,
|
|
],
|
|
propertyIVec3: [
|
|
1, 2, 3,
|
|
4, 5, 6,
|
|
7, 8, 9,
|
|
],
|
|
propertyDVec4: [
|
|
0.1, 0.2, 0.3, 0.4,
|
|
0.3, 0.2, 0.1, 0.0,
|
|
0.1, 0.2, 0.4, 0.5,
|
|
],
|
|
propertyMat4: [
|
|
// the MatrixN constructor is row-major, but internally things are
|
|
// stored column-major. So these are the transpose of the above
|
|
1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 2.5, 0.5, 0, 0, 0, 0.25, 3.5, 0, 0, 0, 0, 1,
|
|
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0,
|
|
],
|
|
propertyIMat3: [
|
|
2, 0, 0, 0, 2, 0, 0, 0, 2,
|
|
1, 0, 0, 0, 1, 0, 0, 0, 1,
|
|
1, 2, 3, 2, 3, 1, 3, 1, 2,
|
|
],
|
|
propertyDMat2: [
|
|
1.5, 0.0, 0.0, 2.5,
|
|
1.0, 0.0, 0.0, 1.0,
|
|
1.5, 3.5, 2.5, 4.5,
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
|
|
const value = propertyValues[propertyId];
|
|
const packed = property.packVectorAndMatrixTypes(value);
|
|
const expected = packedValues[propertyId];
|
|
expect(packed).toEqual(expected);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("packVectorAndMatrixTypes packs nested arrays of vectors", function () {
|
|
const properties = {
|
|
propertyVec2: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIVec3: {
|
|
type: "VEC3",
|
|
componentType: "INT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDVec4: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT64",
|
|
array: true,
|
|
},
|
|
propertyMat4: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIMat3: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDMat2: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyVec2: [
|
|
new Cartesian2(0.1, 0.8),
|
|
new Cartesian2(0.3, 0.5),
|
|
new Cartesian2(0.7, 0.2),
|
|
],
|
|
propertyIVec3: [
|
|
new Cartesian3(1, 2, 3),
|
|
new Cartesian3(4, 5, 6),
|
|
new Cartesian3(7, 8, 9),
|
|
],
|
|
propertyDVec4: [
|
|
new Cartesian4(0.1, 0.2, 0.3, 0.4),
|
|
new Cartesian4(0.3, 0.2, 0.1, 0.0),
|
|
new Cartesian4(0.1, 0.2, 0.4, 0.5),
|
|
],
|
|
propertyMat4: [
|
|
new Matrix4(1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(0, 2.5, 0, 0, 0, 0.5, 0.25, 0, 0, 0, 3.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0),
|
|
],
|
|
propertyIMat3: [
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(1, 2, 3, 2, 3, 1, 3, 1, 2),
|
|
],
|
|
propertyDMat2: [
|
|
new Matrix2(1.5, 0.0, 0.0, 2.5),
|
|
new Matrix2(1.0, 0.0, 0.0, 1.0),
|
|
new Matrix2(1.5, 2.5, 3.5, 4.5),
|
|
],
|
|
};
|
|
|
|
// prettier-ignore
|
|
const packedValues = {
|
|
propertyVec2: [
|
|
[0.1, 0.8],
|
|
[0.3, 0.5],
|
|
[0.7, 0.2],
|
|
],
|
|
propertyIVec3: [
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9],
|
|
],
|
|
propertyDVec4: [
|
|
[0.1, 0.2, 0.3, 0.4],
|
|
[0.3, 0.2, 0.1, 0.0],
|
|
[0.1, 0.2, 0.4, 0.5],
|
|
],
|
|
propertyMat4: [
|
|
// the MatrixN constructor is row-major, but internally things are
|
|
// stored column-major. So these are the transpose of the above
|
|
[1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1],
|
|
[0, 0, 0, 0, 2.5, 0.5, 0, 0, 0, 0.25, 3.5, 0, 0, 0, 0, 1],
|
|
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0],
|
|
],
|
|
propertyIMat3: [
|
|
[2, 0, 0, 0, 2, 0, 0, 0, 2],
|
|
[1, 0, 0, 0, 1, 0, 0, 0, 1],
|
|
[1, 2, 3, 2, 3, 1, 3, 1, 2],
|
|
],
|
|
propertyDMat2: [
|
|
[1.5, 0.0, 0.0, 2.5],
|
|
[1.0, 0.0, 0.0, 1.0],
|
|
[1.5, 3.5, 2.5, 4.5],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
|
|
const value = propertyValues[propertyId];
|
|
const nested = true;
|
|
const packed = property.packVectorAndMatrixTypes(value, nested);
|
|
const expected = packedValues[propertyId];
|
|
expect(packed).toEqual(expected);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("packVectorAndMatrixTypes does not affect other types", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
const properties = {
|
|
propertyString: {
|
|
type: "STRING",
|
|
},
|
|
propertyBoolean: {
|
|
type: "BOOLEAN",
|
|
},
|
|
propertyArray: {
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
array: true,
|
|
count: 5,
|
|
},
|
|
propertyBigIntArray: {
|
|
type: "SCALAR",
|
|
componentType: "UINT64",
|
|
array: true,
|
|
count: 2,
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyString: ["a", "bc", ""],
|
|
propertyBoolean: [true, false, false],
|
|
propertyArray: [
|
|
[1, 2, 3, 4, 5],
|
|
[0, 1, 2, 3, 4],
|
|
[1, 4, 9, 16, 25],
|
|
],
|
|
propertyBigIntArray: [
|
|
[BigInt(0), BigInt(0)],
|
|
[BigInt(1), BigInt(3)],
|
|
[BigInt(45), BigInt(32)],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
const length = propertyValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = propertyValues[propertyId][i];
|
|
const packed = property.packVectorAndMatrixTypes(value);
|
|
expect(packed).toEqual(value);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unpackVectorAndMatrixTypes unpacks vectors and matrices", function () {
|
|
const properties = {
|
|
propertyVec2: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
propertyIVec3: {
|
|
type: "VEC3",
|
|
componentType: "INT32",
|
|
},
|
|
propertyDVec4: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT64",
|
|
},
|
|
propertyMat4: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
},
|
|
propertyIMat3: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
propertyDMat2: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyVec2: [
|
|
new Cartesian2(0.1, 0.8),
|
|
new Cartesian2(0.3, 0.5),
|
|
new Cartesian2(0.7, 0.2),
|
|
],
|
|
propertyIVec3: [
|
|
new Cartesian3(1, 2, 3),
|
|
new Cartesian3(4, 5, 6),
|
|
new Cartesian3(7, 8, 9),
|
|
],
|
|
propertyDVec4: [
|
|
new Cartesian4(0.1, 0.2, 0.3, 0.4),
|
|
new Cartesian4(0.3, 0.2, 0.1, 0.0),
|
|
new Cartesian4(0.1, 0.2, 0.4, 0.5),
|
|
],
|
|
propertyMat4: [
|
|
new Matrix4(1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(0, 2.5, 0, 0, 0, 0.5, 0.25, 0, 0, 0, 3.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0),
|
|
],
|
|
propertyIMat3: [
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(1, 2, 3, 2, 3, 1, 3, 1, 2),
|
|
],
|
|
propertyDMat2: [
|
|
new Matrix2(1.5, 0.0, 0.0, 2.5),
|
|
new Matrix2(1.0, 0.0, 0.0, 1.0),
|
|
new Matrix2(1.5, 2.5, 3.5, 4.5),
|
|
],
|
|
};
|
|
|
|
const packedValues = {
|
|
propertyVec2: [
|
|
[0.1, 0.8],
|
|
[0.3, 0.5],
|
|
[0.7, 0.2],
|
|
],
|
|
propertyIVec3: [
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9],
|
|
],
|
|
propertyDVec4: [
|
|
[0.1, 0.2, 0.3, 0.4],
|
|
[0.3, 0.2, 0.1, 0.0],
|
|
[0.1, 0.2, 0.4, 0.5],
|
|
],
|
|
propertyMat4: [
|
|
// the MatrixN constructor is row-major, but internally things are
|
|
// stored column-major. So these are the transpose of the above
|
|
[1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1],
|
|
[0, 0, 0, 0, 2.5, 0.5, 0, 0, 0, 0.25, 3.5, 0, 0, 0, 0, 1],
|
|
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0],
|
|
],
|
|
propertyIMat3: [
|
|
[2, 0, 0, 0, 2, 0, 0, 0, 2],
|
|
[1, 0, 0, 0, 1, 0, 0, 0, 1],
|
|
[1, 2, 3, 2, 3, 1, 3, 1, 2],
|
|
],
|
|
propertyDMat2: [
|
|
[1.5, 0.0, 0.0, 2.5],
|
|
[1.0, 0.0, 0.0, 1.0],
|
|
[1.5, 3.5, 2.5, 4.5],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
const length = propertyValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = packedValues[propertyId][i];
|
|
const unpacked = property.unpackVectorAndMatrixTypes(value);
|
|
expect(unpacked).toEqual(propertyValues[propertyId][i]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unpackVectorAndMatrixTypes unpacks arrays of vectors and matrices", function () {
|
|
const properties = {
|
|
propertyVec2: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIVec3: {
|
|
type: "VEC3",
|
|
componentType: "INT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDVec4: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT64",
|
|
array: true,
|
|
},
|
|
propertyMat4: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIMat3: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDMat2: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyVec2: [
|
|
new Cartesian2(0.1, 0.8),
|
|
new Cartesian2(0.3, 0.5),
|
|
new Cartesian2(0.7, 0.2),
|
|
],
|
|
propertyIVec3: [
|
|
new Cartesian3(1, 2, 3),
|
|
new Cartesian3(4, 5, 6),
|
|
new Cartesian3(7, 8, 9),
|
|
],
|
|
propertyDVec4: [
|
|
new Cartesian4(0.1, 0.2, 0.3, 0.4),
|
|
new Cartesian4(0.3, 0.2, 0.1, 0.0),
|
|
new Cartesian4(0.1, 0.2, 0.4, 0.5),
|
|
],
|
|
propertyMat4: [
|
|
new Matrix4(1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(0, 2.5, 0, 0, 0, 0.5, 0.25, 0, 0, 0, 3.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0),
|
|
],
|
|
propertyIMat3: [
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(1, 2, 3, 2, 3, 1, 3, 1, 2),
|
|
],
|
|
propertyDMat2: [
|
|
new Matrix2(1.5, 0.0, 0.0, 2.5),
|
|
new Matrix2(1.0, 0.0, 0.0, 1.0),
|
|
new Matrix2(1.5, 2.5, 3.5, 4.5),
|
|
],
|
|
};
|
|
|
|
// prettier-ignore
|
|
const packedValues = {
|
|
propertyVec2: [
|
|
0.1, 0.8,
|
|
0.3, 0.5,
|
|
0.7, 0.2,
|
|
],
|
|
propertyIVec3: [
|
|
1, 2, 3,
|
|
4, 5, 6,
|
|
7, 8, 9,
|
|
],
|
|
propertyDVec4: [
|
|
0.1, 0.2, 0.3, 0.4,
|
|
0.3, 0.2, 0.1, 0.0,
|
|
0.1, 0.2, 0.4, 0.5,
|
|
],
|
|
propertyMat4: [
|
|
// the MatrixN constructor is row-major, but internally things are
|
|
// stored column-major. So these are the transpose of the above
|
|
1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1,
|
|
0, 0, 0, 0, 2.5, 0.5, 0, 0, 0, 0.25, 3.5, 0, 0, 0, 0, 1,
|
|
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0,
|
|
],
|
|
propertyIMat3: [
|
|
2, 0, 0, 0, 2, 0, 0, 0, 2,
|
|
1, 0, 0, 0, 1, 0, 0, 0, 1,
|
|
1, 2, 3, 2, 3, 1, 3, 1, 2,
|
|
],
|
|
propertyDMat2: [
|
|
1.5, 0.0, 0.0, 2.5,
|
|
1.0, 0.0, 0.0, 1.0,
|
|
1.5, 3.5, 2.5, 4.5,
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
|
|
const packed = packedValues[propertyId];
|
|
const unpacked = property.unpackVectorAndMatrixTypes(packed);
|
|
const expected = propertyValues[propertyId];
|
|
expect(unpacked).toEqual(expected);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unpackVectorAndMatrixTypes unpacks nested arrays of vectors", function () {
|
|
const properties = {
|
|
propertyVec2: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIVec3: {
|
|
type: "VEC3",
|
|
componentType: "INT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDVec4: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT64",
|
|
array: true,
|
|
},
|
|
propertyMat4: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
},
|
|
propertyIMat3: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
propertyDMat2: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyVec2: [
|
|
new Cartesian2(0.1, 0.8),
|
|
new Cartesian2(0.3, 0.5),
|
|
new Cartesian2(0.7, 0.2),
|
|
],
|
|
propertyIVec3: [
|
|
new Cartesian3(1, 2, 3),
|
|
new Cartesian3(4, 5, 6),
|
|
new Cartesian3(7, 8, 9),
|
|
],
|
|
propertyDVec4: [
|
|
new Cartesian4(0.1, 0.2, 0.3, 0.4),
|
|
new Cartesian4(0.3, 0.2, 0.1, 0.0),
|
|
new Cartesian4(0.1, 0.2, 0.4, 0.5),
|
|
],
|
|
propertyMat4: [
|
|
new Matrix4(1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(0, 2.5, 0, 0, 0, 0.5, 0.25, 0, 0, 0, 3.5, 0, 0, 0, 0, 1),
|
|
new Matrix4(1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0),
|
|
],
|
|
propertyIMat3: [
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(1, 2, 3, 2, 3, 1, 3, 1, 2),
|
|
],
|
|
propertyDMat2: [
|
|
new Matrix2(1.5, 0.0, 0.0, 2.5),
|
|
new Matrix2(1.0, 0.0, 0.0, 1.0),
|
|
new Matrix2(1.5, 2.5, 3.5, 4.5),
|
|
],
|
|
};
|
|
|
|
// prettier-ignore
|
|
const packedValues = {
|
|
propertyVec2: [
|
|
[0.1, 0.8],
|
|
[0.3, 0.5],
|
|
[0.7, 0.2],
|
|
],
|
|
propertyIVec3: [
|
|
[1, 2, 3],
|
|
[4, 5, 6],
|
|
[7, 8, 9],
|
|
],
|
|
propertyDVec4: [
|
|
[0.1, 0.2, 0.3, 0.4],
|
|
[0.3, 0.2, 0.1, 0.0],
|
|
[0.1, 0.2, 0.4, 0.5],
|
|
],
|
|
propertyMat4: [
|
|
// the MatrixN constructor is row-major, but internally things are
|
|
// stored column-major. So these are the transpose of the above
|
|
[1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 1],
|
|
[0, 0, 0, 0, 2.5, 0.5, 0, 0, 0, 0.25, 3.5, 0, 0, 0, 0, 1],
|
|
[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0],
|
|
],
|
|
propertyIMat3: [
|
|
[2, 0, 0, 0, 2, 0, 0, 0, 2],
|
|
[1, 0, 0, 0, 1, 0, 0, 0, 1],
|
|
[1, 2, 3, 2, 3, 1, 3, 1, 2],
|
|
],
|
|
propertyDMat2: [
|
|
[1.5, 0.0, 0.0, 2.5],
|
|
[1.0, 0.0, 0.0, 1.0],
|
|
[1.5, 3.5, 2.5, 4.5],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
|
|
const packed = packedValues[propertyId];
|
|
const nested = true;
|
|
const unpacked = property.unpackVectorAndMatrixTypes(packed, nested);
|
|
const expected = propertyValues[propertyId];
|
|
expect(unpacked).toEqual(expected);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("unpackVectorAndMatrixTypes does not affect other types", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
const properties = {
|
|
propertyString: {
|
|
type: "STRING",
|
|
},
|
|
propertyBoolean: {
|
|
type: "BOOLEAN",
|
|
},
|
|
propertyArray: {
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
array: true,
|
|
count: 5,
|
|
},
|
|
propertyBigIntArray: {
|
|
type: "SCALAR",
|
|
componentType: "UINT64",
|
|
array: true,
|
|
count: 2,
|
|
},
|
|
};
|
|
|
|
const propertyValues = {
|
|
propertyString: ["a", "bc", ""],
|
|
propertyBoolean: [true, false, false],
|
|
propertyArray: [
|
|
[1, 2, 3, 4, 5],
|
|
[0, 1, 2, 3, 4],
|
|
[1, 4, 9, 16, 25],
|
|
],
|
|
propertyBigIntArray: [
|
|
[BigInt(0), BigInt(0)],
|
|
[BigInt(1), BigInt(3)],
|
|
[BigInt(45), BigInt(32)],
|
|
],
|
|
};
|
|
|
|
for (const propertyId in properties) {
|
|
if (properties.hasOwnProperty(propertyId)) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: propertyId,
|
|
property: properties[propertyId],
|
|
});
|
|
const length = propertyValues[propertyId].length;
|
|
for (let i = 0; i < length; ++i) {
|
|
const value = propertyValues[propertyId][i];
|
|
const unpacked = property.unpackVectorAndMatrixTypes(value);
|
|
expect(unpacked).toEqual(value);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("validate returns undefined if the value is valid", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "VEC3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(new Cartesian3(1.0, 2.0, 3.0))).toBeUndefined();
|
|
});
|
|
|
|
it("validate returns undefined for valid arrays of vectors", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "VEC3",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
});
|
|
|
|
expect(
|
|
property.validate([
|
|
new Cartesian3(1.0, 2.0, 3.0),
|
|
new Cartesian3(4.0, 5.0, 6.0),
|
|
new Cartesian3(7.0, 8.0, 9.0),
|
|
]),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it("validate returns undefined for valid arrays of matrices", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 3,
|
|
},
|
|
});
|
|
|
|
expect(
|
|
property.validate([
|
|
new Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1),
|
|
new Matrix3(2, 0, 0, 0, 2, 0, 0, 0, 2),
|
|
new Matrix3(3, 0, 0, 0, 3, 0, 0, 0, 3),
|
|
]),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it("validate returns error message if property is required but value is undefined", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
expect(property.validate(undefined)).toBe(
|
|
"required property must have a value",
|
|
);
|
|
});
|
|
|
|
it("validate returns undefined if value is undefined but a default is available", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
required: true,
|
|
default: -1.0,
|
|
},
|
|
});
|
|
|
|
expect(property.validate(undefined)).not.toBeDefined();
|
|
});
|
|
|
|
it("validate returns error message if type is ARRAY and value is not an array", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 8,
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("value 8 must be an array");
|
|
});
|
|
|
|
it("validate returns error message if type is a vector and the component type is not vector-compatibile", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "VEC2",
|
|
componentType: "STRING",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe(
|
|
"componentType STRING is incompatible with vector type VEC2",
|
|
);
|
|
});
|
|
|
|
it("validate returns error message if type is a matrix and the component type is not vector-compatibile", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "MAT3",
|
|
componentType: "INT64",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe(
|
|
"componentType INT64 is incompatible with matrix type MAT3",
|
|
);
|
|
});
|
|
|
|
it("validate returns error message if type is a vector and value is not a Cartesian", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "VEC2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("vector value 8 must be a Cartesian2");
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "VEC3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("vector value 8 must be a Cartesian3");
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "VEC4",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("vector value 8 must be a Cartesian4");
|
|
});
|
|
|
|
it("validate returns error message if type is a matrix and value is not a Matrix", function () {
|
|
let property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "MAT2",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("matrix value 8 must be a Matrix2");
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "MAT3",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("matrix value 8 must be a Matrix3");
|
|
|
|
property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "MAT4",
|
|
componentType: "FLOAT32",
|
|
},
|
|
});
|
|
|
|
expect(property.validate(8.0)).toBe("matrix value 8 must be a Matrix4");
|
|
});
|
|
|
|
it("validate returns error message for an array that doesn't match the count", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "position",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "FLOAT32",
|
|
array: true,
|
|
count: 6,
|
|
},
|
|
});
|
|
|
|
expect(property.validate([1.0, 2.0])).toBe(
|
|
"Array length does not match property.arrayLength",
|
|
);
|
|
});
|
|
|
|
it("validate returns error message if enum name is invalid", function () {
|
|
const myEnum = MetadataEnum.fromJson({
|
|
id: "myEnum",
|
|
enum: {
|
|
values: [
|
|
{
|
|
value: 0,
|
|
name: "ValueA",
|
|
},
|
|
{
|
|
value: 1,
|
|
name: "ValueB",
|
|
},
|
|
{
|
|
value: 999,
|
|
name: "Other",
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "myEnum",
|
|
property: {
|
|
type: "ENUM",
|
|
enumType: "myEnum",
|
|
},
|
|
enums: {
|
|
myEnum: myEnum,
|
|
},
|
|
});
|
|
|
|
expect(property.validate("INVALID")).toBe(
|
|
"value INVALID is not a valid enum name for myEnum",
|
|
);
|
|
expect(property.validate(0)).toBe(
|
|
"value 0 is not a valid enum name for myEnum",
|
|
);
|
|
});
|
|
|
|
it("validate returns error message if value does not match the type (SCALAR)", function () {
|
|
const types = [
|
|
"INT8",
|
|
"UINT8",
|
|
"INT16",
|
|
"UINT16",
|
|
"INT32",
|
|
"UINT32",
|
|
"INT64",
|
|
"UINT64",
|
|
"FLOAT32",
|
|
"FLOAT64",
|
|
];
|
|
|
|
for (let i = 0; i < types.length; ++i) {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: types[i],
|
|
},
|
|
});
|
|
expect(property.validate({})).toBe(
|
|
`value [object Object] does not match type ${types[i]}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
it("validate returns error message if value does not match the type (BOOLEAN)", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "BOOLEAN",
|
|
},
|
|
});
|
|
expect(property.validate({})).toBe(
|
|
`value [object Object] does not match type BOOLEAN`,
|
|
);
|
|
});
|
|
|
|
it("validate returns error message if value does not match the type (STRING)", function () {
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "STRING",
|
|
},
|
|
});
|
|
expect(property.validate({})).toBe(
|
|
`value [object Object] does not match type STRING`,
|
|
);
|
|
});
|
|
|
|
it("validate returns error message if value is out of range", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
const outOfRangeValues = {
|
|
INT8: [-129, 128],
|
|
UINT8: [-1, 256],
|
|
INT16: [-32769, 32768],
|
|
UINT16: [-1, 65536],
|
|
INT32: [-2147483649, 2147483648],
|
|
UINT32: [-1, 4294967296],
|
|
INT64: [BigInt("-9223372036854775809"), BigInt("9223372036854775808")],
|
|
UINT64: [BigInt(-1), BigInt("18446744073709551616")],
|
|
FLOAT32: [-Number.MAX_VALUE, Number.MAX_VALUE],
|
|
};
|
|
|
|
for (const type in outOfRangeValues) {
|
|
if (outOfRangeValues.hasOwnProperty(type)) {
|
|
const values = outOfRangeValues[type];
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: type,
|
|
},
|
|
});
|
|
for (let i = 0; i < values.length; ++i) {
|
|
expect(property.validate(values[i])).toBe(
|
|
`value ${values[i]} is out of range for type ${type}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("validate returns error message for non-finite values", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
const nonFiniteValues = [
|
|
NaN,
|
|
Number.POSITIVE_INFINITY,
|
|
Number.NEGATIVE_INFINITY,
|
|
];
|
|
const types = [
|
|
"INT8",
|
|
"UINT8",
|
|
"INT16",
|
|
"UINT16",
|
|
"INT32",
|
|
"UINT32",
|
|
"INT64",
|
|
"UINT64",
|
|
"FLOAT32",
|
|
"FLOAT64",
|
|
];
|
|
|
|
for (let i = 0; i < types.length; i++) {
|
|
const type = types[i];
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: type,
|
|
},
|
|
});
|
|
for (let i = 0; i < nonFiniteValues.length; ++i) {
|
|
expect(property.validate(nonFiniteValues[i])).toBe(
|
|
`value ${nonFiniteValues[i]} of type ${type} must be finite`,
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
it("validate returns error message if component value is out of range", function () {
|
|
if (!FeatureDetection.supportsBigInt()) {
|
|
return;
|
|
}
|
|
|
|
const outOfRangeValues = {
|
|
INT8: [-129, 128],
|
|
UINT8: [-1, 256],
|
|
INT16: [-32769, 32768],
|
|
UINT16: [-1, 65536],
|
|
INT32: [-2147483649, 2147483648],
|
|
UINT32: [-1, 4294967296],
|
|
INT64: [BigInt("-9223372036854775809"), BigInt("9223372036854775808")],
|
|
UINT64: [BigInt(-1), BigInt("18446744073709551616")],
|
|
FLOAT32: [-Number.MAX_VALUE, Number.MAX_VALUE],
|
|
};
|
|
|
|
for (const componentType in outOfRangeValues) {
|
|
if (outOfRangeValues.hasOwnProperty(componentType)) {
|
|
const values = outOfRangeValues[componentType];
|
|
const property = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
array: true,
|
|
type: "SCALAR",
|
|
componentType: componentType,
|
|
},
|
|
});
|
|
for (let i = 0; i < values.length; ++i) {
|
|
expect(property.validate(values)).toBe(
|
|
`value ${values[0]} is out of range for type ${componentType}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it("validate returns error message if value is outside the normalized range", function () {
|
|
const propertyInt8 = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "INT8",
|
|
normalized: true,
|
|
},
|
|
});
|
|
|
|
const propertyUint8 = MetadataClassProperty.fromJson({
|
|
id: "property",
|
|
property: {
|
|
type: "SCALAR",
|
|
componentType: "UINT8",
|
|
normalized: true,
|
|
},
|
|
});
|
|
|
|
expect(propertyInt8.validate(-1.1)).toBe(
|
|
"value -1.1 is out of range for type INT8 (normalized)",
|
|
);
|
|
expect(propertyInt8.validate(1.1)).toBe(
|
|
"value 1.1 is out of range for type INT8 (normalized)",
|
|
);
|
|
expect(propertyUint8.validate(-0.1)).toBe(
|
|
"value -0.1 is out of range for type UINT8 (normalized)",
|
|
);
|
|
expect(propertyUint8.validate(1.1)).toBe(
|
|
"value 1.1 is out of range for type UINT8 (normalized)",
|
|
);
|
|
});
|
|
|
|
describe("valueTransformInPlace", function () {
|
|
it("applies function to a scalar", function () {
|
|
const value = 1;
|
|
const offset = 1;
|
|
const scale = 2;
|
|
const result = MetadataClassProperty.valueTransformInPlace(
|
|
value,
|
|
offset,
|
|
scale,
|
|
MetadataComponentType.applyValueTransform,
|
|
);
|
|
|
|
expect(result).toBe(3);
|
|
});
|
|
|
|
it("applies function to a flat array", function () {
|
|
const value = [1, 1, 1];
|
|
const offset = [1, 2, 3];
|
|
const scale = [2, 2, 2];
|
|
const result = MetadataClassProperty.valueTransformInPlace(
|
|
value,
|
|
offset,
|
|
scale,
|
|
MetadataComponentType.applyValueTransform,
|
|
);
|
|
expect(result).toEqual([3, 4, 5]);
|
|
});
|
|
|
|
it("applies function to a nested array", function () {
|
|
const values = [
|
|
[1, 1, 1],
|
|
[1, 1, 1],
|
|
[1, 1, 1],
|
|
];
|
|
const offset = [
|
|
[1, 2, 3],
|
|
[1, 2, 3],
|
|
[1, 2, 3],
|
|
];
|
|
const scale = [
|
|
[2, 2, 2],
|
|
[2, 2, 2],
|
|
[2, 2, 2],
|
|
];
|
|
const result = MetadataClassProperty.valueTransformInPlace(
|
|
values,
|
|
offset,
|
|
scale,
|
|
MetadataComponentType.applyValueTransform,
|
|
);
|
|
expect(result).toEqual([
|
|
[3, 4, 5],
|
|
[3, 4, 5],
|
|
[3, 4, 5],
|
|
]);
|
|
});
|
|
});
|
|
});
|