@@ -62,17 +62,21 @@ public interface LevelOfDetailSelector {
62
62
63
63
protected static final double DEFAULT_DEPTH_OFFSET = -0.03 ;
64
64
65
- private static Vec3 placePoint = new Vec3 ();
65
+ private static final Vec3 placePoint = new Vec3 ();
66
66
67
- private static Vec3 screenPlacePoint = new Vec3 ();
67
+ private static final Vec3 screenPlacePoint = new Vec3 ();
68
68
69
- private static Vec3 groundPoint = new Vec3 ();
69
+ private static final Vec3 groundPoint = new Vec3 ();
70
70
71
- private static Vec2 offset = new Vec2 ();
71
+ private static final Vec2 offset = new Vec2 ();
72
72
73
- private static Matrix4 unitSquareTransform = new Matrix4 ();
73
+ private static final Matrix4 imageTransform = new Matrix4 ();
74
74
75
- private static Viewport screenBounds = new Viewport ();
75
+ private static final Matrix4 labelTransform = new Matrix4 ();
76
+
77
+ private static final Viewport imageBounds = new Viewport ();
78
+
79
+ private static final Viewport labelBounds = new Viewport ();
76
80
77
81
/**
78
82
* The placemark's geographic position.
@@ -105,6 +109,11 @@ public interface LevelOfDetailSelector {
105
109
*/
106
110
protected Texture activeTexture ;
107
111
112
+ /**
113
+ * The texture associated with the label attributes, or null if the attributes specify no image.
114
+ */
115
+ protected Texture labelTexture ;
116
+
108
117
/**
109
118
* The picked object ID associated with the placemark during the current render pass.
110
119
*/
@@ -115,8 +124,7 @@ public interface LevelOfDetailSelector {
115
124
/**
116
125
* The label text to draw near the placemark.
117
126
*/
118
- // TODO: implement label property
119
- // protected String label;
127
+ protected String label ;
120
128
121
129
/**
122
130
* Determines whether the normal or highlighted attibutes should be used.
@@ -210,7 +218,7 @@ public Placemark(Position position, PlacemarkAttributes attributes, String name)
210
218
this .setPosition (position );
211
219
this .setAltitudeMode (WorldWind .ABSOLUTE );
212
220
this .setDisplayName (name == null || name .isEmpty () ? "Placemark" : name );
213
- // this.setLabel(name); // TODO: call setLabel(name)
221
+ //this.setLabel(name);
214
222
this .attributes = attributes ;
215
223
this .eyeDistanceScaling = false ;
216
224
this .eyeDistanceScalingThreshold = DEFAULT_EYE_DISTANCE_SCALING_THRESHOLD ;
@@ -257,10 +265,9 @@ public static Placemark createWithImage(Position position, ImageSource imageSour
257
265
*
258
266
* @return A new Placemark with a PlacemarkAttributes bundle containing TextAttributes.
259
267
*/
260
- // TODO: implement createWithImageAndLabel factory method
261
- // public static Placemark createWithImageAndLabel(Position position, ImageSource imageSource, String label) {
262
- // return new Placemark(position, PlacemarkAttributes.createWithImage(imageSource), label);
263
- // }
268
+ public static Placemark createWithImageAndLabel (Position position , ImageSource imageSource , String label ) {
269
+ return new Placemark (position , PlacemarkAttributes .createWithImage (imageSource ), label );
270
+ }
264
271
265
272
/**
266
273
* Gets this placemark's geographic position.
@@ -385,15 +392,15 @@ public Placemark setLevelOfDetailSelector(LevelOfDetailSelector levelOfDetailSel
385
392
this .levelOfDetailSelector = levelOfDetailSelector ;
386
393
return this ;
387
394
}
388
- /**
395
+
396
+ /*
389
397
* Gets the text used to label this placemark on the globe.
390
398
*
391
399
* @return The text used to label a placemark on the globe when labels are enabled
392
400
*/
393
- // TODO: implement getLabel()
394
- // public String getLabel() {
395
- // return label;
396
- // }
401
+ public String getLabel () {
402
+ return label ;
403
+ }
397
404
398
405
/**
399
406
* Sets the text used for this placemark's label on the globe.
@@ -402,11 +409,10 @@ public Placemark setLevelOfDetailSelector(LevelOfDetailSelector levelOfDetailSel
402
409
*
403
410
* @return This placemark
404
411
*/
405
- // TODO: implement setLabel()
406
- // public Placemark setLabel(String label) {
407
- // this.label = label;
408
- // return this;
409
- // }
412
+ public Placemark setLabel (String label ) {
413
+ this .label = label ;
414
+ return this ;
415
+ }
410
416
411
417
/**
412
418
* Indicates whether this placemark's size is reduced at higher eye distances. If true, this placemark's size is
@@ -749,61 +755,13 @@ protected void doRender(RenderContext rc) {
749
755
// Compute the placemark icon's active texture.
750
756
this .determineActiveTexture (rc );
751
757
752
- // If the placemark's icon is visible, enqueue a drawable icon for processing on the OpenGL thread.
753
- WWMath .boundingRectForUnitSquare (unitSquareTransform , screenBounds );
754
- if (rc .frustum .intersectsViewport (screenBounds )) {
755
- Pool <DrawableScreenTexture > pool = rc .getDrawablePool (DrawableScreenTexture .class );
756
- DrawableScreenTexture drawable = DrawableScreenTexture .obtain (pool );
757
- this .prepareDrawableIcon (rc , drawable );
758
- rc .offerShapeDrawable (drawable , this .cameraDistance );
759
- }
760
-
761
- // Release references to objects stored in the render resource cache.
762
- this .activeTexture = null ;
763
-
764
- // Enqueue a picked object that associates the placemark's icon and leader with its picked object ID.
765
- if (rc .pickMode && rc .drawableCount () != drawableCount ) {
766
- rc .offerPickedObject (PickedObject .fromRenderable (this .pickedObjectId , this , rc .currentLayer ));
767
- }
768
- }
769
-
770
- /**
771
- * Determines the placemark attributes to use for the current render pass.
772
- *
773
- * @param rc the current render context
774
- */
775
- protected void determineActiveAttributes (RenderContext rc ) {
776
- if (this .highlighted && this .highlightAttributes != null ) {
777
- this .activeAttributes = this .highlightAttributes ;
778
- } else {
779
- this .activeAttributes = this .attributes ;
780
- }
781
- }
782
-
783
- /**
784
- * Determines the image texture and unit square transform to use for the current render pass.
785
- *
786
- * @param rc the current render context
787
- */
788
- protected void determineActiveTexture (RenderContext rc ) {
789
- // TODO: Refactor!
790
- if (this .activeAttributes .imageSource != null ) {
791
- // Earlier in doRender(), an attempt was made to 'get' the activeTexture from the cache.
792
- // If was not found in the cache we need to retrieve a texture from the image source.
793
- if (this .activeTexture == null ) {
794
- this .activeTexture = rc .retrieveTexture (this .activeAttributes .imageSource , null ); // puts retrieved textures in the cache
795
- }
796
- } else {
797
- this .activeTexture = null ; // there is no imageSource; draw a simple colored square
798
- }
799
-
800
758
// Compute an camera-position proximity scaling factor, so that distant placemarks can be scaled smaller than
801
759
// nearer placemarks.
802
760
double visibilityScale = this .isEyeDistanceScaling () ?
803
761
Math .max (this .activeAttributes .minimumImageScale , Math .min (1 , this .getEyeDistanceScalingThreshold () / this .cameraDistance )) : 1 ;
804
762
805
763
// Initialize the unit square transform to the identity matrix.
806
- unitSquareTransform .setToIdentity ();
764
+ imageTransform .setToIdentity ();
807
765
808
766
// Apply the icon's translation and scale according to the image size, image offset and image scale. The image
809
767
// offset is defined with its origin at the image's bottom-left corner and axes that extend up and to the right
@@ -831,34 +789,113 @@ protected void determineActiveTexture(RenderContext rc) {
831
789
}
832
790
833
791
// Position image on screen
834
- unitSquareTransform .multiplyByTranslation (
792
+ imageTransform .multiplyByTranslation (
835
793
screenPlacePoint .x ,
836
794
screenPlacePoint .y ,
837
795
screenPlacePoint .z );
838
796
839
797
// Divide Z by 2^24 to prevent texture clipping when tilting (where 24 is depth buffer bit size).
840
798
// Doing so will limit depth range to (diagonal length)/2^24 and make its value within 0..1 range.
841
- unitSquareTransform .multiplyByScale (1 , 1 , 1d / (1 << 24 ) );
799
+ imageTransform .multiplyByScale (1 , 1 , 1d / (1 << 24 ) );
842
800
843
801
// Perform the tilt so that the image tilts back from its base into the view volume
844
802
if (this .imageTilt != 0 ) {
845
- double tilt = this .imageTiltReference == WorldWind .RELATIVE_TO_GLOBE ?
803
+ double actualTilt = this .imageTiltReference == WorldWind .RELATIVE_TO_GLOBE ?
846
804
rc .camera .tilt + this .imageTilt : this .imageTilt ;
847
- unitSquareTransform .multiplyByRotation (-1 , 0 , 0 , tilt );
805
+ imageTransform .multiplyByRotation (-1 , 0 , 0 , actualTilt );
848
806
}
849
807
850
808
// Perform image rotation
851
809
if (this .imageRotation != 0 ) {
852
- double rotation = this .imageRotationReference == WorldWind .RELATIVE_TO_GLOBE ?
810
+ double actualRotation = this .imageRotationReference == WorldWind .RELATIVE_TO_GLOBE ?
853
811
rc .camera .heading - this .imageRotation : -this .imageRotation ;
854
- unitSquareTransform .multiplyByRotation (0 , 0 , 1 , rotation );
812
+ imageTransform .multiplyByRotation (0 , 0 , 1 , actualRotation );
855
813
}
856
814
857
815
// Apply pivot translation
858
- unitSquareTransform .multiplyByTranslation (-offsetX , -offsetY , 0 );
816
+ imageTransform .multiplyByTranslation (-offsetX , -offsetY , 0 );
859
817
860
818
// Apply scale
861
- unitSquareTransform .multiplyByScale (scaleX , scaleY , 1 );
819
+ imageTransform .multiplyByScale (scaleX , scaleY , 1 );
820
+
821
+ // If the placemark's icon is visible, enqueue a drawable icon for processing on the OpenGL thread.
822
+ WWMath .boundingRectForUnitSquare (imageTransform , imageBounds );
823
+ if (rc .frustum .intersectsViewport (imageBounds )) {
824
+ Pool <DrawableScreenTexture > pool = rc .getDrawablePool (DrawableScreenTexture .class );
825
+ DrawableScreenTexture drawable = DrawableScreenTexture .obtain (pool );
826
+ this .prepareDrawableIcon (rc , drawable );
827
+ rc .offerShapeDrawable (drawable , this .cameraDistance );
828
+ }
829
+
830
+ // If there's a label, perform these same operations for the label texture.
831
+ if (this .mustDrawLabel (rc )) {
832
+ // Render the label's texture when the label's position is in the frustum. If the label's position is outside
833
+ // the frustum we don't do anything. This ensures that label textures are rendered only as necessary.
834
+ this .labelTexture = rc .getText (this .label , this .activeAttributes .labelAttributes );
835
+ if (this .labelTexture == null && rc .frustum .containsPoint (placePoint )) {
836
+ this .labelTexture = rc .renderText (this .label , this .activeAttributes .labelAttributes );
837
+ }
838
+
839
+ if (this .labelTexture != null ) {
840
+ int w = this .labelTexture .getWidth ();
841
+ int h = this .labelTexture .getHeight ();
842
+ this .activeAttributes .labelAttributes .textOffset .offsetForSize (w , h , offset );
843
+
844
+ labelTransform .setTranslation (
845
+ screenPlacePoint .x - offset .x ,
846
+ screenPlacePoint .y - offset .y ,
847
+ screenPlacePoint .z );
848
+
849
+ labelTransform .setScale (w , h , 1 );
850
+
851
+ WWMath .boundingRectForUnitSquare (labelTransform , labelBounds );
852
+ if (rc .frustum .intersectsViewport (labelBounds )) {
853
+ Pool <DrawableScreenTexture > pool = rc .getDrawablePool (DrawableScreenTexture .class );
854
+ DrawableScreenTexture drawable = DrawableScreenTexture .obtain (pool );
855
+ this .prepareDrawableLabel (rc , drawable );
856
+ rc .offerShapeDrawable (drawable , this .cameraDistance );
857
+ }
858
+ }
859
+ }
860
+
861
+ // Release references to objects stored in the render resource cache.
862
+ this .activeTexture = null ;
863
+ this .labelTexture = null ;
864
+
865
+ // Enqueue a picked object that associates the placemark's icon and leader with its picked object ID.
866
+ if (rc .pickMode && rc .drawableCount () != drawableCount ) {
867
+ rc .offerPickedObject (PickedObject .fromRenderable (this .pickedObjectId , this , rc .currentLayer ));
868
+ }
869
+ }
870
+
871
+ /**
872
+ * Determines the placemark attributes to use for the current render pass.
873
+ *
874
+ * @param rc the current render context
875
+ */
876
+ protected void determineActiveAttributes (RenderContext rc ) {
877
+ if (this .highlighted && this .highlightAttributes != null ) {
878
+ this .activeAttributes = this .highlightAttributes ;
879
+ } else {
880
+ this .activeAttributes = this .attributes ;
881
+ }
882
+ }
883
+
884
+ /**
885
+ * Determines the image texture and unit square transform to use for the current render pass.
886
+ *
887
+ * @param rc the current render context
888
+ */
889
+ protected void determineActiveTexture (RenderContext rc ) {
890
+ if (this .activeAttributes .imageSource != null ) {
891
+ // Earlier in doRender(), an attempt was made to 'get' the activeTexture from the cache.
892
+ // If was not found in the cache we need to retrieve a texture from the image source.
893
+ if (this .activeTexture == null ) {
894
+ this .activeTexture = rc .retrieveTexture (this .activeAttributes .imageSource , null ); // puts retrieved textures in the cache
895
+ }
896
+ } else {
897
+ this .activeTexture = null ; // there is no imageSource; draw a simple colored square
898
+ }
862
899
}
863
900
864
901
/**
@@ -876,7 +913,7 @@ protected void prepareDrawableIcon(RenderContext rc, DrawableScreenTexture drawa
876
913
}
877
914
878
915
// Use the plaemark's unit square transform matrix.
879
- drawable .unitSquareTransform .set (unitSquareTransform );
916
+ drawable .unitSquareTransform .set (imageTransform );
880
917
881
918
// Configure the drawable according to the placemark's active attributes. Use a color appropriate for the pick
882
919
// mode. When picking use a unique color associated with the picked object ID. Use the texture associated with
@@ -887,6 +924,37 @@ protected void prepareDrawableIcon(RenderContext rc, DrawableScreenTexture drawa
887
924
drawable .enableDepthTest = this .activeAttributes .depthTest ;
888
925
}
889
926
927
+ /**
928
+ * Prepares this placemark's label for processing in a subsequent drawing pass. Implementations must be
929
+ * careful not to leak resources from Placemark into the Drawable.
930
+ *
931
+ * @param rc the current render context
932
+ * @param drawable the Drawable to be prepared
933
+ */
934
+ protected void prepareDrawableLabel (RenderContext rc , DrawableScreenTexture drawable ) {
935
+ // Use the basic GLSL program to draw the placemark's label.
936
+ drawable .program = (BasicShaderProgram ) rc .getShaderProgram (BasicShaderProgram .KEY );
937
+ if (drawable .program == null ) {
938
+ drawable .program = (BasicShaderProgram ) rc .putShaderProgram (BasicShaderProgram .KEY , new BasicShaderProgram (rc .resources ));
939
+ }
940
+
941
+ // Use the label's unit square transform matrix.
942
+ drawable .unitSquareTransform .set (labelTransform );
943
+
944
+ // Configure the drawable according to the active label attributes. Use a color appropriate for the pick mode. When
945
+ // picking use a unique color associated with the picked object ID. Use the texture associated with the active
946
+ // attributes' text image and its associated tex coord transform. The text texture includes the appropriate
947
+ // color for drawing, specifying white for normal drawing ensures the color multiplication in the shader results
948
+ // in the texture's color.
949
+ if (rc .pickMode ) {
950
+ drawable .color .set (this .pickColor );
951
+ } else {
952
+ drawable .color .set (1 , 1 , 1 , 1 );
953
+ }
954
+ drawable .texture = this .labelTexture ;
955
+ drawable .enableDepthTest = this .activeAttributes .labelAttributes .isEnableDepthTest ();
956
+ }
957
+
890
958
/**
891
959
* Prepares this placemark's leader for drawing in a subsequent drawing pass. Implementations must be careful not to
892
960
* leak resources from Placemark into the Drawable.
@@ -925,13 +993,10 @@ protected void prepareDrawableLeader(RenderContext rc, DrawableLines drawable) {
925
993
*
926
994
* @return True if there is a valid label and label attributes.
927
995
*/
928
-
929
996
protected boolean mustDrawLabel (RenderContext rc ) {
930
- return false ;
931
- // TODO: implement mustDrawLabel()
932
- // return this.label != null
933
- // && !this.label.isEmpty()
934
- // && this.activeAttributes.labelAttributes != null;
997
+ return this .label != null
998
+ && !this .label .isEmpty ()
999
+ && this .activeAttributes .labelAttributes != null ;
935
1000
}
936
1001
937
1002
/**
0 commit comments