├── README.md
├── TODO.md
├── examples
├── basic.html
├── sun-light-estimation
│ ├── README.md
│ ├── google-map-geocoder.html
│ ├── sun-position.html
│ └── vendor
│ │ └── suncalc.js
└── vendor
│ └── ar.js
│ ├── aframe
│ └── build
│ │ └── aframe-ar.js
│ └── data
│ └── data
│ └── camera_para.dat
├── src
├── gps-camera-debug.js
├── gps-camera-position.js
├── gps-camera-rotation.js
└── gps-entity-place.js
└── tmp
├── obsolete-gps-ar.js
├── original-old-buggy.html
└── phills-sphere.html
/README.md:
--------------------------------------------------------------------------------
1 | # Experimentation with GPS for AR
2 |
3 | This is an experimentation of using phone gps + gyroscope to display Augmented reality.
4 |
5 | Note: GPS accuracy is significantly less than normal AR tracking. So be sure
6 | it matches your use-case.
7 |
8 | Note2: this is very experimental and not finished.
9 |
10 | # Credit
11 | It is based on the discussion from this [github issue](https://github.com/jeromeetienne/AR.js/issues/190).
12 | It has been originated by [1d10t](https://github.com/1d10t) in this [file](https://1d10t.github.io/test/phills-sphere.html).
13 | Thanks a LOT for your contribution!
14 |
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 | - gps-place: only one parameters. location
2 | - a lot of components options are uselessly complex
3 |
4 | - camera initialisation isnt compatible with marker projection matrix
5 | - see how to make it so
6 |
7 | - make a good example
8 | - how to handle the specific of the user latitude/longitude
9 |
10 |
11 | - display stuff independantly of the Z
12 | - thus the tracking seems less bad
13 |
14 | - make components name more uniforms - more ar.js like
15 | - gps-place - for an object in real world
16 | - gps-debug - for camera - to display debug
17 | - compass-rotation - for camera - to set the compass of the camera
18 | - gps-position - for camera - to set the position from the gps
19 | - put arjs-gps-* instead of gps-
20 | - new name => arjs-gps-location and arjs-gps-camera
21 |
22 | - improve object location to be searched by google maps or similar
23 | - thus no need to push unreadable coordinates
24 |
25 |
26 | - DONE put the aframe components in their own file
27 | - DONE make a debug layer
28 | - component gps-debug on camera
29 |
30 |
31 | # Possible Demo
32 | - put several spot in the real world
33 | - well known cities
34 | - search local interest: e.g. closest restaurants, museums
35 | - display them with a a-text
36 | - name of the place + distance from the camera
37 | - display them independantly from the distance to the camera
38 |
--------------------------------------------------------------------------------
/examples/basic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
12 |
13 | current lng/lat coords: ,
14 |
15 |
16 | origin lng/lat coords: ,
17 |
18 |
19 | camera 3d position:
,
20 |
21 | compass heading: ,
22 | camera angle: ,
23 | yaw angle:
24 |
25 |
26 | `
27 | document.body.appendChild(domElement.children[0])
28 |
29 | // TODO cleanup this code
30 | // TODO build the html element in there
31 |
32 | camera.addEventListener('componentchanged', function (event) {
33 | switch(event.detail.name){
34 | case 'rotation':
35 | //console.log('camera rotation changed', event.detail.newData);
36 | var compassRotation = camera.components['gps-camera-rotation']
37 | var lookControls = camera.components['look-controls']
38 |
39 | camera_angle.innerText = event.detail.newData.y.toFixed(2)
40 |
41 | if( lookControls ){
42 | yaw_angle.innerText = THREE.Math.radToDeg(lookControls.yawObject.rotation.y).toFixed(2)
43 | }
44 | if( compassRotation && compassRotation.heading !== null ){
45 | compass_heading.innerText = compassRotation.heading.toFixed(2)
46 | }
47 | break
48 | case 'position':
49 | //console.log('camera position changed', event.detail.newData)
50 | camera_p_x.innerText = event.detail.newData.x
51 | camera_p_z.innerText = event.detail.newData.z
52 |
53 | var gpsPosition = camera.components['gps-camera-position']
54 | if( gpsPosition ){
55 | if(gpsPosition.currentCoords){
56 | current_coords_longitude.innerText = gpsPosition.currentCoords.longitude
57 | current_coords_latitude.innerText = gpsPosition.currentCoords.latitude
58 | }
59 | if(gpsPosition.originCoords){
60 | origin_coords_longitude.innerText = gpsPosition.originCoords.longitude
61 | origin_coords_latitude.innerText = gpsPosition.originCoords.latitude
62 | }
63 | }
64 |
65 | break
66 | }
67 | })
68 |
69 | }
70 | })
71 |
--------------------------------------------------------------------------------
/src/gps-camera-position.js:
--------------------------------------------------------------------------------
1 | AFRAME.registerComponent('gps-camera-position', {
2 |
3 | _watchPositionId: null,
4 |
5 | originCoords: null,
6 | currentCoords: null,
7 |
8 | schema: {
9 | minAccuracy: {
10 | type: 'int',
11 | default: 100
12 | },
13 | },
14 |
15 | init: function () {
16 |
17 | this._watchPositionId = this._initWatchGPS(function(position){
18 | // https://developer.mozilla.org/en-US/docs/Web/API/Coordinates
19 | this.currentCoords = position.coords
20 | this._updatePosition()
21 | }.bind(this))
22 |
23 | },
24 | remove: function() {
25 | if(this._watchPositionId) navigator.geolocation.clearWatch(this._watchPositionId)
26 | this._watchPositionId = null
27 | },
28 |
29 | _initWatchGPS: function( onSuccess, onError ){
30 | // TODO put that in .init directly
31 |
32 | if( onError === undefined ){
33 | onError = function(err) { console.warn('ERROR('+err.code+'): '+err.message) }
34 | }
35 |
36 | if( "geolocation" in navigator === false ){
37 | onError({code: 0, message: 'Geolocation is not supported by your browser'})
38 | return
39 | }
40 |
41 | // https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition
42 | return navigator.geolocation.watchPosition(onSuccess, onError, {
43 | enableHighAccuracy: true,
44 | maximumAge: 0,
45 | timeout: 27000
46 | })
47 | },
48 |
49 | _updatePosition: function () {
50 | // dont update if accuracy isnt good enough
51 | if( this.currentCoords.accuracy > this.data.minAccuracy ) return
52 |
53 | // init originCoords if needed
54 | if( this.originCoords === null ) this.originCoords = this.currentCoords
55 |
56 | var position = this.el.getAttribute('position')
57 |
58 | // compute position.x
59 | var dstCoords = {
60 | longitude: this.currentCoords.longitude,
61 | latitude: this.originCoords.latitude
62 | }
63 | position.x = this.computeDistanceMeters(this.originCoords, dstCoords)
64 | position.x *= this.currentCoords.longitude > this.originCoords.longitude ? 1 : -1
65 |
66 | // compute position.z
67 | var dstCoords = {
68 | longitude: this.originCoords.longitude,
69 | latitude: this.currentCoords.latitude
70 | }
71 | position.z = this.computeDistanceMeters(this.originCoords, dstCoords)
72 | position.z *= this.currentCoords.latitude > this.originCoords.latitude ? -1 : 1
73 |
74 | // update element position
75 | this.el.setAttribute('position', position)
76 | },
77 |
78 | computeDistanceMeters: function(src, dest) {
79 | // 'Calculate distance, bearing and more between Latitude/Longitude points'
80 | // https://www.movable-type.co.uk/scripts/latlong.html
81 | var dlon = THREE.Math.degToRad(dest.longitude - src.longitude)
82 | var dlat = THREE.Math.degToRad(dest.latitude - src.latitude)
83 |
84 | var a = (Math.sin(dlat / 2) * Math.sin(dlat / 2)) + Math.cos(THREE.Math.degToRad(src.latitude)) * Math.cos(THREE.Math.degToRad(dest.latitude)) * (Math.sin(dlon / 2) * Math.sin(dlon / 2))
85 | var angle = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
86 |
87 | return angle * 6378160
88 | },
89 |
90 |
91 | })
92 |
--------------------------------------------------------------------------------
/src/gps-camera-rotation.js:
--------------------------------------------------------------------------------
1 | AFRAME.registerComponent('gps-camera-rotation', {
2 |
3 | lookControls: null,
4 | heading: null,
5 |
6 |
7 | schema: {
8 | },
9 |
10 | init: function () {
11 |
12 | if( this.el.components['look-controls'] === undefined ) return
13 |
14 | this.lookControls = this.el.components['look-controls']
15 |
16 | // listen to deviceorientation event
17 | var eventName = this._getDeviceOrientationEventName()
18 | this._$onDeviceOrientation = this._onDeviceOrientation.bind(this)
19 | window.addEventListener( eventName, this._$onDeviceOrientation, false)
20 |
21 | window.addEventListener('compassneedscalibration', function(event) {
22 | alert('Your compass needs calibrating! Wave your device in a figure-eight motion')
23 | event.preventDefault()
24 | }, true)
25 |
26 | },
27 |
28 | tick: function( time, timeDelta ){
29 |
30 | if( this.heading === null ) return
31 |
32 | this._updateRotation()
33 |
34 | },
35 |
36 | remove: function () {
37 | var eventName = this._getDeviceOrientationEventName()
38 | window.removeEventListener(eventName, this._$onDeviceOrientation, false)
39 | },
40 |
41 | _getDeviceOrientationEventName: function(){
42 | if('ondeviceorientationabsolute' in window){
43 | var eventName = 'deviceorientationabsolute'
44 | }else if('ondeviceorientation' in window){
45 | var eventName = 'deviceorientation'
46 | }else{
47 | var eventName = ''
48 | console.error('Compass not supported')
49 | }
50 | return eventName
51 | },
52 |
53 | _computeCompassHeading: function (alpha, beta, gamma) {
54 |
55 | // Convert degrees to radians
56 | var alphaRad = alpha * (Math.PI / 180)
57 | var betaRad = beta * (Math.PI / 180)
58 | var gammaRad = gamma * (Math.PI / 180)
59 |
60 | // Calculate equation components
61 | var cA = Math.cos(alphaRad)
62 | var sA = Math.sin(alphaRad)
63 | var cB = Math.cos(betaRad)
64 | var sB = Math.sin(betaRad)
65 | var cG = Math.cos(gammaRad)
66 | var sG = Math.sin(gammaRad)
67 |
68 | // Calculate A, B, C rotation components
69 | var rA = - cA * sG - sA * sB * cG
70 | var rB = - sA * sG + cA * sB * cG
71 | var rC = - cB * cG
72 |
73 | // Calculate compass heading
74 | var compassHeading = Math.atan(rA / rB)
75 |
76 | // Convert from half unit circle to whole unit circle
77 | if(rB < 0) {
78 | compassHeading += Math.PI
79 | }else if(rA < 0) {
80 | compassHeading += 2 * Math.PI
81 | }
82 |
83 | // Convert radians to degrees
84 | compassHeading *= 180 / Math.PI
85 |
86 | return compassHeading
87 | },
88 |
89 | _onDeviceOrientation: function( event ){
90 |
91 | // compute heading
92 | if( event.webkitCompassHeading !== undefined ){
93 | if(event.webkitCompassAccuracy < 50){
94 | this.heading = event.webkitCompassHeading
95 | }else{
96 | console.warn('webkitCompassAccuracy is event.webkitCompassAccuracy')
97 | }
98 | }else if( event.alpha !== null ){
99 | if(event.absolute === true || event.absolute === undefined ) {
100 | this.heading = this._computeCompassHeading(event.alpha, event.beta, event.gamma)
101 | }else{
102 | console.warn('event.absolute === false')
103 | }
104 | }else{
105 | console.warn('event.alpha === null')
106 | }
107 | },
108 |
109 | _updateRotation: function() {
110 |
111 | var heading = 360 - this.heading
112 | var cameraRotation = this.el.getAttribute('rotation').y
113 | var yawRotation = THREE.Math.radToDeg(this.lookControls.yawObject.rotation.y)
114 |
115 | var offset = ( heading - ( cameraRotation - yawRotation ) ) % 360
116 |
117 | this.lookControls.yawObject.rotation.y = THREE.Math.degToRad(offset)
118 |
119 | },
120 |
121 | })
122 |
--------------------------------------------------------------------------------
/src/gps-entity-place.js:
--------------------------------------------------------------------------------
1 | AFRAME.registerComponent('gps-entity-place', {
2 |
3 | _cameraGpsPosition: null,
4 | _deferredInitInterval: 0,
5 |
6 | schema: {
7 | latitude: {
8 | type: 'number',
9 | default: 0
10 | },
11 | longitude: {
12 | type: 'number',
13 | default: 0
14 | },
15 | },
16 |
17 | init: function () {
18 | // TODO use a ._initialized = true instead
19 | if( this._deferredInit() ) return
20 |
21 | this._deferredInitInterval = setInterval(this._deferredInit.bind(this), 100)
22 | },
23 |
24 | _deferredInit: function () {
25 |
26 | if( this._cameraGpsPosition === null ){
27 | var camera = document.querySelector('a-camera, [camera]')
28 | if( camera.components['gps-camera-position'] === undefined) return
29 | this._cameraGpsPosition = camera.components['gps-camera-position']
30 | }
31 |
32 | console.log(this._cameraGpsPosition.originCoords)
33 | if( this._cameraGpsPosition.originCoords === null ) return
34 |
35 | clearInterval(this._deferredInitInterval)
36 | this._deferredInitInterval = 0
37 |
38 | this._updatePosition()
39 |
40 |
41 | return true
42 | },
43 |
44 | _updatePosition: function() {
45 |
46 | var position = {x: 0, y: 0, z: 0}
47 |
48 | // update position.x
49 | var dstCoords = {
50 | longitude: this.data.longitude,
51 | latitude: this._cameraGpsPosition.originCoords.latitude
52 | }
53 | position.x = this._cameraGpsPosition.computeDistanceMeters( this._cameraGpsPosition.originCoords, dstCoords )
54 | position.x *= this.data.longitude > this._cameraGpsPosition.originCoords.longitude ? 1 : -1
55 |
56 | // update position.z
57 | var dstCoords = {
58 | longitude: this._cameraGpsPosition.originCoords.longitude,
59 | latitude: this.data.latitude
60 | }
61 | position.z = this._cameraGpsPosition.computeDistanceMeters(this._cameraGpsPosition.originCoords, dstCoords)
62 | position.z *= this.data.latitude > this._cameraGpsPosition.originCoords.latitude ? -1 : 1
63 |
64 | // update element's position in 3d world
65 | this.el.setAttribute('position', position)
66 | }
67 | })
68 |
--------------------------------------------------------------------------------
/tmp/obsolete-gps-ar.js:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | // component gps-position
3 | //////////////////////////////////////////////////////////////////////////////
4 |
5 | AFRAME.registerComponent('gps-position', {
6 |
7 | _watchPositionId: null,
8 |
9 | originCoords: null,
10 | currentCoords: null,
11 |
12 | schema: {
13 | accuracy: {
14 | type: 'int',
15 | default: 100
16 | },
17 | 'origin-coords-latitude': {
18 | type: 'number',
19 | default: NaN
20 | },
21 | 'origin-coords-longitude': {
22 | type: 'number',
23 | default: NaN
24 | }
25 | },
26 |
27 | init: function () {
28 |
29 | if( !isNaN(this.data['origin-coords-latitude']) && !isNaN(this.data['origin-coords-longitude']) ){
30 | this.originCoords = {latitude: this.data['origin-coords-latitude'], longitude: this.data['origin-coords-longitude']}
31 | }
32 |
33 | this._watchPositionId = this._initWatchGPS(function(position){
34 | // https://developer.mozilla.org/en-US/docs/Web/API/Coordinates
35 | this.currentCoords = position.coords
36 | this._updatePosition()
37 | }.bind(this))
38 |
39 | },
40 | remove: function() {
41 | if(this._watchPositionId) navigator.geolocation.clearWatch(this._watchPositionId)
42 | this._watchPositionId = null
43 | },
44 |
45 | _initWatchGPS: function( onSuccess, onError ){
46 | // TODO put that in .init directly
47 |
48 | if( onError === undefined ){
49 | onError = function(err) { console.warn('ERROR('+err.code+'): '+err.message) }
50 | }
51 |
52 | if( "geolocation" in navigator === false ){
53 | onError({code: 0, message: 'Geolocation is not supported by your browser'})
54 | return
55 | }
56 |
57 | // https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/watchPosition
58 | return navigator.geolocation.watchPosition(onSuccess, onError, {
59 | enableHighAccuracy: true,
60 | maximumAge: 0,
61 | timeout: 27000
62 | })
63 | },
64 |
65 | _updatePosition: function () {
66 | // dont update if accuracy isnt good enough
67 | if( this.currentCoords.accuracy > this.data.accuracy ) return
68 |
69 | // init originCoords if needed
70 | if( this.originCoords === null ) this.originCoords = this.currentCoords
71 |
72 | var position = this.el.getAttribute('position')
73 |
74 | // compute position.x
75 | var dstCoords = {
76 | longitude: this.currentCoords.longitude,
77 | latitude: this.originCoords.latitude
78 | }
79 | position.x = this.computeDistanceMeters(this.originCoords, dstCoords)
80 | position.x *= this.currentCoords.longitude > this.originCoords.longitude ? 1 : -1
81 |
82 | // compute position.z
83 | var dstCoords = {
84 | longitude: this.originCoords.longitude,
85 | latitude: this.currentCoords.latitude
86 | }
87 | position.z = this.computeDistanceMeters(this.originCoords, dstCoords)
88 | position.z *= this.currentCoords.latitude > this.originCoords.latitude ? -1 : 1
89 |
90 | // update element position
91 | this.el.setAttribute('position', position)
92 | },
93 |
94 | computeDistanceMeters: function(src, dest) {
95 | // 'Calculate distance, bearing and more between Latitude/Longitude points'
96 | // https://www.movable-type.co.uk/scripts/latlong.html
97 | var dlon = THREE.Math.degToRad(dest.longitude - src.longitude)
98 | var dlat = THREE.Math.degToRad(dest.latitude - src.latitude)
99 |
100 | var a = (Math.sin(dlat / 2) * Math.sin(dlat / 2)) + Math.cos(THREE.Math.degToRad(src.latitude)) * Math.cos(THREE.Math.degToRad(dest.latitude)) * (Math.sin(dlon / 2) * Math.sin(dlon / 2))
101 | var angle = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
102 |
103 | return angle * 6378160
104 | },
105 |
106 |
107 | })
108 |
109 |
110 | //////////////////////////////////////////////////////////////////////////////
111 | // component compass-rotation
112 | //////////////////////////////////////////////////////////////////////////////
113 |
114 | AFRAME.registerComponent('compass-rotation', {
115 |
116 | lookControls: null,
117 | lastTimestamp: 0,
118 | heading: null,
119 |
120 |
121 | schema: {
122 | fixTime: {
123 | type: 'int',
124 | default: 2000
125 | },
126 | orientationEvent: {
127 | type: 'string',
128 | default: 'auto'
129 | }
130 | },
131 |
132 | init: function () {
133 |
134 | if( this.el.components['look-controls'] === undefined ) return
135 |
136 | this.lookControls = this.el.components['look-controls']
137 |
138 | this.handlerOrientation = this.handlerOrientation.bind(this)
139 |
140 | if( this.data.orientationEvent === 'auto' ){
141 | if('ondeviceorientationabsolute' in window){
142 | this.data.orientationEvent = 'deviceorientationabsolute'
143 | }else if('ondeviceorientation' in window){
144 | this.data.orientationEvent = 'deviceorientation'
145 | }else{
146 | this.data.orientationEvent = ''
147 | alert('Compass not supported')
148 | return
149 | }
150 | }
151 |
152 | window.addEventListener( this.data.orientationEvent, this.handlerOrientation, false)
153 |
154 | window.addEventListener('compassneedscalibration', function(event) {
155 | alert('Your compass needs calibrating! Wave your device in a figure-eight motion')
156 | event.preventDefault()
157 | }, true)
158 |
159 | },
160 |
161 | tick: function( time, timeDelta ){
162 |
163 | if(this.heading === null || this.lastTimestamp > (time - this.data.fixTime)) return
164 |
165 | this.lastTimestamp = time
166 | this._updateRotation()
167 |
168 | },
169 |
170 | _computeCompassHeading: function (alpha, beta, gamma) {
171 |
172 | // Convert degrees to radians
173 | var alphaRad = alpha * (Math.PI / 180)
174 | var betaRad = beta * (Math.PI / 180)
175 | var gammaRad = gamma * (Math.PI / 180)
176 |
177 | // Calculate equation components
178 | var cA = Math.cos(alphaRad)
179 | var sA = Math.sin(alphaRad)
180 | var cB = Math.cos(betaRad)
181 | var sB = Math.sin(betaRad)
182 | var cG = Math.cos(gammaRad)
183 | var sG = Math.sin(gammaRad)
184 |
185 | // Calculate A, B, C rotation components
186 | var rA = - cA * sG - sA * sB * cG
187 | var rB = - sA * sG + cA * sB * cG
188 | var rC = - cB * cG
189 |
190 | // Calculate compass heading
191 | var compassHeading = Math.atan(rA / rB)
192 |
193 | // Convert from half unit circle to whole unit circle
194 | if(rB < 0) {
195 | compassHeading += Math.PI
196 | }else if(rA < 0) {
197 | compassHeading += 2 * Math.PI
198 | }
199 |
200 | // Convert radians to degrees
201 | compassHeading *= 180 / Math.PI
202 |
203 | return compassHeading
204 | },
205 |
206 | handlerOrientation: function( event ){
207 |
208 | var heading = null
209 |
210 | //console.log('device orientation event', event)
211 |
212 | if( event.webkitCompassHeading !== undefined ){
213 |
214 | if(event.webkitCompassAccuracy < 50){
215 | heading = event.webkitCompassHeading
216 | }else{
217 | console.warn('webkitCompassAccuracy is event.webkitCompassAccuracy')
218 | }
219 |
220 | }else if( event.alpha !== null ){
221 | if(event.absolute === true || event.absolute === undefined ) {
222 | heading = this._computeCompassHeading(event.alpha, event.beta, event.gamma)
223 | }else{
224 | console.warn('event.absolute === false')
225 | }
226 | }else{
227 | console.warn('event.alpha === null')
228 | }
229 |
230 | this.heading = heading
231 | },
232 |
233 | _updateRotation: function() {
234 |
235 | /*
236 | camera.components["look-controls"].yawObject.rotation.y = THREE.Math.degToRad(
237 | (
238 | 360
239 | - camera.components["compass-rotation"].heading
240 | - (
241 | camera.getAttribute('rotation').y
242 | - THREE.Math.radToDeg(camera.components["look-controls"].yawObject.rotation.y)
243 | )
244 | )
245 | % 360
246 | )
247 | */
248 |
249 |
250 | var heading = 360 - this.heading
251 | var camera_rotation = this.el.getAttribute('rotation').y
252 | var yaw_rotation = THREE.Math.radToDeg(this.lookControls.yawObject.rotation.y)
253 |
254 | var offset = ( heading - ( camera_rotation - yaw_rotation ) ) % 360
255 |
256 | this.lookControls.yawObject.rotation.y = THREE.Math.degToRad(offset)
257 |
258 | },
259 |
260 | remove: function () {
261 | if(this.data.orientationEvent){
262 | window.removeEventListener(this.data.orientationEvent, this.handlerOrientation, false)
263 | }
264 | }
265 |
266 | })
267 |
268 |
269 | //////////////////////////////////////////////////////////////////////////////
270 | // Component gps-debug
271 | //////////////////////////////////////////////////////////////////////////////
272 |
273 | AFRAME.registerComponent('gps-debug', {
274 | init : function(){
275 | var camera = this.el;
276 |
277 | //////////////////////////////////////////////////////////////////////////////
278 | // Create html
279 | //////////////////////////////////////////////////////////////////////////////
280 | var domElement = document.createElement('div')
281 | domElement.innerHTML = `
282 |
283 |
284 |
285 | current coords: ,
286 | (origin coords: , )
287 |
288 |
289 | camera coords: ,
290 |
291 |
292 | compass heading: ,
293 | camera angle: ,
294 | yaw angle:
295 |
296 |
297 | `
298 | document.body.appendChild(domElement.children[0])
299 |
300 | // TODO cleanup this code
301 | // TODO build the html element in there
302 |
303 | camera.addEventListener('componentchanged', function (event) {
304 | switch(event.detail.name){
305 | case 'rotation':
306 | //console.log('camera rotation changed', event.detail.newData);
307 | var compassRotation = camera.components['compass-rotation']
308 | var lookControls = camera.components['look-controls']
309 |
310 | camera_angle.innerText = event.detail.newData.y;
311 |
312 | if( lookControls ){
313 | yaw_angle.innerText = THREE.Math.radToDeg(lookControls.yawObject.rotation.y);
314 | }
315 | if( compassRotation ){
316 | compass_heading.innerText = compassRotation.heading;
317 | }
318 | break;
319 | case 'position':
320 | //console.log('camera position changed', event.detail.newData);
321 | camera_p_x.innerText = event.detail.newData.x;
322 | camera_p_z.innerText = event.detail.newData.z;
323 |
324 | var gpsPosition = camera.components['gps-position'];
325 | if( gpsPosition ){
326 | if(gpsPosition.currentCoords){
327 | current_coords_longitude.innerText = gpsPosition.currentCoords.longitude;
328 | current_coords_latitude.innerText = gpsPosition.currentCoords.latitude;
329 | }
330 | if(gpsPosition.originCoords){
331 | origin_coords_longitude.innerText = gpsPosition.originCoords.longitude;
332 | origin_coords_latitude.innerText = gpsPosition.originCoords.latitude;
333 | }
334 | }
335 |
336 | break;
337 | }
338 | });
339 |
340 | }
341 | })
342 |
343 |
344 | //////////////////////////////////////////////////////////////////////////////
345 | // Component gps-place
346 | //////////////////////////////////////////////////////////////////////////////
347 |
348 | AFRAME.registerComponent('gps-place', {
349 |
350 | _cameraGpsPosition: null,
351 | _deferredInitInterval: 0,
352 |
353 | schema: {
354 | latitude: {
355 | type: 'number',
356 | default: 0
357 | },
358 | longitude: {
359 | type: 'number',
360 | default: 0
361 | },
362 | cameraSelector: { // TODO do i need this ?
363 | type: 'string',
364 | default: 'a-camera, [camera]'
365 | }
366 | },
367 |
368 | init: function () {
369 | if( this._deferredInit() ) return
370 | this._deferredInitInterval = setInterval(this._deferredInit.bind(this), 100)
371 | },
372 |
373 | _deferredInit: function () {
374 |
375 | if( this._cameraGpsPosition === null ){
376 | var camera = document.querySelector(this.data.cameraSelector)
377 | if(typeof(camera.components['gps-position']) == 'undefined') return
378 | this._cameraGpsPosition = camera.components['gps-position']
379 | }
380 |
381 | if( this._cameraGpsPosition.originCoords === null ) return
382 |
383 | this._updatePosition()
384 |
385 | clearInterval(this._deferredInitInterval)
386 | this._deferredInitInterval = 0
387 |
388 | return true
389 | },
390 |
391 | _updatePosition: function() {
392 |
393 | var position = {x: 0, y: 0, z: 0}
394 |
395 | // update position.x
396 | var dstCoords = {
397 | longitude: this.data.longitude,
398 | latitude: this._cameraGpsPosition.originCoords.latitude
399 | }
400 | position.x = this._cameraGpsPosition.computeDistanceMeters( this._cameraGpsPosition.originCoords, dstCoords )
401 | position.x *= this.data.longitude > this._cameraGpsPosition.originCoords.longitude ? 1 : -1
402 |
403 | // update position.z
404 | var dstCoords = {
405 | longitude: this._cameraGpsPosition.originCoords.longitude,
406 | latitude: this.data.latitude
407 | }
408 | position.z = this._cameraGpsPosition.computeDistanceMeters(this._cameraGpsPosition.originCoords, dstCoords)
409 | position.z *= this.data.latitude > this._cameraGpsPosition.originCoords.latitude ? -1 : 1
410 |
411 | // update element's position
412 | this.el.setAttribute('position', position)
413 | }
414 | })
415 |
--------------------------------------------------------------------------------
/tmp/original-old-buggy.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
452 |
453 |
454 |
455 |
456 |
457 | coords: ,
458 | (zero coords: , )
459 |
460 |
461 | camera coords: ,
462 |
463 |
464 | compass heading: ,
465 | camera angle: ,
466 | yaw angle:
467 |
468 |
geohash_7chars:
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
495 |
496 |
497 |
498 |
499 |
500 |
--------------------------------------------------------------------------------
/tmp/phills-sphere.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
384 |
385 |
386 |
387 |
388 |
389 | coords: ,
390 | (zero coords: , )
391 |
392 |
393 | camera coords: ,
394 |
395 |
396 | compass heading: ,
397 | camera angle: ,
398 | yaw angle:
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
--------------------------------------------------------------------------------