Hey.
I am trying to create a wall, but here I am having problems:
How to create a wall correctly?
Is it possible to create a wall from a shape and raise it using ExtrudeBufferGeometry?
I tried to create squares from a shape and move them with cubes, but I could not rotate this square in the directions of the mouse.
Another question: how to turn the shape? He has no Z coordinates.
I just drew a square and made an ExtrudeBufferGeometry. The square goes to the side. I need to raise it up on Y.
As for walls, if I understood what you mean, this example may help you.
As for rotation - is there a reason why you can’t rotate the shape before (or even after) extruding it, to make it face the direction you want to extrude it in ?
Sorry, I don’t understand what the issue is rn. As above, you can rotate the extruded geometry like any geometry.
Example (these geometries are based on the same path that’s extruded in different directions. If you’d like to rotate them perfectly you can also create a pivot group around an extruded geometry to control the origin point of rotations.)
If you want to extrude lines - not shapes - it would be easier to work with points and just create geometries from them, since you don’t need to extrude anything at all then.
If I’m understanding right, maybe this is half of what you are trying to do, except what you’ll want is probably extrude 3d geometry and not flat planes.
At a high level, what you could do is have a WallCreator class that takes in two points.
And from there you can create each wall based on each wall segment.
You’ll of course need to provide in the wall height and thickness so you can create or extrude the geometry correctly. You may also need to handle re-positioning the walls and rotating it into place after you create the 3D piece from each segment.
A decision you’ll have to make too is, whether to create each wall geometry at the origin and position and rotate it into place, or create the wall geometry exactly at the segment locations. Each path has it’s up and down, but I do find it’s easier to create each wall at the origin and then re-position and re-rotate the 3D object into place.
@Sushant_Kumar
I found myself stuck on this topic for way to long because there is nobody answering the questions with code for how to get seamless corners and provide code for it. So for people coming to this topic searching for how to create walls with seamless corners…
These topic are helpful:
I found 2 ways: First way i got this to work
You can do this with @hofkThreeG.js i prefer the createProfiledContourUV over createProfiledContourMMgeometry. Because with MM each segment would handle its own normal and therefor lighting and shadow.
// Define the profile shape (thickness and height in cm, i convert all my 'units' since my points are in cm)
const thickness = 10 / 100; // Wall thickness
const height = 240 / 100; // Wall height
//create a material for each wall
const materials = [];
//example points (startpoint each wall in cm)
const points = [
{ x: 0, y: 0 },
{ x: 420, y: 0 },
{ x: 320, y: -229 },
{ x: 500, y: -330 },
{ x: 120, y: -330 }
];
//define cross-section of the wall. The wall thickness is 10cm and the height is 300cm
const profileShape = [
0, 0, // Bottom left (inner)
thickness, 0, // Bottom right (inner)
thickness, height, // Top right (inner)
0, height, // Top left (inner)
-thickness, height, // Top left (outer)
-thickness, 0 // Bottom left (outer)
];
const contour = [];
//convert my points to contour and here you can add multiple materials for each wall
points.forEach(wall => {
contour.push(wall.from.x / 100, wall.from.y / 100);
//outerwall
materials.push(new MeshPhongMaterial({
color: 0xff0000, side: DoubleSide
}))
//innerwall
materials.push(new MeshPhongMaterial({
color: 0x00ff00, side: DoubleSide
}))
//top first part
materials.push(new MeshPhongMaterial({
color: 0x0000ff, side: DoubleSide
}))
//top second part
materials.push(new MeshPhongMaterial({
color: 0x0000ff, side: DoubleSide
}))
});
const frame = new Group();
const contourClosed = true;
const openEnded = false;
const matPerSquare = false;
ThreeG.createProfiledContourUV(frame, profileShape, contour, materials, matPerSquare, contourClosed, openEnded);
frame.rotateX(-Math.PI / 2); //rotate so the frame is on the floor
frame.receiveShadow = true
frame.castShadow = true
scene.add(frame)
Second way i got this to work
Basically what you need to do is creating a wall (box) starting from one point to the next.
You will then always have a gap or intersection. You then need to calculate the vertices that intersect or leave a gap and change the vertices to the correct position. I’m still working on it and is almost finished but this gives you an idea.
Maybe someone could improve this.
//Create wall geometry with inner and outer vertices
function createWallGeometry(innerStart, innerEnd, outerStart, outerEnd) {
const geometry = new BufferGeometry();
const vertices = new Float32Array([
outerStart.x, wallHeight, outerStart.y, // outer top left
outerEnd.x, wallHeight, outerEnd.y, // outer top right
outerStart.x, 0, outerStart.y, // outer bottom left
outerEnd.x, 0, outerEnd.y, // outer bottom right
innerStart.x, wallHeight, innerStart.y, // inner top left
innerEnd.x, wallHeight, innerEnd.y, // inner top right
innerStart.x, 0, innerStart.y, // inner bottom left
innerEnd.x, 0, innerEnd.y // inner bottom right
]);
geometry.setAttribute('position', new BufferAttribute(vertices, 3));
geometry.setIndex([
0, 2, 1, 2, 3, 1, // outer face
4, 5, 6, 6, 5, 7, // inner face
0, 1, 4, 1, 5, 4, // top face
2, 6, 3, 3, 6, 7, // bottom face
0, 4, 2, 2, 4, 6, // left face
1, 3, 5, 3, 7, 5 // right face
]);
return geometry;
}
function calculateIntersection(p1, d1, p2, d2) {
const x1 = p1.x, y1 = p1.y;
const x2 = p2.x, y2 = p2.y;
const dx1 = d1.x, dy1 = d1.y;
const dx2 = d2.x, dy2 = d2.y;
const determinant = dx1 * dy2 - dy1 * dx2;
if (determinant === 0) return null; // Lines are parallel
const t = ((x2 - x1) * dy2 + (y1 - y2) * dx2) / determinant;
return { x: x1 + t * dx1, y: y1 + t * dy1 };
}
// Function to get direction vector
function getDirection(start, end) {
const length = Math.hypot(end.x - start.x, end.y - start.y);
return { x: (end.x - start.x) / length, y: (end.y - start.y) / length };
}
for (let i = 0; i < points.length; i++) {
const start = points[i];
const end = points[(i + 1) % points.length]; // Get next point point
const direction = getDirection(start, end);
const perpendicular = { x: -direction.y, y: direction.x }; // Perpendicular to direction
// Inner and outer offsets
let innerStart = {
x: start.x - perpendicular.x * wallThickness / 2,
y: start.y - perpendicular.y * wallThickness / 2
};
let innerEnd = {
x: end.x - perpendicular.x * wallThickness / 2,
y: end.y - perpendicular.y * wallThickness / 2
};
let outerStart = {
x: start.x + perpendicular.x * wallThickness / 2,
y: start.y + perpendicular.y * wallThickness / 2
};
let outerEnd = {
x: end.x + perpendicular.x * wallThickness / 2,
y: end.y + perpendicular.y * wallThickness / 2
};
if (i > 0) {
const prevStart = points[i - 1];
const prevDirection = getDirection(prevStart, start);
const prevPerpendicular = { x: -prevDirection.y, y: prevDirection.x };
let prevInnerEnd = {
x: start.x - prevPerpendicular.x * wallThickness / 2,
y: start.y - prevPerpendicular.y * wallThickness / 2
};
let prevOuterEnd = {
x: start.x + prevPerpendicular.x * wallThickness / 2,
y: start.y + prevPerpendicular.y * wallThickness / 2
};
const innerIntersection = calculateIntersection(
{ x: prevStart.x - prevPerpendicular.x * wallThickness / 2, y: prevStart.y - prevPerpendicular.y * wallThickness / 2 },
prevDirection,
innerStart,
direction
);
const outerIntersection = calculateIntersection(
{ x: prevStart.x + prevPerpendicular.x * wallThickness / 2, y: prevStart.y + prevPerpendicular.y * wallThickness / 2 },
prevDirection,
outerStart,
direction
);
if (innerIntersection) {
innerStart = innerIntersection;
prevInnerEnd = innerIntersection;
}
if (outerIntersection) {
outerStart = outerIntersection;
prevOuterEnd = outerIntersection;
}
// Update previous wall geometry with intersection points
const prevWallGeometry = createWallGeometry(prevStart, prevInnerEnd, prevStart, prevOuterEnd);
const wallMaterial = new MeshBasicMaterial({ color: 0xaa80f0, side: DoubleSide});
const prevWall = scene.children[scene.children.length - 1];
const final = mergeGeometries([prevWallGeometry, prevWall.geometry]);
const prevWallMesh = new Mesh(final, wallMaterial);
scene.add(prevWallMesh);
//remove the old wall since we now merged it
scene.remove(prevWall)
}
const wallGeometry = createWallGeometry(innerStart, innerEnd, outerStart, outerEnd);
const wallMaterial = new MeshBasicMaterial({ color: 0xfa8080, side: DoubleSide});
const wallMesh = new Mesh(wallGeometry, wallMaterial);
// Add wall to scene
scene.add(wallMesh);
}