Hi! I recently started to learn babylonjs. I’m trying to create a roof by using given roof data.
Would you mind sharing your knowledge for me to solve this problem?
Let me explain the project briefly here.
The data I’m given has roof azimuth and tilt and its points represent an individual roof’s coordinate.
What I tried here is that:
1. draw roof’s outlines for reference by using LinesMesh
2. get direction to get the axis to rotate(tilt) roof plane
3. draw a roof plane by using PolygonMeshBuilder (converted the points to start from (0, 0, 0))
4. rotate(tilt) the the roof plane by using direction(axis)
5. move back to original desired place
So the issue I’m facing is that PolygonMeshBuilder might not be the proper way I want to create a roof dynamically since:
1. given roof’s coordinates are all in 3d already. so if I just use its (x, y(0), z) and rotate it, it creates a gap between roof planes obviously.
2. given roof’s coordinates are often uneven. Flat polygons are always created so I can see sunk roof planes here and there.
The ways I could think of were that:
fill the closed line mesh with texture => the doc showed it was filled with polygon as well
I have the same problem, your data structure is very complicated. May be you should simplify it in your playground if you want us tu be able to help you easily.
I have a BJS app that does does architecture and have a lot of experience with what you’re trying to do. Laying out 3d structures from 2d point is in my experience a bad way to go. Check out the polyhedron mesh builder. Here’s an example of a primitive ‘monopoly house’ that I use in my app. You can use CSGs to get a roof from this or you can specify more vertices to give it a roof shape from the start.
hi @JohnK@bvaisman Thanks for your reply! I removed all unnecessary datas in the playground. I should have thought of this before I ask a question here. sorry for inconvenience and thanks for trying to help me! PG Link
Thanks @bvaisman when I tried to build each roof plane by using PolygonMeshBuilder, this method uses only (x, 0, z) no matter I put y or not. so it created roof plane flat. so that’s why I tried to rotate using roof’s azimuth. (I know this is a bad way since the roof’s points are already in 3d. if I create the flat plane using y and z and rotate the roof, it creates a gap between roof planes obviously.)
I’ll try the custom polyhedron! thanks a lot! I’ll keep you all posted here
@bvaisman btw, the order of vertex of a polyhedron is important? I’m still trying to create one with the sample data, but couldn’t make it yet.
The points for the roof is in 3d in my case but it doesn’t have any depth. For example, if the roof’s points has 4 or 5 points(in the case the first and last points are the same. Line in the canvas was used to draw the roof), it is just flat irregular rectangle, not extruded at all. So I tried to create another set of points which are right below the original points and concatenated those points to the original roof points. And this try didn’t work. I’m not sure whether the order of those points are important or not. or how CreatePolyhedron works to create one.
Here’s an example to help you. I’ve created a class named Polygone to build a polygon with a base defined by an array of points an a depth. The origine of my polygon is defined on the pts[0] point.
@nali4214 not so much the order of the vertices in the vertex array as long as they are in the correct order for each face in the face array. Look at a face from the side you want to see the face then the order should be anticlockwise.
Here is a simple gable roof numbered.
First create the planes for the outside roof (blue). In this case we form the inside planes of the roof by dropping the outside vertices 0.5.
Assign positions to each vertex then set up each face array.
To supplement the information provided by JohnK, here’s a slightly more complicated example that does a bit of automation.
1: start with points for roof top faces.
2: clone and offset y of these points for bottom faces.
3: make face arrays for top faces
4: offset and reverse (to correct normals) top face arrays to make bottom face arrays.
5. make side face arrays
6. put it all together
@flex@JohnK@bvaisman Thanks for your help! Sorry for being late to reply. I just came back to this again. I’ll be focusing on this more today and hope I can get back to you soon!! Thanks again!
Thanks again @flex@JohnK@bvaisman !! I could create a roof as I wanted. I couldn’t have done this without your help!! I’ll learn babylonjs more deligently and hope I can help other people here in the near future!!
Nice. It’s quite fun to use. In terms of UI, I would just push the new points when you unselect the sphere (or even better, on drag). Here the change happens only when you select a sphere again which is a bit odd.
Something like what’s below. If you put up a playground that makes the image above I’ll jam it in.
recalculateUVs(mesh: Mesh){
let flatArray = mesh.getVerticesData(VertexBuffer.PositionKind);
const vertices = [];
for(let n = 0; n < flatArray.length;n+=3){
vertices.push(Vector3.FromArray(flatArray,n));
}
flatArray = mesh.getVerticesData(VertexBuffer.NormalKind);
const normals = [];
for(let n = 0; n < flatArray.length;n+=3){
normals.push(Vector3.FromArray(flatArray,n));
}
const uvs: number[] = [];
uvs.length = vertices.length * 2;
const indices = mesh.getIndices()!;
vertices.forEach((vertex,i) =>{
let u = undefined;
let v = undefined;
/* in here, figure out, based on material orientation and normal whether u is from x,y or z
and multiplyInPlace vertex to make decal scaling look nice
*/
//if(???){
u = vertex.z;
v = vertex.x;
//}else(){}
uvs[i*2] = u;
uvs[i*2+1]= v;
});
mesh.setVerticesData(VertexBuffer.UVKind, uvs, true);
}