]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/render_area_2d.cxx
Hans FUGAL: mac compilation fix
[flightgear.git] / src / Instrumentation / render_area_2d.cxx
1 // RenderArea2D.cxx - a class to manage 2D polygon-based drawing
2 //                    for a complex instrument (eg. GPS).
3 //
4 // Written by David Luff, started 2005.
5 //
6 // Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 // $Id$
23
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #ifdef HAVE_WINDOWS_H
30 #   include <windows.h>
31 #endif
32
33 #include "render_area_2d.hxx"
34
35 #include SG_GL_H
36
37
38 static const float dummy_normals[][3] = {{0.0f, 0.0f, 0.0f},
39                                          {0.0f, 0.0f, 0.0f},
40                                          {0.0f, 0.0f, 0.0f},
41                                          {0.0f, 0.0f, 0.0f}};
42
43 RA2DPrimitive::RA2DPrimitive() {
44         invert = false;
45         debug = false;
46 }
47                                                                                  
48 RenderArea2D::RenderArea2D(int logx, int logy, int sizex, int sizey, int posx, int posy) {
49         _logx = logx;
50         _logy = logy;
51         _sizex = sizex;
52         _sizey = sizey;
53         _posx = posx;
54         _posy = posy;
55         _clipx1 = 0;
56         _clipx2 = _logx - 1;
57         _clipy1 = 0;
58         _clipy2 = _logy - 1;
59         
60         _backgroundColor[0] = 0.0;
61         _backgroundColor[1] = 0.0;
62         _backgroundColor[2] = 0.0;
63         _backgroundColor[3] = 1.0;
64         _pixelColor[0] = 1.0;
65         _pixelColor[1] = 0.0;
66         _pixelColor[2] = 0.0;
67         _pixelColor[3] = 1.0;
68         
69         _ra2d_debug = false;
70 }
71
72 void RenderArea2D::draw() {
73 #if 0
74     glDisable(GL_TEXTURE_2D);
75         /*
76     glColor3f(1, 1, 0);
77         
78         float x1 = _posx;
79         float x2 = _posx + _sizex;
80         float y1 = _posy;
81         float y2 = _posy + _sizey;
82         
83         glBegin(GL_LINE_LOOP);
84     glVertex2f(x1, y1);
85     glVertex2f(x1, y2);
86     glVertex2f(x2, y2);
87     glVertex2f(x2, y1);
88     glEnd();
89         */
90         oldDrawBackground();
91         
92         for(unsigned int i = 0; i < drawing_list.size(); ++i) {
93                 RA2DPrimitive prim = drawing_list[i];
94                 switch(prim.type) {
95                 case RA2D_LINE:
96                         oldDrawLine(prim.x1, prim.y1, prim.x2, prim.y2);
97                         break;
98                 case RA2D_QUAD:
99                         if(prim.debug) {
100                                 //cout << "Clipping = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n';
101                                 //cout << "Drawing quad " << prim.x1 << ", " << prim.y1 << " to " << prim.x2 << ", " << prim.y2 << '\n';
102                         }
103                         oldDrawQuad(prim.x1, prim.y1, prim.x2, prim.y2, prim.invert);
104                         break;
105                 case RA2D_PIXEL:
106                         oldDrawPixel(prim.x1, prim.y1, prim.invert);
107                         break;
108                 }
109         }
110         
111         glEnable(GL_TEXTURE_2D);
112 #endif
113 }
114
115 // Set clipping region in logical units
116 void RenderArea2D::SetClipRegion(int x1, int y1, int x2, int y2) {
117         _clipx1 = x1;
118         _clipx2 = x2;
119         _clipy1 = y1;
120         _clipy2 = y2;
121         //cout << "Set clip region, clip region = "  << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n';
122 }
123
124 // Set clip region to be the same as the rendered area (default)
125 void RenderArea2D::ResetClipRegion() {
126         _clipx1 = 0;
127         _clipx2 = _logx - 1;
128         _clipy1 = 0;
129         _clipy2 = _logy - 1;
130         //cout << "Reset clip region, clip region = "  << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n';
131 }
132
133 void RenderArea2D::SetPosition(int posx, int posy) {
134         _posx = posx;
135         _posy = posy;
136 }
137
138 void RenderArea2D::SetLogicalSize(int logx, int logy) {
139         _logx = logx;
140         _logy = logy;
141 }
142
143 void RenderArea2D::SetActualSize(int sizex, int sizey) {
144         _sizex = sizex;
145         _sizey = sizey;
146 }
147
148 void RenderArea2D::DrawPixel(int x, int y, bool invert) {
149         // Clipping is currently performed in oldDrawPixel - could clip here instead though.
150
151         RA2DPrimitive prim;
152         prim.x1 = x;
153         prim.y1 = y;
154         prim.x2 = 0;
155         prim.y2 = 0;
156         prim.type = RA2D_PIXEL;
157         prim.invert = invert;
158         drawing_list.push_back(prim);
159 }
160
161 void RenderArea2D::oldDrawPixel(int x, int y, bool invert) {
162         // Clip
163         if(x < _clipx1 || x > _clipx2 || y < _clipy1 || y > _clipy2) return;
164         
165         // Scale to position within background
166         float fx1 = (float)x, fy1 = (float)y;
167         float rx = (float)_sizex / (float)_logx;
168         float ry = (float)_sizey / (float)_logy;
169         fx1 *= rx;
170         fy1 *= ry;
171         float fx2 = fx1 + rx;
172         float fy2 = fy1 + ry;
173         
174         // Translate to final position
175         fx1 += (float)_posx;
176         fx2 += (float)_posx;
177         fy1 += (float)_posy;
178         fy2 += (float)_posy;
179         
180         //cout << "DP: " << fx1 << ", " << fy1 << " ... " << fx2 << ", " << fy2 << '\n';
181         
182         doSetColor(invert ? _backgroundColor : _pixelColor);
183         sgVec2 corners[4];
184         sgSetVec2(corners[0], fx1, fy1);
185         sgSetVec2(corners[1], fx2, fy1);
186         sgSetVec2(corners[2], fx2, fy2);
187         sgSetVec2(corners[3], fx1, fy2);
188         //cout << "Drawing pixel, x,y is " << x << ", " << y << ", fx is [x1,x2,y1,y2] " << fx1 << ", " << fx2 << ", " << fy1 << ", " << fy2 << '\n';
189         doDrawQuad(&corners[0], dummy_normals);
190 }
191
192 void RenderArea2D::DrawLine(int x1, int y1, int x2, int y2) {
193         RA2DPrimitive prim;
194         prim.x1 = x1;
195         prim.y1 = y1;
196         prim.x2 = x2;
197         prim.y2 = y2;
198         prim.type = RA2D_LINE;
199         prim.invert = false;
200         drawing_list.push_back(prim);
201 }
202
203 void RenderArea2D::oldDrawLine(int x1, int y1, int x2, int y2) {
204         // Crude implementation of Bresenham line drawing algorithm.
205         
206         // Our lines are non directional, so first order the points x-direction-wise to leave only 4 octants to consider.
207         if(x2 < x1) {
208                 int tmp_x = x1;
209                 int tmp_y = y1;
210                 x1 = x2;
211                 y1 = y2;
212                 x2 = tmp_x;
213                 y2 = tmp_y;
214         }
215         
216         bool flip_y = (y1 > y2 ? true : false);
217         int dx = x2 - x1;
218         int dy = (flip_y ? y1 - y2 : y2 - y1); 
219         if(dx > dy) {
220                 // push the x dir
221                 int y = y1;
222                 int yn = dx/2;
223                 for(int x=x1; x<=x2; ++x) {
224                         DrawPixel(x, y);
225                         yn += dy;
226                         if(yn >= dx) {
227                                 yn -= dx;
228                                 y = (flip_y ? y - 1 : y + 1);
229                         }
230                 }
231         } else {
232                 // push the y dir
233                 int x = x1;
234                 int xn = dy/2;
235                 // Must be a more elegant way to roll the next two cases into one!
236                 if(flip_y) {
237                         for(int y=y1; y>=y2; --y) {
238                                 DrawPixel(x, y);
239                                 xn += dx;
240                                 if(xn >= dy) {
241                                         xn -= dy;
242                                         x++;
243                                 }
244                         }
245                 } else {
246                         for(int y=y1; y<=y2; ++y) {
247                                 DrawPixel(x, y);
248                                 xn += dx;
249                                 if(xn >= dy) {
250                                         xn -= dy;
251                                         x++;
252                                 }
253                         }
254                 }
255         }
256 }
257
258 void RenderArea2D::DrawQuad(int x1, int y1, int x2, int y2, bool invert) {
259         // Clip and sanity-check.
260         if(x1 > x2) {
261                 int x = x2;
262                 x2 = x1;
263                 x1 = x;
264         }
265         if(y1 > y2) {
266                 int y = y2;
267                 y2 = y1;
268                 y1 = y;
269         }
270         x1 = x1 < _clipx1 ? _clipx1 : x1;
271         if(x1 > _clipx2) { return; }
272         x2 = x2 > _clipx2 ? _clipx2 : x2;
273         if(x2 < _clipx1) { return; }
274         y1 = y1 < _clipy1 ? _clipy1 : y1;
275         if(y1 > _clipy2) { return; }
276         y2 = y2 > _clipy2 ? _clipy2 : y2;
277         if(y2 < _clipy1) { return; }
278         
279         RA2DPrimitive prim;
280         prim.x1 = x1;
281         prim.y1 = y1;
282         prim.x2 = x2;
283         prim.y2 = y2;
284         prim.type = RA2D_QUAD;
285         prim.invert = invert;
286         if(_ra2d_debug) prim.debug = true;
287         drawing_list.push_back(prim);
288 }
289
290 void RenderArea2D::oldDrawQuad(int x1, int y1, int x2, int y2, bool invert) {
291         // Scale to position within background
292         float fx1 = (float)x1, fy1 = (float)y1;
293         float fx2 = (float)x2, fy2 = (float)y2;
294         float rx = (float)_sizex / (float)_logx;
295         float ry = (float)_sizey / (float)_logy;
296         fx1 *= rx;
297         fy1 *= ry;
298         fx2 *= rx;
299         fy2 *= ry;
300         
301         fx2 += rx;
302         fy2 += ry;
303         
304         // Translate to final position
305         fx1 += (float)_posx;
306         fx2 += (float)_posx;
307         fy1 += (float)_posy;
308         fy2 += (float)_posy;
309         
310         //cout << "DP: " << fx1 << ", " << fy1 << " ... " << fx2 << ", " << fy2 << '\n';
311         
312         doSetColor(invert ? _backgroundColor : _pixelColor);
313         sgVec2 corners[4];
314         sgSetVec2(corners[0], fx1, fy1);
315         sgSetVec2(corners[1], fx2, fy1);
316         sgSetVec2(corners[2], fx2, fy2);
317         sgSetVec2(corners[3], fx1, fy2);
318         doDrawQuad(&corners[0], dummy_normals);
319 }
320
321 void RenderArea2D::DrawBackground() {
322         // TODO
323 }
324
325 void RenderArea2D::oldDrawBackground() {
326         doSetColor(_backgroundColor);
327         sgVec2 corners[4];
328         sgSetVec2(corners[0], (float)_posx, (float)_posy);
329         sgSetVec2(corners[1], (float)(_posx + _sizex), (float)_posy);
330         sgSetVec2(corners[2], (float)(_posx + _sizex), (float)(_posy + _sizey));
331         sgSetVec2(corners[3], (float)_posx, (float)(_posy + _sizey));
332         doDrawQuad(&corners[0], dummy_normals);
333 }
334
335 void RenderArea2D::Flush() {
336         drawing_list.clear();
337 }
338
339 // -----------------------------------------
340 //
341 // Actual drawing routines copied from Atlas
342 //
343 // -----------------------------------------
344
345 void RenderArea2D::doSetColor( const float *rgba ) {
346   //OSGFIXME
347 #if 0
348   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba);
349   glColor4fv( rgba );
350 #endif
351 }
352
353 void RenderArea2D::doDrawQuad( const sgVec2 *p, const sgVec3 *normals ) {
354         //cout << "doDrawQuad: " << *p[0] << ", " << *(p[0]+1) << ", " << *p[1] << ", " << *(p[1]+1) << ", " << *p[2] << ", " << *p([2]+1) << ", " << *p[3] << ", " << *p([3]+1) <<'\n';
355   //OSGFIXME
356 #if 0
357   glBegin(GL_QUADS);
358   glNormal3fv( normals[0] ); glVertex2fv( p[0] );
359   glNormal3fv( normals[1] ); glVertex2fv( p[1] );
360   glNormal3fv( normals[2] ); glVertex2fv( p[2] );
361   glNormal3fv( normals[3] ); glVertex2fv( p[3] );
362   glEnd();
363 #endif
364 }
365
366 void RenderArea2D::doDrawQuad( const sgVec2 *p, const sgVec3 *normals, const sgVec4 *color ) {
367   //OSGFIXME
368 #if 0
369   glBegin(GL_QUADS);
370     glColor4fv( color[0] );glNormal3fv( normals[0] ); glVertex2fv( p[0] );
371     glColor4fv( color[1] );glNormal3fv( normals[1] ); glVertex2fv( p[1] );
372     glColor4fv( color[2] );glNormal3fv( normals[2] ); glVertex2fv( p[2] );
373     glColor4fv( color[3] );glNormal3fv( normals[3] ); glVertex2fv( p[3] );
374   glEnd();
375 #endif
376 }