Merge lp:~nha/widelands/opengl into lp:widelands

Proposed by Nicolai Hähnle on 2013-02-07
Status: Merged
Merged at revision: 6501
Proposed branch: lp:~nha/widelands/opengl
Merge into: lp:widelands
Diff against target: 4139 lines (+1650/-1730)
34 files modified
.bzrignore (+2/-0)
src/graphic/graphic.cc (+1/-15)
src/graphic/graphic.h (+3/-4)
src/graphic/igraphic.h (+4/-2)
src/graphic/image_loader.h (+0/-1)
src/graphic/render/gamerenderer.cc (+286/-0)
src/graphic/render/gamerenderer.h (+97/-0)
src/graphic/render/gamerenderer_gl.cc (+669/-0)
src/graphic/render/gamerenderer_gl.h (+132/-0)
src/graphic/render/gamerenderer_sdl.cc (+279/-0)
src/graphic/render/gamerenderer_sdl.h (+55/-0)
src/graphic/render/gameview_opengl.cc (+0/-104)
src/graphic/render/gameview_opengl.h (+0/-56)
src/graphic/render/gameview_sdl.cc (+0/-105)
src/graphic/render/gameview_sdl.h (+0/-50)
src/graphic/render/gl_surface_texture.cc (+2/-2)
src/graphic/render/gl_surface_texture.h (+1/-1)
src/graphic/render/minimaprenderer.cc (+5/-970)
src/graphic/render/minimaprenderer.h (+10/-69)
src/graphic/render/terrain_opengl.h (+0/-327)
src/graphic/rendertarget.h (+3/-1)
src/logic/instances.h (+1/-1)
src/logic/tribe.h (+1/-1)
src/logic/world.cc (+3/-0)
src/logic/world.h (+3/-1)
src/point.h (+4/-1)
src/rect.h (+1/-1)
src/wui/mapview.cc (+17/-14)
src/wui/mapview.h (+3/-0)
src/wui/minimap.cc (+3/-3)
worlds/blackland/terrainconf (+17/-1)
worlds/desert/terrainconf (+16/-0)
worlds/greenland/terrainconf (+16/-0)
worlds/winterland/terrainconf (+16/-0)
To merge this branch: bzr merge lp:~nha/widelands/opengl
Reviewer Review Type Date Requested Status
SirVer 2013-02-07 Approve on 2013-02-10
Review via email: mp+147207@code.launchpad.net

Description of the change

Rewrite the OpenGL renderer to be closer to OpenGL best practices. Using vertex arrays gets performance from < 0.5 fps to the point where OpenGL is no longer the bottleneck on at least my system. Tested both OpenGL and SDL rendering with a little bit of playing and editing.

Please take a quick look, in particular a quick test for regressions on different systems would be nice.

To post a comment you must log in.
Tino (tino79) wrote :

It works fine on windows, just noticed:
- If i deactivate OpenGL in the Advanced Options menu->Apply->Apply -> Widelands quits, not stderr.txt
- If i active OpenGL via Options menu => Back to main menu, but no fonts, only white bars. I can quit widelands and then the updated config gets written. But if i load a game => crash.

Manually changing config works and Widelands runs fine in both modes. Only on-the-fly change does not.

Nicolai Hähnle (nha) wrote :

Could you please check whether you get the same crashes in current trunk? I remembered having one similar crash when switching between software and OpenGL before my changes, but unfortunately I didn't follow up because I thought there may be something driver-related going on.

Tino (tino79) wrote :

Sorry, you are right. The same problem occurs with a trunk build.
I am pretty sure it worked at some point before.

Nicolai Hähnle (nha) wrote :

Thank you so much for testing! Could you file a bug report for that so we don't forget about it?

SirVer (sirver) wrote :

Nicolai! The code compiles and runs great on later Mac OS X - I cannot check with old OS X as my wife took the laptop with her to work. The speedup is quite tremendous: on 100x speed terrain rendering takes less than 15% CPU now on my box. Superb work as always from you.

As you might have noticed we took up a review kind of process. The specifics are not clear yet - I just learned on my job that this can be very useful and improve the code significantly. So here are some comments:

- the diff here on the site is borked (it reports merge conflicts). Can you repropose? I think it updates the diff.
- adding the intensity parameter to the load() function seems suboptimal. First it is very specific to OpenGL rendering as SDL has no use for it. Secondly it gives the class a second task (namely loading and then 'flattening' the image). How about moving the edge/road loading and ownership out of graphic into the gameview renderer and giving only the GLTextures the intensity parameter. You could even make a conversion (static) method that could convert an RGB to an intensity texture - this would slow startup by a tad, but would keep this stuff internal to the (gl) terrain rendering - I feel that is a cleaner design.
- Some of the functions (e.g. drawobject(), but also others) are very long and repetitive? Can you find some seams to offload stuff into private or even better static methods/functions? I would not feel comfi to refactor anything in those methods as they stand now :)
- "and should be treated as read-only by derived classes": You made two pointers const, why not the third as well? How about not making those protected members, but instead combine them into a struct RenderState or so and pass this down to the functions doing the work? Your call.
- RenderTarget & dst: I prefer to pass a mutable object by pointer. The reason is that it becomes apparent on the call site if the call might modify the object or not. I realize that you prefer to use reference when an object must be passed (i.e. cannot be NULL), but i feel adding an assert as first line to the function does an equally good job. Your choice of course.
- I love MapviewPixelFunctions. I will wrap some of those for Lua (there are some values hard coded there).
- You pass Point by value regularly - why not use a const reference?
- GameRenderer is a struct, but should be a class. We started to run into trouble with clang complaining about the difference. We now use Class for anything with non trivial methods and struct otherwise. Sorry, you need to type the public: now :)

lp:~nha/widelands/opengl updated on 2013-02-08
6513. By Nicolai Hähnle on 2013-02-08

Merge trunk

Nicolai Hähnle (nha) wrote :
Download full text (3.5 KiB)

> Nicolai! The code compiles and runs great on later Mac OS X - I cannot check with old OS X as my wife took the laptop with her to work. The speedup is quite tremendous: on 100x speed terrain rendering takes less than 15% CPU now on my box. Superb work as always from you.
Thank you.
> As you might have noticed we took up a review kind of process. The specifics are not clear yet - I just learned on my job that this can be very useful and improve the code significantly. So here are some comments:
>
> - the diff here on the site is borked (it reports merge conflicts). Can you repropose? I think it updates the diff.
Should be fixed now.
> - adding the intensity parameter to the load() function seems suboptimal. First it is very specific to OpenGL rendering as SDL has no use for it. Secondly it gives the class a second task (namely loading and then 'flattening' the image). How about moving the edge/road loading and ownership out of graphic into the gameview renderer and giving only the GLTextures the intensity parameter. You could even make a conversion (static) method that could convert an RGB to an intensity texture - this would slow startup by a tad, but would keep this stuff internal to the (gl) terrain rendering - I feel that is a cleaner design.
Loading the edge.png texture in GameRendererGL does make sense, though
then it would probably be best to make GameRendererGL a "singleton" to
avoid loading the texture multiple times. Or is your new image cache
meant to also cache textures provided by some other part of the code, so
that multiple instances of GameRendererGL would be using the same texture?
> - Some of the functions (e.g. drawobject(), but also others) are very long and repetitive? Can you find some seams to offload stuff into private or even better static methods/functions? I would not feel comfi to refactor anything in those methods as they stand now :)
I'll have to think about it. The problem is that a lot of that stuff is
inherently a two-pass approach.
> - "and should be treated as read-only by derived classes": You made two pointers const, why not the third as well?
The renderer is not supposed to modify egbase or player, but it _is_
supposed to modify the RenderTarget.
> How about not making those protected members, but instead combine them into a struct RenderState or so and pass this down to the functions doing the work? Your call.
> - RenderTarget & dst: I prefer to pass a mutable object by pointer. The reason is that it becomes apparent on the call site if the call might modify the object or not. I realize that you prefer to use reference when an object must be passed (i.e. cannot be NULL), but i feel adding an assert as first line to the function does an equally good job. Your choice of course.
So sigra's influence is in decline? I actually agree with you in
general, but I believe that most code still passes RenderTargets around
by reference and it's better to be consistent. Besides, it's usually
pretty obvious that you want RenderTargets to be modified.
> - I love MapviewPixelFunctions. I will wrap some of those for Lua (there are some values hard coded there).
> - You pass Point by value regularly - why not u...

Read more...

lp:~nha/widelands/opengl updated on 2013-02-09
6514. By Nicolai Hähnle on 2013-02-08

GameRenderer: pass Point by reference

6515. By Nicolai Hähnle on 2013-02-08

GameRenderer: change struct to class

6516. By Nicolai Hähnle on 2013-02-08

Refactor edge dithering

6517. By Nicolai Hähnle on 2013-02-08

Refactor base terrain rendering

6518. By Nicolai Hähnle on 2013-02-08

Refacter GameRenderer::draw_objects to have a bit less duplication

6519. By Nicolai Hähnle on 2013-02-09

Remove intensity flags from non-OpenGL loading

6520. By Nicolai Hähnle on 2013-02-09

Re-add USE_OPENGL guards

Nicolai Hähnle (nha) wrote :

I adjusted the code based on your comments, except the road rendering which just seemed a bit too awkward to unify. Does get_dither_edge_texture fit with your concept of how the ImageCache is supposed to work?

SirVer (sirver) wrote :

Not sure if the code in the diff is up to date again... I did a bzr merge and looked at my local copy.

Responses:
> So sigra's influence is in decline?
Erik has not been around for a long time now. He started a job and
mentioned some years back that this will likely make it hard for him to
continue on widelands. I wouldn't say that is 'influence is in decline',
we just develop, learn and change :)

> I actually agree with you in general, but I believe that most code still
>passes RenderTargets around by reference and it's better to be
>consistent. Besides, it's usually pretty obvious that you want
>RenderTargets to be modified.
Ack.

About get_dither_edge_texture: Yes, approximately. I pushed a branch for merging - I think what you want here is a new TransformedImage or directly using the SurfaceCache. I pushed my branch for review just now, so you can have a look at my design. As you were quicker with the merge proposal though, the fun of fixing the merge conflicts is on me, I guess.

Nitpicking:
- Widelands::Editor_Game_Base const &. Prefer to put const in front, more similar to a pointer. Same for other objects of course.
- class GameRenderer. Make boost::noncopyable?
- in some places inside function you could use const for variables more
  aggressively. This would give the compiler a better chance to
  optimise.
- What about the dynamic_casts? Why not static, we should know the types
  in all cases, right?
- assert(sizeof(basevertex) == 32); We have a compile assert statement
  for this somewhere.

These are just nits from my point of view. So I am completely fine with
merging this as is. Can you do the merge or should I - just remember to
never push your branch to trunk, always merge into trunk and push that.

review: Approve
SirVer (sirver) wrote :

Oh just as a comment: I will try to merge your and my branch in a new branch.

SirVer (sirver) wrote :

I merged our two branches in lp:~widelands-dev/widelands/opengl_and_autocache because I had time to do this today. I am not sure how to go forward now, though :). I do not want to redo the merge - it was quite a lot of work. Can we continue working on this joint branch?

As a sidenote, I am now going over this and do some of the fixes I suggested myself. I suggest for the future to always push to ~widelands-dev, so that the reviewer can do small fixes himself directly.

SirVer (sirver) wrote :

- I did fix the position of the const in const Klass&. I also added a style rule for this now (there are a lot of warnings in the rest of the code).
- Also added a boost::noncopyable to rendertarget.

Nicolai Hähnle (nha) wrote :

Nice, and thank you for merging those two branches! I have to run for now, so I would suggest you just do the merge into trunk whenever you're happy with it. Just some quick replies:

1. get_dither_edge_texture(): Since this is such a special case for now, I would just go directly to the SurfaceCache, but I don't have strong feelings about it. I haven't looked at your merge yet.

2. const-modifiers: Sigra was always very vocal about putting the const at the end, because that is more consistent with const-ness when you have pointers-to-pointers, and that just rubbed off a little bit onto me, but I have no strong feelings either way.

3. GameRenderer: Yes, should be boost::noncopyable, forgot about that.

4. const local variables: Compilers should be grown-up enough to be able to do optimizations themselves, but it does make sense to avoid future refactoring bugs.

5. Yes, those dynamic_casts could be static_casts, but it's not a performance critical path. In the spirit of defensive programming, one could leave it as is.

6. compile-time asserts: You're absolutely right about that.

SirVer (sirver) wrote :

1. I used the surface cache directly. I am a little unhappy that we copy and paste the image loading code here. I added a TODO for this which will let me sleep :-)

2. I do not understand this argument. const Klass* and const Klass& reads clearer to me. And you always read right to left. Oh well - mainly bikeshedding. I settled this for now by adding a new style checker rule. It reports > 1000 violations right now oO. Will see if I can get them fixed tonight.

3. done.
4. Couldn't be bothered for now to touch this. Just add as much const in as you can in the future. It makes life easier often (I just learned this at work basically).
5. Left as is. I trust you that it is not on timing critical paths.
6. done.

I did the fixes in the common branch and merged it into trunk. How cool is that: Widelands became faster, less demanding on the hardware and uses less memory and these improvements all came in one commit.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2012-06-20 09:07:10 +0000
+++ .bzrignore 2013-02-09 12:25:26 +0000
@@ -23,3 +23,5 @@
23/tribes/**/*.xhtml23/tribes/**/*.xhtml
24/global/**/*.xhtml24/global/**/*.xhtml
2525
26# Local KDevelop settings files
27**/.kdev_include_paths
2628
=== modified file 'src/graphic/graphic.cc'
--- src/graphic/graphic.cc 2013-01-05 20:11:57 +0000
+++ src/graphic/graphic.cc 2013-02-09 12:25:26 +0000
@@ -238,8 +238,7 @@
238238
239 m_caps.gl.multitexture =239 m_caps.gl.multitexture =
240 ((strstr(extensions, "GL_ARB_multitexture") != 0) and240 ((strstr(extensions, "GL_ARB_multitexture") != 0) and
241 (strstr(extensions, "GL_ARB_texture_env_combine") != 0))241 (strstr(extensions, "GL_ARB_texture_env_combine") != 0));
242 and (m_caps.gl.max_tex_combined >= 6);
243 log("Graphics: OpenGL: Multitexture capabilities ");242 log("Graphics: OpenGL: Multitexture capabilities ");
244 log(m_caps.gl.multitexture ? "sufficient\n" : "insufficient, only basic terrain rendering possible\n");243 log(m_caps.gl.multitexture ? "sufficient\n" : "insufficient, only basic terrain rendering possible\n");
245244
@@ -971,10 +970,6 @@
971 m_roadtextures->pic_road_normal = imgcache().load(PicMod_Game, buf, false);970 m_roadtextures->pic_road_normal = imgcache().load(PicMod_Game, buf, false);
972 snprintf(buf, sizeof(buf), "worlds/%s/pics/roadt_busy.png", worldname.c_str());971 snprintf(buf, sizeof(buf), "worlds/%s/pics/roadt_busy.png", worldname.c_str());
973 m_roadtextures->pic_road_busy = imgcache().load(PicMod_Game, buf, false);972 m_roadtextures->pic_road_busy = imgcache().load(PicMod_Game, buf, false);
974
975 // load edge texture
976 snprintf(buf, sizeof(buf), "worlds/%s/pics/edge.png", worldname.c_str());
977 m_edgetexture = imgcache().load(PicMod_Game, buf, false);
978}973}
979974
980/**975/**
@@ -987,12 +982,3 @@
987 return982 return
988 (roadtex == Widelands::Road_Normal ? m_roadtextures->pic_road_normal : m_roadtextures->pic_road_busy);983 (roadtex == Widelands::Road_Normal ? m_roadtextures->pic_road_normal : m_roadtextures->pic_road_busy);
989}984}
990
991/**
992 * Returns the alpha mask texture for edges.
993 * \return The edge texture (alpha mask)
994 */
995const IPicture* Graphic::get_edge_texture()
996{
997 return m_edgetexture;
998}
999985
=== modified file 'src/graphic/graphic.h'
--- src/graphic/graphic.h 2013-01-05 18:52:13 +0000
+++ src/graphic/graphic.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team2 * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -119,7 +119,8 @@
119119
120 void save_png(const IPicture*, StreamWrite*) const;120 void save_png(const IPicture*, StreamWrite*) const;
121121
122 virtual IPicture* convert_sdl_surface_to_picture(SDL_Surface *, bool alpha = false) const;122 virtual IPicture* convert_sdl_surface_to_picture
123 (SDL_Surface *, bool alpha = false) const;
123124
124 Surface* create_surface(int32_t w, int32_t h, bool alpha = false) const;125 Surface* create_surface(int32_t w, int32_t h, bool alpha = false) const;
125126
@@ -144,7 +145,6 @@
144145
145 void set_world(std::string);146 void set_world(std::string);
146 const IPicture* get_road_texture(int32_t roadtex);147 const IPicture* get_road_texture(int32_t roadtex);
147 const IPicture* get_edge_texture();
148148
149 const GraphicCaps& caps() const throw () {return m_caps;}149 const GraphicCaps& caps() const throw () {return m_caps;}
150150
@@ -178,7 +178,6 @@
178 /// stores which features the current renderer has178 /// stores which features the current renderer has
179 GraphicCaps m_caps;179 GraphicCaps m_caps;
180 Road_Textures * m_roadtextures;180 Road_Textures * m_roadtextures;
181 const IPicture* m_edgetexture;
182 std::vector<Texture *> m_maptextures;181 std::vector<Texture *> m_maptextures;
183 std::vector<AnimationGfx *> m_animations;182 std::vector<AnimationGfx *> m_animations;
184183
185184
=== modified file 'src/graphic/igraphic.h'
--- src/graphic/igraphic.h 2012-12-15 18:40:59 +0000
+++ src/graphic/igraphic.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2006-2012 by the Widelands Development Team2 * Copyright (C) 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -32,7 +32,9 @@
32public:32public:
33 virtual ~IGraphic() {};33 virtual ~IGraphic() {};
3434
35 virtual IPicture* convert_sdl_surface_to_picture(SDL_Surface*, bool alpha = false) const = 0;35 virtual IPicture* convert_sdl_surface_to_picture
36 (SDL_Surface*,
37 bool alpha = false) const = 0;
36 virtual IBlitableSurface * create_surface(int32_t w, int32_t h, bool alpha = false) const = 0;38 virtual IBlitableSurface * create_surface(int32_t w, int32_t h, bool alpha = false) const = 0;
3739
38 virtual ImageCache& imgcache() const = 0;40 virtual ImageCache& imgcache() const = 0;
3941
=== modified file 'src/graphic/image_loader.h'
--- src/graphic/image_loader.h 2012-12-13 21:10:32 +0000
+++ src/graphic/image_loader.h 2013-02-09 12:25:26 +0000
@@ -34,4 +34,3 @@
34};34};
3535
36#endif /* end of include guard: IMAGE_LOADER_H */36#endif /* end of include guard: IMAGE_LOADER_H */
37
3837
=== added file 'src/graphic/render/gamerenderer.cc'
--- src/graphic/render/gamerenderer.cc 1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer.cc 2013-02-09 12:25:26 +0000
@@ -0,0 +1,286 @@
1/*
2 * Copyright (C) 2010-2013 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#include "gamerenderer.h"
21
22#include "graphic/rendertarget.h"
23
24#include "logic/editor_game_base.h"
25#include "logic/player.h"
26
27#include "wui/mapviewpixelfunctions.h"
28#include "wui/overlay_manager.h"
29
30#include "upcast.h"
31
32using namespace Widelands;
33
34GameRenderer::GameRenderer()
35{
36}
37
38GameRenderer::~GameRenderer()
39{
40}
41
42void GameRenderer::rendermap
43 (RenderTarget & dst,
44 Widelands::Editor_Game_Base const & egbase,
45 Widelands::Player const & player,
46 Point const & viewofs)
47{
48 m_dst = &dst;
49 m_dst_offset = -viewofs;
50 m_egbase = &egbase;
51 m_player = &player;
52
53 draw_wrapper();
54}
55
56void GameRenderer::rendermap
57 (RenderTarget & dst,
58 Widelands::Editor_Game_Base const & egbase,
59 Point const & viewofs)
60{
61 m_dst = &dst;
62 m_dst_offset = -viewofs;
63 m_egbase = &egbase;
64 m_player = 0;
65
66 draw_wrapper();
67}
68
69void GameRenderer::draw_wrapper()
70{
71 Point tl_map = m_dst->get_offset() - m_dst_offset;
72
73 assert(tl_map.x >= 0); // divisions involving negative numbers are bad
74 assert(tl_map.y >= 0);
75
76 m_minfx = tl_map.x / TRIANGLE_WIDTH - 1;
77 m_minfy = tl_map.y / TRIANGLE_HEIGHT - 1;
78 m_maxfx = (tl_map.x + m_dst->get_rect().w + (TRIANGLE_WIDTH / 2)) / TRIANGLE_WIDTH;
79 m_maxfy = (tl_map.y + m_dst->get_rect().h) / TRIANGLE_HEIGHT;
80
81 // fudge for triangle boundary effects and for height differences
82 m_minfx -= 1;
83 m_minfy -= 1;
84 m_maxfx += 1;
85 m_maxfy += 10;
86
87 draw();
88}
89
90void GameRenderer::draw_objects()
91{
92 static const uint32_t F = 0;
93 static const uint32_t R = 1;
94 static const uint32_t BL = 2;
95 static const uint32_t BR = 3;
96 Map const & map = m_egbase->map();
97
98 for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
99 for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
100 Coords ncoords(fx, fy);
101 map.normalize_coords(ncoords);
102 FCoords coords[4];
103 coords[F] = map.get_fcoords(ncoords);
104 coords[R] = map.r_n(coords[F]);
105 coords[BL] = map.bl_n(coords[F]);
106 coords[BR] = map.br_n(coords[F]);
107 Point pos[4];
108 MapviewPixelFunctions::get_basepix(Coords(fx, fy), pos[F].x, pos[F].y);
109 MapviewPixelFunctions::get_basepix(Coords(fx + 1, fy), pos[R].x, pos[R].y);
110 MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1) - 1, fy + 1), pos[BL].x, pos[BL].y);
111 MapviewPixelFunctions::get_basepix(Coords(fx + (fy & 1), fy + 1), pos[BR].x, pos[BR].y);
112 for (uint32_t d = 0; d < 4; ++d) {
113 pos[d].y -= coords[d].field->get_height() * HEIGHT_FACTOR;
114 pos[d] += m_dst_offset;
115 }
116
117 Player_Number owner_number[4];
118 bool isborder[4];
119 Vision vision[4] = {2, 2, 2, 2};
120 for (uint32_t d = 0; d < 4; ++d)
121 owner_number[d] = coords[d].field->get_owned_by();
122 for (uint32_t d = 0; d < 4; ++d)
123 isborder[d] = coords[d].field->is_border();
124
125 if (m_player && !m_player->see_all()) {
126 for (uint32_t d = 0; d < 4; ++d) {
127 Player::Field const & pf = m_player->fields()[map.get_index(coords[d], map.get_width())];
128 vision[d] = pf.vision;
129 if (pf.vision == 1) {
130 owner_number[d] = pf.owner;
131 isborder[d] = pf.border;
132 }
133 }
134 }
135
136 if (isborder[F]) {
137 Player const & owner = m_egbase->player(owner_number[F]);
138 uint32_t const anim = owner.frontier_anim();
139 if (vision[F])
140 m_dst->drawanim(pos[F], anim, 0, &owner);
141 for (uint32_t d = 1; d < 4; ++d) {
142 if
143 ((vision[F] || vision[d]) &&
144 isborder[d] &&
145 (owner_number[d] == owner_number[F] || !owner_number[d]))
146 {
147 m_dst->drawanim(middle(pos[F], pos[d]), anim, 0, &owner);
148 }
149 }
150 }
151
152 if (1 < vision[F]) { // Render stuff that belongs to the node.
153 if (BaseImmovable * const imm = coords[F].field->get_immovable())
154 imm->draw(*m_egbase, *m_dst, coords[F], pos[F]);
155 for
156 (Bob * bob = coords[F].field->get_first_bob();
157 bob;
158 bob = bob->get_next_bob())
159 bob->draw(*m_egbase, *m_dst, pos[F]);
160 } else if (vision[F] == 1) {
161 Player::Field const & f_pl = m_player->fields()[map.get_index(coords[F], map.get_width())];
162 const Player * owner = owner_number[F] ? m_egbase->get_player(owner_number[F]) : 0;
163 if
164 (const Map_Object_Descr * const map_object_descr =
165 f_pl.map_object_descr[TCoords<>::None])
166 {
167 if
168 (const Player::Constructionsite_Information * const csinf =
169 f_pl.constructionsite[TCoords<>::None])
170 {
171 // draw the partly finished constructionsite
172 uint32_t anim;
173 try {
174 anim = csinf->becomes->get_animation("build");
175 } catch (Map_Object_Descr::Animation_Nonexistent & e) {
176 try {
177 anim = csinf->becomes->get_animation("unoccupied");
178 } catch (Map_Object_Descr::Animation_Nonexistent) {
179 anim = csinf->becomes->get_animation("idle");
180 }
181 }
182 const AnimationGfx::Index nr_frames = g_gr->nr_frames(anim);
183 uint32_t cur_frame =
184 csinf->totaltime ? csinf->completedtime * nr_frames / csinf->totaltime : 0;
185 uint32_t tanim = cur_frame * FRAME_LENGTH;
186 uint32_t w, h;
187 g_gr->get_animation_size(anim, tanim, w, h);
188 uint32_t lines = h * csinf->completedtime * nr_frames;
189 if (csinf->totaltime)
190 lines /= csinf->totaltime;
191 assert(h * cur_frame <= lines);
192 lines -= h * cur_frame; // This won't work if pictures have various sizes.
193
194 if (cur_frame) // not the first frame
195 // draw the prev frame from top to where next image will be drawing
196 m_dst->drawanimrect
197 (pos[F], anim, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
198 else if (csinf->was) {
199 // Is the first frame, but there was another building here before,
200 // get its last build picture and draw it instead.
201 uint32_t a;
202 try {
203 a = csinf->was->get_animation("unoccupied");
204 } catch (Map_Object_Descr::Animation_Nonexistent & e) {
205 a = csinf->was->get_animation("idle");
206 }
207 m_dst->drawanimrect
208 (pos[F], a, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
209 }
210 assert(lines <= h);
211 m_dst->drawanimrect(pos[F], anim, tanim, owner, Rect(Point(0, h - lines), w, lines));
212 } else if (upcast(const Building_Descr, building, map_object_descr)) {
213 // this is a building therefore we either draw unoccupied or idle animation
214 uint32_t pic;
215 try {
216 pic = building->get_animation("unoccupied");
217 } catch (Map_Object_Descr::Animation_Nonexistent & e) {
218 pic = building->get_animation("idle");
219 }
220 m_dst->drawanim(pos[F], pic, 0, owner);
221 } else if (const uint32_t pic = map_object_descr->main_animation()) {
222 m_dst->drawanim(pos[F], pic, 0, owner);
223 } else if (map_object_descr == &Widelands::g_flag_descr) {
224 m_dst->drawanim(pos[F], owner->flag_anim(), 0, owner);
225 }
226 }
227 }
228
229 {
230 // Render overlays on the node
231 Overlay_Manager::Overlay_Info overlay_info[MAX_OVERLAYS_PER_NODE];
232
233 const Overlay_Manager::Overlay_Info * const end =
234 overlay_info
235 +
236 map.overlay_manager().get_overlays(coords[F], overlay_info);
237
238 for
239 (const Overlay_Manager::Overlay_Info * it = overlay_info;
240 it < end;
241 ++it)
242 m_dst->blit(pos[F] - it->hotspot, it->pic);
243 }
244
245 {
246 // Render overlays on the R triangle
247 Overlay_Manager::Overlay_Info overlay_info[MAX_OVERLAYS_PER_TRIANGLE];
248 Overlay_Manager::Overlay_Info const * end =
249 overlay_info
250 +
251 map.overlay_manager().get_overlays
252 (TCoords<>(coords[F], TCoords<>::R), overlay_info);
253
254 Point tripos
255 ((pos[F].x + pos[R].x + pos[BR].x) / 3,
256 (pos[F].y + pos[R].y + pos[BR].y) / 3);
257
258 for
259 (Overlay_Manager::Overlay_Info const * it = overlay_info;
260 it < end;
261 ++it)
262 m_dst->blit(tripos - it->hotspot, it->pic);
263 }
264
265 {
266 // Render overlays on the D triangle
267 Overlay_Manager::Overlay_Info overlay_info[MAX_OVERLAYS_PER_TRIANGLE];
268 Overlay_Manager::Overlay_Info const * end =
269 overlay_info
270 +
271 map.overlay_manager().get_overlays
272 (TCoords<>(coords[F], TCoords<>::D), overlay_info);
273
274 Point tripos
275 ((pos[F].x + pos[BL].x + pos[BR].x) / 3,
276 (pos[F].y + pos[BL].y + pos[BR].y) / 3);
277
278 for
279 (Overlay_Manager::Overlay_Info const * it = overlay_info;
280 it < end;
281 ++it)
282 m_dst->blit(tripos - it->hotspot, it->pic);
283 }
284 }
285 }
286}
0287
=== added file 'src/graphic/render/gamerenderer.h'
--- src/graphic/render/gamerenderer.h 1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer.h 2013-02-09 12:25:26 +0000
@@ -0,0 +1,97 @@
1/*
2 * Copyright (C) 2010-2013 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#ifndef WIDELANDS_GAMERENDERER_H
21#define WIDELANDS_GAMERENDERER_H
22
23#include "point.h"
24
25namespace Widelands {
26 struct Player;
27 struct Editor_Game_Base;
28};
29
30struct RenderTarget;
31
32/**
33 * This abstract base class renders the main game view into an
34 * arbitrary @ref RenderTarget.
35 *
36 * Specializations exist for SDL software rendering and for OpenGL rendering.
37 *
38 * Users of this class should keep instances alive for as long as possible,
39 * so that target-specific optimizations (such as caching data) can
40 * be effective.
41 */
42class GameRenderer {
43public:
44 GameRenderer();
45 virtual ~GameRenderer();
46
47 /**
48 * Renders the map from a player's point of view into the
49 * given drawing window.
50 *
51 * @param viewofs is the offset of the upper left corner of
52 * the window into the map, in pixels.
53 */
54 void rendermap
55 (RenderTarget & dst,
56 Widelands::Editor_Game_Base const & egbase,
57 Widelands::Player const & player,
58 Point const & viewofs);
59
60 /**
61 * Renders the map from an omniscient perspective.
62 * This is used for spectators, players that see all, and in the editor.
63 */
64 void rendermap
65 (RenderTarget & dst,
66 Widelands::Editor_Game_Base const & egbase,
67 Point const & viewofs);
68
69protected:
70 virtual void draw() = 0;
71
72 void draw_objects();
73
74 /**
75 * The following variables, which are setup by @ref rendermap,
76 * are only valid during rendering,
77 * and should be treated as read-only by derived classes.
78 */
79 /*@{*/
80 RenderTarget * m_dst;
81 Widelands::Editor_Game_Base const * m_egbase;
82 Widelands::Player const * m_player;
83
84 /// Translation from map pixel coordinates to @ref m_dst pixel coordinates
85 Point m_dst_offset;
86
87 int32_t m_minfx;
88 int32_t m_minfy;
89 int32_t m_maxfx;
90 int32_t m_maxfy;
91 /*@}*/
92
93private:
94 void draw_wrapper();
95};
96
97#endif //WIDELANDS_GAMEVIEW_H
098
=== added file 'src/graphic/render/gamerenderer_gl.cc'
--- src/graphic/render/gamerenderer_gl.cc 1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_gl.cc 2013-02-09 12:25:26 +0000
@@ -0,0 +1,669 @@
1/*
2 * Copyright (C) 2011-2013 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#ifdef USE_OPENGL
21#include "gamerenderer_gl.h"
22
23#include "gl_surface.h"
24
25#include "logic/editor_game_base.h"
26#include "logic/player.h"
27
28#include "graphic/graphic.h"
29#include "graphic/rendertarget.h"
30#include "graphic/texture.h"
31
32#include "wui/mapviewpixelconstants.h"
33#include "wui/mapviewpixelfunctions.h"
34#include "wui/overlay_manager.h"
35
36#include <SDL_image.h>
37
38using namespace Widelands;
39
40static const uint32_t PatchSize = 4;
41
42GameRendererGL::GameRendererGL() :
43 m_patch_vertices_size(0),
44 m_patch_indices_size(0),
45 m_edge_vertices_size(0),
46 m_road_vertices_size(0)
47{
48}
49
50GameRendererGL::~GameRendererGL()
51{
52}
53
54const GLSurfaceTexture * GameRendererGL::get_dither_edge_texture(const Widelands::World & world)
55{
56 char fname[256];
57 snprintf(fname, sizeof(fname), "%s/pics/edge.png", world.basedir().c_str());
58 std::string cachename = std::string("gltex#") + fname;
59
60 const GLSurfaceTexture * edgetexture =
61 dynamic_cast<const GLSurfaceTexture *>(g_gr->imgcache().get(PicMod_Game, cachename));
62 if (!edgetexture) {
63 FileRead fr;
64 fr.fastOpen(*g_fs, fname);
65
66 SDL_Surface * sdlsurf = IMG_Load_RW(SDL_RWFromMem(fr.Data(0), fr.GetSize()), 1);
67 if (!sdlsurf)
68 throw wexception("%s", IMG_GetError());
69
70 edgetexture = new GLSurfaceTexture(sdlsurf, true);
71 g_gr->imgcache().insert(PicMod_Game, cachename, edgetexture);
72 }
73 return edgetexture;
74}
75
76uint32_t GameRendererGL::patch_index(const Coords & f) const
77{
78 uint32_t x = f.x - m_patch_size.x;
79 uint32_t y = f.y - m_patch_size.y;
80
81 assert(x < m_patch_size.w);
82 assert(y < m_patch_size.h);
83
84 uint32_t outerx = x / PatchSize;
85 uint32_t outery = y / PatchSize;
86 uint32_t innerx = x % PatchSize;
87 uint32_t innery = y % PatchSize;
88
89 return
90 (outery * (m_patch_size.w / PatchSize) + outerx) * (PatchSize * PatchSize) +
91 innery * PatchSize + innerx;
92}
93
94uint8_t GameRendererGL::field_brightness(const FCoords & coords) const
95{
96 uint32_t brightness;
97 brightness = 144 + coords.field->get_brightness();
98 brightness = (brightness * 255) / 160;
99 if (brightness > 255)
100 brightness = 255;
101
102 if (m_player && !m_player->see_all()) {
103 const Map & map = m_egbase->map();
104 const Player::Field & pf = m_player->fields()[Map::get_index(coords, map.get_width())];
105 if (pf.vision == 0) {
106 return 0;
107 } else if (pf.vision == 1) {
108 static const uint32_t DecayTime = 20000;
109 Duration time_ago = m_egbase->get_gametime() - pf.time_node_last_unseen;
110 if (time_ago < DecayTime)
111 brightness = (brightness * (2 * DecayTime - time_ago)) / (2 * DecayTime);
112 else
113 brightness = brightness / 2;
114 }
115 }
116
117 return brightness;
118}
119
120void GameRendererGL::draw()
121{
122 m_surface = dynamic_cast<GLSurface *>(m_dst->get_surface());
123 if (!m_surface)
124 return;
125 m_rect = m_dst->get_rect();
126 m_surface_offset = m_dst_offset + m_rect + m_dst->get_offset();
127
128 m_patch_size.x = m_minfx - 1;
129 m_patch_size.y = m_minfy;
130 m_patch_size.w = ((m_maxfx - m_minfx + 2 + PatchSize) / PatchSize) * PatchSize;
131 m_patch_size.h = ((m_maxfy - m_minfy + 1 + PatchSize) / PatchSize) * PatchSize;
132
133 glScissor
134 (m_rect.x, m_surface->get_h() - m_rect.y - m_rect.h,
135 m_rect.w, m_rect.h);
136 glEnable(GL_SCISSOR_TEST);
137
138 prepare_terrain_base();
139 draw_terrain_base();
140 if (g_gr->caps().gl.multitexture && g_gr->caps().gl.max_tex_combined >= 2) {
141 prepare_terrain_dither();
142 draw_terrain_dither();
143 }
144 prepare_roads();
145 draw_roads();
146 draw_objects();
147
148 glDisable(GL_SCISSOR_TEST);
149}
150
151template<typename vertex>
152void GameRendererGL::compute_basevertex(const Coords & coords, vertex & vtx) const
153{
154 Map const & map = m_egbase->map();
155 Coords ncoords(coords);
156 map.normalize_coords(ncoords);
157 FCoords fcoords = map.get_fcoords(ncoords);
158 Point pix;
159 MapviewPixelFunctions::get_basepix(coords, pix.x, pix.y);
160 pix.y -= fcoords.field->get_height() * HEIGHT_FACTOR;
161 pix += m_surface_offset;
162 vtx.x = pix.x;
163 vtx.y = pix.y;
164 Point tex;
165 MapviewPixelFunctions::get_basepix(coords, tex.x, tex.y);
166 vtx.tcx = float(tex.x) / TEXTURE_WIDTH;
167 vtx.tcy = float(tex.y) / TEXTURE_HEIGHT;
168 uint8_t brightness = field_brightness(fcoords);
169 vtx.color[0] = vtx.color[1] = vtx.color[2] = brightness;
170 vtx.color[3] = 255;
171}
172
173void GameRendererGL::count_terrain_base(Terrain_Index ter)
174{
175 if (ter >= m_terrain_freq.size())
176 m_terrain_freq.resize(ter + 1);
177 m_terrain_freq[ter] += 1;
178}
179
180void GameRendererGL::add_terrain_base_triangle
181 (Terrain_Index ter, const Coords & p1, const Coords & p2, const Coords & p3)
182{
183 uint32_t index = m_patch_indices_indexs[ter];
184 m_patch_indices[index++] = patch_index(p1);
185 m_patch_indices[index++] = patch_index(p2);
186 m_patch_indices[index++] = patch_index(p3);
187 m_patch_indices_indexs[ter] = index;
188}
189
190void GameRendererGL::collect_terrain_base(bool onlyscan)
191{
192 Map const & map = m_egbase->map();
193
194 uint32_t index = 0;
195 for (uint32_t outery = 0; outery < m_patch_size.h / PatchSize; ++outery) {
196 for (uint32_t outerx = 0; outerx < m_patch_size.w / PatchSize; ++outerx) {
197 for (uint32_t innery = 0; innery < PatchSize; ++innery) {
198 for (uint32_t innerx = 0; innerx < PatchSize; ++innerx) {
199 Coords coords
200 (m_patch_size.x + outerx * PatchSize + innerx,
201 m_patch_size.y + outery * PatchSize + innery);
202
203 if (onlyscan) {
204 assert(index == patch_index(coords));
205 compute_basevertex(coords, m_patch_vertices[index]);
206 ++index;
207 }
208
209 if (coords.x >= m_minfx && coords.y >= m_minfy && coords.x <= m_maxfx && coords.y <= m_maxfy) {
210 Coords ncoords(coords);
211 map.normalize_coords(ncoords);
212 FCoords fcoords = map.get_fcoords(ncoords);
213 Terrain_Index ter_d = fcoords.field->get_terrains().d;
214 Terrain_Index ter_r = fcoords.field->get_terrains().r;
215
216 if (onlyscan) {
217 count_terrain_base(ter_d);
218 count_terrain_base(ter_r);
219 } else {
220 Coords brn(coords.x + (coords.y & 1), coords.y + 1);
221 Coords bln(brn.x - 1, brn.y);
222 Coords rn(coords.x + 1, coords.y);
223
224 add_terrain_base_triangle(ter_d, coords, bln, brn);
225 add_terrain_base_triangle(ter_r, coords, brn, rn);
226 }
227 }
228 }
229 }
230 }
231 }
232}
233
234void GameRendererGL::prepare_terrain_base()
235{
236 assert(sizeof(basevertex) == 32);
237
238 uint32_t reqsize = m_patch_size.w * m_patch_size.h;
239 if (reqsize > 0x10000)
240 throw wexception("Too many vertices; decrease screen resolution");
241
242 if (reqsize > m_patch_vertices_size) {
243 m_patch_vertices.reset(new basevertex[reqsize]);
244 m_patch_vertices_size = reqsize;
245 }
246
247 if (m_terrain_freq.size() < 16)
248 m_terrain_freq.resize(16);
249 m_terrain_freq.assign(m_terrain_freq.size(), 0);
250
251 collect_terrain_base(true);
252
253 m_terrain_freq_cum.resize(m_terrain_freq.size());
254 uint32_t nrtriangles = 0;
255 for (uint32_t idx = 0; idx < m_terrain_freq.size(); ++idx) {
256 m_terrain_freq_cum[idx] = nrtriangles;
257 nrtriangles += m_terrain_freq[idx];
258 }
259
260 if (3 * nrtriangles > m_patch_indices_size) {
261 m_patch_indices.reset(new uint16_t[3 * nrtriangles]);
262 m_patch_indices_size = 3 * nrtriangles;
263 }
264
265 m_patch_indices_indexs.resize(m_terrain_freq.size());
266 for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter)
267 m_patch_indices_indexs[ter] = 3 * m_terrain_freq_cum[ter];
268
269 collect_terrain_base(false);
270
271 for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter) {
272 assert(m_patch_indices_indexs[ter] == 3 * (m_terrain_freq_cum[ter] + m_terrain_freq[ter]));
273 }
274}
275
276void GameRendererGL::draw_terrain_base()
277{
278 Map const & map = m_egbase->map();
279 World const & world = map.world();
280
281 glMatrixMode(GL_TEXTURE);
282 glLoadIdentity();
283
284 glVertexPointer(2, GL_FLOAT, sizeof(basevertex), &m_patch_vertices[0].x);
285 glTexCoordPointer(2, GL_FLOAT, sizeof(basevertex), &m_patch_vertices[0].tcx);
286 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(basevertex), &m_patch_vertices[0].color);
287 glEnableClientState(GL_VERTEX_ARRAY);
288 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
289 glEnableClientState(GL_COLOR_ARRAY);
290
291 glColor3f(1.0, 1.0, 1.0);
292 glDisable(GL_BLEND);
293
294 for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter) {
295 if (!m_terrain_freq[ter])
296 continue;
297
298 const Texture & texture =
299 *g_gr->get_maptexture_data
300 (world.terrain_descr(ter).get_texture());
301 glBindTexture(GL_TEXTURE_2D, texture.getTexture());
302 glDrawRangeElements
303 (GL_TRIANGLES,
304 0, m_patch_size.w * m_patch_size.h - 1,
305 3 * m_terrain_freq[ter], GL_UNSIGNED_SHORT,
306 &m_patch_indices[3 * m_terrain_freq_cum[ter]]);
307 }
308
309 glDisableClientState(GL_VERTEX_ARRAY);
310 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
311 glDisableClientState(GL_COLOR_ARRAY);
312}
313
314void GameRendererGL::add_terrain_dither_triangle
315 (bool onlyscan, Terrain_Index ter, const Coords & edge1, const Coords & edge2, const Coords & opposite)
316{
317 if (onlyscan) {
318 if (ter >= m_terrain_edge_freq.size())
319 m_terrain_edge_freq.resize(ter + 1);
320 m_terrain_edge_freq[ter] += 1;
321 } else {
322 static const float TyZero = 1.0 / TEXTURE_HEIGHT;
323 static const float TyOne = 1.0 - TyZero;
324
325 uint32_t index = m_terrain_edge_indexs[ter];
326 compute_basevertex(edge1, m_edge_vertices[index]);
327 m_edge_vertices[index].edgex = 0.0;
328 m_edge_vertices[index].edgey = TyZero;
329 ++index;
330 compute_basevertex(edge2, m_edge_vertices[index]);
331 m_edge_vertices[index].edgex = 1.0;
332 m_edge_vertices[index].edgey = TyZero;
333 ++index;
334 compute_basevertex(opposite, m_edge_vertices[index]);
335 m_edge_vertices[index].edgex = 0.5;
336 m_edge_vertices[index].edgey = TyOne;
337 ++index;
338 m_terrain_edge_indexs[ter] = index;
339 }
340}
341
342void GameRendererGL::collect_terrain_dither(bool onlyscan)
343{
344 Map const & map = m_egbase->map();
345 World const & world = map.world();
346
347 for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
348 for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
349 Coords ncoords(fx, fy);
350 map.normalize_coords(ncoords);
351 FCoords fcoords = map.get_fcoords(ncoords);
352
353 Terrain_Index ter_d = fcoords.field->get_terrains().d;
354 Terrain_Index ter_r = fcoords.field->get_terrains().r;
355 Terrain_Index ter_u = map.tr_n(fcoords).field->get_terrains().d;
356 Terrain_Index ter_rr = map.r_n(fcoords).field->get_terrains().d;
357 Terrain_Index ter_l = map.l_n(fcoords).field->get_terrains().r;
358 Terrain_Index ter_dd = map.bl_n(fcoords).field->get_terrains().r;
359 int32_t lyr_d = world.get_ter(ter_d).dither_layer();
360 int32_t lyr_r = world.get_ter(ter_r).dither_layer();
361 int32_t lyr_u = world.get_ter(ter_u).dither_layer();
362 int32_t lyr_rr = world.get_ter(ter_rr).dither_layer();
363 int32_t lyr_l = world.get_ter(ter_l).dither_layer();
364 int32_t lyr_dd = world.get_ter(ter_dd).dither_layer();
365
366 Coords f(fx, fy);
367 Coords rn(fx + 1, fy);
368 Coords brn(fx + (fy & 1), fy + 1);
369 Coords bln(brn.x - 1, brn.y);
370
371 if (lyr_r > lyr_d) {
372 add_terrain_dither_triangle(onlyscan, ter_r, brn, f, bln);
373 } else if (ter_d != ter_r) {
374 add_terrain_dither_triangle(onlyscan, ter_d, f, brn, rn);
375 }
376 if ((lyr_u > lyr_r) || (lyr_u == lyr_r && ter_u != ter_r)) {
377 add_terrain_dither_triangle(onlyscan, ter_u, rn, f, brn);
378 }
379 if (lyr_rr > lyr_r) {
380 add_terrain_dither_triangle(onlyscan, ter_rr, brn, rn, f);
381 }
382 if ((lyr_l > lyr_d) || (lyr_l == lyr_d && ter_l != ter_d)) {
383 add_terrain_dither_triangle(onlyscan, ter_l, f, bln, brn);
384 }
385 if (lyr_dd > lyr_d) {
386 add_terrain_dither_triangle(onlyscan, ter_dd, bln, brn, f);
387 }
388 }
389 }
390}
391
392/*
393 * Schematic of triangle neighborhood:
394 *
395 * *
396 * / \
397 * / u \
398 * (f)/ \
399 * *------*------* (r)
400 * \ l / \ r / \
401 * \ / \ / \
402 * \/ d \/ rr \
403 * *------*------* (br)
404 * \ dd /
405 * \ /
406 * \/
407 * *
408 */
409void GameRendererGL::prepare_terrain_dither()
410{
411 assert(sizeof(dithervertex) == 32);
412
413 if (m_terrain_edge_freq.size() < 16)
414 m_terrain_edge_freq.resize(16);
415 m_terrain_edge_freq.assign(m_terrain_edge_freq.size(), 0);
416
417 collect_terrain_dither(true);
418
419 uint32_t nrtriangles = 0;
420 m_terrain_edge_freq_cum.resize(m_terrain_edge_freq.size());
421 for (Terrain_Index ter = 0; ter < m_terrain_edge_freq.size(); ++ter) {
422 m_terrain_edge_freq_cum[ter] = nrtriangles;
423 nrtriangles += m_terrain_edge_freq[ter];
424 }
425
426 if (3 * nrtriangles > m_edge_vertices_size) {
427 m_edge_vertices.reset(new dithervertex[3 * nrtriangles]);
428 m_edge_vertices_size = 3 * nrtriangles;
429 }
430
431 m_terrain_edge_indexs.resize(m_terrain_edge_freq_cum.size());
432 for (Terrain_Index ter = 0; ter < m_terrain_edge_freq.size(); ++ter)
433 m_terrain_edge_indexs[ter] = 3 * m_terrain_edge_freq_cum[ter];
434
435 collect_terrain_dither(false);
436
437 for (Terrain_Index ter = 0; ter < m_terrain_edge_freq.size(); ++ter) {
438 assert(m_terrain_edge_indexs[ter] == 3 * (m_terrain_edge_freq_cum[ter] + m_terrain_edge_freq[ter]));
439 }
440}
441
442void GameRendererGL::draw_terrain_dither()
443{
444 Map const & map = m_egbase->map();
445 World const & world = map.world();
446
447 if (m_edge_vertices_size == 0)
448 return;
449
450 glVertexPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].x);
451 glTexCoordPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].tcx);
452 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(dithervertex), &m_edge_vertices[0].color);
453 glEnableClientState(GL_VERTEX_ARRAY);
454 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
455 glEnableClientState(GL_COLOR_ARRAY);
456
457 glActiveTextureARB(GL_TEXTURE1_ARB);
458 glClientActiveTextureARB(GL_TEXTURE1_ARB);
459 glTexCoordPointer(2, GL_FLOAT, sizeof(dithervertex), &m_edge_vertices[0].edgex);
460 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
461 GLuint edge = get_dither_edge_texture(world)->get_gl_texture();
462 glBindTexture(GL_TEXTURE_2D, edge);
463 glEnable(GL_TEXTURE_2D);
464 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
465 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
466 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
467 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
468 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
469 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
470 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
471 glActiveTextureARB(GL_TEXTURE0_ARB);
472 glClientActiveTextureARB(GL_TEXTURE0_ARB);
473
474 glEnable(GL_BLEND);
475 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
476
477 for (Terrain_Index ter = 0; ter < m_terrain_freq.size(); ++ter) {
478 if (!m_terrain_edge_freq[ter])
479 continue;
480
481 const Texture & texture =
482 *g_gr->get_maptexture_data
483 (world.terrain_descr(ter).get_texture());
484 glBindTexture(GL_TEXTURE_2D, texture.getTexture());
485 glDrawArrays
486 (GL_TRIANGLES,
487 3 * m_terrain_edge_freq_cum[ter], 3 * m_terrain_edge_freq[ter]);
488 }
489
490 glDisableClientState(GL_VERTEX_ARRAY);
491 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
492 glDisableClientState(GL_COLOR_ARRAY);
493 glActiveTextureARB(GL_TEXTURE1_ARB);
494 glClientActiveTextureARB(GL_TEXTURE1_ARB);
495 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
496 glDisable(GL_TEXTURE_2D);
497 glActiveTextureARB(GL_TEXTURE0_ARB);
498 glClientActiveTextureARB(GL_TEXTURE0_ARB);
499}
500
501uint8_t GameRendererGL::field_roads(const FCoords & coords) const
502{
503 if (m_player) {
504 const Map & map = m_egbase->map();
505 const Player::Field & pf = m_player->fields()[Map::get_index(coords, map.get_width())];
506 return pf.roads | map.get_overlay_manager().get_road_overlay(coords);
507 } else {
508 return coords.field->get_roads();
509 }
510}
511
512void GameRendererGL::prepare_roads()
513{
514 const Map & map = m_egbase->map();
515
516 m_road_freq[0] = 0;
517 m_road_freq[1] = 0;
518
519 for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
520 for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
521 Coords ncoords(fx, fy);
522 map.normalize_coords(ncoords);
523 FCoords fcoords = map.get_fcoords(ncoords);
524 uint8_t roads = field_roads(fcoords);
525
526 for (int dir = 0; dir < 3; ++dir) {
527 uint8_t road = (roads >> (2 * dir)) & Road_Mask;
528 if (road >= Road_Normal && road <= Road_Busy) {
529 ++m_road_freq[road - Road_Normal];
530 }
531 }
532 }
533 }
534
535 uint32_t nrquads = m_road_freq[0] + m_road_freq[1];
536 if (4 * nrquads > m_road_vertices_size) {
537 m_road_vertices.reset(new basevertex[4 * nrquads]);
538 m_road_vertices_size = 4 * nrquads;
539 }
540
541 uint32_t indexs[2];
542 indexs[0] = 0;
543 indexs[1] = 4 * m_road_freq[0];
544
545 for (int32_t fy = m_minfy; fy <= m_maxfy; ++fy) {
546 for (int32_t fx = m_minfx; fx <= m_maxfx; ++fx) {
547 Coords ncoords(fx, fy);
548 map.normalize_coords(ncoords);
549 FCoords fcoords = map.get_fcoords(ncoords);
550 uint8_t roads = field_roads(fcoords);
551
552 uint8_t road = (roads >> Road_East) & Road_Mask;
553 if (road >= Road_Normal && road <= Road_Busy) {
554 uint32_t index = indexs[road - Road_Normal];
555 basevertex start, end;
556 compute_basevertex(Coords(fx, fy), start);
557 compute_basevertex(Coords(fx + 1, fy), end);
558 m_road_vertices[index] = start;
559 m_road_vertices[index].y -= 2;
560 m_road_vertices[index].tcy -= 2.0 / TEXTURE_HEIGHT;
561 ++index;
562 m_road_vertices[index] = start;
563 m_road_vertices[index].y += 2;
564 m_road_vertices[index].tcy += 2.0 / TEXTURE_HEIGHT;
565 ++index;
566 m_road_vertices[index] = end;
567 m_road_vertices[index].y += 2;
568 m_road_vertices[index].tcy += 2.0 / TEXTURE_HEIGHT;
569 ++index;
570 m_road_vertices[index] = end;
571 m_road_vertices[index].y -= 2;
572 m_road_vertices[index].tcy -= 2.0 / TEXTURE_HEIGHT;
573 ++index;
574 indexs[road - Road_Normal] = index;
575 }
576
577 road = (roads >> Road_SouthEast) & Road_Mask;
578 if (road >= Road_Normal && road <= Road_Busy) {
579 uint32_t index = indexs[road - Road_Normal];
580 basevertex start, end;
581 compute_basevertex(Coords(fx, fy), start);
582 compute_basevertex(Coords(fx + (fy & 1), fy + 1), end);
583 m_road_vertices[index] = start;
584 m_road_vertices[index].x += 3;
585 m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
586 ++index;
587 m_road_vertices[index] = start;
588 m_road_vertices[index].x -= 3;
589 m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
590 ++index;
591 m_road_vertices[index] = end;
592 m_road_vertices[index].x -= 3;
593 m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
594 ++index;
595 m_road_vertices[index] = end;
596 m_road_vertices[index].x += 3;
597 m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
598 ++index;
599 indexs[road - Road_Normal] = index;
600 }
601
602 road = (roads >> Road_SouthWest) & Road_Mask;
603 if (road >= Road_Normal && road <= Road_Busy) {
604 uint32_t index = indexs[road - Road_Normal];
605 basevertex start, end;
606 compute_basevertex(Coords(fx, fy), start);
607 compute_basevertex(Coords(fx + (fy & 1) - 1, fy + 1), end);
608 m_road_vertices[index] = start;
609 m_road_vertices[index].x += 3;
610 m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
611 ++index;
612 m_road_vertices[index] = start;
613 m_road_vertices[index].x -= 3;
614 m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
615 ++index;
616 m_road_vertices[index] = end;
617 m_road_vertices[index].x -= 3;
618 m_road_vertices[index].tcx -= 3.0 / TEXTURE_HEIGHT;
619 ++index;
620 m_road_vertices[index] = end;
621 m_road_vertices[index].x += 3;
622 m_road_vertices[index].tcx += 3.0 / TEXTURE_HEIGHT;
623 ++index;
624 indexs[road - Road_Normal] = index;
625 }
626 }
627 }
628
629 assert(indexs[0] == 4 * m_road_freq[0]);
630 assert(indexs[1] == 4 * nrquads);
631}
632
633void GameRendererGL::draw_roads()
634{
635 if (!m_road_freq[0] && !m_road_freq[1])
636 return;
637
638 GLuint rt_normal =
639 dynamic_cast<GLSurfaceTexture const &>
640 (*g_gr->get_road_texture(Widelands::Road_Normal)).get_gl_texture();
641 GLuint rt_busy =
642 dynamic_cast<GLSurfaceTexture const &>
643 (*g_gr->get_road_texture(Widelands::Road_Busy)).get_gl_texture();
644
645 glVertexPointer(2, GL_FLOAT, sizeof(basevertex), &m_road_vertices[0].x);
646 glTexCoordPointer(2, GL_FLOAT, sizeof(basevertex), &m_road_vertices[0].tcx);
647 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(basevertex), &m_road_vertices[0].color);
648 glEnableClientState(GL_VERTEX_ARRAY);
649 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
650 glEnableClientState(GL_COLOR_ARRAY);
651
652 glDisable(GL_BLEND);
653
654 if (m_road_freq[0]) {
655 glBindTexture(GL_TEXTURE_2D, rt_normal);
656 glDrawArrays(GL_QUADS, 0, 4 * m_road_freq[0]);
657 }
658
659 if (m_road_freq[1]) {
660 glBindTexture(GL_TEXTURE_2D, rt_busy);
661 glDrawArrays(GL_QUADS, 4 * m_road_freq[0], 4 * m_road_freq[1]);
662 }
663
664 glDisableClientState(GL_VERTEX_ARRAY);
665 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
666 glDisableClientState(GL_COLOR_ARRAY);
667}
668
669#endif // USE_OPENGL
0670
=== added file 'src/graphic/render/gamerenderer_gl.h'
--- src/graphic/render/gamerenderer_gl.h 1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_gl.h 2013-02-09 12:25:26 +0000
@@ -0,0 +1,132 @@
1/*
2 * Copyright (C) 2011-2013 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#ifdef USE_OPENGL
21#ifndef WIDELANDS_GAMERENDERER_GL_H
22#define WIDELANDS_GAMERENDERER_GL_H
23
24#include "gamerenderer.h"
25
26#include "logic/widelands.h"
27
28#include "rect.h"
29
30#include <vector>
31#include <boost/scoped_array.hpp>
32
33namespace Widelands {
34struct Coords;
35struct FCoords;
36struct World;
37}
38
39class GLSurface;
40class GLSurfaceTexture;
41
42/**
43 * OpenGL implementation of @ref GameRenderer.
44 */
45class GameRendererGL : public GameRenderer {
46public:
47 GameRendererGL();
48 virtual ~GameRendererGL();
49
50private:
51 struct basevertex {
52 float x;
53 float y;
54 float tcx;
55 float tcy;
56 uint8_t color[4];
57 uint32_t pad[3];
58 };
59
60 struct dithervertex {
61 float x;
62 float y;
63 float tcx;
64 float tcy;
65 float edgex;
66 float edgey;
67 uint8_t color[4];
68 uint32_t pad[1];
69 };
70
71 const GLSurfaceTexture * get_dither_edge_texture(const Widelands::World & world);
72
73 void draw();
74 void prepare_terrain_base();
75 void collect_terrain_base(bool onlyscan);
76 void count_terrain_base(Widelands::Terrain_Index ter);
77 void add_terrain_base_triangle
78 (Widelands::Terrain_Index ter,
79 const Widelands::Coords & p1, const Widelands::Coords & p2, const Widelands::Coords & p3);
80 void draw_terrain_base();
81 void prepare_terrain_dither();
82 void collect_terrain_dither(bool onlyscan);
83 void add_terrain_dither_triangle
84 (bool onlyscan, Widelands::Terrain_Index ter,
85 const Widelands::Coords & edge1, const Widelands::Coords & edge2,
86 const Widelands::Coords & opposite);
87 void draw_terrain_dither();
88 void prepare_roads();
89 void draw_roads();
90
91 uint32_t patch_index(const Widelands::Coords & f) const;
92 uint8_t field_brightness(const Widelands::FCoords & coords) const;
93 uint8_t field_roads(const Widelands::FCoords & coords) const;
94 template<typename vertex>
95 void compute_basevertex(const Widelands::Coords & coords, vertex & vtx) const;
96
97 /**
98 * The following variables are only valid during rendering.
99 */
100 /*@{*/
101 GLSurface * m_surface;
102
103 /// Bounding rectangle inside the destination surface
104 Rect m_rect;
105
106 /// Translation from map pixel coordinates to surface pixel coordinates
107 /// (relative to the top-left corner of the surface, @b not relative
108 /// to the bounding rectangle)
109 Point m_surface_offset;
110
111 Rect m_patch_size;
112 boost::scoped_array<basevertex> m_patch_vertices;
113 uint32_t m_patch_vertices_size;
114 boost::scoped_array<uint16_t> m_patch_indices;
115 uint32_t m_patch_indices_size;
116 std::vector<uint32_t> m_patch_indices_indexs;
117 std::vector<uint32_t> m_terrain_freq;
118 std::vector<uint32_t> m_terrain_freq_cum;
119 boost::scoped_array<dithervertex> m_edge_vertices;
120 uint32_t m_edge_vertices_size;
121 std::vector<uint32_t> m_terrain_edge_freq;
122 std::vector<uint32_t> m_terrain_edge_freq_cum;
123 std::vector<uint32_t> m_terrain_edge_indexs;
124
125 uint32_t m_road_freq[2];
126 boost::scoped_array<basevertex> m_road_vertices;
127 uint32_t m_road_vertices_size;
128 /*@}*/
129};
130
131#endif // WIDELANDS_GAMERENDERER_GL_H
132#endif // USE_OPENGL
0133
=== added file 'src/graphic/render/gamerenderer_sdl.cc'
--- src/graphic/render/gamerenderer_sdl.cc 1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_sdl.cc 2013-02-09 12:25:26 +0000
@@ -0,0 +1,279 @@
1/*
2 * Copyright (C) 2010-2013 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#include "gamerenderer_sdl.h"
21
22#include "logic/field.h"
23#include "logic/map.h"
24#include "logic/player.h"
25
26#include "graphic/rendertarget.h"
27
28#include "wui/overlay_manager.h"
29
30#include "terrain_sdl.h"
31
32
33using namespace Widelands;
34
35///This is used by rendermap to calculate the brightness of the terrain.
36inline static Sint8 node_brightness
37 (Widelands::Time const gametime,
38 Widelands::Time const last_seen,
39 Widelands::Vision const vision,
40 int8_t result)
41{
42 if (vision == 0)
43 result = -128;
44 else if (vision == 1) {
45 assert(last_seen <= gametime);
46 Widelands::Duration const time_ago = gametime - last_seen;
47 result =
48 static_cast<Sint16>
49 (((static_cast<Sint16>(result) + 128) >> 1)
50 *
51 (1.0 + (time_ago < 45000 ? expf(-8.46126929e-5 * time_ago) : 0)))
52 -
53 128;
54 }
55
56 return result;
57}
58
59
60void GameRendererSDL::draw()
61{
62 draw_terrain();
63 draw_objects();
64}
65
66void GameRendererSDL::draw_terrain()
67{
68 if (m_player && !m_player->see_all())
69 m_dst->get_surface()->fill_rect(m_dst->get_rect(), RGBAColor(0, 0, 0, 255));
70
71 Map const & map = m_egbase->map();
72 World const & world = map.world();
73 uint32_t const mapwidth = map.get_width();
74
75#define get_terrain_texture(ter) \
76 (g_gr->get_maptexture_data(world.terrain_descr((ter)).get_texture()))
77
78 int32_t dx = m_maxfx - m_minfx + 1;
79 int32_t dy = m_maxfy - m_minfy + 1;
80 int32_t linear_fy = m_minfy;
81 int32_t b_posy = linear_fy * TRIANGLE_HEIGHT + m_dst_offset.y;
82
83 Widelands::Time const gametime = m_egbase->get_gametime();
84
85 while (dy--) {
86 const int32_t posy = b_posy;
87 b_posy += TRIANGLE_HEIGHT;
88 const int32_t linear_fx = m_minfx;
89 FCoords r(Coords(linear_fx, linear_fy));
90 FCoords br(Coords(linear_fx + (linear_fy & 1) - 1, linear_fy + 1));
91 int32_t r_posx =
92 r.x * TRIANGLE_WIDTH
93 +
94 (linear_fy & 1) * (TRIANGLE_WIDTH / 2)
95 +
96 m_dst_offset.x;
97 int32_t br_posx = r_posx - TRIANGLE_WIDTH / 2;
98
99 // Calculate safe (bounded) field coordinates and get field pointers
100 map.normalize_coords(r);
101 map.normalize_coords(br);
102 Map_Index r_index = Map::get_index (r, mapwidth);
103 r.field = &map[r_index];
104 Map_Index br_index = Map::get_index(br, mapwidth);
105 br.field = &map[br_index];
106 FCoords tr;
107 map.get_tln(r, &tr);
108 Map_Index tr_index = tr.field - &map[0];
109
110 const Texture * f_r_texture;
111
112 if (m_player && !m_player->see_all()) {
113 const Player::Field & l_pf = m_player->fields()[Map::get_index(map.l_n(r), mapwidth)];
114 f_r_texture = get_terrain_texture(l_pf.terrains.r);
115 } else {
116 f_r_texture = get_terrain_texture(map.l_n(r).field->get_terrains().r);
117 }
118
119 uint32_t count = dx;
120
121 while (count--) {
122 const FCoords bl = br;
123 const FCoords f = r;
124 const int32_t f_posx = r_posx;
125 const int32_t bl_posx = br_posx;
126 Map_Index f_index = r_index;
127 Map_Index bl_index = br_index;
128 move_r(mapwidth, tr, tr_index);
129 move_r(mapwidth, r, r_index);
130 move_r(mapwidth, br, br_index);
131 r_posx += TRIANGLE_WIDTH;
132 br_posx += TRIANGLE_WIDTH;
133
134 const Texture * l_r_texture = f_r_texture;
135 const Texture * f_d_texture;
136 const Texture * tr_d_texture;
137 uint8_t roads;
138 Sint8 f_brightness;
139 Sint8 r_brightness;
140 Sint8 bl_brightness;
141 Sint8 br_brightness;
142
143 if (m_player && !m_player->see_all()) {
144 const Player::Field & f_pf = m_player->fields()[f_index];
145 const Player::Field & r_pf = m_player->fields()[r_index];
146 const Player::Field & bl_pf = m_player->fields()[bl_index];
147 const Player::Field & br_pf = m_player->fields()[br_index];
148 const Player::Field & tr_pf = m_player->fields()[tr_index];
149
150 f_r_texture = get_terrain_texture(f_pf.terrains.r);
151 f_d_texture = get_terrain_texture(f_pf.terrains.d);
152 tr_d_texture = get_terrain_texture(tr_pf.terrains.d);
153
154 roads = f_pf.roads | map.overlay_manager().get_road_overlay(f);
155
156 f_brightness = node_brightness
157 (gametime, f_pf.time_node_last_unseen,
158 f_pf.vision, f.field->get_brightness());
159 r_brightness = node_brightness
160 (gametime, r_pf.time_node_last_unseen,
161 r_pf.vision, r.field->get_brightness());
162 bl_brightness = node_brightness
163 (gametime, bl_pf.time_node_last_unseen,
164 bl_pf.vision, bl.field->get_brightness());
165 br_brightness = node_brightness
166 (gametime, br_pf.time_node_last_unseen,
167 br_pf.vision, br.field->get_brightness());
168 } else {
169 f_r_texture = get_terrain_texture(f.field->get_terrains().r);
170 f_d_texture = get_terrain_texture(f.field->get_terrains().d);
171 tr_d_texture = get_terrain_texture(tr.field->get_terrains().d);
172
173 roads = f.field->get_roads();
174
175 f_brightness = f.field->get_brightness();
176 r_brightness = r.field->get_brightness();
177 bl_brightness = bl.field->get_brightness();
178 br_brightness = br.field->get_brightness();
179 }
180
181 Vertex f_vert
182 (f_posx, posy - f.field->get_height() * HEIGHT_FACTOR,
183 f_brightness, 0, 0);
184 Vertex r_vert
185 (r_posx, posy - r.field->get_height() * HEIGHT_FACTOR,
186 r_brightness, TRIANGLE_WIDTH, 0);
187 Vertex bl_vert
188 (bl_posx, b_posy - bl.field->get_height() * HEIGHT_FACTOR,
189 bl_brightness, 0, 64);
190 Vertex br_vert
191 (br_posx, b_posy - br.field->get_height() * HEIGHT_FACTOR,
192 br_brightness, TRIANGLE_WIDTH, 64);
193
194 if (linear_fy & 1) {
195 f_vert.tx += TRIANGLE_WIDTH / 2;
196 r_vert.tx += TRIANGLE_WIDTH / 2;
197 } else {
198 f_vert.tx += TRIANGLE_WIDTH;
199 r_vert.tx += TRIANGLE_WIDTH;
200 bl_vert.tx += TRIANGLE_WIDTH / 2;
201 br_vert.tx += TRIANGLE_WIDTH / 2;
202 }
203
204 draw_field // Render ground
205 (*m_dst,
206 f_vert, r_vert, bl_vert, br_vert,
207 roads,
208 *tr_d_texture, *l_r_texture, *f_d_texture, *f_r_texture);
209 }
210
211 ++linear_fy;
212 }
213
214#undef get_terrain_texture
215}
216
217
218/**
219 * Draw ground textures and roads for the given parallelogram (two triangles)
220 * into the bitmap.
221 *
222 * Vertices:
223 * - f_vert vertex of the field
224 * - r_vert vertex right of the field
225 * - bl_vert vertex bottom left of the field
226 * - br_vert vertex bottom right of the field
227 *
228 * Textures:
229 * - f_r_texture Terrain of the triangle right of the field
230 * - f_d_texture Terrain of the triangle under of the field
231 * - tr_d_texture Terrain of the triangle top of the right triangle ??
232 * - l_r_texture Terrain of the triangle left of the down triangle ??
233 *
234 * (tr_d)
235 *
236 * (f) *------* (r)
237 * / \ r /
238 * (l_r) / \ /
239 * / d \/
240 * (bl) *------* (br)
241 */
242void GameRendererSDL::draw_field
243 (RenderTarget & dst,
244 Vertex const & f_vert,
245 Vertex const & r_vert,
246 Vertex const & bl_vert,
247 Vertex const & br_vert,
248 uint8_t roads,
249 Texture const & tr_d_texture,
250 Texture const & l_r_texture,
251 Texture const & f_d_texture,
252 Texture const & f_r_texture)
253{
254 upcast(SDLSurface, sdlsurf, dst.get_surface());
255 if (sdlsurf)
256 {
257 sdlsurf->set_subwin(dst.get_rect());
258 switch (sdlsurf->format().BytesPerPixel) {
259 case 2:
260 draw_field_int<Uint16>
261 (*sdlsurf,
262 f_vert, r_vert, bl_vert, br_vert,
263 roads,
264 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
265 break;
266 case 4:
267 draw_field_int<Uint32>
268 (*sdlsurf,
269 f_vert, r_vert, bl_vert, br_vert,
270 roads,
271 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
272 break;
273 default:
274 assert(false);
275 break;
276 }
277 sdlsurf->unset_subwin();
278 }
279}
0280
=== added file 'src/graphic/render/gamerenderer_sdl.h'
--- src/graphic/render/gamerenderer_sdl.h 1970-01-01 00:00:00 +0000
+++ src/graphic/render/gamerenderer_sdl.h 2013-02-09 12:25:26 +0000
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2010-2013 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#ifndef WIDELANDS_GAMERENDERER_SDL_H
21#define WIDELANDS_GAMERENDERER_SDL_H
22
23#include "gamerenderer.h"
24
25struct Texture;
26struct Vertex;
27
28/**
29 * Software-rendering implementation of @ref GameRenderer.
30 */
31class GameRendererSDL : public GameRenderer {
32protected:
33 void draw();
34
35private:
36 void draw_terrain();
37
38 /**
39 * Helper function to draw two terrain triangles. This is called from the
40 * rendermap() functions.
41 */
42 void draw_field
43 (RenderTarget & dst,
44 Vertex const & f_vert,
45 Vertex const & r_vert,
46 Vertex const & bl_vert,
47 Vertex const & br_vert,
48 uint8_t roads,
49 Texture const & tr_d_texture,
50 Texture const & l_r_texture,
51 Texture const & f_d_texture,
52 Texture const & f_r_texture);
53};
54
55#endif // WIDELANDS_GAMERENDERER_SDL_H
056
=== removed file 'src/graphic/render/gameview_opengl.cc'
--- src/graphic/render/gameview_opengl.cc 2012-09-21 21:36:07 +0000
+++ src/graphic/render/gameview_opengl.cc 1970-01-01 00:00:00 +0000
@@ -1,104 +0,0 @@
1/*
2 * Copyright (C) 2011-2012 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20#ifdef USE_OPENGL
21
22#include "gameview_opengl.h"
23
24#include "constants.h"
25#include "economy/road.h"
26#include "graphic/graphic.h"
27#include "graphic/texture.h"
28
29#include "terrain_opengl.h"
30
31using namespace Widelands;
32
33/**
34 * Draw ground textures and roads for the given parallelogram (two triangles)
35 * into the bitmap.
36 *
37 * Vertices:
38 * - f_vert vertex of the field
39 * - r_vert vertex right of the field
40 * - bl_vert vertex bottom left of the field
41 * - br_vert vertex bottom right of the field
42 *
43 * Textures:
44 * - f_r_texture Terrain of the triangle right of the field
45 * - f_d_texture Terrain of the triangle under of the field
46 * - tr_d_texture Terrain of the triangle top of the right triangle ??
47 * - l_r_texture Terrain of the triangle left of the down triangle ??
48 *
49 * (tr_d)
50 *
51 * (f) *------* (r)
52 * / \ r /
53 * (l_r) / \ /
54 * / d \/
55 * (bl) *------* (br)
56 */
57void GameViewOpenGL::draw_field
58 (Rect & subwin,
59 Vertex const & f_vert,
60 Vertex const & r_vert,
61 Vertex const & bl_vert,
62 Vertex const & br_vert,
63 uint8_t roads,
64 Texture const & tr_d_texture,
65 Texture const & l_r_texture,
66 Texture const & f_d_texture,
67 Texture const & f_r_texture)
68{
69 // Draw triangle right (bottom) of the field
70 draw_field_opengl
71 (subwin, f_vert, br_vert, r_vert, f_r_texture, f_d_texture, tr_d_texture);
72 // Draw triangle bottom of the field
73 draw_field_opengl
74 (subwin, f_vert, bl_vert, br_vert, f_d_texture, l_r_texture, f_d_texture);
75
76 // Draw the roads
77 draw_roads_opengl(subwin, roads, f_vert, r_vert, bl_vert, br_vert);
78}
79
80void GameViewOpenGL::rendermap_init()
81{
82 glMatrixMode(GL_TEXTURE);
83 glLoadIdentity();
84 glScalef
85 (1.0f / static_cast<GLfloat>(TEXTURE_WIDTH),
86 1.0f / static_cast<GLfloat>(TEXTURE_HEIGHT), 1);
87 glDisable(GL_BLEND);
88
89 // Use scissor test to clip the window. This takes coordinates in screen
90 // coordinates (y goes from bottom to top)
91 glScissor
92 (m_rect.x, g_gr->get_yres() - m_rect.y - m_rect.h,
93 m_rect.w, m_rect.h);
94 glEnable(GL_SCISSOR_TEST);
95}
96
97void GameViewOpenGL::rendermap_deint()
98{
99 glDisable(GL_SCISSOR_TEST);
100 glMatrixMode(GL_TEXTURE);
101 glLoadIdentity();
102}
103
104#endif
1050
=== removed file 'src/graphic/render/gameview_opengl.h'
--- src/graphic/render/gameview_opengl.h 2012-09-21 21:36:07 +0000
+++ src/graphic/render/gameview_opengl.h 1970-01-01 00:00:00 +0000
@@ -1,56 +0,0 @@
1/*
2 * Copyright (C) 2011 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20#ifdef USE_OPENGL
21#ifndef GAMEVIEW_OPENGL_H_
22#define GAMEVIEW_OPENGL_H_
23
24#include "gameview.h"
25
26class GameViewOpenGL : public GameView
27{
28public:
29 GameViewOpenGL(RenderTarget & rt):
30 GameView(rt) {}
31 ~GameViewOpenGL() {}
32
33protected:
34 /**
35 * Helper function to draw two terrain triangles. This is called from the
36 * rendermap() functions.
37 */
38 void draw_field
39 (Rect & subwin,
40 Vertex const & f_vert,
41 Vertex const & r_vert,
42 Vertex const & bl_vert,
43 Vertex const & br_vert,
44 uint8_t roads,
45 Texture const & tr_d_texture,
46 Texture const & l_r_texture,
47 Texture const & f_d_texture,
48 Texture const & f_r_texture);
49
50 void rendermap_init();
51 void rendermap_deint();
52};
53
54
55#endif /* GAMEVIEW_OPENGL_H_ */
56#endif /* USE_OPENGL */
570
=== removed file 'src/graphic/render/gameview_sdl.cc'
--- src/graphic/render/gameview_sdl.cc 2012-12-07 20:25:12 +0000
+++ src/graphic/render/gameview_sdl.cc 1970-01-01 00:00:00 +0000
@@ -1,105 +0,0 @@
1/*
2 * Copyright (C) 2011-2012 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20#include "gameview_sdl.h"
21
22#include "upcast.h"
23
24#include "economy/road.h"
25#include "economy/flag.h"
26
27#include "wui/minimap.h"
28#include "wui/mapviewpixelconstants.h"
29
30#include "logic/field.h"
31#include "logic/map.h"
32#include "logic/player.h"
33
34#include "graphic/graphic.h"
35#include "graphic/rendertarget.h"
36#include "graphic/surface.h"
37#include "graphic/texture.h"
38
39#include "wui/overlay_manager.h"
40
41#include "terrain_sdl.h"
42
43
44/**
45 * Draw ground textures and roads for the given parallelogram (two triangles)
46 * into the bitmap.
47 *
48 * Vertices:
49 * - f_vert vertex of the field
50 * - r_vert vertex right of the field
51 * - bl_vert vertex bottom left of the field
52 * - br_vert vertex bottom right of the field
53 *
54 * Textures:
55 * - f_r_texture Terrain of the triangle right of the field
56 * - f_d_texture Terrain of the triangle under of the field
57 * - tr_d_texture Terrain of the triangle top of the right triangle ??
58 * - l_r_texture Terrain of the triangle left of the down triangle ??
59 *
60 * (tr_d)
61 *
62 * (f) *------* (r)
63 * / \ r /
64 * (l_r) / \ /
65 * / d \/
66 * (bl) *------* (br)
67 */
68void GameViewSDL::draw_field
69 (Rect & subwin,
70 Vertex const & f_vert,
71 Vertex const & r_vert,
72 Vertex const & bl_vert,
73 Vertex const & br_vert,
74 uint8_t roads,
75 Texture const & tr_d_texture,
76 Texture const & l_r_texture,
77 Texture const & f_d_texture,
78 Texture const & f_r_texture)
79{
80 upcast(SDLSurface, sdlsurf, m_surface);
81 if (sdlsurf)
82 {
83 sdlsurf->set_subwin(subwin);
84 switch (sdlsurf->format().BytesPerPixel) {
85 case 2:
86 draw_field_int<Uint16>
87 (*sdlsurf,
88 f_vert, r_vert, bl_vert, br_vert,
89 roads,
90 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
91 break;
92 case 4:
93 draw_field_int<Uint32>
94 (*sdlsurf,
95 f_vert, r_vert, bl_vert, br_vert,
96 roads,
97 tr_d_texture, l_r_texture, f_d_texture, f_r_texture);
98 break;
99 default:
100 assert(false);
101 break;
102 }
103 sdlsurf->unset_subwin();
104 }
105}
1060
=== removed file 'src/graphic/render/gameview_sdl.h'
--- src/graphic/render/gameview_sdl.h 2012-02-27 20:24:28 +0000
+++ src/graphic/render/gameview_sdl.h 1970-01-01 00:00:00 +0000
@@ -1,50 +0,0 @@
1/*
2 * Copyright (C) 2011-2012 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 */
19
20#ifndef GAMEVIEW_SDL_H_
21#define GAMEVIEW_SDL_H_
22
23#include "gameview.h"
24
25class GameViewSDL : public GameView
26{
27public:
28 GameViewSDL(RenderTarget & rt):
29 GameView(rt) {}
30 ~GameViewSDL() {}
31
32protected:
33 /**
34 * Helper function to draw two terrain triangles. This is called from the
35 * rendermap() functions.
36 */
37 void draw_field
38 (Rect & subwin,
39 Vertex const & f_vert,
40 Vertex const & r_vert,
41 Vertex const & bl_vert,
42 Vertex const & br_vert,
43 uint8_t roads,
44 Texture const & tr_d_texture,
45 Texture const & l_r_texture,
46 Texture const & f_d_texture,
47 Texture const & f_r_texture);
48};
49
50#endif /* GAMEVIEW_SDL_H_ */
510
=== modified file 'src/graphic/render/gl_surface_texture.cc'
--- src/graphic/render/gl_surface_texture.cc 2013-01-04 09:59:13 +0000
+++ src/graphic/render/gl_surface_texture.cc 2013-02-09 12:25:26 +0000
@@ -85,7 +85,7 @@
85 *85 *
86 * \note Takes ownership of the given surface.86 * \note Takes ownership of the given surface.
87 */87 */
88GLSurfaceTexture::GLSurfaceTexture(SDL_Surface * surface)88GLSurfaceTexture::GLSurfaceTexture(SDL_Surface * surface, bool intensity)
89{89{
90 init(surface->w, surface->h);90 init(surface->w, surface->h);
9191
@@ -166,7 +166,7 @@
166 SDL_LockSurface(surface);166 SDL_LockSurface(surface);
167167
168 glTexImage2D168 glTexImage2D
169 (GL_TEXTURE_2D, 0, GL_RGBA, m_tex_w, m_tex_h, 0,169 (GL_TEXTURE_2D, 0, intensity ? GL_INTENSITY : GL_RGBA, m_tex_w, m_tex_h, 0,
170 pixels_format, GL_UNSIGNED_BYTE, surface->pixels);170 pixels_format, GL_UNSIGNED_BYTE, surface->pixels);
171171
172 SDL_UnlockSurface(surface);172 SDL_UnlockSurface(surface);
173173
=== modified file 'src/graphic/render/gl_surface_texture.h'
--- src/graphic/render/gl_surface_texture.h 2012-12-15 18:40:59 +0000
+++ src/graphic/render/gl_surface_texture.h 2013-02-09 12:25:26 +0000
@@ -30,7 +30,7 @@
30 static void Initialize();30 static void Initialize();
31 static void Cleanup();31 static void Cleanup();
3232
33 GLSurfaceTexture(SDL_Surface * surface);33 GLSurfaceTexture(SDL_Surface * surface, bool intensity = false);
34 GLSurfaceTexture(int w, int h, bool alpha);34 GLSurfaceTexture(int w, int h, bool alpha);
35 virtual ~GLSurfaceTexture();35 virtual ~GLSurfaceTexture();
3636
3737
=== renamed file 'src/graphic/render/gameview.cc' => 'src/graphic/render/minimaprenderer.cc'
--- src/graphic/render/gameview.cc 2012-12-14 20:09:35 +0000
+++ src/graphic/render/minimaprenderer.cc 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2010-2012 by the Widelands Development Team2 * Copyright (C) 2010-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -17,7 +17,7 @@
17 *17 *
18 */18 */
1919
20#include "gameview.h"20#include "minimaprenderer.h"
21#include "upcast.h"21#include "upcast.h"
2222
23#include "economy/road.h"23#include "economy/road.h"
@@ -39,931 +39,7 @@
3939
40#include "terrain_sdl.h"40#include "terrain_sdl.h"
4141
42using Widelands::BaseImmovable;42using namespace Widelands;
43using Widelands::Coords;
44using Widelands::FCoords;
45using Widelands::Map;
46using Widelands::Map_Object_Descr;
47using Widelands::Player;
48using Widelands::TCoords;
49using namespace Widelands;
50
51///This is used by rendermap to calculate the brightness of the terrain.
52inline static Sint8 node_brightness
53 (Widelands::Time const gametime,
54 Widelands::Time const last_seen,
55 Widelands::Vision const vision,
56 int8_t result)
57{
58 if (vision == 0)
59 result = -128;
60 else if (vision == 1) {
61 assert(last_seen <= gametime);
62 Widelands::Duration const time_ago = gametime - last_seen;
63 result =
64 static_cast<Sint16>
65 (((static_cast<Sint16>(result) + 128) >> 1)
66 *
67 (1.0 + (time_ago < 45000 ? expf(-8.46126929e-5 * time_ago) : 0)))
68 -
69 128;
70 }
71
72 return result;
73}
74
75
76#define RENDERMAP_INITIALIZATIONS \
77 viewofs -= m_offset; \
78 \
79 Map const & map = egbase.map(); \
80 Widelands::World const & world = map.world(); \
81 Overlay_Manager const & overlay_manager = map.get_overlay_manager(); \
82 uint32_t const mapwidth = map.get_width(); \
83 int32_t minfx, minfy; \
84 int32_t maxfx, maxfy; \
85 \
86 /* hack to prevent negative numbers */ \
87 minfx = (viewofs.x + (TRIANGLE_WIDTH >> 1)) / TRIANGLE_WIDTH - 1; \
88 \
89 minfy = viewofs.y / TRIANGLE_HEIGHT; \
90 maxfx = (viewofs.x + (TRIANGLE_WIDTH >> 1) + m_rect.w) / TRIANGLE_WIDTH; \
91 maxfy = (viewofs.y + m_rect.h) / TRIANGLE_HEIGHT; \
92 maxfx += 1; /* because of big buildings */ \
93 maxfy += 10; /* because of heights */ \
94 \
95 int32_t dx = maxfx - minfx + 1; \
96 int32_t dy = maxfy - minfy + 1; \
97 int32_t linear_fy = minfy; \
98 bool row_is_forward = linear_fy & 1; \
99 int32_t b_posy = linear_fy * TRIANGLE_HEIGHT - viewofs.y; \
100
101
102/**
103 * Loop through fields row by row. For each field, draw ground textures, then
104 * roads, then immovables, then bobs, then overlay stuff (build icons etc...)
105 */
106void GameView::rendermap
107 (Widelands::Editor_Game_Base const & egbase,
108 Widelands::Player const & player,
109 Point viewofs)
110{
111 m_surface->fill_rect(m_rect, RGBAColor(0, 0, 0, 255));
112
113 if (player.see_all())
114 return rendermap(egbase, viewofs);
115
116 RENDERMAP_INITIALIZATIONS;
117
118 const Player::Field * const first_player_field = player.fields();
119 Widelands::Time const gametime = egbase.get_gametime();
120
121 rendermap_init();
122
123 while (dy--) {
124 const int32_t posy = b_posy;
125 b_posy += TRIANGLE_HEIGHT;
126 const int32_t linear_fx = minfx;
127 FCoords r(Coords(linear_fx, linear_fy));
128 FCoords br(Coords(linear_fx - not row_is_forward, linear_fy + 1));
129 int32_t r_posx =
130 r.x * TRIANGLE_WIDTH
131 +
132 row_is_forward * (TRIANGLE_WIDTH / 2)
133 -
134 viewofs.x;
135 int32_t br_posx = r_posx - TRIANGLE_WIDTH / 2;
136
137 // Calculate safe (bounded) field coordinates and get field pointers
138 map.normalize_coords(r);
139 map.normalize_coords(br);
140 Widelands::Map_Index r_index = Map::get_index (r, mapwidth);
141 r.field = &map[r_index];
142 Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
143 br.field = &map[br_index];
144 const Player::Field * r_player_field = first_player_field + r_index;
145 const Player::Field * br_player_field = first_player_field + br_index;
146 FCoords tr, f;
147 map.get_tln(r, &tr);
148 map.get_ln(r, &f);
149 Widelands::Map_Index tr_index = tr.field - &map[0];
150 const Texture * f_r_texture =
151 g_gr->get_maptexture_data
152 (world
153 .terrain_descr(first_player_field[f.field - &map[0]].terrains.r)
154 .get_texture());
155
156 uint32_t count = dx;
157
158 while (count--) {
159 const FCoords bl = br;
160 const Player::Field & f_player_field = *r_player_field;
161 const Player::Field & bl_player_field = *br_player_field;
162 f = r;
163 const int32_t f_posx = r_posx, bl_posx = br_posx;
164 const Texture & l_r_texture = *f_r_texture;
165 move_r(mapwidth, tr, tr_index);
166 move_r(mapwidth, r, r_index);
167 move_r(mapwidth, br, br_index);
168 r_player_field = first_player_field + r_index;
169 br_player_field = first_player_field + br_index;
170 r_posx += TRIANGLE_WIDTH;
171 br_posx += TRIANGLE_WIDTH;
172 const Texture & tr_d_texture =
173 *g_gr->get_maptexture_data
174 (world.terrain_descr(first_player_field[tr_index].terrains.d).get_texture());
175 const Texture & f_d_texture =
176 *g_gr->get_maptexture_data(world.terrain_descr(f_player_field.terrains.d).get_texture());
177 f_r_texture =
178 g_gr->get_maptexture_data(world.terrain_descr(f_player_field.terrains.r).get_texture());
179
180 uint8_t const roads =
181 f_player_field.roads | overlay_manager.get_road_overlay(f);
182
183 Vertex f_vert
184 (f_posx, posy - f.field->get_height() * HEIGHT_FACTOR,
185 node_brightness
186 (gametime, f_player_field.time_node_last_unseen,
187 f_player_field.vision, f.field->get_brightness()),
188 0, 0);
189 Vertex r_vert
190 (r_posx, posy - r.field->get_height() * HEIGHT_FACTOR,
191 node_brightness
192 (gametime, r_player_field->time_node_last_unseen,
193 r_player_field->vision, r.field->get_brightness()),
194 TRIANGLE_WIDTH, 0);
195 Vertex bl_vert
196 (bl_posx, b_posy - bl.field->get_height() * HEIGHT_FACTOR,
197 node_brightness
198 (gametime, bl_player_field.time_node_last_unseen,
199 bl_player_field.vision, bl.field->get_brightness()),
200 0, 64);
201 Vertex br_vert
202 (br_posx, b_posy - br.field->get_height() * HEIGHT_FACTOR,
203 node_brightness
204 (gametime, br_player_field->time_node_last_unseen,
205 br_player_field->vision, br.field->get_brightness()),
206 TRIANGLE_WIDTH, 64);
207
208 if (row_is_forward) {
209 f_vert.tx += TRIANGLE_WIDTH / 2;
210 r_vert.tx += TRIANGLE_WIDTH / 2;
211 } else {
212 f_vert.tx += TRIANGLE_WIDTH;
213 r_vert.tx += TRIANGLE_WIDTH;
214 bl_vert.tx += TRIANGLE_WIDTH / 2;
215 br_vert.tx += TRIANGLE_WIDTH / 2;
216 }
217
218 draw_field // Render ground
219 (m_rect,
220 f_vert, r_vert, bl_vert, br_vert,
221 roads,
222 tr_d_texture, l_r_texture, f_d_texture, *f_r_texture);
223 }
224
225 ++linear_fy;
226 row_is_forward = not row_is_forward;
227 }
228
229 {
230 const int32_t dx2 = maxfx - minfx + 1;
231 int32_t dy2 = maxfy - minfy + 1;
232 int32_t linear_fy2 = minfy;
233 bool row_is_forward2 = linear_fy2 & 1;
234 int32_t b_posy2 = linear_fy2 * TRIANGLE_HEIGHT - viewofs.y - m_offset.y;
235
236 while (dy2--) {
237 const int32_t posy = b_posy2;
238 b_posy2 += TRIANGLE_HEIGHT;
239
240 { // Draw things on the node.
241 const int32_t linear_fx = minfx;
242 FCoords r (Coords(linear_fx, linear_fy2));
243 FCoords br(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
244
245 // Calculate safe (bounded) field coordinates and get field pointers.
246 map.normalize_coords(r);
247 map.normalize_coords(br);
248 Widelands::Map_Index r_index = Map::get_index (r, mapwidth);
249 r.field = &map[r_index];
250 Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
251 br.field = &map[br_index];
252 FCoords tr, f;
253 map.get_tln(r, &tr);
254 map.get_ln(r, &f);
255 bool r_is_border;
256 uint8_t f_owner_number = f.field->get_owned_by(); // do not use if f_vision < 1 -> PPOV
257 uint8_t r_owner_number;
258 r_is_border = r.field->is_border(); // do not use if f_vision < 1 -> PPOV
259 r_owner_number = r.field->get_owned_by(); // do not use if f_vision < 1 -> PPOV
260 uint8_t br_owner_number = br.field->get_owned_by(); // do not use if f_vision < 1 -> PPOV
261 Player::Field const * r_player_field = first_player_field + r_index;
262 const Player::Field * br_player_field = first_player_field + br_index;
263 Widelands::Vision r_vision = r_player_field->vision;
264 Widelands::Vision br_vision = br_player_field->vision;
265 Point r_pos
266 (linear_fx * TRIANGLE_WIDTH
267 +
268 row_is_forward2 * (TRIANGLE_WIDTH / 2)
269 -
270 viewofs.x - m_offset.x,
271 posy - r.field->get_height() * HEIGHT_FACTOR);
272 Point br_pos
273 (r_pos.x - TRIANGLE_WIDTH / 2,
274 b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
275
276 int32_t count = dx2;
277
278 while (count--) {
279 f = r;
280 const Player::Field & f_player_field = *r_player_field;
281 move_r(mapwidth, tr);
282 move_r(mapwidth, r, r_index);
283 move_r(mapwidth, br, br_index);
284 r_player_field = first_player_field + r_index;
285 br_player_field = first_player_field + br_index;
286
287 // do not use if f_vision < 1 -> PPOV
288 const uint8_t tr_owner_number = tr.field->get_owned_by();
289
290 const bool f_is_border = r_is_border;
291 const uint8_t l_owner_number = f_owner_number;
292 const uint8_t bl_owner_number = br_owner_number;
293 f_owner_number = r_owner_number;
294 r_is_border = r.field->is_border(); // do not use if f_vision < 1 -> PPOV
295 r_owner_number = r.field->get_owned_by(); // do not use if f_vision < 1 -> PPOV
296 br_owner_number = br.field->get_owned_by(); // do not use if f_vision < 1 -> PPOV
297 Widelands::Vision const f_vision = r_vision;
298 Widelands::Vision const bl_vision = br_vision;
299 r_vision = player.vision (r_index);
300 br_vision = player.vision(br_index);
301 const Point f_pos = r_pos, bl_pos = br_pos;
302 r_pos = Point(r_pos.x + TRIANGLE_WIDTH, posy - r.field->get_height() * HEIGHT_FACTOR);
303 br_pos = Point(br_pos.x + TRIANGLE_WIDTH, b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
304
305 if (1 < f_vision) { // Render stuff that belongs to the node.
306 // Render border markes on and halfway between border nodes.
307 if (f_is_border) {
308 const Player & owner = egbase.player(f_owner_number);
309 uint32_t const anim = owner.frontier_anim();
310 drawanim(f_pos, anim, 0, &owner);
311 if
312 ((f_vision | r_vision)
313 and
314 r_owner_number == f_owner_number
315 and
316 ((tr_owner_number == f_owner_number)
317 xor
318 (br_owner_number == f_owner_number)))
319 drawanim(middle(f_pos, r_pos), anim, 0, &owner);
320 if
321 ((f_vision | bl_vision)
322 and
323 bl_owner_number == f_owner_number
324 and
325 ((l_owner_number == f_owner_number)
326 xor
327 (br_owner_number == f_owner_number)))
328 drawanim(middle(f_pos, bl_pos), anim, 0, &owner);
329 if
330 ((f_vision | br_vision)
331 and
332 br_owner_number == f_owner_number
333 and
334 ((r_owner_number == f_owner_number)
335 xor
336 (bl_owner_number == f_owner_number)))
337 drawanim(middle(f_pos, br_pos), anim, 0, &owner);
338 }
339
340
341 // Render bobs
342 // TODO - rendering order?
343 // This must be defined somehow. Some bobs have a higher
344 // priority than others. Maybe this priority is a moving
345 // versus non-moving bobs thing? draw_ground implies that
346 // this doesn't render map objects. Are there any overdraw
347 // issues with the current rendering order?
348
349 // Draw Map_Objects hooked to this field
350 if (BaseImmovable * const imm = f.field->get_immovable())
351 imm->draw(egbase, *this, f, f_pos);
352 for
353 (Widelands::Bob * bob = f.field->get_first_bob();
354 bob;
355 bob = bob->get_next_bob())
356 bob->draw(egbase, *this, f_pos);
357
358 // Render overlays on nodes.
359 Overlay_Manager::Overlay_Info
360 overlay_info[MAX_OVERLAYS_PER_NODE];
361
362 const Overlay_Manager::Overlay_Info * const end =
363 overlay_info
364 +
365 overlay_manager.get_overlays(f, overlay_info);
366
367 for
368 (const Overlay_Manager::Overlay_Info * it = overlay_info;
369 it < end;
370 ++it)
371 blit(f_pos - it->hotspot, it->pic);
372 } else if (f_vision == 1) {
373 const Player * owner = f_player_field.owner ? egbase.get_player(f_player_field.owner) : 0;
374 if (owner) {
375 // Draw borders as they stood the last time we saw them
376 uint32_t const anim = owner->frontier_anim();
377 if (f_player_field.border)
378 drawanim(f_pos, anim, 0, owner);
379 if (f_player_field.border_r)
380 drawanim(middle(f_pos, r_pos), anim, 0, owner);
381 if (f_player_field.border_br)
382 drawanim(middle(f_pos, bl_pos), anim, 0, owner);
383 if (f_player_field.border_bl)
384 drawanim(middle(f_pos, br_pos), anim, 0, owner);
385 }
386 if
387 (const Map_Object_Descr * const map_object_descr =
388 f_player_field.map_object_descr[TCoords<>::None])
389 {
390 if
391 (const Player::Constructionsite_Information * const csinf =
392 f_player_field.constructionsite[TCoords<>::None])
393 {
394 // draw the partly finished constructionsite
395 uint32_t anim;
396 try {
397 anim = csinf->becomes->get_animation("build");
398 } catch (Map_Object_Descr::Animation_Nonexistent & e) {
399 try {
400 anim = csinf->becomes->get_animation("unoccupied");
401 } catch (Map_Object_Descr::Animation_Nonexistent) {
402 anim = csinf->becomes->get_animation("idle");
403 }
404 }
405 const AnimationGfx::Index nr_frames = g_gr->nr_frames(anim);
406 uint32_t cur_frame =
407 csinf->totaltime ? csinf->completedtime * nr_frames / csinf->totaltime : 0;
408 uint32_t tanim = cur_frame * FRAME_LENGTH;
409 uint32_t w, h;
410 g_gr->get_animation_size(anim, tanim, w, h);
411 uint32_t lines = h * csinf->completedtime * nr_frames;
412 if (csinf->totaltime)
413 lines /= csinf->totaltime;
414 assert(h * cur_frame <= lines);
415 lines -= h * cur_frame; // This won't work if pictures have various sizes.
416
417 if (cur_frame) // not the first frame
418 // draw the prev frame from top to where next image will be drawing
419 drawanimrect
420 (f_pos, anim, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
421 else if (csinf->was) {
422 // Is the first frame, but there was another building here before,
423 // get its last build picture and draw it instead.
424 uint32_t a;
425 try {
426 a = csinf->was->get_animation("unoccupied");
427 } catch (Map_Object_Descr::Animation_Nonexistent & e) {
428 a = csinf->was->get_animation("idle");
429 }
430 drawanimrect
431 (f_pos, a, tanim - FRAME_LENGTH, owner, Rect(Point(0, 0), w, h - lines));
432 }
433 assert(lines <= h);
434 drawanimrect(f_pos, anim, tanim, owner, Rect(Point(0, h - lines), w, lines));
435 } else if (upcast(const Building_Descr, building, map_object_descr)) {
436 // this is a building therefore we either draw unoccupied or idle animation
437 uint32_t pic;
438 try {
439 pic = building->get_animation("unoccupied");
440 } catch (Map_Object_Descr::Animation_Nonexistent & e) {
441 pic = building->get_animation("idle");
442 }
443 drawanim(f_pos, pic, 0, owner);
444 } else if (const uint32_t pic = map_object_descr->main_animation()) {
445 drawanim(f_pos, pic, 0, owner);
446 } else if (map_object_descr == &Widelands::g_flag_descr) {
447 drawanim(f_pos, owner->flag_anim(), 0, owner);
448 }
449 }
450 }
451 }
452 }
453
454 if (false) { // Draw things on the R-triangle (nothing to draw yet).
455 const int32_t linear_fx = minfx;
456 FCoords r(Coords(linear_fx, linear_fy2));
457 FCoords b(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
458 int32_t posx =
459 (linear_fx - 1) * TRIANGLE_WIDTH
460 +
461 (row_is_forward2 + 1) * (TRIANGLE_WIDTH / 2)
462 -
463 viewofs.x;
464
465 // Calculate safe (bounded) field coordinates.
466 map.normalize_coords(r);
467 map.normalize_coords(b);
468
469 // Get field pointers.
470 r.field = &map[Map::get_index(r, mapwidth)];
471 b.field = &map[Map::get_index(b, mapwidth)];
472
473 int32_t count = dx2;
474
475 // One less iteration than for nodes and D-triangles.
476 while (--count) {
477 const FCoords f = r;
478 map.get_rn(r, &r);
479 map.get_rn(b, &b);
480 posx += TRIANGLE_WIDTH;
481
482 // FIXME Implement visibility rules for objects on triangles
483 // FIXME when they are used in the game. The only things that
484 // FIXME are drawn on triangles now (except the ground) are
485 // FIXME overlays for the editor terrain tool, and the editor
486 // FIXME does not need visibility rules.
487 { // FIXME Visibility check here.
488 Overlay_Manager::Overlay_Info overlay_info
489 [MAX_OVERLAYS_PER_TRIANGLE];
490 const Overlay_Manager::Overlay_Info & overlay_info_end = *
491 (overlay_info
492 +
493 overlay_manager.get_overlays
494 (TCoords<>(f, TCoords<>::R), overlay_info));
495
496 for
497 (const Overlay_Manager::Overlay_Info * it = overlay_info;
498 it < &overlay_info_end;
499 ++it)
500 blit
501 (Point
502 (posx,
503 posy
504 +
505 (TRIANGLE_HEIGHT
506 -
507 (f.field->get_height()
508 +
509 r.field->get_height()
510 +
511 b.field->get_height())
512 *
513 HEIGHT_FACTOR)
514 /
515 3)
516 -
517 it->hotspot,
518 it->pic);
519 }
520 }
521 }
522
523 if (false) { // Draw things on the D-triangle (nothing to draw yet).
524 const int32_t linear_fx = minfx;
525 FCoords f(Coords(linear_fx - 1, linear_fy2));
526 FCoords br
527 (Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
528 int32_t posx =
529 (linear_fx - 1) * TRIANGLE_WIDTH
530 +
531 row_is_forward2 * (TRIANGLE_WIDTH / 2)
532 -
533 viewofs.x;
534
535 // Calculate safe (bounded) field coordinates.
536 map.normalize_coords(f);
537 map.normalize_coords(br);
538
539 // Get field pointers.
540 f.field = &map[Map::get_index(f, mapwidth)];
541 br.field = &map[Map::get_index(br, mapwidth)];
542
543 int32_t count = dx2;
544
545 while (count--) {
546 const FCoords bl = br;
547 map.get_rn(f, &f);
548 map.get_rn(br, &br);
549 posx += TRIANGLE_WIDTH;
550
551 { // FIXME Visibility check here.
552 Overlay_Manager::Overlay_Info overlay_info
553 [MAX_OVERLAYS_PER_TRIANGLE];
554 Overlay_Manager::Overlay_Info const * const overlay_info_end
555 =
556 overlay_info
557 +
558 overlay_manager.get_overlays
559 (TCoords<>(f, TCoords<>::D), overlay_info);
560
561 for
562 (const Overlay_Manager::Overlay_Info * it = overlay_info;
563 it < overlay_info_end;
564 ++it)
565 blit
566 (Point
567 (posx,
568 posy
569 +
570 ((TRIANGLE_HEIGHT * 2)
571 -
572 (f.field->get_height()
573 +
574 bl.field->get_height()
575 +
576 br.field->get_height())
577 *
578 HEIGHT_FACTOR)
579 /
580 3)
581 -
582 it->hotspot,
583 it->pic);
584 }
585 }
586 }
587
588 ++linear_fy2;
589 row_is_forward2 = not row_is_forward2;
590 }
591 }
592
593 rendermap_deint();
594
595 g_gr->reset_texture_animation_reminder();
596}
597
598void GameView::rendermap
599 (Widelands::Editor_Game_Base const & egbase,
600 Point viewofs)
601{
602 RENDERMAP_INITIALIZATIONS;
603
604 rendermap_init();
605
606 while (dy--) {
607 const int32_t posy = b_posy;
608 b_posy += TRIANGLE_HEIGHT;
609 const int32_t linear_fx = minfx;
610 FCoords r(Coords(linear_fx, linear_fy));
611 FCoords br(Coords(linear_fx - not row_is_forward, linear_fy + 1));
612 int32_t r_posx =
613 r.x * TRIANGLE_WIDTH
614 +
615 row_is_forward * (TRIANGLE_WIDTH / 2)
616 -
617 viewofs.x;
618 int32_t br_posx = r_posx - TRIANGLE_WIDTH / 2;
619
620 // Calculate safe (bounded) field coordinates and get field pointers
621 map.normalize_coords(r);
622 map.normalize_coords(br);
623 Widelands::Map_Index r_index = Map::get_index (r, mapwidth);
624 r.field = &map[r_index];
625 Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
626 br.field = &map[br_index];
627 FCoords tr, f;
628 map.get_tln(r, &tr);
629 map.get_ln(r, &f);
630 const Texture * f_r_texture =
631 g_gr->get_maptexture_data
632 (world.terrain_descr(f.field->terrain_r()).get_texture());
633
634 uint32_t count = dx;
635
636 while (count--) {
637 const FCoords bl = br;
638 f = r;
639 const int32_t f_posx = r_posx, bl_posx = br_posx;
640 const Texture & l_r_texture = *f_r_texture;
641 move_r(mapwidth, tr);
642 move_r(mapwidth, r, r_index);
643 move_r(mapwidth, br, br_index);
644 r_posx += TRIANGLE_WIDTH;
645 br_posx += TRIANGLE_WIDTH;
646 const Texture & tr_d_texture =
647 *g_gr->get_maptexture_data
648 (world.terrain_descr(tr.field->terrain_d()).get_texture());
649 const Texture & f_d_texture =
650 *g_gr->get_maptexture_data
651 (world.terrain_descr(f.field->terrain_d()).get_texture());
652 f_r_texture =
653 g_gr->get_maptexture_data
654 (world.terrain_descr(f.field->terrain_r()).get_texture());
655
656 const uint8_t roads =
657 f.field->get_roads() | overlay_manager.get_road_overlay(f);
658
659 Vertex f_vert
660 (f_posx, posy - f.field->get_height() * HEIGHT_FACTOR,
661 f.field->get_brightness(),
662 0, 0);
663 Vertex r_vert
664 (r_posx, posy - r.field->get_height() * HEIGHT_FACTOR,
665 r.field->get_brightness(),
666 TRIANGLE_WIDTH, 0);
667 Vertex bl_vert
668 (bl_posx, b_posy - bl.field->get_height() * HEIGHT_FACTOR,
669 bl.field->get_brightness(),
670 0, 64);
671 Vertex br_vert
672 (br_posx, b_posy - br.field->get_height() * HEIGHT_FACTOR,
673 br.field->get_brightness(),
674 TRIANGLE_WIDTH, 64);
675
676 if (row_is_forward) {
677 f_vert.tx += TRIANGLE_WIDTH / 2;
678 r_vert.tx += TRIANGLE_WIDTH / 2;
679 } else {
680 bl_vert.tx -= TRIANGLE_WIDTH / 2;
681 br_vert.tx -= TRIANGLE_WIDTH / 2;
682 }
683
684 draw_field // Render ground
685 (m_rect,
686 f_vert, r_vert, bl_vert, br_vert,
687 roads,
688 tr_d_texture, l_r_texture, f_d_texture, *f_r_texture);
689 }
690
691 ++linear_fy;
692 row_is_forward = not row_is_forward;
693 }
694
695 {
696 const int32_t dx2 = maxfx - minfx + 1;
697 int32_t dy2 = maxfy - minfy + 1;
698 int32_t linear_fy2 = minfy;
699 bool row_is_forward2 = linear_fy2 & 1;
700 int32_t b_posy2 = linear_fy2 * TRIANGLE_HEIGHT - viewofs.y;
701
702 while (dy2--) {
703 const int32_t posy = b_posy2;
704 b_posy2 += TRIANGLE_HEIGHT;
705
706 { // Draw things on the node.
707 const int32_t linear_fx = minfx;
708 FCoords r(Coords(linear_fx, linear_fy2));
709 FCoords br
710 (Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
711
712 // Calculate safe (bounded) field coordinates and get field
713 // pointers.
714 map.normalize_coords(r);
715 map.normalize_coords(br);
716 Widelands::Map_Index r_index = Map::get_index (r, mapwidth);
717 r.field = &map[r_index];
718 Widelands::Map_Index br_index = Map::get_index(br, mapwidth);
719 br.field = &map[br_index];
720 FCoords tr, f;
721 map.get_tln(r, &tr);
722 map.get_ln(r, &f);
723 bool r_is_border;
724 uint8_t f_owner_number = f.field->get_owned_by();
725 uint8_t r_owner_number;
726 r_is_border = r.field->is_border();
727 r_owner_number = r.field->get_owned_by();
728 uint8_t br_owner_number = br.field->get_owned_by();
729 Point r_pos
730 (linear_fx * TRIANGLE_WIDTH
731 +
732 row_is_forward2 * (TRIANGLE_WIDTH / 2)
733 -
734 viewofs.x,
735 posy - r.field->get_height() * HEIGHT_FACTOR);
736 Point br_pos
737 (r_pos.x - TRIANGLE_WIDTH / 2,
738 b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
739
740 int32_t count = dx2;
741
742 while (count--) {
743 f = r;
744 move_r(mapwidth, tr);
745 move_r(mapwidth, r, r_index);
746 move_r(mapwidth, br, br_index);
747 const uint8_t tr_owner_number = tr.field->get_owned_by();
748 const bool f_is_border = r_is_border;
749 const uint8_t l_owner_number = f_owner_number;
750 const uint8_t bl_owner_number = br_owner_number;
751 f_owner_number = r_owner_number;
752 r_is_border = r.field->is_border();
753 r_owner_number = r.field->get_owned_by();
754 br_owner_number = br.field->get_owned_by();
755 const Point f_pos = r_pos, bl_pos = br_pos;
756 r_pos = Point
757 (r_pos.x + TRIANGLE_WIDTH,
758 posy - r.field->get_height() * HEIGHT_FACTOR);
759 br_pos = Point
760 (br_pos.x + TRIANGLE_WIDTH,
761 b_posy2 - br.field->get_height() * HEIGHT_FACTOR);
762
763 // Render border markes on and halfway between border nodes.
764 if (f_is_border) {
765 const Player & owner = egbase.player(f_owner_number);
766 uint32_t const anim = owner.frontier_anim();
767 drawanim(f_pos, anim, 0, &owner);
768 if
769 (r_owner_number == f_owner_number
770 and
771 ((tr_owner_number == f_owner_number)
772 xor
773 (br_owner_number == f_owner_number)))
774 drawanim(middle(f_pos, r_pos), anim, 0, &owner);
775 if
776 (bl_owner_number == f_owner_number
777 and
778 ((l_owner_number == f_owner_number)
779 xor
780 (br_owner_number == f_owner_number)))
781 drawanim(middle(f_pos, bl_pos), anim, 0, &owner);
782 if
783 (br_owner_number == f_owner_number
784 and
785 ((r_owner_number == f_owner_number)
786 xor
787 (bl_owner_number == f_owner_number)))
788 drawanim(middle(f_pos, br_pos), anim, 0, &owner);
789 }
790
791 { // Render stuff that belongs to the node.
792
793 // Render bobs
794 // TODO - rendering order?
795 // This must be defined somehow. Some bobs have a higher
796 // priority than others. Maybe this priority is a moving
797 // versus non-moving bobs thing? draw_ground implies that
798 // this doesn't render map objects. Are there any overdraw
799 // issues with the current rendering order?
800
801 // Draw Map_Objects hooked to this field
802 if (BaseImmovable * const imm = f.field->get_immovable())
803 imm->draw(egbase, *this, f, f_pos);
804 for
805 (Widelands::Bob * bob = f.field->get_first_bob();
806 bob;
807 bob = bob->get_next_bob())
808 bob->draw(egbase, *this, f_pos);
809
810 // Render overlays on nodes.
811 Overlay_Manager::Overlay_Info
812 overlay_info[MAX_OVERLAYS_PER_NODE];
813
814 const Overlay_Manager::Overlay_Info * const end =
815 overlay_info
816 +
817 overlay_manager.get_overlays(f, overlay_info);
818
819 for
820 (const Overlay_Manager::Overlay_Info * it = overlay_info;
821 it < end;
822 ++it)
823 blit(f_pos - it->hotspot, it->pic);
824 }
825 }
826 }
827
828 { // Draw things on the R-triangle.
829 const int32_t linear_fx = minfx;
830 FCoords r(Coords(linear_fx, linear_fy2));
831 FCoords b
832 (Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
833 int32_t posx =
834 (linear_fx - 1) * TRIANGLE_WIDTH
835 +
836 (row_is_forward2 + 1) * (TRIANGLE_WIDTH / 2)
837 -
838 viewofs.x;
839
840 // Calculate safe (bounded) field coordinates.
841 map.normalize_coords(r);
842 map.normalize_coords(b);
843
844 // Get field pointers.
845 r.field = &map[Map::get_index(r, mapwidth)];
846 b.field = &map[Map::get_index(b, mapwidth)];
847
848 int32_t count = dx2;
849
850 // One less iteration than for nodes and D-triangles.
851 while (--count) {
852 const FCoords f = r;
853 map.get_rn(r, &r);
854 map.get_rn(b, &b);
855 posx += TRIANGLE_WIDTH;
856
857 {
858 Overlay_Manager::Overlay_Info overlay_info
859 [MAX_OVERLAYS_PER_TRIANGLE];
860 Overlay_Manager::Overlay_Info const & overlay_info_end =
861 *
862 (overlay_info
863 +
864 overlay_manager.get_overlays
865 (TCoords<>(f, TCoords<>::R), overlay_info));
866
867 for
868 (Overlay_Manager::Overlay_Info const * it = overlay_info;
869 it < &overlay_info_end;
870 ++it)
871 blit
872 (Point
873 (posx,
874 posy
875 +
876 (TRIANGLE_HEIGHT
877 -
878 (f.field->get_height()
879 +
880 r.field->get_height()
881 +
882 b.field->get_height())
883 *
884 HEIGHT_FACTOR)
885 /
886 3)
887 -
888 it->hotspot,
889 it->pic);
890 }
891 }
892 }
893
894 { // Draw things on the D-triangle.
895 const int32_t linear_fx = minfx;
896 FCoords f(Coords(linear_fx - 1, linear_fy2));
897 FCoords br(Coords(linear_fx - not row_is_forward2, linear_fy2 + 1));
898 int32_t posx =
899 (linear_fx - 1) * TRIANGLE_WIDTH
900 +
901 row_is_forward2 * (TRIANGLE_WIDTH / 2)
902 -
903 viewofs.x;
904
905 // Calculate safe (bounded) field coordinates.
906 map.normalize_coords(f);
907 map.normalize_coords(br);
908
909 // Get field pointers.
910 f.field = &map[Map::get_index(f, mapwidth)];
911 br.field = &map[Map::get_index(br, mapwidth)];
912
913 int32_t count = dx2;
914
915 while (count--) {
916 const FCoords bl = br;
917 map.get_rn(f, &f);
918 map.get_rn(br, &br);
919 posx += TRIANGLE_WIDTH;
920
921 {
922 Overlay_Manager::Overlay_Info overlay_info
923 [MAX_OVERLAYS_PER_TRIANGLE];
924 const Overlay_Manager::Overlay_Info & overlay_info_end = *
925 (overlay_info
926 +
927 overlay_manager.get_overlays
928 (TCoords<>(f, TCoords<>::D), overlay_info));
929
930 for
931 (const Overlay_Manager::Overlay_Info * it = overlay_info;
932 it < &overlay_info_end;
933 ++it)
934 blit
935 (Point
936 (posx,
937 posy
938 +
939 ((TRIANGLE_HEIGHT * 2)
940 -
941 (f.field->get_height()
942 +
943 bl.field->get_height()
944 +
945 br.field->get_height())
946 *
947 HEIGHT_FACTOR)
948 /
949 3)
950 -
951 it->hotspot,
952 it->pic);
953 }
954 }
955 }
956
957 ++linear_fy2;
958 row_is_forward2 = not row_is_forward2;
959 }
960 }
961
962 rendermap_deint();
963
964 g_gr->reset_texture_animation_reminder();
965}
966
96743
968/**44/**
969 * Renders a minimap into the current window. The field at viewpoint will be45 * Renders a minimap into the current window. The field at viewpoint will be
@@ -973,7 +49,7 @@
973 * Calculate the field at the top-left corner of the clipping rect49 * Calculate the field at the top-left corner of the clipping rect
974 * The entire clipping rect will be used for drawing.50 * The entire clipping rect will be used for drawing.
975 */51 */
976void GameView::renderminimap52void MiniMapRenderer::renderminimap
977 (Widelands::Editor_Game_Base const & egbase,53 (Widelands::Editor_Game_Base const & egbase,
978 Player const * const player,54 Player const * const player,
979 Point const viewpoint,55 Point const viewpoint,
@@ -986,47 +62,6 @@
986}62}
98763
98864
989
990/**
991 * Draw ground textures and roads for the given parallelogram (two triangles)
992 * into the bitmap.
993 *
994 * Vertices:
995 * - f_vert vertex of the field
996 * - r_vert vertex right of the field
997 * - bl_vert vertex bottom left of the field
998 * - br_vert vertex bottom right of the field
999 *
1000 * Textures:
1001 * - f_r_texture Terrain of the triangle right of the field
1002 * - f_d_texture Terrain of the triangle under of the field
1003 * - tr_d_texture Terrain of the triangle top of the right triangle ??
1004 * - l_r_texture Terrain of the triangle left of the down triangle ??
1005 *
1006 * (tr_d)
1007 *
1008 * (f) *------* (r)
1009 * / \ r /
1010 * (l_r) / \ /
1011 * / d \/
1012 * (bl) *------* (br)
1013 */
1014
1015void GameView::draw_field
1016 (Rect & /* subwin */,
1017 Vertex const & /* f_vert */,
1018 Vertex const & /* r_vert */,
1019 Vertex const & /* bl_vert */,
1020 Vertex const & /* br_vert */,
1021 uint8_t /* roads */,
1022 Texture const & /* tr_d_texture */,
1023 Texture const & /* l_r_texture */,
1024 Texture const & /* f_d_texture */,
1025 Texture const & /* f_r_texture */)
1026{
1027
1028}
1029
1030/*65/*
1031 * Blend to colors; only needed for calc_minimap_color below66 * Blend to colors; only needed for calc_minimap_color below
1032 */67 */
@@ -1290,7 +325,7 @@
1290viewpt is the field at the top left of the rectangle.325viewpt is the field at the top left of the rectangle.
1291===============326===============
1292*/327*/
1293void GameView::draw_minimap328void MiniMapRenderer::draw_minimap
1294 (Widelands::Editor_Game_Base const & egbase,329 (Widelands::Editor_Game_Base const & egbase,
1295 Widelands::Player const * const player,330 Widelands::Player const * const player,
1296 Rect const rc,331 Rect const rc,
1297332
=== renamed file 'src/graphic/render/gameview.h' => 'src/graphic/render/minimaprenderer.h'
--- src/graphic/render/gameview.h 2012-11-24 16:22:10 +0000
+++ src/graphic/render/minimaprenderer.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2010-2012 by the Widelands Development Team2 * Copyright (C) 2010-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -17,58 +17,25 @@
17 *17 *
18 */18 */
1919
20#ifndef WIDELANDS_GAMEVIEW_H20#ifndef WIDELANDS_MINIMAPRENDERER_H
21#define WIDELANDS_GAMEVIEW_H21#define WIDELANDS_MINIMAPRENDERER_H
22
23#include "graphic/rendertarget.h"
2224
23namespace Widelands {25namespace Widelands {
24 struct Player;26 struct Player;
25 struct Editor_Game_Base;27 struct Editor_Game_Base;
26};28};
2729
28struct Vertex;
29struct Texture;
30
31#include "graphic/rendertarget.h"
32
33/**30/**
34 * This class does the game rendering. The class is initialized from a31 * This class renders the minimap.
35 * RenderTarget and can draw views of the game and the minimap. The game
36 * can be rendered to the full screen or to a subwindow. This depends on
37 * the RenderTarget from which it was initialized.
38 *
39 * @todo GameView mixes opengl and software rendering. This should be split
40 * properly to have different classes for OpenGL and Software rendering.
41 * Perhaps creating a GameRenderManager where different rendering classes can
42 * be registered so it is easiely possible to create different game rendering?
43 */32 */
44class GameView : public RenderTarget33class MiniMapRenderer : public RenderTarget
45{34{
46public:35public:
47 GameView(RenderTarget & rt) :36 MiniMapRenderer(RenderTarget & rt) :
48 RenderTarget(rt) {}37 RenderTarget(rt) {}
49 virtual ~GameView() {}38 virtual ~MiniMapRenderer() {}
50
51 /**
52 * Renders the map from a player's point of view into the current drawing
53 * window.
54 *
55 * Will call the function below when player.see_all().
56 *
57 * viewofs is the offset of the upper left corner of the window into the map,
58 * in pixels.
59 */
60 void rendermap
61 (Widelands::Editor_Game_Base const & egbase,
62 Widelands::Player const & player,
63 Point viewofs);
64
65 /**
66 * Same as above but not from a player's point of view. Used in game when
67 * rendering for a player that sees all and the editor.
68 */
69 void rendermap
70 (Widelands::Editor_Game_Base const & egbase,
71 Point viewofs);
7239
73 /**40 /**
74 * Render the minimap. If player is not 0, it renders from that player's41 * Render the minimap. If player is not 0, it renders from that player's
@@ -81,22 +48,6 @@
81 uint32_t flags);48 uint32_t flags);
8249
83protected:50protected:
84 /**
85 * Helper function to draw two terrain triangles. This is called from the
86 * rendermap() functions.
87 */
88 virtual void draw_field
89 (Rect & subwin,
90 Vertex const & f_vert,
91 Vertex const & r_vert,
92 Vertex const & bl_vert,
93 Vertex const & br_vert,
94 uint8_t roads,
95 Texture const & tr_d_texture,
96 Texture const & l_r_texture,
97 Texture const & f_d_texture,
98 Texture const & f_r_texture);
99
100 /// A helper function to draw the minimap. This is called from51 /// A helper function to draw the minimap. This is called from
101 /// renderminimap().52 /// renderminimap().
102 void draw_minimap53 void draw_minimap
@@ -106,16 +57,6 @@
106 Point viewpt,57 Point viewpt,
107 Point framept,58 Point framept,
108 uint32_t flags);59 uint32_t flags);
109
110 /**
111 * This is called before the view of the game is rendered.
112 */
113 virtual void rendermap_init() {}
114
115 /**
116 * This is called after the view of the game is rendered.
117 */
118 virtual void rendermap_deint() {}
119};60};
12061
121#endif //WIDELANDS_GAMEVIEW_H62#endif //WIDELANDS_MINIMAPRENDERER_H
12263
=== removed file 'src/graphic/render/terrain_opengl.h'
--- src/graphic/render/terrain_opengl.h 2012-12-07 07:32:24 +0000
+++ src/graphic/render/terrain_opengl.h 1970-01-01 00:00:00 +0000
@@ -1,327 +0,0 @@
1/*
2 * Copyright (C) 2010-2012 by the Widelands Development Team
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 */
19
20#ifdef USE_OPENGL
21#ifndef TERRAIN_OPENGL_H
22#define TERRAIN_OPENGL_H
23
24#include "gl_surface_texture.h"
25#include "vertex.h"
26
27
28void draw_field_opengl
29 (Rect const & subwin,
30 Vertex const & p1,
31 Vertex const & p2,
32 Vertex const & p3,
33 Texture const & texture,
34 Texture const & left_texture,
35 Texture const & top_texture)
36{
37 if (p1.b <= -128 and p2.b <= -128 and p3.b <= -128)
38 return;
39
40 Vertex t1(p1), t2(p2), t3(p3);
41
42 t1.x = p1.x + subwin.x;
43 t1.y = p1.y + subwin.y;
44 t2.x = p2.x + subwin.x;
45 t2.y = p2.y + subwin.y;
46 t3.x = p3.x + subwin.x;
47 t3.y = p3.y + subwin.y;
48
49 if (t1.x < subwin.x and t2.x < subwin.x and t3.x < subwin.x)
50 return;
51 if (t1.y < subwin.y and t2.y < subwin.y and t3.y < subwin.y)
52 return;
53
54 int const subxr = subwin.x + subwin.w;
55 if (t1.x > subxr and t2.x > subxr and t3.x > subxr)
56 return;
57
58 int const subyd = subwin.y + subwin.h;
59 if (t1.y > subyd and t2.y > subyd and t3.y > subyd)
60 return;
61
62 glEnable(GL_BLEND);
63
64 if (g_gr->caps().gl.multitexture) {
65
66 // load current texture
67 glActiveTextureARB(GL_TEXTURE0_ARB);
68 glEnable(GL_TEXTURE_2D);
69 glBindTexture(GL_TEXTURE_2D, texture.getTexture());
70 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
71
72 // initialize all texture layers to prevent bug if some layers are skipped
73 for (int i = 1; i < 5; i++) {
74 glActiveTextureARB(GL_TEXTURE0_ARB + i);
75 glEnable(GL_TEXTURE_2D);
76 glBindTexture(GL_TEXTURE_2D, top_texture.getTexture());
77 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
78 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
79 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
80 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
81 }
82
83 if ((&top_texture != &texture) and not (p1.b == -128 and p3.b == -128)) {
84 // load top texture
85 glActiveTextureARB(GL_TEXTURE1_ARB);
86 glEnable(GL_TEXTURE_2D);
87 glBindTexture(GL_TEXTURE_2D, top_texture.getTexture());
88 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
89 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
90 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
91 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
92
93 GLuint edge = dynamic_cast<GLSurfaceTexture const &>
94 (*g_gr->get_edge_texture()).get_gl_texture();
95
96 // combine current and top texture
97 glActiveTextureARB(GL_TEXTURE2_ARB);
98 glEnable(GL_TEXTURE_2D);
99 glBindTexture(GL_TEXTURE_2D, edge);
100 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
101 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
102 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
103 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1_ARB);
104 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
105 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
106 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
107 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
108 }
109
110 if ((&left_texture != &texture) and not (p1.b == -128 and p2.b == -128)) {
111 // load left texture
112 glActiveTextureARB(GL_TEXTURE3_ARB);
113 glEnable(GL_TEXTURE_2D);
114 glBindTexture(GL_TEXTURE_2D, left_texture.getTexture());
115 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
116 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
117 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
118 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
119
120 GLuint edge = dynamic_cast<GLSurfaceTexture const &>
121 (*g_gr->get_edge_texture()).get_gl_texture();
122
123 // combine current and left texture
124 glActiveTextureARB(GL_TEXTURE4_ARB);
125 glEnable(GL_TEXTURE_2D);
126 glBindTexture(GL_TEXTURE_2D, edge);
127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
129 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
130 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
131 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
132 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE3_ARB);
133 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
134 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
135 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
136 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
137 }
138
139 // Fade effect for fog of war
140 glActiveTextureARB(GL_TEXTURE5_ARB);
141 glEnable(GL_TEXTURE_2D);
142 // texture does not matter but one has to be bound
143 glBindTexture(GL_TEXTURE_2D, texture.getTexture());
144 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
145 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
146 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
147 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
148 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
149 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
150
151 glBegin(GL_TRIANGLES); {
152 {
153 GLfloat const brightness = (150.0 + p1.b) / 150.0;
154 glColor3f(brightness, brightness, brightness);
155 }
156 glMultiTexCoord2iARB(GL_TEXTURE0_ARB, t1.tx, t1.ty);
157 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t1.tx / TEXTURE_WIDTH, t1.ty / TEXTURE_WIDTH);
158 glMultiTexCoord2fARB(GL_TEXTURE2_ARB, 0, 0);
159 glMultiTexCoord2fARB(GL_TEXTURE3_ARB, t1.tx / TEXTURE_WIDTH, t1.ty / TEXTURE_WIDTH);
160 glMultiTexCoord2fARB(GL_TEXTURE4_ARB, 1, 0);
161 glMultiTexCoord2fARB(GL_TEXTURE5_ARB, t1.tx / TEXTURE_WIDTH, t1.ty / TEXTURE_WIDTH);
162 glVertex2f(t1.x, t1.y);
163
164 {
165 GLfloat const brightness = (150.0 + p2.b) / 150.0;
166 glColor3f(brightness, brightness, brightness);
167 }
168 glMultiTexCoord2iARB(GL_TEXTURE0_ARB, t2.tx, t2.ty);
169 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t2.tx / TEXTURE_WIDTH, t2.ty / TEXTURE_WIDTH);
170 glMultiTexCoord2fARB(GL_TEXTURE2_ARB, 0.5, 1);
171 glMultiTexCoord2fARB(GL_TEXTURE3_ARB, t2.tx / TEXTURE_WIDTH, t2.ty / TEXTURE_WIDTH);
172 glMultiTexCoord2fARB(GL_TEXTURE4_ARB, 0, 0);
173 glMultiTexCoord2fARB(GL_TEXTURE5_ARB, t2.tx / TEXTURE_WIDTH, t2.ty / TEXTURE_WIDTH);
174 glVertex2f(t2.x, t2.y);
175
176 {
177 GLfloat const brightness = (150.0 + p3.b) / 150.0;
178 glColor3f(brightness, brightness, brightness);
179 }
180 glMultiTexCoord2iARB(GL_TEXTURE0_ARB, t3.tx, t3.ty);
181 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, t3.tx / TEXTURE_WIDTH, t3.ty / TEXTURE_WIDTH);
182 glMultiTexCoord2fARB(GL_TEXTURE2_ARB, 1, 0);
183 glMultiTexCoord2fARB(GL_TEXTURE3_ARB, t3.tx / TEXTURE_WIDTH, t3.ty / TEXTURE_WIDTH);
184 glMultiTexCoord2fARB(GL_TEXTURE4_ARB, 0.5, 1);
185 glMultiTexCoord2fARB(GL_TEXTURE5_ARB, t3.tx / TEXTURE_WIDTH, t3.ty / TEXTURE_WIDTH);
186 glVertex2f(t3.x, t3.y);
187 } glEnd();
188
189 // Cleanup OpenGL
190 glActiveTextureARB(GL_TEXTURE5_ARB);
191 glDisable(GL_TEXTURE_2D);
192 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
193 glActiveTextureARB(GL_TEXTURE4_ARB);
194 glDisable(GL_TEXTURE_2D);
195 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
196 glActiveTextureARB(GL_TEXTURE3_ARB);
197 glDisable(GL_TEXTURE_2D);
198 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
199 glActiveTextureARB(GL_TEXTURE2_ARB);
200 glDisable(GL_TEXTURE_2D);
201 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
202 glActiveTextureARB(GL_TEXTURE1_ARB);
203 glDisable(GL_TEXTURE_2D);
204 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
205 glActiveTextureARB(GL_TEXTURE0_ARB);
206 glEnable(GL_TEXTURE_2D);
207 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
208
209 } else {
210 // don't use multitexture
211 glBindTexture(GL_TEXTURE_2D, texture.getTexture());
212 glBegin(GL_TRIANGLES); {
213 {
214 GLfloat const brightness = (150.0 + p1.b) / 150.0;
215 glColor3f(brightness, brightness, brightness);
216 }
217 glTexCoord2i(t1.tx, t1.ty);
218 glVertex2f(t1.x, t1.y);
219
220 {
221 GLfloat const brightness = (150.0 + p2.b) / 150.0;
222 glColor3f(brightness, brightness, brightness);
223 }
224 glTexCoord2i(t2.tx, t2.ty);
225 glVertex2f(t2.x, t2.y);
226
227 {
228 GLfloat const brightness = (150.0 + p3.b) / 150.0;
229 glColor3f(brightness, brightness, brightness);
230 }
231 glTexCoord2i(t3.tx, t3.ty);
232 glVertex2f(t3.x, t3.y);
233 } glEnd();
234 }
235}
236
237#define horiz_road_opengl(tex, start, end) \
238 glBindTexture( GL_TEXTURE_2D, tex); \
239 glBegin(GL_QUADS); { \
240 glTexCoord2i(0, 0); \
241 glVertex2f(subwin.x + start.x, subwin.y + start.y - 2); \
242 glTexCoord2i(TEXTURE_WIDTH, 0); \
243 glVertex2f(subwin.x + end.x, subwin.y + end.y - 2); \
244 glTexCoord2i(TEXTURE_WIDTH, 4); \
245 glVertex2f(subwin.x + end.x, subwin.y + end.y + 2); \
246 glTexCoord2i(0, 4); \
247 glVertex2f(subwin.x + start.x, subwin.y + start.y + 2); \
248 } glEnd(); \
249
250#define vert_road_opengl(tex, start, end) \
251 glBindTexture( GL_TEXTURE_2D, tex); \
252 glBegin(GL_QUADS); { \
253 glTexCoord2i(0, 0); \
254 glVertex2f(subwin.x + start.x - 3, subwin.y + start.y); \
255 glTexCoord2i(6, 0); \
256 glVertex2f(subwin.x + start.x + 3, subwin.y + start.y); \
257 glTexCoord2i(TEXTURE_WIDTH, TEXTURE_HEIGHT); \
258 glVertex2f(subwin.x + end.x + 3, subwin.y + end.y); \
259 glTexCoord2i(TEXTURE_WIDTH - 6, TEXTURE_HEIGHT); \
260 glVertex2f(subwin.x + end.x - 3, subwin.y + end.y); \
261 } glEnd(); \
262
263void draw_roads_opengl
264 (Rect & subwin,
265 uint8_t roads,
266 Vertex const & f_vert,
267 Vertex const & r_vert,
268 Vertex const & bl_vert,
269 Vertex const & br_vert)
270{
271 uint8_t road;
272
273 GLuint rt_normal =
274 dynamic_cast<GLSurfaceTexture const &>
275 (*g_gr->get_road_texture(Widelands::Road_Normal)).get_gl_texture();
276 GLuint rt_busy =
277 dynamic_cast<GLSurfaceTexture const &>
278 (*g_gr->get_road_texture(Widelands::Road_Busy)).get_gl_texture();
279
280 glDisable(GL_BLEND);
281 glColor4f(1.0f, 1.0f, 1.0f, 0.6f);
282
283 road = (roads >> Widelands::Road_East) & Widelands::Road_Mask;
284 if ((-128 < f_vert.b or -128 < r_vert.b) and road) {
285 switch (road) {
286 case Widelands::Road_Normal:
287 horiz_road_opengl(rt_normal, f_vert, r_vert)
288 break;
289 case Widelands::Road_Busy:
290 horiz_road_opengl(rt_busy, f_vert, r_vert)
291 break;
292 default:
293 assert(false);
294 }
295 }
296
297 road = (roads >> Widelands::Road_SouthEast) & Widelands::Road_Mask;
298 if ((-128 < f_vert.b or -128 < br_vert.b) and road) {
299 switch (road) {
300 case Widelands::Road_Normal:
301 vert_road_opengl(rt_normal, f_vert, br_vert);
302 break;
303 case Widelands::Road_Busy:
304 vert_road_opengl(rt_busy, f_vert, br_vert);
305 break;
306 default:
307 assert(false);
308 }
309 }
310
311 road = (roads >> Widelands::Road_SouthWest) & Widelands::Road_Mask;
312 if ((-128 < f_vert.b or -128 < bl_vert.b) and road) {
313 switch (road) {
314 case Widelands::Road_Normal:
315 vert_road_opengl(rt_normal, f_vert, bl_vert);
316 break;
317 case Widelands::Road_Busy:
318 vert_road_opengl(rt_busy, f_vert, bl_vert);
319 break;
320 default:
321 assert(false);
322 }
323 }
324}
325
326#endif
327#endif
3280
=== modified file 'src/graphic/rendertarget.h'
--- src/graphic/rendertarget.h 2012-12-15 18:40:59 +0000
+++ src/graphic/rendertarget.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team2 * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -88,6 +88,8 @@
88 void reset();88 void reset();
8989
90 Surface* get_surface() {return m_surface;}90 Surface* get_surface() {return m_surface;}
91 const Rect & get_rect() const {return m_rect;}
92 const Point & get_offset() const {return m_offset;}
9193
92protected:94protected:
93 bool clip(Rect & r) const throw ();95 bool clip(Rect & r) const throw ();
9496
=== modified file 'src/logic/instances.h'
--- src/logic/instances.h 2013-02-03 10:44:13 +0000
+++ src/logic/instances.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team2 * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
66
=== modified file 'src/logic/tribe.h'
--- src/logic/tribe.h 2013-02-03 10:44:13 +0000
+++ src/logic/tribe.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002, 2006-2011 by the Widelands Development Team2 * Copyright (C) 2002, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
66
=== modified file 'src/logic/world.cc'
--- src/logic/world.cc 2012-11-30 22:10:10 +0000
+++ src/logic/world.cc 2013-02-09 12:25:26 +0000
@@ -821,6 +821,7 @@
821m_name (s->get_name()),821m_name (s->get_name()),
822m_descname (s->get_string("name", s->get_name())),822m_descname (s->get_string("name", s->get_name())),
823m_frametime (FRAME_LENGTH),823m_frametime (FRAME_LENGTH),
824m_dither_layer (0),
824m_valid_resources (0),825m_valid_resources (0),
825m_nr_valid_resources(0),826m_nr_valid_resources(0),
826m_default_resources (-1),827m_default_resources (-1),
@@ -896,6 +897,8 @@
896 throw game_data_error("%s: invalid type '%s'", m_name.c_str(), is);897 throw game_data_error("%s: invalid type '%s'", m_name.c_str(), is);
897 }898 }
898899
900 m_dither_layer = s->get_int("dither_layer", 0);
901
899 // Determine template of the texture animation pictures902 // Determine template of the texture animation pictures
900 char fnametmpl[256];903 char fnametmpl[256];
901904
902905
=== modified file 'src/logic/world.h'
--- src/logic/world.h 2012-11-30 22:10:10 +0000
+++ src/logic/world.h 2013-02-09 12:25:26 +0000
@@ -113,6 +113,7 @@
113 int32_t get_default_resources_amount() const throw () {113 int32_t get_default_resources_amount() const throw () {
114 return m_default_amount;114 return m_default_amount;
115 }115 }
116 int32_t dither_layer() const {return m_dither_layer;}
116117
117private:118private:
118 const std::string m_name;119 const std::string m_name;
@@ -121,12 +122,13 @@
121 uint32_t m_frametime;122 uint32_t m_frametime;
122 uint8_t m_is;123 uint8_t m_is;
123124
125 int32_t m_dither_layer;
126
124 uint8_t * m_valid_resources;127 uint8_t * m_valid_resources;
125 uint8_t m_nr_valid_resources;128 uint8_t m_nr_valid_resources;
126 int8_t m_default_resources;129 int8_t m_default_resources;
127 int32_t m_default_amount;130 int32_t m_default_amount;
128 uint32_t m_texture; // renderer's texture131 uint32_t m_texture; // renderer's texture
129
130};132};
131133
132struct MapGenInfo;134struct MapGenInfo;
133135
=== modified file 'src/point.h'
--- src/point.h 2012-09-21 21:36:07 +0000
+++ src/point.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002-2004, 2006-2007 by the Widelands Development Team2 * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -44,6 +44,9 @@
44 Point operator+ (const Point & other) const {44 Point operator+ (const Point & other) const {
45 return Point(x + other.x, y + other.y);45 return Point(x + other.x, y + other.y);
46 }46 }
47 Point operator- () const {
48 return Point(-x, -y);
49 }
47 Point operator- (const Point & other) const {50 Point operator- (const Point & other) const {
48 return Point(x - other.x, y - other.y);51 return Point(x - other.x, y - other.y);
49 }52 }
5053
=== modified file 'src/rect.h'
--- src/rect.h 2013-02-04 21:52:38 +0000
+++ src/rect.h 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team2 * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
66
=== modified file 'src/wui/mapview.cc'
--- src/wui/mapview.cc 2012-12-16 14:29:46 +0000
+++ src/wui/mapview.cc 2013-02-09 12:25:26 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team2 * Copyright (C) 2002-2004, 2006-2013 by the Widelands Development Team
3 *3 *
4 * This program is free software; you can redistribute it and/or4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License5 * modify it under the terms of the GNU General Public License
@@ -19,7 +19,6 @@
1919
20#include "mapview.h"20#include "mapview.h"
2121
22
23#include "interactive_base.h"22#include "interactive_base.h"
24#include "interactive_player.h"23#include "interactive_player.h"
25#include "mapviewpixelfunctions.h"24#include "mapviewpixelfunctions.h"
@@ -30,9 +29,8 @@
3029
31#include "graphic/graphic.h"30#include "graphic/graphic.h"
32#include "graphic/rendertarget.h"31#include "graphic/rendertarget.h"
33#include "graphic/render/gameview.h"32#include "graphic/render/gamerenderer_gl.h"
34#include "graphic/render/gameview_opengl.h"33#include "graphic/render/gamerenderer_sdl.h"
35#include "graphic/render/gameview_sdl.h"
3634
37#include "upcast.h"35#include "upcast.h"
3836
@@ -48,6 +46,11 @@
48m_complete_redraw_needed(true)46m_complete_redraw_needed(true)
49{}47{}
5048
49Map_View::~Map_View()
50{
51 // explicit destructor so that smart pointer destructors
52 // with forward-declared types are properly instantiated
53}
5154
52/// Moves the mouse cursor so that it is directly above the given node55/// Moves the mouse cursor so that it is directly above the given node
53void Map_View::warp_mouse_to_node(Widelands::Coords const c) {56void Map_View::warp_mouse_to_node(Widelands::Coords const c) {
@@ -95,21 +98,21 @@
9598
96 egbase.map().overlay_manager().load_graphics();99 egbase.map().overlay_manager().load_graphics();
97100
98 GameView * gameview;101 if (!m_renderer) {
99#ifdef USE_OPENGL102#ifdef USE_OPENGL
100 if (g_opengl) {103 if (g_opengl) {
101 gameview = new GameViewOpenGL(dst);104 m_renderer.reset(new GameRendererGL());
102 } else105 } else
103#endif106#endif
104 {107 {
105 gameview = new GameViewSDL(dst);108 m_renderer.reset(new GameRendererSDL());
109 }
106 }110 }
107 if (upcast(Interactive_Player const, interactive_player, &intbase())) {111 if (upcast(Interactive_Player const, interactive_player, &intbase())) {
108 gameview->rendermap(egbase, interactive_player->player(), m_viewpoint);112 m_renderer->rendermap(dst, egbase, interactive_player->player(), m_viewpoint);
109 } else {113 } else {
110 gameview->rendermap(egbase, m_viewpoint);114 m_renderer->rendermap(dst, egbase, m_viewpoint);
111 }115 }
112 delete gameview;
113116
114 m_complete_redraw_needed = false;117 m_complete_redraw_needed = false;
115 draw_tooltip(dst, tooltip());118 draw_tooltip(dst, tooltip());
116119
=== modified file 'src/wui/mapview.h'
--- src/wui/mapview.h 2012-02-15 21:25:34 +0000
+++ src/wui/mapview.h 2013-02-09 12:25:26 +0000
@@ -27,6 +27,7 @@
2727
28#include "ui_basic/panel.h"28#include "ui_basic/panel.h"
2929
30struct GameRenderer;
30struct Interactive_Base;31struct Interactive_Base;
3132
32/**33/**