root/trunk/luigi/gldraw.d

Revision 41, 13.9 kB (checked in by baxissimo, 2 years ago)

Took out Derelict libs from sdl build file. Discovered why it was that I had needed them in the first place.

Added more error checking to glddraw.d

Line 
1 //---------------------------------------------------------------------
2 /*
3  Copyright:
4
5   luigi/gldraw.d -- OpenGL drawing utilities 'luigi' user interface library.
6
7   Copyright (C) 2006 William V. Baxter III
8
9   This software is provided 'as-is', without any express or implied
10   warranty.  In no event will the authors be held liable for any
11   damages arising from the use of this software.
12
13   Permission is granted to anyone to use this software for any
14   purpose, including commercial applications, and to alter it and
15   redistribute it freely, subject to the following restrictions:
16
17   1. The origin of this software must not be misrepresented; you must
18      not claim that you wrote the original software. If you use this
19      software in a product, an acknowledgment in the product
20      documentation would be appreciated but is not required.
21
22   2. Altered source versions must be plainly marked as such, and must
23      not be misrepresented as being the original software.
24   3. This notice may not be removed or altered from any source distribution.
25
26   William Baxter wbaxter@gmail.com
27 */
28 module luigi.gldraw;
29
30 import luigi.gui;
31 import luigi.opengl;
32 import luigi.base;
33 import std.math : PI,sin,cos;
34
35 class GLException : Exception
36 {
37     this(char[] msg) { super(msg); }
38 }
39
40
41 void translate(float x, float y)
42 {
43     glTranslatef(x,y,0);
44 }
45 void translate(Point p)
46 {
47     glTranslatef(p.x,p.y,0);
48 }
49 void untranslate(float x, float y)
50 {
51     glTranslatef(-x,-y,0);
52 }
53 void untranslate(Point p)
54 {
55     glTranslatef(-p.x,-p.y,0);
56 }
57
58 void push_clip_rect(Rect r)
59 {
60     // Rect is in user coords & needs to be projected to window coords for glscissor
61     glPushAttrib(GL_SCISSOR_BIT);
62     glEnable(GL_SCISSOR_TEST);
63     float[16] M; glGetFloatv(GL_MODELVIEW_MATRIX, &M[0]);
64     float[16] P;  glGetFloatv(GL_PROJECTION_MATRIX, &P[0]);
65     int[4] V;  glGetIntegerv(GL_VIEWPORT, &V[0]);
66
67     // This is basically gluProject, but we only care about the 2D
68     // part so we can shortcut the math a bit.
69
70     // Transform point r.pos  [r.pos.x, r.pos.y, 0, 1]
71     void xform(inout Point p)
72     {
73         float x = M[0] * p.x  + M[4] * p.y + M[12];
74         float y = M[1] * p.x  + M[5] * p.y + M[13];
75         float z = M[2] * p.x  + M[6] * p.y + M[14];
76         float w = M[3] * p.x  + M[7] * p.y + M[15];
77         p.x = P[0] * x + P[4] * y + P[8] * z + P[12] * w;
78         p.y = P[1] * x + P[5] * y + P[9] * z + P[13] * w;
79         w   = P[3] * x + P[7] * y + P[11]* z + P[15] * w;
80         p.x /= w;
81         p.y /= w;
82     }
83
84     Point p1 = r.pos;
85     Point p2 = r.pos; p2 += r.size;
86     xform(p1);
87     xform(p2);
88
89     int ix,iy,ix2,iy2;
90     ix  = V[0] + cast(int)((1 + p1.x) * V[2] / 2);
91     iy  = V[1] + cast(int)((1 + p1.y) * V[3] / 2);
92     ix2 = V[0] + cast(int)((1 + p2.x) * V[2] / 2);
93     iy2 = V[1] + cast(int)((1 + p2.y) * V[3] / 2);
94     int ih = iy2-iy;
95    
96     if (ih>0) {
97         glScissor(ix, iy, ix2-ix, iy2-iy);
98     }
99     else {
100         glScissor(ix, iy2, ix2-ix, -ih);
101     }
102 }
103 void pop_clip_rect()
104 {
105     glPopAttrib();
106 }
107
108 void fill_rect(Rect r) {
109     glBegin(GL_QUADS);
110     glVertex2f(r.x1,r.y1);
111     glVertex2f(r.x2,r.y1);
112     glVertex2f(r.x2,r.y2);
113     glVertex2f(r.x1,r.y2);
114     glEnd();
115 }
116
117 void fill_rect(Rect r, float[4] tc) {
118     glBegin(GL_QUADS);
119     glTexCoord2f(tc[0],tc[1]); glVertex2f(r.x1,r.y1);
120     glTexCoord2f(tc[2],tc[1]); glVertex2f(r.x2,r.y1);
121     glTexCoord2f(tc[2],tc[3]); glVertex2f(r.x2,r.y2);
122     glTexCoord2f(tc[0],tc[3]); glVertex2f(r.x1,r.y2);
123     glEnd();
124 }
125
126 void fill_rect(Rect r, int[4] tc) {
127     glBegin(GL_QUADS);
128     glTexCoord2i(tc[0],tc[1]); glVertex2f(r.x1,r.y1);
129     glTexCoord2i(tc[2],tc[1]); glVertex2f(r.x2,r.y1);
130     glTexCoord2i(tc[2],tc[3]); glVertex2f(r.x2,r.y2);
131     glTexCoord2i(tc[0],tc[3]); glVertex2f(r.x1,r.y2);
132     glEnd();
133 }
134
135 void stroke_rect(Rect r) {
136     glBegin(GL_LINE_LOOP);
137     glVertex2f(r.x1,r.y1);
138     glVertex2f(r.x2,r.y1);
139     glVertex2f(r.x2,r.y2);
140     glVertex2f(r.x1,r.y2);
141     glEnd();
142 }
143
144 void fill_circle(float x, float y, float radius, int slices=16)
145 {
146     glTranslatef(x,y,0);
147     glBegin(GL_TRIANGLE_FAN);
148     glVertex2f(0,0);
149     float astep = 2*PI/slices;
150     for(int i=0; i<slices+1; i++)
151     {
152         float a = i*astep;
153         float c = radius*cos(a);
154         float s = radius*sin(a);
155         glVertex2f(c,s);
156     }
157     glEnd();
158     glTranslatef(-x,-y,0);
159 }
160
161
162 void stroke_circle(float x, float y, float radius=1, int slices=16)
163 {
164     glTranslatef(x,y,0);
165     glBegin(GL_LINE_LOOP);
166     float astep = 2*PI/slices;
167     for(int i=0; i<slices+1; i++)
168     {
169         float a = i*astep;
170         float c = radius*cos(a);
171         float s = radius*sin(a);
172         glVertex2f(c,s);
173     }
174     glEnd();
175     glTranslatef(-x,-y,0);
176 }
177
178 void fill_arc(float x, float y, float radius, float start, float radians, int slices=16)
179 {
180     glTranslatef(x,y,0);
181     glBegin(GL_TRIANGLE_FAN);
182     glVertex2f(0,0);
183     float astep = radians/slices;
184     for(int i=0; i<slices+1; i++)
185     {
186         float a = start+i*astep;
187         float c = radius*cos(a);
188         float s = -radius*sin(a);
189         glVertex2f(c,s);
190     }
191     glEnd();
192     glTranslatef(-x,-y,0);
193 }
194
195 void stroke_arc(float x, float y, float radius, float start, float radians, int slices=16)
196 {
197     glTranslatef(x,y,0);
198     glBegin(GL_LINE_LOOP);
199     glVertex2f(0,0);
200     float astep = radians/slices;
201     for(int i=0; i<slices+1; i++)
202     {
203         float a = start+i*astep;
204         float c = radius*cos(a);
205         float s = -radius*sin(a);
206         glVertex2f(c,s);
207     }
208     glEnd();
209     glTranslatef(-x,-y,0);
210 }
211
212
213 void fill_rounded_rect(Rect r, float radius, int slices=8)
214 {
215     Rect ir = r; ir.inset(radius);
216     if (2*radius >= r.width) { radius = r.width/2; }
217     if (2*radius >= r.height) { radius = r.height/2; }
218     glBegin(GL_QUADS);
219     glVertex2f(ir.x1, r.y1);
220     glVertex2f(ir.x2, r.y1);
221     glVertex2f(ir.x2, r.y2);
222     glVertex2f(ir.x1, r.y2);
223
224     glVertex2f(r.x1,  ir.y1);
225     glVertex2f(ir.x2, ir.y1);
226     glVertex2f(ir.x2, ir.y2);
227     glVertex2f(r.x1,  ir.y2);
228
229     glVertex2f(ir.x2, ir.y1);
230     glVertex2f(r.x2,  ir.y1);
231     glVertex2f(r.x2,  ir.y2);
232     glVertex2f(ir.x2, ir.y2);
233     glEnd();
234
235     fill_arc(ir.x1,ir.y1,radius, PI/2,PI/2,slices);
236     fill_arc(ir.x2,ir.y1,radius, 0,PI/2,slices);
237     fill_arc(ir.x1,ir.y2,radius, PI,PI/2,slices);
238     fill_arc(ir.x2,ir.y2,radius, -PI/2,PI/2,slices);
239 }
240
241 void stroke_rounded_rect(Rect r, float radius, int slices=8)
242 {
243     Rect ir = r; ir.inset(radius);
244     if (2*radius >= r.width) { radius = r.width/2; }
245     if (2*radius >= r.height) { radius = r.height/2; }
246
247     void _arc(float x, float y, float start, float radians, int slices=16)
248     {
249         glTranslatef(x,y,0);
250         float astep = radians/slices;
251         for(int i=0; i<slices+1; i++)
252         {
253             float a = start+i*astep;
254             float c = radius*cos(a);
255             float s = -radius*sin(a);
256             glVertex2f(c,s);
257         }
258         glTranslatef(-x,-y,0);
259     }
260
261     glBegin(GL_LINE_LOOP);
262     _arc(ir.x1,ir.y1, PI/2, PI/2);
263     _arc(ir.x2,ir.y1, 0,    PI/2);
264     _arc(ir.x1,ir.y2, PI,   PI/2);
265     _arc(ir.x2,ir.y2, -PI/2,PI/2);
266     glEnd();
267
268 }
269
270 void stroke_raised_rect( Rect r, Color bkg, Color dark, Color medium, Color light)
271 {
272     r.inset(0.5);
273
274     with (r) {
275         translate(0.5,0.5); scope(exit) untranslate(0.5,0.5);
276         glColor4ubv( bkg.ptr );
277         glBegin( GL_LINE_LOOP );
278         glVertex2f( x+1, y+1 );  glVertex2f( x2-1, y+1 );
279         glVertex2f( x2-1, y2-1 );  glVertex2f( x+1, y2-1 );
280         glEnd();
281
282         glColor4ubv( light.ptr );
283         glBegin( GL_LINE_STRIP );
284         glVertex2f( x, y2 );  glVertex2f( x, y );  glVertex2f( x2, y );
285         glEnd();
286
287         glColor4ubv( dark.ptr );
288         glBegin( GL_LINE_STRIP );
289         glVertex2f( x2, y );  glVertex2f( x2, y2 );  glVertex2f( x, y2 );
290         glEnd();
291
292         glColor4ubv( medium.ptr );
293         glBegin( GL_LINE_STRIP );
294         glVertex2f( x2-1, y+1 );  glVertex2f( x2-1, y2-1 );  glVertex2f( x+1, y2-1 );
295         glEnd();
296     }
297 }
298
299 void stroke_sunken_rect( Rect r, Color bkg, Color dark, Color medium, Color light)
300 {
301     r.inset(0.5);
302    
303     with(r) {
304         // inner loop
305         glBegin( GL_LINE_STRIP );
306         glColor4ubv( medium.ptr );
307         glVertex2f( x +1, y2-1 );
308         glVertex2f( x +1, y +1 );
309         glVertex2f( x2-1, y +1 );
310
311         glColor4ubv( bkg.ptr );
312         glVertex2f( x2-1, y +1 );
313         glVertex2f( x2-1, y2-1 );
314         glVertex2f( x +1, y2-1 );
315         glEnd();
316
317         // outer loop
318         glBegin( GL_LINE_STRIP );
319         glColor4ubv( dark.ptr );
320         glVertex2f( x , y2 );
321         glVertex2f( x , y  );
322         glVertex2f( x2, y  );
323
324         glColor4ubv( light.ptr );
325         glVertex2f( x2, y  );
326         glVertex2f( x2, y2 );
327         glVertex2f( x , y2 );
328         glEnd();
329     }
330 //    stroke_raised_rect(r, bkg, light, medium, dark);
331 /*
332     glColor3ubv(dark.ptr);
333     glBegin( GL_LINE_LOOP );
334     glVertex2f( r.x, r.y );         glVertex2f( r.x2, r.y );
335     glVertex2f( r.x2, r.y2 );       glVertex2f( r.x, r.y2 );
336     glEnd();
337
338     glBegin( GL_LINE_LOOP );
339     glVertex2f( r.x+1, r.y+1 );       glVertex2f( r.x2-1, r.y+1 );
340     glVertex2f( r.x2-1, r.y2-1 );     glVertex2f( r.x+1, r.y2-1 );
341     glEnd();
342 */
343
344 /*
345     float x = r.x;
346     float y = r.y;
347     float x2 = r.x2;
348     float y2 = r.y2;
349
350     glColor3ubv( bkgd_color );
351     glBegin( GL_LINE_LOOP );
352     glVertex2f( x+1, y+1 );         glVertex2f( x2-1, y+1 );
353     glVertex2f( x2-1, y2-1 );     glVertex2f( x+1, y2-1 );
354     glEnd();
355
356     glColor4ubv( dark );
357     glBegin( GL_LINE_STRIP );
358     glVertex2f( x, y2 );  glVertex2f( x, y );  glVertex2f( x2, y );
359     glEnd();
360
361     glColor4ubv( light );
362     glBegin( GL_LINE_STRIP );
363     glVertex2f( x2, y );  glVertex2f( x2, y2 );  glVertex2f( x, y2 );
364     glEnd();
365
366     glColor4ubv( medium );
367     glBegin( GL_LINE_STRIP );
368     glVertex2f( x2-1, y+1 );  glVertex2f( x2-1, y2-1 );  glVertex2f( x+1, y2-1 );
369     glEnd();
370 */
371 }
372
373 char[] getGLErrors(char[] file = null, int line = -1)
374 {
375     GLenum err;
376     char[] errstr = null;
377     int count = 0;
378     while ( (err=glGetError()) != GL_NO_ERROR)
379     {
380         if (!errstr) errstr = "OpenGL error: ";
381         else errstr ~= std.string.format("\nOpenGL error(%d) : ", ++count);
382         if (file) errstr ~= std.string.format("%s(%s): ", file, line);
383         else if (line >= 0) errstr ~= std.string.format("(%s): ", line);
384         switch(err) {
385         case GL_INVALID_ENUM:
386             // An unacceptable value is specified for an enumerated
387             // argument. The offending command is ignored, having no
388             // side effect other than to set the error flag.
389             errstr ~= "Invalid enum";
390             break;
391         case GL_INVALID_VALUE:
392             //A numeric argument is out of range. The offending command is
393             //ignored, having no side effect other than to set the error
394             //flag.
395             errstr ~= "Invalid value";
396             break;
397         case GL_INVALID_OPERATION:
398             //The specified operation is not allowed in the current
399             //state. The offending command is ignored, having no side
400             //effect other than to set the error flag.
401             errstr ~= "Invalid operation";
402             break;
403
404         case GL_STACK_OVERFLOW:
405             // This command would cause a stack overflow. The
406             // offending command is ignored, having no side effect
407             // other than to set the error flag.
408             errstr ~= "Stack overflow";
409             break;
410
411         case GL_STACK_UNDERFLOW:
412             //  This command would cause a stack underflow. The
413             //  offending command is ignored, having no side effect
414             //  other than to set the error flag.
415             errstr ~= "Stack underflow";
416             break;
417
418         case GL_OUT_OF_MEMORY:
419             //  There is not enough memory left to execute the
420             //  command. The state of the GL is undefined, except for
421             //  the state of the error flags, after this error is
422             //  recorded.
423             errstr ~= "Out of memory";
424             break;
425         default:
426             errstr ~= std.string.format("Unknown error code: %s", err);
427         }
428     }
429     return errstr;
430 }
431
432 void checkGLErrors(char[] file = null, int line = -1)
433 {
434     char[] ret = getGLErrors(file,line);
435     if (ret) {
436         writefln(ret);
437     }
438 }
439 void throwGLErrors(char[] file = null, int line = -1)
440 {
441     char[] ret = getGLErrors(file,line);
442     if (ret) {
443         throw new GLException(ret);
444     }
445 }
446
447
448 //----------------------------------------------------------------------------
449 void push_graphics_state(Rect viewport) {
450     glPushAttrib(GL_ENABLE_BIT // depth test, blending, texturing etc
451                  | GL_POLYGON_BIT // poly mode, cull face etc
452                  //| GL_CURRENT_BIT  // color, rasterpos etc
453                  //| GL_DEPTH_BUFFER_BIT  // GL_DEPTH_TEST
454                  //| GL_COLOR_BUFFER_BIT // GL_BLEND
455                  );
456     glDisable(GL_DEPTH_TEST);
457     glDisable(GL_LIGHTING);
458     glDisable(GL_CULL_FACE);
459     glDisable(GL_TEXTURE_2D);
460     glEnable(GL_BLEND);
461     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
462
463     glViewport(0,0,lrint(viewport.w),lrint(viewport.h));
464     glMatrixMode(GL_PROJECTION);
465     glPushMatrix();
466     glLoadIdentity();
467     // Note! We put the origin at top left to match window sys conventions
468     glOrtho(viewport.x, viewport.x2,
469             viewport.y2, viewport.y1,
470             -1,1);
471     glMatrixMode(GL_MODELVIEW);
472     glPushMatrix();
473     glLoadIdentity();
474 }
475
476 void pop_graphics_state() {
477     glPopAttrib();
478     glMatrixMode(GL_PROJECTION);
479     glPopMatrix();
480     glMatrixMode(GL_MODELVIEW);
481     glPopMatrix();
482     // TODO restore viewport?
483     version(Debug) {
484         checkGLErrors(__FILE__,__LINE__);
485     }
486 }
Note: See TracBrowser for help on using the browser.