mirror of
https://git.mirrors.martin98.com/https://github.com/google/draco
synced 2025-04-22 05:39:54 +08:00

-Increase version to 1.0.1 -Update Javascript decode timing example -Fix async creation of DracoDecoderModule -fixes wasm parallel decoding -Introduce base class for geometric normal predictor -Added integer attribute interface to JavaScript decoder -Move loading Draco decoder into three.js Draco loader -Add compiler launcher support to CMake build -Add sanitizer support via CMake build -Check we are not reading past the end of the attribute buffer
207 lines
6.2 KiB
HTML
207 lines
6.2 KiB
HTML
<html>
|
|
<head>
|
|
<title>Draco Decode Timing</title>
|
|
|
|
<script type="text/javascript">
|
|
'use strict';
|
|
|
|
// Global Draco decoder.
|
|
let dracoDecoder = {};
|
|
let dracoDecoderType = {};
|
|
|
|
// This function loads a JavaScript file and adds it to the page. "path" is
|
|
// the path to the JavaScript file. "onLoadFunc" is the function to be called
|
|
// when the JavaScript file has been loaded.
|
|
function loadJavaScriptFile(path, onLoadFunc) {
|
|
const head = document.getElementsByTagName('head')[0];
|
|
const element = document.createElement('script');
|
|
element.type = 'text/javascript';
|
|
element.src = path;
|
|
if (onLoadFunc !== null)
|
|
element.onload = onLoadFunc;
|
|
|
|
head.appendChild(element);
|
|
}
|
|
|
|
function loadWebAssemblyDecoder() {
|
|
dracoDecoderType['wasmBinaryFile'] = 'draco_decoder.wasm';
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open('GET', 'draco_decoder.wasm', true);
|
|
xhr.responseType = 'arraybuffer';
|
|
|
|
xhr.onload = function() {
|
|
// For WebAssembly the object passed into DracoModule() must contain a
|
|
// property with the name of wasmBinary and the value must be an
|
|
// ArrayBuffer containing the contents of the .wasm file.
|
|
dracoDecoderType['wasmBinary'] = xhr.response;
|
|
createDracoDecoder();
|
|
};
|
|
|
|
xhr.send(null)
|
|
}
|
|
|
|
function createDracoDecoder() {
|
|
// draco_decoder.js or draco_wasm_wrapper.js must be loaded before
|
|
// DracoModule is created.
|
|
if (typeof dracoDecoderType === 'undefined')
|
|
dracoDecoderType = {};
|
|
dracoDecoderType['onModuleLoaded'] = function(module) {
|
|
enableButtons();
|
|
};
|
|
const create_t0 = performance.now();
|
|
|
|
dracoDecoder = DracoDecoderModule(dracoDecoderType);
|
|
const create_t1 = performance.now();
|
|
addCell('DracoModule', true);
|
|
addCell(' ' + (create_t1 - create_t0), false);
|
|
}
|
|
|
|
// This function will test if the browser has support for WebAssembly. If it
|
|
// does it will download the WebAssembly Draco decoder, if not it will download
|
|
// the asmjs Draco decoder.
|
|
function loadDracoDecoder() {
|
|
if (typeof WebAssembly !== 'object') {
|
|
// No WebAssembly support. DracoModule must be called with no parameters
|
|
// or an empty object to create a JavaScript decoder.
|
|
loadJavaScriptFile('draco_decoder.js', createDracoDecoder);
|
|
} else {
|
|
loadJavaScriptFile('draco_wasm_wrapper.js', loadWebAssemblyDecoder);
|
|
}
|
|
}
|
|
|
|
// Functions to handle logging output.
|
|
// String to hold table output.
|
|
let dt = '';
|
|
|
|
function startTable() {
|
|
dt += '<table><tr>';
|
|
dt += '<td>Filename</td>';
|
|
dt += '<td>Total milli</td>';
|
|
dt += '<td>Decode milli</td>';
|
|
dt += '<td>Size bytes</td>';
|
|
dt += '<td>Num points</td>';
|
|
}
|
|
|
|
function addCell(str, newRow) {
|
|
if (newRow)
|
|
dt += '</tr><tr>';
|
|
dt += '<td>' + str + '</td>';
|
|
}
|
|
|
|
function finishTable() {
|
|
dt += '</table>';
|
|
document.getElementById('tableOutput').innerHTML = dt;
|
|
}
|
|
|
|
function s_log(str, end_line, reset) {
|
|
if (reset)
|
|
document.getElementById('status').innerHTML = '';
|
|
document.getElementById('status').innerHTML += str;
|
|
if (end_line)
|
|
document.getElementById('status').innerHTML += "<br/>";
|
|
}
|
|
|
|
// Functions to handle the input from the buttons.
|
|
function enableButtons() {
|
|
document.getElementById('decodeOne').disabled = false;
|
|
document.getElementById('decodeMult').disabled = false;
|
|
}
|
|
|
|
function onDecodeClick() {
|
|
startTable();
|
|
const inputs = document.getElementById('u').value.split(',');
|
|
const build =
|
|
(typeof WebAssembly !== 'object') ? 'JavaScript' : 'WebAssembly';
|
|
s_log('Decoding ' + inputs.length + ' files... using ' + build, true, true);
|
|
testMeshDecodingAsync(inputs, 0);
|
|
}
|
|
|
|
function onDecodeMultipleClick() {
|
|
startTable();
|
|
const inputs = document.getElementById('u').value.split(',');
|
|
const decode_count = parseInt(document.getElementById('decode_count').value);
|
|
const build =
|
|
(typeof WebAssembly !== 'object') ? 'JavaScript' : 'WebAssembly';
|
|
s_log('Decoding ' + (decode_count * inputs.length) + ' files... using ' +
|
|
build, true, true);
|
|
|
|
let fileList = [];
|
|
for (let i = 0; i < decode_count; ++i) {
|
|
fileList = fileList.concat(inputs);
|
|
}
|
|
testMeshDecodingAsync(fileList, 0);
|
|
}
|
|
|
|
// Decode geometry.
|
|
function testMeshDecodingAsync(filenameList, index) {
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open("GET", filenameList[index], true);
|
|
xhr.responseType = "arraybuffer";
|
|
|
|
xhr.onload = function(event) {
|
|
const arrayBuffer = xhr.response;
|
|
if (arrayBuffer) {
|
|
const byteArray = new Uint8Array(arrayBuffer);
|
|
|
|
const total_t0 = performance.now();
|
|
|
|
const buffer = new dracoDecoder.DecoderBuffer();
|
|
buffer.Init(byteArray, byteArray.length);
|
|
|
|
const decoder = new dracoDecoder.Decoder();
|
|
|
|
const decode_t0 = performance.now();
|
|
const geometryType = decoder.GetEncodedGeometryType(buffer);
|
|
let dracoGeometry;
|
|
let decodingStatus;
|
|
if (geometryType == dracoDecoder.TRIANGULAR_MESH) {
|
|
dracoGeometry = new dracoDecoder.Mesh();
|
|
decodingStatus = decoder.DecodeBufferToMesh(buffer, dracoGeometry);
|
|
} else {
|
|
dracoGeometry = new dracoDecoder.PointCloud();
|
|
decodingStatus =
|
|
decoder.DecodeBufferToPointCloud(buffer, dracoGeometry);
|
|
}
|
|
const t1 = performance.now();
|
|
|
|
addCell(filenameList[index], true);
|
|
addCell('' + (t1 - total_t0), false);
|
|
addCell('' + (t1 - decode_t0), false);
|
|
addCell('' + byteArray.length, false);
|
|
addCell('' + dracoGeometry.num_points(), false);
|
|
|
|
dracoDecoder.destroy(dracoGeometry);
|
|
dracoDecoder.destroy(decoder);
|
|
dracoDecoder.destroy(buffer);
|
|
|
|
if (index < filenameList.length - 1) {
|
|
index = index + 1;
|
|
testMeshDecodingAsync(filenameList, index);
|
|
} else {
|
|
finishTable();
|
|
}
|
|
}
|
|
};
|
|
|
|
xhr.send(null);
|
|
}
|
|
|
|
loadDracoDecoder();
|
|
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<H1>Draco Decode Timing</H1>
|
|
Draco file to be decoded. If more than one file, add as comma separated list. E.g. "file1.drc,file2.drc,file3.drc"</br>
|
|
<input id="u" type="text" size="80" value="input.drc"/>
|
|
<input type="button" value="Decode" id="decodeOne" onClick="onDecodeClick();" disabled>
|
|
<input id="decode_count" type="text" size="10" value="10"/>
|
|
<input type="button" value="Decode Multiple" id="decodeMult" onClick="onDecodeMultipleClick();" disabled>
|
|
<br/>
|
|
<div id="status"> </div></br>
|
|
<div id="tableOutput"> </div>
|
|
</body>
|
|
</html>
|
|
|