var pas = {}; var rtl = { quiet: false, debug_load_units: false, debug_rtti: false, debug: function(){ if (rtl.quiet || !console || !console.log) return; console.log(arguments); }, error: function(s){ rtl.debug('Error: ',s); throw s; }, warn: function(s){ rtl.debug('Warn: ',s); }, hasString: function(s){ return rtl.isString(s) && (s.length>0); }, isArray: function(a) { return Array.isArray(a); }, isFunction: function(f){ return typeof(f)==="function"; }, isModule: function(m){ return rtl.isObject(m) && rtl.hasString(m.$name) && (pas[m.$name]===m); }, isImplementation: function(m){ return rtl.isObject(m) && rtl.isModule(m.$module) && (m.$module.$impl===m); }, isNumber: function(n){ return typeof(n)==="number"; }, isObject: function(o){ var s=typeof(o); return (typeof(o)==="object") && (o!=null); }, isString: function(s){ return typeof(s)==="string"; }, getNumber: function(n){ return typeof(n)==="number"?n:NaN; }, getChar: function(c){ return ((typeof(c)==="string") && (c.length===1)) ? c : ""; }, getObject: function(o){ return ((typeof(o)==="object") || (typeof(o)==='function')) ? o : null; }, isPasClass: function(type){ return (rtl.isObject(type) && type.hasOwnProperty('$classname') && rtl.isObject(type.$module)); }, isPasClassInstance: function(type){ return (rtl.isObject(type) && rtl.isPasClass(type.$class)); }, hexStr: function(n,digits){ return ("000000000000000"+n.toString(16).toUpperCase()).slice(-digits); }, m_loading: 0, m_loading_intf: 1, m_intf_loaded: 2, m_loading_impl: 3, // loading all used unit m_initializing: 4, // running initialization m_initialized: 5, module: function(module_name, intfuseslist, intfcode, impluseslist, implcode){ if (rtl.debug_load_units) rtl.debug('rtl.module name="'+module_name+'" intfuses='+intfuseslist+' impluses='+impluseslist+' hasimplcode='+rtl.isFunction(implcode)); if (!rtl.hasString(module_name)) rtl.error('invalid module name "'+module_name+'"'); if (!rtl.isArray(intfuseslist)) rtl.error('invalid interface useslist of "'+module_name+'"'); if (!rtl.isFunction(intfcode)) rtl.error('invalid interface code of "'+module_name+'"'); if (!(impluseslist==undefined) && !rtl.isArray(impluseslist)) rtl.error('invalid implementation useslist of "'+module_name+'"'); if (!(implcode==undefined) && !rtl.isFunction(implcode)) rtl.error('invalid implementation code of "'+module_name+'"'); if (pas[module_name]) rtl.error('module "'+module_name+'" is already registered'); var module = pas[module_name] = { $name: module_name, $intfuseslist: intfuseslist, $impluseslist: impluseslist, $state: rtl.m_loading, $intfcode: intfcode, $implcode: implcode, $impl: null, $rtti: Object.create(rtl.tSectionRTTI) }; module.$rtti.$module = module; if (implcode) module.$impl = { $module: module, $rtti: module.$rtti }; }, exitcode: 0, run: function(module_name){ function doRun(){ if (!rtl.hasString(module_name)) module_name='program'; if (rtl.debug_load_units) rtl.debug('rtl.run module="'+module_name+'"'); rtl.initRTTI(); var module = pas[module_name]; if (!module) rtl.error('rtl.run module "'+module_name+'" missing'); rtl.loadintf(module); rtl.loadimpl(module); if (module_name=='program'){ if (rtl.debug_load_units) rtl.debug('running $main'); var r = pas.program.$main(); if (rtl.isNumber(r)) rtl.exitcode = r; } } if (rtl.showUncaughtExceptions) { try{ doRun(); } catch(re) { var errMsg = re.hasOwnProperty('$class') ? re.$class.$classname : ''; errMsg += ((errMsg) ? ': ' : '') + (re.hasOwnProperty('fMessage') ? re.fMessage : re); alert('Uncaught Exception : '+errMsg); rtl.exitCode = 216; } } else { doRun(); } return rtl.exitcode; }, loadintf: function(module){ if (module.$state>rtl.m_loading_intf) return; // already finished if (rtl.debug_load_units) rtl.debug('loadintf: "'+module.$name+'"'); if (module.$state===rtl.m_loading_intf) rtl.error('unit cycle detected "'+module.$name+'"'); module.$state=rtl.m_loading_intf; // load interfaces of interface useslist rtl.loaduseslist(module,module.$intfuseslist,rtl.loadintf); // run interface if (rtl.debug_load_units) rtl.debug('loadintf: run intf of "'+module.$name+'"'); module.$intfcode(module.$intfuseslist); // success module.$state=rtl.m_intf_loaded; // Note: units only used in implementations are not yet loaded (not even their interfaces) }, loaduseslist: function(module,useslist,f){ if (useslist==undefined) return; for (var i in useslist){ var unitname=useslist[i]; if (rtl.debug_load_units) rtl.debug('loaduseslist of "'+module.$name+'" uses="'+unitname+'"'); if (pas[unitname]==undefined) rtl.error('module "'+module.$name+'" misses "'+unitname+'"'); f(pas[unitname]); } }, loadimpl: function(module){ if (module.$state>=rtl.m_loading_impl) return; // already processing if (module.$state0){ o = this[newinstancefnname](fnname,args); } else { o = Object.create(this); } o.$class = this; // Note: o.$class === Object.getPrototypeOf(o) o.$init(); try{ o[fnname].apply(o,args); if (o.AfterConstruction) o.AfterConstruction(); } catch($e){ o.$destroy; throw $e; } return o; }; c.$destroy = function(fnname){ if (this.BeforeDestruction) this.BeforeDestruction(); this[fnname](); this.$final; }; rtl.initClass(c,parent,name,initfn); }, tObjectDestroy: "Destroy", free: function(obj,name){ if (obj[name]==null) return; obj[name].$destroy(rtl.tObjectDestroy); obj[name]=null; }, freeLoc: function(obj){ if (obj==null) return; obj.$destroy(rtl.tObjectDestroy); return null; }, is: function(instance,type){ return type.isPrototypeOf(instance) || (instance===type); }, isExt: function(instance,type,mode){ // mode===1 means instance must be a Pascal class instance // mode===2 means instance must be a Pascal class // Notes: // isPrototypeOf and instanceof return false on equal // isPrototypeOf does not work for Date.isPrototypeOf(new Date()) // so if isPrototypeOf is false test with instanceof // instanceof needs a function on right side if (instance == null) return false; // Note: ==null checks for undefined too if ((typeof(type) !== 'object') && (typeof(type) !== 'function')) return false; if (instance === type){ if (mode===1) return false; if (mode===2) return rtl.isPasClass(instance); return true; } if (type.isPrototypeOf && type.isPrototypeOf(instance)){ if (mode===1) return rtl.isPasClassInstance(instance); if (mode===2) return rtl.isPasClass(instance); return true; } if ((typeof type == 'function') && (instance instanceof type)) return true; return false; }, Exception: null, EInvalidCast: null, EAbstractError: null, ERangeError: null, raiseE: function(typename){ var t = rtl[typename]; if (t==null){ var mod = pas.SysUtils; if (!mod) mod = pas.sysutils; if (mod){ t = mod[typename]; if (!t) t = mod[typename.toLowerCase()]; if (!t) t = mod['Exception']; if (!t) t = mod['exception']; } } if (t){ if (t.Create){ throw t.$create("Create"); } else if (t.create){ throw t.$create("create"); } } if (typename === "EInvalidCast") throw "invalid type cast"; if (typename === "EAbstractError") throw "Abstract method called"; if (typename === "ERangeError") throw "range error"; throw typename; }, as: function(instance,type){ if((instance === null) || rtl.is(instance,type)) return instance; rtl.raiseE("EInvalidCast"); }, asExt: function(instance,type,mode){ if((instance === null) || rtl.isExt(instance,type,mode)) return instance; rtl.raiseE("EInvalidCast"); }, createInterface: function(module, name, guid, fnnames, ancestor, initfn){ //console.log('createInterface name="'+name+'" guid="'+guid+'" names='+fnnames); var i = ancestor?Object.create(ancestor):{}; module[name] = i; i.$module = module; i.$name = name; i.$fullname = module.$name+'.'+name; i.$guid = guid; i.$guidr = null; i.$names = fnnames?fnnames:[]; if (rtl.isFunction(initfn)){ // rtti if (rtl.debug_rtti) rtl.debug('createInterface '+i.$fullname); var t = i.$module.$rtti.$Interface(name,{ "interface": i, module: module }); i.$rtti = t; if (ancestor) t.ancestor = ancestor.$rtti; if (!t.ancestor) t.ancestor = null; initfn.call(i); } return i; }, strToGUIDR: function(s,g){ var p = 0; function n(l){ var h = s.substr(p,l); p+=l; return parseInt(h,16); } p+=1; // skip { g.D1 = n(8); p+=1; // skip - g.D2 = n(4); p+=1; // skip - g.D3 = n(4); p+=1; // skip - if (!g.D4) g.D4=[]; g.D4[0] = n(2); g.D4[1] = n(2); p+=1; // skip - for(var i=2; i<8; i++) g.D4[i] = n(2); return g; }, guidrToStr: function(g){ if (g.$intf) return g.$intf.$guid; var h = rtl.hexStr; var s='{'+h(g.D1,8)+'-'+h(g.D2,4)+'-'+h(g.D3,4)+'-'+h(g.D4[0],2)+h(g.D4[1],2)+'-'; for (var i=2; i<8; i++) s+=h(g.D4[i],2); s+='}'; return s; }, createTGUID: function(guid){ var TGuid = (pas.System)?pas.System.TGuid:pas.system.tguid; var g = rtl.strToGUIDR(guid,new TGuid()); return g; }, getIntfGUIDR: function(intfTypeOrVar){ if (!intfTypeOrVar) return null; if (!intfTypeOrVar.$guidr){ var g = rtl.createTGUID(intfTypeOrVar.$guid); if (!intfTypeOrVar.hasOwnProperty('$guid')) intfTypeOrVar = Object.getPrototypeOf(intfTypeOrVar); g.$intf = intfTypeOrVar; intfTypeOrVar.$guidr = g; } return intfTypeOrVar.$guidr; }, addIntf: function (aclass, intf, map){ function jmp(fn){ if (typeof(fn)==="function"){ return function(){ return fn.apply(this.$o,arguments); }; } else { return function(){ rtl.raiseE('EAbstractError'); }; } } if(!map) map = {}; var t = intf; var item = Object.create(t); aclass.$intfmaps[intf.$guid] = item; do{ var names = t.$names; if (!names) break; for (var i=0; i=minval) && (i<=maxval)) return i; rtl.raiseE('ERangeError'); }, rcc: function(c,minval,maxval){ // range check char if ((typeof(c)==='string') && (c.length===1)){ var i = c.charCodeAt(0); if ((i>=minval) && (i<=maxval)) return c; } rtl.raiseE('ERangeError'); }, rcSetCharAt: function(s,index,c){ // range check setCharAt if ((typeof(s)!=='string') || (index<0) || (index>=s.length)) rtl.raiseE('ERangeError'); return rtl.setCharAt(s,index,c); }, rcCharAt: function(s,index){ // range check charAt if ((typeof(s)!=='string') || (index<0) || (index>=s.length)) rtl.raiseE('ERangeError'); return s.charAt(index); }, rcArrR: function(arr,index){ // range check read array if (Array.isArray(arr) && (typeof(index)==='number') && (index>=0) && (index2){ // arr,index1,index2,... arr=arr[index]; for (var i=2; i=0) && (indexsrcarray.length) end = srcarray.length; if (index>=end) return []; if (type===0){ return srcarray.slice(index,end); } else { var a = []; a.length = end-index; rtl.arrayClone(type,srcarray,index,end,a,0); return a; } }, setCharAt: function(s,index,c){ return s.substr(0,index)+c+s.substr(index+1); }, getResStr: function(mod,name){ var rs = mod.$resourcestrings[name]; return rs.current?rs.current:rs.org; }, createSet: function(){ var s = {}; for (var i=0; i newlen){ return s.substring(0,newlen); } else if (s.repeat){ // Note: repeat needs ECMAScript6! return s+' '.repeat(newlen-oldlen); } else { while (oldlen=width) return s; if (s.repeat){ // Note: repeat needs ECMAScript6! return ' '.repeat(width-l) + s; } else { while (l2){ return rtl.spaceLeft(d.toFixed(p),w); } else { // exponent width var pad = ""; var ad = Math.abs(d); if (ad<1.0e+10) { pad='00'; } else if (ad<1.0e+100) { pad='0'; } if (arguments.length<2) { w=9; } else if (w<9) { w=9; } var p = w-8; var s=(d>0 ? " " : "" ) + d.toExponential(p); s=s.replace(/e(.)/,'E$1'+pad); return rtl.spaceLeft(s,w); } }, initRTTI: function(){ if (rtl.debug_rtti) rtl.debug('initRTTI'); // base types rtl.tTypeInfo = { name: "tTypeInfo" }; function newBaseTI(name,kind,ancestor){ if (!ancestor) ancestor = rtl.tTypeInfo; if (rtl.debug_rtti) rtl.debug('initRTTI.newBaseTI "'+name+'" '+kind+' ("'+ancestor.name+'")'); var t = Object.create(ancestor); t.name = name; t.kind = kind; rtl[name] = t; return t; }; function newBaseInt(name,minvalue,maxvalue,ordtype){ var t = newBaseTI(name,1 /* tkInteger */,rtl.tTypeInfoInteger); t.minvalue = minvalue; t.maxvalue = maxvalue; t.ordtype = ordtype; return t; }; newBaseTI("tTypeInfoInteger",1 /* tkInteger */); newBaseInt("shortint",-0x80,0x7f,0); newBaseInt("byte",0,0xff,1); newBaseInt("smallint",-0x8000,0x7fff,2); newBaseInt("word",0,0xffff,3); newBaseInt("longint",-0x80000000,0x7fffffff,4); newBaseInt("longword",0,0xffffffff,5); newBaseInt("nativeint",-0x10000000000000,0xfffffffffffff,6); newBaseInt("nativeuint",0,0xfffffffffffff,7); newBaseTI("char",2 /* tkChar */); newBaseTI("string",3 /* tkString */); newBaseTI("tTypeInfoEnum",4 /* tkEnumeration */,rtl.tTypeInfoInteger); newBaseTI("tTypeInfoSet",5 /* tkSet */); newBaseTI("double",6 /* tkDouble */); newBaseTI("boolean",7 /* tkBool */); newBaseTI("tTypeInfoProcVar",8 /* tkProcVar */); newBaseTI("tTypeInfoMethodVar",9 /* tkMethod */,rtl.tTypeInfoProcVar); newBaseTI("tTypeInfoArray",10 /* tkArray */); newBaseTI("tTypeInfoDynArray",11 /* tkDynArray */); newBaseTI("tTypeInfoPointer",15 /* tkPointer */); var t = newBaseTI("pointer",15 /* tkPointer */,rtl.tTypeInfoPointer); t.reftype = null; newBaseTI("jsvalue",16 /* tkJSValue */); newBaseTI("tTypeInfoRefToProcVar",17 /* tkRefToProcVar */,rtl.tTypeInfoProcVar); // member kinds rtl.tTypeMember = {}; function newMember(name,kind){ var m = Object.create(rtl.tTypeMember); m.name = name; m.kind = kind; rtl[name] = m; }; newMember("tTypeMemberField",1); // tmkField newMember("tTypeMemberMethod",2); // tmkMethod newMember("tTypeMemberProperty",3); // tmkProperty // base object for storing members: a simple object rtl.tTypeMembers = {}; // tTypeInfoStruct - base object for tTypeInfoClass, tTypeInfoRecord, tTypeInfoInterface var tis = newBaseTI("tTypeInfoStruct",0); tis.$addMember = function(name,ancestor,options){ if (rtl.debug_rtti){ if (!rtl.hasString(name) || (name.charAt()==='$')) throw 'invalid member "'+name+'", this="'+this.name+'"'; if (!rtl.is(ancestor,rtl.tTypeMember)) throw 'invalid ancestor "'+ancestor+':'+ancestor.name+'", "'+this.name+'.'+name+'"'; if ((options!=undefined) && (typeof(options)!='object')) throw 'invalid options "'+options+'", "'+this.name+'.'+name+'"'; }; var t = Object.create(ancestor); t.name = name; this.members[name] = t; this.names.push(name); if (rtl.isObject(options)){ for (var key in options) if (options.hasOwnProperty(key)) t[key] = options[key]; }; return t; }; tis.addField = function(name,type,options){ var t = this.$addMember(name,rtl.tTypeMemberField,options); if (rtl.debug_rtti){ if (!rtl.is(type,rtl.tTypeInfo)) throw 'invalid type "'+type+'", "'+this.name+'.'+name+'"'; }; t.typeinfo = type; this.fields.push(name); return t; }; tis.addFields = function(){ var i=0; while(i $mod.MaxConsoleLines) { CurrentCount -= 1; $impl.LinesParent.removeChild($impl.LinesParent.firstChild); }; $impl.LastLine = document.createElement("div"); $impl.LastLine.className = "pasconsole"; $impl.LinesParent.appendChild($impl.LastLine); }; $impl.WriteConsole = function (S, NewLine) { var CL = ""; CL = $impl.LastLine.innerText; CL = CL + ("" + S); $impl.LastLine.innerText = CL; if (NewLine) { if ($mod.ConsoleLinesToBrowserLog) window.console.log(CL); $impl.AppendLine(); }; }; }); rtl.module("SysUtils",["System","JS"],function () { "use strict"; var $mod = this; this.IntToStr = function (Value) { var Result = ""; Result = "" + Value; return Result; }; rtl.createClass($mod,"TFormatSettings",pas.System.TObject,function () { }); this.FormatSettings = null; $mod.$init = function () { $mod.FormatSettings = $mod.TFormatSettings.$create("Create"); }; }); rtl.module("math",["System","SysUtils"],function () { "use strict"; var $mod = this; this.DegToRad = function (deg) { var Result = 0.0; Result = deg * (Math.PI / 180.0); return Result; }; }); rtl.module("Mat4",["System","browserconsole","JS","math"],function () { "use strict"; var $mod = this; var $impl = $mod.$impl; rtl.createClass($mod,"TMat4",pas.System.TObject,function () { this.$init = function () { pas.System.TObject.$init.call(this); this.RawComponents = rtl.arraySetLength(null,0.0,4,4); }; this.$final = function () { this.RawComponents = undefined; pas.System.TObject.$final.call(this); }; this.Identity = function () { this.RawComponents[0][0] = 1.0; this.RawComponents[0][1] = 0.0; this.RawComponents[0][2] = 0.0; this.RawComponents[0][3] = 0.0; this.RawComponents[1][0] = 0.0; this.RawComponents[1][1] = 1.0; this.RawComponents[1][2] = 0.0; this.RawComponents[1][3] = 0.0; this.RawComponents[2][0] = 0.0; this.RawComponents[2][1] = 0.0; this.RawComponents[2][2] = 1.0; this.RawComponents[2][3] = 0.0; this.RawComponents[3][0] = 0.0; this.RawComponents[3][1] = 0.0; this.RawComponents[3][2] = 0.0; this.RawComponents[3][3] = 1.0; }; this.Translate = function (tx, ty, tz) { this.RawComponents[0][0] = 1.0; this.RawComponents[0][1] = 0.0; this.RawComponents[0][2] = 0.0; this.RawComponents[0][3] = 0.0; this.RawComponents[1][0] = 0.0; this.RawComponents[1][1] = 1.0; this.RawComponents[1][2] = 0.0; this.RawComponents[1][3] = 0.0; this.RawComponents[2][0] = 0.0; this.RawComponents[2][1] = 0.0; this.RawComponents[2][2] = 1.0; this.RawComponents[2][3] = 0.0; this.RawComponents[3][0] = tx; this.RawComponents[3][1] = ty; this.RawComponents[3][2] = tz; this.RawComponents[3][3] = 1.0; }; this.RotateZ = function (Angle) { $mod.SinCos(Angle,{a: 1, p: this.RawComponents[0], get: function () { return this.p[this.a]; }, set: function (v) { this.p[this.a] = v; }},{a: 0, p: this.RawComponents[0], get: function () { return this.p[this.a]; }, set: function (v) { this.p[this.a] = v; }}); this.RawComponents[0][2] = 0.0; this.RawComponents[0][3] = 0.0; this.RawComponents[1][0] = -this.RawComponents[0][1]; this.RawComponents[1][1] = this.RawComponents[0][0]; this.RawComponents[1][2] = 0.0; this.RawComponents[1][3] = 0.0; this.RawComponents[2][0] = 0.0; this.RawComponents[2][1] = 0.0; this.RawComponents[2][2] = 1.0; this.RawComponents[2][3] = 0.0; this.RawComponents[3][0] = 0.0; this.RawComponents[3][1] = 0.0; this.RawComponents[3][2] = 0.0; this.RawComponents[3][3] = 1.0; }; this.Ortho = function (Left, Right, Bottom, Top, zNear, zFar) { var rml = 0.0; var tmb = 0.0; var fmn = 0.0; rml = Right - Left; tmb = Top - Bottom; fmn = zFar - zNear; this.RawComponents[0][0] = 2.0 / rml; this.RawComponents[0][1] = 0.0; this.RawComponents[0][2] = 0.0; this.RawComponents[0][3] = 0.0; this.RawComponents[1][0] = 0.0; this.RawComponents[1][1] = 2.0 / tmb; this.RawComponents[1][2] = 0.0; this.RawComponents[1][3] = 0.0; this.RawComponents[2][0] = 0.0; this.RawComponents[2][1] = 0.0; this.RawComponents[2][2] = -2.0 / fmn; this.RawComponents[2][3] = 0.0; this.RawComponents[3][0] = -(Right + Left) / rml; this.RawComponents[3][1] = -(Top + Bottom) / tmb; this.RawComponents[3][2] = -(zFar + zNear) / fmn; this.RawComponents[3][3] = 1.0; }; this.Multiply = function (m) { var Result = null; Result = $mod.TMat4.$create("Identity"); Result.RawComponents[0][0] = (((m.RawComponents[0][0] * this.RawComponents[0][0]) + (m.RawComponents[0][1] * this.RawComponents[1][0])) + (m.RawComponents[0][2] * this.RawComponents[2][0])) + (m.RawComponents[0][3] * this.RawComponents[3][0]); Result.RawComponents[0][1] = (((m.RawComponents[0][0] * this.RawComponents[0][1]) + (m.RawComponents[0][1] * this.RawComponents[1][1])) + (m.RawComponents[0][2] * this.RawComponents[2][1])) + (m.RawComponents[0][3] * this.RawComponents[3][1]); Result.RawComponents[0][2] = (((m.RawComponents[0][0] * this.RawComponents[0][2]) + (m.RawComponents[0][1] * this.RawComponents[1][2])) + (m.RawComponents[0][2] * this.RawComponents[2][2])) + (m.RawComponents[0][3] * this.RawComponents[3][2]); Result.RawComponents[0][3] = (((m.RawComponents[0][0] * this.RawComponents[0][3]) + (m.RawComponents[0][1] * this.RawComponents[1][3])) + (m.RawComponents[0][2] * this.RawComponents[2][3])) + (m.RawComponents[0][3] * this.RawComponents[3][3]); Result.RawComponents[1][0] = (((m.RawComponents[1][0] * this.RawComponents[0][0]) + (m.RawComponents[1][1] * this.RawComponents[1][0])) + (m.RawComponents[1][2] * this.RawComponents[2][0])) + (m.RawComponents[1][3] * this.RawComponents[3][0]); Result.RawComponents[1][1] = (((m.RawComponents[1][0] * this.RawComponents[0][1]) + (m.RawComponents[1][1] * this.RawComponents[1][1])) + (m.RawComponents[1][2] * this.RawComponents[2][1])) + (m.RawComponents[1][3] * this.RawComponents[3][1]); Result.RawComponents[1][2] = (((m.RawComponents[1][0] * this.RawComponents[0][2]) + (m.RawComponents[1][1] * this.RawComponents[1][2])) + (m.RawComponents[1][2] * this.RawComponents[2][2])) + (m.RawComponents[1][3] * this.RawComponents[3][2]); Result.RawComponents[1][3] = (((m.RawComponents[1][0] * this.RawComponents[0][3]) + (m.RawComponents[1][1] * this.RawComponents[1][3])) + (m.RawComponents[1][2] * this.RawComponents[2][3])) + (m.RawComponents[1][3] * this.RawComponents[3][3]); Result.RawComponents[2][0] = (((m.RawComponents[2][0] * this.RawComponents[0][0]) + (m.RawComponents[2][1] * this.RawComponents[1][0])) + (m.RawComponents[2][2] * this.RawComponents[2][0])) + (m.RawComponents[2][3] * this.RawComponents[3][0]); Result.RawComponents[2][1] = (((m.RawComponents[2][0] * this.RawComponents[0][1]) + (m.RawComponents[2][1] * this.RawComponents[1][1])) + (m.RawComponents[2][2] * this.RawComponents[2][1])) + (m.RawComponents[2][3] * this.RawComponents[3][1]); Result.RawComponents[2][2] = (((m.RawComponents[2][0] * this.RawComponents[0][2]) + (m.RawComponents[2][1] * this.RawComponents[1][2])) + (m.RawComponents[2][2] * this.RawComponents[2][2])) + (m.RawComponents[2][3] * this.RawComponents[3][2]); Result.RawComponents[2][3] = (((m.RawComponents[2][0] * this.RawComponents[0][3]) + (m.RawComponents[2][1] * this.RawComponents[1][3])) + (m.RawComponents[2][2] * this.RawComponents[2][3])) + (m.RawComponents[2][3] * this.RawComponents[3][3]); Result.RawComponents[3][0] = (((m.RawComponents[3][0] * this.RawComponents[0][0]) + (m.RawComponents[3][1] * this.RawComponents[1][0])) + (m.RawComponents[3][2] * this.RawComponents[2][0])) + (m.RawComponents[3][3] * this.RawComponents[3][0]); Result.RawComponents[3][1] = (((m.RawComponents[3][0] * this.RawComponents[0][1]) + (m.RawComponents[3][1] * this.RawComponents[1][1])) + (m.RawComponents[3][2] * this.RawComponents[2][1])) + (m.RawComponents[3][3] * this.RawComponents[3][1]); Result.RawComponents[3][2] = (((m.RawComponents[3][0] * this.RawComponents[0][2]) + (m.RawComponents[3][1] * this.RawComponents[1][2])) + (m.RawComponents[3][2] * this.RawComponents[2][2])) + (m.RawComponents[3][3] * this.RawComponents[3][2]); Result.RawComponents[3][3] = (((m.RawComponents[3][0] * this.RawComponents[0][3]) + (m.RawComponents[3][1] * this.RawComponents[1][3])) + (m.RawComponents[3][2] * this.RawComponents[2][3])) + (m.RawComponents[3][3] * this.RawComponents[3][3]); return Result; }; this.CopyList = function () { var Result = []; var x = 0; var y = 0; var list = null; list = new Array(); for (x = 0; x <= 3; x++) for (y = 0; y <= 3; y++) list.push(this.RawComponents[x][y]); Result = list; return Result; }; }); this.SinCos = function (angle, sinus, cosinus) { sinus.set(Math.sin(angle)); cosinus.set(Math.cos(angle)); }; $mod.$init = function () { $impl.Matrix4x4Identity = $mod.TMat4.$create("Identity"); }; },null,function () { "use strict"; var $mod = this; var $impl = $mod.$impl; $impl.Matrix4x4Identity = null; }); rtl.module("MemoryBuffer",["System","JS"],function () { "use strict"; var $mod = this; rtl.createClass($mod,"TMemoryBuffer",pas.System.TObject,function () { this.$init = function () { pas.System.TObject.$init.call(this); this.byteBuffer = null; this.byteOffset = 0; this.floatBuffer = null; }; this.$final = function () { this.byteBuffer = undefined; this.floatBuffer = undefined; pas.System.TObject.$final.call(this); }; this.Create$1 = function (size) { this.byteBuffer = new Uint8Array(size); }; this.AddBytes = function (count, data) { this.byteBuffer.set(data,this.byteOffset); this.byteOffset = this.byteOffset + (count * 1); }; this.AddFloats = function (count, data) { var floatOffset = 0; floatOffset = Math.floor(this.byteOffset / 4); if (this.floatBuffer === null) this.floatBuffer = new Float32Array(this.byteBuffer.buffer,0,Math.floor(this.byteBuffer.byteLength / 4)); this.floatBuffer.set(data,floatOffset); this.byteOffset = this.byteOffset + (count * 4); }; }); }); rtl.module("webgl",["System","JS","Web"],function () { "use strict"; var $mod = this; }); rtl.module("GLTypes",["System","webgl","JS"],function () { "use strict"; var $mod = this; this.TVec2 = function (s) { if (s) { this.x = s.x; this.y = s.y; } else { this.x = 0.0; this.y = 0.0; }; this.$equal = function (b) { return (this.x === b.x) && (this.y === b.y); }; }; this.V2 = function (x, y) { var Result = new $mod.TVec2(); Result.x = x; Result.y = y; return Result; }; this.ToFloats$1 = function (v) { var Result = []; Result = rtl.arraySetLength(Result,0.0,2); Result[0] = v.x; Result[1] = v.y; return Result; }; this.RGBAb = function (r, g, b, a) { var Result = []; Result[0] = r; Result[1] = g; Result[2] = b; Result[3] = a; return Result; }; }); rtl.module("GLUtils",["System","Mat4","GLTypes","browserconsole","Web","webgl","JS","math","SysUtils"],function () { "use strict"; var $mod = this; var $impl = $mod.$impl; rtl.createClass($mod,"TShader",pas.System.TObject,function () { this.$init = function () { pas.System.TObject.$init.call(this); this.gl = null; this.vertexShader = null; this.fragmentShader = null; this.programID = null; }; this.$final = function () { this.gl = undefined; this.vertexShader = undefined; this.fragmentShader = undefined; this.programID = undefined; pas.System.TObject.$final.call(this); }; this.Create$1 = function (context, vertexShaderSource, fragmentShaderSource) { this.gl = context; this.vertexShader = this.CreateShader(this.gl.VERTEX_SHADER,vertexShaderSource); this.fragmentShader = this.CreateShader(this.gl.FRAGMENT_SHADER,fragmentShaderSource); }; this.Compile = function () { this.programID = this.gl.createProgram(); this.gl.attachShader(this.programID,this.vertexShader); this.gl.attachShader(this.programID,this.fragmentShader); }; this.Link = function () { this.gl.linkProgram(this.programID); if (!this.gl.getProgramParameter(this.programID,this.gl.LINK_STATUS)) { $impl.Fatal(this.gl.getProgramInfoLog(this.programID)); }; }; this.Use = function () { this.gl.useProgram(this.programID); }; this.BindAttribLocation = function (index, name) { this.gl.bindAttribLocation(this.programID,index,name); }; this.SetUniformMat4 = function (name, value) { var list = []; list = value.CopyList(); this.gl.uniformMatrix4fv(this.GetUniformLocation(name),false,list); $impl.GLFatal(this.gl,"gl.uniformMatrix4fv"); }; this.GetUniformLocation = function (name) { var Result = null; Result = this.gl.getUniformLocation(this.programID,name); $impl.GLFatal(this.gl,"gl.getUniformLocation"); return Result; }; this.CreateShader = function (theType, source) { var Result = null; var shader = null; shader = this.gl.createShader(theType); if (shader === null) $impl.Fatal("create shader failed"); this.gl.shaderSource(shader,source); this.gl.compileShader(shader); if (this.gl.getShaderParameter(shader,this.gl.COMPILE_STATUS)) { return shader; } else { $impl.Fatal$1(this.gl.getShaderInfoLog(shader)); }; return Result; }; }); this.GLSizeof = function (glType) { var Result = 0; var $tmp1 = glType; if (($tmp1 === WebGLRenderingContext.UNSIGNED_BYTE) || ($tmp1 === WebGLRenderingContext.BYTE)) { Result = 1} else if (($tmp1 === WebGLRenderingContext.SHORT) || ($tmp1 === WebGLRenderingContext.UNSIGNED_SHORT)) { Result = 2} else if (($tmp1 === WebGLRenderingContext.INT) || ($tmp1 === WebGLRenderingContext.UNSIGNED_INT)) { Result = 4} else if ($tmp1 === WebGLRenderingContext.FLOAT) { Result = 4} else { $impl.Fatal("GLSizeof type is invalid."); }; return Result; }; },null,function () { "use strict"; var $mod = this; var $impl = $mod.$impl; $impl.Fatal = function (messageString) { pas.System.Writeln("*** FATAL: ",messageString); return; }; $impl.Fatal$1 = function (messageString) { pas.System.Writeln("*** FATAL: ",messageString); return; }; $impl.GLFatal = function (gl, messageString) { var error = 0; error = gl.getError(); if (error !== WebGLRenderingContext.NO_ERROR) { var $tmp1 = error; if ($tmp1 === WebGLRenderingContext.INVALID_VALUE) { messageString = messageString + " (GL_INVALID_VALUE)"} else if ($tmp1 === WebGLRenderingContext.INVALID_OPERATION) { messageString = messageString + " (GL_INVALID_OPERATION)"} else if ($tmp1 === WebGLRenderingContext.INVALID_ENUM) { messageString = messageString + " (GL_INVALID_ENUM)"} else { messageString = (messageString + " ") + pas.SysUtils.IntToStr(error); }; $impl.Fatal(messageString); }; }; }); rtl.module("program",["System","Mat4","MemoryBuffer","GLUtils","GLTypes","SysUtils","browserconsole","Web","webgl","JS","math"],function () { "use strict"; var $mod = this; this.GLVertex2 = function (s) { if (s) { this.pos = new pas.GLTypes.TVec2(s.pos); this.color = s.color; } else { this.pos = new pas.GLTypes.TVec2(); this.color = []; }; this.$equal = function (b) { return this.pos.$equal(b.pos) && (this.color === b.color); }; }; this.kSIZEOF_VERTEX = 12; this.GetVertexData = function () { var Result = null; var buffer = null; var verts = null; var v = new $mod.GLVertex2(); var i = 0; verts = new Array(); v.pos = new pas.GLTypes.TVec2(pas.GLTypes.V2(0,0)); v.color = pas.GLTypes.RGBAb(255,0,0,255); verts.push(new $mod.GLVertex2(v)); v.pos = new pas.GLTypes.TVec2(pas.GLTypes.V2(0,100)); v.color = pas.GLTypes.RGBAb(0,255,0,255); verts.push(new $mod.GLVertex2(v)); v.pos = new pas.GLTypes.TVec2(pas.GLTypes.V2(100,100)); v.color = pas.GLTypes.RGBAb(0,0,255,255); verts.push(new $mod.GLVertex2(v)); buffer = pas.MemoryBuffer.TMemoryBuffer.$create("Create$1",[12 * verts.length]); for (var $l1 = 0, $end2 = verts.length - 1; $l1 <= $end2; $l1++) { i = $l1; v = new $mod.GLVertex2(rtl.getObject(verts[i])); buffer.AddFloats(2,pas.GLTypes.ToFloats$1(new pas.GLTypes.TVec2(v.pos))); buffer.AddBytes(4,v.color); }; Result = buffer.byteBuffer; return Result; }; this.nextTime = 0; this.deltaTime = 0; this.gl = null; this.shader = null; this.projTransform = null; this.viewTransform = null; this.modelTransform = null; this.rotateAngle = 0; this.UpdateCanvas = function (time) { var now = 0.0; now = time * 0.001; $mod.deltaTime = now - $mod.nextTime; $mod.nextTime = now; $mod.modelTransform = pas.Mat4.TMat4.$create("Identity"); $mod.modelTransform = $mod.modelTransform.Multiply(pas.Mat4.TMat4.$create("Translate",[100,100,0])); $mod.modelTransform = $mod.modelTransform.Multiply(pas.Mat4.TMat4.$create("RotateZ",[pas.math.DegToRad($mod.rotateAngle)])); $mod.rotateAngle = $mod.rotateAngle + (20 * $mod.deltaTime); $mod.shader.SetUniformMat4("modelTransform",$mod.modelTransform); $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT); $mod.gl.drawArrays($mod.gl.TRIANGLES,0,3); window.requestAnimationFrame($mod.UpdateCanvas); }; this.canvas = null; this.stride = 0; this.offset = 0; this.vertexShaderSource = ""; this.fragmentShaderSource = ""; this.buffer = null; $mod.$main = function () { $mod.canvas = document.createElement("canvas"); $mod.canvas.width = 300; $mod.canvas.height = 300; document.body.appendChild($mod.canvas); $mod.gl = $mod.canvas.getContext("webgl"); if ($mod.gl === null) { pas.System.Writeln("failed to load webgl!"); return; }; $mod.vertexShaderSource = document.getElementById("vertex.glsl").textContent; $mod.fragmentShaderSource = document.getElementById("fragment.glsl").textContent; $mod.shader = pas.GLUtils.TShader.$create("Create$1",[$mod.gl,$mod.vertexShaderSource,$mod.fragmentShaderSource]); $mod.shader.Compile(); $mod.shader.BindAttribLocation(0,"in_position"); $mod.shader.BindAttribLocation(1,"in_color"); $mod.shader.Link(); $mod.shader.Use(); $mod.gl.clearColor(0.9,0.9,0.9,1); $mod.gl.viewport(0,0,$mod.canvas.width,$mod.canvas.height); $mod.gl.clear($mod.gl.COLOR_BUFFER_BIT); $mod.projTransform = pas.Mat4.TMat4.$create("Ortho",[0,$mod.gl.canvas.width,$mod.gl.canvas.height,0,-1,1]); $mod.viewTransform = pas.Mat4.TMat4.$create("Identity"); $mod.modelTransform = pas.Mat4.TMat4.$create("Identity"); $mod.shader.SetUniformMat4("projTransform",$mod.projTransform); $mod.shader.SetUniformMat4("viewTransform",$mod.viewTransform); $mod.shader.SetUniformMat4("modelTransform",$mod.modelTransform); $mod.buffer = $mod.gl.createBuffer(); $mod.gl.bindBuffer($mod.gl.ARRAY_BUFFER,$mod.buffer); $mod.gl.bufferData($mod.gl.ARRAY_BUFFER,$mod.GetVertexData(),$mod.gl.STATIC_DRAW); $mod.offset = 0; $mod.stride = 12; $mod.gl.enableVertexAttribArray(0); $mod.gl.vertexAttribPointer(0,2,$mod.gl.FLOAT,false,$mod.stride,$mod.offset); $mod.offset += pas.GLUtils.GLSizeof($mod.gl.FLOAT) * 2; $mod.gl.enableVertexAttribArray(1); $mod.gl.vertexAttribPointer(1,4,$mod.gl.UNSIGNED_BYTE,true,$mod.stride,$mod.offset); $mod.offset += pas.GLUtils.GLSizeof($mod.gl.UNSIGNED_BYTE) * 4; window.requestAnimationFrame($mod.UpdateCanvas); }; });