The scaleMap
function modifies a Quake 3 map file by scaling the coordinates of its brush entities and origins by a specified amount. This is likely used for resizing or adjusting the scale of map geometry.
npm run import -- "scale quake map"
var fs = require('fs')
var DIGITS = 100.0
function scaleMap(file, amount) {
// get all brushes in map, leaf nodes with at least one vertex
var brushes = importer.regexToArray(/\{[\s\S]*?\}/ig, file)
// replace all brushes with scaled values
brushes.forEach(b => {
var newBrush = b
newBrush = newBrush.replace(/\(((\s*[0-9\.-]+\s*)*)\)/ig, (str, $1) => {
return '( ' + $1.trim().split(/\s+/ig)
.map(n => Math.round((n.includes('.')
? parseFloat(n.trim())
: parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ') + ' )'
})
// scale the texture on the brush
newBrush = newBrush.replace(/\)\s+([^\)\(]*?)\s+((\s*[0-9\.-]+\s*){5,8})/ig, (str, $1, $2) => {
return ') ' + $1 + ' ' + $2.trim().split(/\s+/ig)
.map((n, i) => i >= 5 || i <= 2 ? n : (Math.round((n.includes('.')
? parseFloat(n.trim())
: parseInt(n.trim())) * amount * DIGITS) / DIGITS))
.join(' ') + '\n'
})
file = file.replace(b, newBrush)
})
// replace all origins with scaled
// TODO: make this a function
var origins = importer.regexToArray(/"origin"\s+"((\s*[0-9\.-]+\s*)*)"/ig, file, 1)
origins.forEach($1 => {
var newOrigin = $1.trim().split(/\s+/ig)
.map(n => Math.round((n.includes('.')
? parseFloat(n.trim())
: parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ')
file = file.replace(new RegExp('"origin"\\s+"' + $1 + '"', 'ig'), '"origin" "' + newOrigin + '"')
})
var lips = importer.regexToArray(/"lip"\s+"((\s*[0-9\.-]+\s*)*)"/ig, file, 1)
lips.forEach($1 => {
var newOrigin = $1.trim().split(/\s+/ig)
.map(n => Math.round((n.includes('.')
? parseFloat(n.trim())
: parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ')
file = file.replace(new RegExp('"lip"\\s+"' + $1 + '"', 'ig'), '"lip" "' + newOrigin + '"')
})
// scale models
var models = importer.regexToArray(/\{[\s\S^\}\{]*?"classname"\s+"misc_model"[\s\S^\}\{]*?\}/ig, file)
models.forEach(m => {
var newModel = m
if(m.match(/"modelscale"/i)) {
var match = (/"modelscale"\s+"([^"]*?)"/ig).exec(m)
var scaled = (match[1].includes('.')
? parseFloat(match[1])
: parseInt(match[1])) * amount
newModel = newModel.replace(match[0], '"modelscale" "' + scaled + '"')
} else {
newModel = newModel.replace(/"classname"\s+"misc_model"/ig,
'"classname" "misc_model"\n "modelscale" "' + amount + '"')
}
file = file.replace(m, newModel)
})
return file
}
module.exports = scaleMap
const fs = require('fs');
const importer = require('./importer'); // assuming importer module is in the same directory
const DIGITS = 100.0;
const REGEX_BRUSH = /\{[\s\S]*?\}/ig;
const REGEX_ORIGIN = /"origin"\s+"((\s*[0-9\.-]+\s*)*)"/ig;
const REGEX_LIP = /"lip"\s+"((\s*[0-9\.-]+\s*)*)"/ig;
const REGEX_MODEL = /\{[\s\S^\}\{]*?"classname"\s+"misc_model"[\s\S^\}\{]*?\}/ig;
function scaleMap(file, amount) {
// Get all brushes in map
const brushes = importer.regexToArray(REGEX_BRUSH, file);
// Scale brushes
brushes.forEach((brush) => {
const newBrush = scaleBrush(brush, amount);
file = file.replace(brush, newBrush);
});
// Scale origins
scaleOrigin(file, amount);
scaleLip(file, amount);
// Scale models
const models = importer.regexToArray(REGEX_MODEL, file);
models.forEach((model) => {
const newModel = scaleModel(model, amount);
file = file.replace(model, newModel);
});
return file;
}
function scaleBrush(brush, amount) {
let newBrush = brush;
newBrush = newBrush.replace(/\(((\s*[0-9\.-]+\s*)*)\)/ig, (str, $1) => {
return '('+ $1.trim().split(/\s+/ig)
.map((n) => Math.round((n.includes('.')? parseFloat(n.trim()) : parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ') +')';
});
newBrush = newBrush.replace(/\)\s+([^\)\(]*?)\s+((\s*[0-9\.-]+\s*){5,8})/ig, (str, $1, $2) => {
return ')'+ $1 +'' + $2.trim().split(/\s+/ig)
.map((n, i) => i >= 5 || i <= 2? n : Math.round((n.includes('.')? parseFloat(n.trim()) : parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ') + '\n';
});
return newBrush;
}
function scaleOrigin(file, amount) {
const origins = importer.regexToArray(REGEX_ORIGIN, file, 1);
origins.forEach((origin) => {
const newOrigin = origin.trim().split(/\s+/ig)
.map((n) => Math.round((n.includes('.')? parseFloat(n.trim()) : parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ');
file = file.replace(new RegExp('"origin"\\s+"' + origin + '"', 'ig'), '"origin" "' + newOrigin + '"');
});
}
function scaleLip(file, amount) {
const lips = importer.regexToArray(REGEX_LIP, file, 1);
lips.forEach((lip) => {
const newOrigin = lip.trim().split(/\s+/ig)
.map((n) => Math.round((n.includes('.')? parseFloat(n.trim()) : parseInt(n.trim())) * amount * DIGITS) / DIGITS)
.join(' ');
file = file.replace(new RegExp('"lip"\\s+"' + lip + '"', 'ig'), '"lip" "' + newOrigin + '"');
});
}
function scaleModel(model, amount) {
if (model.match(/"modelscale"/i)) {
const match = (/"modelscale"\s+"([^"]*?)"/ig).exec(model);
const scaled = (match[1].includes('.')? parseFloat(match[1]) : parseInt(match[1])) * amount;
return model.replace(match[0], '"modelscale" "' + scaled + '"');
} else {
return model.replace(/"classname"\s+"misc_model"/ig, '"classname" "misc_model"\n "modelscale" "' + amount + '"');
}
}
module.exports = scaleMap;
This code snippet defines a function scaleMap
that modifies a Quake 3 map file by scaling its brush entities and origins.
Here's a breakdown:
Initialization:
fs
: Node.js module for file system operations.DIGITS
: A constant set to 100.0, likely used for precision during scaling calculations.scaleMap
Function:
file
(the map file content as a string) and amount
(the scaling factor)./\{[\s\S]*?\}/ig
) to find all brush entities within the map file.brushes
.brushes
array.newBrush
) of the original brush.amount
and DIGITS
.file
with the scaled newBrush
.Return Value:
file
content with scaled brush entities and origins.Purpose:
This code snippet is a utility function for modifying Quake 3 map files by scaling their geometry. It's likely used in a larger project for map editing or conversion purposes.