Jump to content

Generating an accurate altitude map for DCS/FC


Recommended Posts

Posted

From the brief look at the Tacview code I had this morning all it did was convert latitude and longitude to x and z, so we can easily change the Tacview code to have it write out the data on an x, z plane.

There are only 10 types of people in the world: Those who understand binary, and those who don't.

Posted
From the brief look at the Tacview code I had this morning all it did was convert latitude and longitude to x and z, so we can easily change the Tacview code to have it write out the data on an x, z plane.

 

Yeah seems easy enough to do. Will be perfect :D :thumbup:

 

Find bottom left corner, find upper right, split into boxes, save :)

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted
Yeah seems easy enough to do. Will be perfect :D :thumbup:

 

Find bottom left corner, find upper right, split into boxes, save :)

 

If you can write some LUA code to do this I'll run it and generate the PNGs.

There are only 10 types of people in the world: Those who understand binary, and those who don't.

Posted
If you can write some LUA code to do this I'll run it and generate the PNGs.

 

Do you feed the data to some other software for generating the PNGs or do you save to a raw file in between?

Maybe your PNG generation is in lua itself?

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted
Do you feed the data to some other software for generating the PNGs or do you save to a raw file in between?

Maybe your PNG generation is in lua itself?

 

No, the PNG generation is separate from LUA. Just use the same setup as what is done in the Tacview LUA file.

There are only 10 types of people in the world: Those who understand binary, and those who don't.

Posted (edited)
If you can write some LUA code to do this I'll run it and generate the PNGs.

 

Well, just wrote this right now so 90% it doesnt do the right thing and 75% it wont even run :). But we can build on it. I'd propose something like this:

 

 


----------------- SETTINGS GO HERE -------------

local lowLeft_lon = 41; -- define lower left corner
local lowLeft_lat = 35; -- define lower left corner
local highRight_lon = 45; -- define upper right corner
local highRight_lat = 45; -- define upper right corner

local subSquareSide = 37040; -- 20 nautical miles in meters
local dimSamples = 1200; -- number of steps per dimension inside each sub section (=pts-1)


------------------ ACTUAL WORK DONE BELOW -----------------

function SaveMap()

local lowLeftXZ = LoGeoCoordinatesToLoCoordinates(lowLeft_lon, lowLeft_lat);
local highRightXZ = LoGeoCoordinatesToLoCoordinates(highRight_lon, highRight_lat);

local xRange = highRightXZ.x - lowLeftXZ.x;
local zRange = highRightXZ.z - lowLeftXZ.z;
local xStart = lowLeftXZ.x;
local zStart = lowLeftXZ.z;

local xSteps = math.floor(0.5 + math.abs(xRange) / subSquareSide);
local zSteps = math.floor(0.5 + math.abs(zRange) / subSquareSide);
local xStep = xRange / xSteps;
local zStep = zRange / zSteps;

local SUBSECTION = {}; -- for memory reasons, we dont want to reallocate this for each new sub section

for ix = 1, xSteps do
	local x2 = xStart + ix * xStep;
	local x1 = x1 - xStep;
	for iz = 1,zSteps do
		local z2 = zStart + iz * zStep;
		local z1 = z2 - zStep;
		scanSquare(SUBSECTION, x1, x2, z1, z2, dimSamples);
		save(SUBSECTION, x1, x2, z1, z2, dimSamples);
	end
end

end

function scanSquare(SUBSECTION, xStart, xEnd, zStart, zEnd, dimSamples)
local xStep = (xEnd - xStart) / dimSamples;
local zStep = (zEnd - zStart) / dimSamples;

for ix = 0, dimSamples do
	local x = xStart + ix * xStep;
	for iz = 0, dimSamples do
		local z = zStart + iz * zStep;
		SUBSECTION[1 + ix][1 + iz] = LoGetAltitude(x, z); -- lua indices start with 1 right?
	end
end
end

function save(SUBSECTION, x1, x2, z1, z2, dimSamples)
-- Implement saving/compression here
end

 

That would include this box (which I guess we could make larger if we want to)

box.png

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted (edited)

Then there is also the question....how do we sample values from the images without completely unpacknig them to raw format :P. I have never done such a thing before. I was able to load them in java but that also stored them in a seriously inefficient format.

 

Loading them as OpenGL textures might do better, but I think that also uncompresses them entirely..hm..

Perhaps I have no choice but to load textures/images on demand and unload unused ones. Also to store several different

resolution ones for different zoom levels. :/. This is what I didn't really want, but unless I find a way to sample the images

without completely loading their raw format into memory, I'm stuck :P.

 

Maybe another way would be to go back to my original idea, basically an adaptive mesh solution.

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted

Regardless of unpacking, at some point or another you will have to load the data in to memory. You may want to try to use fancy algorithms, but I always favor the easy approach first and prove that it isn't workable before going for more complex solutions.

There are only 10 types of people in the world: Those who understand binary, and those who don't.

Posted (edited)
Regardless of unpacking, at some point or another you will have to load the data in to memory. You may want to try to use fancy algorithms, but I always favor the easy approach first and prove that it isn't workable before going for more complex solutions.

 

yes but the memory footprint difference is huge, comparing uncompressed to compressed. It all depends on the application what you need. It looks like I might need a decent number of zoom levels for this if I'm going to get it to work properly :P. I aint saying our/your work here is not usable for me. I will definitely use the pictures at a data source regardless. The question is if I should use them to generate the live datasource or if I should use the pictures themselves as a live datasource.

 

The simplest/most direct approach I have in mind right now is cache the files into ram, and uncompress the ones I need on demand. Also Ill need 3-5 zoom levels for my application hmm... Will be a bit of work ^^.

 

I'm thinking something like these steps: 30 m, 100 m, 500 m, 1 km. if we are lucky it shouldnt take more than 50 MB + 5 MB + 0.2 MB + 0.05 MB = 55.25 MB total if I store them compressed. But if I store them uncompressed......well....I simply can't ^^, not enough ram.

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted (edited)

Ok I've updated the data export script a bit. My idea is to send the data via sockets to a png-generating app. This though depends on a lua client class I wrote:

 

EDIT: rewrote it again. This one is actually exporting something :). havent checked everything about it yet but it seems to be working.

 


----------------- SETTINGS GO HERE -------------

local lowLeft_lon = 35; -- define lower left corner
local lowLeft_lat = 41; -- define lower left corner
local highRight_lon = 45; -- define upper right corner
local highRight_lat = 45; -- define upper right corner

local subSquareSide = 37040; -- 20 nautical miles in meters
local dimSamples = 1200; -- number of steps per dimension inside each sub section (=pts-1)


------------------ ACTUAL WORK DONE BELOW -----------------

local SUBSECTION = {}; -- for memory reasons, we dont want to reallocate this for each new sub section
	
local lowLeftXZ = LoGeoCoordinatesToLoCoordinates(lowLeft_lon, lowLeft_lat);
local highRightXZ = LoGeoCoordinatesToLoCoordinates(highRight_lon, highRight_lat);

local xRange = highRightXZ.x - lowLeftXZ.x;
local zRange = highRightXZ.z - lowLeftXZ.z;
local xStart = lowLeftXZ.x;
local zStart = lowLeftXZ.z;

local xSteps = math.floor(0.5 + math.abs(xRange) / subSquareSide);
local zSteps = math.floor(0.5 + math.abs(zRange) / subSquareSide);
local xStep = xRange / xSteps;
local zStep = zRange / zSteps;

function SaveMap(client)

-- Associate a grid index with this client object
if (not client.ix) or (not client.iz) then
	client.ix = 1;
	client.iz = 1;
elseif client.ix > xSteps or client.iz > zSteps then
	return;
end

-- Our for-loop
local x2 = xStart + client.ix * xStep;
local x1 = x2 - xStep;
local z2 = zStart + client.iz * zStep;
local z1 = z2 - zStep;
scanSquare(SUBSECTION, x1, x2, z1, z2, dimSamples, client.ix, client.iz);
save(SUBSECTION, client, x1, x2, z1, z2, dimSamples, client.ix, client.iz);			

--[[
client.ix = client.ix + 1;
if client.ix == xSteps then
	client.ix = 1;
	client.iz = client.iz + 1;
end--]]

client.iz = client.iz + 1;
if client.iz == zSteps then
	client.iz = 1;
	client.ix = client.ix + 1;
end
		
end

function scanSquare(SUBSECTION, xStart, xEnd, zStart, zEnd, dimSamples, ix, iz)

local xStep = (xEnd - xStart) / dimSamples;
local zStep = (zEnd - zStart) / dimSamples;

SUBSECTION[1] = string.format('%s%s', ix, '\n');
SUBSECTION[2] = string.format('%s%s', iz, '\n');
SUBSECTION[3] = string.format('%s%s', xStart, '\n');
SUBSECTION[4] = string.format('%s%s', xEnd, '\n');
SUBSECTION[5] = string.format('%s%s', zStart, '\n');
SUBSECTION[6] = string.format('%s%s', zEnd, '\n');

local offs = 1 + 6;

ptsPerLine = dimSamples + 1;

for ix = 0, dimSamples do
	local x = xStart + ix * xStep;
	local iBase = offs + ptsPerLine * ix;
	for iz = 0, dimSamples do
		local z = zStart + iz * zStep;
		SUBSECTION[iBase + iz] = string.format('%s%s', LoGetAltitude(x, z), '\n');
	end
end

end

function save(SUBSECTION, client, x1, x2, z1, z2, dimSamples)

-- Implement saving/compression here
local mapData = table.concat(SUBSECTION);
local mapDatalen = string.len(mapData);

-- Allow blocking 
client.connection:settimeout(nil);

-- Send the header and data
client:transmit(string.format('%s%s%s', '!!dnacv02mJ8onvalPD893HNid8V9h6782sdu!!', mapDatalen, '\n'));
client:transmit(mapData);

-- Resume non-blocking
client.connection:settimeout(0.0);

end

 

So unsure if you can use this Case.

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted (edited)

Well it is working (low res picture below). Now I need to store all this data as PNGs of different zoom levels - but that I leave for another day.

 

map.png

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted

Good stuff Yoda. You figured out how to make PNG's yourself?

There are only 10 types of people in the world: Those who understand binary, and those who don't.

Posted (edited)
Good stuff Yoda. You figured out how to make PNG's yourself?

 

Actually thats just a raw 16 bit greyscale image in Java, but Java has standard Imagewriters for PNG format among others, so that part is simple. The hard part will be after that - finding a way to efficiently select which images to load/unload to/from textures given the original pngs data without killing all available memory :P. Fortunately I was yesterday able to figure out how to make OpenGL share resources among different contexts so at least I will only load stuff once to the gpu, even though multiple views/mfds/instruments could be using it. (GEAR uses OpenGL for rendering)

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted (edited)

Unfortunately that compression is not enough compared to png but i will use it to lighten the load a little.

Consider I have a couple of gigs (>5) of data and S3 does 4:1 compression (It's static 4:1 afaik), pngs are more like 100:1 in these cases (due to lots of zeros), therefor I cannot cache the entire map to video mem on the highest resolution.

 

Right now I've run into a problem when calling getAltitude in lua. I seem to get

 

Square::findTrg(534, -444053.093750,740324.687500) - cycle
Square::findTrg(534, -444083.687500,740355.437500) - cycle
Square::findTrg(534, -444114.312500,740386.125000) - cycle

 

errors when calling the function on certain coordinates (not outside the map boundries afaik). I'm guessing this means that some internal ED C function is failing, though I don't know what I should do about it. Is there anything like a try/catch block in lua so that I can use some kind of fall back method here? Annoying to be half way through a "world scan" and bing......problem causes the entire scan to abort with that message.

 

EDIT: nevm that doesnt seem to be what's causing the problems...hmm.

 

EDIT2: Nevm, problems solved. Two problems. Lockon was running out of memory (saving 1.4 mil points in text format and concatenating them into 1 string is apparently bad, solution: reduce number of decimals). Problem 2: it stopped reading back subsections after 31, Solution: Increase parameter "maxSections" :)

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

Posted (edited)

Ok I've generated 3 zoom levels of test PNGs.

1. squares with approx 20 nm sides

2. squares with approx 60 nm sides

3. squares with approx 180 nm sides

 

If you want to see the test images you can have a look at http://www.gigurra.se/GEAR/maps

I did some manual work here, so I will at some point start working on an automated method of generating all zoom levels.

 

EDIT: Furthermore it might be pointless to use squares with sides < 50 nm. Turns out when using those small squares all you get is smooth data anyway, so I might just start with 50 nm squares and let opengl texture scaling do that smoothing instead of storing all those points. Compare the two images below. Can you tell which was recorded 1200x1200 on 20nm squares or 60 nm square? You prob can but there's not a huge difference.

 

zoomed60nm.png

unzoomed20nm.png

Edited by =RvE=Yoda

S = SPARSE(m,n) abbreviates SPARSE([],[],[],m,n,0). This generates the ultimate sparse matrix, an m-by-n all zero matrix. - Matlab help on 'sparse'

  • 1 year later...
Posted

Hi to all,

 

sorry if I re-open this interesting thread :). I would like to create an elevation chart as accurate as possibile of the actual 3D map used in DCS World, but I'm not a programmer and I can't use scripting that much...

 

I saw that some of you archievied to save image files that, as I understand, if joined together could represent an effective elevation chart. I have 2 question:

 

- Is there a way for a newbie like me to re-create such images, to combine them into an elevation chart?

- Do you think that could be possibile to create also a "polygons shadowing map" such as the one used for Tacview ACMI playback?

 

Thanks in advance for the answers :)

ChromiumDis.png

Author of DSMC, mod to enable scenario persistency and save updated miz file

Stable version & site: https://dsmcfordcs.wordpress.com/

Openbeta: https://github.com/Chromium18/DSMC

 

The thing is, helicopters are different from planes. An airplane by it's nature wants to fly, and if not interfered with too strongly by unusual events or by a deliberately incompetent pilot, it will fly. A helicopter does not want to fly. It is maintained in the air by a variety of forces in opposition to each other, and if there is any disturbance in this delicate balance the helicopter stops flying; immediately and disastrously.

  • 2 weeks later...
Posted

bump for the questions :(

(this will be the only one, if un-answered I will assume that it's impossible or too complicated to explain :) )

ChromiumDis.png

Author of DSMC, mod to enable scenario persistency and save updated miz file

Stable version & site: https://dsmcfordcs.wordpress.com/

Openbeta: https://github.com/Chromium18/DSMC

 

The thing is, helicopters are different from planes. An airplane by it's nature wants to fly, and if not interfered with too strongly by unusual events or by a deliberately incompetent pilot, it will fly. A helicopter does not want to fly. It is maintained in the air by a variety of forces in opposition to each other, and if there is any disturbance in this delicate balance the helicopter stops flying; immediately and disastrously.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...