"use strict"; const fs = require("fs"); const path = require("path"); const VEHICLE_IDS = [ "car_a01_002", "car_a02_002", "car_a03_001", "truck_a01_001", "truck_a02_001", "truck_a03_001", ]; const LIBRARY_ROOT = path.resolve(__dirname, "..", "..", "assets", "models", "custom", "lowpoly_cars"); const TEXTURE_NAME = "color_512x512.jpg"; const REVERSED_MODEL_IDS = new Set(["truck_a03_001"]); function writePreviewVehicleLibrary(outDir, fileStem) { const textureOutput = `${fileStem}-vehicle-texture.jpg`; fs.mkdirSync(outDir, { recursive: true }); fs.copyFileSync(path.join(LIBRARY_ROOT, "textures", TEXTURE_NAME), path.join(outDir, textureOutput)); return VEHICLE_IDS.map((id) => { const modelName = `${fileStem}-vehicle-${id}.gltf`; const binName = `${fileStem}-vehicle-${id}.bin`; const sourceDir = path.join(LIBRARY_ROOT, id); const gltf = JSON.parse(fs.readFileSync(path.join(sourceDir, "model.gltf"), "utf8")); for (const image of gltf.images || []) image.uri = textureOutput; for (const buffer of gltf.buffers || []) buffer.uri = binName; if (REVERSED_MODEL_IDS.has(id)) { // The source's longitudinal PCA axis points rearward for this truck. for (const node of gltf.nodes || []) node.rotation = [0, 1, 0, 0]; } for (const material of gltf.materials || []) { const pbr = material.pbrMetallicRoughness || (material.pbrMetallicRoughness = {}); // Match the Cesium foliage profile: lift albedo first, then use the // texture itself as a modest shadow-side floor. pbr.baseColorFactor = [2.1, 2.1, 2.1, 1]; if (pbr.baseColorTexture) { material.emissiveTexture = { ...pbr.baseColorTexture }; material.emissiveFactor = [0.25, 0.25, 0.25]; } } fs.writeFileSync(path.join(outDir, modelName), `${JSON.stringify(gltf, null, 2)}\n`); fs.copyFileSync(path.join(sourceDir, "model.bin"), path.join(outDir, binName)); return modelName; }); } module.exports = { VEHICLE_IDS, REVERSED_MODEL_IDS, writePreviewVehicleLibrary };