UNPKG

three

Version:

JavaScript 3D library

1,171 lines (1,159 loc) 131 kB
/*global ArrayBuffer, Uint32Array, Int32Array, Float32Array, Int8Array, Uint8Array, window, performance, Console*/ /* Copyright (c) 2013 Khaled Mammou - Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ var o3dgc = (function () { "use strict"; var module, local; module = {}; local = {}; local.O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0 = 7; local.O3DGC_BINARY_STREAM_MAX_SYMBOL0 = 127; // ((1 << O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0) >>> 0) - 1; local.O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1 = 6; local.O3DGC_BINARY_STREAM_MAX_SYMBOL1 = 63; // ((1 << O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1) >>> 0) - 1; local.O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32 = 5; // Math.floor((32 + O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0 - 1) / O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0); local.O3DGC_BIG_ENDIAN = 0; local.O3DGC_LITTLE_ENDIAN = 1; local.O3DGC_MAX_DOUBLE = 1.79769e+308; local.O3DGC_MIN_LONG = -2147483647; local.O3DGC_MAX_LONG = 2147483647; local.O3DGC_MAX_UCHAR8 = 255; local.O3DGC_MAX_TFAN_SIZE = 256; local.O3DGC_MAX_ULONG = 4294967295; local.O3DGC_SC3DMC_START_CODE = 0x00001F1; local.O3DGC_DV_START_CODE = 0x00001F2; local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES = 256; local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES = 256; local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES = 32; local.O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS = 2; local.O3DGC_SC3DMC_BINARIZATION_FL = 0; // Fixed Length (not supported) local.O3DGC_SC3DMC_BINARIZATION_BP = 1; // BPC (not supported) local.O3DGC_SC3DMC_BINARIZATION_FC = 2; // 4 bits Coding (not supported) local.O3DGC_SC3DMC_BINARIZATION_AC = 3; // Arithmetic Coding (not supported) local.O3DGC_SC3DMC_BINARIZATION_AC_EGC = 4; // Arithmetic Coding & EGCk local.O3DGC_SC3DMC_BINARIZATION_ASCII = 5; // Arithmetic Coding & EGCk local.O3DGC_STREAM_TYPE_UNKOWN = 0; local.O3DGC_STREAM_TYPE_ASCII = 1; local.O3DGC_STREAM_TYPE_BINARY = 2; local.O3DGC_SC3DMC_NO_PREDICTION = 0; // supported local.O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION = 1; // supported local.O3DGC_SC3DMC_XOR_PREDICTION = 2; // not supported local.O3DGC_SC3DMC_ADAPTIVE_DIFFERENTIAL_PREDICTION = 3; // not supported local.O3DGC_SC3DMC_CIRCULAR_DIFFERENTIAL_PREDICTION = 4; // not supported local.O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION = 5; // supported local.O3DGC_SC3DMC_SURF_NORMALS_PREDICTION = 6; // supported local.O3DGC_SC3DMC_ENCODE_MODE_QBCR = 0; // not supported local.O3DGC_SC3DMC_ENCODE_MODE_SVA = 1; // not supported local.O3DGC_SC3DMC_ENCODE_MODE_TFAN = 2; // supported local.O3DGC_DYNAMIC_VECTOR_ENCODE_MODE_LIFT = 0; local.O3DGC_MIN_NEIGHBORS_SIZE = 128; local.O3DGC_MIN_NUM_NEIGHBORS_SIZE = 16; local.O3DGC_TFANS_MIN_SIZE_ALLOCATED_VERTICES_BUFFER = 128; local.O3DGC_TFANS_MIN_SIZE_TFAN_SIZE_BUFFER = 8; local.O3DGC_DEFAULT_VECTOR_SIZE = 32; module.O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_UNKOWN = 0; module.O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_POSITION = 1; module.O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_NORMAL = 2; module.O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_COLOR = 3; module.O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD = 4; module.O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_WEIGHT = 5; module.O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN = 0; module.O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX = 1; module.O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID = 2; module.O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID = 3; module.O3DGC_OK = 0; module.O3DGC_ERROR_BUFFER_FULL = 1; module.O3DGC_ERROR_CORRUPTED_STREAM = 5; module.O3DGC_ERROR_NON_SUPPORTED_FEATURE = 6; module.O3DGC_ERROR_AC = 7; function SystemEndianness() { var a, b, c; b = new ArrayBuffer(4); a = new Uint32Array(b); c = new Uint8Array(b); a[0] = 1; if (c[0] === 1) { return local.O3DGC_LITTLE_ENDIAN; } return local.O3DGC_BIG_ENDIAN; } // SC3DMCStats class module.SC3DMCStats = function () { this.m_timeCoord = 0; this.m_timeNormal = 0; this.m_timeCoordIndex = 0; this.m_timeFloatAttribute = new Float32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_timeIntAttribute = new Float32Array(local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); this.m_timeReorder = 0; this.m_streamSizeCoord = 0; this.m_streamSizeNormal = 0; this.m_streamSizeCoordIndex = 0; this.m_streamSizeFloatAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_streamSizeIntAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); }; // SC3DMCTriplet class module.SC3DMCTriplet = function (a, b, c) { this.m_a = a; this.m_b = b; this.m_c = c; }; module.SC3DMCTriplet.prototype.Less = function (rhs) { var res; if (this.m_c !== rhs.m_c) { res = (this.m_c < rhs.m_c); } else if (this.m_b !== rhs.m_b) { res = (this.m_b < rhs.m_b); } else { res = (this.m_a < rhs.m_a); } return res; }; module.SC3DMCTriplet.prototype.Equal = function (rhs) { return (this.m_c === rhs.m_c && this.m_b === rhs.m_b && this.m_a === rhs.m_a); }; // SC3DMCPredictor class module.SC3DMCPredictor = function () { this.m_id = new module.SC3DMCTriplet(-1, -1, -1); this.m_pred = new Float32Array(local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES); }; // fix me: optimize this function (e.g., binary search) function InsertPredictor(e, nPred, list, dimFloatArray) { var pos, foundOrInserted, j, j1, j0, h, i; pos = -1; foundOrInserted = false; j1 = nPred.m_value; j0 = 0; for (j = j0; j < j1; ++j) { if (e.Equal(list[j].m_id)) { foundOrInserted = true; break; } else if (e.Less(list[j].m_id)) { if (nPred.m_value < local.O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS) { ++nPred.m_value; } for (h = nPred.m_value - 1; h > j; --h) { list[h].m_id.m_a = list[h - 1].m_id.m_a; list[h].m_id.m_b = list[h - 1].m_id.m_b; list[h].m_id.m_c = list[h - 1].m_id.m_c; for (i = 0; i < dimFloatArray; ++i) { list[h].m_pred[i] = list[h - 1].m_pred[i]; } } list[j].m_id.m_a = e.m_a; list[j].m_id.m_b = e.m_b; list[j].m_id.m_c = e.m_c; pos = j; foundOrInserted = true; break; } } if (!foundOrInserted && nPred.m_value < local.O3DGC_SC3DMC_MAX_PREDICTION_NEIGHBORS) { pos = nPred.m_value++; list[pos].m_id.m_a = e.m_a; list[pos].m_id.m_b = e.m_b; list[pos].m_id.m_c = e.m_c; } return pos; } // Timer class if (typeof window.performance === 'undefined') { window.performance = {}; } if (!window.performance.now) { local.nowOffset = Date.now(); if (performance.timing && performance.timing.navigationStart) { local.nowOffset = performance.timing.navigationStart; } window.performance.now = function now() { return Date.now() - local.nowOffset; }; } module.Timer = function () { this.m_start = 0; this.m_end = 0; }; module.Timer.prototype.Tic = function () { this.m_start = window.performance.now(); }; module.Timer.prototype.Toc = function () { this.m_end = window.performance.now(); }; module.Timer.prototype.GetElapsedTime = function () { return this.m_end - this.m_start; }; // Vec3 class module.Vec3 = function (x, y, z) { this.m_x = x; this.m_y = y; this.m_z = z; }; module.Vec3.prototype.Set = function (x, y, z) { this.m_x = x; this.m_y = y; this.m_z = z; }; module.Vec3.prototype.Sub = function (lhs, rhs) { this.m_x = lhs.m_x - rhs.m_x; this.m_y = lhs.m_y - rhs.m_y; this.m_z = lhs.m_z - rhs.m_z; }; module.Vec3.prototype.Add = function (lhs, rhs) { this.m_x = lhs.m_x + rhs.m_x; this.m_y = lhs.m_y + rhs.m_y; this.m_z = lhs.m_z + rhs.m_z; }; module.Vec3.prototype.SelfAdd = function (v) { this.m_x += v.m_x; this.m_y += v.m_y; this.m_z += v.m_z; }; module.Vec3.prototype.Cross = function (lhs, rhs) { this.m_x = lhs.m_y * rhs.m_z - lhs.m_z * rhs.m_y; this.m_y = lhs.m_z * rhs.m_x - lhs.m_x * rhs.m_z; this.m_z = lhs.m_x * rhs.m_y - lhs.m_y * rhs.m_x; }; module.Vec3.prototype.GetNorm = function () { return Math.sqrt(this.m_x * this.m_x + this.m_y * this.m_y + this.m_z * this.m_z); }; function SphereToCube(vin, vout) { var ax, ay, az; ax = Math.abs(vin.m_x); ay = Math.abs(vin.m_y); az = Math.abs(vin.m_z); if (az >= ax && az >= ay) { if (vin.m_z >= 0) { vout.m_z = 0; vout.m_x = vin.m_x; vout.m_y = vin.m_y; } else { vout.m_z = 1; vout.m_x = -vin.m_x; vout.m_y = -vin.m_y; } } else if (ay >= ax && ay >= az) { if (vin.m_y >= 0) { vout.m_z = 2; vout.m_x = vin.m_z; vout.m_y = vin.m_x; } else { vout.m_z = 3; vout.m_x = -vin.m_z; vout.m_y = -vin.m_x; } } else { if (vin.m_x >= 0) { vout.m_z = 4; vout.m_x = vin.m_y; vout.m_y = vin.m_z; } else { vout.m_z = 5; vout.m_x = -vin.m_y; vout.m_y = -vin.m_z; } } } local.CubeToSphere = { 0: function (vin, vout) { vout.m_x = vin.m_x; vout.m_y = vin.m_y; vout.m_z = Math.sqrt(Math.max(0.0, 1.0 - vout.m_x * vout.m_x - vout.m_y * vout.m_y)); }, 1: function (vin, vout) { vout.m_x = -vin.m_x; vout.m_y = -vin.m_y; vout.m_z = -Math.sqrt(Math.max(0.0, 1.0 - vout.m_x * vout.m_x - vout.m_y * vout.m_y)); }, 2: function (vin, vout) { vout.m_z = vin.m_x; vout.m_x = vin.m_y; vout.m_y = Math.sqrt(Math.max(0.0, 1.0 - vout.m_x * vout.m_x - vout.m_z * vout.m_z)); }, 3: function (vin, vout) { vout.m_z = -vin.m_x; vout.m_x = -vin.m_y; vout.m_y = -Math.sqrt(Math.max(0.0, 1.0 - vout.m_x * vout.m_x - vout.m_z * vout.m_z)); }, 4: function (vin, vout) { vout.m_y = vin.m_x; vout.m_z = vin.m_y; vout.m_x = Math.sqrt(Math.max(0.0, 1.0 - vout.m_y * vout.m_y - vout.m_z * vout.m_z)); }, 5: function (vin, vout) { vout.m_y = -vin.m_x; vout.m_z = -vin.m_y; vout.m_x = -Math.sqrt(Math.max(0.0, 1.0 - vout.m_y * vout.m_y - vout.m_z * vout.m_z)); } }; function IntToUInt(value) { return (value < 0) ? (-1 - (2 * value)) : (2 * value); } function UIntToInt(uiValue) { return (uiValue & 1) ? -((uiValue + 1) >>> 1) : ((uiValue >>> 1)); } module.Iterator = function () { this.m_count = 0; }; module.NumberRef = function () { this.m_value = 0; }; // BinaryStream class module.BinaryStream = function (buffer) { this.m_endianness = SystemEndianness(); this.m_buffer = buffer; this.m_stream = new Uint8Array(this.m_buffer); this.m_localBuffer = new ArrayBuffer(4); this.m_localBufferViewUChar8 = new Uint8Array(this.m_localBuffer); this.m_localBufferViewFloat32 = new Float32Array(this.m_localBuffer); this.m_localBufferViewUInt32 = new Uint32Array(this.m_localBuffer); }; module.BinaryStream.prototype.ReadFloat32Bin = function (bsIterator) { if (this.m_endianness === local.O3DGC_BIG_ENDIAN) { this.m_localBufferViewUChar8[3] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[2] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[1] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[0] = this.m_stream[bsIterator.m_count++]; } else { this.m_localBufferViewUChar8[0] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[1] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[2] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[3] = this.m_stream[bsIterator.m_count++]; } return this.m_localBufferViewFloat32[0]; }; module.BinaryStream.prototype.ReadUInt32Bin = function (bsIterator) { if (this.m_endianness === local.O3DGC_BIG_ENDIAN) { this.m_localBufferViewUChar8[3] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[2] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[1] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[0] = this.m_stream[bsIterator.m_count++]; } else { this.m_localBufferViewUChar8[0] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[1] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[2] = this.m_stream[bsIterator.m_count++]; this.m_localBufferViewUChar8[3] = this.m_stream[bsIterator.m_count++]; } return this.m_localBufferViewUInt32[0]; }; module.BinaryStream.prototype.ReadUChar8Bin = function (bsIterator) { return this.m_stream[bsIterator.m_count++]; }; module.BinaryStream.prototype.ReadUInt32ASCII = function (bsIterator) { var value, shift, i; value = 0; shift = 0; for (i = 0; i < local.O3DGC_BINARY_STREAM_NUM_SYMBOLS_UINT32; ++i) { value += (this.m_stream[bsIterator.m_count++] << shift) >>> 0; shift += local.O3DGC_BINARY_STREAM_BITS_PER_SYMBOL0; } return value; }; module.BinaryStream.prototype.ReadFloat32ASCII = function (bsIterator) { var value = this.ReadUInt32ASCII(bsIterator); if (this.m_endianness === local.O3DGC_BIG_ENDIAN) { this.m_localBufferViewUChar8[3] = value & local.O3DGC_MAX_UCHAR8; value >>>= 8; this.m_localBufferViewUChar8[2] = value & local.O3DGC_MAX_UCHAR8; value >>>= 8; this.m_localBufferViewUChar8[1] = value & local.O3DGC_MAX_UCHAR8; value >>>= 8; this.m_localBufferViewUChar8[0] = value & local.O3DGC_MAX_UCHAR8; } else { this.m_localBufferViewUChar8[0] = value & local.O3DGC_MAX_UCHAR8; value >>>= 8; this.m_localBufferViewUChar8[1] = value & local.O3DGC_MAX_UCHAR8; value >>>= 8; this.m_localBufferViewUChar8[2] = value & local.O3DGC_MAX_UCHAR8; value >>>= 8; this.m_localBufferViewUChar8[3] = value & local.O3DGC_MAX_UCHAR8; } return this.m_localBufferViewFloat32[0]; }; module.BinaryStream.prototype.ReadIntASCII = function (bsIterator) { return UIntToInt(this.ReadUIntASCII(bsIterator)); }; module.BinaryStream.prototype.ReadUIntASCII = function (bsIterator) { var i, x, value; value = this.m_stream[bsIterator.m_count++]; if (value === local.O3DGC_BINARY_STREAM_MAX_SYMBOL0) { i = 0; do { x = this.m_stream[bsIterator.m_count++]; value += ((x >>> 1) << i) >>> 0; i += local.O3DGC_BINARY_STREAM_BITS_PER_SYMBOL1; } while (x & 1); } return value; }; module.BinaryStream.prototype.ReadUCharASCII = function (bsIterator) { return this.m_stream[bsIterator.m_count++]; }; module.BinaryStream.prototype.ReadFloat32 = function (bsIterator, streamType) { if (streamType === local.O3DGC_STREAM_TYPE_ASCII) { return this.ReadFloat32ASCII(bsIterator); } return this.ReadFloat32Bin(bsIterator); }; module.BinaryStream.prototype.ReadUInt32 = function (bsIterator, streamType) { if (streamType === local.O3DGC_STREAM_TYPE_ASCII) { return this.ReadUInt32ASCII(bsIterator); } return this.ReadUInt32Bin(bsIterator); }; module.BinaryStream.prototype.ReadUChar = function (bsIterator, streamType) { if (streamType === local.O3DGC_STREAM_TYPE_ASCII) { return this.ReadUCharASCII(bsIterator); } return this.ReadUChar8Bin(bsIterator); }; module.BinaryStream.prototype.GetBuffer = function (bsIterator, size) { return new Uint8Array(this.m_buffer, bsIterator.m_count, size); }; // Copyright (c) 2004 Amir Said (said@ieee.org) & William A. Pearlman (pearlw@ecse.rpi.edu) // All rights reserved. local.O3DGC_AC_MIN_LENGTH = 0x01000000; // threshold for renormalization local.O3DGC_AC_MAX_LENGTH = 0xFFFFFFFF; // maximum AC interval length local.O3DGC_AC_BM_LENGTH_SHIFT = 13; // Maximum values for binary models length bits discarded before mult. local.O3DGC_AC_BM_MAX_COUNT = (1 << local.O3DGC_AC_BM_LENGTH_SHIFT) >>> 0; // for adaptive models local.O3DGC_AC_DM_LENGTH_SHIFT = 15; // Maximum values for general models length bits discarded before mult. local.O3DGC_AC_DM_MAX_COUNT = (1 << local.O3DGC_AC_DM_LENGTH_SHIFT) >>> 0; // for adaptive models // StaticBitModel class module.StaticBitModel = function () { this.m_bit0Prob = (1 << (local.O3DGC_AC_BM_LENGTH_SHIFT - 1)) >>> 0; // p0 = 0.5 }; module.StaticBitModel.prototype.SetProbability = function (p) { this.m_bit0Prob = Math.floor(p * ((1 << local.O3DGC_AC_BM_LENGTH_SHIFT) >>> 0)); }; // AdaptiveBitModel class module.AdaptiveBitModel = function () { // initialization to equiprobable model this.m_updateCycle = 4; this.m_bitsUntilUpdate = 4; this.m_bit0Prob = (1 << (local.O3DGC_AC_BM_LENGTH_SHIFT - 1)) >>> 0; this.m_bit0Count = 1; this.m_bitCount = 2; }; module.AdaptiveBitModel.prototype.Reset = function () { this.m_updateCycle = 4; this.m_bitsUntilUpdate = 4; this.m_bit0Prob = (1 << (local.O3DGC_AC_BM_LENGTH_SHIFT - 1)) >>> 0; this.m_bit0Count = 1; this.m_bitCount = 2; }; module.AdaptiveBitModel.prototype.Update = function () { // halve counts when a threshold is reached if ((this.m_bitCount += this.m_updateCycle) > local.O3DGC_AC_BM_MAX_COUNT) { this.m_bitCount = (this.m_bitCount + 1) >>> 1; this.m_bit0Count = (this.m_bit0Count + 1) >>> 1; if (this.m_bit0Count === this.m_bitCount) { ++this.m_bitCount; } } // compute scaled bit 0 probability var scale = Math.floor(0x80000000 / this.m_bitCount); this.m_bit0Prob = (this.m_bit0Count * scale) >>> (31 - local.O3DGC_AC_BM_LENGTH_SHIFT); // set frequency of model updates this.m_updateCycle = (5 * this.m_updateCycle) >>> 2; if (this.m_updateCycle > 64) { this.m_updateCycle = 64; } this.m_bitsUntilUpdate = this.m_updateCycle; }; // AdaptiveDataModel class module.AdaptiveDataModel = function () { this.m_buffer = {}; this.m_distribution = {}; this.m_symbolCount = {}; this.m_decoderTable = {}; this.m_totalCount = 0; this.m_updateCycle = 0; this.m_symbolsUntilUpdate = 0; this.m_dataSymbols = 0; this.m_lastSymbol = 0; this.m_tableSize = 0; this.m_tableShift = 0; }; module.AdaptiveDataModel.prototype.Update = function () { var n, sum, s, scale, k, max_cycle, w; // halve counts when a threshold is reached if ((this.m_totalCount += this.m_updateCycle) > local.O3DGC_AC_DM_MAX_COUNT) { this.m_totalCount = 0; for (n = 0; n < this.m_dataSymbols; ++n) { this.m_totalCount += (this.m_symbolCount[n] = (this.m_symbolCount[n] + 1) >>> 1); } } // compute cumulative distribution, decoder table sum = 0; s = 0; scale = Math.floor(0x80000000 / this.m_totalCount); if (this.m_tableSize === 0) { for (k = 0; k < this.m_dataSymbols; ++k) { this.m_distribution[k] = (scale * sum) >>> (31 - local.O3DGC_AC_DM_LENGTH_SHIFT); sum += this.m_symbolCount[k]; } } else { for (k = 0; k < this.m_dataSymbols; ++k) { this.m_distribution[k] = (scale * sum) >>> (31 - local.O3DGC_AC_DM_LENGTH_SHIFT); sum += this.m_symbolCount[k]; w = this.m_distribution[k] >>> this.m_tableShift; while (s < w) { this.m_decoderTable[++s] = k - 1; } } this.m_decoderTable[0] = 0; while (s <= this.m_tableSize) { this.m_decoderTable[++s] = this.m_dataSymbols - 1; } } // set frequency of model updates this.m_updateCycle = (5 * this.m_updateCycle) >>> 2; max_cycle = ((this.m_dataSymbols + 6) << 3) >>> 0; if (this.m_updateCycle > max_cycle) { this.m_updateCycle = max_cycle; } this.m_symbolsUntilUpdate = this.m_updateCycle; }; module.AdaptiveDataModel.prototype.Reset = function () { var k; if (this.m_dataSymbols === 0) { return; } // restore probability estimates to uniform distribution this.m_totalCount = 0; this.m_updateCycle = this.m_dataSymbols; for (k = 0; k < this.m_dataSymbols; ++k) { this.m_symbolCount[k] = 1; } this.Update(); this.m_symbolsUntilUpdate = this.m_updateCycle = (this.m_dataSymbols + 6) >>> 1; }; module.AdaptiveDataModel.prototype.SetAlphabet = function (number_of_symbols) { if ((number_of_symbols < 2) || (number_of_symbols > (1 << 11))) { Console.log("invalid number of data symbols"); return module.O3DGC_ERROR_AC; } if (this.m_dataSymbols !== number_of_symbols) { // assign memory for data model this.m_dataSymbols = number_of_symbols; this.m_lastSymbol = this.m_dataSymbols - 1; // define size of table for fast decoding if (this.m_dataSymbols > 16) { var table_bits = 3; while (this.m_dataSymbols > ((1 << (table_bits + 2)) >>> 0)) { ++table_bits; } this.m_tableSize = (1 << table_bits) >>> 0; this.m_tableShift = local.O3DGC_AC_DM_LENGTH_SHIFT - table_bits; this.m_buffer = new ArrayBuffer(4 * (2 * this.m_dataSymbols + this.m_tableSize + 2)); this.m_distribution = new Uint32Array(this.m_buffer, 0, this.m_dataSymbols); this.m_symbolCount = new Uint32Array(this.m_buffer, 4 * this.m_dataSymbols, this.m_dataSymbols); this.m_decoderTable = new Uint32Array(this.m_buffer, 8 * this.m_dataSymbols, this.m_tableSize + 2); } else {// small alphabet: no table needed this.m_tableSize = this.m_tableShift = 0; this.m_buffer = new ArrayBuffer(4 * 2 * this.m_dataSymbols); this.m_distribution = new Uint32Array(this.m_buffer, 0, this.m_dataSymbols); this.m_symbolCount = new Uint32Array(this.m_buffer, 4 * this.m_dataSymbols, this.m_dataSymbols); this.m_decoderTable = {}; } } this.Reset(); // initialize model return module.O3DGC_OK; }; // ArithmeticDecoder class module.ArithmeticDecoder = function () { this.m_codeBuffer = {}; this.m_acShift = 0; this.m_base = 0; this.m_value = 0; this.m_length = 0; // arithmetic coding state this.m_bufferSize = 0; this.m_mode = 0; // mode: 0 = undef, 1 = encoder, 2 = decoder }; module.ArithmeticDecoder.prototype.SetBuffer = function (max_code_bytes, user_buffer) { if (max_code_bytes === 0) { Console.log("invalid codec buffer size"); return module.O3DGC_ERROR_AC; } if (this.m_mode !== 0) { Console.log("cannot set buffer while encoding or decoding"); return module.O3DGC_ERROR_AC; } this.m_bufferSize = max_code_bytes; this.m_codeBuffer = user_buffer; }; module.ArithmeticDecoder.prototype.StartDecoder = function () { if (this.m_mode !== 0) { Console.log("cannot start decoder"); return module.O3DGC_ERROR_AC; } if (this.m_bufferSize === 0) { Console.log("no code buffer set"); return module.O3DGC_ERROR_AC; } // initialize decoder: interval, pointer, initial code value this.m_mode = 2; this.m_length = local.O3DGC_AC_MAX_LENGTH; this.m_acShift = 3; this.m_value = ((this.m_codeBuffer[0] << 24) | (this.m_codeBuffer[1] << 16) | (this.m_codeBuffer[2] << 8) | (this.m_codeBuffer[3])) >>> 0; }; module.ArithmeticDecoder.prototype.StopDecoder = function () { if (this.m_mode !== 2) { Console.log("invalid to stop decoder"); return module.O3DGC_ERROR_AC; } this.m_mode = 0; }; module.ArithmeticDecoder.prototype.GetBit = function () { this.m_length >>>= 1; // halve interval var bit = (this.m_value >= this.m_length); // decode bit if (bit) { this.m_value -= this.m_length; // move base } if (this.m_length < local.O3DGC_AC_MIN_LENGTH) { this.RenormDecInterval(); // renormalization } return bit; }; module.ArithmeticDecoder.prototype.GetBits = function (bits) { var s = Math.floor(this.m_value / (this.m_length >>>= bits)); // decode symbol, change length this.m_value -= this.m_length * s; // update interval if (this.m_length < local.O3DGC_AC_MIN_LENGTH) { this.RenormDecInterval(); // renormalization } return s; }; module.ArithmeticDecoder.prototype.DecodeStaticBitModel = function (M) { var x, bit; x = M.m_bit0Prob * (this.m_length >>> local.O3DGC_AC_BM_LENGTH_SHIFT); // product l x p0 bit = (this.m_value >= x); // decision // update & shift interval if (!bit) { this.m_length = x; } else { this.m_value -= x; // shifted interval base = 0 this.m_length -= x; } if (this.m_length < local.O3DGC_AC_MIN_LENGTH) { this.RenormDecInterval(); // renormalization } return bit; // return data bit value }; module.ArithmeticDecoder.prototype.DecodeAdaptiveBitModel = function (M) { var x, bit; x = M.m_bit0Prob * (this.m_length >>> local.O3DGC_AC_BM_LENGTH_SHIFT); // product l x p0 bit = (this.m_value >= x); // decision // update interval if (!bit) { this.m_length = x; ++M.m_bit0Count; } else { this.m_value -= x; this.m_length -= x; } if (this.m_length < local.O3DGC_AC_MIN_LENGTH) { this.RenormDecInterval(); // renormalization } if (--M.m_bitsUntilUpdate === 0) { M.Update(); // periodic model update } return bit; // return data bit value }; module.ArithmeticDecoder.prototype.DecodeAdaptiveDataModel = function (M) { var n, s, x, y, t, dv, z, m; y = this.m_length; if (M.m_tableSize > 0) { // use table look-up for faster decoding dv = Math.floor(this.m_value / (this.m_length >>>= local.O3DGC_AC_DM_LENGTH_SHIFT)); t = dv >>> M.m_tableShift; s = M.m_decoderTable[t]; // initial decision based on table look-up n = M.m_decoderTable[t + 1] + 1; while (n > s + 1) { // finish with bisection search m = (s + n) >>> 1; if (M.m_distribution[m] > dv) { n = m; } else { s = m; } } // compute products x = M.m_distribution[s] * this.m_length; if (s !== M.m_lastSymbol) { y = M.m_distribution[s + 1] * this.m_length; } } else { // decode using only multiplications x = s = 0; this.m_length >>>= local.O3DGC_AC_DM_LENGTH_SHIFT; m = (n = M.m_dataSymbols) >>> 1; // decode via bisection search do { z = this.m_length * M.m_distribution[m]; if (z > this.m_value) { n = m; y = z; // value is smaller } else { s = m; x = z; // value is larger or equal } } while ((m = (s + n) >>> 1) !== s); } this.m_value -= x; // update interval this.m_length = y - x; if (this.m_length < local.O3DGC_AC_MIN_LENGTH) { this.RenormDecInterval(); // renormalization } ++M.m_symbolCount[s]; if (--M.m_symbolsUntilUpdate === 0) { M.Update(false); // periodic model update } return s; }; module.ArithmeticDecoder.prototype.ExpGolombDecode = function (k, bModel0, bModel1) { var symbol, binary_symbol, l; symbol = 0; binary_symbol = 0; do { l = this.DecodeAdaptiveBitModel(bModel1); if (l) { symbol += (1 << k) >>> 0; k++; } } while (l); while (k--) { //next binary part if (this.DecodeStaticBitModel(bModel0)) { binary_symbol = (binary_symbol | (1 << k)) >>> 0; } } return (symbol + binary_symbol); }; module.ArithmeticDecoder.prototype.RenormDecInterval = function () { do { // read least-significant byte this.m_value = ((this.m_value << 8) | this.m_codeBuffer[++this.m_acShift]) >>> 0; this.m_length = (this.m_length << 8) >>> 0; } while (this.m_length < local.O3DGC_AC_MIN_LENGTH); // length multiplied by 256 }; module.ArithmeticDecoder.prototype.DecodeIntACEGC = function (mModelValues, bModel0, bModel1, exp_k, M) { var uiValue = this.DecodeAdaptiveDataModel(mModelValues); if (uiValue === M) { uiValue += this.ExpGolombDecode(exp_k, bModel0, bModel1); } return UIntToInt(uiValue); }; module.ArithmeticDecoder.prototype.DecodeUIntACEGC = function (mModelValues, bModel0, bModel1, exp_k, M) { var uiValue = this.DecodeAdaptiveDataModel(mModelValues); if (uiValue === M) { uiValue += this.ExpGolombDecode(exp_k, bModel0, bModel1); } return uiValue; }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // FIFO class module.FIFO = function () { this.m_data = {}; this.m_allocated = 0; this.m_size = 0; this.m_start = 0; this.m_end = 0; }; module.FIFO.prototype.Clear = function () { this.m_start = this.m_end = this.m_size = 0; }; module.FIFO.prototype.GetAllocatedSize = function () { return this.m_allocated; }; module.FIFO.prototype.GetSize = function () { return this.m_size; }; module.FIFO.prototype.Allocate = function (size) { if (size > this.m_allocated) { this.m_allocated = size; this.m_data = new Int32Array(this.m_allocated); } this.Clear(); return module.O3DGC_OK; }; module.FIFO.prototype.PopFirst = function () { --this.m_size; var current = this.m_start++; if (this.m_start === this.m_allocated) { this.m_end = 0; } return this.m_data[current]; }; module.FIFO.prototype.PushBack = function (value) { --this.m_size; this.m_data[this.m_end] = value; ++this.m_size; ++this.m_end; if (this.m_end === this.m_allocated) { this.m_end = 0; } }; // IndexedFaceSet class module.IndexedFaceSet = function () { this.m_nCoordIndex = 0; this.m_nCoord = 0; this.m_nNormal = 0; this.m_numFloatAttributes = 0; this.m_numIntAttributes = 0; this.m_creaseAngle = 30.0; this.m_ccw = true; this.m_solid = true; this.m_convex = true; this.m_isTriangularMesh = true; this.m_coordMin = new Float32Array(3); this.m_coordMax = new Float32Array(3); this.m_normalMin = new Float32Array(3); this.m_normalMax = new Float32Array(3); this.m_nFloatAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_nIntAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); this.m_dimFloatAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_dimIntAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); this.m_typeFloatAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_typeIntAttribute = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); this.m_minFloatAttributeBuffer = new ArrayBuffer(4 * local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES); this.m_minFloatAttribute = new Float32Array(this.m_minFloatAttributeBuffer); this.m_maxFloatAttributeBuffer = new ArrayBuffer(4 * local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES); this.m_maxFloatAttribute = new Float32Array(this.m_maxFloatAttributeBuffer); this.m_coordIndex = {}; this.m_coord = {}; this.m_normal = {}; this.m_floatAttribute = []; this.m_intAttribute = []; }; module.IndexedFaceSet.prototype.GetNCoordIndex = function () { return this.m_nCoordIndex; }; module.IndexedFaceSet.prototype.GetNCoordIndex = function () { return this.m_nCoordIndex; }; module.IndexedFaceSet.prototype.GetNCoord = function () { return this.m_nCoord; }; module.IndexedFaceSet.prototype.GetNNormal = function () { return this.m_nNormal; }; module.IndexedFaceSet.prototype.GetNFloatAttribute = function (a) { return this.m_nFloatAttribute[a]; }; module.IndexedFaceSet.prototype.GetNIntAttribute = function (a) { return this.m_nIntAttribute[a]; }; module.IndexedFaceSet.prototype.GetNumFloatAttributes = function () { return this.m_numFloatAttributes; }; module.IndexedFaceSet.prototype.GetNumIntAttributes = function () { return this.m_numIntAttributes; }; module.IndexedFaceSet.prototype.GetCoordMinArray = function () { return this.m_coordMin; }; module.IndexedFaceSet.prototype.GetCoordMaxArray = function () { return this.m_coordMax; }; module.IndexedFaceSet.prototype.GetNormalMinArray = function () { return this.m_normalMin; }; module.IndexedFaceSet.prototype.GetNormalMaxArray = function () { return this.m_normalMax; }; module.IndexedFaceSet.prototype.GetFloatAttributeMinArray = function (a) { return (new Float32Array(this.m_minFloatAttributeBuffer, a * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES * 4, this.GetFloatAttributeDim(a))); }; module.IndexedFaceSet.prototype.GetFloatAttributeMaxArray = function (a) { return (new Float32Array(this.m_maxFloatAttributeBuffer, a * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES * 4, this.GetFloatAttributeDim(a))); }; module.IndexedFaceSet.prototype.GetFloatAttributeDim = function (a) { return this.m_dimFloatAttribute[a]; }; module.IndexedFaceSet.prototype.GetIntAttributeDim = function (a) { return this.m_dimIntAttribute[a]; }; module.IndexedFaceSet.prototype.GetFloatAttributeType = function (a) { return this.m_typeFloatAttribute[a]; }; module.IndexedFaceSet.prototype.GetIntAttributeType = function (a) { return this.m_typeIntAttribute[a]; }; module.IndexedFaceSet.prototype.GetFloatAttributeMax = function (a, dim) { return this.m_maxFloatAttribute[a * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim]; }; module.IndexedFaceSet.prototype.GetCreaseAngle = function () { return this.m_creaseAngle; }; module.IndexedFaceSet.prototype.GetCreaseAngle = function () { return this.m_creaseAngle; }; module.IndexedFaceSet.prototype.GetCCW = function () { return this.m_ccw; }; module.IndexedFaceSet.prototype.GetSolid = function () { return this.m_solid; }; module.IndexedFaceSet.prototype.GetConvex = function () { return this.m_convex; }; module.IndexedFaceSet.prototype.GetIsTriangularMesh = function () { return this.m_isTriangularMesh; }; module.IndexedFaceSet.prototype.GetCoordIndex = function () { return this.m_coordIndex; }; module.IndexedFaceSet.prototype.GetCoordIndex = function () { return this.m_coordIndex; }; module.IndexedFaceSet.prototype.GetCoord = function () { return this.m_coord; }; module.IndexedFaceSet.prototype.GetNormal = function () { return this.m_normal; }; module.IndexedFaceSet.prototype.GetFloatAttribute = function (a) { return this.m_floatAttribute[a]; }; module.IndexedFaceSet.prototype.GetIntAttribute = function (a) { return this.m_intAttribute[a]; }; module.IndexedFaceSet.prototype.SetNCoordIndex = function (nCoordIndex) { this.m_nCoordIndex = nCoordIndex; }; module.IndexedFaceSet.prototype.SetNNormalIndex = function (nNormalIndex) { }; module.IndexedFaceSet.prototype.SetNormalPerVertex = function (perVertex) { }; module.IndexedFaceSet.prototype.SetNFloatAttributeIndex = function (nFloatAttributeIndex) { }; module.IndexedFaceSet.prototype.SetNIntAttributeIndex = function (nIntAttributeIndex) { }; module.IndexedFaceSet.prototype.SetFloatAttributePerVertex = function (perVertex) { }; module.IndexedFaceSet.prototype.SetIntAttributePerVertex = function (perVertex) { }; module.IndexedFaceSet.prototype.SetNCoord = function (nCoord) { this.m_nCoord = nCoord; }; module.IndexedFaceSet.prototype.SetNNormal = function (nNormal) { this.m_nNormal = nNormal; }; module.IndexedFaceSet.prototype.SetNumFloatAttributes = function (numFloatAttributes) { this.m_numFloatAttributes = numFloatAttributes; }; module.IndexedFaceSet.prototype.SetNumIntAttributes = function (numIntAttributes) { this.m_numIntAttributes = numIntAttributes; }; module.IndexedFaceSet.prototype.SetCreaseAngle = function (creaseAngle) { this.m_creaseAngle = creaseAngle; }; module.IndexedFaceSet.prototype.SetCCW = function (ccw) { this.m_ccw = ccw; }; module.IndexedFaceSet.prototype.SetSolid = function (solid) { this.m_solid = solid; }; module.IndexedFaceSet.prototype.SetConvex = function (convex) { this.m_convex = convex; }; module.IndexedFaceSet.prototype.SetIsTriangularMesh = function (isTriangularMesh) { this.m_isTriangularMesh = isTriangularMesh; }; module.IndexedFaceSet.prototype.SetCoordMin = function (j, min) { this.m_coordMin[j] = min; }; module.IndexedFaceSet.prototype.SetCoordMax = function (j, max) { this.m_coordMax[j] = max; }; module.IndexedFaceSet.prototype.SetNormalMin = function (j, min) { this.m_normalMin[j] = min; }; module.IndexedFaceSet.prototype.SetNormalMax = function (j, max) { this.m_normalMax[j] = max; }; module.IndexedFaceSet.prototype.SetNFloatAttribute = function (a, nFloatAttribute) { this.m_nFloatAttribute[a] = nFloatAttribute; }; module.IndexedFaceSet.prototype.SetNIntAttribute = function (a, nIntAttribute) { this.m_nIntAttribute[a] = nIntAttribute; }; module.IndexedFaceSet.prototype.SetFloatAttributeDim = function (a, d) { this.m_dimFloatAttribute[a] = d; }; module.IndexedFaceSet.prototype.SetIntAttributeDim = function (a, d) { this.m_dimIntAttribute[a] = d; }; module.IndexedFaceSet.prototype.SetFloatAttributeType = function (a, d) { this.m_typeFloatAttribute[a] = d; }; module.IndexedFaceSet.prototype.SetIntAttributeType = function (a, d) { this.m_typeIntAttribute[a] = d; }; module.IndexedFaceSet.prototype.SetFloatAttributeMin = function (a, dim, min) { this.m_minFloatAttribute[a * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim] = min; }; module.IndexedFaceSet.prototype.SetFloatAttributeMax = function (a, dim, max) { this.m_maxFloatAttribute[a * local.O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES + dim] = max; }; module.IndexedFaceSet.prototype.SetCoordIndex = function (coordIndex) { this.m_coordIndex = coordIndex; }; module.IndexedFaceSet.prototype.SetCoord = function (coord) { this.m_coord = coord; }; module.IndexedFaceSet.prototype.SetNormal = function (normal) { this.m_normal = normal; }; module.IndexedFaceSet.prototype.SetFloatAttribute = function (a, floatAttribute) { this.m_floatAttribute[a] = floatAttribute; }; module.IndexedFaceSet.prototype.SetIntAttribute = function (a, intAttribute) { this.m_intAttribute[a] = intAttribute; }; // SC3DMCEncodeParams class module.SC3DMCEncodeParams = function () { var a; this.m_numFloatAttributes = 0; this.m_numIntAttributes = 0; this.m_floatAttributeQuantBits = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_floatAttributePredMode = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); this.m_intAttributePredMode = new Uint32Array(local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); this.m_encodeMode = local.O3DGC_SC3DMC_ENCODE_MODE_TFAN; this.m_streamTypeMode = local.O3DGC_STREAM_TYPE_ASCII; this.m_coordQuantBits = 14; this.m_normalQuantBits = 8; this.m_coordPredMode = local.O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION; this.m_normalPredMode = local.O3DGC_SC3DMC_SURF_NORMALS_PREDICTION; for (a = 0; a < local.O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES; ++a) { this.m_floatAttributePredMode[a] = local.O3DGC_SC3DMC_PARALLELOGRAM_PREDICTION; } for (a = 0; a < local.O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES; ++a) { this.m_intAttributePredMode[a] = local.O3DGC_SC3DMC_DIFFERENTIAL_PREDICTION; } }; module.SC3DMCEncodeParams.prototype.GetStreamType = function () { return this.m_streamTypeMode; }; module.SC3DMCEncodeParams.prototype.GetEncodeMode = function () { return this.m_encodeMode; }; module.SC3DMCEncodeParams.prototype.GetNumFloatAttributes = function () { return this.m_numFloatAttributes; }; module.SC3DMCEncodeParams.prototype.GetNumIntAttributes = function () { return this.m_numIntAttributes; }; module.SC3DMCEncodeParams.prototype.GetCoordQuantBits = function () { return this.m_coordQuantBits; }; module.SC3DMCEncodeParams.prototype.GetNormalQuantBits = function () { return this.m_normalQuantBits; }; module.SC3DMCEncodeParams.prototype.GetFloatAttributeQuantBits = function (a) { return this.m_floatAttributeQuantBits[a]; }; module.SC3DMCEncodeParams.prototype.GetCoordPredMode = function () { return this.m_coordPredMode; }; module.SC3DMCEncodeParams.prototype.GetNormalPredMode = function () { return this.m_normalPredMode; }; module.SC3DMCEncodeParams.prototype.GetFloatAttributePredMode = function (a) { return this.m_floatAttributePredMode[a]; }; module.SC3DMCEncodeParams.prototype.GetIntAttributePredMode = function (a) { return this.m_intAttributePredMode[a]; }; module.SC3DMCEncodeParams.prototype.GetCoordPredMode = function () { return this.m_coordPredMode; }; module.SC3DMCEncodeParams.prototype.GetNormalPredMode = function () { return this.m_normalPredMode; }; module.SC3DMCEncodeParams.prototype.GetFloatAttributePredMode = function (a) { return this.m_floatAttributePredMode[a]; }; module.SC3DMCEncodeParams.prototype.GetIntAttributePredMode = function (a) { return this.m_intAttributePredMode[a]; }; module.SC3DMCEncodeParams.prototype.SetStreamType = function (streamTypeMode) { this.m_streamTypeMode = streamTypeMode; }; module.SC3DMCEncodeParams.prototype.SetEncodeMode = function (encodeMode) { this.m_encodeMode = encodeMode; }; module.SC3DMCEncodeParams.prototype.SetNumFloatAttributes = function (numFloatAttributes) { this.m_numFloatAttributes = numFloatAttributes; }; module.SC3DMCEncodeParams.prototype.SetNumIntAttributes = function (numIntAttributes) { this.m_numIntAttributes = numIntAttributes; }; module.SC3DMCEncodeParams.prototype.SetCoordQuantBits = function (coordQuantBits) { this.m_coordQuantBits = coordQuantBits; }; module.SC3DMCEncodeParams.prototype.SetNormalQuantBits = function (normalQuantBits) { this.m_normalQuantBits = normalQuantBits; }; module.SC3DMCEncodeParams.prototype.SetFloatAttributeQuantBits = function (a, q) { this.m_floatAttributeQuantBits[a] = q; }; module.SC3DMCEncodeParams.prototype.SetCoordPredMode = function (coordPredMode) { this.m_coordPredMode = coordPredMode; }; module.SC3DMCEncodeParams.prototype.SetNormalPredMode = function (normalPredMode) { this.m_normalPredMode = normalPredMode; }; module.SC3DMCEncodeParams.prototype.SetFloatAttributePredMode = function (a, p) { this.m_floatAttributePredMode[a] = p; }; module.SC3DMCEncodeParams.prototype.SetIntAttributePredMode = function (a, p) { this.m_intAttributePredMode[a] = p; }; // AdjacencyInfo class module.AdjacencyInfo = function () { this.m_neighborsSize = 0; // actual allocated size for m_neighbors this.m_numNeighborsSize = 0; // actual allocated size for m_numNeighbors this.m_numElements = 0; // number of elements this.m_neighbors = {}; this.m_numNeighbors = {}; }; module.AdjacencyInfo.prototype.Allocate = function (numNeighborsSize, neighborsSize) { this.m_numElements = numNeighborsSize; if (neighborsSize > this.m_neighborsSize) { this.m_neighborsSize = neighborsSize; this.m_neighbors = new Int32Array(this.m_neighborsSize); } if (numNeighborsSize > this.m_numNeighborsSize) { this.m_numNeighborsSize = numNeighborsSize; this.m_numNeighbors = new Int32Array(this.m_numNeighborsSize); } return module.O3DGC_OK; }; module.AdjacencyInfo.prototype.AllocateNumNeighborsArray = function (numElements) { if (numElements > this.m_numNeighborsSize) { this.m_numNeighborsSize = numElements; this.m_numNeighbors = new Int32Array(this.m_numNeighborsSize); } this.m_numElements = numElements; return module.O3DGC_OK; }; module.AdjacencyInfo.prototype.AllocateNeighborsArray = function () { var i; for (i = 1; i < this.m_numElements; ++i) { this.m_numNeighbors[i] += this.m_numNeighbors[i - 1]; } if (this.m_numNeighbors[this.m_numElements - 1] > this.m_neighborsSize) { this.m_neighborsSize = this.m_numNeighbors[this.m_numElements - 1]; this.m_neighbors = new Int32Array(this.m_neighborsSize); } return module.O3DGC_OK; }; module.AdjacencyInfo.pr