Add many C based math and statistic functions
This commit is contained in:
parent
05bc965d10
commit
570c12e3db
165
scripts/base.js
165
scripts/base.js
|
@ -512,7 +512,7 @@ Object.copy = function(proto, ...objs)
|
|||
return c;
|
||||
}
|
||||
|
||||
/* OBJECT DEFININTioNS */
|
||||
/* OBJECT DEFININTIONS */
|
||||
Object.defHidden = function(obj, prop)
|
||||
{
|
||||
Object.defineProperty(obj, prop, {enumerable:false, writable:true});
|
||||
|
@ -657,19 +657,6 @@ Object.defineProperty(Object.prototype, 'push', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Object.prototype, 'findIndex', {
|
||||
value: function(x) {
|
||||
var i = 0;
|
||||
for (var key in this) {
|
||||
if (this[key] === x) return i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* STRING DEFS */
|
||||
|
||||
Object.defineProperty(String.prototype, 'next', {
|
||||
|
@ -763,12 +750,6 @@ Object.defineProperty(String.prototype, 'up_path', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'resolve', {
|
||||
value: function(path) {
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'fromlast', {
|
||||
value: function(val) {
|
||||
var idx = this.lastIndexOf(val);
|
||||
|
@ -836,23 +817,7 @@ Object.defineProperty(String.prototype, 'updir', {
|
|||
|
||||
Object.defineProperty(String.prototype, 'trimchr', {
|
||||
value: function(chars) {
|
||||
var start = this.length;
|
||||
var end = 0;
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
if (!chars.includes(this[i])) {
|
||||
start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = this.length-1; i >= 0; i--) {
|
||||
if (!chars.includes(this[i])) {
|
||||
end = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return this.substring(start,end);
|
||||
return vector.trimchr(this, chars);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -860,11 +825,6 @@ Object.defineProperty(String.prototype, 'uc', { value: function() { return this.
|
|||
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
|
||||
|
||||
/* ARRAY DEFS */
|
||||
Object.defineProperty(Array.prototype, 'aspect', {
|
||||
value: function() {
|
||||
return this.x/this.y;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Array.prototype, 'copy', {
|
||||
value: function() {
|
||||
var c = [];
|
||||
|
@ -1015,13 +975,6 @@ swizz.forEach(function(x) {
|
|||
};
|
||||
make_swizz();
|
||||
|
||||
Object.defineProperty(Array.prototype, 'add', {
|
||||
value: function(b) {
|
||||
var c = [];
|
||||
for (var i = 0; i < this.length; i++) { c[i] = this[i] + b[i]; }
|
||||
return c;
|
||||
}});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'normalized', {
|
||||
value: function() {
|
||||
var c = this.slice();
|
||||
|
@ -1056,13 +1009,6 @@ Object.defineProperty(Array.prototype, 'doubleup', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'sub', {
|
||||
value: function(b) {
|
||||
var c = [];
|
||||
for (var i = 0; i < this.length; i++) { c[i] = this[i] - b[i]; }
|
||||
return c;
|
||||
}});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'mult', {
|
||||
value: function(arr) {
|
||||
var c = [];
|
||||
|
@ -1076,16 +1022,6 @@ Object.defineProperty(Array.prototype, 'apply', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'scale', {
|
||||
value: function(s) {
|
||||
if (Array.isArray(s)) {
|
||||
var c = this.slice();
|
||||
c.forEach(function(x,i) { c[i] = x * s[i]; });
|
||||
return c;
|
||||
}
|
||||
return this.map(function(x) { return x*s; });
|
||||
}});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'sorted', {
|
||||
value: function() {
|
||||
return this.toSorted();
|
||||
|
@ -1119,7 +1055,6 @@ Object.defineProperty(Array.prototype, 'mapvec', {
|
|||
return this.map((x,i) => fn(x,b[i]));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Object.defineProperty(Array.prototype, 'remove', {
|
||||
value: function(b) {
|
||||
|
@ -1257,19 +1192,23 @@ Object.defineProperty(Array.prototype, 'mirrored', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(Array.prototype, 'lerp', {
|
||||
value: function(to, t) {
|
||||
var c = [];
|
||||
this.forEach(function(x,i) {
|
||||
c[i] = (to[i] - x) * t + x;
|
||||
});
|
||||
return c;
|
||||
}
|
||||
});
|
||||
Math.lerp = vector.lerp;
|
||||
Math.gcd = vector.gcd;
|
||||
Math.lcm = vector.lcm;
|
||||
Math.sum = vector.sum;
|
||||
Math.mean = vector.mean;
|
||||
Math.sigma = vector.sigma;
|
||||
Math.median = vector.median;
|
||||
|
||||
Math.lerp = function(s,f,t) { return (f-s)*t + s; };
|
||||
Math.gcd = function(a,b) { return b === 0 ? a : gcd(b,a%b); }
|
||||
Math.lcm = function(a,b) { return (a*b)/gcd(a,b); }
|
||||
Math.variance = function(series) {
|
||||
var mean = Math.mean(series);
|
||||
var vnce = 0;
|
||||
for (var i = 0; i < series.length; i++)
|
||||
vnce += Math.pow(series[i]-mean, 2);
|
||||
return vnce/(series.length);
|
||||
}
|
||||
|
||||
Math.ci = function(series) { return 3*Math.sigma(series)/Math.sqrt(series.length); }
|
||||
|
||||
Math.grab_from_points = function(pos, points, slop) {
|
||||
var shortest = slop;
|
||||
|
@ -1313,22 +1252,18 @@ Object.defineProperty(Object.prototype, 'lerp',{
|
|||
return obj;
|
||||
}});
|
||||
|
||||
/* MATH EXTENSioNS */
|
||||
/* MATH EXTENSIONS */
|
||||
Object.defineProperty(Number.prototype, 'lerp', {
|
||||
value: function(to, t) {
|
||||
var s = this;
|
||||
return (to - this) * t + this;
|
||||
}
|
||||
value: function(to, t) { return Math.lerp(this, to, t); }
|
||||
});
|
||||
|
||||
Object.defineProperty(Number.prototype, 'clamp', {
|
||||
value: function(from,to) {
|
||||
return Math.clamp(this,from,to);
|
||||
}
|
||||
value: function(from,to) { return Math.clamp(this,from,to); }
|
||||
});
|
||||
|
||||
Math.clamp = function (x, l, h) { return x > h ? h : x < l ? l : x; }
|
||||
Math.clamp = vector.clamp;
|
||||
|
||||
Math.random_range = function(min,max) { return Math.random() * (max-min) + min; };
|
||||
Math.random_range = vector.random_range;
|
||||
Math.rand_int = function(max) { return Math.floor(Math.random()*max); };
|
||||
|
||||
Math.snap = function(val, grid) {
|
||||
|
@ -1340,33 +1275,17 @@ Math.snap = function(val, grid) {
|
|||
return d+i;
|
||||
}
|
||||
|
||||
Math.angledist = function (a1, a2) {
|
||||
a1 = a1%1;
|
||||
a2 = a2%1;
|
||||
var dist = a2 - a1;
|
||||
if (dist == 0) return dist;
|
||||
|
||||
if (dist > 0) {
|
||||
if (dist > 0.5) return dist-1;
|
||||
return dist;
|
||||
}
|
||||
|
||||
if (dist < -0.5) return dist+1;
|
||||
|
||||
return dist;
|
||||
};
|
||||
Math.angledist = vector.angledist;
|
||||
Math.angledist.doc = "Find the shortest angle between two angles.";
|
||||
Math.TAU = Math.PI*2;
|
||||
Math.deg2rad = function(deg) { return deg * 0.0174533; };
|
||||
Math.rad2deg = function(rad) { return rad / 0.0174533; };
|
||||
Math.deg2rad = function(x) { return x; };
|
||||
Math.rad2deg = function(x) { return x; };
|
||||
Math.turn2rad = function(x) { return x*Math.TAU; };
|
||||
Math.rad2turn = function(x) { return x/Math.TAU; };
|
||||
Math.turn2deg = function(x) { return x*360; };
|
||||
Math.deg2turn = function(x) { return x/360; };
|
||||
Math.randomint = function(max) { return Math.clamp(Math.floor(Math.random() * max), 0, max-1); };
|
||||
Math.variate = function(n, pct) { return n + (Math.random_range(-pct,pct)*n); }
|
||||
Math.variate = vector.variate;
|
||||
|
||||
/* BOUNDINGBOXES */
|
||||
var bbox = {};
|
||||
|
@ -1501,38 +1420,16 @@ bbox.fromobjs = function(objs)
|
|||
var Vector = {};
|
||||
Vector.length = function(v) { return Math.hypot(...v); }
|
||||
|
||||
Vector.norm = function(v) {
|
||||
var len = Vector.length(v);
|
||||
if (!len) return [0,0];
|
||||
return [v.x/len, v.y/len];
|
||||
}
|
||||
Vector.project = function(a, b) { return vector.project(a,b); }
|
||||
Vector.dot = function(a, b) { return vector.dot(a,b); },
|
||||
Vector.norm = vector.norm;
|
||||
Vector.project = vector.project;
|
||||
Vector.dot = vector.dot;
|
||||
Vector.random = function() {
|
||||
var vec = [Math.random()-0.5, Math.random()-0.5];
|
||||
return Vector.norm(vec);
|
||||
}
|
||||
|
||||
Vector.midpoint = function(a,b) { return [(a.x+b.x)/2, (a.y+b.y)/2]; }
|
||||
Vector.distance = function(a,b) { return Math.hypot(b.x-a.x, b.y-a.y); }
|
||||
|
||||
Vector.angle_between = function(a,b)
|
||||
{
|
||||
var dot = Vector.dot(a,b);
|
||||
var am = Vector.length(a);
|
||||
var bm = Vector.length(b);
|
||||
var cos_a = dot / (am*bm);
|
||||
var angle = Math.acos(cos_a);
|
||||
return Math.rad2turn(angle);
|
||||
}
|
||||
|
||||
Vector.angle = function(v) { return Math.rad2turn(Math.atan2(v.y, v.x)); }
|
||||
Vector.rotate = function(v,angle) {
|
||||
var r = Vector.length(v);
|
||||
angle += Vector.angle(v);
|
||||
angle = Math.turn2rad(angle);
|
||||
return [r*Math.cos(angle), r*Math.sin(angle)];
|
||||
}
|
||||
Vector.angle_between = vector.angle_between;
|
||||
Vector.rotate = vector.rotate;
|
||||
|
||||
Vector.equal = function(v1, v2, tol) {
|
||||
if (!tol)
|
||||
|
|
|
@ -17,20 +17,17 @@ var fullrect = [0,0,1,1];
|
|||
|
||||
var sprite_addbucket = function(sprite)
|
||||
{
|
||||
return;
|
||||
var pp = sprite.gameobject.drawlayer.toString();
|
||||
sprite_buckets[pp] ??= {};
|
||||
sprite_buckets[pp][sprite.path] ??= {};
|
||||
sprite_buckets[pp][sprite.path][sprite.guid] = sprite;
|
||||
var layer = sprite.gameobject.drawlayer;
|
||||
sprite_buckets[layer] ??= {};
|
||||
sprite_buckets[layer][sprite.path] ??= {};
|
||||
sprite_buckets[layer][sprite.path][sprite.guid] = sprite;
|
||||
}
|
||||
|
||||
var sprite_rmbucket = function(sprite)
|
||||
{
|
||||
return;
|
||||
var pp = sprite.gameobject.drawlayer.toString();
|
||||
if (!sprite_buckets[pp]) return;
|
||||
if (!sprite_buckets[pp][sprite.path]) return;
|
||||
delete sprite_buckets[pp][sprite.path][sprite.guid];
|
||||
for (var layer of Object.values(sprite_buckets))
|
||||
for (var path of Object.values(layer))
|
||||
delete path[sprite.guid];
|
||||
}
|
||||
|
||||
var sprite = {
|
||||
|
@ -59,6 +56,7 @@ var sprite = {
|
|||
//self.path = playing.path;
|
||||
self.frame = playing.frames[f].rect;
|
||||
self.rect = [self.frame.x, self.frame.y, self.frame.w, self.frame.h];
|
||||
self.update_dimensions();
|
||||
f = (f+1)%playing.frames.length;
|
||||
if (f === 0) {
|
||||
self.anim_done?.();
|
||||
|
@ -88,6 +86,8 @@ var sprite = {
|
|||
this.rect = fullrect;
|
||||
|
||||
var anim = SpriteAnim.make(p);
|
||||
this.update_dimensions();
|
||||
this.sync();
|
||||
|
||||
if (!anim) return;
|
||||
this.anim = anim;
|
||||
|
@ -99,6 +99,7 @@ var sprite = {
|
|||
return this._p;
|
||||
},
|
||||
kill() {
|
||||
sprite_rmbucket(this);
|
||||
this.del_anim?.();
|
||||
this.anim = undefined;
|
||||
this.gameobject = undefined;
|
||||
|
@ -111,7 +112,10 @@ var sprite = {
|
|||
this.pos = this.pos.scale(x);
|
||||
},
|
||||
anchor:[0,0],
|
||||
sync() { },
|
||||
sync() {
|
||||
sprite_rmbucket(this);
|
||||
sprite_addbucket(this);
|
||||
},
|
||||
pick() { return this; },
|
||||
boundingbox() {
|
||||
var dim = this.dimensions();
|
||||
|
@ -120,17 +124,21 @@ var sprite = {
|
|||
return bbox.fromcwh(realpos,dim);
|
||||
},
|
||||
|
||||
update_dimensions() {
|
||||
this._dimensions = [this.texture.width*this.rect[2], this.texture.height*this.rect[3]];
|
||||
component.sprite_dim_hook?.(this);
|
||||
},
|
||||
|
||||
dimensions() {
|
||||
var dim = [this.texture.width, this.texture.height];
|
||||
dim.x *= this.frame.w;
|
||||
dim.y *= this.frame.h;
|
||||
return dim;
|
||||
return this._dimensions;
|
||||
},
|
||||
width() { return this.dimensions().x; },
|
||||
height() { return this.dimensions().y; },
|
||||
};
|
||||
globalThis.allsprites = {};
|
||||
globalThis.sprite_buckets = [];
|
||||
var sprite_buckets = {};
|
||||
|
||||
component.sprite_buckets = function() { return sprite_buckets; }
|
||||
|
||||
sprite.doc = {
|
||||
path: "Path to the texture.",
|
||||
|
@ -173,6 +181,7 @@ component.sprite = function(obj) {
|
|||
sp.guid = prosperon.guid();
|
||||
allsprites[sp.guid] = sp;
|
||||
if (component.sprite.make_hook) component.sprite.make_hook(sp);
|
||||
sprite_addbucket(sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ Object.defineProperty(String.prototype, "folder", {
|
|||
|
||||
globalThis.Resources = {};
|
||||
|
||||
Resources.rm_fn = function(fn, text)
|
||||
Resources.rm_fn = function rm_fn(fn, text)
|
||||
{
|
||||
var reg = new RegExp(fn.source + "\\s*\\(");
|
||||
var match;
|
||||
|
@ -48,7 +48,7 @@ Resources.rm_fn = function(fn, text)
|
|||
}
|
||||
Resources.rm_fn.doc = "Remove calls to a given function from a given text script.";
|
||||
|
||||
Resources.replpath = function (str, path) {
|
||||
Resources.replpath = function replpath(str, path) {
|
||||
if (!str) return str;
|
||||
if (str[0] === "/") return str.rm(0);
|
||||
|
||||
|
@ -66,7 +66,7 @@ Resources.replpath = function (str, path) {
|
|||
return str;
|
||||
};
|
||||
|
||||
Resources.replstrs = function (path) {
|
||||
Resources.replstrs = function replstrs(path) {
|
||||
if (!path) return;
|
||||
var script = io.slurp(path);
|
||||
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
|
||||
|
@ -223,7 +223,7 @@ globalThis.global = globalThis;
|
|||
|
||||
var use_cache = {};
|
||||
|
||||
globalThis.use = function(file, env = {}, script) {
|
||||
globalThis.use = function use(file, env = {}, script) {
|
||||
file = Resources.find_script(file);
|
||||
profile.cache("USE", file);
|
||||
|
||||
|
@ -238,6 +238,7 @@ globalThis.use = function(file, env = {}, script) {
|
|||
use_cache[file] = fn;
|
||||
var ret = fn.call(env);
|
||||
profile.endcache();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -254,6 +255,7 @@ function stripped_use (file, env = {}, script) {
|
|||
var fn = os.eval(file, script);
|
||||
var ret = fn.call(env);
|
||||
profile.endcache();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -274,6 +276,13 @@ debug.enabled = true;
|
|||
bare_use("scripts/base.js");
|
||||
bare_use("scripts/profile.js");
|
||||
|
||||
prosperon.release = function()
|
||||
{
|
||||
profile.enabled = false;
|
||||
console.enabled = false;
|
||||
debug.enabled = false;
|
||||
}
|
||||
|
||||
bare_use("preconfig.js");
|
||||
|
||||
if (!profile.enabled)
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
globalThis.entityreport = {};
|
||||
|
||||
var timer_update = function(dt)
|
||||
{
|
||||
this.fn();
|
||||
|
||||
}
|
||||
|
||||
function obj_unique_name(name, obj) {
|
||||
name = name.replaceAll('.', '_');
|
||||
if (!(name in obj)) return name;
|
||||
|
@ -68,7 +74,7 @@ var entity = {
|
|||
delay(fn, seconds) {
|
||||
var timers = this.timers;
|
||||
var stop = function() {
|
||||
timers.remove(stop);
|
||||
delete timers[guid];
|
||||
execute = undefined;
|
||||
stop = undefined;
|
||||
rm?.();
|
||||
|
@ -91,7 +97,8 @@ var entity = {
|
|||
}
|
||||
|
||||
var rm = Register.update.register(update);
|
||||
timers.push(stop);
|
||||
var guid = prosperon.guid();
|
||||
timers[guid] = (stop);
|
||||
return stop;
|
||||
},
|
||||
|
||||
|
@ -146,7 +153,7 @@ var entity = {
|
|||
|
||||
ent.components = {};
|
||||
ent.objects = {};
|
||||
ent.timers = [];
|
||||
ent.timers = {};
|
||||
|
||||
if (!text)
|
||||
ent.ur = emptyur;
|
||||
|
@ -339,8 +346,8 @@ dup(diff) {
|
|||
this.__kill = true;
|
||||
console.spam(`Killing entity of type ${this.ur}`);
|
||||
|
||||
for (var t of this.timers) t();
|
||||
this.timers = [];
|
||||
this.timers.forEach(x => x());
|
||||
delete this.timers;
|
||||
Event.rm_obj(this);
|
||||
input.do_uncontrol(this);
|
||||
|
||||
|
|
|
@ -202,8 +202,6 @@ mum.image = function(path, data = {})
|
|||
else
|
||||
data.height = tex.height;
|
||||
|
||||
|
||||
|
||||
if (!data.width) data.width = tex.width;
|
||||
if (!data.height) data.height = tex.height;
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ var make_emitter = function()
|
|||
var e = Object.create(emitter);
|
||||
e.ssbo = render.make_textssbo();
|
||||
e.shape = shape.centered_quad;
|
||||
e.shader = render.make_shader("shaders/baseparticle.cg");
|
||||
e.shader = "shaders/baseparticle.cg";
|
||||
e.dead = [];
|
||||
return e;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,32 @@
|
|||
var t_units = ["ns", "us", "ms", "s", "ks", "Ms"];
|
||||
|
||||
profile.cpu = function(fn, times = 1, q = "unnamed") {
|
||||
var start = profile.now();
|
||||
for (var i = 0; i < times; i++)
|
||||
fn();
|
||||
|
||||
var elapsed = profile.now() - start;
|
||||
var avgt = profile.best_t(elapsed/times);
|
||||
var totalt = profile.best_t(elapsed);
|
||||
function calc_cpu(fn, times, diff=0)
|
||||
{
|
||||
var series = [];
|
||||
|
||||
for (var i = 0; i < times; i++) {
|
||||
var st = profile.now();
|
||||
fn(i);
|
||||
series.push(profile.now()-st-diff);
|
||||
}
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
say(`profile [${q}]: ${profile.best_t(avgt)} average [${profile.best_t(totalt)} for ${times} loops]`);
|
||||
function empty_fn() {}
|
||||
|
||||
profile.cpu = function profile_cpu(fn, times = 1, q = "unnamed") {
|
||||
profile.gather_stop();
|
||||
var empty = calc_cpu(empty_fn, 100000);
|
||||
var mean = Math.mean(empty);
|
||||
var series = calc_cpu(fn,times, mean);
|
||||
|
||||
var elapsed = Math.sum(series);
|
||||
var avgt = profile.best_t(elapsed/series.length);
|
||||
var totalt = profile.best_t(elapsed);
|
||||
|
||||
say(`profile [${q}]: ${avgt} ± ${profile.best_t(Math.ci(series))} [${totalt} for ${times} loops]`);
|
||||
start_prof_gather();
|
||||
}
|
||||
|
||||
profile.ms = function(t) { return t/1000000; }
|
||||
|
@ -35,27 +52,33 @@ function add_callgraph(fn, line, time) {
|
|||
var hittar = 500;
|
||||
var hitpct = 0.2;
|
||||
var start_gather = profile.now();
|
||||
|
||||
function start_prof_gather()
|
||||
{
|
||||
profile.gather(hittar, function() {
|
||||
var time = profile.now()-st;
|
||||
|
||||
var err = new Error();
|
||||
var stack = err.stack.split("\n");
|
||||
|
||||
stack = stack.slice(1);
|
||||
stack = stack.map(x => x.slice(7).split(' '));
|
||||
|
||||
var fns = stack.map(x => x[0]).filter(x=>x);
|
||||
var lines = stack.map(x => x[1]).filter(x => x);
|
||||
lines = lines.map(x => x.slice(1,x.length-1));
|
||||
|
||||
for (var i = 0; i < fns.length; i++)
|
||||
add_callgraph(fns[i], lines[i], time);
|
||||
|
||||
st = profile.now();
|
||||
|
||||
profile.gather_rate(Math.variate(hittar,hitpct));
|
||||
});
|
||||
}
|
||||
|
||||
if (profile.enabled)
|
||||
profile.gather(hittar, function() {
|
||||
var time = profile.now()-st;
|
||||
|
||||
var err = new Error();
|
||||
var stack = err.stack.split("\n");
|
||||
|
||||
stack = stack.slice(1);
|
||||
stack = stack.map(x => x.slice(7).split(' '));
|
||||
|
||||
var fns = stack.map(x => x[0]).filter(x=>x);
|
||||
var lines = stack.map(x => x[1]).filter(x => x);
|
||||
lines = lines.map(x => x.slice(1,x.length-1));
|
||||
|
||||
for (var i = 0; i < fns.length; i++)
|
||||
add_callgraph(fns[i], lines[i], time);
|
||||
|
||||
st = profile.now();
|
||||
|
||||
profile.gather_rate(Math.variate(hittar,hitpct));
|
||||
});
|
||||
start_prof_gather();
|
||||
|
||||
var filecache = {};
|
||||
function get_line(file, line) {
|
||||
|
@ -96,6 +119,7 @@ profile.print_cpu_instr = function()
|
|||
|
||||
profile.best_t = function (t) {
|
||||
var qq = 0;
|
||||
|
||||
while (t > 1000 && qq < t_units.length-1) {
|
||||
t /= 1000;
|
||||
qq++;
|
||||
|
@ -109,28 +133,29 @@ profile.report = function (start, msg = "[undefined report]") { console.info(`${
|
|||
var profile_frames = {};
|
||||
var profile_frame_ts = [];
|
||||
var profile_cframe = profile_frames;
|
||||
var profile_frame = 0;
|
||||
profile.frame = function(title)
|
||||
var pframe = 0;
|
||||
|
||||
profile.frame = function profile_frame(title)
|
||||
{
|
||||
profile_frame_ts.push(profile_cframe);
|
||||
profile_cframe[title] ??= {};
|
||||
profile_cframe = profile_cframe[title];
|
||||
profile_cframe._times ??= [];
|
||||
profile_cframe._times[profile_frame] = profile.now();
|
||||
profile_cframe._times[pframe] ??= 0;
|
||||
profile_cframe._times[pframe] = profile.now() - profile_cframe._times[pframe];
|
||||
}
|
||||
|
||||
profile.endframe = function()
|
||||
profile.endframe = function profile_endframe()
|
||||
{
|
||||
if (profile_cframe === profile_frames) return;
|
||||
profile_cframe._times[profile_frame] = profile.now() - profile_cframe._times[profile_frame];
|
||||
profile_cframe._times[pframe] = profile.now() - profile_cframe._times[pframe];
|
||||
profile_cframe = profile_frame_ts.pop();
|
||||
if (profile_cframe === profile_frames) profile_frame++;
|
||||
if (profile_cframe === profile_frames) pframe++;
|
||||
}
|
||||
|
||||
var print_frame = function(frame, indent, title)
|
||||
{
|
||||
var avg = frame._times.reduce((sum, e) => sum += e)/frame._times.length;
|
||||
say(indent + `${title} ::::: ${profile.best_t(avg)} (${frame._times.length} hits)`);
|
||||
say(indent + `${title} ::::: ${profile.best_t(Math.mean(frame._times))} ± ${profile.best_t(Math.ci(frame._times))} (${frame._times.length} hits)`);
|
||||
|
||||
for (var i in frame) {
|
||||
if (i === '_times') continue;
|
||||
|
@ -150,14 +175,14 @@ var report_cache = {};
|
|||
var cachest = 0;
|
||||
var cachegroup;
|
||||
var cachetitle;
|
||||
profile.cache = function(group, title)
|
||||
profile.cache = function profile_cache(group, title)
|
||||
{
|
||||
cachest = profile.now();
|
||||
cachegroup = group;
|
||||
cachetitle = title;
|
||||
}
|
||||
|
||||
profile.endcache = function(tag = "")
|
||||
profile.endcache = function profile_endcache(tag = "")
|
||||
{
|
||||
addreport(cachegroup, cachetitle + tag, cachest);
|
||||
}
|
||||
|
|
|
@ -316,21 +316,23 @@ var Register = {
|
|||
|
||||
add_cb(name, e_event = false) {
|
||||
var n = {};
|
||||
var fns = [];
|
||||
var fns = {};
|
||||
|
||||
n.register = function (fn, oname) {
|
||||
if (!(fn instanceof Function)) return;
|
||||
|
||||
var guid = prosperon.guid();
|
||||
|
||||
var dofn = function(...args) {
|
||||
profile.cache(name,oname);
|
||||
var st = profile.now();
|
||||
fn(...args);
|
||||
profile.endcache();
|
||||
profile.endcache();
|
||||
}
|
||||
|
||||
fns.push(dofn);
|
||||
fns[guid] = dofn;
|
||||
return function () {
|
||||
fns.remove(dofn);
|
||||
delete fns[guid];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -6,24 +6,24 @@ render.doc = {
|
|||
|
||||
var cur = {};
|
||||
|
||||
render.use_shader = function(shader)
|
||||
render.use_shader = function use_shader(shader)
|
||||
{
|
||||
if (typeof shader === 'string')
|
||||
shader = render.make_shader(shader);
|
||||
shader = make_shader(shader);
|
||||
if (cur.shader === shader) return;
|
||||
cur.shader = shader;
|
||||
cur.globals = {};
|
||||
cur.bind = undefined;
|
||||
cur.mesh = undefined;
|
||||
render.setpipeline(shader.pipe);
|
||||
shader_globals(cur.shader);
|
||||
}
|
||||
|
||||
render.use_mat = function(mat)
|
||||
render.use_mat = function use_mat(mat)
|
||||
{
|
||||
if (!cur.shader) return;
|
||||
if (cur.mat === mat) return;
|
||||
|
||||
render.shader_apply_material(cur.shader, mat, cur.mat);
|
||||
shader_apply_material(cur.shader, mat, cur.mat);
|
||||
|
||||
cur.mat = mat;
|
||||
|
||||
|
@ -38,7 +38,7 @@ render.use_mat = function(mat)
|
|||
|
||||
var models_array = [];
|
||||
|
||||
render.set_model = function(t)
|
||||
function set_model(t)
|
||||
{
|
||||
if (cur.shader.vs.unimap.model)
|
||||
render.setunim4(0, cur.shader.vs.unimap.model.slot, t);
|
||||
|
@ -96,7 +96,7 @@ var face_map = {
|
|||
ccw: 1
|
||||
}
|
||||
|
||||
render.poly_prim = function(verts)
|
||||
render.poly_prim = function poly_prim(verts)
|
||||
{
|
||||
var index = [];
|
||||
if (verts.length < 1) return undefined;
|
||||
|
@ -131,31 +131,15 @@ function shader_directive(shader, name, map)
|
|||
return ff;
|
||||
}
|
||||
|
||||
function global_uni(uni, stage)
|
||||
{
|
||||
cur.globals[stage] ??= {};
|
||||
if (cur.globals[stage][uni.name]) return true;
|
||||
switch(uni.name) {
|
||||
case "time":
|
||||
cur.globals[stage][uni.name]
|
||||
render.setuniv(stage, uni.slot, profile.secs(profile.now()));
|
||||
cur.globals[stage][uni.name] = true;
|
||||
return true;
|
||||
case "projection":
|
||||
render.setuniproj(stage, uni.slot);
|
||||
cur.globals[stage][uni.name] = true;
|
||||
return true;
|
||||
case "view":
|
||||
render.setuniview(stage, uni.slot);
|
||||
cur.globals[stage][uni.name] = true;
|
||||
return true;
|
||||
case "vp":
|
||||
render.setunivp(stage, uni.slot);
|
||||
cur.globals[stage][uni.name] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
var uni_globals = {
|
||||
time(stage, slot) { render.setuniv(stage, slot, profile.secs(profile.now())); },
|
||||
projection(stage,slot) { render.setuniproj(stage, slot); },
|
||||
view(stage,slot) { render.setuniview(stage, slot); },
|
||||
vp(stage,slot) { render.setunivp(stage,slot); },
|
||||
}
|
||||
|
||||
function set_global_uni(uni, stage) {
|
||||
uni_globals[uni.name]?.(stage, uni.slot);
|
||||
}
|
||||
|
||||
var setcam = render.set_camera;
|
||||
|
@ -170,8 +154,14 @@ render.set_camera = function(cam)
|
|||
}
|
||||
|
||||
var shader_cache = {};
|
||||
|
||||
function strip_shader_inputs(shader)
|
||||
{
|
||||
for (var a of shader.vs.inputs)
|
||||
a.name = a.name.slice(2);
|
||||
}
|
||||
|
||||
render.make_shader = function(shader)
|
||||
function make_shader(shader)
|
||||
{
|
||||
if (shader_cache[shader]) return shader_cache[shader];
|
||||
|
||||
|
@ -198,6 +188,7 @@ render.make_shader = function(shader)
|
|||
profile.endcache(" [cached]");
|
||||
var shaderobj = json.decode(io.slurp(writejson));
|
||||
var obj = shaderobj[os.sys()];
|
||||
strip_shader_inputs(obj);
|
||||
obj.pipe = render.pipeline(obj);
|
||||
shader_cache[shader] = obj;
|
||||
return obj;
|
||||
|
@ -314,6 +305,7 @@ render.make_shader = function(shader)
|
|||
profile.endcache();
|
||||
|
||||
var obj = compiled[os.sys()];
|
||||
strip_shader_inputs(obj);
|
||||
obj.pipe = render.pipeline(obj);
|
||||
|
||||
shader_cache[shader] = obj;
|
||||
|
@ -326,11 +318,20 @@ var shader_unisize = {
|
|||
12: render.setuniv3,
|
||||
16: render.setuniv4
|
||||
};
|
||||
|
||||
function shader_globals(shader)
|
||||
{
|
||||
for (var p in shader.vs.unimap)
|
||||
set_global_uni(shader.vs.unimap[p], 0);
|
||||
|
||||
for (var p in shader.fs.unimap)
|
||||
set_global_uni(shader.fs.unimap[p], 1);
|
||||
}
|
||||
|
||||
render.shader_apply_material = function(shader, material = {}, old = {})
|
||||
function shader_apply_material(shader, material = {}, old = {})
|
||||
{
|
||||
for (var p in shader.vs.unimap) {
|
||||
if (global_uni(shader.vs.unimap[p], 0)) continue;
|
||||
if (!(p in material)) continue;
|
||||
if (material[p] === old[p]) continue;
|
||||
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
|
||||
var s = shader.vs.unimap[p];
|
||||
|
@ -338,7 +339,7 @@ render.shader_apply_material = function(shader, material = {}, old = {})
|
|||
}
|
||||
|
||||
for (var p in shader.fs.unimap) {
|
||||
if (global_uni(shader.fs.unimap[p], 1)) continue;
|
||||
if (!(p in material)) continue;
|
||||
if (material[p] === old[p]) continue;
|
||||
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
|
||||
var s = shader.fs.unimap[p];
|
||||
|
@ -355,7 +356,7 @@ render.shader_apply_material = function(shader, material = {}, old = {})
|
|||
render.setuniv2(0, shader.vs.unimap.diffuse_size.slot, [material.diffuse.width, material.diffuse.height]);
|
||||
}
|
||||
|
||||
render.sg_bind = function(mesh, ssbo)
|
||||
function sg_bind(mesh, ssbo)
|
||||
{
|
||||
if (cur.mesh === mesh && cur.bind) {
|
||||
cur.bind.inst = 1;
|
||||
|
@ -371,13 +372,10 @@ render.sg_bind = function(mesh, ssbo)
|
|||
if (cur.shader.vs.inputs)
|
||||
for (var a of cur.shader.vs.inputs) {
|
||||
if (!(a.name in mesh)) {
|
||||
if (!(a.name.slice(2) in mesh)) {
|
||||
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
|
||||
return undefined;
|
||||
} else
|
||||
bind.attrib.push(mesh[a.name.slice(2)]);
|
||||
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
|
||||
return undefined;
|
||||
} else
|
||||
bind.attrib.push(mesh[a.name]);
|
||||
bind.attrib.push(mesh[a.name]);
|
||||
}
|
||||
|
||||
if (cur.shader.indexed) {
|
||||
|
@ -448,15 +446,15 @@ var polyssboshader;
|
|||
var sprite_ssbo;
|
||||
|
||||
render.init = function() {
|
||||
textshader = render.make_shader("shaders/text_base.cg");
|
||||
render.spriteshader = render.make_shader("shaders/sprite.cg");
|
||||
spritessboshader = render.make_shader("shaders/sprite_ssbo.cg");
|
||||
render.postshader = render.make_shader("shaders/simplepost.cg");
|
||||
slice9shader = render.make_shader("shaders/9slice.cg");
|
||||
circleshader = render.make_shader("shaders/circle.cg");
|
||||
polyshader = render.make_shader("shaders/poly.cg");
|
||||
parshader = render.make_shader("shaders/baseparticle.cg");
|
||||
polyssboshader = render.make_shader("shaders/poly_ssbo.cg");
|
||||
textshader = make_shader("shaders/text_base.cg");
|
||||
render.spriteshader = make_shader("shaders/sprite.cg");
|
||||
spritessboshader = make_shader("shaders/sprite_ssbo.cg");
|
||||
render.postshader = make_shader("shaders/simplepost.cg");
|
||||
slice9shader = make_shader("shaders/9slice.cg");
|
||||
circleshader = make_shader("shaders/circle.cg");
|
||||
polyshader = make_shader("shaders/poly.cg");
|
||||
parshader = make_shader("shaders/baseparticle.cg");
|
||||
polyssboshader = make_shader("shaders/poly_ssbo.cg");
|
||||
textssbo = render.make_textssbo();
|
||||
poly_ssbo = render.make_textssbo();
|
||||
sprite_ssbo = render.make_textssbo();
|
||||
|
@ -493,47 +491,55 @@ render.init = function() {
|
|||
}
|
||||
}
|
||||
|
||||
render.sprites = function(gridsize = 1)
|
||||
render.sprites = function render_sprites(gridsize = 1)
|
||||
{
|
||||
/*
|
||||
profile.frame("bucketing");
|
||||
var sps = Object.values(allsprites);
|
||||
var sprite_buckets = {};
|
||||
|
||||
var buckets = [];
|
||||
for (var i = 0; i <= 20; i++)
|
||||
buckets[i] = {};
|
||||
|
||||
for (var sprite of sps) {
|
||||
var pp = sprite.gameobject.drawlayer;
|
||||
sprite_buckets[pp] ??= {};
|
||||
sprite_buckets[pp][sprite.path] ??= {};
|
||||
sprite_buckets[pp][sprite.path][sprite.guid] = sprite;
|
||||
render.sprite_hook?.(sprite);
|
||||
var layer = sprite.gameobject.drawlayer+10;
|
||||
if (buckets[layer][sprite.path])
|
||||
buckets[layer][sprite.path].push(sprite);
|
||||
else
|
||||
buckets[layer][sprite.path] = [sprite];
|
||||
}
|
||||
|
||||
profile.endframe();
|
||||
*/
|
||||
|
||||
profile.frame("sorting");
|
||||
var sprite_buckets = component.sprite_buckets();
|
||||
|
||||
var buckets = Object.entries(sprite_buckets).sort((a,b) => {
|
||||
var na = Number(a[0]);
|
||||
var ba = Number(b[0]);
|
||||
if (na < ba) return -1;
|
||||
if (na === ba) return 0;
|
||||
var nb = Number(b[0]);
|
||||
if (na < nb) return -1;
|
||||
return 1;
|
||||
});
|
||||
profile.endframe();
|
||||
|
||||
|
||||
profile.frame("drawing");
|
||||
render.use_shader(spritessboshader);
|
||||
for (var bucket of buckets) {
|
||||
for (var img of Object.values(bucket[1])) {
|
||||
for (var layer of buckets) {
|
||||
for (var img of Object.values(layer[1])) {
|
||||
var sparray = Object.values(img);
|
||||
if (sparray.length === 0) continue;
|
||||
var ss = sparray[0];
|
||||
render.use_mat(ss);
|
||||
render.make_sprite_ssbo(Object.values(sparray), sprite_ssbo);
|
||||
render.make_sprite_ssbo(sparray, sprite_ssbo);
|
||||
render.draw(shape.quad, sprite_ssbo, sparray.length);
|
||||
}
|
||||
}
|
||||
profile.endframe();
|
||||
}
|
||||
|
||||
render.circle = function(pos, radius, color) {
|
||||
check_flush();
|
||||
render.circle = function render_circle(pos, radius, color) {
|
||||
flush();
|
||||
var mat = {
|
||||
radius: radius,
|
||||
coord: pos,
|
||||
|
@ -544,56 +550,71 @@ render.circle = function(pos, radius, color) {
|
|||
render.draw(shape.quad);
|
||||
}
|
||||
|
||||
render.poly = function(points, color, transform) {
|
||||
render.poly = function render_poly(points, color, transform) {
|
||||
var buffer = render.poly_prim(points);
|
||||
var mat = { shade: color};
|
||||
render.use_shader(polyshader);
|
||||
render.set_model(transform);
|
||||
set_model(transform);
|
||||
render.use_mat(mat);
|
||||
render.draw(buffer);
|
||||
}
|
||||
|
||||
var nextflush = undefined;
|
||||
var check_flush = function(flush_fn)
|
||||
function flush()
|
||||
{
|
||||
nextflush?.();
|
||||
nextflush = undefined;
|
||||
}
|
||||
|
||||
function check_flush(flush_fn)
|
||||
{
|
||||
if (!flush_fn) {
|
||||
if (!nextflush) return;
|
||||
nextflush();
|
||||
nextflush = undefined;
|
||||
}
|
||||
if (!nextflush)
|
||||
nextflush = flush_fn;
|
||||
else if (nextflush !== flush_fn) {
|
||||
nextflush();
|
||||
nextflush = flush_fn;
|
||||
}
|
||||
nextflush();
|
||||
nextflush = flush_fn;
|
||||
}
|
||||
}
|
||||
|
||||
var poly_cache = [];
|
||||
var poly_idx = 0;
|
||||
var poly_ssbo;
|
||||
|
||||
render.flush_poly = function()
|
||||
function poly_e()
|
||||
{
|
||||
if (poly_cache.length === 0) return;
|
||||
render.use_shader(polyssboshader);
|
||||
render.use_mat({});
|
||||
render.make_particle_ssbo(poly_cache, poly_ssbo);
|
||||
render.draw(shape.centered_quad, poly_ssbo, poly_cache.length);
|
||||
poly_cache = [];
|
||||
var e;
|
||||
poly_idx++;
|
||||
if (poly_idx > poly_cache.length) {
|
||||
e = {
|
||||
transform:os.make_transform(),
|
||||
color: Color.white
|
||||
};
|
||||
poly_cache.push(e);
|
||||
return e;
|
||||
}
|
||||
var e = poly_cache[poly_idx-1];
|
||||
e.transform.unit();
|
||||
return e;
|
||||
}
|
||||
|
||||
render.line = function(points, color = Color.white, thickness = 1) {
|
||||
var transform = os.make_transform();
|
||||
var dist = Vector.distance(points[0],points[1]);
|
||||
transform.move(Vector.midpoint(points[0],points[1]));
|
||||
transform.rotate([0,0,-1], Vector.angle([points[1].x-points[0].x, points[1].y-points[0].y]));
|
||||
transform.scale = [dist, thickness, 1];
|
||||
poly_cache.push({
|
||||
transform:transform,
|
||||
color:color
|
||||
});
|
||||
|
||||
check_flush(render.flush_poly);
|
||||
function flush_poly()
|
||||
{
|
||||
if (poly_idx === 0) return;
|
||||
render.use_shader(polyssboshader);
|
||||
render.use_mat({});
|
||||
render.make_particle_ssbo(poly_cache.slice(0,poly_idx), poly_ssbo);
|
||||
render.draw(shape.centered_quad, poly_ssbo, poly_cache.length);
|
||||
poly_idx = 0;
|
||||
}
|
||||
|
||||
render.line = function render_line(points, color = Color.white, thickness = 1) {
|
||||
var poly = poly_e();
|
||||
var dist = vector.distance(points[0],points[1]);
|
||||
poly.transform.move(vector.midpoint(points[0],points[1]));
|
||||
poly.transform.rotate([0,0,-1], vector.angle([points[1].x-points[0].x, points[1].y-points[0].y]));
|
||||
poly.transform.scale = [dist, thickness, 1];
|
||||
poly.color = color;
|
||||
check_flush(flush_poly);
|
||||
}
|
||||
|
||||
/* All draw in screen space */
|
||||
|
@ -601,7 +622,7 @@ render.point = function(pos,size,color = Color.blue) {
|
|||
render.circle(pos,size,size,color);
|
||||
};
|
||||
|
||||
render.cross = function(pos, size, color = Color.red, thickness = 1) {
|
||||
render.cross = function render_cross(pos, size, color = Color.red, thickness = 1) {
|
||||
var a = [
|
||||
pos.add([0,size]),
|
||||
pos.add([0,-size])
|
||||
|
@ -614,7 +635,7 @@ render.cross = function(pos, size, color = Color.red, thickness = 1) {
|
|||
render.line(b,color,thickness);
|
||||
};
|
||||
|
||||
render.arrow = function(start, end, color = Color.red, wingspan = 4, wingangle = 10) {
|
||||
render.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, wingangle = 10) {
|
||||
var dir = end.sub(start).normalized();
|
||||
var wing1 = [
|
||||
Vector.rotate(dir, wingangle).scale(wingspan).add(end),
|
||||
|
@ -629,39 +650,34 @@ render.arrow = function(start, end, color = Color.red, wingspan = 4, wingangle =
|
|||
render.line(wing2,color);
|
||||
};
|
||||
|
||||
render.coordinate = function(pos, size, color) {
|
||||
render.coordinate = function render_coordinate(pos, size, color) {
|
||||
render.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color);
|
||||
render.point(pos, 2, color);
|
||||
}
|
||||
|
||||
render.boundingbox = function(bb, color = Color.white) {
|
||||
render.boundingbox = function render_boundingbox(bb, color = Color.white) {
|
||||
render.line(bbox.topoints(bb).wrapped(1), color);
|
||||
}
|
||||
|
||||
render.rectangle = function(lowerleft, upperright, color) {
|
||||
render.rectangle = function render_rectangle(lowerleft, upperright, color) {
|
||||
var transform = os.make_transform();
|
||||
var wh = [upperright.x-lowerleft.x, upperright.y-lowerleft.y];
|
||||
transform.move(Vector.midpoint(lowerleft,upperright));
|
||||
transform.scale = [wh.x,wh.y,1];
|
||||
poly_cache.push({
|
||||
transform:transform,
|
||||
color:color
|
||||
});
|
||||
check_flush(render.flush_poly);
|
||||
var poly = poly_e();
|
||||
poly.transform.move(vector.midpoint(lowerleft,upperright));
|
||||
poly.transform.scale = [wh.x,wh.y,1];
|
||||
poly.color = color;
|
||||
check_flush(flush_poly);
|
||||
};
|
||||
|
||||
render.box = function(pos, wh, color = Color.white) {
|
||||
var transform = os.make_transform();
|
||||
transform.move(pos);
|
||||
transform.scale = [wh.x,wh.y,1];
|
||||
poly_cache.push({
|
||||
transform:transform,
|
||||
color:color
|
||||
});
|
||||
check_flush(render.flush_poly);
|
||||
render.box = function render_box(pos, wh, color = Color.white) {
|
||||
var poly = poly_e();
|
||||
poly.transform.move(pos);
|
||||
poly.transform.scale = [wh.x,wh.y,1];
|
||||
poly.color = color;
|
||||
check_flush(flush_poly);
|
||||
};
|
||||
|
||||
render.window = function(pos, wh, color) { render.box(pos.add(wh.scale(0.5)),wh,color); };
|
||||
render.window = function render_window(pos, wh, color) { render.box(pos.add(wh.scale(0.5)),wh,color); };
|
||||
|
||||
render.text_bb = function(str, size = 1, wrap = -1, pos = [0,0])
|
||||
{
|
||||
|
@ -693,12 +709,12 @@ render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, ancho
|
|||
};
|
||||
|
||||
render.image = function(tex, pos, scale = [tex.width, tex.height], rotation = 0, color = Color.white) {
|
||||
check_flush();
|
||||
flush();
|
||||
var t = os.make_transform();
|
||||
t.pos = pos;
|
||||
t.scale = [scale.x/tex.width,scale.y/tex.height,1];
|
||||
render.use_shader(render.spriteshader);
|
||||
render.set_model(t);
|
||||
set_model(t);
|
||||
render.use_mat({
|
||||
shade: color,
|
||||
diffuse: tex,
|
||||
|
@ -729,7 +745,7 @@ render.slice9 = function(tex, pos, bb, scale = [tex.width,tex.height], color = C
|
|||
border = [bb.l/tex.width, bb.b/tex.height, bb.r/tex.width, bb.t/tex.height];
|
||||
|
||||
render.use_shader(slice9shader);
|
||||
render.set_model(t);
|
||||
set_model(t);
|
||||
render.use_mat({
|
||||
shade: color,
|
||||
diffuse:tex,
|
||||
|
@ -768,16 +784,16 @@ render.flush_text = function()
|
|||
render.draw(shape.quad, textssbo, amt);
|
||||
}
|
||||
|
||||
render.fontcache = {};
|
||||
var fontcache = {};
|
||||
render.set_font = function(path, size) {
|
||||
var fontstr = `${path}-${size}`;
|
||||
if (render.font && render.fontcache[fontstr] === render.font) return;
|
||||
if (!render.fontcache[fontstr]) render.fontcache[fontstr] = os.make_font(path, size);
|
||||
if (render.font && fontcache[fontstr] === render.font) return;
|
||||
if (!fontcache[fontstr]) fontcache[fontstr] = os.make_font(path, size);
|
||||
|
||||
render.flush_text();
|
||||
|
||||
gui.font_set(render.fontcache[fontstr]);
|
||||
render.font = render.fontcache[fontstr];
|
||||
gui.font_set(fontcache[fontstr]);
|
||||
render.font = fontcache[fontstr];
|
||||
}
|
||||
|
||||
render.doc = "Draw shapes in screen space.";
|
||||
|
@ -786,15 +802,14 @@ render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
|||
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
|
||||
render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
|
||||
|
||||
render.draw = function(mesh, ssbo, inst = 1)
|
||||
render.draw = function render_draw(mesh, ssbo, inst = 1)
|
||||
{
|
||||
render.sg_bind(mesh, ssbo);
|
||||
sg_bind(mesh, ssbo);
|
||||
profile.frame("gpu");
|
||||
render.spdraw(cur.bind.count, inst);
|
||||
profile.endframe();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
|
||||
// Camera viewport is [left,bottom,right,top] in relative values
|
||||
function camviewport()
|
||||
|
@ -947,7 +962,7 @@ prosperon.render = function()
|
|||
render.commit();
|
||||
}
|
||||
|
||||
prosperon.process = function() {
|
||||
prosperon.process = function process() {
|
||||
profile.frame("frame");
|
||||
var dt = profile.secs(profile.now()) - frame_t;
|
||||
frame_t = profile.secs(profile.now());
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const HMM_Vec2 v2zero = {0,0};
|
||||
const HMM_Vec2 v2one = {1,1};
|
||||
const HMM_Vec3 v3zero = {0,0,0};
|
||||
const HMM_Vec3 v3one = {1,1,1};
|
||||
const HMM_Vec4 v4zero = {0,0,0,0};
|
||||
|
||||
const HMM_Vec3 vX = {1.0,0.0,0.0};
|
||||
|
@ -17,7 +18,7 @@ const HMM_Vec3 vLEFT = {-1,0,0};
|
|||
const HMM_Vec3 vRIGHT = {1,0,0};
|
||||
|
||||
const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
|
||||
const HMM_Quat QUAT1 = {1,0,0,0};
|
||||
const HMM_Quat QUAT1 = {0,0,0,1};
|
||||
|
||||
/*
|
||||
* Angle unit conversion functions
|
||||
|
@ -262,14 +263,9 @@ HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right) {
|
|||
return Result;
|
||||
}
|
||||
|
||||
HMM_Vec2 HMM_ScaleV2(HMM_Vec2 v, double s)
|
||||
{
|
||||
return HMM_V2(v.X*s, v.Y*s);
|
||||
}
|
||||
|
||||
HMM_Vec3 HMM_ScaleV3(HMM_Vec3 v, double s)
|
||||
HMM_Vec2 HMM_ScaleV2(HMM_Vec2 v, double s)
|
||||
{
|
||||
return HMM_V3(v.x*s,v.y*s,v.z*s);
|
||||
return HMM_V2(v.X*s, v.Y*s);
|
||||
}
|
||||
|
||||
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right) {
|
||||
|
@ -529,7 +525,6 @@ float HMM_AngleV4(HMM_Vec4 a, HMM_Vec4 b)
|
|||
}
|
||||
|
||||
HMM_Vec2 HMM_NormV2(HMM_Vec2 A) {
|
||||
// HMM_MulV2F(A, 1.0/HMM_LenV2(A)+FLOAT_MIN);
|
||||
return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
|
||||
}
|
||||
|
||||
|
|
|
@ -416,6 +416,7 @@ typedef union HMM_Mat4 {
|
|||
extern const HMM_Vec2 v2zero;
|
||||
extern const HMM_Vec2 v2one;
|
||||
extern const HMM_Vec3 v3zero;
|
||||
extern const HMM_Vec3 v3one;
|
||||
extern const HMM_Vec4 v4zero;
|
||||
|
||||
typedef signed int HMM_Bool;
|
||||
|
@ -477,7 +478,6 @@ HMM_Vec4 HMM_AddV4(HMM_Vec4 Left, HMM_Vec4 Right);
|
|||
HMM_Vec2 HMM_SubV2(HMM_Vec2 Left, HMM_Vec2 Right);
|
||||
HMM_Vec3 HMM_SubV3(HMM_Vec3 Left, HMM_Vec3 Right);
|
||||
HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right);
|
||||
HMM_Vec3 HMM_ScaleV3(HMM_Vec3 v, double s);
|
||||
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right);
|
||||
HMM_Vec2 HMM_MulV2F(HMM_Vec2 Left, float Right);
|
||||
HMM_Vec3 HMM_MulV3(HMM_Vec3 Left, HMM_Vec3 Right);
|
||||
|
|
|
@ -1142,6 +1142,25 @@ JSValue js_vector_dot(JSContext *js, JSValue self, int argc, JSValue *argv) { re
|
|||
|
||||
JSC_CCALL(vector_project, return vec22js(HMM_ProjV2(js2vec2(argv[0]), js2vec2(argv[1]))))
|
||||
|
||||
JSC_CCALL(vector_midpoint,
|
||||
HMM_Vec2 a = js2vec2(argv[0]);
|
||||
HMM_Vec2 b = js2vec2(argv[1]);
|
||||
// HMM_Vec2 c = HMM_AddV2(a,b);
|
||||
// c = HMM_DivV2F(c, 2);
|
||||
return vec22js((HMM_Vec2){(a.x+b.x)/2, (a.y+b.y)/2});
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_distance,
|
||||
HMM_Vec2 a = js2vec2(argv[0]);
|
||||
HMM_Vec2 b = js2vec2(argv[1]);
|
||||
return number2js(HMM_DistV2(a,b));
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_angle,
|
||||
HMM_Vec2 a = js2vec2(argv[0]);
|
||||
return angle2js(atan2(a.y,a.x));
|
||||
)
|
||||
|
||||
/* Given a series of points p, computes a new series with them expanded on either side by d */
|
||||
HMM_Vec2 *inflatepoints(HMM_Vec2 *p, float d, int n)
|
||||
{
|
||||
|
@ -1204,11 +1223,251 @@ JSC_CCALL(vector_rotate,
|
|||
return vec22js(vec);
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_add,
|
||||
HMM_Vec4 a = js2vec4(argv[0]);
|
||||
HMM_Vec4 b = js2vec4(argv[1]);
|
||||
HMM_Vec4 c = HMM_AddV4(a,b);
|
||||
return vec42js(c);
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_norm,
|
||||
int len = js_arrlen(argv[0]);
|
||||
|
||||
switch(len) {
|
||||
case 2: return vec22js(HMM_NormV2(js2vec2(argv[0])));
|
||||
case 3: return vec32js(HMM_NormV3(js2vec3(argv[0])));
|
||||
case 4: return vec42js(HMM_NormV4(js2vec4(argv[0])));
|
||||
}
|
||||
return argv[0];
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_angle_between,
|
||||
int len = js_arrlen(argv[0]);
|
||||
switch(len) {
|
||||
case 2: return angle2js(HMM_AngleV2(js2vec2(argv[0]), js2vec2(argv[1])));
|
||||
case 3: return angle2js(HMM_AngleV3(js2vec3(argv[0]), js2vec3(argv[1])));
|
||||
case 4: return angle2js(HMM_AngleV4(js2vec4(argv[0]), js2vec4(argv[1])));
|
||||
}
|
||||
return angle2js(0);
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_lerp,
|
||||
double s = js2number(argv[0]);
|
||||
double f = js2number(argv[1]);
|
||||
double t = js2number(argv[2]);
|
||||
|
||||
return number2js((f-s)*t+s);
|
||||
)
|
||||
|
||||
int gcd(int a, int b) {
|
||||
if (b == 0)
|
||||
return a;
|
||||
return gcd(b, a % b);
|
||||
}
|
||||
|
||||
JSC_CCALL(vector_gcd,
|
||||
return number2js(gcd(js2number(argv[0]), js2number(argv[1])));
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_lcm,
|
||||
double a = js2number(argv[0]);
|
||||
double b = js2number(argv[1]);
|
||||
return number2js((a*b)/gcd(a,b));
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_clamp,
|
||||
double x = js2number(argv[0]);
|
||||
double l = js2number(argv[1]);
|
||||
double h = js2number(argv[2]);
|
||||
return number2js(x > h ? h : x < l ? l : x);
|
||||
)
|
||||
|
||||
JSC_SSCALL(vector_trimchr,
|
||||
int len = js2number(js_getpropstr(argv[0], "length"));
|
||||
char *start = str;
|
||||
|
||||
while (*start == *str2)
|
||||
start++;
|
||||
|
||||
char *end = str + len-1;
|
||||
while(*end == *str2)
|
||||
end--;
|
||||
|
||||
ret = JS_NewStringLen(js, start, end-start+1);
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_angledist,
|
||||
double a1 = js2number(argv[0]);
|
||||
double a2 = js2number(argv[1]);
|
||||
a1 = fmod(a1,1);
|
||||
a2 = fmod(a2,1);
|
||||
double dist = a2-a1;
|
||||
if (dist == 0) return number2js(dist);
|
||||
if (dist > 0) {
|
||||
if (dist > 0.5) return number2js(dist-1);
|
||||
return number2js(dist);
|
||||
}
|
||||
|
||||
if (dist < -0.5) return number2js(dist+1);
|
||||
|
||||
return number2js(dist);
|
||||
)
|
||||
|
||||
double r2()
|
||||
{
|
||||
return (double)rand() / (double)RAND_MAX ;
|
||||
}
|
||||
|
||||
double rand_range(double min, double max) {
|
||||
return r2() * (max-min) + min;
|
||||
}
|
||||
|
||||
JSC_CCALL(vector_variate,
|
||||
double n = js2number(argv[0]);
|
||||
double pct = js2number(argv[1]);
|
||||
|
||||
return number2js(n + (rand_range(-pct,pct)*n));
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_random_range, return number2js(rand_range(js2number(argv[0]), js2number(argv[1]))))
|
||||
|
||||
JSC_CCALL(vector_mean,
|
||||
double len = js_arrlen(argv[0]);
|
||||
double sum;
|
||||
for (int i = 0; i < len; i++)
|
||||
sum += js2number(js_getpropidx(argv[0], i));
|
||||
|
||||
return number2js(sum/len);
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_sum,
|
||||
double sum;
|
||||
int len = js_arrlen(argv[0]);
|
||||
for (int i = 0; i < len; i++)
|
||||
sum += js2number(js_getpropidx(argv[0], i));
|
||||
|
||||
return number2js(sum);
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_sigma,
|
||||
int len = js_arrlen(argv[0]);
|
||||
double sum;
|
||||
for (int i = 0; i < len; i++)
|
||||
sum += js2number(js_getpropidx(argv[0], i));
|
||||
|
||||
double mean = sum/(double)len;
|
||||
|
||||
double sq_diff = 0;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
double x = js2number(js_getpropidx(argv[0],i));
|
||||
sq_diff += pow(x-mean, 2);
|
||||
}
|
||||
|
||||
double variance = sq_diff/((double)len);
|
||||
|
||||
return number2js(sqrt(variance));
|
||||
)
|
||||
|
||||
JSC_CCALL(vector_median,
|
||||
int len = js_arrlen(argv[0]);
|
||||
double arr[len];
|
||||
double temp;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
arr[i] = js2number(js_getpropidx(argv[0], i));
|
||||
|
||||
for (int i = 0; i < len-1; i++) {
|
||||
for (int j = i+1; j < len; j++) {
|
||||
if (arr[i] > arr[j]) {
|
||||
temp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len % 2 == 0) return number2js((arr[len/2-1] + arr[len/2])/2.0);
|
||||
return number2js(arr[len/2]);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_vector_funcs[] = {
|
||||
MIST_FUNC_DEF(vector,dot,2),
|
||||
MIST_FUNC_DEF(vector,project,2),
|
||||
MIST_FUNC_DEF(vector, dot,2),
|
||||
MIST_FUNC_DEF(vector, project,2),
|
||||
MIST_FUNC_DEF(vector, inflate, 2),
|
||||
MIST_FUNC_DEF(vector, rotate, 2)
|
||||
MIST_FUNC_DEF(vector, rotate, 2),
|
||||
MIST_FUNC_DEF(vector, add, 2),
|
||||
MIST_FUNC_DEF(vector, midpoint, 2),
|
||||
MIST_FUNC_DEF(vector, distance, 2),
|
||||
MIST_FUNC_DEF(vector, angle, 1),
|
||||
MIST_FUNC_DEF(vector, norm, 1),
|
||||
MIST_FUNC_DEF(vector, angle_between, 2),
|
||||
MIST_FUNC_DEF(vector, lerp, 3),
|
||||
MIST_FUNC_DEF(vector, gcd, 2),
|
||||
MIST_FUNC_DEF(vector, lcm, 2),
|
||||
MIST_FUNC_DEF(vector, clamp, 3),
|
||||
MIST_FUNC_DEF(vector, trimchr, 2),
|
||||
MIST_FUNC_DEF(vector, angledist, 2),
|
||||
MIST_FUNC_DEF(vector, variate, 2),
|
||||
MIST_FUNC_DEF(vector, random_range, 2),
|
||||
MIST_FUNC_DEF(vector, mean, 1),
|
||||
MIST_FUNC_DEF(vector, sum, 1),
|
||||
MIST_FUNC_DEF(vector, sigma, 1),
|
||||
MIST_FUNC_DEF(vector, median, 1)
|
||||
};
|
||||
|
||||
#define JS_HMM_FN(OP, HMM, SIGN) \
|
||||
JSC_CCALL(array_##OP, \
|
||||
int len = js_arrlen(self); \
|
||||
if (!JS_IsArray(js, argv[0])) { \
|
||||
double n = js2number(argv[0]); \
|
||||
JSValue arr = JS_NewArray(js); \
|
||||
for (int i = 0; i < len; i++) \
|
||||
js_setprop_num(arr, i, number2js(js2number(js_getpropidx(self,i)) SIGN n)); \
|
||||
return arr; \
|
||||
} \
|
||||
switch(len) { \
|
||||
case 2: \
|
||||
return vec22js(HMM_##HMM##V2(js2vec2(self), js2vec2(argv[0]))); \
|
||||
case 3: \
|
||||
return vec32js(HMM_##HMM##V3(js2vec3(self), js2vec3(argv[0]))); \
|
||||
case 4: \
|
||||
return vec42js(HMM_##HMM##V4(js2vec4(self), js2vec4(argv[0]))); \
|
||||
} \
|
||||
\
|
||||
JSValue arr = JS_NewArray(js); \
|
||||
for (int i = 0; i < len; i++) { \
|
||||
double a = js2number(js_getpropidx(self,i)); \
|
||||
double b = js2number(js_getpropidx(argv[0],i)); \
|
||||
js_setprop_num(arr, i, number2js(a SIGN b)); \
|
||||
} \
|
||||
return arr; \
|
||||
) \
|
||||
|
||||
JS_HMM_FN(add, Add, +)
|
||||
JS_HMM_FN(sub, Sub, -)
|
||||
JS_HMM_FN(div, Div, /)
|
||||
JS_HMM_FN(scale, Mul, *)
|
||||
|
||||
JSC_CCALL(array_lerp,
|
||||
int len = js_arrlen(self);
|
||||
JSValue arr = JS_NewArray(js);
|
||||
double t = js2number(argv[1]);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
double from = js2number(js_getpropidx(self, i));
|
||||
double to = js2number(js_getpropidx(argv[0], i));
|
||||
js_setprop_num(arr, i, number2js((to - from) * t + from));
|
||||
}
|
||||
return arr;
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_array_funcs[] = {
|
||||
MIST_FUNC_DEF(array, add, 1),
|
||||
MIST_FUNC_DEF(array, sub, 1),
|
||||
MIST_FUNC_DEF(array, div,1),
|
||||
MIST_FUNC_DEF(array, scale, 1),
|
||||
MIST_FUNC_DEF(array, lerp, 2)
|
||||
};
|
||||
|
||||
JSC_CCALL(game_engine_start, engine_start(argv[0],argv[1], js2number(argv[2]), js2number(argv[3])))
|
||||
|
@ -1234,13 +1493,18 @@ static const JSCFunctionListEntry js_input_funcs[] = {
|
|||
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
||||
JSC_CCALL(prosperon_window_render, openglRender(js2vec2(argv[0])))
|
||||
JSC_CCALL(prosperon_guid,
|
||||
uint8_t bytes[16];
|
||||
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
|
||||
char uuid[37];
|
||||
snprintf(uuid, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
|
||||
bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
|
||||
return str2js(uuid);
|
||||
int bits = 32;
|
||||
char guid[33];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int r = rand();
|
||||
for (int j = 0; j < 8; j++) {
|
||||
guid[i*8+j] = "0123456789abcdef"[r%16];
|
||||
r /= 16;
|
||||
}
|
||||
}
|
||||
|
||||
guid[32] = 0;
|
||||
return str2js(guid);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_prosperon_funcs[] = {
|
||||
|
@ -1613,6 +1877,13 @@ JSC_CCALL(transform_phys2d,
|
|||
t->rotation = HMM_MulQ(t->rotation, rot);
|
||||
)
|
||||
|
||||
JSC_CCALL(transform_unit,
|
||||
transform *t = js2transform(self);
|
||||
t->pos = v3zero;
|
||||
t->rotation = QUAT1;
|
||||
t->scale = v3one;
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_transform_funcs[] = {
|
||||
CGETSET_ADD(transform, pos),
|
||||
CGETSET_ADD(transform, scale),
|
||||
|
@ -1623,6 +1894,7 @@ static const JSCFunctionListEntry js_transform_funcs[] = {
|
|||
MIST_FUNC_DEF(transform, angle, 1),
|
||||
MIST_FUNC_DEF(transform, lookat, 1),
|
||||
MIST_FUNC_DEF(transform, direction, 1),
|
||||
MIST_FUNC_DEF(transform, unit, 0),
|
||||
};
|
||||
|
||||
JSC_GETSET(dsp_node, pass, boolean)
|
||||
|
@ -2741,6 +3013,10 @@ void ffi_load() {
|
|||
JSSTATIC(damped_spring, cpConstraint_proto)
|
||||
JSSTATIC(groove, cpConstraint_proto)
|
||||
|
||||
JSValue array_proto = js_getpropstr(globalThis, "Array");
|
||||
array_proto = js_getpropstr(array_proto, "prototype");
|
||||
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, 4);
|
||||
|
||||
JS_FreeValue(js,globalThis);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue