Interpolating points (#3002)

* Add a class for rendering an interpolated point cloud (WIP)

* Make sure that we render the correct number of points

* Group interpolation properties into a property owner

* Update interpolation stuff (which was broken :) )

* Prevent interpolation from breaking with only one step or invalid interpolation values

* Add trigger properties for controlling interpolation

* Allow setting start interpolation value from asset

* Implement spline-based interpolation

* Cleanup, and interpolate to start and end

* And asset type documentation

* Add example asset

* Handle missing data values in interpolation

* Always show values at the knots, if there is one

* Experiment with more dynamic rendering (batching)

* Speed up interpolation by doing it on GPU instead of CPU

* Bring back spline interpolation (this time on GPU)

* Refactor initial data buffering

* Add a helper function to compute transformed positions

* Use vec3 positions instead of vec4 (less data to transfer)

* Update interpolation value documentation

* Apply suggestions from code review

Co-authored-by: Alexander Bock <alexander.bock@liu.se>

* Increase interpolation speed max value

* Fix faulty indentation

* I banish thee, redundant empty line

---------

Co-authored-by: Alexander Bock <alexander.bock@liu.se>
This commit is contained in:
Emma Broman
2024-01-30 09:43:11 +01:00
committed by GitHub
parent bcc728cbfd
commit 2406a886ec
13 changed files with 1063 additions and 76 deletions

View File

@@ -0,0 +1,61 @@
time,x,y,z,dynamic_value,static_value
0.0,675.0297905065192,1672.6820684730765,-124.14442820502654,1,1
0.0,9.0852354697237,1080.363474597831,266.4506394528842,3,3
0.0,783.6498618493837,-332.90868790089644,166.73196289611994,5,5
0.0,163.88116606175208,-978.1393719572736,1260.016529398092,10,10
0.0,-934.1529593143864,-590.4853596059422,-622.5048517597389,11,11
0.0,77.99426967464474,-184.5196836590583,1835.5681393474856,13,13
0.0,77.99426967464474,-184.5196836590583,1835.5681393474856,14,14
0.0,-269.98667369858055,-559.2891044933908,-1487.2591171480176,15,15
0.0,-710.8143185498654,-627.4209210346181,-1504.56518583112,17,17
0.0,-710.8143185498654,-627.4209210346181,-1504.56518583112,18,18
1.0,1350.0595810130385,3345.364136946153,-248.28885641005309,2,1
1.0,18.1704709394474,2160.726949195662,532.9012789057684,6,3
1.0,1567.2997236987674,-665.8173758017929,333.4639257922399,10,5
1.0,327.76233212350417,-1956.2787439145472,2520.033058796184,20,10
1.0,-1868.3059186287728,-1180.9707192118844,-1245.0097035194779,22,11
1.0,155.98853934928948,-369.0393673181166,3671.136278694971,26,13
1.0,155.98853934928948,-369.0393673181166,3671.136278694971,28,14
1.0,-539.9733473971611,-1118.5782089867816,-2974.518234296035,30,15
1.0,-1421.628637099731,-1254.8418420692362,-3009.13037166224,34,17
1.0,-1421.628637099731,-1254.8418420692362,-3009.13037166224,36,18
2.0,2700.119162026077,6690.728273892306,-496.57771282010617,4,1
2.0,36.3409418788948,4321.453898391324,1065.8025578115369,12,3
2.0,3134.5994473975347,-1331.6347516035858,666.9278515844798,20,5
2.0,655.5246642470083,-3912.5574878290945,5040.066117592368,40,10
2.0,-3736.6118372575456,-2361.941438423769,-2490.0194070389557,44,11
2.0,311.97707869857896,-738.0787346362332,7342.272557389942,52,13
2.0,311.97707869857896,-738.0787346362332,7342.272557389942,56,14
2.0,-1079.9466947943222,-2237.1564179735633,-5949.03646859207,60,15
2.0,-2843.257274199462,-2509.6836841384725,-6018.26074332448,68,17
2.0,-2843.257274199462,-2509.6836841384725,-6018.26074332448,72,18
3.0,5400.238324052154,13381.456547784612,-993.1554256402123,8,1
3.0,72.6818837577896,8642.907796782649,2131.6051156230737,24,3
3.0,6269.1988947950695,-2663.2695032071715,1333.8557031689595,40,5
3.0,1311.0493284940167,-7825.114975658189,10080.132235184736,80,10
3.0,-7473.223674515091,-4723.882876847538,-4980.038814077911,88,11
3.0,623.9541573971579,-1476.1574692724664,14684.545114779885,104,13
3.0,623.9541573971579,-1476.1574692724664,14684.545114779885,112,14
3.0,-2159.8933895886444,-4474.312835947127,-11898.07293718414,120,15
3.0,-5686.514548398924,-5019.367368276945,-12036.52148664896,136,17
3.0,-5686.514548398924,-5019.367368276945,-12036.52148664896,144,18
4.0,10800.476648104308,26762.913095569224,-1986.3108512804247,16,1
4.0,145.3637675155792,17285.815593565298,4263.2102312461475,48,3
4.0,12538.397789590139,-5326.539006414343,2667.711406337919,80,5
4.0,2622.0986569880333,-15650.229951316378,20160.26447036947,160,10
4.0,-14946.447349030183,-9447.765753695076,-9960.077628155823,176,11
4.0,1247.9083147943159,-2952.314938544933,29369.09022955977,208,13
4.0,1247.9083147943159,-2952.314938544933,29369.09022955977,224,14
4.0,-4319.786779177289,-8948.625671894253,-23796.14587436828,240,15
4.0,-11373.029096797847,-10038.73473655389,-24073.04297329792,272,17
4.0,-11373.029096797847,-10038.73473655389,-24073.04297329792,288,18
5.0,21600.953296208616,53525.82619113845,-3972.6217025608494,32,1
5.0,290.7275350311584,34571.631187130595,8526.420462492295,96,3
5.0,25076.795579180278,-10653.078012828686,5335.422812675838,160,5
5.0,5244.197313976067,-31300.459902632756,40320.52894073894,320,10
5.0,-29892.894698060365,-18895.53150739015,-19920.155256311646,352,11
5.0,2495.8166295886317,-5904.629877089866,58738.18045911954,416,13
5.0,2495.8166295886317,-5904.629877089866,58738.18045911954,448,14
5.0,-8639.573558354577,-17897.251343788506,-47592.29174873656,480,15
5.0,-22746.058193595694,-20077.46947310778,-48146.08594659584,544,17
5.0,-22746.058193595694,-20077.46947310778,-48146.08594659584,576,18
1 time x y z dynamic_value static_value
2 0.0 675.0297905065192 1672.6820684730765 -124.14442820502654 1 1
3 0.0 9.0852354697237 1080.363474597831 266.4506394528842 3 3
4 0.0 783.6498618493837 -332.90868790089644 166.73196289611994 5 5
5 0.0 163.88116606175208 -978.1393719572736 1260.016529398092 10 10
6 0.0 -934.1529593143864 -590.4853596059422 -622.5048517597389 11 11
7 0.0 77.99426967464474 -184.5196836590583 1835.5681393474856 13 13
8 0.0 77.99426967464474 -184.5196836590583 1835.5681393474856 14 14
9 0.0 -269.98667369858055 -559.2891044933908 -1487.2591171480176 15 15
10 0.0 -710.8143185498654 -627.4209210346181 -1504.56518583112 17 17
11 0.0 -710.8143185498654 -627.4209210346181 -1504.56518583112 18 18
12 1.0 1350.0595810130385 3345.364136946153 -248.28885641005309 2 1
13 1.0 18.1704709394474 2160.726949195662 532.9012789057684 6 3
14 1.0 1567.2997236987674 -665.8173758017929 333.4639257922399 10 5
15 1.0 327.76233212350417 -1956.2787439145472 2520.033058796184 20 10
16 1.0 -1868.3059186287728 -1180.9707192118844 -1245.0097035194779 22 11
17 1.0 155.98853934928948 -369.0393673181166 3671.136278694971 26 13
18 1.0 155.98853934928948 -369.0393673181166 3671.136278694971 28 14
19 1.0 -539.9733473971611 -1118.5782089867816 -2974.518234296035 30 15
20 1.0 -1421.628637099731 -1254.8418420692362 -3009.13037166224 34 17
21 1.0 -1421.628637099731 -1254.8418420692362 -3009.13037166224 36 18
22 2.0 2700.119162026077 6690.728273892306 -496.57771282010617 4 1
23 2.0 36.3409418788948 4321.453898391324 1065.8025578115369 12 3
24 2.0 3134.5994473975347 -1331.6347516035858 666.9278515844798 20 5
25 2.0 655.5246642470083 -3912.5574878290945 5040.066117592368 40 10
26 2.0 -3736.6118372575456 -2361.941438423769 -2490.0194070389557 44 11
27 2.0 311.97707869857896 -738.0787346362332 7342.272557389942 52 13
28 2.0 311.97707869857896 -738.0787346362332 7342.272557389942 56 14
29 2.0 -1079.9466947943222 -2237.1564179735633 -5949.03646859207 60 15
30 2.0 -2843.257274199462 -2509.6836841384725 -6018.26074332448 68 17
31 2.0 -2843.257274199462 -2509.6836841384725 -6018.26074332448 72 18
32 3.0 5400.238324052154 13381.456547784612 -993.1554256402123 8 1
33 3.0 72.6818837577896 8642.907796782649 2131.6051156230737 24 3
34 3.0 6269.1988947950695 -2663.2695032071715 1333.8557031689595 40 5
35 3.0 1311.0493284940167 -7825.114975658189 10080.132235184736 80 10
36 3.0 -7473.223674515091 -4723.882876847538 -4980.038814077911 88 11
37 3.0 623.9541573971579 -1476.1574692724664 14684.545114779885 104 13
38 3.0 623.9541573971579 -1476.1574692724664 14684.545114779885 112 14
39 3.0 -2159.8933895886444 -4474.312835947127 -11898.07293718414 120 15
40 3.0 -5686.514548398924 -5019.367368276945 -12036.52148664896 136 17
41 3.0 -5686.514548398924 -5019.367368276945 -12036.52148664896 144 18
42 4.0 10800.476648104308 26762.913095569224 -1986.3108512804247 16 1
43 4.0 145.3637675155792 17285.815593565298 4263.2102312461475 48 3
44 4.0 12538.397789590139 -5326.539006414343 2667.711406337919 80 5
45 4.0 2622.0986569880333 -15650.229951316378 20160.26447036947 160 10
46 4.0 -14946.447349030183 -9447.765753695076 -9960.077628155823 176 11
47 4.0 1247.9083147943159 -2952.314938544933 29369.09022955977 208 13
48 4.0 1247.9083147943159 -2952.314938544933 29369.09022955977 224 14
49 4.0 -4319.786779177289 -8948.625671894253 -23796.14587436828 240 15
50 4.0 -11373.029096797847 -10038.73473655389 -24073.04297329792 272 17
51 4.0 -11373.029096797847 -10038.73473655389 -24073.04297329792 288 18
52 5.0 21600.953296208616 53525.82619113845 -3972.6217025608494 32 1
53 5.0 290.7275350311584 34571.631187130595 8526.420462492295 96 3
54 5.0 25076.795579180278 -10653.078012828686 5335.422812675838 160 5
55 5.0 5244.197313976067 -31300.459902632756 40320.52894073894 320 10
56 5.0 -29892.894698060365 -18895.53150739015 -19920.155256311646 352 11
57 5.0 2495.8166295886317 -5904.629877089866 58738.18045911954 416 13
58 5.0 2495.8166295886317 -5904.629877089866 58738.18045911954 448 14
59 5.0 -8639.573558354577 -17897.251343788506 -47592.29174873656 480 15
60 5.0 -22746.058193595694 -20077.46947310778 -48146.08594659584 544 17
61 5.0 -22746.058193595694 -20077.46947310778 -48146.08594659584 576 18

View File

@@ -0,0 +1,61 @@
time,x,y,z
0.0,675.0297905065192,1672.6820684730765,-124.14442820502654
0.0,9.0852354697237,1080.363474597831,266.4506394528842
0.0,783.6498618493837,-332.90868790089644,166.73196289611994
0.0,163.88116606175208,-978.1393719572736,1260.016529398092
0.0,-934.1529593143864,-590.4853596059422,-622.5048517597389
0.0,77.99426967464474,-184.5196836590583,1835.5681393474856
0.0,77.99426967464474,-184.5196836590583,1835.5681393474856
0.0,-269.98667369858055,-559.2891044933908,-1487.2591171480176
0.0,-710.8143185498654,-627.4209210346181,-1504.56518583112
0.0,-710.8143185498654,-627.4209210346181,-1504.56518583112
1.0,1668.4580965289847,745.846682848152,2807.1531096380813
1.0,-267.4433668726456,148.90396745731732,-185.1019615201871
1.0,2079.026938050769,151.01585523117177,301.7883722719676
1.0,3209.940878877803,-4804.699861272869,-1589.4798430288217
1.0,-1402.4597087610582,-4040.3210246320077,-1711.2703008101043
1.0,-390.2796442237164,-1309.0947421410037,2057.413318767218
1.0,3236.419900689428,-2210.181924327906,-466.4190154971202
1.0,1264.882784607237,69.2055606971569,-735.8630804566736
1.0,-1649.7630904197697,-2443.46907207704,-2705.84256566873
1.0,374.30576862206385,-3452.028323705201,-2087.952685417674
2.0,465.0448720701909,2222.779842838973,3455.3210484276715
2.0,3437.11300214523,491.6405298372583,-955.2665223528202
2.0,2052.032488574901,-80.28070954530929,-1052.0556283399499
2.0,1094.5190209660022,-5406.907252451447,-366.127265347086
2.0,242.63011544531992,-6997.3650053668625,350.72874418179754
2.0,-2831.9669441657607,-2748.783158930421,3919.9735569996146
2.0,3654.1470906989384,-3131.459466247481,-2144.8540619423975
2.0,-2654.4574631523137,2183.4500131349887,-1354.287832159103
2.0,-4306.135188216631,-1756.232492940117,-2043.315702861602
2.0,768.0282403603109,-6978.108634430669,-136.86243117295544
3.0,-493.303603620389,2945.5710538558005,3015.977272752648
3.0,3065.7950488175957,3567.7136627691966,-241.04137932932736
3.0,-160.63745943715548,-151.93278776521237,1903.7324611430824
3.0,-1297.8942271953392,-2277.6199408234343,-1402.6677018943808
3.0,1867.681760233716,-12236.85521354635,-1266.2584616045776
3.0,-119.48688702411482,-1104.9781501799732,2916.459469830542
3.0,3510.126847538271,-2957.3653297711385,-314.04982653824914
3.0,-647.3916673682654,1585.4353122032537,-696.785612839734
3.0,-3582.8631381213627,-1572.7109398691125,-3102.8361103956795
3.0,-522.2112688499377,-10953.246463632455,889.6724350537568
4.0,-299.1485049243082,114.829569754972,-821.5651578454349
4.0,5003.085029883374,2726.4230172384787,-294.0691302277611
4.0,-1564.7436471918602,-837.3618208187513,2024.1928810251354
4.0,-1953.2185203908757,-3882.1744792666723,3523.8165230761915
4.0,1083.4654539694006,-12559.426636878368,-1650.9803911668228
4.0,-3046.516783288352,-296.8764365508964,3519.554154497767
4.0,4102.367401667423,815.0064726499218,-383.47336594873576
4.0,-125.2811230084867,1934.5909378669317,-3034.141688078798
4.0,-3572.6362248364408,-1057.610158423584,-817.1904813656383
4.0,-991.3855356002316,-11102.13829516479,2393.538500427305
5.0,1282.9153891617857,-2986.4972923772934,-366.64528863717607
5.0,3184.310120293896,2863.5489668505334,2320.216378337095
5.0,1240.8449746803383,-2961.969248270961,-1190.7735880973198
5.0,-4756.920645975437,-2934.989617996309,3893.0842401408
5.0,2257.179641569941,-14398.275105345974,-1131.2148026699756
5.0,1334.3944683316054,2802.9923734841823,5083.199898052388
5.0,2121.294751406046,-751.5001120225525,-2857.3747877048995
5.0,-1257.8765822140306,1290.4679054555804,-5675.05491424735
5.0,-3373.3334946611585,569.4242763157556,226.69264986815688
5.0,-1998.3368438326302,-13563.866928032701,2987.507846893677
1 time x y z
2 0.0 675.0297905065192 1672.6820684730765 -124.14442820502654
3 0.0 9.0852354697237 1080.363474597831 266.4506394528842
4 0.0 783.6498618493837 -332.90868790089644 166.73196289611994
5 0.0 163.88116606175208 -978.1393719572736 1260.016529398092
6 0.0 -934.1529593143864 -590.4853596059422 -622.5048517597389
7 0.0 77.99426967464474 -184.5196836590583 1835.5681393474856
8 0.0 77.99426967464474 -184.5196836590583 1835.5681393474856
9 0.0 -269.98667369858055 -559.2891044933908 -1487.2591171480176
10 0.0 -710.8143185498654 -627.4209210346181 -1504.56518583112
11 0.0 -710.8143185498654 -627.4209210346181 -1504.56518583112
12 1.0 1668.4580965289847 745.846682848152 2807.1531096380813
13 1.0 -267.4433668726456 148.90396745731732 -185.1019615201871
14 1.0 2079.026938050769 151.01585523117177 301.7883722719676
15 1.0 3209.940878877803 -4804.699861272869 -1589.4798430288217
16 1.0 -1402.4597087610582 -4040.3210246320077 -1711.2703008101043
17 1.0 -390.2796442237164 -1309.0947421410037 2057.413318767218
18 1.0 3236.419900689428 -2210.181924327906 -466.4190154971202
19 1.0 1264.882784607237 69.2055606971569 -735.8630804566736
20 1.0 -1649.7630904197697 -2443.46907207704 -2705.84256566873
21 1.0 374.30576862206385 -3452.028323705201 -2087.952685417674
22 2.0 465.0448720701909 2222.779842838973 3455.3210484276715
23 2.0 3437.11300214523 491.6405298372583 -955.2665223528202
24 2.0 2052.032488574901 -80.28070954530929 -1052.0556283399499
25 2.0 1094.5190209660022 -5406.907252451447 -366.127265347086
26 2.0 242.63011544531992 -6997.3650053668625 350.72874418179754
27 2.0 -2831.9669441657607 -2748.783158930421 3919.9735569996146
28 2.0 3654.1470906989384 -3131.459466247481 -2144.8540619423975
29 2.0 -2654.4574631523137 2183.4500131349887 -1354.287832159103
30 2.0 -4306.135188216631 -1756.232492940117 -2043.315702861602
31 2.0 768.0282403603109 -6978.108634430669 -136.86243117295544
32 3.0 -493.303603620389 2945.5710538558005 3015.977272752648
33 3.0 3065.7950488175957 3567.7136627691966 -241.04137932932736
34 3.0 -160.63745943715548 -151.93278776521237 1903.7324611430824
35 3.0 -1297.8942271953392 -2277.6199408234343 -1402.6677018943808
36 3.0 1867.681760233716 -12236.85521354635 -1266.2584616045776
37 3.0 -119.48688702411482 -1104.9781501799732 2916.459469830542
38 3.0 3510.126847538271 -2957.3653297711385 -314.04982653824914
39 3.0 -647.3916673682654 1585.4353122032537 -696.785612839734
40 3.0 -3582.8631381213627 -1572.7109398691125 -3102.8361103956795
41 3.0 -522.2112688499377 -10953.246463632455 889.6724350537568
42 4.0 -299.1485049243082 114.829569754972 -821.5651578454349
43 4.0 5003.085029883374 2726.4230172384787 -294.0691302277611
44 4.0 -1564.7436471918602 -837.3618208187513 2024.1928810251354
45 4.0 -1953.2185203908757 -3882.1744792666723 3523.8165230761915
46 4.0 1083.4654539694006 -12559.426636878368 -1650.9803911668228
47 4.0 -3046.516783288352 -296.8764365508964 3519.554154497767
48 4.0 4102.367401667423 815.0064726499218 -383.47336594873576
49 4.0 -125.2811230084867 1934.5909378669317 -3034.141688078798
50 4.0 -3572.6362248364408 -1057.610158423584 -817.1904813656383
51 4.0 -991.3855356002316 -11102.13829516479 2393.538500427305
52 5.0 1282.9153891617857 -2986.4972923772934 -366.64528863717607
53 5.0 3184.310120293896 2863.5489668505334 2320.216378337095
54 5.0 1240.8449746803383 -2961.969248270961 -1190.7735880973198
55 5.0 -4756.920645975437 -2934.989617996309 3893.0842401408
56 5.0 2257.179641569941 -14398.275105345974 -1131.2148026699756
57 5.0 1334.3944683316054 2802.9923734841823 5083.199898052388
58 5.0 2121.294751406046 -751.5001120225525 -2857.3747877048995
59 5.0 -1257.8765822140306 1290.4679054555804 -5675.05491424735
60 5.0 -3373.3334946611585 569.4242763157556 226.69264986815688
61 5.0 -1998.3368438326302 -13563.866928032701 2987.507846893677

View File

@@ -0,0 +1,92 @@
local Points = {
Identifier = "Example_InterpolatedPoints_ColorMapped",
Renderable = {
Type = "RenderableInterpolatedPoints",
-- The dataset here is just a linearly expanding dataset, where the points move in
-- a straight line
File = asset.resource("data/interpolation_expand.csv"),
-- Specify how many objects the rows in the dataset represent. Here, the dataset is
-- consists of 10 objects with positions at 6 different time steps. This information
-- is required
NumberOfObjects = 10,
-- Both the position and data values will be interpolated, so use a color map
Coloring = {
ColorMapping = {
File = asset.resource("viridis.cmap")
}
},
-- Reduce the scale of the points a bit compared to default, so we see them more clearly
SizeSettings = {
ScaleExponent = 3.5
}
},
GUI = {
Name = "Interpolating Points with Color Map",
Path = "/Example/Interpolated Point Clouds",
Description = [[Example of interpolating points with a color map. The data value
used for the coloring will also be inteprolated, leading to the points changing
color throughout the interpolation.]]
}
}
local Points_Smoothed = {
Identifier = "Example_InterpolatedPoints_Spline",
Renderable = {
Type = "RenderableInterpolatedPoints",
-- Using a random walk dataset, to get movement in some different directions
File = asset.resource("data/interpolation_randomwalk.csv"),
-- Same number of objects as above - 10 objects with positions at 6 different
-- time steps
NumberOfObjects = 10,
Interpolation = {
-- Smoothen transitions between two different sets of points, by
-- using a spline based interpolation of the points
UseSplineInterpolation = true
},
-- Just use a fixed coloring here, no color mapping
Coloring = {
FixedColor = { 0.0, 0.5, 0.0 }
},
-- Reduce the scale of the points a bit compared to default, so we see them more clearly
SizeSettings = {
ScaleExponent = 3.0
}
},
GUI = {
Name = "Interpolating Points (Spline)",
Path = "/Example/Interpolated Point Clouds",
Description = [[Example of interpolating points with spline-based interpolation
for the position. This leads to smoother transitions at the nodes of the
interpolation. Try disabling the spline interpolation in the GUI (under
Renderable->Interpolation) to see the difference.]]
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Points)
openspace.addSceneGraphNode(Points_Smoothed)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Points_Smoothed)
openspace.removeSceneGraphNode(Points)
end)
asset.export(Points)
asset.export(Points_Smoothed)
asset.meta = {
Name = "Example - Interpolated Point Clouds",
Version = "1.0",
Description = [[Example of point clouds that support interpolation. One uses a linear
motion and color mapping. The other example uses a spline interpolation for the
approximation of the positions, to result in smoother transitions between the sets
of positions. The interpolation can be triggered using the properties under
Renderable->Interpolation in the Scene menu.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -44,6 +44,7 @@ set(HEADER_FILES
rendering/grids/renderablegrid.h
rendering/grids/renderableradialgrid.h
rendering/grids/renderablesphericalgrid.h
rendering/pointcloud/renderableinterpolatedpoints.h
rendering/pointcloud/renderablepointcloud.h
rendering/pointcloud/renderablepolygoncloud.h
rendering/renderablecartesianaxes.h
@@ -105,6 +106,7 @@ set(SOURCE_FILES
rendering/grids/renderablegrid.cpp
rendering/grids/renderableradialgrid.cpp
rendering/grids/renderablesphericalgrid.cpp
rendering/pointcloud/renderableinterpolatedpoints.cpp
rendering/pointcloud/renderablepointcloud.cpp
rendering/pointcloud/renderablepolygoncloud.cpp
rendering/renderablecartesianaxes.cpp
@@ -152,9 +154,6 @@ set(SHADER_FILES
shaders/arrow_vs.glsl
shaders/axes_fs.glsl
shaders/axes_vs.glsl
shaders/billboardpoint_fs.glsl
shaders/billboardpoint_gs.glsl
shaders/billboardpoint_vs.glsl
shaders/disc_fs.glsl
shaders/disc_vs.glsl
shaders/grid_vs.glsl
@@ -167,6 +166,10 @@ set(SHADER_FILES
shaders/model_vs.glsl
shaders/plane_fs.glsl
shaders/plane_vs.glsl
shaders/pointcloud/billboardpoint_fs.glsl
shaders/pointcloud/billboardpoint_gs.glsl
shaders/pointcloud/billboardpoint_vs.glsl
shaders/pointcloud/billboardpoint_interpolated_vs.glsl
shaders/polygon_fs.glsl
shaders/polygon_gs.glsl
shaders/polygon_vs.glsl

View File

@@ -43,6 +43,7 @@
#include <modules/base/rendering/grids/renderablegrid.h>
#include <modules/base/rendering/grids/renderableradialgrid.h>
#include <modules/base/rendering/grids/renderablesphericalgrid.h>
#include <modules/base/rendering/pointcloud/renderableinterpolatedpoints.h>
#include <modules/base/rendering/pointcloud/renderablepointcloud.h>
#include <modules/base/rendering/pointcloud/renderablepolygoncloud.h>
#include <modules/base/rendering/renderablecartesianaxes.h>
@@ -146,6 +147,9 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
fRenderable->registerClass<RenderablePlaneTimeVaryingImage>(
"RenderablePlaneTimeVaryingImage"
);
fRenderable->registerClass<RenderableInterpolatedPoints>(
"RenderableInterpolatedPoints"
);
fRenderable->registerClass<RenderablePointCloud>("RenderablePointCloud");
fRenderable->registerClass<RenderablePolygonCloud>("RenderablePolygonCloud");
fRenderable->registerClass<RenderablePrism>("RenderablePrism");
@@ -226,6 +230,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
RenderableCartesianAxes::Documentation(),
RenderableDisc::Documentation(),
RenderableGrid::Documentation(),
RenderableInterpolatedPoints::Documentation(),
RenderableLabel::Documentation(),
RenderableModel::Documentation(),
RenderableNodeArrow::Documentation(),

View File

@@ -0,0 +1,544 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/pointcloud/renderableinterpolatedpoints.h>
#include <modules/base/basemodule.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/glm.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/interpolator.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <optional>
namespace {
constexpr std::string_view _loggerCat = "RenderableInterpolatedPoints";
constexpr openspace::properties::Property::PropertyInfo InterpolationValueInfo = {
"Value",
"Value",
"The value to use for interpolation. The max value is set from the number of "
"steps in the dataset, so a step of one corresponds to one step in the dataset "
"and values in-between will be determined using interpolation.",
openspace::properties::Property::Visibility::NoviceUser
};
constexpr openspace::properties::Property::PropertyInfo StepsInfo = {
"NumberOfSteps",
"Number of Steps",
"The number of steps available in the dataset, including the initial positions.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo JumpToNextInfo = {
"JumpToNext",
"Jump to Next",
"Immediately set the interpolation value to correspond to the next set of point "
"positions compared to the current.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo JumpToPrevInfo = {
"JumpToPrevious",
"Jump to Previous",
"Immediately set the interpolation value to correspond to the previous set of "
"point positions compared to the current.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo InterpolateToNextInfo = {
"InterpolateToNext",
"Interpolate to Next",
"Trigger an interpolation to the next set of point positions. The duration of "
"the interpolation is set based on the Interpolaton Speed property.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo InterpolateToPrevInfo = {
"InterpolateToPrevious",
"Interpolate to Previous",
"Trigger an interpolation to the previous set of point positions. The duration "
"of the interpolation is set based on the Interpolaton Speed property.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo InterpolateToEndInfo = {
"InterpolateToEnd",
"Interpolate to End",
"Trigger an interpolation all the way to the final set of positions. The "
"duration of the interpolation is set based on the Interpolaton Speed property.",
openspace::properties::Property::Visibility::NoviceUser
};
constexpr openspace::properties::Property::PropertyInfo InterpolateToStartInfo = {
"InterpolateToStart",
"Interpolate to Start",
"Trigger an inverted interpolation to the initial set of positions. The duration "
"of the interpolation is set based on the Interpolaton Speed property.",
openspace::properties::Property::Visibility::NoviceUser
};
constexpr openspace::properties::Property::PropertyInfo InterpolationSpeedInfo = {
"Speed",
"Interpolation Speed",
"Affects how long the interpolation takes when triggered using one of the "
"trigger properties. A value of 1 means that a step takes 1 second.",
openspace::properties::Property::Visibility::NoviceUser
};
constexpr openspace::properties::Property::PropertyInfo UseSplineInfo = {
"UseSplineInterpolation",
"Use Spline Interpolation",
"If true, the points will be interpolated using a Catmull-Rom spline instead of "
"linearly. This leads to a smoother transition at the breakpoints, i.e. between "
"each step.",
openspace::properties::Property::Visibility::AdvancedUser
};
// RenderableInterpolatedPoints is a version of the RenderablePointCloud class, where
// the dataset may contain multiple time steps that can be interpolated between. It
// supports interpolation of both of positions and data values used for color mapping
// or size.
//
// The dataset should be structured in a way so that the first N rows correspond to
// the first set of positions for the objects, the next N rows to the second set of
// positions, and so on. The number of objects in the dataset must be specified in the
// asset.
struct [[codegen::Dictionary(RenderableInterpolatedPoints)]] Parameters {
// The number of objects to read from the dataset. Every N:th datapoint will
// be interpreted as the same point, but at a different step in the interpolation
int numberOfObjects [[codegen::greaterequal(1)]];
struct Interpolation {
// [[codegen::verbatim(InterpolationValueInfo.description)]]
std::optional<double> value;
// [[codegen::verbatim(InterpolationSpeedInfo.description)]]
std::optional<double> speed;
// [[codegen::verbatim(UseSplineInfo.description)]]
std::optional<bool> useSplineInterpolation;
};
// Initial settings for the interpolation
std::optional<Interpolation> interpolation;
};
#include "renderableinterpolatedpoints_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation RenderableInterpolatedPoints::Documentation() {
return codegen::doc<Parameters>(
"base_renderableinterpolatedpoints",
RenderablePointCloud::Documentation()
);
}
RenderableInterpolatedPoints::Interpolation::Interpolation()
: properties::PropertyOwner({ "Interpolation", "Interpolation", "" })
, value(InterpolationValueInfo, 0.f, 0.f, 1.f)
, nSteps(StepsInfo)
, goToNextStep(JumpToNextInfo)
, goToPrevStep(JumpToPrevInfo)
, interpolateToNextStep(InterpolateToNextInfo)
, interpolateToPrevStep(InterpolateToPrevInfo)
, interpolateToEnd(InterpolateToEndInfo)
, interpolateToStart(InterpolateToStartInfo)
, speed(InterpolationSpeedInfo, 1.f, 0.01f, 100.f)
, useSpline(UseSplineInfo, false)
{
addProperty(value);
auto triggerInterpolation = [](std::string_view identifier, float v, float d) {
std::string script = fmt::format(
"openspace.setPropertyValueSingle(\"{}\", {}, {})",
identifier, v, d
);
// No syncing, as this was triggered from a property change (which happened
// based on an already synced script)
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
};
interpolateToEnd.onChange([triggerInterpolation, this]() {
float remaining = value.maxValue() - value;
float duration = remaining / speed;
triggerInterpolation(
value.fullyQualifiedIdentifier(),
value.maxValue(),
duration
);
});
interpolateToStart.onChange([triggerInterpolation, this]() {
float duration = value / speed;
triggerInterpolation(value.fullyQualifiedIdentifier(), 0.f, duration);
});
interpolateToNextStep.onChange([triggerInterpolation, this]() {
float prevValue = glm::floor(value);
float newValue = glm::min(prevValue + 1.f, value.maxValue());
float duration = 1.f / speed;
triggerInterpolation(value.fullyQualifiedIdentifier(), newValue, duration);
});
interpolateToPrevStep.onChange([triggerInterpolation, this]() {
float prevValue = glm::ceil(value);
float newValue = glm::max(prevValue - 1.f, value.minValue());
float duration = 1.f / speed;
triggerInterpolation(value.fullyQualifiedIdentifier(), newValue, duration);
});
addProperty(interpolateToEnd);
addProperty(interpolateToStart);
addProperty(interpolateToNextStep);
addProperty(interpolateToPrevStep);
addProperty(speed);
goToNextStep.onChange([this]() {
float prevValue = glm::floor(value);
value = glm::min(prevValue + 1.f, value.maxValue());
});
goToPrevStep.onChange([this]() {
float prevValue = glm::ceil(value);
value = glm::max(prevValue - 1.f, value.minValue());
});
addProperty(goToNextStep);
addProperty(goToPrevStep);
nSteps.setReadOnly(true);
addProperty(nSteps);
addProperty(useSpline);
}
RenderableInterpolatedPoints::RenderableInterpolatedPoints(
const ghoul::Dictionary& dictionary)
: RenderablePointCloud(dictionary)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
addPropertySubOwner(_interpolation);
if (p.interpolation.has_value()) {
_interpolation.value = static_cast<float>(
p.interpolation->value.value_or(_interpolation.value)
);
_interpolation.speed = static_cast<float>(
p.interpolation->speed.value_or(_interpolation.speed)
);
_interpolation.useSpline = p.interpolation->useSplineInterpolation.value_or(
_interpolation.useSpline
);
}
unsigned int nObjects = static_cast<unsigned int>(p.numberOfObjects);
// At this point, the dataset has been loaded and the number of points computed. We
// need to recompute them and compute how many steps the number of points
// corresponded to
if (_nDataPoints % nObjects != 0) {
LERROR(fmt::format(
"Mismatch between provided number of data entries and the specified number "
"of points. Expected the number of entries in the data file {} to be evenly "
"divisible by the number of points", _dataFile
));
}
_interpolation.nSteps = _nDataPoints / nObjects;
_interpolation.value.setMaxValue(static_cast<float>(_interpolation.nSteps - 1));
_interpolation.value.onChange([this]() {
bool passedAKnot =
glm::ceil(_interpolation.value) != glm::ceil(_prevInterpolationValue);
if (passedAKnot) {
_dataIsDirty = true;
}
_prevInterpolationValue = _interpolation.value;
});
_interpolation.useSpline.onChange([this]() {
_dataIsDirty = true;
_shouldReinitializeBufferdata = true;
});
// This property is mostly for show in the UI, but also used to tell how many points
// should be rendered. So make sure it is updated once we know the number of
// interpolation steps
_nDataPoints = nObjects;
}
void RenderableInterpolatedPoints::initializeShadersAndGlExtras() {
_program = BaseModule::ProgramObjectManager.request(
"RenderablePointCloud_Interpolated",
[]() {
return global::renderEngine->buildRenderProgram(
"RenderablePointCloud_Interpolated",
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_interpolated_vs.glsl"),
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_fs.glsl"),
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_gs.glsl")
);
}
);
initializeBufferData();
}
void RenderableInterpolatedPoints::deinitializeShaders() {
BaseModule::ProgramObjectManager.release(
"RenderablePointCloud_Interpolated",
[](ghoul::opengl::ProgramObject* p) {
global::renderEngine->removeRenderProgram(p);
}
);
_program = nullptr;
}
void RenderableInterpolatedPoints::bindDataForPointRendering() {
RenderablePointCloud::bindDataForPointRendering();
float t0 = computeCurrentLowerValue();
float t = glm::clamp(_interpolation.value - t0, 0.f, 1.f);
_program->setUniform("interpolationValue", t);
_program->setUniform("useSpline", _interpolation.useSpline);
}
void RenderableInterpolatedPoints::preUpdate() {
if (_shouldReinitializeBufferdata) {
initializeBufferData();
_shouldReinitializeBufferdata = false;
}
}
int RenderableInterpolatedPoints::nAttributesPerPoint() const {
int n = RenderablePointCloud::nAttributesPerPoint();
// Need twice as much information as the regular points
n *= 2;
if (_interpolation.useSpline) {
// Use two more positions (xyz)
n += 2 * 3;
}
return n;
}
std::vector<float> RenderableInterpolatedPoints::createDataSlice() {
ZoneScoped;
if (_dataset.entries.empty()) {
return std::vector<float>();
}
std::vector<float> result;
result.reserve(nAttributesPerPoint() * _nDataPoints);
// Find the information we need for the interpolation and to identify the points,
// and make sure these result in valid indices in all cases
float t0 = computeCurrentLowerValue();
float t1 = t0 + 1.f;
t1 = glm::clamp(t1, 0.f, _interpolation.value.maxValue());
unsigned int t0Index = static_cast<unsigned int>(t0);
unsigned int t1Index = static_cast<unsigned int>(t1);
// What datavar is in use for the index color
int colorParamIndex = currentColorParameterIndex();
// What datavar is in use for the size scaling (if present)
int sizeParamIndex = currentSizeParameterIndex();
double maxRadius = 0.0;
for (unsigned int i = 0; i < _nDataPoints; i++) {
using namespace dataloader;
const Dataset::Entry& e0 = _dataset.entries[t0Index * _nDataPoints + i];
const Dataset::Entry& e1 = _dataset.entries[t1Index * _nDataPoints + i];
glm::dvec3 position0 = transformedPosition(e0);
glm::dvec3 position1 = transformedPosition(e1);
const double r = glm::max(glm::length(position0), glm::length(position1));
maxRadius = glm::max(maxRadius, r);
// Positions
for (int j = 0; j < 3; ++j) {
result.push_back(static_cast<float>(position0[j]));
}
for (int j = 0; j < 3; ++j) {
result.push_back(static_cast<float>(position1[j]));
}
if (_interpolation.useSpline && _interpolation.nSteps > 1) {
// Compute the extra positions, before and after the other ones
unsigned int beforeIndex = static_cast<unsigned int>(
glm::max(t0 - 1.f, 0.f)
);
unsigned int afterIndex = static_cast<unsigned int>(
glm::min(t1 + 1.f, _interpolation.value.maxValue() - 1.f)
);
const Dataset::Entry& e00 = _dataset.entries[beforeIndex * _nDataPoints + i];
const Dataset::Entry& e11 = _dataset.entries[afterIndex * _nDataPoints + i];
glm::dvec3 positionBefore = transformedPosition(e00);
glm::dvec3 positionAfter = transformedPosition(e11);
for (int j = 0; j < 3; ++j) {
result.push_back(static_cast<float>(positionBefore[j]));
}
for (int j = 0; j < 3; ++j) {
result.push_back(static_cast<float>(positionAfter[j]));
}
}
// Colors
if (_hasColorMapFile) {
result.push_back(e0.data[colorParamIndex]);
result.push_back(e1.data[colorParamIndex]);
}
// Size data
if (_hasDatavarSize) {
// @TODO: Consider more detailed control over the scaling. Currently the value
// is multiplied with the value as is. Should have similar mapping properties
// as the color mapping
result.push_back(e0.data[sizeParamIndex]);
result.push_back(e1.data[sizeParamIndex]);
}
// @TODO: Also need to update label positions, if we have created labels from the dataset
// And make sure these are created from only the first set of points..
}
setBoundingSphere(maxRadius);
return result;
}
void RenderableInterpolatedPoints::initializeBufferData() {
if (_vao == 0) {
glGenVertexArrays(1, &_vao);
LDEBUG(fmt::format("Generating Vertex Array id '{}'", _vao));
}
if (_vbo == 0) {
glGenBuffers(1, &_vbo);
LDEBUG(fmt::format("Generating Vertex Buffer Object id '{}'", _vbo));
}
const int attibutesPerPoint = nAttributesPerPoint();
const unsigned int bufferSize = attibutesPerPoint * _nDataPoints * sizeof(float);
// Allocate the memory for the buffer (we will want to upload the data quite often)
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, bufferSize, nullptr, GL_DYNAMIC_DRAW);
int attributeOffset = 0;
auto addFloatAttribute = [&](const std::string& name, GLint nValues) {
GLint attrib = _program->attributeLocation(name);
glEnableVertexAttribArray(attrib);
glVertexAttribPointer(
attrib,
nValues,
GL_FLOAT,
GL_FALSE,
attibutesPerPoint * sizeof(float),
(attributeOffset > 0) ?
reinterpret_cast<void*>(attributeOffset * sizeof(float)) :
nullptr
);
attributeOffset += nValues;
};
addFloatAttribute("in_position0", 3);
addFloatAttribute("in_position1", 3);
if (_interpolation.useSpline) {
addFloatAttribute("in_position_before", 3);
addFloatAttribute("in_position_after", 3);
}
if (_hasColorMapFile) {
addFloatAttribute("in_colorParameter0", 1);
addFloatAttribute("in_colorParameter1", 1);
}
if (_hasDatavarSize) {
addFloatAttribute("in_scalingParameter0", 1);
addFloatAttribute("in_scalingParameter1", 1);
}
glBindVertexArray(0);
}
void RenderableInterpolatedPoints::updateBufferData() {
if (!_hasDataFile || _dataset.entries.empty()) {
return;
}
ZoneScopedN("Data dirty");
TracyGpuZone("Data dirty");
LDEBUG("Regenerating data");
// Regenerate data and update buffer
std::vector<float> slice = createDataSlice();
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferSubData(GL_ARRAY_BUFFER, 0, slice.size() * sizeof(float), slice.data());
glBindVertexArray(0);
_dataIsDirty = false;
}
bool RenderableInterpolatedPoints::isAtKnot() const {
float v = _interpolation.value;
return (v - glm::floor(v)) < std::numeric_limits<float>::epsilon();
}
float RenderableInterpolatedPoints::computeCurrentLowerValue() const {
float t0 = glm::floor(_interpolation.value);
if (isAtKnot()) {
t0 = t0 - 1.f;
}
const float maxTValue = _interpolation.value.maxValue();
float maxAllowedT0 = glm::max(maxTValue - 1.f, 0.f);
t0 = glm::clamp(t0, 0.f, maxAllowedT0);
return t0;
}
} // namespace openspace

View File

@@ -0,0 +1,100 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___RENDERABLEINTERPOLATEDPOINTS___H__
#define __OPENSPACE_MODULE_BASE___RENDERABLEINTERPOLATEDPOINTS___H__
#include <modules/base/rendering/pointcloud/renderablepointcloud.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/scalar/uintproperty.h>
#include <openspace/properties/triggerproperty.h>
namespace ghoul::opengl { class Texture; }
namespace openspace {
namespace documentation { struct Documentation; }
/**
* A specialization of the RenderablePointCloud that supports interpolation beetween
* different positions for the points.
*/
class RenderableInterpolatedPoints : public RenderablePointCloud {
public:
explicit RenderableInterpolatedPoints(const ghoul::Dictionary& dictionary);
~RenderableInterpolatedPoints() override = default;
static documentation::Documentation Documentation();
protected:
void initializeShadersAndGlExtras() override;
void deinitializeShaders() override;
void bindDataForPointRendering() override;
void preUpdate() override;
int nAttributesPerPoint() const override;
/**
* Create the data slice to use for rendering the points. Compared to the regular
* point cloud, the data slice for an interpolated set of points will have to be
* recreated when the interpolation value changes, and will only include a subset of
* the points in the entire dataset
*
* \return The dataslice to use for rendering the points
*/
std::vector<float> createDataSlice() override;
void initializeBufferData();
void updateBufferData() override;
private:
bool isAtKnot() const;
float computeCurrentLowerValue() const;
struct Interpolation : public properties::PropertyOwner {
Interpolation();
properties::FloatProperty value;
properties::UIntProperty nSteps;
properties::TriggerProperty goToNextStep;
properties::TriggerProperty goToPrevStep;
properties::TriggerProperty interpolateToNextStep;
properties::TriggerProperty interpolateToPrevStep;
properties::TriggerProperty interpolateToEnd;
properties::TriggerProperty interpolateToStart;
properties::FloatProperty speed;
properties::BoolProperty useSpline;
};
Interpolation _interpolation;
float _prevInterpolationValue = 0.f;
bool _shouldReinitializeBufferdata = false;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___RENDERABLEINTERPOLATEDPOINTS___H__

View File

@@ -628,17 +628,7 @@ void RenderablePointCloud::initialize() {
void RenderablePointCloud::initializeGL() {
ZoneScoped;
_program = BaseModule::ProgramObjectManager.request(
"RenderablePointCloud",
[]() {
return global::renderEngine->buildRenderProgram(
"RenderablePointCloud",
absPath("${MODULE_BASE}/shaders/billboardpoint_vs.glsl"),
absPath("${MODULE_BASE}/shaders/billboardpoint_fs.glsl"),
absPath("${MODULE_BASE}/shaders/billboardpoint_gs.glsl")
);
}
);
initializeShadersAndGlExtras();
ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames);
@@ -653,6 +643,27 @@ void RenderablePointCloud::deinitializeGL() {
glDeleteVertexArrays(1, &_vao);
_vao = 0;
deinitializeShaders();
BaseModule::TextureManager.release(_spriteTexture);
_spriteTexture = nullptr;
}
void RenderablePointCloud::initializeShadersAndGlExtras() {
_program = BaseModule::ProgramObjectManager.request(
"RenderablePointCloud",
[]() {
return global::renderEngine->buildRenderProgram(
"RenderablePointCloud",
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_vs.glsl"),
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_fs.glsl"),
absPath("${MODULE_BASE}/shaders/pointcloud/billboardpoint_gs.glsl")
);
}
);
}
void RenderablePointCloud::deinitializeShaders() {
BaseModule::ProgramObjectManager.release(
"RenderablePointCloud",
[](ghoul::opengl::ProgramObject* p) {
@@ -660,9 +671,6 @@ void RenderablePointCloud::deinitializeGL() {
}
);
_program = nullptr;
BaseModule::TextureManager.release(_spriteTexture);
_spriteTexture = nullptr;
}
void RenderablePointCloud::bindTextureForRendering() const {
@@ -699,51 +707,8 @@ float RenderablePointCloud::computeDistanceFadeValue(const RenderData& data) con
return fadeValue * funcValue;
}
void RenderablePointCloud::renderBillboards(const RenderData& data,
const glm::dmat4& modelMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
if (!_hasDataFile || _dataset.entries.empty()) {
return;
}
glEnablei(GL_BLEND, 0);
if (_useAdditiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
else {
// Normal blending, with transparency
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
_program->activate();
_program->setUniform(_uniformCache.cameraPos, data.camera.positionVec3());
_program->setUniform(
_uniformCache.cameraLookup,
glm::vec3(data.camera.lookUpVectorWorldSpace())
);
void RenderablePointCloud::bindDataForPointRendering() {
_program->setUniform(_uniformCache.renderOption, _renderOption.value());
_program->setUniform(_uniformCache.modelMatrix, modelMatrix);
_program->setUniform(
_uniformCache.cameraViewMatrix,
data.camera.combinedViewMatrix()
);
_program->setUniform(
_uniformCache.projectionMatrix,
glm::dmat4(data.camera.projectionMatrix())
);
_program->setUniform(_uniformCache.up, glm::vec3(orthoUp));
_program->setUniform(_uniformCache.right, glm::vec3(orthoRight));
_program->setUniform(_uniformCache.fadeInValue, fadeInVariable);
_program->setUniform(_uniformCache.opacity, opacity());
_program->setUniform(_uniformCache.scaleExponent, _sizeSettings.scaleExponent);
@@ -811,9 +776,58 @@ void RenderablePointCloud::renderBillboards(const RenderData& data,
_colorSettings.colorMapping->useBelowRangeColor
);
}
}
void RenderablePointCloud::renderBillboards(const RenderData& data,
const glm::dmat4& modelMatrix,
const glm::dvec3& orthoRight,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
if (!_hasDataFile || _dataset.entries.empty()) {
return;
}
glEnablei(GL_BLEND, 0);
if (_useAdditiveBlending) {
glDepthMask(false);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
}
else {
// Normal blending, with transparency
glDepthMask(true);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
_program->activate();
_program->setUniform(_uniformCache.cameraPos, data.camera.positionVec3());
_program->setUniform(
_uniformCache.cameraLookup,
glm::vec3(data.camera.lookUpVectorWorldSpace())
);
_program->setUniform(_uniformCache.renderOption, _renderOption.value());
_program->setUniform(_uniformCache.modelMatrix, modelMatrix);
_program->setUniform(
_uniformCache.cameraViewMatrix,
data.camera.combinedViewMatrix()
);
_program->setUniform(
_uniformCache.projectionMatrix,
glm::dmat4(data.camera.projectionMatrix())
);
_program->setUniform(_uniformCache.up, glm::vec3(orthoUp));
_program->setUniform(_uniformCache.right, glm::vec3(orthoRight));
_program->setUniform(_uniformCache.fadeInValue, fadeInVariable);
bindDataForPointRendering();
glBindVertexArray(_vao);
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_dataset.entries.size()));
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(_nDataPoints));
glBindVertexArray(0);
_program->deactivate();
@@ -857,9 +871,13 @@ void RenderablePointCloud::render(const RenderData& data, RendererTasks&) {
}
}
void RenderablePointCloud::preUpdate() {}
void RenderablePointCloud::update(const UpdateData&) {
ZoneScoped;
preUpdate();
if (_dataIsDirty) {
updateBufferData();
}
@@ -869,8 +887,16 @@ void RenderablePointCloud::update(const UpdateData&) {
}
}
glm::dvec3 RenderablePointCloud::transformedPosition(
const dataloader::Dataset::Entry& e) const
{
const double unitMeter = toMeter(_unit);
glm::dvec4 position = glm::dvec4(glm::dvec3(e.position) * unitMeter, 1.0);
return glm::dvec3(_transformationMatrix * position);
}
int RenderablePointCloud::nAttributesPerPoint() const {
int n = 4; // position
int n = 3; // position
n += _hasColorMapFile ? 1 : 0;
n += _hasDatavarSize ? 1 : 0;
return n;
@@ -909,13 +935,13 @@ void RenderablePointCloud::updateBufferData() {
glEnableVertexAttribArray(positionAttrib);
glVertexAttribPointer(
positionAttrib,
4,
3,
GL_FLOAT,
GL_FALSE,
attibutesPerPoint * sizeof(float),
nullptr
);
attributeOffset += 4;
attributeOffset += 3;
if (_hasColorMapFile) {
GLint colorParamAttrib = _program->attributeLocation("in_colorParameter");
@@ -1022,24 +1048,20 @@ std::vector<float> RenderablePointCloud::createDataSlice() {
int sizeParamIndex = currentSizeParameterIndex();
double maxRadius = 0.0;
double biggestCoord = -1.0;
for (const dataloader::Dataset::Entry& e : _dataset.entries) {
const double unitMeter = toMeter(_unit);
glm::dvec4 position = glm::dvec4(glm::dvec3(e.position) * unitMeter, 1.0);
position = _transformationMatrix * position;
glm::dvec3 position = transformedPosition(e);
const double r = glm::length(position);
maxRadius = std::max(maxRadius, r);
// Positions
for (int j = 0; j < 4; ++j) {
for (int j = 0; j < 3; ++j) {
result.push_back(static_cast<float>(position[j]));
}
// Colors
if (_hasColorMapFile) {
biggestCoord = std::max(biggestCoord, glm::compMax(position));
result.push_back(e.data[colorParamIndex]);
}

View File

@@ -74,8 +74,16 @@ public:
static documentation::Documentation Documentation();
protected:
int nAttributesPerPoint() const;
void updateBufferData();
virtual void initializeShadersAndGlExtras();
virtual void deinitializeShaders();
virtual void bindDataForPointRendering();
virtual void preUpdate();
glm::dvec3 transformedPosition(const dataloader::Dataset::Entry& e) const;
virtual int nAttributesPerPoint() const;
virtual void updateBufferData();
void updateSpriteTexture();
/// Find the index of the currently chosen color parameter in the dataset
@@ -83,7 +91,7 @@ protected:
/// Find the index of the currently chosen size parameter in the dataset
int currentSizeParameterIndex() const;
std::vector<float> createDataSlice();
virtual std::vector<float> createDataSlice();
virtual void bindTextureForRendering() const;

View File

@@ -0,0 +1,91 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
#include "PowerScaling/powerScaling_vs.hglsl"
in vec3 in_position0;
in vec3 in_position1;
// Only used if spline interpolation is desired
in vec3 in_position_before;
in vec3 in_position_after;
in float in_colorParameter0;
in float in_colorParameter1;
in float in_scalingParameter0;
in float in_scalingParameter1;
uniform bool useSpline;
uniform float interpolationValue;
flat out float colorParameter;
flat out float scalingParameter;
float interpolateDataValue(float v0, float v1, float t) {
const float Epsilon = 1E-7;
const float NaN = log(-1.0); // undefined
// To make sure we render values at knots with neighboring missing values,
// check 0 and 1 expicitly
if (abs(t) < Epsilon) {
return v0;
}
if (abs(1.0 - t) < Epsilon) {
return v1;
}
bool isMissing = isnan(v0) || isnan(v1);
return isMissing ? NaN : mix(v0, v1, t);
}
vec3 interpolateCatmullRom(float t, vec3 p0, vec3 p1, vec3 p2, vec3 p3) {
float t2 = t * t;
float t3 = t2 * t;
return 0.5 * (
2.0 * p1 +
t * (p2 - p0) +
t2 * (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) +
t3 * (3.0 * p1 - p0 - 3.0 * p2 + p3)
);
}
void main() {
float t = interpolationValue;
colorParameter = interpolateDataValue(in_colorParameter0, in_colorParameter1, t);
scalingParameter = interpolateDataValue(in_scalingParameter0, in_scalingParameter1, t);
vec3 position = mix(in_position0, in_position1, t);
if (useSpline) {
position = interpolateCatmullRom(
t,
in_position_before,
in_position0,
in_position1,
in_position_after
);
}
gl_Position = vec4(position, 1.0);
}

View File

@@ -26,7 +26,7 @@
#include "PowerScaling/powerScaling_vs.hglsl"
in vec4 in_position;
in vec3 in_position;
in float in_colorParameter;
in float in_scalingParameter;
@@ -36,5 +36,5 @@ flat out float scalingParameter;
void main() {
colorParameter = in_colorParameter;
scalingParameter = in_scalingParameter;
gl_Position = in_position;
gl_Position = vec4(in_position, 1.0);
}