Skip to content

Instantly share code, notes, and snippets.

@sunetos
Created January 12, 2010 21:00
Show Gist options
  • Save sunetos/275610 to your computer and use it in GitHub Desktop.
Save sunetos/275610 to your computer and use it in GitHub Desktop.
/**
* @preserve
* Adamia 3D Engine v0.1
* Copyright (c) 2010 Adam R. Smith
* Licensed under the new BSD License:
* http://www.opensource.org/licenses/bsd-license.php
*
* Project home: http://code.google.com/p/adamia-3d/
*
* Date: 01/12/2010
*/
if (typeof(a3d) == 'undefined') {
/** @namespace */ a3d = {};
}
// Taken from http://ejohn.org/blog/simple-javascript-inheritance/
// Inspired by base2 and Prototype
(function(){
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
/** @class */
this.Class = function(){};
// Create a new Class that inherits from this class
Class.extend = function(prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] = typeof prop[name] == "function" &&
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
(function(name, fn){
return function() {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name]) :
prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if ( !initializing && this.init )
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
/**
* Enum for big or little endian.
* @enum {number}
*/
a3d.Endian = {
BIG: 0
, LITTLE: 1
};
/**
* Attempt to imitate AS3's ByteArray as very high-performance javascript.
* I aliased the functions to have shorter names, like ReadUInt32 as well as ReadUnsignedInt.
* I used some code from http://fhtr.blogspot.com/2009/12/3d-models-and-parsing-binary-data-with.html
* to kick-start it, but I added optimizations and support both big and little endian.
* Note that you cannot change the endianness after construction.
* @extends Class
*/
a3d.ByteArray = Class.extend({
data: ''
, length: 0
, pos: 0
, pow: Math.pow
, endian: a3d.Endian.BIG
, TWOeN23: Math.pow(2, -23)
, TWOeN52: Math.pow(2, -52)
/** @constructor */
, init: function(data, endian) {
this.data = (data !== undefined) ? data : '';
if (endian !== undefined) this.endian = endian;
this.length = data.length;
// Cache the function pointers based on endianness.
// This avoids doing an if-statement in every function call.
var funcExt = (endian == a3d.Endian.BIG) ? 'BE' : 'LE';
var funcs = ['readInt32', 'readInt16', 'readUInt32', 'readUInt16', 'readFloat32', 'readFloat64'];
for (var func in funcs) {
this[funcs[func]] = this[funcs[func] + funcExt];
}
// Add redundant members that match actionscript for compatibility
var funcMap = {readUnsignedByte: 'readByte', readUnsignedInt: 'readUInt32',
readFloat: 'readFloat32', readDouble: 'readFloat64', readShort: 'readInt16',
readBoolean: 'readBool', readInt: 'readInt32'};
for (var func in funcMap) {
this[func] = this[funcMap[func]];
}
}
, readByte: function() {
return (this.data.charCodeAt(this.pos++) & 0xFF);
}
, readBool: function() {
return (this.data.charCodeAt(this.pos++) & 0xFF) ? true : false;
}
, readUInt32BE: function() {
var data = this.data, pos = (this.pos += 4) - 4;
return ((data.charCodeAt(pos) & 0xFF) << 24) |
((data.charCodeAt(++pos) & 0xFF) << 16) |
((data.charCodeAt(++pos) & 0xFF) << 8) |
(data.charCodeAt(++pos) & 0xFF);
}
, readInt32BE: function() {
var data = this.data, pos = (this.pos += 4) - 4;
var x = ((data.charCodeAt(pos) & 0xFF) << 24) |
((data.charCodeAt(++pos) & 0xFF) << 16) |
((data.charCodeAt(++pos) & 0xFF) << 8) |
(data.charCodeAt(++pos) & 0xFF);
return (x >= 2147483648) ? x - 4294967296 : x;
}
, readUInt16BE: function() {
var data = this.data, pos = (this.pos += 2) - 2;
return ((data.charCodeAt(pos) & 0xFF) << 8) |
(data.charCodeAt(++pos) & 0xFF);
}
, readInt16BE: function() {
var data = this.data, pos = (this.pos += 2) - 2;
var x = ((data.charCodeAt(pos) & 0xFF) << 8) |
(data.charCodeAt(++pos) & 0xFF);
return (x >= 32768) ? x - 65536 : x;
}
, readFloat32BE: function() {
var data = this.data, pos = (this.pos += 4) - 4;
var b1 = data.charCodeAt(pos) & 0xFF,
b2 = data.charCodeAt(++pos) & 0xFF,
b3 = data.charCodeAt(++pos) & 0xFF,
b4 = data.charCodeAt(++pos) & 0xFF;
var sign = 1 - ((b1 >> 7) << 1); // sign = bit 0
var exp = (((b1 << 1) & 0xFF) | (b2 >> 7)) - 127; // exponent = bits 1..8
var sig = ((b2 & 0x7F) << 16) | (b3 << 8) | b4; // significand = bits 9..31
if (sig == 0 && exp == -127)
return 0.0;
return sign*(1 + this.TWOeN23*sig)*this.pow(2, exp);
}
, readFloat64BE: function() {
var data = this.data, pos = (this.pos += 8) - 8;
var b1 = data.charCodeAt(pos) & 0xFF,
b2 = data.charCodeAt(++pos) & 0xFF,
b3 = data.charCodeAt(++pos) & 0xFF,
b4 = data.charCodeAt(++pos) & 0xFF,
b5 = data.charCodeAt(++pos) & 0xFF,
b6 = data.charCodeAt(++pos) & 0xFF,
b7 = data.charCodeAt(++pos) & 0xFF,
b8 = data.charCodeAt(++pos) & 0xFF;
var sign = 1 - ((b1 >> 7) << 1); // sign = bit 0
var exp = (((b1 << 4) & 0x7FF) | (b2 >> 4)) - 1023; // exponent = bits 1..11
// This crazy toString() stuff works around the fact that js ints are
// only 32 bits and signed, giving us 31 bits to work with
var sig = (((b2 & 0xF) << 16) | (b3 << 8) | b4).toString(2) +
((b5 >> 7) ? '1' : '0') +
(((b5&0x7F) << 24) | (b6 << 16) | (b7 << 8) | b8).toString(2); // significand = bits 12..63
sig = parseInt(sig, 2);
if (sig == 0 && exp == -1023)
return 0.0;
return sign*(1.0 + this.TWOeN52*sig)*this.pow(2, exp);
}
, readUInt32LE: function() {
var data = this.data, pos = (this.pos += 4);
return ((data.charCodeAt(--pos) & 0xFF) << 24) |
((data.charCodeAt(--pos) & 0xFF) << 16) |
((data.charCodeAt(--pos) & 0xFF) << 8) |
(data.charCodeAt(--pos) & 0xFF);
}
, readInt32LE: function() {
var data = this.data, pos = (this.pos += 4);
var x = ((data.charCodeAt(--pos) & 0xFF) << 24) |
((data.charCodeAt(--pos) & 0xFF) << 16) |
((data.charCodeAt(--pos) & 0xFF) << 8) |
(data.charCodeAt(--pos) & 0xFF);
return (x >= 2147483648) ? x - 4294967296 : x;
}
, readUInt16LE: function() {
var data = this.data, pos = (this.pos += 2);
return ((data.charCodeAt(--pos) & 0xFF) << 8) |
(data.charCodeAt(--pos) & 0xFF);
}
, readInt16LE: function() {
var data = this.data, pos = (this.pos += 2);
var x = ((data.charCodeAt(--pos) & 0xFF) << 8) |
(data.charCodeAt(--pos) & 0xFF);
return (x >= 32768) ? x - 65536 : x;
}
, readFloat32LE: function() {
var data = this.data, pos = (this.pos += 4);
var b1 = data.charCodeAt(--pos) & 0xFF,
b2 = data.charCodeAt(--pos) & 0xFF,
b3 = data.charCodeAt(--pos) & 0xFF,
b4 = data.charCodeAt(--pos) & 0xFF;
var sign = 1 - ((b1 >> 7) << 1); // sign = bit 0
var exp = (((b1 << 1) & 0xFF) | (b2 >> 7)) - 127; // exponent = bits 1..8
var sig = ((b2 & 0x7F) << 16) | (b3 << 8) | b4; // significand = bits 9..31
if (sig == 0 && exp == -127)
return 0.0;
return sign*(1 + this.TWOeN23*sig)*this.pow(2, exp);
}
, readFloat64LE: function() {
var data = this.data, pos = (this.pos += 8);
var b1 = data.charCodeAt(--pos) & 0xFF,
b2 = data.charCodeAt(--pos) & 0xFF,
b3 = data.charCodeAt(--pos) & 0xFF,
b4 = data.charCodeAt(--pos) & 0xFF,
b5 = data.charCodeAt(--pos) & 0xFF,
b6 = data.charCodeAt(--pos) & 0xFF,
b7 = data.charCodeAt(--pos) & 0xFF,
b8 = data.charCodeAt(--pos) & 0xFF;
var sign = 1 - ((b1 >> 7) << 1); // sign = bit 0
var exp = (((b1 << 4) & 0x7FF) | (b2 >> 4)) - 1023; // exponent = bits 1..11
// This crazy toString() stuff works around the fact that js ints are
// only 32 bits and signed, giving us 31 bits to work with
var sig = (((b2 & 0xF) << 16) | (b3 << 8) | b4).toString(2) +
((b5 >> 7) ? '1' : '0') +
(((b5&0x7F) << 24) | (b6 << 16) | (b7 << 8) | b8).toString(2); // significand = bits 12..63
sig = parseInt(sig, 2);
if (sig == 0 && exp == -1023)
return 0.0;
return sign*(1.0 + this.TWOeN52*sig)*this.pow(2, exp);
}
});
/*
Adamia 3D Engine v0.1
Copyright (c) 2010 Adam R. Smith
Licensed under the new BSD License:
http://www.opensource.org/licenses/bsd-license.php
Project home: http://code.google.com/p/adamia-3d/
Date: 01/12/2010
*/
if(typeof a3d=="undefined")a3d={};
(function(){var a=false,b=/xyz/.test(function(){})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(d){function c(){!a&&this.init&&this.init.apply(this,arguments)}var f=this.prototype;a=true;var g=new this;a=false;for(var e in d)g[e]=typeof d[e]=="function"&&typeof f[e]=="function"&&b.test(d[e])?function(h,i){return function(){var j=this._super;this._super=f[h];var k=i.apply(this,arguments);this._super=j;return k}}(e,d[e]):d[e];c.prototype=g;c.constructor=c;c.extend=arguments.callee;
return c}})();a3d.Endian={BIG:0,LITTLE:1};
a3d.ByteArray=Class.extend({data:"",length:0,pos:0,pow:Math.pow,endian:a3d.Endian.BIG,TWOeN23:Math.pow(2,-23),TWOeN52:Math.pow(2,-52),init:function(a,b){this.data=a!==undefined?a:"";if(b!==undefined)this.endian=b;this.length=a.length;a=b==a3d.Endian.BIG?"BE":"LE";b=["readInt32","readInt16","readUInt32","readUInt16","readFloat32","readFloat64"];for(var d in b)this[b[d]]=this[b[d]+a];a={readUnsignedByte:"readByte",readUnsignedInt:"readUInt32",readFloat:"readFloat32",readDouble:"readFloat64",readShort:"readInt16",
readBoolean:"readBool",readInt:"readInt32"};for(d in a)this[d]=this[a[d]]},readByte:function(){return this.data.charCodeAt(this.pos++)&255},readBool:function(){return this.data.charCodeAt(this.pos++)&255?true:false},readUInt32BE:function(){var a=this.data,b=(this.pos+=4)-4;return(a.charCodeAt(b)&255)<<24|(a.charCodeAt(++b)&255)<<16|(a.charCodeAt(++b)&255)<<8|a.charCodeAt(++b)&255},readInt32BE:function(){var a=this.data,b=(this.pos+=4)-4;a=(a.charCodeAt(b)&255)<<24|(a.charCodeAt(++b)&255)<<16|(a.charCodeAt(++b)&
255)<<8|a.charCodeAt(++b)&255;return a>=2147483648?a-4294967296:a},readUInt16BE:function(){var a=this.data,b=(this.pos+=2)-2;return(a.charCodeAt(b)&255)<<8|a.charCodeAt(++b)&255},readInt16BE:function(){var a=this.data,b=(this.pos+=2)-2;a=(a.charCodeAt(b)&255)<<8|a.charCodeAt(++b)&255;return a>=32768?a-65536:a},readFloat32BE:function(){var a=this.data,b=(this.pos+=4)-4,d=a.charCodeAt(b)&255,c=a.charCodeAt(++b)&255,f=a.charCodeAt(++b)&255;b=a.charCodeAt(++b)&255;a=(d<<1&255|c>>7)-127;c=(c&127)<<16|
f<<8|b;if(c==0&&a==-127)return 0;return(1-(d>>7<<1))*(1+this.TWOeN23*c)*this.pow(2,a)},readFloat64BE:function(){var a=this.data,b=(this.pos+=8)-8,d=a.charCodeAt(b)&255,c=a.charCodeAt(++b)&255,f=a.charCodeAt(++b)&255,g=a.charCodeAt(++b)&255,e=a.charCodeAt(++b)&255,h=a.charCodeAt(++b)&255,i=a.charCodeAt(++b)&255;b=a.charCodeAt(++b)&255;a=1-(d>>7<<1);d=(d<<4&2047|c>>4)-1023;c=((c&15)<<16|f<<8|g).toString(2)+(e>>7?"1":"0")+((e&127)<<24|h<<16|i<<8|b).toString(2);c=parseInt(c,2);if(c==0&&d==-1023)return 0;
return a*(1+this.TWOeN52*c)*this.pow(2,d)},readUInt32LE:function(){var a=this.data,b=this.pos+=4;return(a.charCodeAt(--b)&255)<<24|(a.charCodeAt(--b)&255)<<16|(a.charCodeAt(--b)&255)<<8|a.charCodeAt(--b)&255},readInt32LE:function(){var a=this.data,b=this.pos+=4;a=(a.charCodeAt(--b)&255)<<24|(a.charCodeAt(--b)&255)<<16|(a.charCodeAt(--b)&255)<<8|a.charCodeAt(--b)&255;return a>=2147483648?a-4294967296:a},readUInt16LE:function(){var a=this.data,b=this.pos+=2;return(a.charCodeAt(--b)&255)<<8|a.charCodeAt(--b)&
255},readInt16LE:function(){var a=this.data,b=this.pos+=2;a=(a.charCodeAt(--b)&255)<<8|a.charCodeAt(--b)&255;return a>=32768?a-65536:a},readFloat32LE:function(){var a=this.data,b=this.pos+=4,d=a.charCodeAt(--b)&255,c=a.charCodeAt(--b)&255,f=a.charCodeAt(--b)&255;b=a.charCodeAt(--b)&255;a=(d<<1&255|c>>7)-127;c=(c&127)<<16|f<<8|b;if(c==0&&a==-127)return 0;return(1-(d>>7<<1))*(1+this.TWOeN23*c)*this.pow(2,a)},readFloat64LE:function(){var a=this.data,b=this.pos+=8,d=a.charCodeAt(--b)&255,c=a.charCodeAt(--b)&
255,f=a.charCodeAt(--b)&255,g=a.charCodeAt(--b)&255,e=a.charCodeAt(--b)&255,h=a.charCodeAt(--b)&255,i=a.charCodeAt(--b)&255;b=a.charCodeAt(--b)&255;a=1-(d>>7<<1);d=(d<<4&2047|c>>4)-1023;c=((c&15)<<16|f<<8|g).toString(2)+(e>>7?"1":"0")+((e&127)<<24|h<<16|i<<8|b).toString(2);c=parseInt(c,2);if(c==0&&d==-1023)return 0;return a*(1+this.TWOeN52*c)*this.pow(2,d)}});
@velara3
Copy link

velara3 commented Dec 30, 2015

"I did not port any of the write() functions since my current project does not need them, but if there is enough demand I would consider porting them too. "

+1 please

@devlfm
Copy link

devlfm commented Mar 28, 2017

+1

@ohimark
Copy link

ohimark commented Feb 16, 2018

Hey man, a simple thank you is not enough !

THANK YOU For Sharing !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment