尝试使用https://threejs.org/examples/#webgl_geometry_extrude_shapes2演示的示例SVG解析代码。它没有适当地支持' a'路径命令。我在https://gist.github.com/IkarosKappler/d3c39db08115085bcb18和我自己的一些引用https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes中发现了一些更正,但仍然出现了问题。
这是显示原始SVG的示例。
https://codepen.io/matelich/pen/rKzXZV
由于堆栈需要代码,因此这是错误地解析和解释A和路径的代码:
// - elliptical arc
case "A":
case "a":
rx = eatNum();
ry = eatNum();
xar = eatNum() * DEGS_TO_RADS;
laf = eatNum(); //large arc flag
sf = eatNum(); //sweep flag
nx = eatNum();
ny = eatNum();
if (activeCmd == "a") {
// relative
nx += x;
ny += y;
}
if(rx != 0 && ry != 0) {
console.debug(
"Read arc params: rx=" + rx + ", ry=" + ry + ", xar=" + xar + ", laf=" + laf + ", sf=" + sf + ", nx=" + nx + ", ny=" + ny
);
//might need to bring this back if absellipse doesn't work
//if (rx !== ry)
// console.warn("Forcing elliptical arc to be a circular one :(", rx, ry);
// SVG implementation notes does all the math for us! woo!
// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
// step1, using x1 as x1'
x1 = Math.cos(xar) * (x - nx) / 2 + Math.sin(xar) * (y - ny) / 2;
y1 = -Math.sin(xar) * (x - nx) / 2 + Math.cos(xar) * (y - ny) / 2;
// step 2, using x2 as cx'
console.debug( "TMP x1=" + x1 + ", y1=" + y1 + ", (rx*rx * y1*y1 + ry*ry * x1*x1)=" + (rx * rx * y1 * y1 + ry * ry * x1 * x1) + ", (rx*rx * ry*ry - rx*rx * y1*y1 - ry*ry * x1*x1)=" + (rx * rx * ry * ry - rx * rx * y1 * y1 - ry * ry * x1 * x1));
var norm = Math.sqrt(
Math.abs(
(rx * rx * ry * ry - rx * rx * y1 * y1 - ry * ry * x1 * x1) /
(rx * rx * y1 * y1 + ry * ry * x1 * x1)
)
);
if (laf === sf) norm = -norm;
x2 = norm * rx * y1 / ry;
y2 = norm * -ry * x1 / rx;
console.debug("TMP norm=" + norm + ", x2=" + x2 + ", y2=" + y2);
// step 3
cx = Math.cos(xar) * x2 - Math.sin(xar) * y2 + (x + nx) / 2;
cy = Math.sin(xar) * x2 + Math.cos(xar) * y2 + (y + ny) / 2;
console.debug("TMP cx=" + cx + ", cy=" + cy);
var u = new THREE.Vector2(1, 0),
v = new THREE.Vector2((x1 - x2) / rx, (y1 - y2) / ry);
var startAng = Math.acos(u.dot(v) / u.length() / v.length());
if (u.x * v.y - u.y * v.x < 0) startAng = -startAng;
// we can reuse 'v' from start angle as our 'u' for delta angle
u.x = (-x1 - x2) / rx;
u.y = (-y1 - y2) / ry;
var deltaAng = Math.acos(v.dot(u) / v.length() / u.length());
// This normalization ends up making our curves fail to triangulate...
if (u.x * v.y - u.y * v.x < 0) deltaAng = -deltaAng;
if (!sf && deltaAng > 0) deltaAng -= Math.PI * 2;
if (sf && deltaAng < 0) deltaAng += Math.PI * 2;
console.debug(
"Building arc from values: cx=" + cx + ", cy=" + cy + ", startAng=" + startAng + ", deltaAng=" + deltaAng + ", endAng=" + (startAng + deltaAng) + ", sweepFlag=" + sf );
// path.absarc(cx, cy, rx, startAng, startAng + deltaAng, sf);
path.absellipse(cx, cy, rx, ry, startAng, startAng + deltaAng, sf);
} else {
path.lineTo(nx, ny);
}
或者,也许它只是我的ShapePath黑客?
THREE.ShapePath.prototype.absarc = function( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
this.currentPath.absarc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise);
};
THREE.ShapePath.prototype.absellipse = function( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise ) {
this.currentPath.absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise );
};
答案 0 :(得分:2)
您仍然可以使用SVGLoader加载SVG并检索ShapePath对象的数组。然后,您可以使用ShapePath.toShapes并使用这些形状来创建ExtrudeBufferGeometry
&#39; s。它实际上与webgl_loader_svg.html
中的工作流程相同,只是使用ExtrudeBufferGeometry