add shaped path routing
This commit is contained in:
parent
cbc363d49f
commit
64380b6ef6
4 changed files with 157 additions and 25 deletions
|
|
@ -125,7 +125,14 @@
|
||||||
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),
|
faces: codec.allocFloat32Array(layer.faces),
|
||||||
color: layer.color
|
color: layer.color,
|
||||||
|
paths: layer.paths.map(path => {
|
||||||
|
return {
|
||||||
|
index: path.index,
|
||||||
|
faces: path.faces,
|
||||||
|
z: path.z
|
||||||
|
}
|
||||||
|
})
|
||||||
} })
|
} })
|
||||||
};
|
};
|
||||||
return enc;
|
return enc;
|
||||||
|
|
@ -138,7 +145,8 @@
|
||||||
polys: decode(v.data[i].polys, state),
|
polys: decode(v.data[i].polys, state),
|
||||||
lines: decodePointArray(v.data[i].lines),
|
lines: decodePointArray(v.data[i].lines),
|
||||||
faces: v.data[i].faces,
|
faces: v.data[i].faces,
|
||||||
color: v.data[i].color
|
color: v.data[i].color,
|
||||||
|
paths: v.data[i].paths
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return render;
|
return render;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
lines: [],
|
lines: [],
|
||||||
polys: [],
|
polys: [],
|
||||||
faces: [],
|
faces: [],
|
||||||
|
paths: [],
|
||||||
color: colors || {
|
color: colors || {
|
||||||
line: 0,
|
line: 0,
|
||||||
face: 0
|
face: 0
|
||||||
|
|
@ -37,33 +38,21 @@
|
||||||
|
|
||||||
addPoly(poly) {
|
addPoly(poly) {
|
||||||
this.current.polys.push(poly);
|
this.current.polys.push(poly);
|
||||||
// const lines = this.current.lines;
|
|
||||||
// const points = poly.points;
|
|
||||||
// const len = points.length;
|
|
||||||
// for (let i=1; i<len; i++) {
|
|
||||||
// lines.push(points[i-1], points[i]);
|
|
||||||
// }
|
|
||||||
// if (!poly.open) {
|
|
||||||
// lines.push(points[len - 1], points[0]);
|
|
||||||
// }
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addPolys(arr) {
|
addPolys(polys) {
|
||||||
for (let i=0; i<arr.length; i++) {
|
polys = flat(polys);
|
||||||
this.addPoly(arr[i]);
|
for (let i=0; i<polys.length; i++) {
|
||||||
|
this.addPoly(polys[i]);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addFlat(polys, options) {
|
addFlats(polys, options) {
|
||||||
let opts = options || {};
|
const opts = options || {};
|
||||||
let offset = opts.offset || 1;
|
const offset = opts.offset || 1;
|
||||||
if (Array.isArray(polys)) {
|
polys = flat(polys);
|
||||||
polys = POLY.flatten(polys, [], true);
|
|
||||||
} else {
|
|
||||||
polys = POLY.flatten([polys], [], true);
|
|
||||||
}
|
|
||||||
if (!polys.length) {
|
if (!polys.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +70,118 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addPaths(polys, options) {
|
||||||
|
const opts = options || {};
|
||||||
|
const offset = opts.offset || 1;
|
||||||
|
polys = flat(polys);
|
||||||
|
if (!polys.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const profile = new THREE.Shape();
|
||||||
|
profile.moveTo(-offset, -offset);
|
||||||
|
profile.lineTo(-offset, offset);
|
||||||
|
profile.lineTo( offset, offset);
|
||||||
|
profile.lineTo( offset, -offset);
|
||||||
|
|
||||||
|
polys.forEach(poly => {
|
||||||
|
const contour = [];
|
||||||
|
poly.points.forEach(p => {
|
||||||
|
contour.push(new THREE.Vector2(p.x, p.y));
|
||||||
|
});
|
||||||
|
const {index, faces} = ProfiledContourGeometry(profile, contour, true);
|
||||||
|
this.current.paths.push({ index, faces, z: poly.getZ() });
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function flat(polys) {
|
||||||
|
if (Array.isArray(polys)) {
|
||||||
|
return POLY.flatten(polys, [], true);
|
||||||
|
} else {
|
||||||
|
return POLY.flatten([polys], [], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProfiledContourGeometry(profileShape, contour, contourClosed) {
|
||||||
|
|
||||||
|
contourClosed = contourClosed !== undefined ? contourClosed : true;
|
||||||
|
|
||||||
|
let profileGeometry = new THREE.ShapeBufferGeometry(profileShape);
|
||||||
|
profileGeometry.rotateX(Math.PI * .5);
|
||||||
|
|
||||||
|
let profile = profileGeometry.attributes.position;
|
||||||
|
let faces = new Float32Array(profile.count * contour.length * 3);
|
||||||
|
|
||||||
|
for (let i = 0; i < contour.length; i++) {
|
||||||
|
let v1 = new THREE.Vector2().subVectors(contour[i - 1 < 0 ? contour.length - 1 : i - 1], contour[i]);
|
||||||
|
let v2 = new THREE.Vector2().subVectors(contour[i + 1 == contour.length ? 0 : i + 1], contour[i]);
|
||||||
|
let angle = v2.angle() - v1.angle();
|
||||||
|
let halfAngle = angle * .5;
|
||||||
|
let hA = halfAngle;
|
||||||
|
let tA = v2.angle() + Math.PI * .5;
|
||||||
|
|
||||||
|
if (!contourClosed){
|
||||||
|
if (i == 0 || i == contour.length - 1) {hA = Math.PI * .5;}
|
||||||
|
if (i == contour.length - 1) {tA = v1.angle() - Math.PI * .5;}
|
||||||
|
}
|
||||||
|
|
||||||
|
let shift = Math.tan(hA - Math.PI * .5);
|
||||||
|
let shiftMatrix = new THREE.Matrix4().set(
|
||||||
|
1, 0, 0, 0,
|
||||||
|
-shift, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
);
|
||||||
|
|
||||||
|
let tempAngle = tA;
|
||||||
|
let rotationMatrix = new THREE.Matrix4().set(
|
||||||
|
Math.cos(tempAngle), -Math.sin(tempAngle), 0, 0,
|
||||||
|
Math.sin(tempAngle), Math.cos(tempAngle), 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
);
|
||||||
|
|
||||||
|
let translationMatrix = new THREE.Matrix4().set(
|
||||||
|
1, 0, 0, contour[i].x,
|
||||||
|
0, 1, 0, contour[i].y,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
let cloneProfile = profile.clone();
|
||||||
|
cloneProfile.applyMatrix4(shiftMatrix);
|
||||||
|
cloneProfile.applyMatrix4(rotationMatrix);
|
||||||
|
cloneProfile.applyMatrix4(translationMatrix);
|
||||||
|
|
||||||
|
faces.set(cloneProfile.array, cloneProfile.count * i * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = [];
|
||||||
|
let lastCorner = contourClosed == false ? contour.length - 1: contour.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < lastCorner; i++) {
|
||||||
|
for (let j = 0; j < profile.count; j++) {
|
||||||
|
let currCorner = i;
|
||||||
|
let nextCorner = i + 1 == contour.length ? 0 : i + 1;
|
||||||
|
let currPoint = j;
|
||||||
|
let nextPoint = j + 1 == profile.count ? 0 : j + 1;
|
||||||
|
|
||||||
|
let a = nextPoint + profile.count * currCorner;
|
||||||
|
let b = currPoint + profile.count * currCorner;
|
||||||
|
let c = currPoint + profile.count * nextCorner;
|
||||||
|
let d = nextPoint + profile.count * nextCorner;
|
||||||
|
|
||||||
|
index.push(a, b, d);
|
||||||
|
index.push(b, c, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {index, faces};
|
||||||
}
|
}
|
||||||
|
|
||||||
self.kiri.Render = Render;
|
self.kiri.Render = Render;
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [layer, data] of Object.entries(render.layers)) {
|
for (const [layer, data] of Object.entries(render.layers)) {
|
||||||
const { polys, lines, faces } = data;
|
const { polys, lines, faces, paths } = data;
|
||||||
if (polys.length || lines.length) {
|
if (polys.length || lines.length) {
|
||||||
const mat = new THREE.LineBasicMaterial({ color: data.color.line });
|
const mat = new THREE.LineBasicMaterial({ color: data.color.line });
|
||||||
const geo = new THREE.Geometry(), vert = geo.vertices;
|
const geo = new THREE.Geometry(), vert = geo.vertices;
|
||||||
|
|
@ -79,6 +79,29 @@
|
||||||
mesh.receiveShadow = true;
|
mesh.receiveShadow = true;
|
||||||
group.add(mesh);
|
group.add(mesh);
|
||||||
}
|
}
|
||||||
|
if (paths.length) {
|
||||||
|
const mat = new THREE.MeshPhongMaterial({
|
||||||
|
transparent: true,
|
||||||
|
shininess: 100,
|
||||||
|
specular: 0x181818,
|
||||||
|
opacity: 1,
|
||||||
|
color: data.color.face,
|
||||||
|
side: THREE.DoubleSide
|
||||||
|
});
|
||||||
|
paths.forEach((path, i) => {
|
||||||
|
const { index, faces, z } = path;
|
||||||
|
const geo = new THREE.BufferGeometry();
|
||||||
|
geo.setAttribute('position', new THREE.BufferAttribute(faces, 3));
|
||||||
|
geo.setIndex(index);
|
||||||
|
geo.computeFaceNormals();
|
||||||
|
geo.computeVertexNormals();
|
||||||
|
const mesh = new THREE.Mesh(geo, mat);
|
||||||
|
mesh.position.z = z;
|
||||||
|
mesh.castShadow = true;
|
||||||
|
mesh.receiveShadow = true;
|
||||||
|
group.add(mesh);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slice.view.add(group);
|
slice.view.add(group);
|
||||||
|
|
|
||||||
|
|
@ -124,8 +124,9 @@
|
||||||
// sliceAll.push(data.slice);
|
// sliceAll.push(data.slice);
|
||||||
// data.slice.output()
|
// data.slice.output()
|
||||||
// .setLayer("debug", {face: 0xff0000, line: 0})
|
// .setLayer("debug", {face: 0xff0000, line: 0})
|
||||||
// // .addFlat(POLY.setZ(tshadow.clone(true), data.z), {offset: 1, outline: true});
|
// // .addFlats(POLY.setZ(tshadow.clone(true), data.z), {offset: 1, outline: true});
|
||||||
// .addPolys(POLY.setZ(tshadow.clone(true), data.z));
|
// // .addPolys(POLY.setZ(tshadow.clone(true), data.z));
|
||||||
|
// .addPaths(POLY.setZ(tshadow.clone(true), data.z));
|
||||||
updateOp(index, total);
|
updateOp(index, total);
|
||||||
}, genso: true });
|
}, genso: true });
|
||||||
let shadowTop = terrain[terrain.length - 1];
|
let shadowTop = terrain[terrain.length - 1];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue