Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/placemark rotation and tilt #251

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ protected void onPostExecute(Void notUsed) {
Placemark drone = new Placemark(
Position.fromDegrees(32.4520, 63.44553, 3000),
MilStd2525.getPlacemarkAttributes("SFAPMFQM--GIUSA", modifiers, null));
drone.getAttributes().setDrawLeader(true);

symbolLayer.addRenderable(drone);

Expand All @@ -96,6 +97,7 @@ protected void onPostExecute(Void notUsed) {
Placemark launcher = new Placemark(
Position.fromDegrees(32.4014, 63.3894, 0),
MilStd2525.getPlacemarkAttributes("SHGXUCFRMS----G", modifiers, null));
launcher.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);

symbolLayer.addRenderable(launcher);

Expand All @@ -109,6 +111,7 @@ protected void onPostExecute(Void notUsed) {
Placemark machineGun = new Placemark(
Position.fromDegrees(32.3902, 63.4161, 0),
MilStd2525.getPlacemarkAttributes("SFGPEWRH--MTUSG", modifiers, null));
machineGun.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);

symbolLayer.addRenderable(machineGun);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ public Bitmap createBitmap() {
Rect bounds = imageInfo.getImageBounds(); // The extents of the image, including text modifiers
this.placemarkOffset = new Offset(
WorldWind.OFFSET_PIXELS, centerPoint.x, // x offset
WorldWind.OFFSET_PIXELS, bounds.height() - centerPoint.y); // y offset converted to lower-left origin
// Use billboarding or lollipopping to prevent icon clipping by terrain as described in MIL-STD-2525C APPENDIX F.5.1.1.2
WorldWind.OFFSET_PIXELS, 0/*bounds.height() - centerPoint.y*/); // y offset converted to lower-left origin

// Apply the placemark offset to the attributes on the main thread. This is necessary to synchronize write
// access to placemarkAttributes from the thread that invokes this BitmapFactory and read access from the
Expand Down
57 changes: 33 additions & 24 deletions worldwind/src/main/java/gov/nasa/worldwind/shape/Placemark.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public interface LevelOfDetailSelector {
*/
protected static final double DEFAULT_EYE_DISTANCE_SCALING_THRESHOLD = 1e6;

protected static final double DEFAULT_DEPTH_OFFSET = -0.1;
protected static final double DEFAULT_DEPTH_OFFSET = -0.03;

private static Vec3 placePoint = new Vec3();

Expand Down Expand Up @@ -684,8 +684,9 @@ protected void doRender(RenderContext rc) {

// Compute a screen depth offset appropriate for the current viewing parameters.
double depthOffset = 0;
if (this.cameraDistance < rc.horizonDistance) {
depthOffset = DEFAULT_DEPTH_OFFSET;
double absTilt = Math.abs( rc.camera.tilt );
if (this.cameraDistance < rc.horizonDistance && absTilt <= 90) {
depthOffset = ( 1 - absTilt / 90 ) * DEFAULT_DEPTH_OFFSET;
}

// Project the placemark's model point to screen coordinates, using the screen depth offset to push the screen
Expand Down Expand Up @@ -808,48 +809,56 @@ protected void determineActiveTexture(RenderContext rc) {
// offset is defined with its origin at the image's bottom-left corner and axes that extend up and to the right
// from the origin point. When the placemark has no active texture the image scale defines the image size and no
// other scaling is applied.
double offsetX, offsetY, scaleX, scaleY;
if (this.activeTexture != null) {
int w = this.activeTexture.getWidth();
int h = this.activeTexture.getHeight();
double s = this.activeAttributes.imageScale * visibilityScale;
this.activeAttributes.imageOffset.offsetForSize(w, h, offset);

unitSquareTransform.multiplyByTranslation(
screenPlacePoint.x - offset.x * s,
screenPlacePoint.y - offset.y * s,
screenPlacePoint.z);

unitSquareTransform.multiplyByScale(w * s, h * s, 1);
offsetX = offset.x * s;
offsetY = offset.y * s;
scaleX = w * s;
scaleY = h * s;
} else {
// This branch serves both non-textured attributes and also textures that haven't been loaded yet.
// We set the size for non-loaded textures to the typical size of a contemporary "small" icon (24px)
double size = this.activeAttributes.imageSource != null ? 24 : this.activeAttributes.imageScale;
size *= visibilityScale;
this.activeAttributes.imageOffset.offsetForSize(size, size, offset);
offsetX = offset.x;
offsetY = offset.y;
scaleX = scaleY = size;
}

unitSquareTransform.multiplyByTranslation(
screenPlacePoint.x - offset.x,
screenPlacePoint.y - offset.y,
// Position image on screen
unitSquareTransform.multiplyByTranslation(
screenPlacePoint.x,
screenPlacePoint.y,
screenPlacePoint.z);

unitSquareTransform.multiplyByScale(size, size, 1);
// Divide Z by 2^24 to prevent texture clipping when tilting (where 24 is depth buffer bit size).
// Doing so will limit depth range to (diagonal length)/2^24 and make its value within 0..1 range.
unitSquareTransform.multiplyByScale(1, 1, 1d / (1 << 24) );

// Perform the tilt so that the image tilts back from its base into the view volume
if (this.imageTilt != 0) {
double tilt = this.imageTiltReference == WorldWind.RELATIVE_TO_GLOBE ?
rc.camera.tilt + this.imageTilt : this.imageTilt;
unitSquareTransform.multiplyByRotation(-1, 0, 0, tilt);
}

// ... perform image rotation
// Perform image rotation
if (this.imageRotation != 0) {
double rotation = this.imageRotationReference == WorldWind.RELATIVE_TO_GLOBE ?
rc.camera.heading - this.imageRotation : -this.imageRotation;
unitSquareTransform.multiplyByTranslation(0.5, 0.5, 0);
rc.camera.heading - this.imageRotation : -this.imageRotation;
unitSquareTransform.multiplyByRotation(0, 0, 1, rotation);
unitSquareTransform.multiplyByTranslation(-0.5, -0.5, 0);
}

// ... and perform the tilt so that the image tilts back from its base into the view volume.
if (this.imageTilt != 0) {
double tilt = this.imageTiltReference == WorldWind.RELATIVE_TO_GLOBE ?
rc.camera.tilt + this.imageTilt : this.imageTilt;
unitSquareTransform.multiplyByRotation(-1, 0, 0, tilt);
}
// Apply pivot translation
unitSquareTransform.multiplyByTranslation(-offsetX, -offsetY, 0);

// Apply scale
unitSquareTransform.multiplyByScale(scaleX, scaleY, 1);
}

/**
Expand Down