UNPKG

mdx-m3-viewer

Version:

A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.

222 lines (173 loc) 5.73 kB
ModelViewer = ModelViewer.default; let common = ModelViewer.common; let quat = common.glMatrix.quat; let vec3 = common.glMatrix.vec3; let math = common.math; let geometry = common.geometry; var keyboard = {}; var mouse = { buttons: [false, false, false], x: 0, y: 0, x2: 0, y2: 0 }; var canvas = document.getElementById('canvas'); var viewer = new ModelViewer.viewer.ModelViewer(canvas, { alpha: true }); var model; var instance; viewer.on('error', (e) => console.error(e)); viewer.addHandler(ModelViewer.viewer.handlers.mdx); viewer.addHandler(ModelViewer.viewer.handlers.blp); viewer.addHandler(ModelViewer.viewer.handlers.tga); viewer.addHandler(ModelViewer.viewer.handlers.dds); viewer.gl.clearColor(0, 0, 0, 1); let backgroundOpaque = true; let turnTable = false; let turnTableSpeed = 0; let turnTableQuat = quat.create(); let isRecording = false; let recordingFrame = 0; let oneTimeRecord = false; let zip = new JSZip(); let frameCounterElement = document.getElementById('frame_counter'); let sequenceNameElement = document.getElementById('sequence_name'); (function step() { viewer.updateAndRender(); if (instance) { instance.rotate(turnTableQuat); if (isRecording || oneTimeRecord) { oneTimeRecord = false; zip.file( `${recordingFrame++}_${model.name}_${Math.floor(instance.frame)}.png`, viewer.canvas.toDataURL().substring(22), { base64: true } ); frameCounterElement.textContent = recordingFrame; } } requestAnimationFrame(step); })(); let scene = viewer.addScene(); console.log(scene); setupCamera(scene, 500); console.log('Viewer version', ModelViewer.version); // Run the next sequence for the given instance at e. function runNextSequence(e) { let instance = e.target; instance.setSequence((instance.sequence + 1) % instance.model.sequences.length); } // Log load starts to the console. viewer.on('loadstart', target => { let path = target.fetchUrl; if (path) { console.log('Loading ' + target.fetchUrl); } }); // Log load ends to the console. viewer.on('load', target => { let path = target.fetchUrl; if (path) { console.log('Finished loading ' + target.fetchUrl); } }); function normalizePath(path) { return path.toLocaleLowerCase().replace(/\\/g, '/'); } // Load a local file function onLocalFileLoaded(name, buffer) { if (name.endsWith('.mdx')) { let pathSolver = src => { if (src === buffer) { return src; } else { return localOrHive(normalizePath(src)); } }; turnTableSpeed = 0; quat.identity(turnTableQuat); isRecording = false; scene.clear(); viewer.load(buffer, pathSolver) .then((model) => { instance = model.addInstance(); instance.setSequenceLoopMode(2); instance.setSequence(0); sequenceNameElement.textContent = model.sequences[0].name; scene.addInstance(instance); }); } } canvas.addEventListener('contextmenu', function (e) { e.preventDefault(); }); canvas.addEventListener('selectstart', function (e) { e.preventDefault(); }); function onFileDrop(e) { let file = e.dataTransfer.files[0]; if (file) { let name = file.name.toLowerCase(); if (name.endsWith('.mdx') || name.endsWith('.blp')) { let reader = new FileReader(); reader.addEventListener('loadend', e => onLocalFileLoaded(name, e.target.result)); reader.readAsArrayBuffer(file); } } } document.addEventListener('dragover', e => { e.preventDefault(); }); document.addEventListener('dragend', e => { e.preventDefault(); onFileDrop(e); }); document.addEventListener('drop', e => { e.preventDefault(); onFileDrop(e); }); window.addEventListener('keydown', e => { let key = e.key; if (instance) { if (key === ' ') { isRecording = !isRecording; } else if (key === 'ArrowLeft') { if (instance.sequence === 0) { instance.setSequence(model.sequences.length - 1); } else { instance.setSequence(instance.sequence - 1); } sequenceNameElement.textContent = model.sequences[instance.sequence].name; } else if (key === 'ArrowRight') { if (instance.sequence === model.sequences.length - 1) { instance.setSequence(0); } else { instance.setSequence(instance.sequence + 1); } sequenceNameElement.textContent = model.sequences[instance.sequence].name; } else if (key === 'ArrowUp') { turnTableSpeed += 0.2; quat.setAxisAngle(turnTableQuat, [0, 0, 1], math.degToRad(turnTableSpeed)); } else if (key === 'ArrowDown') { turnTableSpeed -= 0.2; quat.setAxisAngle(turnTableQuat, [0, 0, 1], math.degToRad(turnTableSpeed)); } else if (key === 'Enter') { oneTimeRecord = true; } else if (key === 'Escape') { if (recordingFrame > 0) { zip.generateAsync({ type: 'blob' }).then(blob => { saveAs(blob, `recorded_frames_${recordingFrame}.zip`); zip = new JSZip(); recordingFrame = 0; frameCounterElement.textContent = ''; }); } } } if (key === 'b') { backgroundOpaque = !backgroundOpaque; if (backgroundOpaque) { viewer.gl.clearColor(0, 0, 0, 1); sequenceNameElement.style.color = 'white'; frameCounterElement.style.color = 'white'; } else { viewer.gl.clearColor(0, 0, 0, 0); sequenceNameElement.style.color = 'black'; frameCounterElement.style.color = 'black'; } } });