import crypto from "node:crypto"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const resourceRoot = path.resolve(process.env.VDB_RESOURCE_ROOT ?? "/home/mes123456/resource-library/blender-web-vdb"); const converter = path.join(repoRoot, "build_vdb_tools", "vdb_to_nanovdb"); const generator = path.join(repoRoot, "build_vdb_tools", "vdb_fixture_generator"); const openVDBLicense = "/home/mes123456/working/build_oiio_deps/build/openvdb/src/external_openvdb/LICENSE"; const ccLicense = path.join(resourceRoot, "licenses", "CC-BY-4.0.txt"); function sha256(file) { return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex"); } function entry(id, relativePath, kind, license, origin, extra = {}) { const file = path.join(resourceRoot, relativePath); if (!fs.statSync(file).isFile()) throw new Error(`VDB_RESOURCE_MISSING: ${file}`); return { id, kind, path: relativePath, byteLength: fs.statSync(file).size, sha256: sha256(file), license, origin, ...extra }; } fs.mkdirSync(path.join(resourceRoot, "generated"), { recursive: true }); fs.mkdirSync(path.join(resourceRoot, "licenses"), { recursive: true }); fs.copyFileSync(openVDBLicense, path.join(resourceRoot, "licenses", "OpenVDB-Apache-2.0.txt")); if (!fs.existsSync(ccLicense)) throw new Error("VDB_RESOURCE_LICENSE_MISSING: CC-BY-4.0.txt"); const smoke = fs.readFileSync(path.join(resourceRoot, "generated", "generated-smoke.vdb")); fs.writeFileSync(path.join(resourceRoot, "generated", "generated-smoke-truncated.vdb"), smoke.subarray(0, 1024)); const generatedOrigin = "Generated locally by tools/vdb/vdb_fixture_generator.cc with OpenVDB 13.0.0; contains no third-party model data"; const officialOrigin = "OpenVDB official sample model repository"; const entries = [ entry("generated-smoke", "generated/generated-smoke.vdb", "SOURCE_VDB", "PROJECT_GENERATED_FIXTURE", generatedOrigin), entry("generated-level-set", "generated/generated-level-set.vdb", "SOURCE_VDB", "PROJECT_GENERATED_FIXTURE", generatedOrigin), entry("generated-large-bounds-sparse", "generated/generated-large-bounds-sparse.vdb", "SOURCE_VDB", "PROJECT_GENERATED_FIXTURE", generatedOrigin), entry("generated-smoke-truncated", "generated/generated-smoke-truncated.vdb", "MALFORMED_VDB", "PROJECT_GENERATED_FIXTURE", generatedOrigin, { expectedResult: "VDB_CONVERSION_FAILED" }), entry("official-sphere", "official/sphere.vdb", "SOURCE_VDB", "CC-BY-4.0", officialOrigin, { sourcePage: "https://www.openvdb.org/download/", sourceUrl: "https://media.githubusercontent.com/media/AcademySoftwareFoundation/openvdb-website/master/download/models/sphere.vdb", upstreamLfsSha256: "bb884a9a38354e47191c4ece4a11d1e051594a910fde56501cfc51ff52b171ab", attribution: "Academy Software Foundation OpenVDB sample models", }), entry("generated-smoke-nanovdb", "nanovdb/generated-smoke.nvdb", "NANOVDB_BUNDLE", "PROJECT_GENERATED_FIXTURE", "Derived from generated-smoke", { derivedFrom: "generated-smoke" }), entry("generated-level-set-nanovdb", "nanovdb/generated-level-set.nvdb", "NANOVDB_BUNDLE", "PROJECT_GENERATED_FIXTURE", "Derived from generated-level-set", { derivedFrom: "generated-level-set" }), entry("generated-large-bounds-sparse-nanovdb", "nanovdb/generated-large-bounds-sparse.nvdb", "NANOVDB_BUNDLE", "PROJECT_GENERATED_FIXTURE", "Derived from generated-large-bounds-sparse", { derivedFrom: "generated-large-bounds-sparse" }), entry("official-sphere-nanovdb", "nanovdb/official-sphere.nvdb", "NANOVDB_BUNDLE", "CC-BY-4.0", officialOrigin, { derivedFrom: "official-sphere" }), entry("generated-smoke-browser-manifest", "manifests/generated-smoke.nanovdb.json", "NANOVDB_MANIFEST", "PROJECT_GENERATED_FIXTURE", "Derived from generated-smoke conversion report", { derivedFrom: "generated-smoke-nanovdb" }), entry("generated-smoke-conversion-report", "reports/generated-smoke-conversion.json", "CONVERSION_REPORT", "PROJECT_GENERATED_FIXTURE", "Native OpenVDB to NanoVDB report", { derivedFrom: "generated-smoke" }), entry("generated-level-set-conversion-report", "reports/generated-level-set-conversion.json", "CONVERSION_REPORT", "PROJECT_GENERATED_FIXTURE", "Native OpenVDB to NanoVDB report", { derivedFrom: "generated-level-set" }), entry("generated-large-bounds-conversion-report", "reports/generated-large-bounds-sparse-conversion.json", "CONVERSION_REPORT", "PROJECT_GENERATED_FIXTURE", "Native OpenVDB to NanoVDB report", { derivedFrom: "generated-large-bounds-sparse" }), entry("official-sphere-conversion-report", "reports/official-sphere-conversion.json", "CONVERSION_REPORT", "CC-BY-4.0", officialOrigin, { derivedFrom: "official-sphere" }), ]; const manifest = { schemaVersion: 1, libraryId: "blender-web-vdb", resourceRoot, licenses: [ { id: "OpenVDB-Apache-2.0", path: "licenses/OpenVDB-Apache-2.0.txt", sha256: sha256(path.join(resourceRoot, "licenses", "OpenVDB-Apache-2.0.txt")) }, { id: "CC-BY-4.0", path: "licenses/CC-BY-4.0.txt", sha256: sha256(ccLicense) }, ], toolchain: { openVDBVersion: "13.0.0", nanoVDBVersion: "32.9.0", converterPath: converter, converterSha256: sha256(converter), generatorPath: generator, generatorSha256: sha256(generator), }, entries, }; fs.writeFileSync(path.join(resourceRoot, "manifest.json"), `${JSON.stringify(manifest, null, 2)}\n`); fs.writeFileSync(path.join(resourceRoot, "SOURCE.md"), `# Blender Web VDB Resource Library\n\n` + `Generated fixtures are produced locally by \`tools/vdb/vdb_fixture_generator.cc\` and contain no third-party model data.\n\n` + `\`official/sphere.vdb\` is from the OpenVDB official sample model repository, is covered by CC-BY-4.0, and was verified against Git LFS SHA-256 \`bb884a9a38354e47191c4ece4a11d1e051594a910fde56501cfc51ff52b171ab\`.\n\n` + `Source page: https://www.openvdb.org/download/\n`); process.stdout.write(`vdb-resource-catalog-ok entries=${entries.length} root=${resourceRoot}\n`);