ViRGIS-Team / pdal-upm

Unity Package for PDAL
MIT License
6 stars 2 forks source link

Any example how to use it? The one on the front page doesn't work #5

Closed leorid closed 1 year ago

leorid commented 1 year ago

When trying to use the example-code it says that on the line BpcData pc = view.GetBakedPointCloud(); the GetBakedPointCloud method wasn't found. Is this an extension?

What does GetPackedMesh return? How to use GetAllPackedPoints? To use the method, a DimTypeList is required, which I could create, but it requests an IntPtr and I've no idea where I should get this?

All I want to do is to read various file formats (ptx, maybe e57, maybe laz) and just get all the points, normals, colors as Vector3 or floats into a list.

How to do that with this package? Are there any examples I've missed?

runette commented 1 year ago

Hi @leorid

Firstly - an apology. In the most recent versions I changed the ABI to make the package considerably faster but it looks like I forgot to update the example code! Sorry. I will get around to doing that ASAP.

Be assured that this package is the way to do what you want (I think).

Some notes:

PDAL supports two general types of data held in views:

The easiest way in this package to access the point cloud data as positions and colour is to do the following

using (PointViewIterator views = pl.Views) {
                views.Reset();

                while (views.HasNext())
                {
                    PointView view = views.Next;
                    if (view != null)
                    {
                        Console.WriteLine($"Point Count is {view.Size}");
                        BakedPointCloud features = await BakedPointCloud.Initialize(view);

and example of real use is here. This is, obviously, a lot more complicated than the example.

The BakedPointCloud structure is a part of this package and so is not an extension. It can be seen here. It can be seen that the class contains the data as two Texture2D properties - one contains the point position (x,y,z which is saved in the Texture2D as RGBAFloat but don't be fooled - it is position data and not colour data) and colour (r,g,b as RGBA32 ).

Texture2D is a very efficient way of managing very large datasets (I have used this up to about 10 million points ) and is designed to be passed directly to VFX / shader for rendering. However - if you want the data as a list - the easiest way is to use this function and then call GetPixels on the Texture2D - or GetRawTextureData that gets a NativeArray and is much more efficient.

Mesh data can be accessed using a BakedMesh object which is created in almost the same way

using (PointViewIterator views = pl.Views) {
                views.Reset();

                while (views.HasNext())
                {
                    PointView view = views.Next;
                    if (view != null)
                    {
                        Console.WriteLine($"Point Count is {view.Size}");
                        BakedMesh features = await BakedMesh.Initialize(view);

The Mesh data is held in a DMesh3 property in the BakedMesh - this is a class defined in the Geometry3sharp library and provides the ability to manipulate the mesh.

I will try to update the docs soon

leorid commented 1 year ago

Amazing, thanks for your quick response. You really saved me from some serious headache.

With your help I got it working almost immediately. Thanks a lot. :D

About the Normals -> we used them for some fake lighting in some releases, but I don't think it's really required for the thing I'm working on right now. And if it would be required, I could calculate them myself.

I have three more questions: 1) Is there a way to find out if the point cloud even has color data? (would all colors be white or "clear" then?) 2) Is there a way to shift the origin (maybe with the pipeline-commands)? Unity doesn't like float values in the tens of thousands range (e.g. points 534.000m away from the origin). I've imported the point could I'm using for testing so that the first point is the origin, in order to see if it's working, but by doing so, I guess I'm losing a lot of precission. 3) PTX and E57 files have a rotation / position saved within them - how can I read those values?

runette commented 1 year ago

Amazing, thanks for your quick response. You really saved me from some serious headache.

:)

With your help I got it working almost immediately. Thanks a lot. :D

About the Normals -> we used them for some fake lighting in some releases, but I don't think it's really required for the thing I'm working on right now. And if it would be required, I could calculate them myself.

To my mind - Point Cloud data cannot have normals since they are points - you have to turn it to a mesh to have normals and there a lot of questions about how to group points that will determine what the normals to the mesh would be.

I would be interested in a counter example.

I have two more questions:

  1. Is there a way to find out if the point cloud even has color data? (would all colors be white or "clear" then?)

If you use the BakedPointCloud functions, then if the PC has no colour (specifically it has no dimension called red) then the colour Texture2D is just as initialised, which from memory would make it black but I would have to experiment.

If this is important - you can tell by going back to the lower level data structures but that gets more complicated.

  1. Is there a way to shift the origin (maybe with the pipeline-commands)? Unity doesn't like float values in the tens of thousands range (e.g. points 534.000m away from the origin). I've imported the point could I'm using for testing so that the first point is the origin, in order to see if it's working, but by doing so, I guess I'm losing a lot of precission.

This is always an interesting issue with Geolocated point clouds and other data (and a large part of the development of ViRGiS).

If you are getting values like 534,000 (sorry - I have to use the UK representation to get my head around it) then that means that the data is in a projected CRS. What we do in ViRGiS, since we are working in a GIS paradigm with a project origin, is to create an engineering CRS which is oblique transverse mercator with the "origin" of the CRS at the origin of the project, defined in WKT2, and then use the PDAL pipeline to efficiently (in C++ and using the Proj library) transport the dataset into this CRS.

This does require that you know the CRS of the original data - preferably as an EPSG code.

What you get is the same point cloud but transposed to a 3D cartesian coordinate set where 0,0,0 is the origin you defined - and is probably local affine up to the precision limits of Unity.

If you are interested more in this - PM me.