@aura3d/engine 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -42
- package/dist/aura3d-cli/asset-core-types.d.ts +19 -0
- package/dist/aura3d-cli/asset-core-types.d.ts.map +1 -1
- package/dist/aura3d-cli/asset-manifest.d.ts.map +1 -1
- package/dist/aura3d-cli/asset-manifest.js +2 -1
- package/dist/aura3d-cli/asset-manifest.js.map +1 -1
- package/dist/aura3d-cli/cli-help.d.ts.map +1 -1
- package/dist/aura3d-cli/cli-help.js +2 -0
- package/dist/aura3d-cli/cli-help.js.map +1 -1
- package/dist/aura3d-cli/cli.js +24 -1
- package/dist/aura3d-cli/cli.js.map +1 -1
- package/dist/aura3d-cli/index.d.ts +5 -1
- package/dist/aura3d-cli/index.d.ts.map +1 -1
- package/dist/aura3d-cli/index.js +5 -1
- package/dist/aura3d-cli/index.js.map +1 -1
- package/dist/aura3d-cli/meshy/admission.d.ts +40 -0
- package/dist/aura3d-cli/meshy/admission.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/admission.js +126 -0
- package/dist/aura3d-cli/meshy/admission.js.map +1 -0
- package/dist/aura3d-cli/meshy/evidence.d.ts +12 -0
- package/dist/aura3d-cli/meshy/evidence.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/evidence.js +37 -0
- package/dist/aura3d-cli/meshy/evidence.js.map +1 -0
- package/dist/aura3d-cli/meshy/import.d.ts +25 -0
- package/dist/aura3d-cli/meshy/import.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/import.js +104 -0
- package/dist/aura3d-cli/meshy/import.js.map +1 -0
- package/dist/aura3d-cli/meshy/index.d.ts +10 -0
- package/dist/aura3d-cli/meshy/index.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/index.js +6 -0
- package/dist/aura3d-cli/meshy/index.js.map +1 -0
- package/dist/aura3d-cli/meshy/metadata.d.ts +22 -0
- package/dist/aura3d-cli/meshy/metadata.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/metadata.js +176 -0
- package/dist/aura3d-cli/meshy/metadata.js.map +1 -0
- package/dist/aura3d-cli/meshy/provenance.d.ts +4 -0
- package/dist/aura3d-cli/meshy/provenance.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/provenance.js +21 -0
- package/dist/aura3d-cli/meshy/provenance.js.map +1 -0
- package/dist/aura3d-cli/meshy/thumbnail.d.ts +19 -0
- package/dist/aura3d-cli/meshy/thumbnail.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/thumbnail.js +59 -0
- package/dist/aura3d-cli/meshy/thumbnail.js.map +1 -0
- package/dist/aura3d-cli/meshy/validation.d.ts +5 -0
- package/dist/aura3d-cli/meshy/validation.d.ts.map +1 -0
- package/dist/aura3d-cli/meshy/validation.js +64 -0
- package/dist/aura3d-cli/meshy/validation.js.map +1 -0
- package/dist/create-aura3d/index.js +1 -1
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.d.ts.map +1 -1
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js +86 -4
- package/dist/create-aura3d/showcase-spec-game-geometry-extractor.js.map +1 -1
- package/dist/engine/agent-api/GameGenreKits.d.ts +7 -1
- package/dist/engine/agent-api/GameGenreKits.d.ts.map +1 -1
- package/dist/engine/agent-api/GameGenreKits.js +33 -3
- package/dist/engine/agent-api/GameGenreKits.js.map +1 -1
- package/dist/engine/agent-api/index.d.ts +15 -0
- package/dist/engine/agent-api/index.d.ts.map +1 -1
- package/dist/engine/agent-api/index.js +51 -6
- package/dist/engine/agent-api/index.js.map +1 -1
- package/dist/engine/agent-api/product-viewer-runtime.d.ts.map +1 -1
- package/dist/engine/production-runtime/TypedGLBActor.d.ts +14 -0
- package/dist/engine/production-runtime/TypedGLBActor.d.ts.map +1 -1
- package/dist/engine/production-runtime/TypedGLBActor.js +59 -4
- package/dist/engine/production-runtime/TypedGLBActor.js.map +1 -1
- package/dist/rendering/ForwardPass.d.ts +2 -0
- package/dist/rendering/ForwardPass.d.ts.map +1 -1
- package/dist/rendering/ForwardPass.js.map +1 -1
- package/dist/rendering/Renderer.js +5 -4
- package/dist/rendering/Renderer.js.map +1 -1
- package/dist/rendering/SceneOptimization.d.ts +1 -0
- package/dist/rendering/SceneOptimization.d.ts.map +1 -1
- package/dist/rendering/SceneOptimization.js +4 -2
- package/dist/rendering/SceneOptimization.js.map +1 -1
- package/package.json +27 -22
- package/templates/cinematic-scene/package.json +1 -1
- package/templates/mini-game/package.json +1 -1
- package/templates/product-viewer/package.json +1 -1
- package/templates/cinematic-scene/node_modules/.vite/deps/_metadata.json +0 -8
- package/templates/cinematic-scene/node_modules/.vite/deps/package.json +0 -3
- package/templates/cinematic-scene/test-results/.last-run.json +0 -6
- package/templates/cinematic-scene/test-results/route-health-Aura3D-cinematic-scene-reaches-ready-state/error-context.md +0 -64
- package/templates/product-viewer/node_modules/.vite/deps/_metadata.json +0 -8
- package/templates/product-viewer/node_modules/.vite/deps/package.json +0 -3
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync, statSync } from "node:fs";
|
|
3
|
+
export const MAX_MESHY_METADATA_BYTES = 1024 * 1024;
|
|
4
|
+
const SECRET_KEY = /(?:^|_)(?:api_?key|access_?token|refresh_?token|authorization|bearer|client_?secret|password|credentials?|cookie|private_?key|environment|env)(?:$|_)/i;
|
|
5
|
+
const SIGNED_QUERY_KEY = /^(?:x-amz-|x-goog-|signature$|sig$|token$|expires$|credential$|policy$|key-pair-id$)/i;
|
|
6
|
+
export function readMeshyMetadata(path) {
|
|
7
|
+
const size = statSync(path).size;
|
|
8
|
+
if (size > MAX_MESHY_METADATA_BYTES) {
|
|
9
|
+
throw new Error(`Meshy metadata exceeds ${MAX_MESHY_METADATA_BYTES} bytes: ${path}`);
|
|
10
|
+
}
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error(`Meshy metadata is not valid JSON: ${path}`);
|
|
17
|
+
}
|
|
18
|
+
const root = record(parsed, "Meshy metadata");
|
|
19
|
+
rejectCredentialFields(root, "metadata");
|
|
20
|
+
const task = optionalRecord(root.task, "metadata.task") ?? root;
|
|
21
|
+
const prompt = optionalString(first(task.prompt, root.prompt), "prompt");
|
|
22
|
+
const settingsValue = first(task.settings, task.parameters, root.settings, root.parameters);
|
|
23
|
+
const settings = settingsValue === undefined ? undefined : sanitizeRecord(record(settingsValue, "settings"), 0);
|
|
24
|
+
return compact({
|
|
25
|
+
providerCli: optionalString(first(root.providerCli, root.provider_cli, root.cliVersion, root.cli_version), "providerCli"),
|
|
26
|
+
taskId: optionalString(first(task.taskId, task.task_id, task.id, root.taskId, root.task_id), "taskId"),
|
|
27
|
+
parentTaskIds: stringList(first(task.parentTaskIds, task.parent_task_ids, task.parentTaskId, task.parent_task_id), "parentTaskIds"),
|
|
28
|
+
operation: optionalString(first(task.operation, task.type, root.operation, root.type), "operation"),
|
|
29
|
+
promptHash: prompt ? `sha256-${createHash("sha256").update(prompt).digest("hex")}` : undefined,
|
|
30
|
+
model: optionalString(first(task.model, task.modelVersion, task.model_version, root.model), "model"),
|
|
31
|
+
settings,
|
|
32
|
+
createdAt: isoString(first(task.createdAt, task.created_at, root.createdAt, root.created_at), "createdAt"),
|
|
33
|
+
finishedAt: isoString(first(task.finishedAt, task.finished_at, task.completedAt, task.completed_at, root.finishedAt, root.finished_at), "finishedAt"),
|
|
34
|
+
consumedCredits: nonNegativeNumber(first(task.consumedCredits, task.consumed_credits, task.credits, root.consumedCredits, root.consumed_credits), "consumedCredits")
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function validateMeshyEvidenceJson(path) {
|
|
38
|
+
const size = statSync(path).size;
|
|
39
|
+
if (size > MAX_MESHY_METADATA_BYTES)
|
|
40
|
+
throw new Error(`Meshy rights evidence exceeds ${MAX_MESHY_METADATA_BYTES} bytes: ${path}`);
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
throw new Error(`Meshy rights evidence is not valid JSON: ${path}`);
|
|
47
|
+
}
|
|
48
|
+
const value = record(parsed, "Meshy rights evidence");
|
|
49
|
+
if (Object.keys(value).length === 0)
|
|
50
|
+
throw new Error("Meshy rights evidence must be a non-empty JSON object.");
|
|
51
|
+
rejectCredentialFields(value, "rights evidence");
|
|
52
|
+
const licenseName = boundedRightsString(value.licenseName, "licenseName", 512);
|
|
53
|
+
const licenseUrl = rightsHttpsUrl(first(value.termsUrl, value.licenseUrl), "termsUrl/licenseUrl");
|
|
54
|
+
const licenseRaw = boundedRightsString(first(value.rightsBasis, value.licenseRaw), "rightsBasis/licenseRaw", 4096);
|
|
55
|
+
return compact({ licenseName, licenseUrl, licenseRaw });
|
|
56
|
+
}
|
|
57
|
+
export function stripSignedUrl(value) {
|
|
58
|
+
try {
|
|
59
|
+
const url = new URL(value);
|
|
60
|
+
if ([...url.searchParams.keys()].some((key) => SIGNED_QUERY_KEY.test(key)))
|
|
61
|
+
url.search = "";
|
|
62
|
+
return url.toString();
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function rejectCredentialFields(value, path) {
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
value.forEach((item, index) => rejectCredentialFields(item, `${path}[${index}]`));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!value || typeof value !== "object")
|
|
74
|
+
return;
|
|
75
|
+
for (const [key, child] of Object.entries(value)) {
|
|
76
|
+
const normalized = key.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[- ]/g, "_");
|
|
77
|
+
if (SECRET_KEY.test(normalized))
|
|
78
|
+
throw new Error(`Meshy input contains forbidden credential field at ${path}.${key}.`);
|
|
79
|
+
rejectCredentialFields(child, `${path}.${key}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function sanitizeRecord(value, depth) {
|
|
83
|
+
if (depth > 4)
|
|
84
|
+
throw new Error("Meshy settings exceed the maximum nesting depth.");
|
|
85
|
+
if (Object.keys(value).length > 100)
|
|
86
|
+
throw new Error("Meshy settings contain too many fields.");
|
|
87
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, sanitizeValue(child, depth + 1)]));
|
|
88
|
+
}
|
|
89
|
+
function sanitizeValue(value, depth) {
|
|
90
|
+
if (value === null || typeof value === "boolean" || typeof value === "number")
|
|
91
|
+
return value;
|
|
92
|
+
if (typeof value === "string") {
|
|
93
|
+
if (value.length > 4096)
|
|
94
|
+
throw new Error("Meshy metadata contains an unexpectedly long string.");
|
|
95
|
+
return stripSignedUrl(value);
|
|
96
|
+
}
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
if (value.length > 100)
|
|
99
|
+
throw new Error("Meshy metadata contains an unexpectedly large array.");
|
|
100
|
+
return value.map((entry) => sanitizeValue(entry, depth));
|
|
101
|
+
}
|
|
102
|
+
return sanitizeRecord(record(value, "settings value"), depth);
|
|
103
|
+
}
|
|
104
|
+
function record(value, label) {
|
|
105
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
106
|
+
throw new Error(`${label} must be a JSON object.`);
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
function optionalRecord(value, label) { return value === undefined ? undefined : record(value, label); }
|
|
110
|
+
function first(...values) { return values.find((value) => value !== undefined && value !== null); }
|
|
111
|
+
function optionalString(value, label) {
|
|
112
|
+
if (value === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
if (typeof value !== "string" || value.trim() === "" || value.length > 4096)
|
|
115
|
+
throw new Error(`Meshy metadata field ${label} must be a non-empty bounded string.`);
|
|
116
|
+
return stripSignedUrl(value.trim());
|
|
117
|
+
}
|
|
118
|
+
function boundedRightsString(value, label, maximumLength) {
|
|
119
|
+
if (value === undefined || value === null)
|
|
120
|
+
return undefined;
|
|
121
|
+
if (typeof value !== "string" || value.trim() === "" || value.length > maximumLength) {
|
|
122
|
+
throw new Error(`Meshy rights evidence field ${label} must be a non-empty string of at most ${maximumLength} characters.`);
|
|
123
|
+
}
|
|
124
|
+
return value.trim();
|
|
125
|
+
}
|
|
126
|
+
function rightsHttpsUrl(value, label) {
|
|
127
|
+
const text = boundedRightsString(value, label, 2048);
|
|
128
|
+
if (!text)
|
|
129
|
+
return undefined;
|
|
130
|
+
let url;
|
|
131
|
+
try {
|
|
132
|
+
url = new URL(text);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
throw new Error(`Meshy rights evidence field ${label} must be an HTTPS URL.`);
|
|
136
|
+
}
|
|
137
|
+
if (url.protocol !== "https:" || url.username || url.password) {
|
|
138
|
+
throw new Error(`Meshy rights evidence field ${label} must be an HTTPS URL without embedded credentials.`);
|
|
139
|
+
}
|
|
140
|
+
return stripSignedUrl(url.toString());
|
|
141
|
+
}
|
|
142
|
+
function isoString(value, label) {
|
|
143
|
+
if (value === undefined)
|
|
144
|
+
return undefined;
|
|
145
|
+
if (typeof value === "number") {
|
|
146
|
+
if (!Number.isFinite(value) || value < 0)
|
|
147
|
+
throw new Error(`Meshy metadata field ${label} must be an ISO-8601 timestamp or non-negative epoch milliseconds.`);
|
|
148
|
+
const timestamp = new Date(value);
|
|
149
|
+
if (Number.isNaN(timestamp.getTime()))
|
|
150
|
+
throw new Error(`Meshy metadata field ${label} must be an ISO-8601 timestamp or non-negative epoch milliseconds.`);
|
|
151
|
+
return timestamp.toISOString();
|
|
152
|
+
}
|
|
153
|
+
const text = optionalString(value, label);
|
|
154
|
+
if (!text)
|
|
155
|
+
return undefined;
|
|
156
|
+
if (Number.isNaN(Date.parse(text)))
|
|
157
|
+
throw new Error(`Meshy metadata field ${label} must be an ISO-8601 timestamp or non-negative epoch milliseconds.`);
|
|
158
|
+
return text;
|
|
159
|
+
}
|
|
160
|
+
function nonNegativeNumber(value, label) {
|
|
161
|
+
if (value === undefined)
|
|
162
|
+
return undefined;
|
|
163
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
164
|
+
throw new Error(`Meshy metadata field ${label} must be a non-negative number.`);
|
|
165
|
+
return value;
|
|
166
|
+
}
|
|
167
|
+
function stringList(value, label) {
|
|
168
|
+
if (value === undefined)
|
|
169
|
+
return undefined;
|
|
170
|
+
const values = Array.isArray(value) ? value : [value];
|
|
171
|
+
if (values.length > 100)
|
|
172
|
+
throw new Error(`Meshy metadata field ${label} contains too many values.`);
|
|
173
|
+
return values.map((entry) => optionalString(entry, label));
|
|
174
|
+
}
|
|
175
|
+
function compact(value) { return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined)); }
|
|
176
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AuraCliGeneratedAssetProvenance } from "../asset-core-types.js";
|
|
2
|
+
import type { SanitizedMeshyMetadata } from "./metadata.js";
|
|
3
|
+
export declare function createMeshyProvenance(projectDir: string, metadataPath: string, rightsPath: string, metadata: SanitizedMeshyMetadata): AuraCliGeneratedAssetProvenance;
|
|
4
|
+
//# sourceMappingURL=provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/provenance.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAE5D,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,+BAA+B,CAgBrK"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { relative } from "node:path";
|
|
3
|
+
export function createMeshyProvenance(projectDir, metadataPath, rightsPath, metadata) {
|
|
4
|
+
return {
|
|
5
|
+
provider: "meshy",
|
|
6
|
+
providerCli: metadata.providerCli ?? "@meshy-ai/cli@0.2.0",
|
|
7
|
+
...(metadata.taskId ? { taskId: metadata.taskId } : {}),
|
|
8
|
+
...(metadata.parentTaskIds?.length ? { parentTaskIds: metadata.parentTaskIds } : {}),
|
|
9
|
+
...(metadata.operation ? { operation: metadata.operation } : {}),
|
|
10
|
+
...(metadata.promptHash ? { promptHash: metadata.promptHash } : {}),
|
|
11
|
+
...(metadata.model ? { model: metadata.model } : {}),
|
|
12
|
+
...(metadata.settings ? { settings: metadata.settings } : {}),
|
|
13
|
+
...(metadata.createdAt ? { createdAt: metadata.createdAt } : {}),
|
|
14
|
+
...(metadata.finishedAt ? { finishedAt: metadata.finishedAt } : {}),
|
|
15
|
+
...(metadata.consumedCredits !== undefined ? { consumedCredits: metadata.consumedCredits } : {}),
|
|
16
|
+
localMetadata: normalized(relative(realpathSync(projectDir), metadataPath)),
|
|
17
|
+
rightsEvidence: normalized(relative(realpathSync(projectDir), rightsPath))
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function normalized(path) { return path.replaceAll("\\", "/"); }
|
|
21
|
+
//# sourceMappingURL=provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/provenance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAIrC,MAAM,UAAU,qBAAqB,CAAC,UAAkB,EAAE,YAAoB,EAAE,UAAkB,EAAE,QAAgC;IAClI,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,qBAAqB;QAC1D,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpF,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnE,GAAG,CAAC,QAAQ,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChG,aAAa,EAAE,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;QAC3E,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;KAC3E,CAAC;AACJ,CAAC;AACD,SAAS,UAAU,CAAC,IAAY,IAAY,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AuraCliRenderedProbe } from "../asset-core-types.js";
|
|
2
|
+
export declare const MAX_MESHY_THUMBNAIL_BYTES: number;
|
|
3
|
+
export interface RetainedMeshyThumbnail {
|
|
4
|
+
readonly sourceFile: string;
|
|
5
|
+
readonly outputPath: string;
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly sha256: string;
|
|
8
|
+
readonly renderedProbe: AuraCliRenderedProbe;
|
|
9
|
+
}
|
|
10
|
+
export declare function findMeshyThumbnail(inputDir: string, requested: string | undefined): string | undefined;
|
|
11
|
+
export declare function retainMeshyThumbnail(options: {
|
|
12
|
+
readonly projectDir: string;
|
|
13
|
+
readonly inputDir: string;
|
|
14
|
+
readonly requested?: string;
|
|
15
|
+
readonly assetName: string;
|
|
16
|
+
readonly outputDir: string;
|
|
17
|
+
readonly publicPath: string;
|
|
18
|
+
}): RetainedMeshyThumbnail | undefined;
|
|
19
|
+
//# sourceMappingURL=thumbnail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thumbnail.d.ts","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/thumbnail.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAKnE,eAAO,MAAM,yBAAyB,QAAmB,CAAC;AAE1D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,oBAAoB,CAAC;CAC9C;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAOtG;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,GAAG,sBAAsB,GAAG,SAAS,CA4BrC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { extname, join, resolve } from "node:path";
|
|
4
|
+
import { resolveConfinedPath } from "./validation.js";
|
|
5
|
+
const THUMBNAIL_NAMES = ["thumbnail", "thumb", "preview", "render"];
|
|
6
|
+
const THUMBNAIL_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".webp"]);
|
|
7
|
+
export const MAX_MESHY_THUMBNAIL_BYTES = 20 * 1024 * 1024;
|
|
8
|
+
export function findMeshyThumbnail(inputDir, requested) {
|
|
9
|
+
if (requested)
|
|
10
|
+
return resolveConfinedPath(inputDir, requested, "thumbnail");
|
|
11
|
+
const matches = readdirSync(inputDir, { withFileTypes: true })
|
|
12
|
+
.filter((entry) => entry.isFile() && THUMBNAIL_EXTENSIONS.has(extname(entry.name).toLowerCase()) && THUMBNAIL_NAMES.includes(entry.name.replace(/\.[^.]+$/, "").toLowerCase()))
|
|
13
|
+
.map((entry) => resolve(inputDir, entry.name));
|
|
14
|
+
if (matches.length > 1)
|
|
15
|
+
throw new Error("Meshy output contains multiple candidate thumbnails. Select exactly one with --thumbnail <relative-image>.");
|
|
16
|
+
return matches[0];
|
|
17
|
+
}
|
|
18
|
+
export function retainMeshyThumbnail(options) {
|
|
19
|
+
const source = findMeshyThumbnail(options.inputDir, options.requested);
|
|
20
|
+
if (!source)
|
|
21
|
+
return undefined;
|
|
22
|
+
const stat = statSync(source);
|
|
23
|
+
const extension = extname(source).toLowerCase();
|
|
24
|
+
if (!stat.isFile() || !THUMBNAIL_EXTENSIONS.has(extension))
|
|
25
|
+
throw new Error("Meshy thumbnail must be a PNG, JPEG, or WebP regular file.");
|
|
26
|
+
if (stat.size === 0 || stat.size > MAX_MESHY_THUMBNAIL_BYTES)
|
|
27
|
+
throw new Error("Meshy thumbnail must be non-empty and no larger than " + MAX_MESHY_THUMBNAIL_BYTES + " bytes.");
|
|
28
|
+
const bytes = readFileSync(source);
|
|
29
|
+
validateImageSignature(bytes, extension);
|
|
30
|
+
const hash = createHash("sha256").update(bytes).digest("hex");
|
|
31
|
+
const fileName = options.assetName + ".meshy-candidate." + hash.slice(0, 8) + extension;
|
|
32
|
+
const outputPath = join(options.outputDir, fileName).replaceAll("\\", "/");
|
|
33
|
+
const destination = resolve(options.projectDir, outputPath);
|
|
34
|
+
mkdirSync(resolve(options.projectDir, options.outputDir), { recursive: true });
|
|
35
|
+
if (!existsSync(destination))
|
|
36
|
+
copyFileSync(source, destination);
|
|
37
|
+
const url = options.publicPath.replace(/\/?$/, "/") + fileName;
|
|
38
|
+
return {
|
|
39
|
+
sourceFile: source,
|
|
40
|
+
outputPath,
|
|
41
|
+
url,
|
|
42
|
+
sha256: "sha256-" + hash,
|
|
43
|
+
renderedProbe: {
|
|
44
|
+
url,
|
|
45
|
+
kind: "manual-inspection",
|
|
46
|
+
sha256: "sha256-" + hash,
|
|
47
|
+
checkedAt: new Date().toISOString()
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function validateImageSignature(bytes, extension) {
|
|
52
|
+
const png = bytes.length >= 8 && bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]));
|
|
53
|
+
const jpeg = bytes.length >= 3 && bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff;
|
|
54
|
+
const webp = bytes.length >= 12 && bytes.toString("ascii", 0, 4) === "RIFF" && bytes.toString("ascii", 8, 12) === "WEBP";
|
|
55
|
+
const valid = extension === ".png" ? png : extension === ".webp" ? webp : jpeg;
|
|
56
|
+
if (!valid)
|
|
57
|
+
throw new Error("Meshy thumbnail content does not match its image extension.");
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=thumbnail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thumbnail.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/thumbnail.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const MAX_MESHY_GLB_BYTES: number;
|
|
2
|
+
export declare function resolveConfinedPath(allowedRoot: string, candidate: string, label: string): string;
|
|
3
|
+
export declare function selectMeshyGlb(inputDir: string, file: string | undefined): string;
|
|
4
|
+
export declare function validateMeshyGlb(path: string): void;
|
|
5
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/validation.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB,QAAoB,CAAC;AAErD,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAgBjG;AACD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAcjF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAWnD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { closeSync, existsSync, openSync, readSync, realpathSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { extname, isAbsolute, relative, resolve } from "node:path";
|
|
3
|
+
export const MAX_MESHY_GLB_BYTES = 100 * 1024 * 1024;
|
|
4
|
+
export function resolveConfinedPath(allowedRoot, candidate, label) {
|
|
5
|
+
if (!existsSync(allowedRoot))
|
|
6
|
+
throw new Error(`Meshy allowed root does not exist: ${allowedRoot}`);
|
|
7
|
+
const lexicalRoot = resolve(allowedRoot);
|
|
8
|
+
const target = resolve(isAbsolute(candidate) ? candidate : resolve(lexicalRoot, candidate));
|
|
9
|
+
const lexicalRelative = relative(lexicalRoot, target);
|
|
10
|
+
if (lexicalRelative === ".." || lexicalRelative.startsWith("../") || isAbsolute(lexicalRelative)) {
|
|
11
|
+
throw new Error(`Meshy ${label} escapes the allowed root: ${candidate}`);
|
|
12
|
+
}
|
|
13
|
+
if (!existsSync(target))
|
|
14
|
+
throw new Error(`Meshy ${label} does not exist: ${candidate}`);
|
|
15
|
+
const root = realpathSync(lexicalRoot);
|
|
16
|
+
const realTarget = realpathSync(target);
|
|
17
|
+
const realRelative = relative(root, realTarget);
|
|
18
|
+
if (realRelative === ".." || realRelative.startsWith("../") || isAbsolute(realRelative)) {
|
|
19
|
+
throw new Error(`Meshy ${label} escapes the allowed root through a symbolic link: ${candidate}`);
|
|
20
|
+
}
|
|
21
|
+
return realTarget;
|
|
22
|
+
}
|
|
23
|
+
export function selectMeshyGlb(inputDir, file) {
|
|
24
|
+
if (!statSync(inputDir).isDirectory())
|
|
25
|
+
throw new Error(`Meshy input must be a directory: ${inputDir}`);
|
|
26
|
+
if (file) {
|
|
27
|
+
const selected = resolveConfinedPath(inputDir, file, "selected GLB");
|
|
28
|
+
validateMeshyGlb(selected);
|
|
29
|
+
return selected;
|
|
30
|
+
}
|
|
31
|
+
const glbs = readdirSync(inputDir, { withFileTypes: true })
|
|
32
|
+
.filter((entry) => entry.isFile() && extname(entry.name).toLowerCase() === ".glb")
|
|
33
|
+
.map((entry) => resolve(inputDir, entry.name));
|
|
34
|
+
if (glbs.length === 0)
|
|
35
|
+
throw new Error("Meshy output contains no GLB. Supply a completed local output directory.");
|
|
36
|
+
if (glbs.length > 1)
|
|
37
|
+
throw new Error("Meshy output contains multiple GLBs. Select exactly one with --file <relative.glb>.");
|
|
38
|
+
validateMeshyGlb(glbs[0]);
|
|
39
|
+
return glbs[0];
|
|
40
|
+
}
|
|
41
|
+
export function validateMeshyGlb(path) {
|
|
42
|
+
const stat = statSync(path);
|
|
43
|
+
if (!stat.isFile())
|
|
44
|
+
throw new Error(`Meshy GLB is not a regular file: ${path}`);
|
|
45
|
+
if (extname(path).toLowerCase() !== ".glb")
|
|
46
|
+
throw new Error(`Meshy selected file must use the .glb extension: ${path}`);
|
|
47
|
+
if (stat.size < 20)
|
|
48
|
+
throw new Error(`Meshy GLB is too small to be valid: ${path}`);
|
|
49
|
+
if (stat.size > MAX_MESHY_GLB_BYTES)
|
|
50
|
+
throw new Error(`Meshy GLB exceeds ${MAX_MESHY_GLB_BYTES} bytes: ${path}`);
|
|
51
|
+
const bytes = Buffer.alloc(12);
|
|
52
|
+
const handle = openSync(path, "r");
|
|
53
|
+
try {
|
|
54
|
+
readSync(handle, bytes, 0, 12, 0);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
closeSync(handle);
|
|
58
|
+
}
|
|
59
|
+
if (bytes.toString("utf8", 0, 4) !== "glTF")
|
|
60
|
+
throw new Error(`Meshy GLB has invalid magic bytes: ${path}`);
|
|
61
|
+
if (bytes.readUInt32LE(8) !== stat.size)
|
|
62
|
+
throw new Error(`Meshy GLB declared length does not match its file size: ${path}`);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../../../packages/aura3d-cli/src/meshy/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,7 +42,7 @@ export function createA3DProject(options) {
|
|
|
42
42
|
const dependencies = { ...(packageJson.dependencies ?? {}) };
|
|
43
43
|
const auraDependencies = Object.keys(dependencies).filter((name) => name.startsWith("@aura3d/"));
|
|
44
44
|
if (auraDependencies.length === 0) {
|
|
45
|
-
dependencies["@aura3d/engine"] = options.packageVersion ?? "2.0.
|
|
45
|
+
dependencies["@aura3d/engine"] = options.packageVersion ?? "2.0.4";
|
|
46
46
|
}
|
|
47
47
|
else if (options.packageVersion) {
|
|
48
48
|
for (const dependency of auraDependencies)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcase-spec-game-geometry-extractor.d.ts","sourceRoot":"","sources":["../../../../packages/create-aura3d/src/showcase-spec-game-geometry-extractor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,2BAA2B,EAE3B,oCAAoC,EAEpC,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAUlC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,yBAAyB,CAAC,CAAC,CAAC,GAAG,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"showcase-spec-game-geometry-extractor.d.ts","sourceRoot":"","sources":["../../../../packages/create-aura3d/src/showcase-spec-game-geometry-extractor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,2BAA2B,EAE3B,oCAAoC,EAEpC,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAUlC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,yBAAyB,CAAC,CAAC,CAAC,GAAG,yBAAyB,CAAC;AA+MnG,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,cAAmB,GAC3B,wBAAwB,CAAC,2BAA2B,CAAC,CAavD;AAED,8FAA8F;AAC9F,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AAED,sFAAsF;AACtF,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,cAAmB,GAC3B,SAAS;IACV,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;CAC9C,EAAE,CAcF;AAgKD,wBAAgB,4CAA4C,CAC1D,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,cAAmB,GAC3B,wBAAwB,CAAC,oCAAoC,CAAC,CAmGhE"}
|
|
@@ -49,6 +49,7 @@ const PLATFORMER_MAX_UPWARD_TRAVERSAL_STEP = 2.5;
|
|
|
49
49
|
const PLATFORMER_MAX_RETAINED_MESH_SURFACES = 16;
|
|
50
50
|
const PLATFORMER_MAX_DECLARED_RETAINED_MESH_SURFACES = 256;
|
|
51
51
|
const PLATFORMER_AUTHORED_WORLD_GENERATOR = "Aura3D Skyline Level 1 deterministic GLB compositor";
|
|
52
|
+
const RACING_AUTHORED_WORLD_GENERATOR = "Aura3D deterministic Formula Circuit builder";
|
|
52
53
|
const PLATFORMER_DECORATIVE_PATTERN = /\b(column|pillar|tower|decor|background|backdrop)\b/i;
|
|
53
54
|
/**
|
|
54
55
|
* Memoizes racing extraction per asset. Ranking a replacement candidate list calls
|
|
@@ -109,14 +110,34 @@ function computeRacingTrackTopology(assetId, options, projectDir) {
|
|
|
109
110
|
if (roadSurface.triangleCount === 0) {
|
|
110
111
|
return failure([`asset-extraction:racing-road-triangles-unreadable:${assetId}`], [`Road primitives in ${assetId} have no readable indexed triangles, so road containment cannot be proven.`]);
|
|
111
112
|
}
|
|
112
|
-
//
|
|
113
|
-
//
|
|
113
|
+
// A deterministic authored circuit may carry its exact generator-owned centreline
|
|
114
|
+
// in the hash-bound GLB. It is accepted only after every point and connecting
|
|
115
|
+
// segment are proven to remain on the extracted asphalt triangles. This preserves
|
|
116
|
+
// an intentional start/finish seam; a radial loop has no semantic seam and can
|
|
117
|
+
// otherwise rotate a certified opening straight into a corner.
|
|
118
|
+
const authoredCenterline = geometry.value.racingAuthoring?.roadCenterline ?? [];
|
|
119
|
+
const authoredUsable = authoredCenterline.length >= 8
|
|
120
|
+
&& authoredCenterline.every((point) => roadSurface.contains(point.x, point.z))
|
|
121
|
+
&& authoredCenterline.every((point, index) => segmentStaysOnRoad(point, authoredCenterline[(index + 1) % authoredCenterline.length], roadSurface))
|
|
122
|
+
&& measureLeadingStraightLength(authoredCenterline) + 1e-3 >= (geometry.value.racingAuthoring?.minimumStartStraightLength ?? 0)
|
|
123
|
+
&& isPlausibleRacingLoop(authoredCenterline);
|
|
124
|
+
// Radial sweep remains the default: it is cheap and exact for star-convex
|
|
125
|
+
// third-party circuits. Fall back to a rasterized loop trace for circuits that
|
|
126
|
+
// double back on themselves.
|
|
114
127
|
const sweptCenterline = createRoadCenterline(roadPrimitives, roadBounds, roadSurface);
|
|
115
128
|
const sweptUsable = sweptCenterline.length >= 8
|
|
116
129
|
&& measureOffRoadRatio(sweptCenterline, roadSurface) <= RACING_MAX_OFF_ROAD_RATIO
|
|
117
130
|
&& isPlausibleRacingLoop(sweptCenterline);
|
|
118
|
-
const centerline =
|
|
119
|
-
|
|
131
|
+
const centerline = authoredUsable
|
|
132
|
+
? authoredCenterline
|
|
133
|
+
: sweptUsable
|
|
134
|
+
? sweptCenterline
|
|
135
|
+
: traceRoadLoop(roadPrimitives, roadSurface);
|
|
136
|
+
const centerlineMethod = authoredUsable
|
|
137
|
+
? "asset-authored-mesh-validated"
|
|
138
|
+
: sweptUsable
|
|
139
|
+
? "radial-band-sweep"
|
|
140
|
+
: "raster-loop-trace";
|
|
120
141
|
if (centerline.length < 8) {
|
|
121
142
|
return failure([`asset-extraction:racing-road-centerline-ambiguous:${assetId}`], [`Road mesh in ${assetId} produced only ${centerline.length} reliable centerline samples.`]);
|
|
122
143
|
}
|
|
@@ -511,6 +532,9 @@ function loadAssetGeometry(assetId, projectDir) {
|
|
|
511
532
|
asset,
|
|
512
533
|
primitives,
|
|
513
534
|
bounds: boundsForPrimitives(primitives),
|
|
535
|
+
...(readRacingAuthoringMetadata(document.value) ? {
|
|
536
|
+
racingAuthoring: readRacingAuthoringMetadata(document.value)
|
|
537
|
+
} : {}),
|
|
514
538
|
...(readPlatformerAuthoringMetadata(document.value) ? {
|
|
515
539
|
platformerAuthoring: readPlatformerAuthoringMetadata(document.value)
|
|
516
540
|
} : {})
|
|
@@ -518,6 +542,59 @@ function loadAssetGeometry(assetId, projectDir) {
|
|
|
518
542
|
reasons: [`read ${primitives.length} GLB primitive(s) from ${assetPath}`]
|
|
519
543
|
};
|
|
520
544
|
}
|
|
545
|
+
function readRacingAuthoringMetadata(document) {
|
|
546
|
+
if (document.json.asset?.generator !== RACING_AUTHORED_WORLD_GENERATOR)
|
|
547
|
+
return undefined;
|
|
548
|
+
const value = document.json.asset.extras?.racingGeometry;
|
|
549
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
550
|
+
return undefined;
|
|
551
|
+
const metadata = value;
|
|
552
|
+
const minimumStartStraightLength = metadata.minimumStartStraightLength;
|
|
553
|
+
const roadWidth = metadata.roadWidth;
|
|
554
|
+
const rawCenterline = metadata.roadCenterline;
|
|
555
|
+
if (typeof minimumStartStraightLength !== "number" || !Number.isFinite(minimumStartStraightLength) ||
|
|
556
|
+
minimumStartStraightLength < 6.75 ||
|
|
557
|
+
typeof roadWidth !== "number" || !Number.isFinite(roadWidth) || roadWidth <= 0 ||
|
|
558
|
+
!Array.isArray(rawCenterline) || rawCenterline.length < 8)
|
|
559
|
+
return undefined;
|
|
560
|
+
const roadCenterline = [];
|
|
561
|
+
for (const rawPoint of rawCenterline) {
|
|
562
|
+
if (!rawPoint || typeof rawPoint !== "object" || Array.isArray(rawPoint))
|
|
563
|
+
return undefined;
|
|
564
|
+
const point = rawPoint;
|
|
565
|
+
if (typeof point.x !== "number" || !Number.isFinite(point.x) ||
|
|
566
|
+
typeof point.z !== "number" || !Number.isFinite(point.z) ||
|
|
567
|
+
typeof point.width !== "number" || !Number.isFinite(point.width) ||
|
|
568
|
+
Math.abs(point.width - roadWidth) > 1e-6)
|
|
569
|
+
return undefined;
|
|
570
|
+
roadCenterline.push({ x: round3(point.x), z: round3(point.z), width: round3(point.width) });
|
|
571
|
+
}
|
|
572
|
+
if (measureLeadingStraightLength(roadCenterline) + 1e-3 < minimumStartStraightLength)
|
|
573
|
+
return undefined;
|
|
574
|
+
return { roadCenterline, minimumStartStraightLength: round3(minimumStartStraightLength) };
|
|
575
|
+
}
|
|
576
|
+
function measureLeadingStraightLength(points) {
|
|
577
|
+
if (points.length < 2)
|
|
578
|
+
return 0;
|
|
579
|
+
const first = points[0];
|
|
580
|
+
const second = points[1];
|
|
581
|
+
const heading = Math.atan2(second.z - first.z, second.x - first.x);
|
|
582
|
+
let length = 0;
|
|
583
|
+
for (let index = 0; index < points.length; index += 1) {
|
|
584
|
+
const from = points[index];
|
|
585
|
+
const to = points[(index + 1) % points.length];
|
|
586
|
+
const segmentHeading = Math.atan2(to.z - from.z, to.x - from.x);
|
|
587
|
+
let delta = segmentHeading - heading;
|
|
588
|
+
while (delta > Math.PI)
|
|
589
|
+
delta -= Math.PI * 2;
|
|
590
|
+
while (delta < -Math.PI)
|
|
591
|
+
delta += Math.PI * 2;
|
|
592
|
+
if (Math.abs(delta) > 1e-4)
|
|
593
|
+
break;
|
|
594
|
+
length += Math.hypot(to.x - from.x, to.z - from.z);
|
|
595
|
+
}
|
|
596
|
+
return round3(length);
|
|
597
|
+
}
|
|
521
598
|
function loadGltfDocument(absolutePath) {
|
|
522
599
|
const buffer = readFileSync(absolutePath);
|
|
523
600
|
if (buffer.length < 20)
|
|
@@ -1732,6 +1809,8 @@ function averageRoadWidth(size) {
|
|
|
1732
1809
|
return round3(Math.max(0.12, Math.min(size[0], size[2]) * 0.08));
|
|
1733
1810
|
}
|
|
1734
1811
|
function measureClosedRouteLength(points) {
|
|
1812
|
+
if (points.length < 2)
|
|
1813
|
+
return 0;
|
|
1735
1814
|
let total = 0;
|
|
1736
1815
|
for (let index = 1; index < points.length; index += 1) {
|
|
1737
1816
|
const previous = points[index - 1];
|
|
@@ -1739,6 +1818,9 @@ function measureClosedRouteLength(points) {
|
|
|
1739
1818
|
if (previous && current)
|
|
1740
1819
|
total += Math.hypot(current.x - previous.x, current.y - previous.y);
|
|
1741
1820
|
}
|
|
1821
|
+
const first = points[0];
|
|
1822
|
+
const last = points[points.length - 1];
|
|
1823
|
+
total += Math.hypot(first.x - last.x, first.y - last.y);
|
|
1742
1824
|
return total;
|
|
1743
1825
|
}
|
|
1744
1826
|
function decimateVertices(vertices, maxCount) {
|