MapsModelsImporter
                                
                                 MapsModelsImporter copied to clipboard
                                
                                    MapsModelsImporter copied to clipboard
                            
                            
                            
                        add: seoul map import capability
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
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:

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)
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.
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.
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
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.
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.
Okay there was some progress.
- 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- refMatrixmust be specified only to be used for Google Maps as it contains- matrix.inverted().
- 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:

- 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)

- results show correct center, scale, and shapes:
 
Here are some concerns:
- buildings' Z values seems to be highly negative like -1200m
- how to get additional input from user
any suggestions?
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. 
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 안녕하세요 :) 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.
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?
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 
location: