You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To avoid camera falling to the ground it is required to correct GL near clip distance calculation taking elevation in camera position into account.
First of all, calculate near clip distance taking terrain elevation at camera point into account in WorldWindow:
@Override
protected void computeViewingTransform(Matrix4 projection, Matrix4 modelview) {
double eyeHorizon = this.globe.horizonDistance(this.navigator.getAltitude());
double atmosphereHorizon = this.globe.horizonDistance(160000);
// The far distance is set to the smallest value that does not clip the atmosphere.
double far = eyeHorizon + atmosphereHorizon;
if (far < 1e3) far = 1e3;
//The near distance is set to a large value that does not clip the globe's surface.
double maxDepthValue = (1L << this.depthBits) - 1L;
double farResolution = 10.0;
double near = far / (maxDepthValue / (1 - farResolution / far) - maxDepthValue + 1);
// Prevent the near clip plane from intersecting the terrain.
double distanceToSurface = this.navigator.getAltitude() - this.globe.getElevationAtLocation(this.navigator.getLatitude(), this.navigator.getLongitude()) * this.getVerticalExaggeration();
if (distanceToSurface > 0) {
double tanHalfFov = Math.tan(0.5 * Math.toRadians(this.fieldOfView));
double maxNearDistance = distanceToSurface / (2 * Math.sqrt(2 * tanHalfFov * tanHalfFov + 1));
if (near > maxNearDistance) near = maxNearDistance;
}
if (near < 1) near = 1;
// Compute a perspective projection matrix given the WorldWindow's viewport, field of view, and clip distances.
projection.setToPerspectiveProjection(this.viewport.width, this.viewport.height, this.fieldOfView, near, far);
// Compute a Cartesian transform matrix from the Navigator.
this.navigator.getAsViewingMatrix(this.globe, modelview);
}
Terrain elevation determination in Globe should be also added:
public double getElevationAtLocation(double latitude, double longitude) {
Sector sector = Sector.fromDegrees(latitude, longitude, 1E-15, 1E-15); // 1E-15 is used because sector can not have 0 with and height
float[] heights = new float[1];
this.getElevationModel().getHeightGrid(sector, 1, 1, heights);
return heights[0];
}
Then limit navigator movements to avoid passing below the ground:
@Override
protected Camera lookAtToCamera(Globe globe, LookAt lookAt, Camera result) {
Camera camera = super.lookAtToCamera(globe, lookAt, result);
// Check if camera altitude is not under the surface
double elevation = wwd.getElevation(camera.latitude, camera.longitude) * wwd.getVerticalExaggeration() + COLLISION_THRESHOLD;
if(elevation > camera.altitude) {
// Set camera altitude above the surface
camera.altitude = elevation;
// Compute new camera point
globe.geographicToCartesian(camera.latitude, camera.longitude, camera.altitude, originPoint);
// Compute look at point
globe.geographicToCartesian(lookAt.latitude, lookAt.longitude, lookAt.altitude, forwardRay.origin);
// Compute normal to globe in look at point
globe.geographicToCartesianNormal(lookAt.latitude, lookAt.longitude, forwardRay.direction);
// Calculate tilt angle between new camera point and look at point
originPoint.subtract(forwardRay.origin).normalize();
double dot = forwardRay.direction.dot(originPoint);
if (dot >= -1 || dot <= 1) {
camera.tilt = Math.toDegrees(Math.acos(dot));
}
}
return camera;
}
To avoid camera falling to the ground it is required to correct GL near clip distance calculation taking elevation in camera position into account.
First of all, calculate near clip distance taking terrain elevation at camera point into account in WorldWindow:
Terrain elevation determination in Globe should be also added:
Then limit navigator movements to avoid passing below the ground:
private final static double COLLISION_THRESHOLD = 10.0; // 10m above surface
The text was updated successfully, but these errors were encountered: