three.js - Three.js 上 ShapeBufferGeometry 的 uv 坐标差异
问题描述
我正在ShapeBufferGeometry
以我在 three.js 源代码中看到的方式在 2d 中生成 uv 坐标,但必须缺少一些东西。我找不到原因,但是对于某些形状,相对于由三个计算的 uv,我计算的点是“某种”的倒序。其他时候,我的积分是商品,等于按三计算的积分。
我做了一个简单的演示,我根据 svg 路径创建了 4 个形状(官方 svg 加载器的简单形式)。对于每个形状,我都创建了自己的 uv 点,并用三个计算的 vs 点来面对它们。由于某种原因,第二组uvs是错误的。
我的算法缺少什么?即使在 three.js 源代码中,2d 形状上的 uv 点也不是这样计算的吗?
const {Shape, ShapeBufferGeometry} = THREE;
const points2array = points =>
points.reduce((tot, point, i) => {
const idx = i * 2;
tot[idx] = point.x;
tot[idx + 1] = point.y;
return tot;
}, new Float32Array((points.length - 1) * 2));
const arrayAreEquals = (a1, a2) => {
return a1.join("-") === a2.join("-");
};
const parseSvgPath = definition => {
const p = new Shape();
let lastX = 0;
let lastY = 0;
definition.forEach(bs => {
switch (bs[0]) {
case "M":
p.moveTo(bs[1], bs[2]);
lastX = bs[1];
lastY = bs[2];
break;
case "H":
p.lineTo(bs[1], lastY);
lastX = bs[1];
break;
case "V":
p.lineTo(lastX, bs[1]);
lastY = bs[1];
break;
case "L":
p.lineTo(bs[1], bs[2]);
lastX = bs[1];
lastY = bs[2];
break;
case "C":
p.bezierCurveTo(bs[1], bs[2], bs[3], bs[4], bs[5], bs[6]);
lastX = bs[5];
lastY = bs[6];
break;
default:
break;
}
});
return p;
};
const path1 = [
["M", 86.1843823832321, 872.5106859767442],
[
"C",
86.1843823832321,
837.5758574244353,
86.1843823832321,
802.6410288721266,
86.1843823832321,
767.7062003198178
],
[
"C",
77.62876350586899,
767.6487330044671,
70.52307758179892,
761.3164804522894,
69.16676572516424,
752.9424605076606
],
[
"C",
69.16676572516424,
797.7197823857083,
69.16676572516424,
842.4971039108538,
69.16676572516424,
887.2744257889015
],
[
"C",
70.52307758179892,
878.9004061971749,
77.62876350586899,
872.5682394002545,
86.1843823832321,
872.5106859767442
],
["Z"]
];
const path2 = [
["M", 172.65222400571358, 137.48388635774268],
["H", 189.6698420753906],
["V", 224.78143268159283],
["H", 172.65222400571358],
["V", 137.48388635774268],
["Z"]
];
const path3 = [
["M", 207.14740017508217, 140.2259332997697],
[
"C",
207.14740017508217,
162.57569399538315,
207.14740017508217,
184.9254546909966,
207.14740017508217,
207.27521503370772
],
[
"C",
212.81992129835598,
207.27521503370772,
218.49246359576745,
207.27521503370772,
224.16500624608122,
207.27521503370772
],
[
"C",
224.16500624608122,
189.8467227044548,
224.16500624608122,
172.41821943523075,
224.16500624608122,
154.98971616600673
],
[
"C",
215.6093870158158,
154.93218426953638,
208.50369615111362,
148.5999962984784,
207.14740017508217,
140.2259332997697
],
["Z"]
];
const path4 = [
["M", 241.64254387743972, 259.9104933629545],
[
"C",
241.64254387743972,
266.86288841179913,
245.7391956877056,
273.23298585307725,
252.1793827006818,
275.9596857801452
],
[
"C",
258.63565958794584,
278.69319248665875,
266.044712322569,
277.1609193114356,
270.93427418233006,
272.1613119293537
],
[
"C",
275.807530897404,
267.1784194115222,
277.2311807465509,
259.739448326223,
274.6196949488009,
253.29540585568543
],
[
"C",
272.0027169326503,
246.83783664022096,
265.7852479689919,
242.52102990999816,
258.7751272803175,
242.52102990999816
],
[
"C",
258.7368084434364,
242.52102990999816,
258.6984684324176,
242.52102990999816,
258.6601495955365,
242.52102990999816
],
[
"C",
258.6601495955365,
230.85035448266098,
258.6601495955365,
219.17970093526603,
258.6601495955365,
207.50904703496877
],
[
"C",
249.12653188515915,
207.57398846800282,
241.64254352453744,
215.45796440533448,
241.64254352453744,
224.89814382244174
],
[
"C",
241.64254387743972,
236.56892723788087,
241.64254387743972,
248.23968877337776,
241.64254387743972,
259.9104933629545
],
["Z"]
];
const shape1 = parseSvgPath(path1);
const geometry1 = new ShapeBufferGeometry(shape1);
const shape2 = parseSvgPath(path2);
const geometry2 = new ShapeBufferGeometry(shape2);
const shape3 = parseSvgPath(path3);
const geometry3 = new ShapeBufferGeometry(shape3);
const shape4 = parseSvgPath(path4);
const geometry4 = new ShapeBufferGeometry(shape4);
console.log(
arrayAreEquals(
points2array(shape1.getPoints()),
geometry1.attributes.uv.array
)
);
console.log(
arrayAreEquals(
points2array(shape2.getPoints()),
geometry2.attributes.uv.array
)
);
console.log(
arrayAreEquals(
points2array(shape3.getPoints()),
geometry3.attributes.uv.array
)
);
console.log(
arrayAreEquals(
points2array(shape4.getPoints()),
geometry4.attributes.uv.array
)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.js"></script>
解决方案
推荐阅读
- javascript - 有没有办法防止后退按钮覆盖localStorage?
- python - Tkinter - 在扩展窗口大小时更改按钮位置
- javascript - 如何在 React 中对状态更改进行 API 调用?
- python - 从 Tensorflow 2.0 导出 pb 文件以与 C API 一起使用
- excel - VLOOKUP 比较两列
- java - 如何在 Android Studio 中为后端服务生成 jar?
- python - 有人可以告诉我这种解决三序列最长公共子序列问题的方法是否正确
- c++ - 没有类型,结构绑定不起作用?
- java - .\classes\Student.java:5:错误:无法访问 IStudentOperations 公共类学生实现 IStudentOperations
- javascript - 如何从html获取值到javascript数组