Hi everyone,
I’m having trouble performing UV mapping on a custom shape created using four curves (top, bottom, left, and right) in Three.js. Initially, I had success with just the top and bottom curves, but integrating the left and right curves to form a closed shape is proving challenging.
I have created curves using cubic bezier curves. I also added shader material and added image texture. I want to distort the image by dragging the control points. Control points are the points that are defined in the curves. It was doing fine when I used only top and bottom curves and did uv mapping and defined indices. But when I added left and right curves then uvs and indices are not mapping perfectly. I mean I can not control four curves at the same time.
Here’s what I have so far:
const sharedPointTopLeft = new THREE.Vector3(-100, 200, 0);
const sharedPointTopRight = new THREE.Vector3(200, 200, 0);
const sharedPointBottomRight = new THREE.Vector3(200, -200, 0);
const sharedPointBottomLeft = new THREE.Vector3(-100, -200, 0);
const sharedPointTopCenter = new THREE.Vector3(50, 200, 0);
const sharedPointBottomCenter = new THREE.Vector3(50, -200, 0);
const sharedPointLeftCenter = new THREE.Vector3(-100, 0, 0);
const sharedPointRightCenter = new THREE.Vector3(200, 0, 0);
const curvesLeft = [
new THREE.CubicBezierCurve3(
sharedPointTopLeft,
new THREE.Vector3(-100, 150, 0),
new THREE.Vector3(-100, 100, 0),
sharedPointLeftCenter
),
new THREE.CubicBezierCurve3(
sharedPointLeftCenter,
new THREE.Vector3(-100, -50, 0),
new THREE.Vector3(-100, -100, 0),
sharedPointBottomLeft
),
];
const curvesTop = [
new THREE.CubicBezierCurve3(
sharedPointTopLeft,
new THREE.Vector3(-50, 200, 0),
new THREE.Vector3(0, 200, 0),
sharedPointTopCenter
),
new THREE.CubicBezierCurve3(
sharedPointTopCenter,
new THREE.Vector3(100, 200, 0),
new THREE.Vector3(150, 200, 0),
sharedPointTopRight
),
];
const curvesRight = [
new THREE.CubicBezierCurve3(
sharedPointTopRight,
new THREE.Vector3(200, 150, 0),
new THREE.Vector3(200, 100, 0),
sharedPointRightCenter
),
new THREE.CubicBezierCurve3(
sharedPointRightCenter,
new THREE.Vector3(200, -50, 0),
new THREE.Vector3(200, -100, 0),
sharedPointBottomRight
),
];
const curvesBottom = [
new THREE.CubicBezierCurve3(
sharedPointBottomLeft,
new THREE.Vector3(-50, -200, 0),
new THREE.Vector3(0, -200, 0),
sharedPointBottomCenter
),
new THREE.CubicBezierCurve3(
sharedPointBottomCenter,
new THREE.Vector3(100, -200, 0),
new THREE.Vector3(150, -200, 0),
sharedPointBottomRight
),
];
function updateShaderGeometry() {
pathTop = new THREE.CurvePath();
curvesTop.forEach((curve) => pathTop.add(curve));
pathBottom = new THREE.CurvePath();
curvesBottom.forEach((curve) => pathBottom.add(curve));
pathLeft = new THREE.CurvePath();
curvesLeft.forEach((curve) => pathLeft.add(curve));
pathRight = new THREE.CurvePath();
curvesRight.forEach((curve) => pathRight.add(curve));
let curvePointsTop = pathTop.getPoints(1000);
let curvePointsBottom = pathBottom.getPoints(1000).reverse();
let curvePointsLeft = pathLeft.getPoints(1000).reverse();
let curvePointsRight = pathRight.getPoints(1000);
const vertices = [];
const uvs = [];
const indices = [];
curvePointsTop.forEach((point, index) => {
vertices.push(point.x, point.y, 0);
uvs.push(index / (curvePointsTop.length - 1), 1);
const bottomPoint = curvePointsBottom[index];
vertices.push(bottomPoint.x, bottomPoint.y, 0);
uvs.push(index / (curvePointsBottom.length - 1), 0);
});
curvePointsLeft.forEach((point, index) => {
vertices.push(point.x, point.y, 0);
uvs.push(0, 1 - index / (curvePointsLeft.length - 1));
const rightPoint = curvePointsRight[index];
vertices.push(rightPoint.x, rightPoint.y, 0);
uvs.push(1, 1 - index / (curvePointsRight.length - 1));
});
for (let i = 0; i < curvePointsTop.length - 1; i++) {
const a = i * 2;
const b = i * 2 + 1;
const c = i * 2 + 2;
const d = i * 2 + 3;
indices.push(a, b, d);
indices.push(a, d, c);
}
const offset = curvePointsTop.length * 2;
for (let i = 0; i < curvePointsLeft.length - 1; i++) {
const a = offset + i * 2;
const b = offset + i * 2 + 1;
const c = offset + i * 2 + 2;
const d = offset + i * 2 + 3;
indices.push(a, b, d);
indices.push(a, d, c);
}
shaderGeometry.setAttribute(
"position",
new THREE.Float32BufferAttribute(vertices, 3)
);
shaderGeometry.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2));
shaderGeometry.setIndex(indices);
shaderGeometry.attributes.position.needsUpdate = true;
shaderGeometry.attributes.uv.needsUpdate = true;
shaderGeometry.index.needsUpdate = true;
shaderMesh.geometry.dispose();
shaderMesh.geometry = shaderGeometry;
shaderMesh.position.z = 0.5;
shaderMesh.geometry.computeVertexNormals();
}
First one is the initial stage and second one when I am trying to distort image.