19
19
import gov .nasa .worldwind .draw .DrawableShape ;
20
20
import gov .nasa .worldwind .draw .DrawableSurfaceShape ;
21
21
import gov .nasa .worldwind .geom .Location ;
22
+ import gov .nasa .worldwind .geom .Matrix3 ;
23
+ import gov .nasa .worldwind .geom .Matrix4 ;
22
24
import gov .nasa .worldwind .geom .Position ;
23
25
import gov .nasa .worldwind .geom .Range ;
24
26
import gov .nasa .worldwind .geom .Vec3 ;
25
27
import gov .nasa .worldwind .render .BasicShaderProgram ;
26
28
import gov .nasa .worldwind .render .BufferObject ;
29
+ import gov .nasa .worldwind .render .ImageOptions ;
27
30
import gov .nasa .worldwind .render .RenderContext ;
31
+ import gov .nasa .worldwind .render .Texture ;
28
32
import gov .nasa .worldwind .util .Logger ;
29
33
import gov .nasa .worldwind .util .Pool ;
30
34
import gov .nasa .worldwind .util .ShortArray ;
@@ -81,6 +85,10 @@ public class Ellipse extends AbstractShape {
81
85
*/
82
86
protected static final int SIDE_RANGE = 2 ;
83
87
88
+ protected static final ImageOptions defaultInteriorImageOptions = new ImageOptions ();
89
+
90
+ protected static final ImageOptions defaultOutlineImageOptions = new ImageOptions ();
91
+
84
92
/**
85
93
* Simple interval count based cache of the keys for element buffers. Element buffers are dependent only on the
86
94
* number of intervals so the keys are cached here. The element buffer object itself is in the
@@ -145,12 +153,28 @@ public class Ellipse extends AbstractShape {
145
153
146
154
protected boolean isSurfaceShape ;
147
155
156
+ protected double texCoord1d ;
157
+
158
+ protected Vec3 texCoord2d = new Vec3 ();
159
+
160
+ protected Matrix3 texCoordMatrix = new Matrix3 ();
161
+
162
+ protected Matrix4 modelToTexCoord = new Matrix4 ();
163
+
148
164
protected double cameraDistance ;
149
165
166
+ protected Vec3 prevPoint = new Vec3 ();
167
+
150
168
private static Position scratchPosition = new Position ();
151
169
152
170
private static Vec3 scratchPoint = new Vec3 ();
153
171
172
+ static {
173
+ defaultInteriorImageOptions .wrapMode = WorldWind .REPEAT ;
174
+ defaultOutlineImageOptions .resamplingMode = WorldWind .NEAREST_NEIGHBOR ;
175
+ defaultOutlineImageOptions .wrapMode = WorldWind .REPEAT ;
176
+ }
177
+
154
178
/**
155
179
* Constructs an ellipse with a null center position, and with major- and minor-radius both 0.0. This ellipse does
156
180
* not display until the center position is defined and the radii are both greater than 0.0.
@@ -378,7 +402,7 @@ public Ellipse setFollowTerrain(boolean followTerrain) {
378
402
* Indicates the maximum number of angular intervals that may be used to approximate this ellipse's geometry on
379
403
* screen.
380
404
*
381
- * @return the maximum number of angular intervals
405
+ * @return the number of angular intervals
382
406
*/
383
407
public int getMaximumIntervals () {
384
408
return this .maximumIntervals ;
@@ -435,6 +459,7 @@ protected void makeDrawable(RenderContext rc) {
435
459
drawable = DrawableSurfaceShape .obtain (pool );
436
460
drawState = ((DrawableSurfaceShape ) drawable ).drawState ;
437
461
((DrawableSurfaceShape ) drawable ).sector .set (this .boundingSector );
462
+ this .cameraDistance = this .cameraDistanceGeographic (rc , this .boundingSector );
438
463
} else {
439
464
Pool <DrawableShape > pool = rc .getDrawablePool (DrawableShape .class );
440
465
drawable = DrawableShape .obtain (pool );
@@ -498,7 +523,21 @@ protected void drawInterior(RenderContext rc, DrawShapeState drawState) {
498
523
return ;
499
524
}
500
525
501
- drawState .texture (null );
526
+ // Configure the drawable to use the interior texture when drawing the interior.
527
+ if (this .activeAttributes .interiorImageSource != null ) {
528
+ Texture texture = rc .getTexture (this .activeAttributes .interiorImageSource );
529
+ if (texture == null ) {
530
+ texture = rc .retrieveTexture (this .activeAttributes .interiorImageSource , defaultInteriorImageOptions );
531
+ }
532
+ if (texture != null ) {
533
+ double metersPerPixel = rc .pixelSizeAtDistance (this .cameraDistance );
534
+ this .computeRepeatingTexCoordTransform (texture , metersPerPixel , this .texCoordMatrix );
535
+ drawState .texture (texture );
536
+ drawState .texCoordMatrix (this .texCoordMatrix );
537
+ }
538
+ } else {
539
+ drawState .texture (null );
540
+ }
502
541
503
542
// Configure the drawable to display the shape's interior.
504
543
drawState .color (rc .pickMode ? this .pickColor : this .activeAttributes .interiorColor );
@@ -509,6 +548,7 @@ protected void drawInterior(RenderContext rc, DrawShapeState drawState) {
509
548
510
549
if (this .extrude ) {
511
550
Range side = drawState .elementBuffer .ranges .get (SIDE_RANGE );
551
+ drawState .texture (null );
512
552
drawState .drawElements (GLES20 .GL_TRIANGLE_STRIP , side .length (),
513
553
GLES20 .GL_UNSIGNED_SHORT , side .lower * 2 );
514
554
}
@@ -519,7 +559,21 @@ protected void drawOutline(RenderContext rc, DrawShapeState drawState) {
519
559
return ;
520
560
}
521
561
522
- drawState .texture (null );
562
+ // Configure the drawable to use the outline texture when drawing the outline.
563
+ if (this .activeAttributes .outlineImageSource != null ) {
564
+ Texture texture = rc .getTexture (this .activeAttributes .outlineImageSource );
565
+ if (texture == null ) {
566
+ texture = rc .retrieveTexture (this .activeAttributes .outlineImageSource , defaultOutlineImageOptions );
567
+ }
568
+ if (texture != null ) {
569
+ double metersPerPixel = rc .pixelSizeAtDistance (this .cameraDistance );
570
+ this .computeRepeatingTexCoordTransform (texture , metersPerPixel , this .texCoordMatrix );
571
+ drawState .texture (texture );
572
+ drawState .texCoordMatrix (this .texCoordMatrix );
573
+ }
574
+ } else {
575
+ drawState .texture (null );
576
+ }
523
577
524
578
// Configure the drawable to display the shape's outline.
525
579
drawState .color (rc .pickMode ? this .pickColor : this .activeAttributes .outlineColor );
@@ -531,6 +585,9 @@ protected void drawOutline(RenderContext rc, DrawShapeState drawState) {
531
585
532
586
if (this .activeAttributes .drawVerticals && this .extrude ) {
533
587
Range side = drawState .elementBuffer .ranges .get (SIDE_RANGE );
588
+ drawState .color (rc .pickMode ? this .pickColor : this .activeAttributes .outlineColor );
589
+ drawState .lineWidth (this .activeAttributes .outlineWidth );
590
+ drawState .texture (null );
534
591
drawState .drawElements (GLES20 .GL_LINES , side .length (),
535
592
GLES20 .GL_UNSIGNED_SHORT , side .lower * 2 );
536
593
}
@@ -551,6 +608,9 @@ protected void assembleGeometry(RenderContext rc) {
551
608
// Determine whether the shape geometry must be assembled as Cartesian geometry or as goegraphic geometry.
552
609
this .isSurfaceShape = (this .altitudeMode == WorldWind .CLAMP_TO_GROUND ) && this .followTerrain ;
553
610
611
+ // Compute a matrix that transforms from Cartesian coordinates to shape texture coordinates.
612
+ this .determineModelToTexCoord (rc );
613
+
554
614
// Use the ellipse's center position as the local origin for vertex positions.
555
615
if (this .isSurfaceShape ) {
556
616
this .vertexOrigin .set (this .center .longitude , this .center .latitude , this .center .altitude );
@@ -563,9 +623,7 @@ protected void assembleGeometry(RenderContext rc) {
563
623
int spineCount = computeNumberSpinePoints (this .activeIntervals ); // activeIntervals must be even
564
624
565
625
// Clear the shape's vertex array. The array will accumulate values as the shapes's geometry is assembled.
566
- // Determine the offset from the top and extruded vertices
567
626
this .vertexIndex = 0 ;
568
- int arrayOffset = computeIndexOffset (this .activeIntervals ) * VERTEX_STRIDE ;
569
627
if (this .extrude && !this .isSurfaceShape ) {
570
628
this .vertexArray = new float [(this .activeIntervals * 2 + spineCount ) * VERTEX_STRIDE ];
571
629
} else {
@@ -589,6 +647,8 @@ protected void assembleGeometry(RenderContext rc) {
589
647
minorArcRadians = this .majorRadius / globeRadius ;
590
648
}
591
649
650
+ // Determine the offset from the top and extruded vertices
651
+ int arrayOffset = computeIndexOffset (this .activeIntervals ) * VERTEX_STRIDE ;
592
652
// Setup spine radius values
593
653
int spineIdx = 0 ;
594
654
double [] spineRadius = new double [spineCount ];
@@ -637,7 +697,6 @@ protected static BufferObject assembleElements(int intervals) {
637
697
638
698
// Generate the top element buffer with spine
639
699
int interiorIdx = intervals ;
640
- int spinePoints = computeNumberSpinePoints (intervals );
641
700
int offset = computeIndexOffset (intervals );
642
701
643
702
// Add the anchor leg
@@ -697,23 +756,32 @@ protected static BufferObject assembleElements(int intervals) {
697
756
protected void addVertex (RenderContext rc , double latitude , double longitude , double altitude , int offset , boolean isExtrudedSkirt ) {
698
757
int offsetVertexIndex = this .vertexIndex + offset ;
699
758
759
+ Vec3 point = rc .geographicToCartesian (latitude , longitude , altitude , this .altitudeMode , scratchPoint );
760
+ Vec3 texCoord2d = this .texCoord2d .set (point ).multiplyByMatrix (this .modelToTexCoord );
761
+
762
+ if (this .vertexIndex == 0 ) {
763
+ this .texCoord1d = 0 ;
764
+ this .prevPoint .set (point );
765
+ } else {
766
+ this .texCoord1d += point .distanceTo (this .prevPoint );
767
+ this .prevPoint .set (point );
768
+ }
769
+
700
770
if (this .isSurfaceShape ) {
701
771
this .vertexArray [this .vertexIndex ++] = (float ) (longitude - this .vertexOrigin .x );
702
772
this .vertexArray [this .vertexIndex ++] = (float ) (latitude - this .vertexOrigin .y );
703
773
this .vertexArray [this .vertexIndex ++] = (float ) (altitude - this .vertexOrigin .z );
704
774
// reserved for future texture coordinate use
705
- this .vertexArray [this .vertexIndex ++] = 0 ;
706
- this .vertexArray [this .vertexIndex ++] = 0 ;
707
- this .vertexArray [this .vertexIndex ++] = 0 ;
775
+ this .vertexArray [this .vertexIndex ++] = ( float ) texCoord2d . x ;
776
+ this .vertexArray [this .vertexIndex ++] = ( float ) texCoord2d . y ;
777
+ this .vertexArray [this .vertexIndex ++] = ( float ) this . texCoord1d ;
708
778
} else {
709
- Vec3 point = rc .geographicToCartesian (latitude , longitude , altitude , this .altitudeMode , scratchPoint );
710
779
this .vertexArray [this .vertexIndex ++] = (float ) (point .x - this .vertexOrigin .x );
711
780
this .vertexArray [this .vertexIndex ++] = (float ) (point .y - this .vertexOrigin .y );
712
781
this .vertexArray [this .vertexIndex ++] = (float ) (point .z - this .vertexOrigin .z );
713
- // reserved for future texture coordinate use
714
- this .vertexArray [this .vertexIndex ++] = 0 ;
715
- this .vertexArray [this .vertexIndex ++] = 0 ;
716
- this .vertexArray [this .vertexIndex ++] = 0 ;
782
+ this .vertexArray [this .vertexIndex ++] = (float ) texCoord2d .x ;
783
+ this .vertexArray [this .vertexIndex ++] = (float ) texCoord2d .y ;
784
+ this .vertexArray [this .vertexIndex ++] = (float ) this .texCoord1d ;
717
785
718
786
if (isExtrudedSkirt ) {
719
787
point = rc .geographicToCartesian (latitude , longitude , 0 , WorldWind .CLAMP_TO_GROUND , scratchPoint );
@@ -727,6 +795,12 @@ protected void addVertex(RenderContext rc, double latitude, double longitude, do
727
795
}
728
796
}
729
797
798
+ protected void determineModelToTexCoord (RenderContext rc ) {
799
+ Vec3 point = rc .geographicToCartesian (this .center .latitude , this .center .longitude , this .center .altitude , this .altitudeMode , scratchPoint );
800
+ this .modelToTexCoord = rc .globe .cartesianToLocalTransform (point .x , point .y , point .z , this .modelToTexCoord );
801
+ this .modelToTexCoord .invertOrthonormal ();
802
+ }
803
+
730
804
/**
731
805
* Calculate the number of times to split the edges of the shape for geometry assembly.
732
806
*
0 commit comments