From 196192cdfe7f530dd9499b6822391f1a2aaea8a9 Mon Sep 17 00:00:00 2001 From: "esrafilian.omid" Date: Fri, 9 Feb 2024 23:53:17 +0100 Subject: [PATCH 1/5] 3D View new changes: OSM file is not mondatory, docs updated, using flickable for 3D Settings, using Loader for Viewer3DManager, touchscreen added --- docs/assets/viewer_3d/open_3d_viewer.jpg | Bin 0 -> 22187 bytes docs/en/qgc-user-guide/viewer_3d/viewer_3d.md | 21 +- src/Viewer3D/CityMapGeometry.cc | 35 +-- src/Viewer3D/CityMapGeometry.h | 5 +- src/Viewer3D/OsmParser.cc | 4 +- src/Viewer3D/OsmParser.h | 2 +- .../Viewer3D/Models3D/CameraLightModel.qml | 6 +- .../Viewer3D/Models3D/Viewer3DModel.qml | 179 +++++++++---- src/Viewer3D/Viewer3D/Viewer3D.qml | 31 ++- src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml | 249 +++++++++--------- src/Viewer3D/Viewer3DQmlBackend.cc | 45 +++- src/Viewer3D/Viewer3DQmlBackend.h | 7 +- 12 files changed, 369 insertions(+), 215 deletions(-) create mode 100644 docs/assets/viewer_3d/open_3d_viewer.jpg diff --git a/docs/assets/viewer_3d/open_3d_viewer.jpg b/docs/assets/viewer_3d/open_3d_viewer.jpg new file mode 100644 index 0000000000000000000000000000000000000000..16569ab636a36ef7ffe12b770d12d789f883f157 GIT binary patch literal 22187 zcmeFZWmsLyvM4%m2$10J?(Q1g-90dIcL`2#mq36J+}&N0;O;KL2^KWL;ZCx$*52>l zbI$kP{rh(F4MvUbs_Lq0o847oJS{w}11PeRGLirU1Oy-r{sW#iP$MNgt;_*HMurZ6 z2LJ#LK!bn+Ai&V`g$Dui`)&e;@&CZqV3_6)4kQ?6g@6Q*!FOly#Ri5k!1n;~Wfcbf zoAx~zE(BlT>V7}}eV39^P$pqxVr5}sX8}{PuyOFQu<^07lCW~|v9R*7v4gQ8vi~Iu zm>fU=9)Z8OK1&Bc`~^!qgMZ-XDj>nqL4osdz%bMwNnydyu>S^Q{(+zIARzzZL-b7h z2R20k7l0G|@4u&ix81WEV9cjwKn#F~g@uEKfro>GLqLFkfrNpKgoucQi-!IRgAk9H zh!Br}fP{jHnuLsjoPdCao0frvm4kzWn3`9RhfRQqorCR}2?PQH0umw;4l*(h8z})P z+yCeE^cg^f2TLRY1wjTtqC!BSLOk^V#9%pLz%BjU*nbiPBos6ZEF3(-3q&wN1In|d zpdg{4U|^u3!PvgwasV0?291>*dgDo&22cBHC<_o6k^ZshPQjrIoddtDC!rr`Owe!6Bhx z;SrIEN$-Nom3J3!i5k`Y{wfPB6d8BYRYML4eU$fmo6VMd%a$Ccg^<9Zd>x}2~lomdW z_NpfN$-I?W6-oo0?pD5`*U=9_7sNk*JOLXr4_SV1t**MRUxFVD$nHh!QA-~p^#dSo zLXgkUR!A2usD6B7DZU-KBfZGTNEk+4ra&jXv`qDv#iGr)ua^HNo%#gGGIQp6@kLo8a@ny}TJ-t+laEt(cC zvVKOB9LLCK)TD%T!!=Q7>`^8Efk`=nS3E;ZPIHk}mV*f9^X~LhpI9*5^-c;6oHNN=OL;gI8_;~Ba6aa+AWup+;T@u{JcSFM?#1h- zIMQ5#VWxtkcsctW>hl`G8Dq#co;sV}s;;Z~7vx8$*F@y1uMy?5-A09e%^p?#V5GP^ zm7Q#wReW_`w0~NEH7S|p6^D_EpKj`nrRXe!n_FMux@auc{wAGn^Afg!{Wf# z{oyG6lz{cOGZLpKKmq$^{^N|4aYz4GW%*F~qZMvYCH0q4fO zG2T9#-hH4Y0=q}0-)wVOLPu()Lt;m%ggiaxjP5vJ57CozfD@lWY$tph zX?Xg?B!EY5`9nunb8FJcIKA{YO^U2Nt$U8Pb_rAA{p|AexzjQK4br-PgUzG`8<&{| zc+@49W&lb;%FTvh?4|V9T;!mvjP}xCsv$Sj9ZJH(&qudC%^A=+)qKh z?7*<`m{~t~Y|p68*n{@9#}omjgnT~z(rlh1$_C#v`+aq!Yog#;;yMh;c2ewC0F3kP zV?L)K*QlHfWsl3)i0nCPtBxn57Xd0RofelVi`W zy`;zFx$DmT$`mg16;Yl?jXjO-7c3>bEgnK2QPWIVwDkon+YGtiG94{E&PP3Z3Gct2 z-4rDApDH+Q3gINivZk8)0)hCBJn1Xc;f+?8C-;V8(#FD^_rTQoRp{DbeAx0?gokywhFwJnckp3O1U+qR0gWy@|R;}0nrK=ITF55#UzjwkFRm^L$PQSCF zKu%&f1G1G@Y-{pI$!~p;iPZ}hgy#slZ$7Ma4UGJe<{vKo*+}s;w*^f9sz?Pt!bAoj zVHrclSaw~sfqw$ts2Fk@x!aLnmZSe_wp5hUOuC0tybugzM^nVd9G-XEgiqu*ebGF` z>DX{&{78G7_0fFn+K2gCSZ(1Ecmf8Lw4MNG;fM5&gHDHQ?o9*s?%Rfg11(4hXH<~+ zenK0sVC(#(`xVRTa{j4wtpr)9rdqs6WnMRB73KBG6F~Me>%mocs>4JEje_Y2Q%cq5 z>m$c?o!rcN(=5#a zA`F;RUHgVCvY84Z(kAfZ&>Gizr07suIA4BHOnw5A{UowbniJ=!;L7bD=-*Xl>J_$3 zV>F$Xz37?B3Eff+rOmTK9pj>hS@A|n1nv(PvO8|7*e`sR<+-r$iAxk)#}R!*=LHzP zr(7{JW|MQBv(m?j>}xUI^XKm$db>D5@A8<0+{fQ6XjhZ4@Hn*c!qzE<6jgSB?5W}x zzx7oh3J(ovBiY}g8&F3)_!;e5dDd-)Hf)9q4UPV?QHz=E^E`qEbG6?dN(URq# zXt;wl6YX^m*pS+5R&hH$QEQCyUn2F7uQ7-%A}6L<$)nyq?ggBFa+XVar*5ev_G4C+ zdFozBg?ibW1((Z*zeu`B%#PsfzOnNf??-f-+$n~1^N*Bm zeF=ybF(cNc+R@012mKwO1Kp0fBA+JJqnLP@7&3fKPD02y5zY1(_B-$p@PBnZxowrT zrgV4h-&b`gd$r^5)cf#G?a^=g3HaQ#j%Dv-QEFf`?0E<|Od*Foln?XbOCXe>GmLK1 zCTtPqY{&Sb9aMK)+#1Ra&NlY1am=)TxW$pnKc4%4>we^TtnW&G`10^h>u;{eGxsw7 zWma>)w1jkGu`Q6Yf0*(b5TfYko`^koAFnm!r%?!{uG@#nu zQjHw8I3b7*9D|W6h(2(?dHiX$cyPYYcRAII*H$0myxLNNTd;Y8$dv2=(_8Czf^XVi zRpDHxCkIK+x1n!};$j%MW#H_|nA3PZndmxf(cm;s@Lf6S2@pgE%(SG|C6KoiIJHf2 zC0vp_)(3-$=xg3T0Z_Y13#eAt-wxvD z%G9R@J9ze$=gwCK(U#@yet=Suj(ICYTV3a2*H>!mxQ_E(%dJ_QGMuC>)XJ@~biV`- zJ7W(Sj})j?@9{cLk44yNOfwG|k}jg_ zF0P=zlMEgA+E38oto4=V=k2*ISgx4nIPFPDzy*CV9$fe5i`-IZu)z%X>BCOeaJkYN zA!+J_aV~RWL({Z^AcqbmCrcXpz1H`7%sRD7mQME7_7vv;9&Q3))#90>L9j zbvfQ!*~#V9`~)&)T$lG0jZ)v~KX9|xsG7$g-L<%!KhRcil=r4fQMM-br^8y>%)|Ps ziUdId+31<9xb`&HjfFWfuToXZmGybgvC^;-9}Ppj@$_RZ1>p(UhJruY#e3O!JU0h*O?+1R!DGtc7ztD3EnO@PWQ9&OPe=5-SnCGe z>7b9-Vy>&BRIvAy8R#8hLiOqu6f}+yxwUlt49BSlbeU%G@Pz#8m~EtZGPx@qsVzFB zyX+)!BR50uqPI>(O%>>C}IY6BY~LzS~w?0U8Y-7hqWjhd{; z-&{vmGXx1>ZV`G<;qlJZH%l!{^4NR!7wNuTFsO#s8*rK4sR(bthrj<|mC;U124LJT zhe8y}RgmkiN!NBRGPW1ro_an3FM#eu?np@)jIxq1a1BaDTgRtA_M6qy3#JTKBR~{! zj2L?}G{jR`Im=NM=5y%L?17^s{Mz-)GAOKMk$v+Hdh+ckqKkk_B(3uYmrTn{aiIpZ zCB?m+==7yKwqWGU`rt1xnQ0x2E{e2xRow0RZm(eHazMV!4qra4ft z4LK`dLN>zElve9MEk11^d04u-I`T0y+q*Csn>v`7F@YTHm_3ahnOT`wm;nJ{Pe)^r zjhQQniJ66!y&&01TNfFLm8l?^7N-J>f}@z3rIqwsXEU|8it3=ZHXvS8GGQSS0Z%?p zJ4ZV+S7Q=SJ6n4fK2Jfi-^}^I@N+gZ8Od)HR~tbxZSawdn1iz!2?rAg6AL5wXvm$7 z49vsX)SORMT=EYG@RK0fA5lF#JeWM#nH-!gm|1ywd6`+*nAzAE!5EA#UiPlWo{aV` zY!5Pf<^$%;WCdoz z&dF-dV$Ng6$j-^e!pOnJ!NX|6X2#3N#ldRA&2DbO%g$r^H@%Xx6}TH2+y1*e&wNb5 zd`#HcL9E=YT#P0>APzT`>Mi7YA#GDhvVQgZ`Lq=i>;*)f6wlfB|gO#1J zg&DK8qnQO6$+NxqM3iL&$=H}!{yZw%8oQc9A{$qjvSl~Yv_>TqtV}buz;QxOX_}3=F%pUwp#{;}Yc-n-l zmJt&(QdU)xl#!PJyHde!&}>_foeMPBF>7b<>Z~dyN&@!kk-&WiAOS?+CBO|J8iQOM zMU<80|Mo5ZpZ8yL&u&rxm}Y$D^?#QCk2%Pu;LQTqCrJXvdJS@Pb_K(4z%ZAGtK&1A z3WhPjKiEvca5)%ea0Uwqh8LdmP5y$9o?(mM@Ux>Dz;ISq6$9(`?4c&H_&3<(-(ZlX zvmF?R1B^pqYG)7T52^hZZ2AoQJi~UjZeZDdr)Le3%1*aEHqBlvC)&T#=$!R4a=4L#m(dSx(`37Er$L@$!H~Qh`Vk6yA4ZEIL(Tq`pNb7|i?KNh3$vYTOJRZMt33 zx^gXt;v>!~22(7J6G6>DAqRRx+5Izb-LlTO%MTyIOy??YHoG1lU~(D z;yOBUiD;Mvm3yH{khXiB=dFZp2feyPA|$Y>aBQ#OI!%)bkM0ikicvfJ&W4Neb&%O0 zm(Z=9-MNRqxkV)mW;@IxuB6wcIh{yPI#J{}da zU`R?8Rg+KKm0p+Y{h+S*tA3#Xvrjg56o-vX`UKHe!$$5lmB%+3N()4+taFAOfm12( zM|4w|eQ|f0+sJ%d)=9ZMKR^Y3UN;(6+M4Zr)D$#04e;Wk2uz1bC5JMGZ^+0iR-(uw zR@FlxKvDTx3x~-II>ga!(XhNtd=F6#4+IEC%HnI$RSd?Hgn32Vy~~idO2}hApF-05 z@jc-+Vgmw|bj zD>9+$8(T#60bjDg#+w5-TMx1f5m|=$#SNC>>kJN6_g8PuUk2LKbFP$G3m(hQ=&qr% z@ltgj9IFjS@f-Xg#8FMJh>kT}5O4-{_En-8?YCQUawYnUYNIjC^e=mdlBOWv0kJ( zq67O%(!tkl*@>AFO-pb6m`|*u3S021zaTx1yvZL6{2AKa7d76YOoLV*fMnXw_pa0? zYn|lO$C`Rq?2#dSx}XQ2AnI2L*VAQzouKl*&SeAto5(RiX0`B)da+d-E%ZXGhTHq{ zcT?vXR*fquB<5I8fWFrK6EMqOpi{!+ir*_bjhGQgWCat2+3<7qCSXXy8P-tH=iUl= z!J0udBw>m&F!Syq`p6R~9u#K6#6OI=W7D9HJK1EH;++`OJ#QRF2HLy;U(W?gl0gL9ob{wYFU9k~>+ z4Bc%h-K?BSh6>v5{208~c$FZmH(s$fcX8igxs(ULcp`B5Ami@B`OYCGG_(tv*F8iDiyu>*Gu2ZXsO1M$SK$s-jEZ(Jm^!R4IQh# zWP1oMinp>S(%PbGzX(&7b6pM#l6-(7@JXu092_WgIs2k#@4a37y`C}p4VDMGPWeI( zZS7PYTJ>U|t*90S`ZURG8A2qbCn6IuG;-_!CF^8XOz_aHdPBbZ{R^#+KP!%T586Je zCf^p{E>myqo?RZ}18h@$oT7%8y-f1`8!5E z?USZ1rVDAqb4Z_5LgtYMTdJwh0X1AAHX{9P5Ut+ve);@GrV!u7i7_ZCe_^zE-5s9Rp);U}QB zFUPkhi+sL`R$f5shNz=O^m5xj;c&5ZlaTZQYOaa--Nh3i^#pjnL$$N{wXEHby1S+lyKAQZmeq`qLXY*h(Y-FV&HBDEQ6MbxXUtCP2~D2rxr~Sofn^?+$6GH<4JjRS z5{NlFPmNv~BTseo^4z@0({zm@UYgPpqKC<=vY?ZKZzwaP?y8zHG8;QEav-n^OpNLj+kR)CX=^dz> z1{#6PACDI>hnNY42=BMr>PGP_I@nXIblzI4V?yeF87eGT%GWaQ*t>lpHE!N^!OrE# z&gvl3H+}hvnJ=QY?WU`9>1@f4`}O%5Y+5O0Bu&pKA!Vo`!fsh-}bLJ~MxPZ2Ga7ve-1Lpp!5bE38}t36X-r z@?sg22I0^`nU7xvu6#$mtbH75PtwISP}qK4TRI|=1rMo8ubPfmMB>wLFWdPxbFA~f zzASr}_Z9ZzeusJF1m%gE8$aDduM|c?JL~5u4GoI6S!5Oo`KYeYmrlbD^-V5XJM+H| z_a`9V4VT&A=1uhqc6ucE0u8%*6PY22Sg=#h_VLQNfZL zk~k;07J$GJ>rT#t)6c-)zWFi2(i8cIQ$=x6Ucts!nbOjt$nHPD)cC%4-ESIn!=oiti|YR2t{ zXeZKN(m?nIL3Sp^+~F!)C|quf9y0?U2k=SVmU03~N{p*n=(>@ddZiDzm`ZaNlT}hQ zwJ2cB0%R@T^c!o7qo+wP;)JSRTYrPqlr(iSbu}q3e^FbTfvcl9@%f147|wWe;=W&w z;|;kfD4&}~>k4{JeSzD2|MQv1edO}DsgoNrM2S=_HE9+RWQA3Jj-CpJ7zO=g)M0Wp z^NKlxLaI#47bc8q*Mc4)ftEvkmPT(e^5SGnieq1MHtc)NT0vyT!Ml8&?5EsvH%xR6 zixp0nr%fG=S5RIB*M-rl%r+FPnOer+LS*U3MvQp(>kRV8p z*hN(Foax1z@tv*sMCt&CsX@`IT-!b9a#+hUY4MiFSlDFW_@jY}AV*V-Af|z8x$+kZ zyfM|&2F7ogYOt>~6xbYr-Qo^EAK2^I#hTucx3m)?HeA zZj5k&NgrOhIY_3dj`7vK&1Bcva@D?OSk(aUOcAVu&#SCR*6FeEctygL5pUa1KHpoF z5*HTvj@!+GSYXk|VOVT^bgZpOi^4F6uiB@!$U$k4Kk|c*dJ#nN;YTGX(ArbQO)$|b z1QK@`oMNfx%zR$EqDn8-XEHc-3)zk8^2?O>vf=D|+17O0vMC@lho)nF)pkN1C}U@^ zfSv0`RV~;~qeOyFM3$hKji!h~I`|QvEb)fxF!d2Zy=G&*B>%9uFsO*;bFgf9qUAh_ zA_L|rb+1!!O%g$rW$P1A7Xhab+8?UeOh;R)Ry`;u;D#D{ta?`L$U^A^ysIZGC6fwp zlOc_V!+AG&AfazL#3JAN*{$Ne0*{GBiVUQ5GpvrPyqV6HX_mI4*Qfnn@^OYzO|4J+ zQxpkNJMVialZm|OC{p=tphsNBGp#7o+TVty$Cd`y=QtN`YcwF^^(4@wNIK)QLvm5j z&cbkV(zze(({2?;H`(B9s&2nQGk-Ea2FIvZi`ZYRWDq zsp=B|6Dyc9!0^evq+f+f-^I8NQhh7@5MS!OU44ESO&T{vdu^y;#70UWN!y?jf(B}+ zPFZfU0Uec$8{JttuT{61dV(51X5=sJD8PbK`5Ug~x-rqA0_9?+Yc%Yf)cf8@2KT{E zjOs6kx*uIjhLJq%2=(Of?U0Tc>hkRuH=&VKUl-WITV^LQX(pJDPb3s%{_tlmM>u!Vkh@^cfT%;Z(R$Br7K~BmvJTVG7brVf5gHg!y+R5 z`!bGB3QNWcUdGu(RGexsv9QTSjm?}B62DAu!Lh5lC7n`mi>Yav1m@M%Pl>B*xVXNr zot*i-hJ$|=2tx?c509T?`&+<00gA*0I-by}_7G116LD>yV6&N24U=D=aA$v`Pe&Vh z(;d&_9bEo<|BnrKJe_w$3znJs{KBf>;yR72T6$qk=Fa|FCx3R(_pp=Ga@TIR(6Bnl zda-KaB7D*P?G@R|PF2`VxQxJ&!0o-ol_ge$iT%I@L7eCt{xpV~FBxX+vYR|PBgMlM z(e9;EgvFm$n!dcqPV@<|iLT8^aXu=A%Ez`{6%u693qutt2Lfs>nwAbNrE{dY?o+JhZwI%2&sH3hhSI5P{FXj5o{xoSh zzVy@_o5ZdI<2lMVV^-BYoHsT4`FznVRs1Xf+WKN{6G6O+ z0`rGX8f1s3aqTP=EIo{0+;&=u`=?@^;mD+3OMR z%OkK5-I|hwGUk#RVJo=J*A2$m`m#Mn`+HcNu&k2rCpo@z1sNhF=g#p9N@j@HVP1{z zK%<0SoX(F%yp@>7-AbfwW$ua9a81Uer{I&(?U0hZ8nc{GD=rW)_-Uh1ga@CmwNEUc zZ+9{oGyV-Xq@s_X@2by+Lz5l1i+5`!9Vb8Io+?HuiD=>0>;dQT$N1VC*StcO@yh8tg z%PxyrE;$81c{hcNyAf=5DJBP}>$y`9FT#;bG2M}1xF=&RnPT^T#C8z6R*Z1Kxokcs zIBmNIDYgucQ!Q1#h7grqe#c74D#eblfz7+cbu=kt?!~2xW>AeXWsD2eRC2Ukz|ScCCX};kNOg0Hae@o5E3NTr&M6R?*3UoDbhPm_kIzLtCvXn@{k& zezqsLj6TFKzR!Yg`e$Qc8EyoHFvn4Ssb^#Q$D;(J_JuIJFrS}ZQu!{uIYw0= zrPc;{rMbr-spMEpHhJC$Xe{Tsj0imsXuhe4kJo@zdfc1j$C&JgB&YM!jkwO}(08|-+5 zsF{+lSnKZSafV=qBuC+NOn3p+*!f`1TDiceq@x{Fevg18zaxE+V#ZfkZo=2I7akX7 zNO!Bq>vwBxx+Z<`=0Ya#TmdP*DTAS`A@T{(Qydi`a&#iEPi$X$?}6pEc&mliru|0G z<@@R(TE2W=JL-=}c$0|6H-s@zz4?;$;Xl6upirKQjs=^3j11`%oT3y%VztPc=CG)* zk*yNluQMp|jZrm&Z~`f9x>Yv~V|j+{6B^Pmq%Yd1+TW5Ul@N80?)o##F)TW;B+i^` z$20#F8~Oq<6EcC;pVs(VeSXYWd)ALZ&2F4}l&A}Af3-bgO)d}fvemb=m$M z>+oi;7 zBMO!hI!4~bmTHR;BJ!dSy1Ow!<ZHS(43qOWNP#6QyS zGOQmu90=bGSyIG1iYFpvD?Q%$uBnImgMsYRB+hm z;dfs>hA(d|u(jW}u}7@PN#tYcv#_)Vx+I{mb(ACUgNHwQ23C>Ug{Dr_Q{h)4+bmUiyZti}W+f?262U zZ-a=}BWF!$8<+B-j+WDhrX9xBi>0)8!V}HpAyj$&8Ah9+iKN@Cra(5S8W*$+sqLs! zNq$ZJ)AA79S6HNE@hfqzSp?n<#NTD^w2!e@_@o*TVmk-&n43#K@zUB=)T5UyEqM~q zN@~!#;W6PedmVO|8w7KjtrjtN&TsZr6ot<#>Ze}xs5#Yd_9a>sh5ke?+V7WSO892O zwSK{`3BLmA=Q5ijM@}b2WUR2daI7v~gU`+?5L67E=mX2%-ng1^!B&-aSwuH zpZ3j1+3Nh5I1QJf)FUy`NY8>s)`_HG-(nrBX7n>qStkwasv&&`rIS-I#C4~0u@0pl zCm?7-6Y?!v&erc-WEs*OZY{3Q?`%}EDF}M(Jpn~$2ScT1E%IE9{ZyZ5+Ek^p*hds~ zO(UZgDg`^@B}d7LP8quG1CZ1P)+17WF00H)Z>vVv^4p!z?s8pcnDfHwP3f^+4$~LU z*=i3cOJu40HD>v=J-0vSFImk3j(r!{TkAPKjB2oe!uAF$(;pCET2R9*Z0$e||%kD`R zgDP!A>Tq1(T{0pxZ7a2tzf3Q=ttV#Ge-Nw6WM|$;EEuF{`eYU?qCL`ve1{U=Mn{6* z96>S>dOGdS&M?>C$b)?gXH_8M&_malAeu6 zt>L7hVboc^Lak1AhKmVp#>1XPBuS@5mZr-$c&uoci1V!sR<7K6r}?ZZqa<9JC&1?8 z9Z~t*>aRZN zSS!cInq8F+oAdPAPCWtD3K<59oFhZ+gZw>#cT{>>?CC@TlCsrvt9--OoeoFA?<>t* zU1$_wi@}&?&b#$@9EBqf6`FV#-Inbdo|>rQWFty_IMsAR6CY9GS3mT>b|Wq#I2pZs z0!}b#wHcu`!fcKSObu2{PGQKT2UJ$JJ*;J><$b3f%$tr(bmcO5N(3f!(jlyyUdkL& zoXsbPjyb&0tuFQzwGzTYwqB+0z<`CR_^LPC7>-tDyunoSDRSmX0%%xs>Py zz>b+_cvn;n$K4ZfB=p2r85g#p8}J%@=vVc+`Kj4P=x`( z9ba#k`*{b~v$ZnyNS)EV;UawEcyzm_cT1K#d2436uH05OY`v6g_D8%ThDCk1O1c=K z{#2Qh)!1j)<+j(8LSYlh>WTRF>zoJ0Wn2Bh4`|eC9i#F~Bs15?*oteF@2rOJ7l#Cd z(|Uj2-c}OAF$^t+}mb3fU9C^n27u(HcHn zZ4)r;Gd$AR2q&8HG)Mt2&#LWZbhq|%>*n?;pMLpJeFTED|=y}&m`r* z>1v3Oyj#OIGJ5p^i=sqvw)jA*um0!ZFq>xB^)fOZOQ`V9fQFxdh;=W1@}UkynRa^p zq{ti8W*jP4_4k-3kkL!AemE7Ab4^)#xe5Iyg$kWV6Yxrny&M>A-J#+c;tA+hubPQ| zy#RM6X*1&-XlIglBPc#n8g0(v=26VD=k;&V5EAXm+7v;P2Q!D@H%^a>kX_hE&u=+% z)4A8j9w>gvvegVA-=}wKDbC4Qut={Sc4JFJ*Dn?>clx#7E_V_oDL-?(MCe3V3GIDm5Hfv}-NqGV&_@IH6uU;7!;06OfYAk>cvWqC+po zA#9v{(R^`;O<@)(k*-O;;9lOgW7|rOjhyhA*MPbziKHHxVQA)ZO@5v}{lHwqevcM| z5CMy^7oraNc92@`#1Rdz;~jmKHC8Ae<7B!HmwI|Rf2Vlon?O5Dy3IauS;_d_5s@F9Y>nql zw9&}*M3e@Tgd#GD2;Tg1;TUn?PV}zDa;M&`sa>A+4=)5h=76(d1j4QA1lwNhZ>?`0V#ySDp$(8+HVqv=AcPjqZGJ&$gBCE39ju6YJZp(V~1a z&5lNG2a)kV*mRr3c)J_c&xLTS5MwEXInJiSu*;If^dOV9QkIU><9Pb!g`f?YeymHw zG~b|yF($iU8SVbqq-5CPNzy=(B;vqacRY)Svs2dA*#ANSe<3QWQ<+@y)f&>rHZ<*H zMgkSwtR>Ni4C{dm+`S)Fj65L}LJ2V5@S zTZWVKME2-PBN#N=4C^XMygxwGq#sYRlqOH8!m!fisvxjT%4zBQmC-tK8rQl@+rpB9M?&u+b(!YSx+d#Ndv82&k?RW#M3#zo zG&NI{IG2`PZ_d&>jWCq=xC@78nB*Vi16Yx;e+}&K!dlFXw~w7-fq3meg9~mC_Y-1JGJd z`0ASK%k=$WBh-jYb*Cvo(`%wA6)r5yxsXEy0*jBioX$xG73liB$_0R}Gt0h_7(=MI)=M~NESy5ZJK-hg4l zmQAImm4xfyQ;?>bQ5_;`_**H{;pJ^&7phS;=E@L!`=l4MBeBbCW~LjC!&t6IQMI`H z$_?F{xZ-TOMMxK-l}jz!yB-o~SP8F}jz$pioxvxGn&m`FjD@dxH#Qw)sV$d3RJ@!% zxWL(jrWPA{MaWt@_bIFwDeOSsvcZ=197S5`yS^0#Th6)Xs?t8rsjwt3IiY~7s%xJq z3Bd*3r}u~3_#X42?q}`{ewut4^iccAuAd{+ExkZ$!$u5fxLpqyTOvWc7et=(N-hE| zKmEbG8!8lVWCsNJ$Pyd`^E(U%fIuY$P{8iS=j{ymYXg%cr)PgV;Dt%ORO2C&-n&IQ zdSxey!I|@GPH(u6ZKJrOd42wYGeQ=s`-bakO{_Q7j2qoK;Vf1;1q~dkPaG!Mp2cCvLUF5pt^s&Y$+e~>o|PqJN1w8Ir*g`YZ`-G~ngr#=e` zeif9ZTPWq4oY^hrosPrlmuIQ!2w9G+;DUS)gl_F zAoPxH&64LPD3fMFK6tj;84;UgD@5;&fMlV|q9x7QSRPzAsW`&R;3uGYj4rRf^?ZCc zn2lKy6J;hK(71JAYDUcmfrTeusS=hgpA3z0Wj{tfu;7$PN{@|2h_RL#b5 z*&^5U*Xc+(_#cRf$(&ml+@K>M*uHGH*L3}0(4dS+osr&Jqc=f+?Z`S-V^Wsz&KdI+ z4rhrbX2q|#Xg6`8U8vhx+9KG4P;ZJGB)mOkd30DS)pwZ+v(jH$2hF0kDepFVyV3Qo zreKH5c6dB%9;v0u$q`^yUUk;*l=Ioj+^tX=l-2|Z4M;m8dO;E+p; zK2E#*zInuL{tZL!^OTBR9**vGymjE=d%Hb$Q6%wdNJ{{#l5R|TuWpVVSEh<)VzY~m z(D%#Yi$$)K*aEuOJc)EJmo5Y?XnnL3fYKDdL}Le6O`>Iy$X&7C(N4XTNVDpGS| zSq!l&G{45rf|(W^N`AstsW)kaQId1LWcV!mI?zwLy_D7Mu&Aj$Q<(zQ zQKMEL@iT7}f@*0@A%`Uv-#8K5Z1x={{#hhlhyfl!Ob#%lMlVu_dlE|55`L95z1VYM zJ1{_4B;F%Qg=q1yUzz?BT~_L^qc}tYQ$QCB&vxo7&P{s&T0Yy?0b9mlxLl3kVrw~( ztvYgxX+)6X5SKEOI~+95r`1uCaQW9>hZ#3I{&#)i@StILxGs6WT*XoGh=F?gkxE>a zK<1I{FvhIebDe0(9~@uZatH`%2OZMb$Vqfo#8DuNVnwca8$H$Pcn_gxq+Y7LTD7v7 zjvc@eXvS|ByxpLhT=wrov+T4?-Yx=}ut8_kKWRor3=V4rqRpoyE zHQj3_k`GZ{4xK5oS6RGAzRT-WSP|}g+#S1q@`RG@4t44s+6P;|PY44X;?<5t?Ha0Z z4lmhT<&0p-lU8%Rtz@>n#X_EkCtq>wOSOhonDkY72$Zihq#ikcli5OS6y=X>36 ztL&4!dxOC3D1-qS^=6+6ModKIWrPuHs256HJsYk0^E;OjP)#p>;b+~RT)?Q72N4!) zjj7H-N0DxIV;@eBFFL(e-w?gufY+Brcbop^xv$Ymbe~4nEx#VRytigR0&9#uj+3N` zD|_WYwIvLmCx3qu<@ZdAB30zrK;XX>KosyA@(lv<8xgtyaCD?4agZfi_G=U}cpOoH zCfk-~cj)zN06!Zb40;W>`5NMf{@O$wF947J^)*B`fGr9TmNm8H{W?>ZU;|Ir)TrP% zC@2W{e?{tngZRMTzCj`RJzt+bPuLrO&DYP-A1JC_dlLpDjU)~;y@WOAWbujALT<8n z7a>J-v{)3Q4Mgd|fq+?y0H%v2ErYm)(c9DS$F%ai!Y;Xj7&bmLX5c?%ve!$tukM z(GOHNLJ{5ZWA|~mUU74sTktf+Bh8SYS34nuXG+|e3uB_%W0l0QbydaLwP#xzrCxm9 zA;|4FK)ufK$nSjf*zc#;!$od{IW?hA73!K=m3T(nvX&_?&A0eXXo-%HNwaCx>B1v* zLA(tl-$tA1t_v+l`g%p4P~|3XG>VymQkQ=jR~JQ<@<8CbvOH7y2P?^;WLIyXhlVUL zJP}QV$s7W0&KNx(F@W3_!-hHho%8}0(-=)K76#(J%9JRzc4Q+S;#e-Ag|wj-Zo%PO_)(u==$JS&20q=w*wb zCCNmSt3zHw5s^>O?EF0i`vrsqq-MUm+9;9@1evr=wnCvutSn1|QGhUyD83{R5K&zp z3Xh83$WkhTwjde614(b9p4z94*c8r@E2KgyP=O>6Qbuau!A)eD%pDnR32z_ui0crM z>#S{0LAHk+iHLmat`SJaP`)2--IpIti{NAe-BR$2NbR#C5N?YI=V`$^X6X4P@e2H< zh+x`Ushs_ro3;I)!~2g4GCk+YNbogR?Y*??zgBJ1%Wq$GoT#Op{K^~Oy3)BMc4c!e ziDp9?5|AA%!S$Yt7Nim3npF;7B&kR-Y4nl{)|;4Bs;PoE*Z9!WE{P|OLm^2LeEHDj zR0AuS3^FN#fYk`p+${c7-;FOH&cW`ytLvhlB5-h9-60x}h+^?(PkF&BVKC!!D%FVk z4}{mhQd+3fN54B>>D_b*$n zeKHesy6oWeMLR^u^cOV2OwK`{IbXO{@*IkZa43t^Ky;GE62%d1DqL=IKK&MaV^cJJ zxgaVkT_Ki88y-9;C^d>unZQ)&KnS5UY2gfXCA=9C!LF|594x7v+^3wrOlJM2KI0e@-)_ae$)M8TO>(e}WqMux zC@GbPUt+8x^mb}%&EBO6WxUz7N=u^8G;$JI5`hfzT9`Fvf|&^tCC@Wa$S&l*Y7eWK#wCI#;nYo9s_4kQlg$pQh6VQ5;2rb9+Rw-Tq7lw zbpF2Z*AM!My(XR8TSeEB;x-({l*3vbQHJoAuZNlI*88LEnY;o8%;@ZU@pw2WFU*G-~D@$TH`V` zCKAR`)cX~On8mQ#oV6)*_&T;i(i;RUS%t;I>sr+AZPfHE^_bWw5<$72=fsV8h{s$~ zcJ58om2BU3QgamcsflS8rb$HUb4+o9;}{RKS!q+T;dR-Xj}8WOj1{Wcxuoefpi}eT zO;Al|cde5dYQfW>N`ce{NyJ~jPh+(CvA8I)`cRxM%c}|UJ1oZ+SF-lr6h(t8+(3Gb z3Qd$U$r)i-@?N!+aboF}(mlO-AW*r_Q!1Vs#m+Sxx&0 zK+J1U%nUI@L^F+|`1ae1jZ@$HqLH~AxL!4OXLB@S;1aN#iqsY=wGk&2vNkveGIkUy z)yQ8)k|O5v30#FyOcIw4J1`tw8UUq@QUWIRINe41$vx_QyNTV8Shvd`7*6o_zLm&# zXpMso?5Dir}C>sUNrl$+ox2ZCVFIuI3z47}q!=24M@4cPWy!DkMPtHX#@49e+TP?Jd{Hf3Oz zNdePBCjzfhIR5}Q)O|de??wp(^X>ltBJcT+?SGE`(3lS-YD_1iLSgwQikOHNL!F=4 zcu@c}(WI6@cg>%8)a{HWyXN&J;%_ZT=D$bs-(*xFfO_QCIMkYZe<$4oruSQaX(3I_ zSO3HSBoF}s00II60s{d60{{R30003I03k6!5K&=)agp$$AhE&!+5iXv0RRC%5PK*J zT84-br@kf@oO^V}^{r0;y2LXegW8Jgx2{g+vr&i6;f*4S*BdEm6Z?T4kW?MnyehwG zX#fiM2hot0DJ!O>4yqopB{;R3G`j z1;~VD3BacdX?ma#Q@#7ZO(7WQ5}gOVZ#kq>hyiKie6RYz`vVq_K!dI>o8IPEkcNJ4uh z^c&ZWXy>eL6Egz}DG-Zwp2VI_+!Ji_Le(Wu9peTKxCBk`1jj`g38p>(N2%?69ngw^ zQ#R0IfYQyU?cNuSE048ys<6iG0L7*^w!x=%3Vg!13@f5q*O{gk^xg$YvD$T23htQc z0Ytnup~dO-;7l<2w)xb!09Q78j<76_i=h=`iekl#gS``j+zYZ15>07L){35-cf@lJ*K@6Q(&{+fz9x^MXRvt&I!fNC{U0Pgwd`1tTN%JWnasUd3 zC|6Z}cH@7Y>#>2l4gv>@O*oq5wpXu8S^<Ba#?!f@6SHu3~1N&(Qob>yHw zoS3TVkBOq~TWLfG)Wv%Q(^5$2;muluVCe&3WCkh7@s-~i4Qe<-K=kSA2@Z!=JA5L2 zk+^L#B?O5V{7{4;6ivvm#_9z!0TU8Y1kyJjP6Qw>2eD67Cx;|+64c~?f}D3aoYluF z>G~8ag}5Aa6%?{!6y=hmIT&t9egx`F_!%3=5 zjZy^{MQIYrnei4M2t(Exu(lIm3>N?`Cx?U*n5i~z1ox3ET74vRv+EVeA!v%Kqx8vz zi1YsdF%C62csoG__g{Z&jN_s4L)iPzW%~gIkm~e68!cg*vjsY6Q&MOJ$UaAL1y@Jp zo#2%q=t=~Tl4&(K)*fzT+z6tJ-}8a&E8-@5{N>i$71t(dv?PdPCO(6F=lJ}0kERCO zwm3*SW|K5s^Yn7W(qg&aCZcA8PX4{)(Qj9_NOWw|$&Bp;L=5}^eea(;7j#W?`R_v% z3gmANpw%k)S_-t$0wbUTHP7h};eK-HfuyGr0xN58$AlstR>X-7G7>9rMWF{jpa;pa zbP3`xS~0E@mOfQ20_59Ok-1BjBXa)Z>4bo@LA6Ilqg{P?pSdF39nf@3ST3njl2arL zbgf~N8pAd(LKw0fJE2ev!A)pWycw_nahW;!;Lg{Rx|Xi^n!i2x(?(5B@@Wrc@YwL7 z0i)2MKOQUKmJQczR0;(5m4ugPCjOa=t>0F=Q*Ay*e7z7&E#3m0t$SRarIDmNQ`QD> z3cCD6MrtfBIFns!Sv_b-arm+?o|Qeod1xS^wIslveTjn1n5nuDr3j*IQ+d23Wy^Yi zqy|y1C(exp`E&oFAM7hF=&9nSXWgA)+1D;bnFUtMw-yU z;R~k$8&~Hy25v+^cqGDlKN&RG7#$(av%`Pj$4!iW!ebmVl+myK41N%@h{ayqZp^kz ZU_=^BPO>bc{{U0-tNparseOsmFile(_osmFilePath); + return true; +} - if(_mapLoadedFlag == 0){ - _osmParser->parseOsmFile(_osmFilePath); - _mapLoadedFlag = 1; +void CityMapGeometry::updateViewer() +{ + clear(); + + if(!_osmParser){ + return; } - if(_mapLoadedFlag){ + if(loadOsmMap()){ _vertexData = _osmParser->buildingToMesh(); int stride = 3 * sizeof(float); @@ -72,7 +78,6 @@ void CityMapGeometry::updateData() addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0, QQuick3DGeometry::Attribute::F32Type); - } update(); } diff --git a/src/Viewer3D/CityMapGeometry.h b/src/Viewer3D/CityMapGeometry.h index b549c94eff2..f0c8f3cd81f 100644 --- a/src/Viewer3D/CityMapGeometry.h +++ b/src/Viewer3D/CityMapGeometry.h @@ -29,14 +29,15 @@ class CityMapGeometry : public QQuick3DGeometry OsmParser* osmParser(){ return _osmParser;} void setOsmParser(OsmParser* newOsmParser); + bool loadOsmMap(); + signals: void modelNameChanged(); void osmFilePathChanged(); - void gpsRefChanged(); void osmParserChanged(); private: - void updateData(); + void updateViewer(); QString _modelName; QString _osmFilePath; diff --git a/src/Viewer3D/OsmParser.cc b/src/Viewer3D/OsmParser.cc index 46fbcd0f771..014ca5442d8 100644 --- a/src/Viewer3D/OsmParser.cc +++ b/src/Viewer3D/OsmParser.cc @@ -69,8 +69,8 @@ void OsmParser::parseOsmFile(QString filePath) component = component.nextSibling().toElement(); } _mapLoadedFlag = true; - emit newMapLoaded(); - qDebug() << _mapBuildings.size() << " Buildings added to the 3D viewer!!!"; + emit mapChanged(); + qDebug() << _mapBuildings.size() << " Buildings loaded!!!"; } void OsmParser::decodeNodeTags(QDomElement &xmlComponent, QMap &nodeMap) diff --git a/src/Viewer3D/OsmParser.h b/src/Viewer3D/OsmParser.h index 77ee0eba26d..0c101afeab7 100644 --- a/src/Viewer3D/OsmParser.h +++ b/src/Viewer3D/OsmParser.h @@ -57,7 +57,7 @@ class OsmParser : public QObject signals: void gpsRefChanged(QGeoCoordinate newGpsRef); - void newMapLoaded(); + void mapChanged(); void buildingLevelHeightChanged(void); }; diff --git a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml index e0cc6b8bd65..ef3ba0bb90d 100644 --- a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml @@ -11,7 +11,7 @@ Node { property real _tilt: 0.001 property real _pan: 0.001 - property real _zoom: 1000 + property real _zoom: 1500 DirectionalLight { @@ -58,6 +58,10 @@ Node { id: cameraPerspectiveOne + eulerRotation{ + x: -90 + } + } } } diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml index a989329d325..597841a0976 100644 --- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml @@ -21,7 +21,54 @@ import QGroundControl.Vehicle View3D { id: topView property var viewer3DManager: null + property bool viewer3DOpen: false + property real rotationSpeed: 0.1 + property real movementSpeed: 1 + property real zoomSpeed: 0.3 + function rotateCamera(newPose: vector2d, lastPose: vector2d) { + let rotation_vec = Qt.vector2d(newPose.y - lastPose.y, newPose.x - lastPose.x); + + let dx_l = rotation_vec.x * rotationSpeed + let dy_l = rotation_vec.y * rotationSpeed + + standAloneScene.cameraOneRotation.x += dx_l + standAloneScene.cameraOneRotation.y += dy_l + } + + function moveCamera(newPose: vector2d, lastPose: vector2d) { + let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180) + let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180) + + let dx_l = (newPose.x - lastPose.x) * movementSpeed + let dy_l = (newPose.y - lastPose.y) * movementSpeed + + //Note: Rotation Matrix is computed as: R = R(-_pitch) * R(_roll) + // Then the corerxt tramslation is: d = R * [dx_l; dy_l; dz_l] + + let dx = dx_l * Math.cos(_pitch) - dy_l * Math.sin(_pitch) * Math.sin(_roll) + let dy = dy_l * Math.cos(_roll) + let dz = dx_l * Math.sin(_pitch) + dy_l * Math.cos(_pitch) * Math.sin(_roll) + + standAloneScene.cameraTwoPosition.x -= dx + standAloneScene.cameraTwoPosition.y += dy + standAloneScene.cameraTwoPosition.z += dz + } + + function zoomCamera(zoomValue){ + let dz_l = zoomValue * zoomSpeed; + + let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180) + let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180) + + let dx = -dz_l * Math.cos(_roll) * Math.sin(_pitch) + let dy = -dz_l * Math.sin(_roll) + let dz = dz_l * Math.cos(_pitch) * Math.cos(_roll) + + standAloneScene.cameraTwoPosition.x -= dx + standAloneScene.cameraTwoPosition.y += dy + standAloneScene.cameraTwoPosition.z += dz + } camera: standAloneScene.cameraOne importScene: CameraLightModel{ @@ -31,7 +78,7 @@ View3D { // renderMode: View3D.Inline environment: SceneEnvironment { - clearColor: "white" + clearColor: "#F9F9F9" backgroundMode: SceneEnvironment.Color } @@ -78,66 +125,102 @@ View3D { vehicle3DLoader.sourceComponent = vehicle3DComponent } - MouseArea{ - property real _transferSpeed: 1 - property real _rotationSpeed: 0.1 - property real _zoomSpeed: 0.3 + DragHandler { + property bool _isMoving: false property point _lastPose; - anchors.fill: parent - acceptedButtons: Qt.AllButtons; - - - onPressed: (mouse)=> { - _lastPose = Qt.point(mouse.x, mouse.y); - } - - onPositionChanged: (mouse)=> { - let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180) - let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180) - // let yaw = standAloneScene.cameraOneRotation.z * (3.1415/180) - - if (mouse.buttons === Qt.LeftButton) { // Left button for translate - let dx_l = (mouse.x - _lastPose.x) * _transferSpeed - let dy_l = (mouse.y - _lastPose.y) * _transferSpeed + id: cameraMovementDragHandler + target: null + acceptedModifiers: Qt.NoModifier + acceptedButtons: Qt.LeftButton + enabled: viewer3DOpen - //Note: Rotation Matrix is computed as: R = R(-_pitch) * R(_roll) - // Then the corerxt tramslation is: d = R * [dx_l; dy_l; dz_l] + onCentroidChanged: { + if(_isMoving){ + moveCamera(centroid.position, _lastPose); + _lastPose = Qt.point(centroid.position.x, centroid.position.y); + } + } - let dx = dx_l * Math.cos(_pitch) - dy_l * Math.sin(_pitch) * Math.sin(_roll) - let dy = dy_l * Math.cos(_roll) - let dz = dx_l * Math.sin(_pitch) + dy_l * Math.cos(_pitch) * Math.sin(_roll) + onActiveChanged: { + if(active){ // When mouse is pressed + _lastPose = Qt.point(centroid.position.x, centroid.position.y); + _isMoving = true + }else{ // When mouse is released + _isMoving = false + } + } + } - standAloneScene.cameraTwoPosition.x -= dx - standAloneScene.cameraTwoPosition.y += dy - standAloneScene.cameraTwoPosition.z += dz - }else if (mouse.buttons === Qt.RightButton){ // Right button for rotation + DragHandler { + property bool _isRotating: false + property point _lastPose; - let rotation_vec = Qt.vector2d(mouse.y - _lastPose.y, mouse.x - _lastPose.x); + id: cameraRotationDragHandler + target: null + acceptedModifiers: Qt.NoModifier + acceptedButtons: Qt.RightButton + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + enabled: viewer3DOpen + + onCentroidChanged: { + if(_isRotating){ + rotateCamera(centroid.position, _lastPose); + _lastPose = Qt.point(centroid.position.x, centroid.position.y); + } + } - let dx_l = rotation_vec.x * _rotationSpeed - let dy_l = rotation_vec.y * _rotationSpeed + onActiveChanged: { + if(active){ // When mouse is pressed + _lastPose = Qt.point(centroid.position.x, centroid.position.y); + _isRotating = true + }else{// When mouse is released + _isRotating = false + } + } + } - standAloneScene.cameraOneRotation.x += dx_l - standAloneScene.cameraOneRotation.y += dy_l + PinchHandler { + id: zoomRotationPinchHandler + target: null - } - _lastPose = Qt.point(mouse.x, mouse.y) - } + property bool _isRotating: false + property point _lastPose; + property real _lastZoomValue; + enabled: viewer3DOpen - onWheel: (wheel)=> { - let dz_l = -wheel.angleDelta.y * _zoomSpeed + onCentroidChanged: { + if(_isRotating){ + rotateCamera(centroid.position, _lastPose); + _lastPose = Qt.point(centroid.position.x, centroid.position.y); + } + } - let _roll = standAloneScene.cameraOneRotation.x * (3.1415/180) - let _pitch = standAloneScene.cameraOneRotation.y * (3.1415/180) + onActiveChanged: { + if (active) { + _lastPose = Qt.point(centroid.position.x, centroid.position.y); + _lastZoomValue = 0 + _isRotating = true; + } else { + _isRotating = false; + } + } + onActiveScaleChanged: { + let zoomValue = (activeScale > 1)?(activeScale - 1):(-((1/activeScale) - 1)) + zoomCamera(- 1000 * (zoomValue - _lastZoomValue)) + _lastZoomValue = zoomValue + } + } - let dx = -dz_l * Math.cos(_roll) * Math.sin(_pitch) - let dy = -dz_l * Math.sin(_roll) - let dz = dz_l * Math.cos(_pitch) * Math.cos(_roll) + WheelHandler { + id: wheelHandler + orientation: Qt.Vertical + target: null + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + enabled: viewer3DOpen - standAloneScene.cameraTwoPosition.x -= dx - standAloneScene.cameraTwoPosition.y += dy - standAloneScene.cameraTwoPosition.z += dz + onWheel: event => { + zoomCamera(-event.angleDelta.y) } } } diff --git a/src/Viewer3D/Viewer3D/Viewer3D.qml b/src/Viewer3D/Viewer3D/Viewer3D.qml index 309742dcb84..4c5fbe019f9 100644 --- a/src/Viewer3D/Viewer3D/Viewer3D.qml +++ b/src/Viewer3D/Viewer3D/Viewer3D.qml @@ -17,8 +17,20 @@ Item{ property bool viewer3DOpen: false property bool settingMenuOpen: false - Viewer3DManager{ - id: _viewer3DManager + Component{ + id: viewer3DManagerComponent + + Viewer3DManager{ + id: _viewer3DManager + } + } + + Loader{ + id: view3DManagerLoader + + onLoaded: { + view3DLoader.source = "Models3D/Viewer3DModel.qml" + } } Loader{ @@ -26,12 +38,19 @@ Item{ anchors.fill: parent onLoaded: { - item.viewer3DManager = _viewer3DManager + item.viewer3DManager = view3DManagerLoader.item } } + Binding{ + target: view3DLoader.item + property: "viewer3DOpen" + value: viewer3DOpen + when: view3DLoader.status == Loader.Ready + } + onViewer3DOpenChanged: { - view3DLoader.source = "Models3D/Viewer3DModel.qml" + view3DManagerLoader.sourceComponent = viewer3DManagerComponent if(viewer3DOpen){ viewer3DBody.z = 1 }else{ @@ -50,12 +69,12 @@ Item{ QGCPopupDialog{ id: settingMenuDialog - title: qsTr("3D view setting") + title: qsTr("3D view settings") buttons: Dialog.Ok | Dialog.Cancel Viewer3DSettingMenu{ id: viewer3DSettingMenu - viewer3DManager: _viewer3DManager + viewer3DManager: view3DManagerLoader.item visible: true } diff --git a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml b/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml index dac15666fd8..24130aebd4c 100644 --- a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml +++ b/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml @@ -11,7 +11,7 @@ import QGroundControl.Viewer3D /// @author Omid Esrafilian -Rectangle { +Flickable { signal menuClosed(bool accept) @@ -20,139 +20,132 @@ Rectangle { id: window_body clip: true - color: qgcPal.window visible: true width: Screen.width * 0.25 - height: Screen.width * 0.15 - - QGCPalette { - id: qgcPal - colorGroupEnabled: enabled - } - - QGCLabel { - id: map_file_label - Layout.fillWidth: true - wrapMode: Text.WordWrap - visible: true - text: qsTr("3D Map File:") - anchors.left: parent.left - anchors.top: parent.top - anchors.leftMargin: leftMarginSpace - anchors.topMargin: ScreenTools.defaultFontPixelWidth * 3 - } - - QGCButton { - id: map_file_btn - anchors.right: map_file_text_feild.right - anchors.top: map_file_text_feild.bottom - anchors.topMargin: ScreenTools.defaultFontPixelWidth * 2 - anchors.rightMargin: ScreenTools.defaultFontPixelWidth - - visible: true - text: qsTr("Select File") - - onClicked: { - fileDialog.openForLoad() - } - - QGCFileDialog { - id: fileDialog - - nameFilters: [qsTr("OpenStreetMap files (*.osm)")] - title: qsTr("Select map file") - onAcceptedForLoad: (file) => { - map_file_text_feild.text = file - } - } - } - - QGCTextField { - id: map_file_text_feild - height: ScreenTools.defaultFontPixelWidth * 4.5 - unitsLabel: "" - showUnits: false - visible: true - - anchors.verticalCenter: map_file_label.verticalCenter - anchors.right: parent.right - anchors.left: map_file_label.right - anchors.rightMargin: 20 - anchors.leftMargin: 20 - readOnly: true - - text: (viewer3DManager)?(viewer3DManager.viewer3DSetting.osmFilePath.rawValue):("nan") - } - - QGCLabel { - id: bld_level_height - Layout.fillWidth: true - wrapMode: Text.WordWrap - visible: true - text: qsTr("Average Building Level Height:") - anchors.left: parent.left - anchors.top: map_file_btn.bottom - anchors.leftMargin: leftMarginSpace - anchors.topMargin: ScreenTools.defaultFontPixelWidth * 2 - } - - QGCTextField { - id: bld_level_height_textfeild - width: ScreenTools.defaultFontPixelWidth * 15 - unitsLabel: "m" - showUnits: true - numericValuesOnly: true - visible: true - - anchors.verticalCenter: bld_level_height.verticalCenter - anchors.left: bld_level_height.right - anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 - - text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue)):("nan") - - validator: RegularExpressionValidator{ - regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ + height: Screen.height * 0.2 + contentWidth: width; + contentHeight: main_column.height + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar {} + + Column { + id: main_column + anchors{ + right: parent.right + left: parent.left + margins: ScreenTools.defaultFontPixelWidth } - - onAccepted: - { - focus = false + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + + RowLayout{ + anchors{ + right: parent.right + left: parent.left + } + QGCLabel { + wrapMode: Text.WordWrap + visible: true + text: qsTr("3D Map File:") + } + + QGCTextField { + id: map_file_text_feild + height: ScreenTools.defaultFontPixelWidth * 4.5 + unitsLabel: "" + showUnits: false + visible: true + Layout.fillWidth: true + readOnly: true + + text: (viewer3DManager)?(viewer3DManager.viewer3DSetting.osmFilePath.rawValue):("nan") + } } - } - - QGCLabel { - id: height_bias_label - Layout.fillWidth: true - wrapMode: Text.WordWrap - visible: true - text: qsTr("Vehicles Altitude Bias:") - anchors.left: parent.left - anchors.top: bld_level_height.bottom - anchors.leftMargin: leftMarginSpace - anchors.topMargin: ScreenTools.defaultFontPixelWidth * 4 - } - - QGCTextField { - id: height_bias_textfeild - width: ScreenTools.defaultFontPixelWidth * 15 - unitsLabel: "m" - showUnits: true - numericValuesOnly: true - visible: true - - anchors.verticalCenter: height_bias_label.verticalCenter - anchors.left: height_bias_label.right - anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 2 - - text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.altitudeBias.rawValue)):("nan") - - validator: RegularExpressionValidator{ - regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ + RowLayout{ + anchors{ + right: parent.right + left: parent.left + } + QGCButton { + id: map_file_btn + Layout.alignment: Qt.AlignRight + + visible: true + text: qsTr("Select File") + + onClicked: { + fileDialog.openForLoad() + } + + QGCFileDialog { + id: fileDialog + + nameFilters: [qsTr("OpenStreetMap files (*.osm)")] + title: qsTr("Select map file") + onAcceptedForLoad: (file) => { + map_file_text_feild.text = file + } + } + } } - onAccepted: - { - focus = false + GridLayout{ + anchors{ + left: parent.left + } + columns: 2 + columnSpacing: ScreenTools.defaultFontPixelHeight + rowSpacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + wrapMode: Text.WordWrap + text: qsTr("Average Building Level Height:") + } + + QGCTextField{ + id: bld_level_height_textfeild + width: ScreenTools.defaultFontPixelWidth * 15 + unitsLabel: "m" + showUnits: true + numericValuesOnly: true + visible: true + + text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue)):("nan") + + validator: RegularExpressionValidator{ + regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ + } + + onAccepted: + { + focus = false + } + } + + QGCLabel { + wrapMode: Text.WordWrap + visible: true + text: qsTr("Vehicles Altitude Bias:") + } + + QGCTextField { + id: height_bias_textfeild + width: ScreenTools.defaultFontPixelWidth * 15 + unitsLabel: "m" + showUnits: true + numericValuesOnly: true + visible: true + + text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.altitudeBias.rawValue)):("nan") + + validator: RegularExpressionValidator{ + regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ + } + + onAccepted: + { + focus = false + } + } } } diff --git a/src/Viewer3D/Viewer3DQmlBackend.cc b/src/Viewer3D/Viewer3DQmlBackend.cc index b3186cf0404..1fd7f59ac00 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.cc +++ b/src/Viewer3D/Viewer3DQmlBackend.cc @@ -3,9 +3,17 @@ #include #include +#include "QGCApplication.h" + +#define GPS_REF_NOT_SET 0 +#define GPS_REF_SET_BY_MAP 1 +#define GPS_REF_SET_BY_VEHICLE 2 + Viewer3DQmlBackend::Viewer3DQmlBackend(QObject *parent) : QObject{parent} { + _gpsRefSet = GPS_REF_NOT_SET; + _activeVehicle = nullptr; } void Viewer3DQmlBackend::init(Viewer3DSettings *viewerSettingThr, OsmParser* osmThr) @@ -14,24 +22,47 @@ void Viewer3DQmlBackend::init(Viewer3DSettings *viewerSettingThr, OsmParser* osm _osmFilePath = viewerSettingThr->osmFilePath()->rawValue().toString(); _osmParserThread = osmThr; + _activeVehicleChangedEvent(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()); + connect(_osmParserThread, &OsmParser::gpsRefChanged, this, &Viewer3DQmlBackend::_gpsRefChangedEvent); + connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::activeVehicleChanged, this, &Viewer3DQmlBackend::_activeVehicleChangedEvent); } -void Viewer3DQmlBackend::setGpsRef(const QGeoCoordinate &gpsRef) +void Viewer3DQmlBackend::_activeVehicleChangedEvent(Vehicle *vehicle) { - if(_gpsRef == gpsRef){ - return; + if(_activeVehicle){ + disconnect(_activeVehicle, &Vehicle::coordinateChanged, this, &Viewer3DQmlBackend::_activeVehicleCoordinateChanged); } - _gpsRef = gpsRef; - emit gpsRefChanged(); + _activeVehicle = vehicle; + if(!_activeVehicle){ // means that all the vehicle have been disconnected + if(_gpsRefSet == GPS_REF_SET_BY_VEHICLE){ + _gpsRefSet = GPS_REF_NOT_SET; + } + }else{ + connect(_activeVehicle, &Vehicle::coordinateChanged, this, &Viewer3DQmlBackend::_activeVehicleCoordinateChanged); + } +} + +void Viewer3DQmlBackend::_activeVehicleCoordinateChanged(QGeoCoordinate newCoordinate) +{ + if(_gpsRefSet == GPS_REF_NOT_SET){ + if(newCoordinate.latitude() && newCoordinate.longitude()){ + _gpsRef = newCoordinate; + _gpsRef.setAltitude(0); + _gpsRefSet = GPS_REF_SET_BY_VEHICLE; + emit gpsRefChanged(); + + qDebug() << "3D viewer gps reference set by vehicles:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude(); + } + } } void Viewer3DQmlBackend::_gpsRefChangedEvent(QGeoCoordinate newGpsRef) { _gpsRef = newGpsRef; - + _gpsRefSet = GPS_REF_SET_BY_MAP; emit gpsRefChanged(); - qDebug() << "3D map gps reference:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude(); + qDebug() << "3D viewer gps reference set by osm map:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude(); } diff --git a/src/Viewer3D/Viewer3DQmlBackend.h b/src/Viewer3D/Viewer3DQmlBackend.h index b248ad83dae..bcbda28d0c7 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.h +++ b/src/Viewer3D/Viewer3DQmlBackend.h @@ -24,7 +24,6 @@ class Viewer3DQmlBackend : public QObject void init(Viewer3DSettings* viewerSettingThr, OsmParser* osmThr=nullptr); QGeoCoordinate gpsRef(){return _gpsRef;} - void setGpsRef(const QGeoCoordinate& gpsRef); signals: void gpsRefChanged(); @@ -36,10 +35,16 @@ class Viewer3DQmlBackend : public QObject QString _osmFilePath; QGeoCoordinate _gpsRef; + uint8_t _gpsRefSet; float _altitudeBias; + Vehicle *_activeVehicle; + + protected slots: void _gpsRefChangedEvent(QGeoCoordinate newGpsRef); + void _activeVehicleChangedEvent(Vehicle* vehicle); + void _activeVehicleCoordinateChanged(QGeoCoordinate newCoordinate); }; #endif // Viewer3DQmlBackend_H From 5d1421fb69227d1647c1f376daec9c74f0d03eda Mon Sep 17 00:00:00 2001 From: "esrafilian.omid" Date: Wed, 21 Feb 2024 10:53:24 +0100 Subject: [PATCH 2/5] docs is updated with how to see a complete list of all components in Qt-maintenance tool --- docs/en/qgc-dev-guide/getting_started/index.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/en/qgc-dev-guide/getting_started/index.md b/docs/en/qgc-dev-guide/getting_started/index.md index e92ffde4ad6..db0241d6711 100644 --- a/docs/en/qgc-dev-guide/getting_started/index.md +++ b/docs/en/qgc-dev-guide/getting_started/index.md @@ -78,6 +78,10 @@ To install Qt: Then install the following components: +::: info +To see a complete list of all available components in the installer _Select Components_ dialog, you might need to check the **"Archive"** box in the right column under the **"Categories"** tab, then click on **"Filter"**. +::: + - Under _Qt _{{ $frontmatter.qt_version }}_ select: - Depending on the OS you want to build for: - **Windows**: _MSVC 2019 64 bit_ From 421464a58be924c9c10a630c3174bd8094c1aef3 Mon Sep 17 00:00:00 2001 From: "esrafilian.omid" Date: Thu, 22 Feb 2024 14:22:48 +0100 Subject: [PATCH 3/5] Viewer3DSettingsMenu is changed to Viewer3DSettingsDialog --- qgroundcontrol.qrc | 2 +- .../FlyViewToolStripActionList.qml | 4 +- .../Viewer3D/Models3D/CameraLightModel.qml | 1 + src/Viewer3D/Viewer3D/Viewer3D.qml | 39 ++++------ ...ingMenu.qml => Viewer3DSettingsDialog.qml} | 71 +++++++------------ 5 files changed, 43 insertions(+), 74 deletions(-) rename src/Viewer3D/Viewer3D/{Viewer3DSettingMenu.qml => Viewer3DSettingsDialog.qml} (68%) diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index de1435f8505..2ce89e879f8 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -315,7 +315,7 @@ src/PlanView/VTOLLandingPatternEditor.qml src/comm/MockLinkOptionsDlg.qml src/FlightDisplay/FlyViewInsetViewer.qml - src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml + src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml src/Viewer3D/Viewer3D/Viewer3D.qml src/Viewer3D/Viewer3D/qmldir src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml diff --git a/src/FlightDisplay/FlyViewToolStripActionList.qml b/src/FlightDisplay/FlyViewToolStripActionList.qml index 367d0700544..023a1fd2be5 100644 --- a/src/FlightDisplay/FlyViewToolStripActionList.qml +++ b/src/FlightDisplay/FlyViewToolStripActionList.qml @@ -55,7 +55,7 @@ ToolStripActionList { iconSource = "/qmlimages/Viewer3D/City3DMapIcon.svg" text = qsTr("3D View") city_map_setting_icon.enabled = false - viewer3DWindow.settingMenuOpen = false + viewer3DWindow.settingsDialogOpen = false city_map_setting_icon.checked = false } }, @@ -66,7 +66,7 @@ ToolStripActionList { enabled: false visible: enabled onTriggered:{ - viewer3DWindow.settingMenuOpen = !viewer3DWindow.settingMenuOpen + viewer3DWindow.settingsDialogOpen = !viewer3DWindow.settingsDialogOpen } }, PreFlightCheckListShowAction { onTriggered: displayPreFlightChecklist() }, diff --git a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml index ef3ba0bb90d..6350f796d63 100644 --- a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml @@ -57,6 +57,7 @@ Node { PerspectiveCamera { id: cameraPerspectiveOne + clipFar: 100000 eulerRotation{ x: -90 diff --git a/src/Viewer3D/Viewer3D/Viewer3D.qml b/src/Viewer3D/Viewer3D/Viewer3D.qml index 4c5fbe019f9..e6324748d68 100644 --- a/src/Viewer3D/Viewer3D/Viewer3D.qml +++ b/src/Viewer3D/Viewer3D/Viewer3D.qml @@ -7,15 +7,16 @@ import QGroundControl.Palette import QGroundControl.ScreenTools import QGroundControl.Controls -// 3D Viewer modules import QGroundControl.Viewer3D import Viewer3D.Models3D +/// @author Omid Esrafilian + Item{ id: viewer3DBody property bool viewer3DOpen: false - property bool settingMenuOpen: false + property bool settingsDialogOpen: false Component{ id: viewer3DManagerComponent @@ -58,36 +59,22 @@ Item{ } } - onSettingMenuOpenChanged:{ - if(settingMenuOpen === true){ - settingMenuComponent.createObject(mainWindow).open() + onSettingsDialogOpenChanged:{ + if(settingsDialogOpen === true){ + settingsDialogComponent.createObject(mainWindow).open() } } Component { - id: settingMenuComponent - - QGCPopupDialog{ - id: settingMenuDialog - title: qsTr("3D view settings") - buttons: Dialog.Ok | Dialog.Cancel + id: settingsDialogComponent - Viewer3DSettingMenu{ - id: viewer3DSettingMenu - viewer3DManager: view3DManagerLoader.item - visible: true - } - - onRejected: { - settingMenuOpen = false - viewer3DSettingMenu.menuClosed(false) - settingMenuDialog.close() - } + Viewer3DSettingsDialog{ + id: view3DSettingsDialog + viewer3DManager: view3DManagerLoader.item + visible: true - onAccepted: { - settingMenuOpen = false - viewer3DSettingMenu.menuClosed(true) - settingMenuDialog.close() + onClosed:{ + settingsDialogOpen = false } } } diff --git a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml b/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml similarity index 68% rename from src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml rename to src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml index 24130aebd4c..64b4c4a7d30 100644 --- a/src/Viewer3D/Viewer3D/Viewer3DSettingMenu.qml +++ b/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml @@ -7,41 +7,24 @@ import QGroundControl.Palette import QGroundControl.ScreenTools import QGroundControl.Controls -import QGroundControl.Viewer3D /// @author Omid Esrafilian -Flickable { +QGCPopupDialog{ + property var viewer3DManager: null - signal menuClosed(bool accept) + title: qsTr("3D view settings") + buttons: Dialog.Ok | Dialog.Cancel - property var viewer3DManager: null - property int leftMarginSpace: ScreenTools.defaultFontPixelWidth - - id: window_body - clip: true - visible: true - width: Screen.width * 0.25 - height: Screen.height * 0.2 - contentWidth: width; - contentHeight: main_column.height - boundsBehavior: Flickable.StopAtBounds - ScrollBar.vertical: ScrollBar {} - - Column { - id: main_column - anchors{ - right: parent.right - left: parent.left - margins: ScreenTools.defaultFontPixelWidth - } - spacing: ScreenTools.defaultFontPixelHeight * 0.5 + ColumnLayout { + property int leftMarginSpace: ScreenTools.defaultFontPixelWidth + id: window_body + clip: true + visible: true + spacing: ScreenTools.defaultFontPixelHeight / 2 RowLayout{ - anchors{ - right: parent.right - left: parent.left - } + Layout.fillWidth: true QGCLabel { wrapMode: Text.WordWrap visible: true @@ -55,19 +38,19 @@ Flickable { showUnits: false visible: true Layout.fillWidth: true + implicitWidth: ScreenTools.defaultFontPixelWidth * 50 + + readOnly: true text: (viewer3DManager)?(viewer3DManager.viewer3DSetting.osmFilePath.rawValue):("nan") } } RowLayout{ - anchors{ - right: parent.right - left: parent.left - } + Layout.alignment: Qt.AlignRight + QGCButton { id: map_file_btn - Layout.alignment: Qt.AlignRight visible: true text: qsTr("Select File") @@ -89,15 +72,14 @@ Flickable { } GridLayout{ - anchors{ - left: parent.left - } columns: 2 columnSpacing: ScreenTools.defaultFontPixelHeight rowSpacing: ScreenTools.defaultFontPixelWidth + Layout.fillWidth: true QGCLabel { wrapMode: Text.WordWrap + Layout.fillWidth: true text: qsTr("Average Building Level Height:") } @@ -124,6 +106,7 @@ Flickable { QGCLabel { wrapMode: Text.WordWrap visible: true + Layout.fillWidth: true text: qsTr("Vehicles Altitude Bias:") } @@ -149,16 +132,14 @@ Flickable { } } - onMenuClosed: function (accept){ - if(accept === true){ - viewer3DManager.qmlBackend.osmFilePath = map_file_text_feild.text - viewer3DManager.qmlBackend.altitudeBias = parseFloat(height_bias_textfeild.text) + onAccepted: { + viewer3DManager.qmlBackend.osmFilePath = map_file_text_feild.text + viewer3DManager.qmlBackend.altitudeBias = parseFloat(height_bias_textfeild.text) - viewer3DManager.viewer3DSetting.osmFilePath.rawValue = map_file_text_feild.text - viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue = parseFloat(bld_level_height_textfeild.text) - viewer3DManager.viewer3DSetting.altitudeBias.rawValue = parseFloat(height_bias_textfeild.text) + viewer3DManager.viewer3DSetting.osmFilePath.rawValue = map_file_text_feild.text + viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue = parseFloat(bld_level_height_textfeild.text) + viewer3DManager.viewer3DSetting.altitudeBias.rawValue = parseFloat(height_bias_textfeild.text) - viewer3DManager.osmParser.buildingLevelHeight = parseFloat(bld_level_height_textfeild.text) - } + viewer3DManager.osmParser.buildingLevelHeight = parseFloat(bld_level_height_textfeild.text) } } From 23d5f3374205fc877304d3905f76736586b726a0 Mon Sep 17 00:00:00 2001 From: "esrafilian.omid" Date: Fri, 23 Feb 2024 23:27:33 +0100 Subject: [PATCH 4/5] adding Viewr3DSettings to SettingsManager --- src/FlightDisplay/FlyView.qml | 1 + .../FlyViewToolStripActionList.qml | 20 ++--- src/Settings/SettingsManager.cc | 2 + src/Settings/SettingsManager.h | 4 + src/Viewer3D/CityMapGeometry.cc | 14 +++- src/Viewer3D/CityMapGeometry.h | 10 ++- src/Viewer3D/OsmParser.cc | 22 +++-- src/Viewer3D/OsmParser.h | 12 ++- .../Viewer3D/Models3D/Viewer3DModel.qml | 11 ++- .../Models3D/Viewer3DVehicleItems.qml | 11 ++- src/Viewer3D/Viewer3D/Viewer3D.qml | 41 ++++----- .../Viewer3D/Viewer3DSettingsDialog.qml | 84 ++++--------------- src/Viewer3D/Viewer3DManager.cc | 5 +- src/Viewer3D/Viewer3DManager.h | 5 +- src/Viewer3D/Viewer3DQmlBackend.cc | 7 +- src/Viewer3D/Viewer3DQmlBackend.h | 11 +-- 16 files changed, 115 insertions(+), 145 deletions(-) diff --git a/src/FlightDisplay/FlyView.qml b/src/FlightDisplay/FlyView.qml index 9092014341b..a956f605206 100644 --- a/src/FlightDisplay/FlyView.qml +++ b/src/FlightDisplay/FlyView.qml @@ -165,6 +165,7 @@ Item { pipMode: !_mainWindowIsMap toolInsets: customOverlay.totalToolInsets mapName: "FlightDisplayView" + enabled: !viewer3DWindow.isOpen } FlyViewVideo { diff --git a/src/FlightDisplay/FlyViewToolStripActionList.qml b/src/FlightDisplay/FlyViewToolStripActionList.qml index 023a1fd2be5..3961c25c771 100644 --- a/src/FlightDisplay/FlyViewToolStripActionList.qml +++ b/src/FlightDisplay/FlyViewToolStripActionList.qml @@ -31,31 +31,25 @@ ToolStripActionList { text: qsTr("3D View") iconSource: "/qmlimages/Viewer3D/City3DMapIcon.svg" onTriggered:{ - if(viewer3DWindow.viewer3DOpen === false) - { + if(viewer3DWindow.isOpen === false){ show3dMap(); - } - else - { + }else{ showFlyMap(); } } - function show3dMap() - { - viewer3DWindow.viewer3DOpen = true + function show3dMap(){ + viewer3DWindow.open() map_icon.iconSource = "/qmlimages/PaperPlane.svg" text= qsTr("Fly") city_map_setting_icon.enabled = true } - function showFlyMap() - { - viewer3DWindow.viewer3DOpen = false + function showFlyMap(){ + viewer3DWindow.close() iconSource = "/qmlimages/Viewer3D/City3DMapIcon.svg" text = qsTr("3D View") city_map_setting_icon.enabled = false - viewer3DWindow.settingsDialogOpen = false city_map_setting_icon.checked = false } }, @@ -66,7 +60,7 @@ ToolStripActionList { enabled: false visible: enabled onTriggered:{ - viewer3DWindow.settingsDialogOpen = !viewer3DWindow.settingsDialogOpen + viewer3DWindow.showSettingsDialog() } }, PreFlightCheckListShowAction { onTriggered: displayPreFlightChecklist() }, diff --git a/src/Settings/SettingsManager.cc b/src/Settings/SettingsManager.cc index 1f4366d814c..488913e832d 100644 --- a/src/Settings/SettingsManager.cc +++ b/src/Settings/SettingsManager.cc @@ -29,6 +29,7 @@ SettingsManager::SettingsManager(QGCApplication* app, QGCToolbox* toolbox) , _adsbVehicleManagerSettings (nullptr) , _batteryIndicatorSettings (nullptr) , _mapsSettings (nullptr) + , _viewer3DSettings (nullptr) #if !defined(NO_ARDUPILOT_DIALECT) , _apmMavlinkStreamRateSettings (nullptr) #endif @@ -58,6 +59,7 @@ void SettingsManager::setToolbox(QGCToolbox *toolbox) _adsbVehicleManagerSettings = new ADSBVehicleManagerSettings (this); _batteryIndicatorSettings = new BatteryIndicatorSettings (this); _mapsSettings = new MapsSettings (this); + _viewer3DSettings = new Viewer3DSettings (this); #if !defined(NO_ARDUPILOT_DIALECT) _apmMavlinkStreamRateSettings = new APMMavlinkStreamRateSettings(this); #endif diff --git a/src/Settings/SettingsManager.h b/src/Settings/SettingsManager.h index b44f93217da..fc089213452 100644 --- a/src/Settings/SettingsManager.h +++ b/src/Settings/SettingsManager.h @@ -32,6 +32,7 @@ #include "BatteryIndicatorSettings.h" #include #include "RemoteIDSettings.h" +#include "Viewer3DSettings.h" /// Provides access to all app settings class SettingsManager : public QGCTool @@ -56,6 +57,7 @@ class SettingsManager : public QGCTool Q_PROPERTY(QObject* adsbVehicleManagerSettings READ adsbVehicleManagerSettings CONSTANT) Q_PROPERTY(QObject* batteryIndicatorSettings READ batteryIndicatorSettings CONSTANT) Q_PROPERTY(QObject* mapsSettings READ mapsSettings CONSTANT) + Q_PROPERTY(QObject* viewer3DSettings READ viewer3DSettings CONSTANT) #if !defined(NO_ARDUPILOT_DIALECT) Q_PROPERTY(QObject* apmMavlinkStreamRateSettings READ apmMavlinkStreamRateSettings CONSTANT) #endif @@ -78,6 +80,7 @@ class SettingsManager : public QGCTool ADSBVehicleManagerSettings* adsbVehicleManagerSettings (void) { return _adsbVehicleManagerSettings; } BatteryIndicatorSettings* batteryIndicatorSettings (void) { return _batteryIndicatorSettings; } MapsSettings* mapsSettings (void) { return _mapsSettings; } + Viewer3DSettings* viewer3DSettings (void) { return _viewer3DSettings; } #if !defined(NO_ARDUPILOT_DIALECT) APMMavlinkStreamRateSettings* apmMavlinkStreamRateSettings(void) { return _apmMavlinkStreamRateSettings; } #endif @@ -98,6 +101,7 @@ class SettingsManager : public QGCTool ADSBVehicleManagerSettings* _adsbVehicleManagerSettings; BatteryIndicatorSettings* _batteryIndicatorSettings; MapsSettings* _mapsSettings; + Viewer3DSettings* _viewer3DSettings; #if !defined(NO_ARDUPILOT_DIALECT) APMMavlinkStreamRateSettings* _apmMavlinkStreamRateSettings; #endif diff --git a/src/Viewer3D/CityMapGeometry.cc b/src/Viewer3D/CityMapGeometry.cc index 3d9db62657b..0bec274b8ee 100644 --- a/src/Viewer3D/CityMapGeometry.cc +++ b/src/Viewer3D/CityMapGeometry.cc @@ -2,6 +2,9 @@ #include +#include "QGCApplication.h" +#include "SettingsManager.h" + CityMapGeometry::CityMapGeometry() { @@ -9,6 +12,11 @@ CityMapGeometry::CityMapGeometry() _modelName = "city_map_defualt_name"; _vertexData.clear(); _mapLoadedFlag = 0; + + _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings(); + + setOsmFilePath(_viewer3DSettings->osmFilePath()->rawValue()); + connect(_viewer3DSettings->osmFilePath(), &Fact::rawValueChanged, this, &CityMapGeometry::setOsmFilePath); } void CityMapGeometry::setModelName(QString modelName) @@ -19,14 +27,14 @@ void CityMapGeometry::setModelName(QString modelName) emit modelNameChanged(); } -void CityMapGeometry::setOsmFilePath(QString filePath) +void CityMapGeometry::setOsmFilePath(QVariant value) { - if(_osmFilePath.compare(filePath) == 0){ + if(_osmFilePath.compare(value.toString()) == 0){ return; } _mapLoadedFlag = 0; - _osmFilePath = filePath; + _osmFilePath = value.toString(); emit osmFilePathChanged(); loadOsmMap(); } diff --git a/src/Viewer3D/CityMapGeometry.h b/src/Viewer3D/CityMapGeometry.h index f0c8f3cd81f..73796320058 100644 --- a/src/Viewer3D/CityMapGeometry.h +++ b/src/Viewer3D/CityMapGeometry.h @@ -9,11 +9,12 @@ /// @author Omid Esrafilian +class Viewer3DSettings; + class CityMapGeometry : public QQuick3DGeometry { Q_OBJECT Q_PROPERTY(QString modelName READ modelName WRITE setModelName NOTIFY modelNameChanged) - Q_PROPERTY(QString osmFilePath READ osmFilePath WRITE setOsmFilePath NOTIFY osmFilePathChanged) Q_PROPERTY(OsmParser* osmParser READ osmParser WRITE setOsmParser NOTIFY osmParserChanged) public: @@ -24,7 +25,6 @@ class CityMapGeometry : public QQuick3DGeometry void setModelName(QString modelName); QString osmFilePath() const {return _osmFilePath;} - void setOsmFilePath(QString filePath); OsmParser* osmParser(){ return _osmParser;} void setOsmParser(OsmParser* newOsmParser); @@ -44,6 +44,12 @@ class CityMapGeometry : public QQuick3DGeometry QByteArray _vertexData; OsmParser *_osmParser; bool _mapLoadedFlag; + Viewer3DSettings* _viewer3DSettings = nullptr; + +private slots: + void setOsmFilePath(QVariant value); + + }; #endif // CITYMAPGEOMETRY_H diff --git a/src/Viewer3D/OsmParser.cc b/src/Viewer3D/OsmParser.cc index 014ca5442d8..9ed77e4eddc 100644 --- a/src/Viewer3D/OsmParser.cc +++ b/src/Viewer3D/OsmParser.cc @@ -4,7 +4,8 @@ #include "earcut.hpp" #include "Viewer3DUtils.h" - +#include "QGCApplication.h" +#include "SettingsManager.h" typedef union { uint array[3]; @@ -19,11 +20,12 @@ typedef union { OsmParser::OsmParser(QObject *parent) : QObject{parent} { - _mainThread = new QThread(this); + _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings(); - this->moveToThread(_mainThread); _gpsRefSet = false; - _buildingLevelHeight = 0; // meters + + setBuildingLevelHeight(_viewer3DSettings->buildingLevelHeight()->rawValue()); // meters + connect(_viewer3DSettings->buildingLevelHeight(), &Fact::rawValueChanged, this, &OsmParser::setBuildingLevelHeight); } void OsmParser::setGpsRef(QGeoCoordinate gpsRef) @@ -33,6 +35,12 @@ void OsmParser::setGpsRef(QGeoCoordinate gpsRef) emit gpsRefChanged(_gpsRefPoint); } +void OsmParser::setBuildingLevelHeight(QVariant value) +{ + _buildingLevelHeight = value.toFloat(); + emit buildingLevelHeightChanged(); +} + void OsmParser::parseOsmFile(QString filePath) { //The QDomDocument class represents an XML document. @@ -151,8 +159,8 @@ void OsmParser::decodeBuildings(QDomElement &xmlComponent, QMap 2 && (bld_tmp.height > 0 || bld_tmp.levels > 0)) { -// float bld_height = (bld_tmp.height >= bld_tmp.levels * _buildingLevelHeight)?(bld_tmp.height):(bld_tmp.levels * _buildingLevelHeight); -// bld_tmp.height = bld_height; + // float bld_height = (bld_tmp.height >= bld_tmp.levels * _buildingLevelHeight)?(bld_tmp.height):(bld_tmp.levels * _buildingLevelHeight); + // bld_tmp.height = bld_height; bld_tmp.points_gps = bld_points; bld_tmp.points_local = bld_points_local; bld_tmp.bb_max = QVector2D(bld_x_max, bld_y_max); @@ -172,7 +180,7 @@ QByteArray OsmParser::buildingToMesh() std::vector > > polygon; std::vector triangulated_mesh; -// bld_height = (ii.value().height >= ii.value().levels * _buildingLevelHeight)?(ii.value().height):(ii.value().levels * _buildingLevelHeight); + // bld_height = (ii.value().height >= ii.value().levels * _buildingLevelHeight)?(ii.value().height):(ii.value().levels * _buildingLevelHeight); if(ii.value().height > 0){ bld_height = ii.value().height; diff --git a/src/Viewer3D/OsmParser.h b/src/Viewer3D/OsmParser.h index 0c101afeab7..02bdb72d7a0 100644 --- a/src/Viewer3D/OsmParser.h +++ b/src/Viewer3D/OsmParser.h @@ -9,9 +9,12 @@ #include #include #include "qgeocoordinate.h" +#include /// @author Omid Esrafilian +class Viewer3DSettings; + class OsmParser : public QObject { struct BuildingType @@ -26,14 +29,14 @@ class OsmParser : public QObject Q_OBJECT - Q_PROPERTY(float buildingLevelHeight READ buildingLevelHeight WRITE setBuildingLevelHeight NOTIFY buildingLevelHeightChanged) + // Q_PROPERTY(float buildingLevelHeight READ buildingLevelHeight WRITE setBuildingLevelHeight NOTIFY buildingLevelHeightChanged) public: explicit OsmParser(QObject *parent = nullptr); void setGpsRef(QGeoCoordinate gpsRef); QGeoCoordinate getGpsRef(){ return _gpsRefPoint;} - void setBuildingLevelHeight(float levelHeight){_buildingLevelHeight = levelHeight; emit buildingLevelHeightChanged();} + float buildingLevelHeight(void){return _buildingLevelHeight;} void parseOsmFile(QString filePath); void decodeNodeTags(QDomElement& xmlComponent, QMap &nodeMap); @@ -45,7 +48,6 @@ class OsmParser : public QObject void trianglateRectangle(std::vector& triangulatedMesh, std::vector verticesCcw, bool invertNormal); private: - QThread* _mainThread; QGeoCoordinate _gpsRefPoint; QMap _mapNodes; QMap _mapBuildings; @@ -53,6 +55,7 @@ class OsmParser : public QObject bool _gpsRefSet; float _buildingLevelHeight; bool _mapLoadedFlag; + Viewer3DSettings* _viewer3DSettings = nullptr; signals: @@ -60,6 +63,9 @@ class OsmParser : public QObject void mapChanged(); void buildingLevelHeightChanged(void); +private slots: + void setBuildingLevelHeight(QVariant value); + }; #endif // OSMPARSER_H diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml index 597841a0976..c62931428f0 100644 --- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml @@ -21,7 +21,7 @@ import QGroundControl.Vehicle View3D { id: topView property var viewer3DManager: null - property bool viewer3DOpen: false + property bool isViewer3DOpen: false property real rotationSpeed: 0.1 property real movementSpeed: 1 property real zoomSpeed: 0.3 @@ -89,7 +89,6 @@ View3D { geometry: CityMapGeometry { id: cityMapGeometry modelName: "city_map" - osmFilePath: (viewer3DManager)?(viewer3DManager.qmlBackend.osmFilePath):("nan") osmParser: (viewer3DManager)?(viewer3DManager.osmParser):(null) } @@ -133,7 +132,7 @@ View3D { target: null acceptedModifiers: Qt.NoModifier acceptedButtons: Qt.LeftButton - enabled: viewer3DOpen + enabled: isViewer3DOpen onCentroidChanged: { if(_isMoving){ @@ -161,7 +160,7 @@ View3D { acceptedModifiers: Qt.NoModifier acceptedButtons: Qt.RightButton acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - enabled: viewer3DOpen + enabled: isViewer3DOpen onCentroidChanged: { if(_isRotating){ @@ -187,7 +186,7 @@ View3D { property bool _isRotating: false property point _lastPose; property real _lastZoomValue; - enabled: viewer3DOpen + enabled: isViewer3DOpen onCentroidChanged: { if(_isRotating){ @@ -217,7 +216,7 @@ View3D { orientation: Qt.Vertical target: null acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - enabled: viewer3DOpen + enabled: isViewer3DOpen onWheel: event => { zoomCamera(-event.angleDelta.y) diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml index 59f74758ad3..ca586e5115f 100644 --- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml +++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DVehicleItems.qml @@ -23,6 +23,9 @@ Node { property var _vehicle: null property var _planMasterController: null property var _missionController: (_planMasterController)?(_planMasterController.missionController):(null) + property var _viewer3DSetting: QGroundControl.settingsManager.viewer3DSettings + property var _altitudeBias: _viewer3DSetting.altitudeBias.rawValue + function addMissionItemsToListModel() { missionWaypointListModel.clear() @@ -85,7 +88,7 @@ Node { id: droneDji3DModel vehicle: _vehicle modelScale: Qt.vector3d(0.05, 0.05, 0.05) - altitudeBias: _backendQml.altitudeBias + altitudeBias: _altitudeBias gpsRef: _backendQml.gpsRef } @@ -96,7 +99,7 @@ Node { delegate: Waypoint3DModel{ opacity: 0.8 missionItem: model - altitudeBias: _backendQml.altitudeBias + altitudeBias: _altitudeBias } } @@ -105,8 +108,8 @@ Node { model: missionPathModel delegate: Line3D{ - p_1: Qt.vector3d(model.x_1 * 10, model.y_1 * 10, (model.z_1 + _backendQml.altitudeBias) * 10) - p_2: Qt.vector3d(model.x_2 * 10, model.y_2 * 10, (model.z_2 + _backendQml.altitudeBias) * 10) + p_1: Qt.vector3d(model.x_1 * 10, model.y_1 * 10, (model.z_1 + _altitudeBias) * 10) + p_2: Qt.vector3d(model.x_2 * 10, model.y_2 * 10, (model.z_2 + _altitudeBias) * 10) lineWidth:8 color: "orange" } diff --git a/src/Viewer3D/Viewer3D/Viewer3D.qml b/src/Viewer3D/Viewer3D/Viewer3D.qml index e6324748d68..a0d09763a19 100644 --- a/src/Viewer3D/Viewer3D/Viewer3D.qml +++ b/src/Viewer3D/Viewer3D/Viewer3D.qml @@ -15,8 +15,22 @@ import Viewer3D.Models3D Item{ id: viewer3DBody - property bool viewer3DOpen: false - property bool settingsDialogOpen: false + property bool isOpen: false + + function open(){ + view3DManagerLoader.sourceComponent = viewer3DManagerComponent + viewer3DBody.z = 1 + isOpen = true; + } + + function close(){ + viewer3DBody.z = 0 + isOpen = false; + } + + function showSettingsDialog(){ + settingsDialogComponent.createObject(mainWindow).open() + } Component{ id: viewer3DManagerComponent @@ -45,26 +59,11 @@ Item{ Binding{ target: view3DLoader.item - property: "viewer3DOpen" - value: viewer3DOpen + property: "isViewer3DOpen" + value: isOpen when: view3DLoader.status == Loader.Ready } - onViewer3DOpenChanged: { - view3DManagerLoader.sourceComponent = viewer3DManagerComponent - if(viewer3DOpen){ - viewer3DBody.z = 1 - }else{ - viewer3DBody.z = 0 - } - } - - onSettingsDialogOpenChanged:{ - if(settingsDialogOpen === true){ - settingsDialogComponent.createObject(mainWindow).open() - } - } - Component { id: settingsDialogComponent @@ -72,10 +71,6 @@ Item{ id: view3DSettingsDialog viewer3DManager: view3DManagerLoader.item visible: true - - onClosed:{ - settingsDialogOpen = false - } } } } diff --git a/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml b/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml index 64b4c4a7d30..6621f61464a 100644 --- a/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml +++ b/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml @@ -3,15 +3,18 @@ import QtQuick.Controls import QtQuick.Dialogs import QtQuick.Layouts +import QGroundControl import QGroundControl.Palette import QGroundControl.ScreenTools import QGroundControl.Controls - +import QGroundControl.FactSystem +import QGroundControl.FactControls /// @author Omid Esrafilian QGCPopupDialog{ - property var viewer3DManager: null + property var viewer3DManager: null + property var _viewer3DSetting: QGroundControl.settingsManager.viewer3DSettings title: qsTr("3D view settings") buttons: Dialog.Ok | Dialog.Cancel @@ -43,7 +46,7 @@ QGCPopupDialog{ readOnly: true - text: (viewer3DManager)?(viewer3DManager.viewer3DSetting.osmFilePath.rawValue):("nan") + text: _viewer3DSetting.osmFilePath.rawValue } } RowLayout{ @@ -71,75 +74,22 @@ QGCPopupDialog{ } } - GridLayout{ - columns: 2 - columnSpacing: ScreenTools.defaultFontPixelHeight - rowSpacing: ScreenTools.defaultFontPixelWidth + LabelledFactTextField { Layout.fillWidth: true + label: qsTr("Average Building Level Height") + fact: _viewer3DSetting.buildingLevelHeight + visible: fact.visible + } - QGCLabel { - wrapMode: Text.WordWrap - Layout.fillWidth: true - text: qsTr("Average Building Level Height:") - } - - QGCTextField{ - id: bld_level_height_textfeild - width: ScreenTools.defaultFontPixelWidth * 15 - unitsLabel: "m" - showUnits: true - numericValuesOnly: true - visible: true - - text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue)):("nan") - - validator: RegularExpressionValidator{ - regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ - } - - onAccepted: - { - focus = false - } - } - - QGCLabel { - wrapMode: Text.WordWrap - visible: true - Layout.fillWidth: true - text: qsTr("Vehicles Altitude Bias:") - } - - QGCTextField { - id: height_bias_textfeild - width: ScreenTools.defaultFontPixelWidth * 15 - unitsLabel: "m" - showUnits: true - numericValuesOnly: true - visible: true - - text: (viewer3DManager)?(Number(viewer3DManager.viewer3DSetting.altitudeBias.rawValue)):("nan") - - validator: RegularExpressionValidator{ - regularExpression: /(-?\d{1,10})([.]\d{1,6})?$/ - } - - onAccepted: - { - focus = false - } - } + LabelledFactTextField { + Layout.fillWidth: true + label: qsTr("Vehicles Altitude Bias") + fact: _viewer3DSetting.altitudeBias + visible: fact.visible } } onAccepted: { - viewer3DManager.qmlBackend.osmFilePath = map_file_text_feild.text - viewer3DManager.qmlBackend.altitudeBias = parseFloat(height_bias_textfeild.text) - - viewer3DManager.viewer3DSetting.osmFilePath.rawValue = map_file_text_feild.text - viewer3DManager.viewer3DSetting.buildingLevelHeight.rawValue = parseFloat(bld_level_height_textfeild.text) - viewer3DManager.viewer3DSetting.altitudeBias.rawValue = parseFloat(height_bias_textfeild.text) - - viewer3DManager.osmParser.buildingLevelHeight = parseFloat(bld_level_height_textfeild.text) + _viewer3DSetting.osmFilePath.value = map_file_text_feild.text } } diff --git a/src/Viewer3D/Viewer3DManager.cc b/src/Viewer3D/Viewer3DManager.cc index 6fc52ca6cc8..20fa20effbb 100644 --- a/src/Viewer3D/Viewer3DManager.cc +++ b/src/Viewer3D/Viewer3DManager.cc @@ -5,8 +5,7 @@ Viewer3DManager::Viewer3DManager() { _qmlBackend = new Viewer3DQmlBackend(this); _osmParser = new OsmParser(); - _viewer3DSetting = new Viewer3DSettings(); - _osmParser->setBuildingLevelHeight(_viewer3DSetting->buildingLevelHeight()->rawValue().toFloat()); // meters - _qmlBackend->init(_viewer3DSetting, _osmParser); + // _osmParser->setBuildingLevelHeight(qgcApp()->toolbox()->settingsManager()->viewer3DSettings()->buildingLevelHeight()->rawValue().toFloat()); // meters + _qmlBackend->init(_osmParser); } diff --git a/src/Viewer3D/Viewer3DManager.h b/src/Viewer3D/Viewer3DManager.h index ab87f0c1a12..648563b0cd0 100644 --- a/src/Viewer3D/Viewer3DManager.h +++ b/src/Viewer3D/Viewer3DManager.h @@ -5,10 +5,11 @@ #include "Viewer3DQmlBackend.h" #include "OsmParser.h" -#include "Viewer3DSettings.h" /// @author Omid Esrafilian +class SettingsManager; + // This class contains all the variables shared between the C++ and QML sides for 3D viewer. class Viewer3DManager : public QObject { @@ -16,7 +17,6 @@ class Viewer3DManager : public QObject Q_PROPERTY(OsmParser* osmParser MEMBER _osmParser CONSTANT) Q_PROPERTY(Viewer3DQmlBackend* qmlBackend MEMBER _qmlBackend CONSTANT) - Q_PROPERTY(Viewer3DSettings* viewer3DSetting MEMBER _viewer3DSetting CONSTANT) public: explicit Viewer3DManager(); @@ -24,7 +24,6 @@ class Viewer3DManager : public QObject protected: OsmParser *_osmParser = nullptr; Viewer3DQmlBackend *_qmlBackend = nullptr; - Viewer3DSettings* _viewer3DSetting = nullptr; }; diff --git a/src/Viewer3D/Viewer3DQmlBackend.cc b/src/Viewer3D/Viewer3DQmlBackend.cc index 1fd7f59ac00..17b879aef15 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.cc +++ b/src/Viewer3D/Viewer3DQmlBackend.cc @@ -4,6 +4,7 @@ #include #include "QGCApplication.h" +#include "SettingsManager.h" #define GPS_REF_NOT_SET 0 #define GPS_REF_SET_BY_MAP 1 @@ -14,13 +15,11 @@ Viewer3DQmlBackend::Viewer3DQmlBackend(QObject *parent) { _gpsRefSet = GPS_REF_NOT_SET; _activeVehicle = nullptr; + _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings(); } -void Viewer3DQmlBackend::init(Viewer3DSettings *viewerSettingThr, OsmParser* osmThr) +void Viewer3DQmlBackend::init(OsmParser* osmThr) { - _altitudeBias = viewerSettingThr->altitudeBias()->rawValue().toFloat(); - _osmFilePath = viewerSettingThr->osmFilePath()->rawValue().toString(); - _osmParserThread = osmThr; _activeVehicleChangedEvent(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle()); diff --git a/src/Viewer3D/Viewer3DQmlBackend.h b/src/Viewer3D/Viewer3DQmlBackend.h index bcbda28d0c7..c4a7ac6b5cd 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.h +++ b/src/Viewer3D/Viewer3DQmlBackend.h @@ -10,35 +10,32 @@ /// @author Omid Esrafilian +class Viewer3DSettings; + class Viewer3DQmlBackend : public QObject { Q_OBJECT - Q_PROPERTY(QString osmFilePath MEMBER _osmFilePath NOTIFY cityMapPathChanged) Q_PROPERTY(QGeoCoordinate gpsRef READ gpsRef NOTIFY gpsRefChanged) - Q_PROPERTY(float altitudeBias MEMBER _altitudeBias NOTIFY altitudeBiasChanged) public: explicit Viewer3DQmlBackend(QObject *parent = nullptr); - void init(Viewer3DSettings* viewerSettingThr, OsmParser* osmThr=nullptr); + void init(OsmParser* osmThr=nullptr); QGeoCoordinate gpsRef(){return _gpsRef;} signals: void gpsRefChanged(); - void altitudeBiasChanged(); - void cityMapPathChanged(); private: OsmParser *_osmParserThread; - QString _osmFilePath; QGeoCoordinate _gpsRef; uint8_t _gpsRefSet; - float _altitudeBias; Vehicle *_activeVehicle; + Viewer3DSettings* _viewer3DSettings = nullptr; protected slots: From 375cea9502e36c09e0273e047096d5c11031f660 Mon Sep 17 00:00:00 2001 From: "esrafilian.omid" Date: Sat, 24 Feb 2024 21:52:13 +0100 Subject: [PATCH 5/5] The 3D View settings are moved to Fly View settings, and a 3D view enabled switch is added --- qgcimages.qrc | 1 - qgroundcontrol.qrc | 1 - .../FlyViewToolStripActionList.qml | 46 ++++----- src/Settings/Viewer3D.SettingsGroup.json | 6 ++ src/Settings/Viewer3DSettings.cc | 1 + src/Settings/Viewer3DSettings.h | 1 + src/Viewer3D/CityMapGeometry.cc | 8 ++ src/Viewer3D/CityMapGeometry.h | 1 + src/Viewer3D/Images/gear_icon.png | Bin 17944 -> 0 bytes src/Viewer3D/OsmParser.cc | 29 ++++-- src/Viewer3D/OsmParser.h | 3 +- .../Viewer3D/Models3D/CameraLightModel.qml | 16 +++ .../Viewer3D/Models3D/Viewer3DModel.qml | 5 + src/Viewer3D/Viewer3D/Viewer3D.qml | 31 +++--- .../Viewer3D/Viewer3DSettingsDialog.qml | 95 ------------------ src/Viewer3D/Viewer3D/qmldir | 1 - src/Viewer3D/Viewer3DManager.cc | 7 +- src/Viewer3D/Viewer3DManager.h | 2 + src/Viewer3D/Viewer3DQmlBackend.cc | 14 ++- src/Viewer3D/Viewer3DQmlBackend.h | 2 +- src/ui/preferences/FlyViewSettings.qml | 90 ++++++++++++++++- 21 files changed, 204 insertions(+), 156 deletions(-) delete mode 100644 src/Viewer3D/Images/gear_icon.png delete mode 100644 src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml diff --git a/qgcimages.qrc b/qgcimages.qrc index 5a1d3340472..8c071fe5526 100644 --- a/qgcimages.qrc +++ b/qgcimages.qrc @@ -207,7 +207,6 @@ src/ui/toolbar/Images/Yield.svg src/FlightMap/Images/ZoomMinus.svg src/FlightMap/Images/ZoomPlus.svg - src/Viewer3D/Images/gear_icon.png src/Viewer3D/Images/city_3d_map_icon.svg diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 2ce89e879f8..daa1cc8275e 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -315,7 +315,6 @@ src/PlanView/VTOLLandingPatternEditor.qml src/comm/MockLinkOptionsDlg.qml src/FlightDisplay/FlyViewInsetViewer.qml - src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml src/Viewer3D/Viewer3D/Viewer3D.qml src/Viewer3D/Viewer3D/qmldir src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml diff --git a/src/FlightDisplay/FlyViewToolStripActionList.qml b/src/FlightDisplay/FlyViewToolStripActionList.qml index 3961c25c771..25fec526325 100644 --- a/src/FlightDisplay/FlyViewToolStripActionList.qml +++ b/src/FlightDisplay/FlyViewToolStripActionList.qml @@ -16,6 +16,7 @@ ToolStripActionList { id: _root signal displayPreFlightChecklist + property bool _viewer3DEnabled: QGroundControl.settingsManager.viewer3DSettings.enabled.rawValue model: [ ToolStripAction { @@ -23,44 +24,33 @@ ToolStripActionList { iconSource: "/qmlimages/Plan.svg" onTriggered:{ mainWindow.showPlanView() - map_icon.showFlyMap() + mapIcon.showFlyMap() } }, ToolStripAction { - id: map_icon + property bool _is3DViewOpen: viewer3DWindow.isOpen + + id: mapIcon + visible: _viewer3DEnabled text: qsTr("3D View") iconSource: "/qmlimages/Viewer3D/City3DMapIcon.svg" onTriggered:{ - if(viewer3DWindow.isOpen === false){ - show3dMap(); + if(_is3DViewOpen === false){ + viewer3DWindow.open() }else{ - showFlyMap(); + viewer3DWindow.close() } } - function show3dMap(){ - viewer3DWindow.open() - map_icon.iconSource = "/qmlimages/PaperPlane.svg" - text= qsTr("Fly") - city_map_setting_icon.enabled = true - } - - function showFlyMap(){ - viewer3DWindow.close() - iconSource = "/qmlimages/Viewer3D/City3DMapIcon.svg" - text = qsTr("3D View") - city_map_setting_icon.enabled = false - city_map_setting_icon.checked = false - } - }, - ToolStripAction { - id: city_map_setting_icon - text: qsTr("Setting") - iconSource: "/qmlimages/Viewer3D/GearIcon.png" - enabled: false - visible: enabled - onTriggered:{ - viewer3DWindow.showSettingsDialog() + on_Is3DViewOpenChanged: { + if(_is3DViewOpen === true){ + mapIcon.iconSource = "/qmlimages/PaperPlane.svg" + text= qsTr("Fly") + }else{ + viewer3DWindow.close() + iconSource = "/qmlimages/Viewer3D/City3DMapIcon.svg" + text = qsTr("3D View") + } } }, PreFlightCheckListShowAction { onTriggered: displayPreFlightChecklist() }, diff --git a/src/Settings/Viewer3D.SettingsGroup.json b/src/Settings/Viewer3D.SettingsGroup.json index e9523742a9c..6aa548f5c71 100644 --- a/src/Settings/Viewer3D.SettingsGroup.json +++ b/src/Settings/Viewer3D.SettingsGroup.json @@ -3,6 +3,12 @@ "fileType": "FactMetaData", "QGC.MetaData.Facts": [ +{ + "name": "enabled", + "shortDesc": "Enable the 3D viewer", + "type": "bool", + "default": false +}, { "name": "osmFilePath", "shortDesc": "Path to the OSM file for the 3D viewer.", diff --git a/src/Settings/Viewer3DSettings.cc b/src/Settings/Viewer3DSettings.cc index 86d2eda5f2d..1583f973ae1 100644 --- a/src/Settings/Viewer3DSettings.cc +++ b/src/Settings/Viewer3DSettings.cc @@ -17,6 +17,7 @@ DECLARE_SETTINGGROUP(Viewer3D, "Viewer3D") qmlRegisterUncreatableType("QGroundControl.SettingsManager", 1, 0, "Viewer3DSettings", "Reference only"); } +DECLARE_SETTINGSFACT(Viewer3DSettings, enabled) DECLARE_SETTINGSFACT(Viewer3DSettings, osmFilePath) DECLARE_SETTINGSFACT(Viewer3DSettings, buildingLevelHeight) DECLARE_SETTINGSFACT(Viewer3DSettings, altitudeBias) diff --git a/src/Settings/Viewer3DSettings.h b/src/Settings/Viewer3DSettings.h index 8a202ffd984..c112d5d8174 100644 --- a/src/Settings/Viewer3DSettings.h +++ b/src/Settings/Viewer3DSettings.h @@ -21,6 +21,7 @@ class Viewer3DSettings : public SettingsGroup DEFINE_SETTING_NAME_GROUP() + DEFINE_SETTINGFACT(enabled) DEFINE_SETTINGFACT(osmFilePath) DEFINE_SETTINGFACT(buildingLevelHeight) DEFINE_SETTINGFACT(altitudeBias) diff --git a/src/Viewer3D/CityMapGeometry.cc b/src/Viewer3D/CityMapGeometry.cc index 0bec274b8ee..d31b04ee227 100644 --- a/src/Viewer3D/CityMapGeometry.cc +++ b/src/Viewer3D/CityMapGeometry.cc @@ -33,6 +33,7 @@ void CityMapGeometry::setOsmFilePath(QVariant value) return; } + clearViewer(); _mapLoadedFlag = 0; _osmFilePath = value.toString(); emit osmFilePathChanged(); @@ -90,3 +91,10 @@ void CityMapGeometry::updateViewer() update(); } } + +void CityMapGeometry::clearViewer() +{ + clear(); + _vertexData.clear(); + update(); +} diff --git a/src/Viewer3D/CityMapGeometry.h b/src/Viewer3D/CityMapGeometry.h index 73796320058..558a82bfb50 100644 --- a/src/Viewer3D/CityMapGeometry.h +++ b/src/Viewer3D/CityMapGeometry.h @@ -38,6 +38,7 @@ class CityMapGeometry : public QQuick3DGeometry private: void updateViewer(); + void clearViewer(); QString _modelName; QString _osmFilePath; diff --git a/src/Viewer3D/Images/gear_icon.png b/src/Viewer3D/Images/gear_icon.png deleted file mode 100644 index 5ba6043e90479d58d5195617ed07d84f1088fc1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17944 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 diff --git a/src/Viewer3D/OsmParser.cc b/src/Viewer3D/OsmParser.cc index 9ed77e4eddc..46f7048b6d5 100644 --- a/src/Viewer3D/OsmParser.cc +++ b/src/Viewer3D/OsmParser.cc @@ -23,6 +23,7 @@ OsmParser::OsmParser(QObject *parent) _viewer3DSettings = qgcApp()->toolbox()->settingsManager()->viewer3DSettings(); _gpsRefSet = false; + _mapLoadedFlag = false; setBuildingLevelHeight(_viewer3DSettings->buildingLevelHeight()->rawValue()); // meters connect(_viewer3DSettings->buildingLevelHeight(), &Fact::rawValueChanged, this, &OsmParser::setBuildingLevelHeight); @@ -32,7 +33,14 @@ void OsmParser::setGpsRef(QGeoCoordinate gpsRef) { _gpsRefPoint = gpsRef; _gpsRefSet = true; - emit gpsRefChanged(_gpsRefPoint); + emit gpsRefChanged(_gpsRefPoint, _gpsRefSet); +} + +void OsmParser::resetGpsRef() +{ + _gpsRefPoint = QGeoCoordinate(0, 0, 0); + _gpsRefSet = false; + emit gpsRefChanged(_gpsRefPoint, _gpsRefSet); } void OsmParser::setBuildingLevelHeight(QVariant value) @@ -43,6 +51,20 @@ void OsmParser::setBuildingLevelHeight(QVariant value) void OsmParser::parseOsmFile(QString filePath) { + if(filePath == "Please select an OSM file"){ + if(_mapLoadedFlag){ + qDebug("The 3D View has been cleared!"); + _mapNodes.clear(); + _mapBuildings.clear(); + _gpsRefSet = false; + _mapLoadedFlag = false; + resetGpsRef(); + }else{ + qDebug("No OSM File is selected!"); + } + return; + } + //The QDomDocument class represents an XML document. QDomDocument xml_content; // Load xml file as raw data @@ -65,11 +87,6 @@ void OsmParser::parseOsmFile(QString filePath) QDomElement component = root.firstChild().toElement(); - _mapNodes.clear(); - _mapBuildings.clear(); - _gpsRefSet = false; - _mapLoadedFlag = false; - while(!component.isNull()) { decodeNodeTags(component, _mapNodes); decodeBuildings(component, _mapBuildings, _mapNodes, _gpsRefPoint); diff --git a/src/Viewer3D/OsmParser.h b/src/Viewer3D/OsmParser.h index 02bdb72d7a0..07f847c091e 100644 --- a/src/Viewer3D/OsmParser.h +++ b/src/Viewer3D/OsmParser.h @@ -35,6 +35,7 @@ class OsmParser : public QObject explicit OsmParser(QObject *parent = nullptr); void setGpsRef(QGeoCoordinate gpsRef); + void resetGpsRef(); QGeoCoordinate getGpsRef(){ return _gpsRefPoint;} float buildingLevelHeight(void){return _buildingLevelHeight;} @@ -59,7 +60,7 @@ class OsmParser : public QObject signals: - void gpsRefChanged(QGeoCoordinate newGpsRef); + void gpsRefChanged(QGeoCoordinate newGpsRef, bool isRefSet); void mapChanged(); void buildingLevelHeightChanged(void); diff --git a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml index 6350f796d63..2bd1f64bbf4 100644 --- a/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/CameraLightModel.qml @@ -13,6 +13,22 @@ Node { property real _pan: 0.001 property real _zoom: 1500 + function resetCamera(){ + camNode.position = Qt.vector3d(0, 0, 0); + camNode.eulerRotation = Qt.vector3d(90, 0, 0); + + cameraPerspectiveThree.position = Qt.vector3d(0, 0, 0); + cameraPerspectiveThree.eulerRotation = Qt.vector3d(0, 0, 0); + + cameraPerspectiveTwo.position = Qt.vector3d(_zoom * Math.sin(_tilt) * Math.cos(_pan), + _zoom * Math.cos(_tilt), + _zoom * Math.sin(_tilt) * Math.sin(_pan)); + cameraPerspectiveTwo.eulerRotation = Qt.vector3d(0, 0, 0); + + cameraPerspectiveOne.position = Qt.vector3d(0, 0, 0); + cameraPerspectiveOne.eulerRotation = Qt.vector3d(-90, 0, 0); + } + DirectionalLight { eulerRotation.x: 180 diff --git a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml index c62931428f0..b0b02f37327 100644 --- a/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml +++ b/src/Viewer3D/Viewer3D/Models3D/Viewer3DModel.qml @@ -21,6 +21,7 @@ import QGroundControl.Vehicle View3D { id: topView property var viewer3DManager: null + readonly property var _gpsRef: viewer3DManager.qmlBackend.gpsRef property bool isViewer3DOpen: false property real rotationSpeed: 0.1 property real movementSpeed: 1 @@ -70,6 +71,10 @@ View3D { standAloneScene.cameraTwoPosition.z += dz } + on_GpsRefChanged:{ + standAloneScene.resetCamera(); + } + camera: standAloneScene.cameraOne importScene: CameraLightModel{ id: standAloneScene diff --git a/src/Viewer3D/Viewer3D/Viewer3D.qml b/src/Viewer3D/Viewer3D/Viewer3D.qml index a0d09763a19..926b7795100 100644 --- a/src/Viewer3D/Viewer3D/Viewer3D.qml +++ b/src/Viewer3D/Viewer3D/Viewer3D.qml @@ -3,6 +3,7 @@ import QtQuick.Controls import QtQuick.Dialogs import QtQuick.Layouts +import QGroundControl import QGroundControl.Palette import QGroundControl.ScreenTools import QGroundControl.Controls @@ -16,11 +17,16 @@ import Viewer3D.Models3D Item{ id: viewer3DBody property bool isOpen: false + property bool _viewer3DEnabled: QGroundControl.settingsManager.viewer3DSettings.enabled.rawValue + function open(){ - view3DManagerLoader.sourceComponent = viewer3DManagerComponent - viewer3DBody.z = 1 - isOpen = true; + if(_viewer3DEnabled === true){ + view3DManagerLoader.sourceComponent = viewer3DManagerComponent + view3DManagerLoader.active = true; + viewer3DBody.z = 1 + isOpen = true; + } } function close(){ @@ -28,8 +34,12 @@ Item{ isOpen = false; } - function showSettingsDialog(){ - settingsDialogComponent.createObject(mainWindow).open() + on_Viewer3DEnabledChanged: { + if(_viewer3DEnabled === false){ + viewer3DBody.close(); + view3DLoader.active = false; + view3DManagerLoader.active = false; + } } Component{ @@ -45,6 +55,7 @@ Item{ onLoaded: { view3DLoader.source = "Models3D/Viewer3DModel.qml" + view3DLoader.active = true; } } @@ -63,14 +74,4 @@ Item{ value: isOpen when: view3DLoader.status == Loader.Ready } - - Component { - id: settingsDialogComponent - - Viewer3DSettingsDialog{ - id: view3DSettingsDialog - viewer3DManager: view3DManagerLoader.item - visible: true - } - } } diff --git a/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml b/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml deleted file mode 100644 index 6621f61464a..00000000000 --- a/src/Viewer3D/Viewer3D/Viewer3DSettingsDialog.qml +++ /dev/null @@ -1,95 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Dialogs -import QtQuick.Layouts - -import QGroundControl -import QGroundControl.Palette -import QGroundControl.ScreenTools -import QGroundControl.Controls -import QGroundControl.FactSystem -import QGroundControl.FactControls - -/// @author Omid Esrafilian - -QGCPopupDialog{ - property var viewer3DManager: null - property var _viewer3DSetting: QGroundControl.settingsManager.viewer3DSettings - - title: qsTr("3D view settings") - buttons: Dialog.Ok | Dialog.Cancel - - ColumnLayout { - property int leftMarginSpace: ScreenTools.defaultFontPixelWidth - - id: window_body - clip: true - visible: true - spacing: ScreenTools.defaultFontPixelHeight / 2 - RowLayout{ - Layout.fillWidth: true - QGCLabel { - wrapMode: Text.WordWrap - visible: true - text: qsTr("3D Map File:") - } - - QGCTextField { - id: map_file_text_feild - height: ScreenTools.defaultFontPixelWidth * 4.5 - unitsLabel: "" - showUnits: false - visible: true - Layout.fillWidth: true - implicitWidth: ScreenTools.defaultFontPixelWidth * 50 - - - readOnly: true - - text: _viewer3DSetting.osmFilePath.rawValue - } - } - RowLayout{ - Layout.alignment: Qt.AlignRight - - QGCButton { - id: map_file_btn - - visible: true - text: qsTr("Select File") - - onClicked: { - fileDialog.openForLoad() - } - - QGCFileDialog { - id: fileDialog - - nameFilters: [qsTr("OpenStreetMap files (*.osm)")] - title: qsTr("Select map file") - onAcceptedForLoad: (file) => { - map_file_text_feild.text = file - } - } - } - } - - LabelledFactTextField { - Layout.fillWidth: true - label: qsTr("Average Building Level Height") - fact: _viewer3DSetting.buildingLevelHeight - visible: fact.visible - } - - LabelledFactTextField { - Layout.fillWidth: true - label: qsTr("Vehicles Altitude Bias") - fact: _viewer3DSetting.altitudeBias - visible: fact.visible - } - } - - onAccepted: { - _viewer3DSetting.osmFilePath.value = map_file_text_feild.text - } -} diff --git a/src/Viewer3D/Viewer3D/qmldir b/src/Viewer3D/Viewer3D/qmldir index 8c326b1c8ba..15a9da02437 100644 --- a/src/Viewer3D/Viewer3D/qmldir +++ b/src/Viewer3D/Viewer3D/qmldir @@ -1,4 +1,3 @@ Module Viewer3D Viewer3D 1.0 Viewer3D.qml -Viewer3DSettingMenu 1.0 Viewer3DSettingMenu.qml diff --git a/src/Viewer3D/Viewer3DManager.cc b/src/Viewer3D/Viewer3DManager.cc index 20fa20effbb..9358a3558ed 100644 --- a/src/Viewer3D/Viewer3DManager.cc +++ b/src/Viewer3D/Viewer3DManager.cc @@ -6,6 +6,11 @@ Viewer3DManager::Viewer3DManager() _qmlBackend = new Viewer3DQmlBackend(this); _osmParser = new OsmParser(); - // _osmParser->setBuildingLevelHeight(qgcApp()->toolbox()->settingsManager()->viewer3DSettings()->buildingLevelHeight()->rawValue().toFloat()); // meters _qmlBackend->init(_osmParser); } + +Viewer3DManager::~Viewer3DManager() +{ + delete _osmParser; + delete _qmlBackend; +} diff --git a/src/Viewer3D/Viewer3DManager.h b/src/Viewer3D/Viewer3DManager.h index 648563b0cd0..e212c4f88ff 100644 --- a/src/Viewer3D/Viewer3DManager.h +++ b/src/Viewer3D/Viewer3DManager.h @@ -21,6 +21,8 @@ class Viewer3DManager : public QObject public: explicit Viewer3DManager(); + ~Viewer3DManager(); + protected: OsmParser *_osmParser = nullptr; Viewer3DQmlBackend *_qmlBackend = nullptr; diff --git a/src/Viewer3D/Viewer3DQmlBackend.cc b/src/Viewer3D/Viewer3DQmlBackend.cc index 17b879aef15..947262f0ae2 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.cc +++ b/src/Viewer3D/Viewer3DQmlBackend.cc @@ -57,11 +57,15 @@ void Viewer3DQmlBackend::_activeVehicleCoordinateChanged(QGeoCoordinate newCoord } } -void Viewer3DQmlBackend::_gpsRefChangedEvent(QGeoCoordinate newGpsRef) -{ - _gpsRef = newGpsRef; - _gpsRefSet = GPS_REF_SET_BY_MAP; - emit gpsRefChanged(); +void Viewer3DQmlBackend::_gpsRefChangedEvent(QGeoCoordinate newGpsRef, bool isRefSet) +{ + if(isRefSet){ + _gpsRef = newGpsRef; + _gpsRefSet = GPS_REF_SET_BY_MAP; + emit gpsRefChanged(); + }else{ + _gpsRefSet = GPS_REF_NOT_SET; + } qDebug() << "3D viewer gps reference set by osm map:" << _gpsRef.latitude() << _gpsRef.longitude() << _gpsRef.altitude(); } diff --git a/src/Viewer3D/Viewer3DQmlBackend.h b/src/Viewer3D/Viewer3DQmlBackend.h index c4a7ac6b5cd..f79fbe8226b 100644 --- a/src/Viewer3D/Viewer3DQmlBackend.h +++ b/src/Viewer3D/Viewer3DQmlBackend.h @@ -39,7 +39,7 @@ class Viewer3DQmlBackend : public QObject protected slots: - void _gpsRefChangedEvent(QGeoCoordinate newGpsRef); + void _gpsRefChangedEvent(QGeoCoordinate newGpsRef, bool isRefSet); void _activeVehicleChangedEvent(Vehicle* vehicle); void _activeVehicleCoordinateChanged(QGeoCoordinate newCoordinate); }; diff --git a/src/ui/preferences/FlyViewSettings.qml b/src/ui/preferences/FlyViewSettings.qml index b9fddbb1f90..29515b31a6e 100644 --- a/src/ui/preferences/FlyViewSettings.qml +++ b/src/ui/preferences/FlyViewSettings.qml @@ -30,6 +30,11 @@ SettingsPage { property Fact _guidedMinimumAltitude: _settingsManager.flyViewSettings.guidedMinimumAltitude property Fact _guidedMaximumAltitude: _settingsManager.flyViewSettings.guidedMaximumAltitude property Fact _maxGoToLocationDistance: _settingsManager.flyViewSettings.maxGoToLocationDistance + property Fact _viewer3DEnabled: _settingsManager.viewer3DSettings.enabled + property Fact _viewer3DOsmFilePath: _settingsManager.viewer3DSettings.osmFilePath + property Fact _viewer3DBuildingLevelHeight: _settingsManager.viewer3DSettings.buildingLevelHeight + property Fact _viewer3DAltitudeBias: _settingsManager.viewer3DSettings.altitudeBias + SettingsGroupLayout { Layout.fillWidth: true @@ -116,7 +121,7 @@ SettingsPage { SettingsGroupLayout { Layout.fillWidth: true - heading: qsTr("Virtual Joystick") + heading: qsTr("Virtual Joystick") visible: _virtualJoystick.visible || _virtualJoystickAutoCenterThrottle.visible FactCheckBoxSlider { @@ -154,4 +159,87 @@ SettingsPage { fact: _lockNoseUpCompass } } + + SettingsGroupLayout { + Layout.fillWidth: true + heading: qsTr("3D View") + + FactCheckBoxSlider { + Layout.fillWidth: true + text: qsTr("Enabled") + fact: _viewer3DEnabled + } + ColumnLayout{ + Layout.fillWidth: true + spacing: ScreenTools.defaultFontPixelWidth + enabled: _viewer3DEnabled.rawValue + + RowLayout{ + Layout.fillWidth: true + spacing: ScreenTools.defaultFontPixelWidth + + QGCLabel { + wrapMode: Text.WordWrap + visible: true + text: qsTr("3D Map File:") + } + + QGCTextField { + id: osmFileTextField + height: ScreenTools.defaultFontPixelWidth * 4.5 + unitsLabel: "" + showUnits: false + visible: true + Layout.fillWidth: true + readOnly: true + text: _viewer3DOsmFilePath.rawValue + } + } + RowLayout{ + Layout.alignment: Qt.AlignRight + spacing: ScreenTools.defaultFontPixelWidth + + QGCButton { + text: qsTr("Clear") + + onClicked: { + osmFileTextField.text = "Please select an OSM file" + _viewer3DOsmFilePath.value = osmFileTextField.text + } + } + + QGCButton { + text: qsTr("Select File") + + onClicked: { + fileDialog.openForLoad() + } + + QGCFileDialog { + id: fileDialog + nameFilters: [qsTr("OpenStreetMap files (*.osm)")] + title: qsTr("Select map file") + onAcceptedForLoad: (file) => { + osmFileTextField.text = file + _viewer3DOsmFilePath.value = osmFileTextField.text + } + } + } + } + } + + LabelledFactTextField { + Layout.fillWidth: true + label: qsTr("Average Building Level Height") + fact: _viewer3DBuildingLevelHeight + enabled: _viewer3DEnabled.rawValue + } + + LabelledFactTextField { + Layout.fillWidth: true + label: qsTr("Vehicles Altitude Bias") + fact: _viewer3DAltitudeBias + enabled: _viewer3DEnabled.rawValue + } + } }