71 lines
2.9 KiB
JavaScript
71 lines
2.9 KiB
JavaScript
"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 V2X_LIBRARY_ROOT = path.resolve(__dirname, "..", "..", "assets", "models", "v2x-vehicles");
|
|
const TEXTURE_NAME = "color_512x512.jpg";
|
|
const REVERSED_MODEL_IDS = new Set(["truck_a03_001"]);
|
|
// These are the dashboard's published vehicle assets. OBU rendering uses
|
|
// 11.glb in CrossCars/index.vue; target vehicles use `${type}${subType}.glb`.
|
|
const V2X_VEHICLE_MODEL_NAMES = ["11.glb", "12.glb", "13.glb", "14.glb", "15.glb", "16.glb", "17.glb", "31.glb", "221.glb", "222.glb"];
|
|
|
|
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;
|
|
});
|
|
}
|
|
|
|
function writePreviewV2xVehicleLibrary(outDir) {
|
|
const targetDir = path.join(outDir, "v2x-vehicles");
|
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
for (const modelName of V2X_VEHICLE_MODEL_NAMES) {
|
|
const source = path.join(V2X_LIBRARY_ROOT, modelName);
|
|
if (!fs.existsSync(source)) throw new Error(`V2X vehicle model not found: ${source}`);
|
|
fs.copyFileSync(source, path.join(targetDir, modelName));
|
|
}
|
|
return V2X_VEHICLE_MODEL_NAMES.map((modelName) => `v2x-vehicles/${modelName}`);
|
|
}
|
|
|
|
module.exports = {
|
|
VEHICLE_IDS,
|
|
REVERSED_MODEL_IDS,
|
|
V2X_VEHICLE_MODEL_NAMES,
|
|
writePreviewVehicleLibrary,
|
|
writePreviewV2xVehicleLibrary,
|
|
};
|