public inbox for xconq7@sourceware.org
 help / color / mirror / Atom feed
* Thoughts on terrain imaging
@ 2004-11-23 16:44 mskala
  2004-11-23 22:08 ` Eric McDonald
  2004-11-24 13:00 ` Eric McDonald
  0 siblings, 2 replies; 6+ messages in thread
From: mskala @ 2004-11-23 16:44 UTC (permalink / raw)
  To: xconq7

[-- Attachment #1: Type: TEXT/PLAIN, Size: 8251 bytes --]

I started taking a look at how to implement the idea I was describing back
in September, of taking a chunk of an image file and displaying it to
replace other terrain images.  Once I started digging around in the code,
I found what I think is probably the best way to do it, which runs as
follows:

* Extend the current "subimages" concept in the image-family system.  You
can already specify special types of images, namely "tile", "border",
"connection", and "transition", and you can specify (for regular images,
which could be cell terrain or units) multiple "subimages".  I propose to
add a new special type of image called "hexgrid".  When you specify a
"hexgrid" image, you specify a subrectangle of an image as you normally do
with other images, and you also specify a number of rows and columns (of
hexagonal cells).  Hexagonal chunks are automatically clipped out of the
source image starting from your specified coordinates, to make up a number
of "subimages" for the image family.

* Add data structures to the map to store, for each cell and cell terrain
type, pointers to image families and subimage numbers for
"override" images.

* Change interfaces so that when they go looking for a cell terrain image
for a given cell, if there is an applicable override image at that cell,
they use it instead.  I'm hoping to keep the amount of per-interface code
for this as small as possible; that should be reasonably easy to do,
because it's mostly just a matter of extending the call interfaces make to
say "Hey, what's the image for this terrain type?" to be "Hey, what's the
image for this terrain type *at these cell coordinates*?"

* Add appropriate forms to GDL to allow setting the override information.

I decided to try implementing these ideas, but I wanted to do it in such a
way that I could test each step and see that it was working before moving
on to the next one, so as a very first step, I wrote a simple game module
which would trigger the "subimage" code, figuring that next I could move
on to making it clip out the subimages in a hex grid instead of the
existing one-dimensional linear offset.  The results are at these URLs:
   http://ansuz.sooke.bc.ca/temporary/maptest.g
   http://ansuz.sooke.bc.ca/temporary/override.gif

Those are supposed to work with the existing code base; the "forest" cells
on the map are supposed to be filled with a random mixture of five
different hexagonal chunks taken out of override.gif (which, you will
note, contains a chunk of the existing map with the colours modified and
some minor edits so that I'll be able to see when it's correctly spliced
in).  In testing that, I discovered a bunch of issues with existing code,
with my test files (I haven't touched the code to actually modify it yet
at all), or issues that will come up soon:

* It doesn't work in the TCL interface except on the highest
magnification.  At other magnifications, the affected cells are just
black.  As far as I can tell, for some reason the automatic scale-down
code isn't running.  Isn't it supposed to?  I thought the idea was you
could specify just one resolution of an image and any others would be
automatically generated if necessary; that certainly works for units, but
at least in this case it doesn't seem to work for terrain.

* It doesn't seem to work in the SDL interface at all - I get a segfault,
see attached backtrace.  I haven't tested this extensively at all, so it's
possible it may be unrelated, but the same build of the SDL interface
seems at least sort of stable with other modules, so I suspect it's
something to do with the same issue as in the TCL interface - I didn't
specify more than one resolution for the terrain images, and there are
issues with generating the other sizes automatically.  This could be a
problem because someone who's doing this clip-and-insert thing will only
naturally have one resolution for the image, and it seems like a bad
thing to force the designer to provide multiple sizes of the same image
from outside the game; the resize code really should work.

* It seems like a shame that images can only have 256 colours, and this'll
be a bigger issue when we have image chunks of serious size, where all the
hexes in the chunk have to share the same palette.  Ideally I think this
would be fixed by making XConq capable of loading PNGs, but it looks like
there are 8-bit assumptions built into a lot of code, and at this point I
don't want to try to change them when that's not my main goal.

* It seems like maybe (I'm not quite clear on this) when there are a bunch
of subimages in an image, the GIF file is being re-read for each one.  
That could already be a performance issue for border/connection terrain;
but with satellite images there could be hundreds, or thousands, of
subimages from the same image, and it would really suck to have to spend
the time to load the GIF a thousand times over.  Better to cache it
somehow; but maybe that's already being done, since border/connection
terrain *doesn't* seem to create a huge loading-time problem, and is
already loading 63 subimages per terrain type.

* There is simply a lot of data involved in covering a whole map with
custom images.  There's not really any way around that.  I think it could
be a problem because there are some warnings I don't understand in the
code (imf.c lines 88-90 and uses of the flag defined there) about some
Windows interfaces having limits on "GDI memory", and there are measures
taken to cut features to save on the amount of imagery loaded.  For
instance, if the flag that says "we have to conserve GDI memory" is set,
then when you specify a lot of alternate images (like in my example file,
which specifies five) only the first three are used.  Well, with a patch
of satellite data you pretty much have to load all the subimages - but if
there are hundreds of them, and you can't afford to load a lot of images
in general, that's going to be a problem.  I don't think there's really
much way to avoid this, short of simply disabling the image-override
mechanism entirely when the "must not load too many images" flag is set.  
No matter what scheme we use, those images have to be loaded if we're
going to use them.  Maybe someone who knows more about Windows and what
that flag is actually for could shed some light on this issue.

* Minor thing, but something I'll include in my patch for sure: the (x n x
y) property for image families doesn't seem to permit negative x/y values,
and I think you'd be likely to want to use those far more often than you'd
want to define both of them to be non-zero, which is behaviour it does
permit.  Easy to change, just by changing ">0" to "!=0".  I'm also not
convinced that this parameter is really 100% correctly implemented in
general, but that's not really my problem and it obviously does at least
sort of work because the terrain in the existing "advanced" game uses it.  
I became interested in this bit of code because it's closely related to
the code I want to add for hex-grid clipping.

* If I clip chunks out of an image on a hexagonal grid, what I will get
will be overlapping rectangular images (88x96 or similar) without the hex
masks that I think the current system might produce.  I'm not sure how
interfaces use images or whether that's likely to be a problem; I suspect
it isn't a problem because of the success of my test files with the
current code, but if it turns out to be, then I guess I'll have to write
some code to generate a hexagonal clipping mask for the images.  The issue
is that the interface asks for an image for terrain for a given cell, the
imf code hands back an image, but that is a rectangle that covers the
bounding rectangle of the cell and includes pixels outside the bounds of
the cell, because there's not a hex mask to clip it to the cell... Will
the interface do the clipping?  Or do I have to generate a mask to go with
the image?  I guess I'll find that out by experiment later.  It seems like
something that the interface probably already has to do anyway, so it's
probably not a problem I need to solve; and if I did need to solve it, I
could, so it's no biggie.
-- 
Matthew Skala
mskala@ansuz.sooke.bc.ca                    Embrace and defend.
http://ansuz.sooke.bc.ca/

[-- Attachment #2: Type: TEXT/PLAIN, Size: 2944 bytes --]

mskala@opal:~/xcmap$ gdb /usr/local/src/xconq-latest/xconq/sdl/xconq
GNU gdb 5.3
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-slackware-linux"...
(gdb) run -g maptest.g
Starting program: /usr/local/src/xconq-latest/xconq/sdl/xconq -g maptest.g
[New Thread 16384 (LWP 28017)]

              Welcome to X11 Xconq version 7.5pre (November 2004)

Xconq is free software and you are welcome to distribute copies of it
under certain conditions; type "o copying" to see the conditions.
There is absolutely no warranty for Xconq; type "o warranty" for details.
Warning: maptest.g:230: Can't set unknown global named `bigicons'.
Making countries; done.
Growing countries; done.
Assigning players to sides; done.
Setting up AIs; done.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 28017)]
0x0815771f in blacken_masked_area(a_image_family*, a_image*, int, int, int) (
    imf=0x825a9f0, img=0x846fb50, rd=65535, g=0, b=65535) at imf.c:1233
1233            img->rawpalette[4 * black + 0] = black;
(gdb) bt
#0  0x0815771f in blacken_masked_area(a_image_family*, a_image*, int, int, int)
    (imf=0x825a9f0, img=0x846fb50, rd=65535, g=0, b=65535) at imf.c:1233
#1  0x0805e3be in sdl_copy_color_image (imf=0x0, img=0x846fb50,
    surface=0x8473248) at sdlimf.cc:125
#2  0x0805e133 in sdl_interp_image_1 (imf=0x825a9f0, img=0x846fb50,
    subimg=0x846fb50, subi=0, force=0) at sdlimf.cc:107
#3  0x0805df77 in sdl_interp_image (imf=0x825a9f0, img=0x846fb50, force=0)
    at sdlimf.cc:58
#4  0x0805deac in sdl_interp_imf(a_image_family*, a_image*, int) (
    imf=0x825a9f0, img=0x846fb50, force=0) at sdlimf.cc:40
#5  0x08156821 in add_shrunken_image (imf=0x825a9f0) at imf.c:863
#6  0x08157176 in best_image(a_image_family*, int, int) (imf=0x825a9f0, w=0,
    h=1) at imf.c:1037
#7  0x0804f616 in init_terrain_images () at sdlinit.cc:179
#8  0x0804f32d in init_display() () at sdlinit.cc:77
#9  0x0804e0c5 in init_all_displays () at sdlmain.cc:2296
#10 0x0804ef8c in launch_game() () at sdlmain.cc:2854
#11 0x08049fd7 in main (argc=136732824, argv=0x1) at sdlunix.cc:115
#12 0x40414bb4 in __libc_start_main () from /lib/libc.so.6
(gdb) list
115                     launch_game();
116             }
117             if (!option_popup_new_game_dialog)
118                 print_instructions();
119             /* At this point we know we can use popups instead of stdio for
120             warnings and messages and such. */
121             use_stdio = FALSE;
122             /* Go into the main play loop. */
123             ui_mainloop();
124
(gdb) quit

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-11-24 13:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-23 16:44 Thoughts on terrain imaging mskala
2004-11-23 22:08 ` Eric McDonald
2004-11-24  3:18   ` mskala
2004-11-24  4:25     ` Eric McDonald
2004-11-24 13:00 ` Eric McDonald
2004-11-25  2:50   ` mskala

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).