MegaGlest Forum
Modding and game content creation => Tools => Topic started by: MuwuM on 22 May 2012, 17:41:59
-
I developed a simple Heightmap Exporter/Importer. Supports gbm and mgm maps and png heightmaps.
http://muwns.eu/mgm/
Old Version:
http://www.muwum-lexicons.de/mgm/ (http://www.muwum-lexicons.de/mgm/)
with this tool you can get maps like this very easy:
(http://img717.imageshack.us/img717/5012/autral.png)
... the Heightmap for this was: (http://img51.imageshack.us/img51/9569/aust.png)
-
Cool!
-
Looks cool! :)
-
Great work MuwuM. A really great tool. :thumbup: Really great. Here is created a map (as experiment) in 3 seconds. ;D
(http://i45.tinypic.com/2n9eueb.png)
Thank you.
-
Nice simple tool for maps, thanks Muwum :thumbup:
-
I guess this tool http://www.earthsculptor.com/ (http://www.earthsculptor.com/) could be quite interesting for some mappers. It is free and has a heightmap exporter. In combination with your tool, you can certainly create some pretty good maps. (Works with Wine under Linux.)
-
Nice tool. :) Can you make the source code available just in case you or your webserver vanish at some point?
-
Can you make the source code available just in case you or your webserver vanish at some point?
of course:
index.php
<?php
if(!is_uploaded_file($_FILES['map']['tmp_name'])){
echo('<h1>Heightmap Exporter/Importer</h1><form action="?" method="post" enctype="multipart/form-data">
Map: <input type="file" name="map" /> This is the map to Export or Import the Heightmap.<br/>
Heightmap: <input type="file" name="highmap" /> If given: Import this Heightmap, if not: Export the Heightmap.<br/>
<input type="submit" value="Export/Import" />
</form> ');
}else{
include('readFunc.php');
$handle = fopen($_FILES['map']['tmp_name'], "rb");
$contents = '';
$version = getInt32($handle);
#echo('Version: '.$version.' <br/>');
$maxPlayers = getInt32($handle);
#echo('maxPlayers: '.$maxPlayers.' <br/>');
$width = getInt32($handle);
#echo('width: '.$width.' <br/>');
$height = getInt32($handle);
#echo('height: '.$height.' <br/>');
$altFactor = getInt32($handle);
#echo('altFactor: '.$altFactor.' <br/>');
$waterLevel = getInt32($handle);
#echo('waterLevel: '.$waterLevel.' <br/>');
$titel = getString($handle,128);
#echo('title: '.$titel.' <br/>');
$autor = getString($handle,128);
#echo('author: '.$autor.' <br/>');
if($version <= 1){
$description = getString($handle,256);
}else{
$description = getString($handle,128);
$magic = getInt32($handle);
$meta = getString($handle,124);
}
#echo('description: '.$description .' <br/>');
$i = 0;
while ($i < $maxPlayers) {
$startLocation[$i] = array(getInt32($handle),getInt32($handle));
#echo('<b>StartLocation Player '.$i .':</b> ('.$startLocation[$i][0].','.$startLocation[$i][1].')<br/>');
$i++;
}
$i = 0;
while ($i < $width * $height) {
$map[($i % $width)][(floor($i / $width))]['h'] = getFloat($handle);
$i++;
}
$i = 0;
while ($i < $width * $height) {
$map[($i % $width)][(floor($i / $width))]['s'] = getInt8($handle);
$i++;
}
$i = 0;
while ($i < $width * $height) {
$map[($i % $width)][(floor($i / $width))]['o'] = getInt8($handle);
$i++;
}
fclose($handle);
$faktor = 1;
$im = imagecreatetruecolor(($width)*$faktor, ($height)*$faktor);
$color = imagecolorallocatealpha($im, 255 ,255, 255,0);
imagefilledrectangle($im, 0, 0, $width*$faktor ,$height*$faktor, $color);
$i = 0;
while ($i < ($width) * ($height)) {
$co = $map[($i % $width)][(floor($i / $width))]['h'] / 20 * 255;
$color = imagecolorallocatealpha($im, $co ,$co, $co, 0);
imagefilledrectangle($im, ($i % $width)*$faktor, (floor($i / $width))*$faktor, ($i % $width+1)*$faktor-1,(floor($i / $width)+1)*$faktor-1, $color);
#echo('<b>Cell ('.($i % $width).','.(floor($i / $width)).')</b><br/><pre>');
#echo(' Height: '.$map[($i % $width)][(floor($i / $width))]['h'].' <br/>');
#echo(' Surface type: '.$map[($i % $width)][(floor($i / $width))]['s'].' <br/>');
#echo(' Object: '.$map[($i % $width)][(floor($i / $width))]['o'].' <br/>');
##echo(' Resource: '.getInt8($handle).' <br/>');
#echo('</pre>');
$i++;
}
if(is_uploaded_file($_FILES['highmap']['tmp_name']) ){
imagedestroy($im);
$im = imagecreatefrompng($_FILES['highmap']['tmp_name']);
$i = 0;
while ($i < ($width) * ($height)) {
$col = imagecolorsforindex ($im,imagecolorat($im, ($i % $width)*$faktor,(floor($i / $width))*$faktor));
$map[($i % $width)][(floor($i / $width))]['h'] = $col['red'] / 255 * 20;
#$color = imagecolorallocatealpha($im, 0 ,0, 0, / 20 * 127);
#imagefilledrectangle($im, ($i % $width)*$faktor, (floor($i / $width))*$faktor, ($i % $width+1)*$faktor-1,(floor($i / $width)+1)*$faktor-1, $color);
$i++;
}
$tmpfname = tempnam("/tmp", "map_");
$handle = fopen($tmpfname, "wb");
writeInt32($handle,$version);
writeInt32($handle,$maxPlayers);
writeInt32($handle,$width);
writeInt32($handle,$height);
writeInt32($handle,$altFactor);
writeInt32($handle,$waterLevel);
writeString($handle,$titel,128);
writeString($handle,$autor,128);
if($version <= 1){
writeString($handle,$description,256);
}else{
writeString($handle,$description,128);
writeInt32($handle,$magic);
writeString($handle,$meta,124);
}
$i = 0;
while ($i < $maxPlayers) {
writeInt32($handle,$startLocation[$i][0]);
writeInt32($handle,$startLocation[$i][1]);
$i++;
}
$i = 0;
while ($i < $width * $height) {
writeFloat($handle,$map[($i % $width)][(floor($i / $width))]['h']);
$i++;
}
$i = 0;
while ($i < $width * $height) {
writeInt8($handle,$map[($i % $width)][(floor($i / $width))]['s']);
$i++;
}
$i = 0;
while ($i < $width * $height) {
writeInt8($handle,$map[($i % $width)][(floor($i / $width))]['o']);
$i++;
}
fclose($handle);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$_FILES['map']['name']);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($tmpfname));
ob_clean();
flush();
readfile($tmpfname);
}else{
header('Content-type: image/png');
imagepng($im);
}
imagedestroy($im);
}
?>readFunc.php
<?php
function getInt32($handle){
$str = fread($handle, 4);
$buf = pack('a4',$str);
$res = unpack('l',$buf);
return $res[1];
}
function getInt8($handle){
$str = fread($handle,1);
$buf = pack('a',$str);
$res = unpack('c',$buf);
return $res[1];
}
function getString($handle,$length){
$str = fread($handle, $length);
$buf = pack('a'.$length,$str);
$res = unpack('a'.$length,$buf);
return $res[1];
}
function getFloat($handle){
$str = fread($handle, 4);
$buf = pack('a4',$str);
$res = unpack('f',$buf);
return $res[1];
}
function writeInt32($handle,$val){
$buf = pack('l',$val);
return fwrite($handle, $buf,4);
}
function writeInt8($handle,$val){
$buf = pack('c',$val);
return fwrite($handle, $buf,1);
}
function writeFloat($handle,$val){
$buf = pack('f',$val);
return fwrite($handle, $buf,4);
}
function writeString($handle,$val,$length){
$buf = pack('a'.$length,$val);
return fwrite($handle, $buf,$length);
}
?>
-
I suggest we add this to svn as well as to megaglest.org?
Thanks
-
Thanks for providing the source code, MuwuM.
I suggest we add this to svn as well as to megaglest.org?
The code currently lacks input validation and is prone to (at least) XSS. Until this is fixed I'd prefer not to host it on megaglest.org
-
I developed a simple Heightmap Exporter/Importer.
http://www.muwum-lexicons.de/mgm/ (http://www.muwum-lexicons.de/mgm/) (supports gbm and mgm maps and png heightmaps)
Does anyone still have have this? The link is dead :(
-
Up again, was offline a few days, as I am moving from one hoster to another
you might also try http://muwum.net/mgm/ (http://muwum.net/mgm/)
-
this should work very well together with the heightmap random generator of tribaltrouble:
https://github.com/ftomassetti/procedurality-lands (https://github.com/ftomassetti/procedurality-lands)
There was a download page on the oddlabs page but since it has been taken down, you can't download it anymore:
https://web.archive.org/web/20080629000920/http://oddlabs.com/procedurality.php (https://web.archive.org/web/20080629000920/http://oddlabs.com/procedurality.php)
-
We played around with this a bit and it turned out that the height differences are not big enough to get a nicely shaped map in MG. Maybe you can offer an additional multiplier for the height calculation to make the height differences more obvious ?
-
As I did not touch the code for ~ 3 years now, I would need to have a short look at it. I will do later this evening.
-
I just rewrote the code in JavaScript & HTML5 (as I prefer it much over php).
http://muwns.eu/mgm/ (http://muwns.eu/mgm/) (testing/not stable)
* Should run with all modern browsers
The whole map procressing is now done localy in web browser, so data is not send to server anymore and resistent to hacking (you can also save and start the file locally).
@ titi: I added a feature to change the contrast of the Heightmap.
Some improvements / more readable code will be done during christmas.
Also created a github repository: https://github.com/MuwuM/mgm-map-editor (https://github.com/MuwuM/mgm-map-editor)
-
Very nice thanks Muwuum!
-
Very nice indeed. :)
This is not just a serverless heightmap editor, it also serves to 'document' the map format more (we could totally use proper descriptions of our file formats and network protocols on the wiki).
And it could lay the foundation to a HTML/Javascript map editor. If anyone is willing to implement this I'll sure be happy to add an upload backend.
-
And it could lay the foundation to a HTML/Javascript map editor. If anyone is willing to implement this I'll sure be happy to add an upload backend.
Might be interesting for a personal project. I'm not sure if it's be worthwhile, though. What could it do that a desktop version couldn't? Mostly I'd think it'd be more limited, since we wouldn't be able to easily run MG to preview the map and there's performance concerns for any kind of larger operations (eg, one feature that comes to mind is treating the height levels of the map as an image and gaussian bluring this to get softer slopes). Probably not an issue at map making sizes, though, and I've done some pretty intensive stuff with JS (my current work involves WebRTC -- sharing video, audio, and screen capture).
I'm not sure what could be done better in a JS version that a desktop version.
-
And it could lay the foundation to a HTML/Javascript map editor. If anyone is willing to implement this I'll sure be happy to add an upload backend.
Might be interesting for a personal project. I'm not sure if it's be worthwhile, though. What could it do that a desktop version couldn't?
As desktop app it is written in C++. It can do everything (even embedding a web-browser running the dedicated HTML/JavaScript code).
But as of today HTML5 (and it's infrastructure) is extremly powerful and can do almost everything (only limited by security restrictions). ;)
Mostly I'd think it'd be more limited, since we wouldn't be able to easily run MG to preview the map
I agree. But we have the megaglest:// URL and we could also add something like support for base64 encoded Map files as url (then we would not even need to save the map as a file if we don't want to)
and there's performance concerns for any kind of larger operations (eg, one feature that comes to mind is treating the height levels of the map as an image and gaussian bluring this to get softer slopes). Probably not an issue at map making sizes, though, and I've done some pretty intensive stuff with JS (my current work involves WebRTC -- sharing video, audio, and screen capture).
As most browsers with good HTML5 support has very optimized code (e.g. GPU-rendering) for Canvas2D (already used in this tool) and WebGL (would be required to preview the map realtime in the browser or WYSIWYG-editing) performance should not be a too big issue. Anyway it is important to write the JavaScript code non-blocking (http://calendar.perfplanet.com/2010/the-truth-about-non-blocking-javascript/) that you won't see the anoying 'This site is not responding'-messages (already used in this tool).
I've done some pretty intensive stuff with JS (my current work involves WebRTC -- sharing video, audio, and screen capture).
I'm not sure what could be done better in a JS version that a desktop version.
e.g. you could use your WebRTC knowledge to add an feature to collaborativly edit maps ;D
It's probably more a question of preference than what is the technical restrictions. A great thing of JavaScript is the huge amount of small libraries that can handle stuff you do not want to develop by yourself.
There are also already HTML5 painting tools available that provide a huge amount of image editing. http://literallycanvas.com/ (http://literallycanvas.com/), https://www.picozu.com/ (https://www.picozu.com/)
Ok, regarding painting it would even be better to write a plugin for GIMP :D , but I hope you got my intention
-
We currently have a wxgtk based editor and model viewer. Build ing this is not much fun since it depends on old libraries which are not available on newer systems. Baxsto wrote an editor in QT, which is already better than the old one, but as far as I know it is not completely done, yet (and could not replace the model viewer). Maybe things would be easier on the web after all. (Or maybe it would just add yet another incomplete option. :P )
-
e.g. you could use your WebRTC knowledge to add an feature to collaborativly edit maps ;D
You probably shouldn't. WebRTC uses UDP. Perfectly suitable to lose some audio or video data (since being real time is what's important), but for collaborative editing, we really wouldn't want a user's change to go ignored (and order is likely important). Also, WebRTC only has native support on Firefox and Chrome for now. My work has to use ActiveX and Java plugins to get IE and Safari working (and that's a non-free third party solution).
A simple web sockets solution to communication is likely more ideal (I've been using SignalR for the signalling channel of said WebRTC application -- it's a nice RPC library for persistent connections, either via long polling or websockets).
-
Just added some features to edit the map (header data only)
Github (https://github.com/MuwuM/mgm-map-editor) and Online Version (http://muwns.eu/mgm/) updated
-
In general this works pretty good and you get wonderful maps, but at least the online version crashes my firefox quite fast.
-
Can you tell me which version of Firefox you are using/ is crashing?
Is it just not responsive or does it really break (firefox closes/tab 'dies'/...)
What actions lead to the crash? Any? Even when waiting? Editing giant maps, using randomizor, changing contrast of the map heights?
I develop with Chrome stable release and Firefox DeveloperEdition (depending on the PC I use, both pretty strong, at least for Website rendering) so there might be some issues I did not notice while testing.
It is not so easy to build long running tasks in browsers. Maybe I should have a look into WebWorkers, beside being hard to learn implement, they could help with such issues. Possibly using WebGL instead of Canvas2D would improve Performance, too.
-
I used this heightmap: https://de.wikipedia.org/wiki/H%C3%B6henfeld#/media/File:Heightmap.png
I scaled it to 128x128 locally and then I just loaded it. After changing the contrast some times and saving the result as a map firefox was frozen ( firefox version 44.0.1 )
This happened several times. ( using http://muwns.eu/mgm/ )
-
Ok, I will debug the issue.
Thank you for providing the information.
I am pretty shure it's an issue with the implementation of contrast. As it is done 100% by CPU now ::)
I will try to optimize this.
-
After 9 hours of refactoring and performance improvements I hopefully managed to find a solution.
Cloud you please check the issue again?
available on http://muwns.eu/mgm/ (http://muwns.eu/mgm/)
-
Uhh I forgot to answer, I already tested it when you replied and everything wokred for me now.
I am very sorry that I forgot to reply :'(
-
That sounds good :) Thank you for testing.