Help with globe extrusion

Rather than using ExtrudePolygon you could try ExtrudeShape https://doc.babylonjs.com/how_to/parametric_shapes#extruded-shapes which has capping capabilities. Rather than filling the polygon by triangulation the cap is formed from a central point to the edge vertices to make triangles.

Just tried that, and i canā€™t quite position the cap in the right spot, but i can see the final look is a little off.

https://www.babylonjs-playground.com/#80VK9V

kind of a folded look.

Right now I have an idea. I want to make an inner polygon of the country, such that the points are offset inside a certain distance. I can use the triangle grid on the inner country polygon, and a ribbon from the outer to inner area of the country. this way the ribbon can overlap the triangle leakage, and it wonā€™t break outside the real boundaries.

building that internal polygon is a little tricky atm, but i hopeful that might work.

and that failed. lol. canā€™t believe how complex this is!

The extrudeShape caping relies on the barycenter computation, what canā€™t be right when the shape has convex and concave parts.

I would suggest, as you own all the data of each country, to chop the largest ones in tinyer polygons (say 3 or 4) then to still use extrudePolygon

1 Like

The problem is the triangulation of a non convex polygon and I forgot you could not use a simple capping procedure as used by ExtrudeShape since this leads to overlapping triangles in the concave regions.

The triangulation method for ExtrudePolygon uses the earcut method and deals with concave regions. However as it minimises the number of triangles used you can be left with large triangles. Only the corners of these triangle are mapped onto the sphere so the mapped triangle can be left under the sphere.

EDIT @Jerome beat me to it - I wrote the post and went out without posting it. Now I did and saw his post.

What is needed is to identify the large triangles and split them into sufficiently small triangles.

1 Like

@Keeger This one combines some of your work with some of mine https://www.babylonjs-playground.com/#5I9JSA#8

Map sphere points to a plane somewhat parallel to country.

Rotate points to horizontal, form a polygon (not extruded). Check relative size of each triangular facet, if greater than 10% of total area add extra points inside the triangle. These extra points will act as singularities ( ie that will be used as holes in making a new polygon but as each hole is a single point no hole is formed but the extra points are used to create more triangles)

Dispose of original polygon and create a new polygon with the singularities.

Rotate polygon back to somewhat parallel to country and map plane points to above sphere using given depth storing the upper edge of the raised country outline. Form a ribbon from the original country outline as one path and the upper edge as the other path.

Merge ribbon and polygon to form a landMass.

4 Likes

wow.

that is pretty amazing John. a lot less triangles than the method i was working on now.

I remember thinking ā€œman i want to add points inside the poly, but that will ruin the shapeā€ and I had no idea I could use single points as holes to achieve part of that logic.

You are awesome!

Looking at the rendered output, I think iā€™m going to keep the ribbon unmerged from the cap. I think Iā€™ll end up using a slightly darker material for the ribbon, to give it more depth look.

now to morph this to a flat plane, with depth. so basically i go from a globe to a flat paper, but the masses are still extruded.

i am working on that now via the googles and reading some docs. I was wondering about your code. in it, you take the 3d points and create a horizontal plane with no depth, and then use that for the area and finding / adding holes.

if I take the sphere, and I want to flatten it, do I do something similar as this code?

    planePoints = [];
centerDistance = 2 * radius;
pointOnPlane = planeNormal.scale(centerDistance);

for (let i = 0; i < nbCoords; i++) {
  let unitVect = outerCoordinates[i].clone().normalize();
  let d = centerDistance / BABYLON.Vector3.Dot(unitVect, planeNormal);
  planePoints.push(unitVect.scale(d));
}

planeX = (planePoints[0].subtract(pointOnPlane)).normalize();
planeY = planeNormal;
planeZ = BABYLON.Vector3.Cross(planeX, planeY).normalize();

let M = new BABYLON.Matrix();
BABYLON.Matrix.FromXYZAxesToRef(planeX, planeY, planeZ, M);

let MT = new BABYLON.Matrix();
M.invertToRef(MT);

let horzPlane = [];
let horzPosition = 0;
for (let i = 0; i < nbCoords; i++) {
  horzPlane[i] = BABYLON.Vector3.TransformCoordinates(planePoints[i], MT);
  horzPosition += horzPlane[i].y;
  horzPlane[i].y = 0;
}

horzPosition /= nbCoords;
//create polygon plane - no depth
let polygon = BABYLON.MeshBuilder.CreatePolygon("polygon", { shape: horzPlane, updatable: true }, scene);

just wondering if thatā€™s a good approach. the extrusion will still be visible, so the 3d isnā€™t going away, itā€™s just the world is moving to a flat plane vs a sphere.

First of all for a flat projection you will not need to work about large triangles since there is no possibility of a curved surface cutting through the plane.

Secondly wanting to project the whole globe rather than part of it is completely different. The way my method works is because I am projecting a section of the sphere onto a plane near ā€œparallelā€ to the section. You cannot have a plane that is any sense ā€œparallelā€ to the whole globe. global projections are listed here List of map projections - Wikipedia with Equirectangular projection - Wikipedia probably the most straight forward.

Whole new ball game.

Here is a start but not right yet. I think I will leave this for you to play with for a while.

ah, that makes sense.

I appreciate all of your help, and the link to the wiki article. You are the supreme Jedi Leader sir :slight_smile:

2 Likes

ok ran into some issues.

when i load the full world, I get these errors in console.

[.WebGL-000001F7D72422A0] GL_INVALID_OPERATION: Error: 0x00000502, in ā€¦/ā€¦/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp, reserveSpaceForAttrib:514. Internal error: 0x00000502: Vertex buffer is not big enough for the draw call.

this happens after all polygons have been dawn. do i need to increase vertex buffer capacity?

the sphere right now, i can drive the camera through it. however I dont want that. is there a way to tell the webgl to treat the sphere as a blockable solid for rendering?

Iā€™m also noticing holes in Brazil, Russia, and Australia. I tried changing the area to add points for > 1%. this fixes Brazil, but not russia or australia, and thatā€™s kind of weird. the hole in russia is huge. but iā€™m not sure if the holes are from the vertexbuffer errors, like maybe it freaked out trying to render them?

[edit]
ok i fixed the error by calling forceSharedVertices() on the finished polygon and ribbon. it changes the look of the cap a little bit, but if i play with lighting, itā€™s not too bad.

and it turns out the error is not why i have holes still in the large countries. so weird. looking at brazil, the largest area value is below 0.1. it is like .08. so thatā€™s why changing to .01 works. however i guess Russia is even smaller? i guess that makes sense cuz of the large landmass. hmm

[edit2]
ok, if I change the number of points to higher (like 10), and a lower area (0.01) it works. so i think iā€™ll add specific checks for russia, australia, and brazil, and leave the rest of the code alone.

2 Likes

This is amazing.

1 Like

Sorry to circle back to this post. but iā€™m running into some weirdness with the holes logic and am confused.

In general, the hole logic works well, and I had to do a few manual tweaks for Russia, Australia, and Brazil. i just adjusted the percent comparison and the number of points generated, and found a balance that worked.

However, Argentina is just blowing my mind. Thereā€™s a small hole in the country, which I originally thought was a lake, but turns out is a hole. When I use the hole logic code to try and close itā€¦it is generating points outside of the border???

Iā€™ve made a playground to demo, rotate the globe to see Argentina. set normalexp = true to see the hole, which is pretty close to center of the country.

So Iā€™ve also had issues with the triangles crossing dips, so like 2 points are way east, and the 3rd is a coast line west of them, and it basically covers that dip with a triangle.

this is leading me to think i should manually create my hole points and store them, and not have to do the calculation. however, when I try to manually fix Argentina by adding holes, it doesnā€™t seem to work at all for me.

Is there something special I need to do? do the holes need to be in a specific order, like left hand rule?

https://www.babylonjs-playground.com/#5I9JSA#12

argentina pic

if I donā€™t draw holes, the triangles covering dips goes away. and looking at the indices, i think the issue may just be something in the addedPoints method. maybe the bug with points outside the triangle is the key.

itā€™s weird, if I request 1 point, i get 0. if i request 2, i get 1. if i request 3ā€¦i get 4 points. trying to figure out what the function is doing exactly. i know what itā€™s attempting to do, i just wonderā€¦if we add 1 point as a hole, does that change the indice logic, so that it causes my ā€˜overlap the dipsā€™ issue? should we add 3 points at a time inside?

I believe I have found a solution. although I have not yet tested it against the world.

Basically I re-wrote the addedPoints function in a way I understood. :slight_smile: I take the number of points I want to add, and I bisect the triangle down the middle as many times as I need. With argentina, I think the issue was the normals of the vectors were pointing away, so the vector add or subtract math was going in the wrong direction. however i was unable to figure out how to handle that.

and this also fixes the issue of crossing the dip so far, because i am guaranteeing the holes are inside the existing triangles, so no one is exiting the borders. will see how it goes against the world.

hereā€™s a playground in case anyone is interesting n the code.

https://www.babylonjs-playground.com/#5I9JSA#14

The problems @Keeger was having with Russia, etc was due to mistakes I made in the addedPoints function in #8. Hope these are now corrected in https://www.babylonjs-playground.com/#5I9JSA#17

3 Likes

Johns code works better than mine, lol. and faster too.

Now you need to add some particlesā€¦ :slight_smile:

hah. soon. :slight_smile: I do have it projecting to a plane using the Van Der Gritten projection method. I find that makes a nice rectangle shape without weird stretching of the main continents.

I never realized how many tris it must take to cover a coastline.
Really excellent project.

Did you ever try reducing the resolution for shits? Not sure the granularity of your data set if it would make any difference.

this is a pretty reduced size actually. Iā€™ve tried using larger sets to see if they reduce the large areas, but no joy.

1 Like