Surface normals

My surface normals are not displaying correctly on my custom geometry.

Is there a way to display the normals of the geometry instance?

The tetrahedron tutorial says to use this:

scene.primitives.add(Cesium.createTangentSpaceDebugPrimitive({
    geometry: tetrahedron,
    modelMatrix: modelMatrix,
    length: 0.2
}));

but that isn’t working for me and I don’t see ‘createTangentSpaceDebugPrimitive’ in the reference documentation. Is there a way to display normals in the latest version of Cesium?

It looks like there's a bug in Primitive being triggered by createTangentSpaceDebugPrimitive.  You can work around it by manually setting the returned primitive._asynchronous to false.  I'm also not sure why it's not showing up in the doc, I'll file a bug for both issues.

Meanwhile, here's a complete example with the workaround.  You might also have to jack up the length value depending on your geometry.

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var scene = viewer.scene;

var dimensions = new Cesium.Cartesian3(400000.0, 300000.0, 500000.0);

var positionOnEllipsoid = Cesium.Cartesian3.fromDegrees(-105.0, 45.0);

var boxModelMatrix = Cesium.Matrix4.multiplyByTranslation(

Cesium.Transforms.eastNorthUpToFixedFrame(positionOnEllipsoid),

new Cesium.Cartesian3(0.0, 0.0, dimensions.z * 0.5), new Cesium.Matrix4());

var boxGeometry = Cesium.BoxGeometry.fromDimensions({

vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT,

dimensions : dimensions

});

var boxGeometryInstance = new Cesium.GeometryInstance({

geometry : boxGeometry,

modelMatrix : boxModelMatrix,

attributes : {

    color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 0.0, 0.0, 0.5))

}

});

scene.primitives.add(new Cesium.Primitive({

geometryInstances : boxGeometryInstance,

appearance : new Cesium.PerInstanceColorAppearance({

    closed: true

})

}));

var debugPrimitive = Cesium.createTangentSpaceDebugPrimitive({

geometry: boxGeometry,

modelMatrix: boxModelMatrix,

length: 100000

});

debugPrimitive._asynchronous = false;

scene.primitives.add(debugPrimitive);

That did the trick thanks!

It doesn’t appear that the sides of my hemisphere object have any normals despite being drawn by the indices:

I’m guessing I will have to calculate the side triangles independently to generate their normals. Right now it is just pulling them all to a single origin point which, much like in the tetrahedron tutorial, is creating strange results.

Thanks again.

There are also some helper functions that you might find useful: GeometryPipeline.computeNormal and GeometryPipeline.computeBinormalAndTangent, which may do it for you. They are not as optimal depending on the geometry, but I think they work in all cases.

According to the tutorial at https://github.com/AnalyticalGraphicsInc/cesium/wiki/Geometry-and-Appearances

“To get better shading, we must duplicate each vertex so that adjacent triangles no longer share vertices.”

Resulting in multiple normals at each verticie, each pointing perpendicular to the triangle that uses them. Perhaps you’re already doing this?

"Using single vertices works best when angle between adjacent triangles is close to 180 degrees (like the triangles in a sphere), and thus the normals for the adjacent triangles are pointing in the same general direction. "

So perhaps just do this on sharp angles.

I will likely have to do that because I’m not getting good results with the other ways I have tried.

Creating the triangles independently, the algorithms to create the vertices and connect the indices gets a bit too complicated for my brain to figure out. As in the image below of a flattened 3x3 version of the polygon, the number of vertices can range from 3 to 6 depending on the point they will connect:

Therefore, I will probably create the face with shared vertices and create the sides with individual vertices to cut out a lot of the complication and hopefully get a similar result.

Yea, splitting your custom primitive into faces sounds like a good idea. Faces being sections that don’t have sharp edges (adjacent triangle normal directions don’t differ much.) Triangles within each face can share vertices without shading problems.

Matt mentioned GeometryPipeline.computeBinormalAndTangent

http://cesiumjs.org/Cesium/Build/Documentation/GeometryPipeline.html

The tutorial has no mention of it though. Perhaps using that would make things even simpler?