improve codec readbility
This commit is contained in:
parent
cf6a4b32d8
commit
01c13a18e7
1 changed files with 179 additions and 175 deletions
|
|
@ -11,7 +11,7 @@
|
||||||
gapp.register("kiri.codec", [], (root, exports) => {
|
gapp.register("kiri.codec", [], (root, exports) => {
|
||||||
|
|
||||||
const { base, kiri } = root;
|
const { base, kiri } = root;
|
||||||
const handlers = {};
|
const decoders = {};
|
||||||
const freeMem = true;
|
const freeMem = true;
|
||||||
|
|
||||||
const codec = exports({
|
const codec = exports({
|
||||||
|
|
@ -25,6 +25,14 @@ const codec = exports({
|
||||||
toCodable
|
toCodable
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const TYPE = {
|
||||||
|
WIDGET: 100,
|
||||||
|
SLICE: 200,
|
||||||
|
TOP: 300,
|
||||||
|
POLY: 400,
|
||||||
|
LAYERS: 500,
|
||||||
|
};
|
||||||
|
|
||||||
function toCodable(object) {
|
function toCodable(object) {
|
||||||
switch (typeof object) {
|
switch (typeof object) {
|
||||||
case 'function':
|
case 'function':
|
||||||
|
|
@ -96,7 +104,7 @@ function encode(o, state) {
|
||||||
return o;
|
return o;
|
||||||
case 'object':
|
case 'object':
|
||||||
if (o.encode) return o.encode(state);
|
if (o.encode) return o.encode(state);
|
||||||
return genOEncode(o, state);
|
return genericObjectEncode(o, state);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -114,17 +122,17 @@ function decode(o, state) {
|
||||||
case 'number':
|
case 'number':
|
||||||
return o;
|
return o;
|
||||||
case 'object':
|
case 'object':
|
||||||
if (o.type && handlers[o.type]) return handlers[o.type](o,state);
|
if (o.type && decoders[o.type]) return decoders[o.type](o,state);
|
||||||
return genODecode(o, state);
|
return genODecode(o, state);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerDecoder(type, handler) {
|
function registerDecoder(type, handler) {
|
||||||
handlers[type] = handler;
|
decoders[type] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
function genOEncode(o, state) {
|
function genericObjectEncode(o, state) {
|
||||||
if (o instanceof Float32Array) return o;
|
if (o instanceof Float32Array) return o;
|
||||||
let out = {};
|
let out = {};
|
||||||
for (let k in o) {
|
for (let k in o) {
|
||||||
|
|
@ -142,42 +150,80 @@ function genODecode(o, state) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ******************************************************************
|
function encodePointArray(points, state) {
|
||||||
* Object Class CODEC Functions
|
if (!points) {
|
||||||
******************************************************************* */
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
kiri.Widget.prototype.encode = function(state) {
|
const length = points.length;
|
||||||
const json = state._json_;
|
|
||||||
const geo = this.getGeoVertices();
|
|
||||||
const coded = {
|
|
||||||
type: 'widget',
|
|
||||||
id: this.id,
|
|
||||||
ver: 1, // for better future encodings
|
|
||||||
json: json, // safe for JSON (float32array mess)
|
|
||||||
group: this.group.id,
|
|
||||||
track: this.track,
|
|
||||||
geo: json ? Array.from(geo) : geo
|
|
||||||
};
|
|
||||||
return coded;
|
|
||||||
};
|
|
||||||
|
|
||||||
registerDecoder('widget', function(v, state) {
|
if (length === 0) {
|
||||||
const id = v.id,
|
return points;
|
||||||
group = v.group || id,
|
}
|
||||||
track = v.track || undefined,
|
|
||||||
widget = kiri.newWidget(id, kiri.Widget.Groups.forid(group));
|
const array = codec.allocFloat32Array(length * 3, state.zeros);
|
||||||
widget.loadVertices(v.json ? v.geo.toFloat32() : v.geo);
|
|
||||||
widget.saved = Date.now();
|
for (let i=0, pos=0, point; i<length; i++) {
|
||||||
if (track && track.pos) {
|
point = points[i];
|
||||||
widget.track = track;
|
array[pos++] = point.x;
|
||||||
widget.move(track.pos.x, track.pos.y, track.pos.z, true);
|
array[pos++] = point.y;
|
||||||
}
|
array[pos++] = point.z;
|
||||||
return widget;
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function decodePointArray(array) {
|
||||||
|
if (!array) return null;
|
||||||
|
|
||||||
|
const length = array.length;
|
||||||
|
const points = new Array(length / 3);
|
||||||
|
|
||||||
|
for (let vid=0, pid=0; vid < length; ) {
|
||||||
|
points[pid++] = base.newPoint(array[vid++], array[vid++], array[vid++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- Widget Codec -----
|
||||||
|
|
||||||
|
kiri.Widget.prototype.encode = function(state) {
|
||||||
|
const json = state._json_;
|
||||||
|
const geo = this.getGeoVertices();
|
||||||
|
const coded = {
|
||||||
|
type: TYPE.WIDGET,
|
||||||
|
id: this.id,
|
||||||
|
ver: 1, // for better future encodings
|
||||||
|
json: json, // safe for JSON (float32array mess)
|
||||||
|
group: this.group.id,
|
||||||
|
track: this.track,
|
||||||
|
geo: json ? Array.from(geo) : geo
|
||||||
|
};
|
||||||
|
return coded;
|
||||||
|
};
|
||||||
|
|
||||||
|
registerDecoder(TYPE.WIDGET, function(v, state) {
|
||||||
|
const id = v.id,
|
||||||
|
group = v.group || id,
|
||||||
|
track = v.track || undefined,
|
||||||
|
widget = kiri.newWidget(id, kiri.Widget.Groups.forid(group));
|
||||||
|
|
||||||
|
widget.loadVertices(v.json ? v.geo.toFloat32() : v.geo);
|
||||||
|
widget.saved = Date.now();
|
||||||
|
if (track && track.pos) {
|
||||||
|
widget.track = track;
|
||||||
|
widget.move(track.pos.x, track.pos.y, track.pos.z, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return widget;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----- Slice Codec -----
|
||||||
|
|
||||||
kiri.Slice.prototype.encode = function(state) {
|
kiri.Slice.prototype.encode = function(state) {
|
||||||
const rv = {
|
const rv = {
|
||||||
type: 'slice',
|
type: TYPE.SLICE,
|
||||||
z: this.z,
|
z: this.z,
|
||||||
index: this.index,
|
index: this.index,
|
||||||
layers: encode(this.layers, state)
|
layers: encode(this.layers, state)
|
||||||
|
|
@ -187,7 +233,7 @@ kiri.Slice.prototype.encode = function(state) {
|
||||||
return rv;
|
return rv;
|
||||||
};
|
};
|
||||||
|
|
||||||
registerDecoder('slice', function(v, state) {
|
registerDecoder(TYPE.SLICE, function(v, state) {
|
||||||
let slice = kiri.newSlice(v.z, state.mesh ? state.mesh.newGroup() : null);
|
let slice = kiri.newSlice(v.z, state.mesh ? state.mesh.newGroup() : null);
|
||||||
|
|
||||||
slice.index = v.index;
|
slice.index = v.index;
|
||||||
|
|
@ -196,13 +242,96 @@ registerDecoder('slice', function(v, state) {
|
||||||
return slice;
|
return slice;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ----- Slice.Top Codec -----
|
||||||
|
|
||||||
|
kiri.Top.prototype.encode = function(state) {
|
||||||
|
let obj = {
|
||||||
|
type: TYPE.TOP,
|
||||||
|
poly: encode(this.poly, state)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (state.full) {
|
||||||
|
obj.last = encode(this.last, state);
|
||||||
|
obj.shells = encode(this.shells, state);
|
||||||
|
obj.fill_off = encode(this.fill_off, state);
|
||||||
|
obj.fill_lines = encode(this.fill_lines, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
registerDecoder(TYPE.TOP, function(v, state) {
|
||||||
|
let top = kiri.newTop(decode(v.poly, state));
|
||||||
|
if (state.full) {
|
||||||
|
top.last = decode(v.last, state);
|
||||||
|
top.shells = decode(v.shells, state);
|
||||||
|
top.fill_off = decode(v.fill_off, state);
|
||||||
|
top.fill_lines = decode(v.fill_lines, state);
|
||||||
|
}
|
||||||
|
return top;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----- Polygon Codec -----
|
||||||
|
|
||||||
|
base.Polygon.prototype.encode = function(state) {
|
||||||
|
if (!state.poly) state.poly = {};
|
||||||
|
|
||||||
|
let cached = state.poly[this.id];
|
||||||
|
if (cached) {
|
||||||
|
return { type: TYPE.POLY, ref: this.id };
|
||||||
|
}
|
||||||
|
|
||||||
|
state.poly[this.id] = this;
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: TYPE.POLY,
|
||||||
|
id: this.id,
|
||||||
|
array: encodePointArray(this.points, state),
|
||||||
|
inner: encode(this.inner, state),
|
||||||
|
parent: encode(this.parent, state),
|
||||||
|
depth: this.depth,
|
||||||
|
color: this.color,
|
||||||
|
open: this.open
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
registerDecoder(TYPE.POLY, function(v, state) {
|
||||||
|
if (!state.poly) state.poly = {};
|
||||||
|
|
||||||
|
// return polygon from cached reference
|
||||||
|
if (v.ref) {
|
||||||
|
return state.poly[v.ref];
|
||||||
|
}
|
||||||
|
|
||||||
|
const array = v.array;
|
||||||
|
const length = array.length;
|
||||||
|
const poly = base.newPolygon();
|
||||||
|
|
||||||
|
for (let vid = 0; vid < length; ) {
|
||||||
|
poly.push(base.newPoint(array[vid++], array[vid++], array[vid++]));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.poly[v.id] = poly;
|
||||||
|
|
||||||
|
poly.id = v.id;
|
||||||
|
poly.open = v.open;
|
||||||
|
poly.inner = decode(v.inner, state);
|
||||||
|
poly.parent = decode(v.parent, state);
|
||||||
|
poly.depth = v.depth;
|
||||||
|
poly.color = v.color;
|
||||||
|
|
||||||
|
return poly;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----- Layers Codec -----
|
||||||
|
|
||||||
kiri.Layers.prototype.encode = function(state) {
|
kiri.Layers.prototype.encode = function(state) {
|
||||||
let zeros = state.zeros;
|
let zeros = state.zeros;
|
||||||
let enc = {
|
let enc = {
|
||||||
type: 'layers',
|
type: TYPE.LAYERS,
|
||||||
layers: Object.keys(this.layers),
|
layers: Object.keys(this.layers),
|
||||||
data: Object.values(this.layers).map(layer => {
|
data: Object.values(this.layers).map(layer => {
|
||||||
const e = {
|
return {
|
||||||
polys: encode(layer.polys, state),
|
polys: encode(layer.polys, state),
|
||||||
lines: encodePointArray(layer.lines, state),
|
lines: encodePointArray(layer.lines, state),
|
||||||
faces: codec.allocFloat32Array(layer.faces, zeros),
|
faces: codec.allocFloat32Array(layer.faces, zeros),
|
||||||
|
|
@ -220,9 +349,7 @@ kiri.Layers.prototype.encode = function(state) {
|
||||||
}),
|
}),
|
||||||
cpath: layer.cpath || codec.undef,
|
cpath: layer.cpath || codec.undef,
|
||||||
off: layer.off
|
off: layer.off
|
||||||
};
|
}
|
||||||
// console.log('-->',layer,e,zeros.length);
|
|
||||||
return e;
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
// aggressively free memory
|
// aggressively free memory
|
||||||
|
|
@ -230,16 +357,18 @@ kiri.Layers.prototype.encode = function(state) {
|
||||||
return enc;
|
return enc;
|
||||||
};
|
};
|
||||||
|
|
||||||
registerDecoder('layers', function(v, state) {
|
registerDecoder(TYPE.LAYERS, function(v, state) {
|
||||||
let render = new kiri.Layers();
|
const render = new kiri.Layers();
|
||||||
for (let i=0; i<v.layers.length; i++) {
|
const { layers } = v;
|
||||||
|
|
||||||
|
for (let i=0; i<layers.length; i++) {
|
||||||
const data = v.data[i];
|
const data = v.data[i];
|
||||||
const d = render.layers[v.layers[i]] = {
|
const d = render.layers[layers[i]] = {
|
||||||
polys: decode(data.polys, state),
|
polys: decode(data.polys, state),
|
||||||
cpoly: data.cpoly,
|
cpoly: data.cpoly,
|
||||||
lines: decodePointArray(data.lines),
|
lines: decodePointArray(data.lines),
|
||||||
faces: codec.allocFloat32Array(data.faces),
|
faces: codec.allocFloat32Array(data.faces),
|
||||||
norms: data.norms ? codec.allocFloat32Array(data.norms) : undefined,
|
norms: codec.allocFloat32Array(data.norms),
|
||||||
cface: data.cface,
|
cface: data.cface,
|
||||||
color: data.color,
|
color: data.color,
|
||||||
paths: data.paths.map(lp => {
|
paths: data.paths.map(lp => {
|
||||||
|
|
@ -247,7 +376,7 @@ registerDecoder('layers', function(v, state) {
|
||||||
z: lp.z,
|
z: lp.z,
|
||||||
index: lp.index,
|
index: lp.index,
|
||||||
faces: codec.allocFloat32Array(lp.faces),
|
faces: codec.allocFloat32Array(lp.faces),
|
||||||
norms: lp.norms ? codec.allocFloat32Array(lp.norms) : undefined
|
norms: codec.allocFloat32Array(lp.norms)
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
cpath: data.cpath,
|
cpath: data.cpath,
|
||||||
|
|
@ -275,134 +404,9 @@ registerDecoder('layers', function(v, state) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// console.log('<--',d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return render;
|
return render;
|
||||||
});
|
});
|
||||||
|
|
||||||
kiri.Top.prototype.encode = function(state) {
|
|
||||||
let obj = {
|
|
||||||
type: 'top',
|
|
||||||
poly: encode(this.poly, state)
|
|
||||||
};
|
|
||||||
if (state.full) {
|
|
||||||
obj.last = encode(this.last, state);
|
|
||||||
obj.shells = encode(this.shells, state);
|
|
||||||
obj.fill_off = encode(this.fill_off, state);
|
|
||||||
obj.fill_lines = encode(this.fill_lines, state);
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
};
|
|
||||||
|
|
||||||
registerDecoder('top', function(v, state) {
|
|
||||||
let top = kiri.newTop(decode(v.poly, state));
|
|
||||||
if (state.full) {
|
|
||||||
top.last = decode(v.last, state);
|
|
||||||
top.shells = decode(v.shells, state);
|
|
||||||
top.fill_off = decode(v.fill_off, state);
|
|
||||||
top.fill_lines = decode(v.fill_lines, state);
|
|
||||||
}
|
|
||||||
return top;
|
|
||||||
});
|
|
||||||
|
|
||||||
function encodePointArray(points, state, z) {
|
|
||||||
if (!points) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (points.length === 0) {
|
|
||||||
return points;
|
|
||||||
}
|
|
||||||
|
|
||||||
let array = codec.allocFloat32Array(points.length * 3, state.zeros),
|
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
points.forEach(function(point) {
|
|
||||||
if (state.rotate) {
|
|
||||||
if (state.centerz) {
|
|
||||||
point.z -= state.centerz;
|
|
||||||
}
|
|
||||||
let v = new THREE.Vector3(point.x, point.y, point.z);
|
|
||||||
v.applyMatrix4(state.rotate);
|
|
||||||
point = {x: v.x, y: v.y, z: v.z};
|
|
||||||
if (state.centerz) {
|
|
||||||
point.z += state.centerz;
|
|
||||||
}
|
|
||||||
if (state.movez) {
|
|
||||||
point.z -= state.movez;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
array[pos++] = point.x;
|
|
||||||
array[pos++] = point.y;
|
|
||||||
array[pos++] = z !== undefined ? z : point.z;
|
|
||||||
});
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decodePointArray(array) {
|
|
||||||
if (!array) return null;
|
|
||||||
|
|
||||||
let vid = 0,
|
|
||||||
pid = 0,
|
|
||||||
points = new Array(array.length/3);
|
|
||||||
|
|
||||||
while (vid < array.length) {
|
|
||||||
points[pid++] = base.newPoint(array[vid++], array[vid++], array[vid++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return points;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Polygon.prototype.encode = function(state) {
|
|
||||||
if (!state.poly) state.poly = {};
|
|
||||||
|
|
||||||
let cached = state.poly[this.id];
|
|
||||||
|
|
||||||
if (cached) {
|
|
||||||
return { type: 'poly', ref: this.id };
|
|
||||||
}
|
|
||||||
|
|
||||||
state.poly[this.id] = this;
|
|
||||||
return {
|
|
||||||
type: 'poly',
|
|
||||||
id: this.id,
|
|
||||||
array: encodePointArray(this.points, state, this.z),
|
|
||||||
inner: encode(this.inner, state),
|
|
||||||
parent: encode(this.parent, state),
|
|
||||||
depth: this.depth,
|
|
||||||
color: this.color,
|
|
||||||
open: this.open
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
registerDecoder('poly', function(v, state) {
|
|
||||||
if (!state.poly) state.poly = {};
|
|
||||||
|
|
||||||
if (v.ref) return state.poly[v.ref];
|
|
||||||
|
|
||||||
let poly = base.newPolygon(),
|
|
||||||
vid = 0;
|
|
||||||
|
|
||||||
// if passed a normal array, convert to float32
|
|
||||||
if (v.array.toFloat32) {
|
|
||||||
v.array = v.array.toFloat32();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (vid < v.array.length) {
|
|
||||||
poly.push(base.newPoint(v.array[vid++], v.array[vid++], v.array[vid++]));
|
|
||||||
}
|
|
||||||
|
|
||||||
poly.id = v.id;
|
|
||||||
poly.open = v.open;
|
|
||||||
|
|
||||||
state.poly[v.id] = poly;
|
|
||||||
|
|
||||||
poly.inner = decode(v.inner, state);
|
|
||||||
poly.parent = decode(v.parent, state);
|
|
||||||
poly.depth = v.depth;
|
|
||||||
poly.color = v.color;
|
|
||||||
|
|
||||||
return poly;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue