Roof Creation by Using PolygonMeshBuilder

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:

  1. fill the closed line mesh with texture => the doc showed it was filled with polygon as well
  2. create a custom mesh => the points should be triangular for that
  3. refer the ‘adding a roof’ doc => the given data is in totally different shape for this
  • there are two roofs at the same time to show you more examples.

PG Link: https://playground.babylonjs.com/#QRAJQP#25

Thanks in advance! :wink:

Hi @nali4214 and welcome to the community. The first and main issue for me is not being able to interpret the data structure.

Hi and welcome to the community,

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 wish you a long journey with BabylonJS.

Boris

Hi and welcome-

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.

Hope that helps.

Flex

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 @flex Let me try this!

I’m not sure to understand exactly what you’re doing and especially why you have to rotate your roof if you have the coordinates of its points.

I make roofs in my applications and I build them “in place” using the polyhedron construction.

For instance, thats what i can obtain when building a veranda :

and viewed from the bottom :

Each piece of the roof between two rafters is made with two merged polyhedrons to obtain the inside and outside colors of the roof.

if you’re sure that the points which define each part of your roof are in the same abstract plane, you can use the custom polyhedron.

Hope it will help.

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.

Hi,

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.

Hope it will help.

Boris

@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.

image

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.

PG from this

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!

1 Like

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!! :wink:

1 Like

Just playing around with the previous pg:Babylon.js Playground

1 Like

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.

I realized that on drag event slows down the computer if you have an house app full of 3d objects like this. On drag end is better.

The question is How can I control the UV mapping for the textures?

Look what happens when I apply a material:

The tiles appear in different angle in different faces

You will need to define your UVs programmatically as well to be sure they match your needs.

1 Like

I read a little about this topic: Map Materials to Individual Mesh Faces | Babylon.js Documentation
but I still dont know how to achieve an adequate UV map orientation; Can you show me an example?

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);
}