three-stdlib
Version:
stand-alone library of threejs examples
93 lines (92 loc) • 3.99 kB
JavaScript
import { BoxGeometry, Vector3 } from "three";
const tempNormal = /* @__PURE__ */ new Vector3();
function getUv(faceDirVector, normal, uvAxis, projectionAxis, radius, sideLength) {
const totArcLength = 2 * Math.PI * radius / 4;
const centerLength = Math.max(sideLength - 2 * radius, 0);
const halfArc = Math.PI / 4;
tempNormal.copy(normal);
tempNormal[projectionAxis] = 0;
tempNormal.normalize();
const arcUvRatio = 0.5 * totArcLength / (totArcLength + centerLength);
const arcAngleRatio = 1 - tempNormal.angleTo(faceDirVector) / halfArc;
if (Math.sign(tempNormal[uvAxis]) === 1) {
return arcAngleRatio * arcUvRatio;
} else {
const lenUv = centerLength / (totArcLength + centerLength);
return lenUv + arcUvRatio + arcUvRatio * (1 - arcAngleRatio);
}
}
class RoundedBoxGeometry extends BoxGeometry {
constructor(width = 1, height = 1, depth = 1, segments = 2, radius = 0.1) {
segments = segments * 2 + 1;
radius = Math.min(width / 2, height / 2, depth / 2, radius);
super(1, 1, 1, segments, segments, segments);
if (segments === 1)
return;
const geometry2 = this.toNonIndexed();
this.index = null;
this.attributes.position = geometry2.attributes.position;
this.attributes.normal = geometry2.attributes.normal;
this.attributes.uv = geometry2.attributes.uv;
const position = new Vector3();
const normal = new Vector3();
const box = new Vector3(width, height, depth).divideScalar(2).subScalar(radius);
const positions = this.attributes.position.array;
const normals = this.attributes.normal.array;
const uvs = this.attributes.uv.array;
const faceTris = positions.length / 6;
const faceDirVector = new Vector3();
const halfSegmentSize = 0.5 / segments;
for (let i = 0, j = 0; i < positions.length; i += 3, j += 2) {
position.fromArray(positions, i);
normal.copy(position);
normal.x -= Math.sign(normal.x) * halfSegmentSize;
normal.y -= Math.sign(normal.y) * halfSegmentSize;
normal.z -= Math.sign(normal.z) * halfSegmentSize;
normal.normalize();
positions[i + 0] = box.x * Math.sign(position.x) + normal.x * radius;
positions[i + 1] = box.y * Math.sign(position.y) + normal.y * radius;
positions[i + 2] = box.z * Math.sign(position.z) + normal.z * radius;
normals[i + 0] = normal.x;
normals[i + 1] = normal.y;
normals[i + 2] = normal.z;
const side = Math.floor(i / faceTris);
switch (side) {
case 0:
faceDirVector.set(1, 0, 0);
uvs[j + 0] = getUv(faceDirVector, normal, "z", "y", radius, depth);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "z", radius, height);
break;
case 1:
faceDirVector.set(-1, 0, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "z", "y", radius, depth);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "z", radius, height);
break;
case 2:
faceDirVector.set(0, 1, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "z", radius, width);
uvs[j + 1] = getUv(faceDirVector, normal, "z", "x", radius, depth);
break;
case 3:
faceDirVector.set(0, -1, 0);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "z", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "z", "x", radius, depth);
break;
case 4:
faceDirVector.set(0, 0, 1);
uvs[j + 0] = 1 - getUv(faceDirVector, normal, "x", "y", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "x", radius, height);
break;
case 5:
faceDirVector.set(0, 0, -1);
uvs[j + 0] = getUv(faceDirVector, normal, "x", "y", radius, width);
uvs[j + 1] = 1 - getUv(faceDirVector, normal, "y", "x", radius, height);
break;
}
}
}
}
export {
RoundedBoxGeometry
};
//# sourceMappingURL=RoundedBoxGeometry.js.map