# Custom geometry for GroundPrimitive

1. A concise explanation of the problem you’re experiencing.

Hi,I wrote a custom geometry(GroundTinGeometry) that used to add a small triangle on terria,some parts of triangle isn’t rendered.

Here is my codes,please give me more suggestions.

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

var positions = Cesium.Cartesian3.fromDegreesArrayHeights([

104.3, 31.5, 8000,

104.5, 31.6, 8000,

104.4, 31.7, 8000

]);

var numPositions = positions.length;

var pos = new Float64Array(numPositions * 3);

for (var i = 0; i < numPositions; ++i) {

pos[i * 3] = positions[i].x;

pos[i * 3 + 1] = positions[i].y;

pos[i * 3 + 2] = positions[i].z;

}

var geometry = new Cesium.GroundTinGeometry({

attributes: {

position: new Cesium.GeometryAttribute({

componentDatatype: Cesium.ComponentDatatype.DOUBLE,

componentsPerAttribute: 3,

values: pos

})

},

indices: new Uint32Array([0, 1, 2])

});

var geoInstance = new Cesium.GeometryInstance({

geometry: geometry,

attributes: {

color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)

}

});

geometryInstances: [geoInstance],

asynchronous: true,

appearance: new Cesium.PerInstanceColorAppearance({

flat: true,

translucent: false

})

}));

// based on Cesium.RectangleGeometry

define(‘Core/GroundTinGeometry’,[

‘./arrayFill’,

‘./BoundingSphere’,

‘./Cartesian2’,

‘./Cartesian3’,

‘./Cartographic’,

‘./Check’,

‘./ComponentDatatype’,

‘./defaultValue’,

‘./defined’,

‘./defineProperties’,

‘./DeveloperError’,

‘./Ellipsoid’,

‘./Geometry’,

‘./GeometryAttribute’,

‘./GeometryAttributes’,

‘./GeometryInstance’,

‘./GeometryOffsetAttribute’,

‘./GeometryPipeline’,

‘./IndexDatatype’,

‘./Math’,

‘./Matrix2’,

‘./Matrix3’,

‘./PolygonPipeline’,

‘./PrimitiveType’,

‘./Quaternion’,

‘./Rectangle’,

‘./RectangleGeometryLibrary’,

‘./VertexFormat’],function(

arrayFill,

BoundingSphere,

Cartesian2,

Cartesian3,

Cartographic,

Check,

ComponentDatatype,

defaultValue,

defined,

defineProperties,

DeveloperError,

Ellipsoid,

Geometry,

GeometryAttribute,

GeometryAttributes,

GeometryInstance,

GeometryOffsetAttribute,

GeometryPipeline,

IndexDatatype,

CesiumMath,

Matrix2,

Matrix3,

PolygonPipeline,

PrimitiveType,

Quaternion,

Rectangle,

RectangleGeometryLibrary,

VertexFormat){

‘use strict’;

var bottomBoundingSphere = new BoundingSphere();

var topBoundingSphere = new BoundingSphere();

var normalScratch = new Cartesian3();

function GroundTinGeometry(options){

var vertices=options.attributes.position.values;

this._positions=;

var i=0;

for(;i<vertices.length;i+=3){

this._positions.push(new Cartesian3(vertices[i],vertices[i+1],vertices[i+2]));

}

this.attributes = options.attributes;

this.indices=options.indices;

this.primitiveType=PrimitiveType.TRIANGLES;

this.boundingSphere=BoundingSphere.fromVertices(vertices);

this._vertexFormat = VertexFormat.clone(defaultValue(options.vertexFormat, VertexFormat.DEFAULT));

this._ellipsoid = Ellipsoid.clone(defaultValue(options.ellipsoid, Ellipsoid.WGS84));

this._height = defaultValue(options.height, 0.0);

this._extrudedHeight = defaultValue(options.extrudedHeight, this._height);

this._surfaceHeight = Math.max(this._height, this._extrudedHeight);

this._workerName = ‘createGroundTinGeometry’;

this._rectangle = undefined;

this._textureCoordinateRotationPoints = undefined;

}

GroundTinGeometry.createGeometry=function(groundTinGeometry){

var vertexFormat = groundTinGeometry._vertexFormat;

var ellipsoid = groundTinGeometry._ellipsoid;

var granularity = groundTinGeometry._granularity;

var t_positions=groundTinGeometry._positions;

var t_indices=groundTinGeometry.indices;

var rectangle = groundTinGeometry._rectangle;

var extrudedHeight = groundTinGeometry._extrudedHeight;

var surfaceHeight=groundTinGeometry._surfaceHeight;

var extrude = !CesiumMath.equalsEpsilon(surfaceHeight, extrudedHeight, 0, CesiumMath.EPSILON2);

var geometries = ;

var i=0;

var boundingSphere;

for(;i<t_indices.length;i+=3){

var triangle=[t_positions[t_indices[i]],t_positions[t_indices[i+1]],t_positions[t_indices[i+2]]];

var geo;

if(extrude){

geo=constructExtrudedTriangle(triangle,ellipsoid,extrudedHeight,surfaceHeight);

}else{

geo=constructTriangle(triangle,ellipsoid);

geo.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(geo.attributes.position.values, surfaceHeight, ellipsoid, false);

}

geometries.push(new GeometryInstance({

geometry : geo

}));

}

var geometry = GeometryPipeline.combineInstances(geometries)[0];

geometry.attributes.position.values = new Float64Array(geometry.attributes.position.values);

geometry.indices = IndexDatatype.createTypedArray(geometry.attributes.position.values.length / 3, geometry.indices);

var attributes = geometry.attributes;

boundingSphere = BoundingSphere.fromVertices(attributes.position.values);

return new Geometry({

attributes : attributes,

indices : geometry.indices,

primitiveType : geometry.primitiveType,

boundingSphere : boundingSphere

});

}

var granularity = groundTinGeometry._granularity;

var ellipsoid = groundTinGeometry._ellipsoid;

var minHeight = minHeightFunc(granularity, ellipsoid);

var maxHeight = maxHeightFunc(granularity, ellipsoid);

return new GroundTinGeometry({

attributes:groundTinGeometry.attributes,

indices:groundTinGeometry.indices,

granularity : granularity,

extrudedHeight : minHeight,

height : maxHeight,

vertexFormat : VertexFormat.POSITION_ONLY,

});

}

function constructTriangle(triangle,ellipsoid,data){

var numPositions = triangle.length;

var pos = new Float64Array(numPositions * 3);

var normals = new Float32Array(numPositions*3);

var normal = normalScratch;

for (var i = 0; i < numPositions; ++i) {

pos[i * 3] = triangle[i].x;

pos[i * 3 + 1] = triangle[i].y;

pos[i * 3 + 2] = triangle[i].z;

var p=new Cartesian3(triangle[i].x,triangle[i].y,triangle[i].z);

normal = ellipsoid.geodeticSurfaceNormal(p, normal);

normals[i * 3] = normal.x;

normals[i * 3+1] = normal.y;

normals[i * 3+2] = normal.z;

}

return new Geometry({

attributes: {

position: new GeometryAttribute({

componentDatatype: ComponentDatatype.DOUBLE,

componentsPerAttribute: 3,

values: pos

}),

normal:new GeometryAttribute({

componentDatatype : ComponentDatatype.FLOAT,

componentsPerAttribute : 3,

values : normals

})

},

indices: new Uint32Array([0, 1, 2]),

primitiveType: PrimitiveType.TRIANGLES,

boundingSphere: BoundingSphere.fromVertices(pos)

});

}

function constructExtrudedTriangle(triangle,ellipsoid,minHeight,maxHeight,data){

var topBottomGeo = constructTriangle(triangle,ellipsoid);

var topPositions = PolygonPipeline.scaleToGeodeticHeight(topBottomGeo.attributes.position.values, maxHeight, ellipsoid, false);

topPositions = new Float64Array(topPositions);

var length = topPositions.length;

var newLength = length * 2;

var positions = new Float64Array(newLength);

positions.set(topPositions);

var bottomPositions = PolygonPipeline.scaleToGeodeticHeight(topBottomGeo.attributes.position.values, minHeight, ellipsoid);

positions.set(bottomPositions, length);

topBottomGeo.attributes.position.values = positions;

var normals =new Float32Array(newLength);

var topNormals = topBottomGeo.attributes.normal.values;

normals.set(topNormals);

for (var i = 0; i < length; i++) {

topNormals[i] = -topNormals[i];

}

normals.set(topNormals, length);

topBottomGeo.attributes.normal.values = normals;

topBottomGeo.indices = new Uint32Array([0,1,2,5,4,3]);

var wallIndices =new Uint32Array([0,1,4,

4,3,0,

1,2,4,

4,5,2,

0,2,3,

3,5,2]);

var wallGeo = new Geometry({

attributes: {

position: new GeometryAttribute({

componentDatatype: ComponentDatatype.DOUBLE,

componentsPerAttribute: 3,

values: positions

}),

normal:new GeometryAttribute({

componentDatatype : ComponentDatatype.FLOAT,

componentsPerAttribute : 3,

values : normals

})

},

indices: wallIndices,

primitiveType: PrimitiveType.TRIANGLES,

boundingSphere: BoundingSphere.fromVertices(positions)

});

var geo = GeometryPipeline.combineInstances([

new GeometryInstance({

geometry : topBottomGeo

}),

new GeometryInstance({

geometry : wallGeo

})

]);

return geo[0];

}

function computeRectangle(positions, ellipsoid, result){

if (!defined(positions) || positions.length < 3) {

if (!defined(result)) {

return new Rectangle();

}

result.west = 0.0;

result.north = 0.0;

result.south = 0.0;

result.east = 0.0;

return result;

}

return Rectangle.fromCartesianArray(positions, ellipsoid, result);

}

function textureCoordinateRotationPoints(groundTinGeometry) {

return [0, 0, 0, 1, 1, 0];

}

defineProperties(GroundTinGeometry.prototype, {

rectangle : {

get : function() {

if (!defined(this._rectangle)) {

this._rectangle = computeRectangle(this._positions, this._ellipsoid);

}

return this._rectangle;

}

},

textureCoordinateRotationPoints : {

get : function() {

if (!defined(this._textureCoordinateRotationPoints)) {

this._textureCoordinateRotationPoints = textureCoordinateRotationPoints(this);

}

return this._textureCoordinateRotationPoints;

}

}

});

return GroundTinGeometry;

});

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

4. The Cesium version you’re using, your operating system and browser.

Cesium 1.53

The reason some triangles would not be rendered is usually because they’re facing the wrong way. I’d try to flip all the normals and see if the missing triangles show up that way (and then all the other triangles should disappear). If this is the issue you’ll need to double check that your triangles have the right orientation.

That’s very kind of you,I add only one small triangle,and set every normal of 6 extruded vertices by ellipsoid.geodeticSurfaceNormal(p, normal).this is also used for wall vertices.