Create mesh in run time

I have a series of points (latitude and longitude data) that constitute the lake surface data. I want to overlay and display this lake surface in Cesium for Unity. My steps are: first, convert all the points to Unity world coordinates, then construct a mesh and add it to the scene as a child object of CesiumGeoreference, and add the CesiumGlobeAnchor component to this object.
is this way correctly?

    private void showRegion(ReadOnlyCollection<IPosition> pts) {
        MeshDataBuilder builder = new MeshDataBuilder(this.cesiumGeoreference, pts);

        // 创建一个mesh
        UnityEngine.Mesh mesh = new UnityEngine.Mesh();
        mesh.vertices = builder.getVertexs();
        mesh.triangles = builder.getTriangles();
        mesh.name = "DynamicLake";

        // 更新法线和边界
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        GameObject lake = new GameObject("Lake");

        // 将生成的 Mesh 应用到 MeshFilter 和 MeshRenderer
        MeshFilter meshFilter = lake.AddComponent<MeshFilter>();
        meshFilter.mesh = mesh;

        MeshRenderer meshRenderer = lake.AddComponent<MeshRenderer>();
        meshRenderer.material = meshMaterial;

        lake.transform.parent = cesiumGeoreference.transform;
        lake.AddComponent<CesiumGlobeAnchor>();
    }

after running, i can not see any lakes, is any wrong here?

I suspect there is an issue with my method of adding. When I previously tested adding a sphere, I used the model’s coordinate system and only converted the center point coordinates of the sphere. Finally, I just set the position of sphere.transform.position, and the sphere was displayed correctly.

class MeshDataBuilder {
    private CesiumGeoreference cesiumGeoreference;
    private List<Vector3> vectors = new List<Vector3>();
    private List<int> triangles = new List<int>();

    public MeshDataBuilder(CesiumGeoreference cesiumGeoreference, ReadOnlyCollection<IPosition> pts) {
        this.cesiumGeoreference= cesiumGeoreference;
        convertVectors(pts);
        buildTriangles();
    }

    private void convertVectors(ReadOnlyCollection<IPosition> pts) {
        foreach (var pt in pts) {
            var p = new double3(pt.Longitude, pt.Latitude, pt.Altitude.GetValueOrDefault(0));
            double3 d3 = convert(p, this.cesiumGeoreference);
            vectors.Add(new Vector3((float)d3.x, (float)d3.y, (float)d3.z));
        }
    }

    public Vector3[] getVertexs() {
        return vectors.ToArray();
    }

    public int[] getTriangles() {
        return triangles.ToArray();
    }

    private void buildTriangles() {
        List<Vertex> vertexes = this.vectors.Select(p => new Vertex(p.x, p.y)).ToList();
        var triangulator = new Dwyer();
        var mesh = triangulator.Triangulate(vertexes, new Configuration());
        var tries = mesh.Triangles;
        foreach (Triangle tri in tries) {
            for (int i = 0; i < 3; i++) {
                this.triangles.Add(tri.GetVertex(i).ID);
            }
        }
    }

    private double3 convert(double3 pt, CesiumGeoreference georeference) {
        // 先转换经纬度为ecef
        var ecet = CesiumWgs84Ellipsoid.LongitudeLatitudeHeightToEarthCenteredEarthFixed(pt);
        // 再转换为unity的世界坐标
        return georeference.TransformEarthCenteredEarthFixedPositionToUnity(ecet);
        //return new Vector3((float)u.x, (float)u.y, (float)u.z);
    }
}

my lake coordinates

{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"SmUserID":0,"Field_SmUserID":0},"geometry":{"type":"Polygon","coordinates":[[[119.8730101514449,36.10249336445282],[119.87625573940797,36.103630979909357],[119.87704327178136,36.10307181504856],[119.87940586890152,36.10307181504856],[119.87990702586642,36.10150998866568],[119.87859447191076,36.09975530717697],[119.87780693953738,36.09913826701102],[119.87656597943385,36.100140954819988],[119.87537274856506,36.100584447269458],[119.87496705006969,36.10108578354581],[119.8730101514449,36.10249336445282]]]}}]}
1 Like

the lake polygon’s shape rendering in gis platform.

finally the lake mesh can be showing in the cesium, but the mesh’s shape is not exactly equals to the original polygon, Obviously, the shape in Unity looks more simplified, as if it has been resampled. why?

Hi @sendreams,

I wonder if you’d have more luck using the Splines package in Unity. It’s available in Unity 2022.2+, and you can add or adjust points on a spline at runtime.

I even found something on the asset store that allows you to extrude a 2D area from a spline:

I hope the above resource helps! I think the main difficulty will be keeping this mesh aligned with the world when the origin shifts (due to the CesiumOriginShift component). You could try using CesiumGlobeAnchor, but I’m not sure if you’ll be able to maintain the precision of the points, unless you recompute their position every time.

while exclude outside triangles, it’s ok now.

i found the reason why mesh extend the orginal polygon.

I want to achieve a effect where when I click on a mesh, the border around it is highlighted. To achieve this effect, do I need to use a shader?

@sendreams please start a new thread for that. Include details of what tileset you’re using.