MapsModelsImporter icon indicating copy to clipboard operation
MapsModelsImporter copied to clipboard

add: seoul map import capability

Open minostauros opened this issue 5 years ago • 12 comments

Importing from https://smap.seoul.go.kr/

#87

seoul map shares strategy 7 with Google Maps

Tested on Google Chrome 85.0.4183.121 (64bit), RendorDoc 1.9, RTX 3090

minostauros avatar Oct 01 '20 17:10 minostauros

Nice job! :) You're the first one to add a new map source ;) It must mean that despite all it starts to get readable. I'm having trouble with the global transform:

etire

It is not only the scale, there is some skewing in the matrices. I had a bit of a similar issue with maps.cz, yet unresolved. Reading the vertex shader, it looks like _f is also contain the projection matrix, while what is used for Google Maps is only the modelView matrix, so it is orthogonal.

(RD1.9, GTX 1070)

eliemichel avatar Oct 01 '20 21:10 eliemichel

Didn't notice the skew as I tested with a few number buildings. Thanks for your quick review. So the postMatrix for maps.cz is a kind of heuristic solution for such issue? What does it do? As said, I'm not that fluent with graphics, so my guess is projection matrix is already multiplied and _f cannot be decomposed.

minostauros avatar Oct 02 '20 04:10 minostauros

Well the postMatrix is a dirty hack that I'm neither proud nor happy with. Yes _f is premultiplied and there is mathematically no unique way of decomposing it, but 1. finding one plausible decomposition should be enough, as long as our _f = proj * view decomposition is such that view is a valid transform matrix, and 2. maybe we can use the important number of matrices _f_i = proj * view_i to find the constant projective part.

Another approach would be to notice that the website uses the https://openlayers.org/ (so do maps.cz and namur.be maps I believe) and extract info from their code. For instance, it seems they are using the default fov of 62°. Near and far planes are a bit more complicated to determine though as they depend on lods.

eliemichel avatar Oct 02 '20 07:10 eliemichel

There are other constants that I thought useless for building the scene, which I excluded with if len(unpacked) < 1 or len(unpacked[0]) < 3: (length of positions). Those excluded stuff contain empty textures and positions are not 4-dim but 2-dim.

Worth to note, _d is consistent thoughout all captures, and _i is consistent within each capture. And _h perhaps seems to be related to the screen resolution (using 4096x2160 display).

For example, from capture 1:

{"$Globals": 
{"_d": [0.0, 1.0, 0.0, 0.0, 0.007843137718737125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
"_h": [3380.0, 0.0, 1.0, 64.0, 4095.0, 64.0, 64.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
"_i": [-128.86721801757812, 146.50613403320312, 3.7172875217708016e-15, 3.715873823781834e-15, 69.3901138305664, 272.08251953125, 6.903526466711099e-15, 6.900901511607558e-15, 0.0, 1.4782794866352394e-16, -1.0003803968429565, -1.0, 239.34097290039062, 177.24179077148438, 451.1508483886719, 460.20159912109375], 
"_j": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
"_k": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
"_l": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}, 
"DrawCall": {"topology": "TRIANGLE_STRIP", "type": "SeoulMap"}}

and from capture 2:

{"$Globals": 
{"_d": [0.0, 1.0, 0.0, 0.0, 0.007843137718737125, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
"_h": [2470.0, 390.0, 1.0, 64.0, 4095.0, 64.0, 64.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
"_i": [-37.10361862182617, 130.9170684814453, 3.3215295883745957e-15, 3.320484349717684e-15, 59.193946838378906, 82.06069946289062, 2.0819826321538367e-15, 2.0813274521691355e-15, 0.0, 1.4782794866352394e-16, -1.0003148317337036, -1.0, -264.4698486328125, -209.93690490722656, 308.6745910644531, 314.89434814453125], 
"_j": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
"_k": [0.0, 0.0, 0.0, 0.0, 975.0, 357.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1170.0, 389.0, 2.0, 1.0], 
"_l": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}, 
"DrawCall": {"topology": "TRIANGLE_STRIP", "type": "SeoulMap"}}

Will do some investigation with those. Just FYI, I attach captured constants in text format. capture1.txt capture2.txt

minostauros avatar Oct 02 '20 13:10 minostauros

Interesting, those extra uniform seem to be present only for the ground planes, not for the building meshes, and in that case it looks like _i is the equivalent of _f. The 64 in _h may well be the camera fov angle in degrees. _h varies among blocks, and so does _k.

My best bet would be to use some least square regression on all matrices to extract the projection matrix.

eliemichel avatar Oct 02 '20 14:10 eliemichel

And some more info from smap using javscript console using chrome devtools. Seems like fov is 45 * PI / 180 = 0.785?. I could manipulate the fov using application.mainMap().getView().setFov()

>>> application.mainMap().getView().getFov()
0.7853981633974483 // 45 * PI / 180
>>> application.mainMap().s.src.far // far and near changes with zoom in/out
66516.65499085707
>>> application.mainMap().s.src.near
6.046914858777795
>>> application.mainMap().s.src.qc // changes when window size changes
(4) [1920, 922, 0, 0]

The aspect ratio should be 1920:922 then.

minostauros avatar Oct 02 '20 14:10 minostauros

Okay there was some progress.

  1. postMatrix = Matrix.Scale(3, 4, Vector((1.0, 0., 0.))) and refMatrix = Matrix.Rotation(-pi, 4, 'Z') @ matrix.inverted() are wrong and should be removed, and refMatrix must be specified only to be used for Google Maps as it contains matrix.inverted().
  2. projection matrix can be extracted from website with the following, by typing into javascript console of developer tools:
function rdoC(a,b,c,d,e,f,g,h,k,m,n,p,q,r,t,u,v){a[0]=b;a[1]=c;a[2]=d;a[3]=e;a[4]=f;a[5]=g;a[6]=h;a[7]=k;a[8]=m;a[9]=n;a[10]=p;a[11]=q;a[12]=r;a[13]=t;a[14]=u;a[15]=v;return a}function rdoz(){var a=Array(16);rdoC(a,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);return a}function rdrz(a,b,c,d,e){var f=b/2;b=e-d;var g=Math.sin(f);if(!b||!g||!c)return a;f=Math.cos(f)/g;return rdoC(a,f/c,0,0,0,0,f,0,0,0,0,-(e+d)/b,-1,0,0,-(2*d*e)/b,0)}pj=rdoz();
rdrz(pj,application.mainMap().s.src.fov,application.mainMap().s.src.jd,application.mainMap().s.src.near,application.mainMap().s.src.far);

the matrix changes when right button is used, so the user should be careful. Also the window size must be retained. But at least the right button isn't used and window size stays the same, the user can continously capture the maps. Example:

화면 캡처 2020-10-04 011554

  1. I could get clean modelview matrix using the projection matrix like:
extracted_projection_matrix_list = [1.1643550826861904, 0, 0, 0, 0, 2.414213562373095, 0, 0, 0, 0, -1.0004811657628294, -1, 0, 0, -14.763227768722993, 0]
matrix = makeMatrix(extracted_projection_matrix_list).inverted() @ makeMatrix(globUniforms['_f'])
print(matrix)

화면 캡처 2020-10-04 011728

  1. results show correct center, scale, and shapes: 화면 캡처 2020-10-04 011906

Here are some concerns:

  • buildings' Z values seems to be highly negative like -1200m
  • how to get additional input from user

any suggestions?

minostauros avatar Oct 03 '20 16:10 minostauros

Congrats for this retro-engineering. The workflow for getting this additional user data would be a bit cumbersome anyway, I would suggest either:

  • Dirty but pragmatic: Add a string input to the import operator (here) and point the user to the documentation for more details and to find the snippet to paste in the js inspector.

  • Cleaner but longer to write and we likely don't need that much: Create a panel that explains the steps to follow, with a button that'll put in the user's clipboard the code snippet, a string field to paste the result etc.

eliemichel avatar Oct 03 '20 20:10 eliemichel

Hi minostauros! 한국분을 만나서 너무나 반갑습니다! ㅠㅠ I was also trying with smap but I just couldn't figure out how to apply your script to the program. I tried many times using different versions of blender and importer but I was only able to work with Blender 2.82 and 0.3.3 of the importer. I tried copying your python script inside the Addon folder (where they are installed) just manually but once I paste not even just importing google map's rdc won't work. Is it possible to share step by step application of the script for smap?

sk9288go avatar Apr 01 '21 20:04 sk9288go

@sk9288go 안녕하세요 :) I kinda stopped working on this as SamScene3D started selling scenery for Seoul ( https://samscene.com/products/seoul-city-wow-for-msfs ). The whole process for smap is currently fully manual, but as I remember the steps are not too deviated from the original guide.

minostauros avatar Apr 02 '21 01:04 minostauros

Hi, I try to do the same process for Israel with a 3D mapping existing for Jerusalem 3D Map can I have you help with this project, please?

LiorArmiev avatar Apr 10 '21 10:04 LiorArmiev

HI! I have done this spring, but now it doesn't run with this error message. Can you tell me what I should modify? Traceback (most recent call last): File "C:\Users\samsung\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons\MapsModelsImporter\operators.py", line 54, in execute importCapture(context, self.filepath, self.max_blocks, pref) File "C:\Users\samsung\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons\MapsModelsImporter\google_maps.py", line 280, in importCapture filesToBlender(context, prefix, max_blocks) File "C:\Users\samsung\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons\MapsModelsImporter\google_maps.py", line 250, in filesToBlender uvs = [ [ (u + ou) * su, (v + ov) * sv ] for u, v in uvs ] File "C:\Users\samsung\AppData\Roaming\Blender Foundation\Blender\2.90\scripts\addons\MapsModelsImporter\google_maps.py", line 250, in uvs = [ [ (u + ou) * su, (v + ov) * sv ] for u, v in uvs ] ValueError: not enough values to unpack (expected 2, got 1)

location: :-1

ahj4119 avatar Sep 22 '21 05:09 ahj4119