Skip to content

Commit 36cef78

Browse files
committed
explored different navigation controls and played with on the ground examples
1 parent 62c4e19 commit 36cef78

File tree

7 files changed

+72
-29
lines changed

7 files changed

+72
-29
lines changed

README.md

+13-2
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,30 @@ Here is an example of the Grand Canyon.
3838
| latitude | latitude | 37.7983222 |
3939
| longitude | longitude | -122.3972797 |
4040
| elevation | for lod | 600 |
41+
| lod | optional | |
4142
| radius | planet size | 6372798 |
4243
| world_radius | planet size | 6372798 |
4344
| observer | who to watch | #camera |
4445
| stretch | height scale | 1 |
4546
| groundTexture | texture fx | |
4647
| buildingTexture | texture fx | |
4748

48-
A-Terrain is the main AFrame component that you interact with. It is a wrapper to manage a bunch of individual A-Tile, A-Building and A-Location objects. You give it a longitude, latitude and elevation and it will make sure that that piece of the planet is rendered.
49+
A-Terrain is the main AFrame component that you interact with in this package. You give it a longitude, latitude and elevation and it will make sure that that piece of the planet is rendered.
50+
51+
You may optionally specify a lod (level of detail or zoom level) which forces a specific resolution of tiles (to understand LOD see https://wiki.openstreetmap.org/wiki/Zoom_levels ). It will produce erratic behavior so it's best to think through what's going on here when you use it. It's worth noting as well that I've slightly modified the orbit controller that you may be used to so that it "slows down" as you get closer to the surface of the planet because otherwise you'd zoom from space to face too fast.
52+
53+
Depending on if you set an observer or not you will get different outcomes:
4954

50-
There are two slight variations in the way it will render the planet.
5155
1) If you specify an observer (which is a DOM node id such as "#camera") then A-Terrain will paint tiles to cover the visible portion of the globe at the given elevation. For example if you used an elevation like 600 (meters above sea level) and you were over the default latitude and longitude (San Francisco) then it would paint a few tiles around downtown San Francisco at almost street level.
56+
5257
2) If you do not specify an observer then it will move and orient the entire globe so that you're standing on the ground at that point on the globe. By this I mean it moves and rotates the surface of the globe to intersect (0,0,0). This is intended to reduce the hassle of having to deal with spherical coordinates.
5358

59+
The 'stretch' argument stretches the planet so that you can see height related details better (such as mountains).
60+
61+
The radius is your model radius. The world_radius is the radius of your planet.
62+
63+
The groundTexture and buildingTexture are art-effects that you can use to thematically make buildings and ground match your application.
64+
5465
### A-Tile API
5566

5667
| Property | Description | Default Value |

dist/aframe-aterrain-component.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/aframe-aterrain-component.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/helloworld/tile.html

+10-6
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@
1212

1313
<a-scene cursor="rayOrigin: mouse">
1414

15-
<a-box id="target" width="10" height="10" depth="100"></a-box>
15+
<a-entity id="target" ></a-box>
16+
17+
<!-- just print a single tile, and knowing the elevation (which in this part of SF is about 29 meters below world ellipsoid - place it at the origin facing up by hand -->
18+
<a-entity a-tile="buildingTexture:../env/glacier4.png" position="-250 29 240" rotation="-90 0 0"></a-entity>
1619

17-
<!-- in this example a default tile is simply rendered - at the origin - at real world scale -->
18-
<a-entity a-tile></a-entity>
1920

2021
<a-entity id="cameraRig">
2122
<a-entity
2223
id="camera"
23-
camera="far:1000"
24-
position="0 0 700"
25-
orbit-controls="
24+
position="0 10 0"
25+
wasd-controls="fly:true"
26+
look-controls
27+
unused_orbit-controls="
2628
autoRotate: false;
2729
target: #target;
2830
enableDamping: true;
@@ -41,6 +43,8 @@
4143

4244
<a-entity light="type: directional; color: #EED; intensity: 3" position="1 1 1"></a-entity>
4345

46+
<a-entity environment="preset: forest; ground:none; playArea:10;"></a-entity>
47+
4448
</a-scene>
4549

4650

examples/sanfrancisco/index.html

+3-5
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,18 @@
1313

1414
<a-entity id="target"></a-entity>
1515

16-
<!-- render the world, focused over this area, with the origin forced to be at 0,0,0 - at 1:1 meter scale... -->
17-
<!-- renders "from" a height of 400 meters which matches a level of detail of 15 - which is where buildings pop in -->
18-
1916
<a-entity a-terrain="fovpad:1;
2017
latitude:37.7983222;
2118
longitude:-122.3972797;
22-
elevation:400;
19+
elevation:1;
20+
lod:15;
2321
">
2422
</a-entity>
2523

2624
<!-- actually the coast near here is 20+ meters or so under ellipsoid sea level according to the data sources -->
2725

2826
<a-entity id="cameraRig" position="0 0 0" >
29-
<a-entity id="camera" camera="near:1;far:100000" wasd-controls look-controls orbit-controls></a-entity>
27+
<a-entity id="camera" camera="near:1;far:100000" wasd-controls="fly:true" look-controls></a-entity>
3028
<a-entity id="lefthand" camera-transform-controls-hand="hand:left" vive-controls="hand: left" oculus-touch-controls="hand: left" windows-motion-controls="hand: left"></a-entity>
3129
<a-entity id="righthand" camera-transform-controls-hand="hand:right" vive-controls="hand: right" oculus-touch-controls="hand: right" windows-motion-controls="hand: right"></a-entity>
3230
</a-entity>

src/TileServer.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ class TileServer {
347347
let material = 0;
348348

349349
if(data.groundTexture && data.groundTexture.length) {
350-
let texture = new THREE.TextureLoader().load('../env/'+data.groundTexture);
350+
let texture = new THREE.TextureLoader().load(data.groundTexture);
351351
material = new THREE.MeshBasicMaterial({map:texture,color:0xffffff});
352352
}
353353

src/a-terrain.js

+42-12
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ AFRAME.registerComponent('a-terrain', {
4141
// How much to stretch planet heights by so that mountains are more visible
4242
// TODO not fully implemented
4343
stretch: {type: 'number', default: 1 },
44-
// LOD = Level of detail. This is for internal use only and is manufactured from the elevation. 15 = the first level where 3d building geometry is allowed to be seen.
45-
lod: {type: 'number', default: 15 },
44+
// LOD = Level of detail. If not specified then it will be computed from elevation.
45+
lod: {type: 'number', default: -1 },
46+
input: {type: 'number', default: 0 },
4647
// fovpad is a hack to circumvent limits with observer field of view; basically a camera could be near the planet but see the whole planet at once
4748
// TODO the tilings strategy should be improved to deal with some of the possible cases of observer field of view - remove this fudge factor later
4849
fovpad: {type: 'number', default: 0 },
@@ -65,6 +66,30 @@ AFRAME.registerComponent('a-terrain', {
6566
// Latch for startup - TODO probably a more elegant way to latch tick() after init callback is done
6667
refreshState: 0,
6768

69+
/*
70+
inputControls: function() {
71+
if(!this.data.input)
72+
return;
73+
74+
// this is an optional control to move the planet under the observer - constantly generating new tiles
75+
76+
document.addEventListener('keydown', (event) => {
77+
switch(event.keyCode) {
78+
case 81: this.data.elevation = this.data.elevation * 1.5; break;
79+
case 69: this.data.elevation = this.data.elevation / 1.5; break;
80+
case 38: case 87: this.data.latitude += this.data.elevation / 10000; break;
81+
case 40: case 83: this.data.latitude -= this.data.elevation / 10000; break;
82+
case 39: case 68: this.data.longitude += this.data.elevation / 10000; break;
83+
case 37: case 65: this.data.longitude -= this.data.elevation / 10000; break;
84+
}
85+
});
86+
},
87+
88+
init: function() {
89+
this.inputControls();
90+
},
91+
*/
92+
6893
///
6994
/// tick at 60fps
7095
///
@@ -80,8 +105,6 @@ AFRAME.registerComponent('a-terrain', {
80105
///
81106
updateView: function() {
82107

83-
try {
84-
85108
let data = this.data;
86109

87110
let observer = (data.observer && data.observer.length) > 0 ? this.el.sceneEl.querySelector("#"+data.observer) : 0;
@@ -122,12 +145,15 @@ try {
122145

123146
// What is a pleasant level of detail for a given distance from the planets center in planetary coordinates?
124147
// TODO it is arguable that this could be specified separately from elevation rather than being inferred
125-
data.lod = TileServer.instance().elevation2lod(data.world_radius,data.elevation);
148+
if(!data.lod < 0 || data.lodLatch == 1) {
149+
data.lodLatch = 1;
150+
data.lod = TileServer.instance().elevation2lod(data.world_radius,data.elevation);
151+
}
126152
}
127153

128154
else {
129155

130-
// test- specify lat lon
156+
// this is a slight hack to allow a caller to specify lat lon - it's not formally documented as a feature
131157

132158
var hash = window.location.hash.substring(1);
133159
var params = {}
@@ -136,6 +162,9 @@ try {
136162
if(params.elev) {
137163
data.elevation = parseFloat(params.elev);
138164
}
165+
if(params.lod) {
166+
data.lod = parseInt(params.lod);
167+
}
139168

140169
// Focus on user supplied latitude longitude and elevation
141170

@@ -166,13 +195,16 @@ try {
166195

167196
// What is a pleasant level of detail for a given distance from the planets center in planetary coordinates?
168197
// TODO it is arguable that this could be specified separately from elevation rather than being inferred
169-
data.lod = TileServer.instance().elevation2lod(data.world_radius,data.elevation);
198+
if(!data.lod < 0 || data.lodLatch == 1) {
199+
data.lodLatch = 1;
200+
data.lod = TileServer.instance().elevation2lod(data.world_radius,data.elevation);
201+
}
170202

171203
TileServer.instance().getGround(data.latitude,data.longitude,data.lod,data.url, groundValue => {
172204
// deal with undefined
173-
if(!groundValue) groundValue = data.elevation;
205+
if(!groundValue) groundValue = 0;
174206
// make sure is above ground
175-
let e = data.elevation > groundValue ? data.elevation : groundValue;
207+
let e = groundValue + data.elevation;
176208
// convert elevation above sea level to to model scale
177209
let height = data.radius * e * data.stretch / data.world_radius + data.radius;
178210
console.log("Dynamically moving planet to adjust for ground=" + groundValue + " height="+height + " stretch="+data.stretch + " elev="+e);
@@ -221,9 +253,7 @@ try {
221253
this.updateOrCreateTile(scratch);
222254
}
223255
}
224-
} catch(e) {
225-
console.error(e);
226-
}
256+
227257
},
228258

229259
///

0 commit comments

Comments
 (0)