three.js线转面。THREE.Line转Shape,line设置lineWidth无效

three.js线转面

项目中有遇到这个问题,在这里记录一下

threejs没有提供类似函数,可以使用第三方库 three-line-2dthree.meshline。这库怎么使用我也没试过,后来才找到的。当时使用自己的方法处理了, 怎么使用可以看npm官网。

  • https://www.npmjs.com/package/three-line-2d
  • https://www.npmjs.com/package/three.meshline

线转面,只需要计算出线上的点在扩散后的位置即可,每个点会生成2个点,再将点连起来形成Shape。

线转换后的Shage示意图
只是简单处理了一下,不能拐弯处实现圆滑效果,直接上代码。

/**
 * 线拉伸成平面
 * @param { {x: number, y: number}[] } points 点
 * @param { number } radius 拉伸半径(宽度)
 * @returns { THREE.Vector2[] }
 */
export function createShapeFromPoints(points, radius = 1) {
  let left = [];
  let right = [];

  for (let i = 0, len = points.length; i < len; i++) {
    let prev = points[i - 1] || {};
    let curr = points[i];
    let next = points[i + 1] || {};

    let v1 = [curr.x - prev.x, curr.y - prev.y];
    let v2 = [next.x - curr.x, next.y - curr.y];
    if (!prev.x && prev.x !== 0) {
      v1 = [...v2];
    } else if (!next.x && next.x !== 0) {
      v2 = [...v1];
    }

    let modelV1 = Math.sqrt(v1[0] ** 2 + v1[1] ** 2);
    let modelV2 = Math.sqrt(v2[0] ** 2 + v2[1] ** 2);
    // 单位向量
    v1 = [v1[0] / modelV1, v1[1] / modelV1];
    v2 = [v2[0] / modelV2, v2[1] / modelV2];
    // 方向和的单位向量
    let vector = [v1[0] + v2[0], v1[1] + v2[1]];
    let modelVector = Math.sqrt(vector[0] ** 2 + vector[1] ** 2);
    vector = [vector[0] / modelVector, vector[1] / modelVector];

    // 扩散点的方向和转角处的角度偏移
    let Lvector = rotateVector(vector, -Math.PI / 2);
    let Rvector = rotateVector(vector, Math.PI / 2);
    let deflection = vectorAngleCosHalf(v1, v2);

    left.push(
      new THREE.Vector2(
        curr.x + Lvector[0] * (radius / deflection),
        curr.y + Lvector[1] * (radius / deflection)
      )
    );
    right.unshift(
      new THREE.Vector2(
        curr.x + Rvector[0] * (radius / deflection),
        curr.y + Rvector[1] * (radius / deflection)
      )
    );

    prev = curr;
  }

  return left.concat(right);
}

/**
 * 向量夹角的cos值
 * @param { [number, number] } a
 * @param { [number, number] } b
 * @returns
 */
export function vectorAngleCos(a, b) {
  return (
    (a[0] * b[0] + a[1] * b[1]) /
    (Math.sqrt(a[0] ** 2 + a[1] ** 2) * Math.sqrt(b[0] ** 2 + b[1] ** 2))
  );
}

/**
 * 向量夹角的一半的cos值
 * @param { [number, number] } a
 * @param { [number, number] } b
 * @returns
 */
export function vectorAngleCosHalf(a, b) {
  return Math.sqrt((1 + vectorAngleCos(a, b)) / 2);
}

/**
 * 将点绕原点旋转
 * @param { [number, number] } param0
 * @param { number } angle
 * @returns { [number, number] }
 */
export function rotateVector([x1, y1], angle) {
  let x2 = x1 * Math.cos(angle) - y1 * Math.sin(angle);
  let y2 = y1 * Math.cos(angle) + x1 * Math.sin(angle);

  return [x2, y2];
}

使用

let line = [
  { x: 0, y: 0 },
  { x: 20, y: 40 },
  { x: 40, y: 10 },
  { x: 100, y: 100 },
];
let points = createShapeFromPoints(line, 2);

let shape = new THREE.Shape(points);
let geometry = new THREE.ShapeGeometry(shape);
let material = new THREE.LineBasicMaterial({
  color: 0x7d5fff,
  transparent: true,
  opacity: 0.9,
});
let line = new THREE.Mesh(geometry, material);

ok, 这样就得到line的Mesh了。

蓝色为原来的线,黑色是计算后的到的多边形points
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

v西瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值