Using LIDAR to generate terrain
I’ve been trying to learn how to obtain and use laser scanned imagery for years. Finally I’ve discovered some good (free) resources and a clear path to import a point cloud into a 3D editor with 0 loss of quality and accuracy. In this tutorial, I'll show you step by step using my new version of Road Atlanta, as I got it into the game.
Intro: LIDAR is basically satellite cartography that’s been recorded with a laser and has all kinds of data attached. It differs from topo maps and GPS plots in that it is very high fidelity and accurate; it records a point every 1 meter horizontally (some times more) with 1cm elevation accuracy. BeamNG uses 1 meter horizontal squares for its terrain system, so you can technically use it as is to clone real terrain. In BeamNG the surface of a mesh converted from a raw point cloud is smooth enough to drive on, with some light smoothing added.
1. Get LIDAR files: for many US locations; [[1]]
a. Search for your location and then plot 4 points surrounding it (not too big)
b. Select Datasets - digital elevation – LIDAR -
c. download options button, download the LAZ file. There may be more than one file if it’s a large area, just get them all, or make your plotted area smaller.
For aerial images that match up easily to the 1:1 overlay map in Terrain Paint: Datasets - Aerial Imagery - NAIP GEOTIFF
Some alternate sources:
Top 6 Free LiDAR Data Sources - GIS Geography [6 Free LiDAR Data Sources - GIS Geography]
[LIDAR Data Sources List – Download LIDAR - Grind GIS]
[Terrain Locations - International]
Some areas you aren’t going to find, especially if they are outside of the US, just keep in mind that it’s a limited resource.
2. Get CloudCompare: [[2]] this app is free and the best solution for working with all kinds of cartography.
3. Open all of your LIDAR file(s) in 'CC’
[[3]]
[ATTACH]264912[/ATTACH]
4. Hit the apply all and yes to all to the 2 pop-ups.
5. Select all clouds in the DB tree panel, and hit merge button. [ATTACH]264914[/ATTACH]
6. In the panel below; properties: scroll down to Scalar Fields; change type to Intensity
[ATTACH]264915[/ATTACH]
7. Below Scalar fields; (SF display params); move the yellow arrow until it’s close to the black wave form.
These 2 steps should clear up the map and you can have some fun in the 3d viewer. You will see details like the roads, grass, and 3D details like buildings and trees. If you left/right click-drag you can rotate/pan and see it from different angles and zoom in with the mouse wheel. Hit F4 to switch to camera centered rotation and you can sort of fly through the scene. If you zoom in too close, the dots get too small to see; in the top left of the viewer, you can increase point size so you can keep zooming in and still see the terrain up close. [ATTACH]264917[/ATTACH]
Now that you are oriented with the map, click the magnifying glass icon on the left tool bar, and the orange and white cube below it to get the view straightened. Go to edit: Global Shift/scale and zero out the 3 shift fields. Save the map as BIN format which is CC’s native format and can be loaded easily. I name it Base_Map.bin
8. Time to cut up the map. The raw cloud map displayed is undoubtedly bigger than the area you want to use for your map. Plan out a square region you will use for your level.
a. Select the cloud from the DB tree panel
b. Click the scissors icon on the middle of the top toolbar
c. A small tool bar will pop-up in the 3D viewer; click the pause button, then pan/zoom to so the region you want is visible.
d. Un-pause, click the polyline selection arrow, and switch it to square selection, drag-select the region you want to keep. You can click the polyline button’s arrow to export the square, and save it as a BIN file for later. You can do this whenever you make a polyline selection and want to reuse it.
e. Hit the red filled-in button and the check mark to finish. Delete the ‘remaining’ section that was cut out. Save this map as a BIN file – I name it Map_All.bin [ATTACH]264918[/ATTACH]
9. Extracting the ‘Ground Points’ is vital. It removes the trees, walls and buildings; leaving you with the only bare terrain which can be paved and have quality 3D scenery added to.
a. First, go to scalar fields again; this time use Classification. In SF display params; move the two circles until they isolate the blue line at the 1.9 / 2.1 parameters (usually).
b. Cut the unwanted sections out: edit: scalar fields: filter by value: split button.
c. Delete the old unchecked map piece and the one labeled outside in DB panel.
Save as a new BIN file ie: Map_Ground.bin
Tip 1: optimizing the terrain is a special step you can use for sections of terrain not normally visited, or things just for looks from afar. You can cut these areas out using the scissors tool and polyselect type. Then use Edit: Subsample to reduce the cloud’s point’s spacing. My USGS files use feet as their measurement, so I make areas 60 feet from the track 3 foot spacing and areas 500-600 feet out 6 feet apart. This makes loading meshes quicker and reduces the poly-count. I then make meshes for the background hills and mountains for areas beyond the terrains limits using 10-20 foot spacing. The finished parts can be converted to mesh with Edit: Mesh: Delaunay 2.5D (XY Plane) - set Max edge length to 6 (higher for parts with big holes and for rougher clouds.)
Tip2: (IMPORTANT STEP ALERT) Making a mesh with just the road polygons is vital if you want to be able to terrain paint them accurately in BeamED and to add a perfectly matched up satiate map image over the terrain.
a. Select the map and Set scalar fields to intensity and move the right circle until the grass areas of the map start to disappear between 50-35 seem to reduce it enough to turn most non road areas white.
b. Then use the trick from step 9: edit: scalar fields: filter by value, to remove the grass sections.
c. This can be used as is or further trimmed using scissors: polyselect: delete.
d. The finished mesh can also be converted to mesh same as Tip 1
e. Once loaded into BeamED (after molding the entire terrain with align to mesh from step 15) , you can paint the road by tracing over the road mesh by setting the road’s material to mult transparency, so it’s see through, then export the terrain, and it will output a PNG image with the road shape on it. This image can be loaded into an image editor and a USGS NAIP GEOTIFF can be overlaid if you set the terrain to 1 meter square size.
I give all grass sections this map as terrain pain type with diffuseSize = "2048"; so it matches the map resolution. Some flipping or mirroring may be needed since the outputted PNG isn’t oriented right.
[ATTACH]264916[/ATTACH]
10. To get the raw points into real 3D, we need to convert it to a mesh. Go to Edit: Mesh: Delaunay 2.5D (XY Plane) - set Max edge length to 0: this setting will fill in any holes with a flat patch the size of the number, in this case infinite.
Alternatively, the cloud saved in step 9 can be converted to a height map that can be imported directly into Beamed using the Tools: projection: rasterize tool. I haven’t learned the workflow for this process yet, other than the Step setting is set to 1 and Edit Grid: Width is set to your terrain’s resolution. I still need to find the optimum settings for the rasterize tool and how to make it a gray scale BMP.
11. Save as OBJ or STL
12. Open in blender or 3DS Max. Assign a material to the mesh. You can also apply UV mapping and a satellite image overlay, if you want to make it easier to paint and pave in BeamED. I’ve tried using a top down screenshot of the 3d viewer in CC, and mapping it to the mesh and it’s matched pretty well to start with and was very useful for painting the initial roads. [ATTACH]264920[/ATTACH]
Cut the mesh into pieces no larger than 200,000 triangles, any bigger and Beamng will crash while loading the mesh. I’ve loaded over a million tri’s total, but they can’t be any bigger per mesh. You can do this in CC before export using scissors tool: polyline selection, or in your 3d editor.
13. Save as DAE
14. Time to move your map into BeamNG
a. Load up a new level in BeamED,
b. Load the DAEs,
c. On the side panel: transform: position box; zero out the xyz values
d. Create a new terrain, set to 2048 resolution, or a prime number closest to your map width in meters;
e. Move the terrain so its origin corner (south west) matches the corner of the mesh. Make sure its max height is slightly more than the mesh and the minimum height is lower than the mesh to avoid spiking. You can gauge this with the set height tool and the specific mesh height by looking in CC at the mesh’s Box Dimensions: Z value. The Square Size should be 1 meter or less, to best suit the mesh density. You can change it until the terrain fits over the mesh if you like.
15. With the terrain in place start molding it to the LIDAR mesh. Go to the terrain edit mode and Align with mesh up/down. You will need to do this task to the whole map. I do it on steps; around the main track first then the outlying parts after I get it drivable. If you applied UV mapping to the mesh and added a map texture, it will be ready for easier painting and adding of scenery objects.
[ATTACH]264921[/ATTACH]
Here's my semi-finished terrain. I used a USGS NAIP 1 meter image overlay on everything to bring it to life.
[ATTACH]264922[/ATTACH]
This tutorial is based on this one I found http://assettocorsamods.net/threads/lidar-point-cloud-to-mesh-tutorial.422/ which is great, but I’ve added some important steps for getting it into BeamNG.
Changelog: 4-29-14 - Some small typos fixed - add how to save polylines. - Fixed step 9. It now includes the steps on how to split the cloud into 2, after excluding trees. - Added some tips after step 9 for making optimized point clouds for exporting to mesh as backdrops. A big tip for isolating the road portions of the point cloud for matching up your LIDAR generated terrain to satellite images. Also for how to make a satellite map overlay material – for terrain paint.