Last active
December 6, 2019 15:05
-
-
Save Kruithne/8d472e944f233fa5bb1b861fcd275582 to your computer and use it in GitHub Desktop.
Clunky MDX converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// WARNING - This was written in a rush, late at night. Mostly broken, not good code. | |
// UV mappings are slightly wrong, scale Y -1 to fix. | |
// Requires modded Bufo found here -> https://gist.github.com/Kruithne/679eb3b3e5099360cbe4c5872f2aa606 | |
// Only exports Verts, Faces, UV and Normals to OBJ format (no MTL, skin it yourself!) | |
const fs = require('fs'); | |
const Bufo = require('./bufo.js'); | |
const path = require('path'); | |
const util = require('util'); | |
const argv = process.argv.splice(2); | |
for (let file of argv) { | |
if (!fs.existsSync(file)) { | |
console.error('Unable to locate file: %s', file); | |
continue; | |
} | |
let filePath = path.resolve(file); | |
let bin = new Bufo(fs.readFileSync(file)); | |
let magic = bin.readString(4); | |
if (magic !== 'MDLX') { | |
console.error('Invalid magic? %s', magic); | |
continue; | |
} | |
let out = []; | |
//let faceIndex = 1; | |
let groupsOut = []; | |
let vertsOut = [] | |
let normalsOut = []; | |
let uvOut = []; | |
while (bin.remainingBytes > 0) { | |
let chunkHeader = bin.readString(4); | |
let chunkLength = bin.readUInt32(); | |
if (chunkHeader === 'VERS') { | |
let version = bin.readUInt32(); | |
console.log('%s (version %d mdx)', filePath, version); | |
} else if (chunkHeader === 'MODL') { | |
let modelName = bin.readString(50).replace(/\0/g, ''); | |
out.push('# Model ' + modelName); | |
console.log('Model name: %s', modelName); | |
bin.move(chunkLength - 50); | |
} else if (chunkHeader === 'GEOS') { | |
let chunk = bin.readBufo(chunkLength); | |
let ofs = []; | |
while (chunk.remainingBytes > 0) { | |
let byte = chunk.readUInt8(); | |
let byteOfs = chunk.offset - 1; | |
if (byte === 0x56) { | |
chunk.move(-1); | |
if (chunk.readString(4) === 'VRTX') { | |
ofs.push(byteOfs); | |
} else { | |
chunk.move(-3); | |
} | |
} | |
} | |
for (let i = 0; i < ofs.length; i++) { | |
let offset = ofs[i]; | |
chunk.seek(offset + 4); | |
groupsOut.push('o ' + i); | |
let vertCount = chunk.readUInt32(); | |
let vertsStartIndex = vertsOut.length; | |
for (let i = 0; i < vertCount; i++) { | |
let verts = chunk.readFloat(3); | |
vertsOut.push('v ' + verts.join(' ')); | |
} | |
chunk.move(4); // NRMs | |
let nrmCount = chunk.readUInt32(); | |
for (let i = 0; i < nrmCount; i++) { | |
let nrms = chunk.readFloat(3); | |
normalsOut.push('vn ' + nrms.join(' ')); | |
} | |
chunk.move(4); // PTYP | |
chunk.move(chunk.readUInt32() * 4); | |
chunk.move(4); // PCNT | |
chunk.move(chunk.readUInt32() * 4); | |
chunk.move(4); // PVTX | |
let faceCountRaw = chunk.readUInt32(); | |
let faceCount = faceCountRaw / 3; | |
for (let i = 0; i < faceCount; i++) { | |
let face = chunk.readUInt16(3); | |
let f1 = vertsStartIndex + face[0] + 1; | |
let f2 = vertsStartIndex + face[1] + 1; | |
let f3 = vertsStartIndex + face[2] + 1; | |
groupsOut.push(util.format('f %d/%d/%d %d/%d/%d %d/%d/%d', f1, f1, f1, f2, f2, f2, f3, f3, f3)); | |
} | |
while (chunk.remainingBytes > 0) { | |
let byte = chunk.readUInt8(); | |
if (byte === 0x55) { | |
chunk.move(-1); | |
if (chunk.readString(4) === 'UVBS') { | |
let uvCount = chunk.readUInt32(); | |
for (let i = 0; i < uvCount; i++) { | |
let uv = chunk.readFloat(2); | |
uvOut.push('vt ' + uv.join(' ')); | |
} | |
} else { | |
chunk.move(-3); | |
} | |
} | |
} | |
} | |
} else { | |
console.log('Unknown chunk: %s (%d bytes)', chunkHeader, chunkLength); | |
bin.move(chunkLength); | |
} | |
} | |
if (out.length > 0) { | |
for (let node of vertsOut) | |
out.push(node); | |
for (let node of normalsOut) | |
out.push(node); | |
for (let node of uvOut) | |
out.push(node); | |
for (let node of groupsOut) | |
out.push(node); | |
let outFile = path.join(path.dirname(filePath), path.basename(filePath, '.mdx') + '.obj'); | |
fs.writeFileSync(outFile, out.join('\n'), 'utf8'); | |
console.log('Writing %s', outFile); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment