Create a custom geometry

When i create a custom geometry, it reports CesiumWidget.js:743 An error occurred while rendering. Rendering has stopped.
TypeError: Cannot read properties of undefined (reading ‘center’)
TypeError: Cannot read properties of undefined (reading ‘center’)
at createVertexArray (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Primitive.js:1264:50)
at Primitive.update (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Primitive.js:1605:5)
at PrimitiveCollection.update (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/PrimitiveCollection.js:365:19)
at updateAndRenderPrimitives (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Scene.js:2662:21)
at executeCommandsInViewport (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Scene.js:2511:3)
at Scene.updateAndExecuteCommands (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Scene.js:2378:5)
at render (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Scene.js:2957:9)
at tryAndCatchError (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Scene.js:2971:5)
at Scene.render (webpack-internal:///./node_modules/@cesium/engine/Source/Scene/Scene.js:3036:5)
at CesiumWidget.render (webpack-internal:///./node_modules/@cesium/engine/Source/Widget/CesiumWidget.js:747:17).
I don’t know how to resolve it, i find much blogs what it can’t improvide method.
source code as example:

class gridPrimitive {

    constructor(options) {
        this.viewer = options.scene
        this.scene = options.viewer.scene
        this.colormaker = new ColorMaker({
            values: [0, 20, 40, 60, 70, 90, 100],
            colors: [
                [98, 113, 184],
                [61, 110, 163],
                [77, 142, 124],
                [162, 135, 64],
                [151, 75, 145],
                [95, 100, 160],
                [91, 136, 161],
            ]
        })
        this.data = this.generateGridData(0.5, 73, 150, 31, 53)
        this.customPrimitive()
        console.log(this.data, 'this.data')
    }


    /**
     * 
     * @param {*} dx
     * @param {*} lon1 
     * @param {*} lon2 
     * @param {*} lat1 
     * @param {*} lat2 
     * @returns 
     */
    generateGridData(dx, lon1, lon2, lat1, lat2) {
        let header = { lon1, lon2, lat1, lat2, dx: dx, dy: dx, nx: (lon2 - lon1) / 0.5, ny: (lat2 - lat1) / 0.5 + 1 }
        let data = []
        for (let i = 0; i < header.nx; i++) {
            for (let j = 0; j < header.ny; j++) {
                data.push(Math.random() * 100)
            }
        }
        console.log({ header, dataLen: data.length }, 'header, dataLen: data.length')
        return {
            header,
            data
        }
    }

    customGeometry() {
        const {lon1, lat2, nx, ny} = this.data.header
        let griddata = this.data.data
        let positions = []
        let colors = []
        let indices = []
        
        for (let i = 0; i < ny; i++) {
            for (let j = 0; j < nx; j++) {
                let index = i * nx + j
                
                let nextLineIndex = (i + 1) * nx + j
                positions.push(...transformPos(i, j)) //3
                colors.push(...this.colormaker.makeColor(griddata[index]).map((e) => e / 255.0), 1.0) //4
                if (j < nx - 1 && i < ny - 1) {
                    indices.push(index, index+1, nextLineIndex, index + 1, nextLineIndex, nextLineIndex + 1)
                }
            }
        }
        console.log(indices, positions, colors, 'indices, positions, colors')
        this.boundingSphere = Cesium.BoundingSphere.fromVertices(positions)
// console.log(Cesium.BoundingSphere.fromVertices(positions), 'Cesium.BoundingSphere.fromVertices(positions, new Cesium.Cartesian3(1.0, 2.0, 3.0), 3)')
        
        function transformPos(i, j) {
            let pos = Cesium.Cartesian3.fromDegrees(lon1 + j * 0.5, lat2 - i * 0.5, 0)
            return [pos.x, pos.y, pos.z]
        }
         //必须明确的告诉 框架 去怎么样处理你提供的数据
         debugger
         let geometry = new Cesium.Geometry({
            attributes: {
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.FLOAT,
                    componentsPerAttribute: 3,
                    values: new Float32Array(positions),
                }),
                color: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.FLOAT,
                    componentsPerAttribute: 4,
                    values: new Float64Array(colors)
                })
            },
            indices: indices,
            boundingSphere: this.boundingSphere
        })
        debugger
        console.log(geometry, 'geometry')
        return geometry
    }

    customPrimitive() {
        console.log(new Cesium.PerInstanceColorAppearance(), 'new Cesium.PerInstanceColorAppearance()')
        console.log(this.customGeometry(), 'this.customGeometry()')
        this.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
                geometry: this.customGeometry()
            }),
            appearance: new Cesium.PerInstanceColorAppearance(),
            asynchronous: false
        }))

    }


}

Hi @11175, I’m afraid that error message is not very helpful, which I’m sure is making it harder for you to debug.
Are you able to share your code as a Sandcastle example? That would make it easier for us to help investigate further.

Sometimes, there are forum questions where I think: Well, that must be a detail, probably easy to fix.

And then I start looking into it…

:slight_smile:
:neutral_face:
:face_with_diagonal_mouth:
:slightly_frowning_face:

After a while of debugging, I can not really pinpoint the reason for the undefined ... center issue. It is related to bounding spheres, the primitiveType, the vertexFormat, and the exact way of instantiating the PerInstanceColorAppearance, and that the position attribute must have type DOUBLE.

However, here is a skeleton of what you are likely trying to accomplish: A custom grid geometry with (random) values at each grid point, mapped to a “color”. (You didn’t provide the ColorMaker class, so I’m just mapping this to shades of red):

Cesium Forum Custom Geometry

I know, the Geometry/Appearance/Primitive API is supposed to be low-level. But nevertheless, I’m strongly considering to open an issue: “Creating custom geometry should be (far) easier”…