Skip to content

Commit

Permalink
Stricter array length checks
Browse files Browse the repository at this point in the history
  • Loading branch information
javagl committed Nov 16, 2024
1 parent 27a4ec7 commit c313f35
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/validation/extensions/NgaGpmValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1993,14 +1993,14 @@ export class NgaGpmValidator implements Validator<any> {
covarUpperTriangle: any,
context: ValidationContext
): boolean {
// The covarUpperTriangle MUST be an array of at least 6 numbers
// The covarUpperTriangle MUST be an array of 6 numbers
if (
!BasicValidator.validateArray(
path,
name,
covarUpperTriangle,
6,
undefined,
6,
"number",
context
)
Expand Down
22 changes: 22 additions & 0 deletions src/validation/extensions/gpm/NgaGpmValidatorCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,4 +382,26 @@ export class NgaGpmValidatorCommon {
static computeTriangularNumber(n: number): number {
return (n * (n + 1)) / 2;
}

/**
* Returns whether the given number is a triangular number.
*
* The https://en.wikipedia.org/wiki/Triangular_number is the number
* of elements in the "upper-triangular of a covariance matrix",
* as used in the NGA GPM extensions.
*
* @param n - The input
* @returns Whether the given number is a triangular number
*/
static isTriangularNumber(n: number): boolean {
// The n-th triangular number is T(n) = (n*(n+1))/2
// The inverse function for that is 0.5 * (sqrt(8*n+1) - 1)
// So n is a triangular number when 8*n+1 is a square
if (n <= 0) {
return false;
}
const radicand = 8 * n + 1;
const integralRoot = Math.round(Math.sqrt(radicand));
return integralRoot * integralRoot === radicand;
}
}
53 changes: 39 additions & 14 deletions src/validation/gltf/gpmLocal/NgaGpmLocalValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { GltfData } from "../GltfData";
import { StructureValidationIssues } from "../../../issues/StructureValidationIssues";
import { TextureValidator } from "../TextureValidator";
import { NgaGpmValidatorCommon } from "../../extensions/gpm/NgaGpmValidatorCommon";
import { NgaGpmValidationIssues } from "../../extensions/gpm/NgaGpmValidationIssues";

/**
* A class for validating the `NGA_gpm_local` extension in glTF assets.
Expand Down Expand Up @@ -269,13 +270,13 @@ export class NgaGpmLocalValidator {
anchorPointsIndirect: any,
context: ValidationContext
): boolean {
// The anchorPointsIndirect MUST be an array of objects
// The anchorPointsIndirect MUST be an array of at least 1 object
if (
!BasicValidator.validateArray(
path,
name,
anchorPointsIndirect,
undefined,
1,
undefined,
"object",
context
Expand Down Expand Up @@ -500,13 +501,13 @@ export class NgaGpmLocalValidator {
anchorPointsDirect: any,
context: ValidationContext
): boolean {
// The anchorPointsDirect MUST be an array of objects
// The anchorPointsDirect MUST be an array of at least 1 object
if (
!BasicValidator.validateArray(
path,
name,
anchorPointsDirect,
undefined,
1,
undefined,
"object",
context
Expand Down Expand Up @@ -610,16 +611,40 @@ export class NgaGpmLocalValidator {
covarianceDirectUpperTriangle: any,
context: ValidationContext
): boolean {
// The covarianceDirectUpperTriangle MUST be an array of numbers
return BasicValidator.validateArray(
path,
"covarianceDirectUpperTriangle",
covarianceDirectUpperTriangle,
undefined,
undefined,
"number",
context
);
// The covarianceDirectUpperTriangle MUST be an array of at least 1 number
if (
!BasicValidator.validateArray(
path,
"covarianceDirectUpperTriangle",
covarianceDirectUpperTriangle,
1,
undefined,
"number",
context
)
) {
return false;
}

let result = true;

// The length of the array for the upper-triangular of the covariance
// matrix MUST be a triangular number
const n = covarianceDirectUpperTriangle.length;
const isTriangularNumber = NgaGpmValidatorCommon.isTriangularNumber(n);
if (!isTriangularNumber) {
const message =
`The number of elements in the upper-triangular of the covariance ` +
`matrix must be a triangular number, but is ${n}`;
const issue = NgaGpmValidationIssues.ARRAY_LENGTH_INCONSISTENT(
path,
message
);
context.addIssue(issue);
result = false;
}

return result;
}

/**
Expand Down

0 comments on commit c313f35

Please sign in to comment.