137 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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;
 | 
						|
} |