LNXSDK/lib/haxerecast/buildnavjs.js

137 lines
4.1 KiB
JavaScript
Raw Normal View History

2025-01-22 16:18:30 +01:00
const fs = require('fs');
const Recast = require("../haxerecast/recastjs/recast");
// Get mesh path and NavMesh config
const recast_settings = process.argv[3];
const path_mesh = './' + process.argv[2] + '.obj'
// Read OBJ file and build NavMesh
readObjFile(path_mesh, (error, vertices, vertexLength, indices, indexLength) => {
if (error) {
console.error('Error:', error);
} else {
buildNavMesh(vertices, vertexLength, indices, indexLength);
}
});
// Parse OBJ file
function readObjFile(objFilePath, callback) {
try {
// Read the OBJ file
const objFileContent = fs.readFileSync(objFilePath, 'utf-8');
// Process the OBJ content
const vertices = [];
const indices = [];
vertices.length
const lines = objFileContent.split('\n');
lines.forEach((line) => {
const parts = line.trim().split(/\s+/);
if (parts[0] === 'v') {
// Vertex data
const x = parseFloat(parts[1]);
const y = parseFloat(parts[2]);
const z = parseFloat(parts[3]);
vertices.push(x, y, z);
} else if (parts[0] === 'f') {
// Face data
const faceIndices = parts.slice(1).map((vertex) => parseInt(vertex.split('/')[0]) - 1);
indices.push(...faceIndices);
}
});
// Call the callback with the result
callback(null, vertices, vertices.length, indices, indices.length);
} catch (error) {
callback(error);
}
}
function buildNavMesh (vertices, vertexLength, indices, indexLength) {
recastSettings = JSON.parse(recast_settings);
Recast().then(function(Recast) {
// Copy recast config settings
var recastConfig = new Recast.rcConfig();
recastConfig.width = recastSettings.width;
recastConfig.height = recastSettings.height;
if(recastSettings.tiledMesh) {
recastConfig.tileSize = recastSettings.tileSize;
}
else {
recastConfig.tileSize = 0;
}
recastConfig.borderSize = recastSettings.borderSize;
recastConfig.cs = recastSettings.cellSize;
recastConfig.ch = recastSettings.cellHeight;
recastConfig.walkableSlopeAngle = recastSettings.walkableSlopeAngle;
recastConfig.walkableHeight = recastSettings.walkableHeight;
recastConfig.walkableClimb = recastSettings.walkableClimb;
recastConfig.walkableRadius = recastSettings.walkableRadius;
recastConfig.maxEdgeLen = recastSettings.maxEdgeLen;
recastConfig.maxSimplificationError = recastSettings.maxSimplificationError;
recastConfig.minRegionArea = recastSettings.minRegionArea;
recastConfig.mergeRegionArea = recastSettings.mergeRegionArea;
recastConfig.maxVertsPerPoly = recastSettings.maxVertsPerPoly;
recastConfig.detailSampleDist = recastSettings.detailSampleDist;
recastConfig.detailSampleMaxError = recastSettings.detailSampleMaxError;
// Init NavMesh
var navNesh = new Recast.NavMesh();
// Build NavMesh
navNesh.build(vertices, vertexLength, indices, indexLength, recastConfig);
// Create debug NavMesh for visualization
var debugNavMesh = navNesh.getDebugNavMesh();
var trianglesCount = debugNavMesh.getTriangleCount();
triangelVertices = []
triangleFaces = []
// Loop through triangles
for(let runTriangle = 0; runTriangle < trianglesCount; runTriangle++) {
var triangle = debugNavMesh.getTriangle(runTriangle);
// Get triangle vertices
var points = [triangle.getPoint(0),
triangle.getPoint(1),
triangle.getPoint(2)];
// Get vertex positon
for(var i in points) {
// y, z interchanged
triangelVertices.push([points[i].x, points[i].z, points[i].y]);
}
// Get triangle indices
var face = [3 * runTriangle + 1,
3 * runTriangle + 2,
3 * runTriangle + 3];
triangleFaces.push(face);
}
// Get OBJ format of triangles
var navMeshObj = saveGeometryToObj(triangelVertices, triangleFaces);
// Write to OBJ file
fs.writeFile(path_mesh, navMeshObj, function (err) {
if (err) throw err;
});
});
}
function saveGeometryToObj (vertices, faces) {
var buffer = '';
//Write Vertices
for (var i in vertices) buffer += 'v ' + (vertices[i][0]) + ' ' + vertices[i][1] + ' ' + vertices[i][2] + '\n';
//Write Faces
for (var i in faces) buffer += 'f ' + (faces[i][0]) + ' ' + faces[i][1] + ' ' + faces[i][2] + '\n';
return buffer;
}