Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

draw.cpp

By: a guest on Jul 5th, 2012  |  syntax: C++  |  size: 13.51 KB  |  views: 17  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1.  
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <cstring>
  5. using namespace std;
  6.  
  7. #include "Draw.h"
  8.  
  9. ///////////////
  10. //OGL Texture//
  11. ///////////////
  12. OGL_Texture::OGL_Texture(){
  13.         w=h=0;
  14.         texture_generated = false;
  15.         Texture_ID = 0;
  16. }
  17. OGL_Texture::~OGL_Texture(){
  18.         if (Texture_ID){glDeleteTextures(1,&Texture_ID);}//0 is not a valid texture id
  19. }
  20.  
  21. void OGL_Texture::gen_texture(uint16_t width, uint16_t height, uint8_t *PixData){
  22.         if (width==0 || height==0){printf("ERROR! WIDTH OR HEIGHT OF TEXTURE == 0"); exit(1);}
  23.         //delete old texture if existing
  24.         if (texture_generated && Texture_ID){
  25.                 glDeleteTextures(1,&Texture_ID);
  26.         }
  27.         w = width;
  28.         h = height;
  29.         //generate texture
  30.         glGenTextures(1,&Texture_ID);
  31.         if (Texture_ID==0){printf("ERROR IN TEXTURE GENERATION! NO DEVICE CONTEXT?"); exit(1);}
  32.         glEnable(GL_TEXTURE_RECTANGLE_NV);
  33.                 glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture_ID);
  34.                 //2d texture, level of detail, number of components (3=rgb), w,h, border, byte order, data format, data
  35.                 glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, PixData);
  36.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  37.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  38.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  39.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  40.                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  41.                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
  42.         glDisable(GL_TEXTURE_RECTANGLE_NV);
  43.         texture_generated = true;
  44. }
  45.  
  46. ///////////////
  47. //OGL Surface//
  48. ///////////////
  49.  
  50. OGL_Surface::OGL_Surface(){
  51.         texture_generated = false;
  52.         bpp=4;
  53.         w=h=0;
  54.         PixData = nullptr;
  55. }
  56. OGL_Surface::~OGL_Surface(){
  57.         if (PixData != nullptr) {delete [] PixData;}
  58. }
  59.  
  60. void OGL_Surface::Create_Surface(uint16_t set_w,uint16_t set_h, char set_bpp){
  61.         if (set_bpp==24){bpp=3;}
  62.         if (set_bpp==32){bpp=4;}
  63.         // if surface already exists and width or height change delete old texture
  64.         if (texture_generated && (w != set_w || h != set_h)){
  65.                 glDeleteTextures(1,&Texture_ID);
  66.                 texture_generated = false;
  67.         }
  68.         // if surface already exists delete old data
  69.         if (PixData != nullptr) {delete [] PixData;}
  70.         w = set_w;
  71.         h = set_h;
  72.         bpp = set_bpp;
  73.         PixData = new uint8_t[w*h*bpp];
  74.         memset(PixData,255, w*h*bpp);
  75. }
  76. void OGL_Surface::Clear_Surface(uint8_t r, uint8_t g, uint8_t b, uint8_t a){
  77.         if (r == g && g == b && bpp==3){
  78.                 memset(PixData, r, w*h*bpp);
  79.         }
  80.         else if (r == g && g == b && b == a && bpp==4){
  81.                 memset(PixData, r, w*h*bpp);
  82.         }
  83.         else{
  84.                 unsigned int pos = 0;
  85.                 while (pos<w*h*bpp){
  86.                         PixData[pos++] = r;
  87.                         PixData[pos++] = g;
  88.                         PixData[pos++] = b;
  89.                         if(bpp==4){PixData[pos++] = a;}
  90.                 }
  91.         }
  92. }
  93. void OGL_Surface::Set_Surface_AlphaKey(uint8_t r, uint8_t g, uint8_t b)
  94. {
  95.         if(bpp!=4){printf("trying to set alphakey on bpp that does not support alpha\n");return;}
  96.         int pos = 0;
  97.         for (unsigned int y = 0; y<h; y++){
  98.                 for (unsigned int x = 0; x<w; x++){
  99.                         if ((PixData[pos]==r) && (PixData[pos+1]==b) && (PixData[pos+2] == b)){
  100.                                 PixData[pos+3]= 0;//if colour = alphakey set alpha channel to 0
  101.                         }
  102.                         pos+=4;
  103.                 }
  104.         }
  105. }
  106. void OGL_Surface::gen_texture(){
  107.         if (w==0 || h==0){printf("ERROR! WIDTH OR HEIGHT OF SURFACE == 0"); exit(1);}
  108.         //Power of two texture support
  109.         uint32_t width = w;
  110.         uint32_t height= h;
  111.         //only generate a texture once
  112.         if (!texture_generated){
  113.                 glGenTextures(1,&Texture_ID);
  114.                 if (Texture_ID==0){printf("ERROR IN TEXTURE GENERATION! NO DEVICE CONTEXT?"); exit(1);}
  115.         }
  116.         glEnable(GL_TEXTURE_RECTANGLE_NV);
  117.                 glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture_ID);
  118.                 //glTexImage2D respecifies the entire texture, changing its size, deleting the previous data etc.
  119.                 //only do this if texture doesn't exist or if w/h change
  120.                 if (!texture_generated){
  121.                         switch (bpp){
  122.                         //2d texture, level of detail, number of components (3=rgb), w,h, border, byte order, data format, data
  123.                                 case 3: glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, PixData); break;
  124.                                 case 4: glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGRA,GL_UNSIGNED_BYTE, PixData); break;
  125.                         }
  126.                 }
  127.                 //glTexSubImage2D only modifies pixel data within the texture.
  128.                 //do this when pixels need to be updated
  129.                 else{
  130.                         switch (bpp){
  131.                                 //2d texture, level of detail, xoffset,yoffset, w,h,  byte order, data format, data
  132.                                 case 3: glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, PixData); break;
  133.                                 case 4: glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, GL_BGRA,GL_UNSIGNED_BYTE, PixData); break;
  134.                         }
  135.                 }
  136.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  137.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  138.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  139.                 glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  140.                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  141.                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
  142.         glDisable(GL_TEXTURE_RECTANGLE_NV);
  143.         texture_generated = true;
  144. }
  145.  
  146. OGL_Texture *Texture_Cast(OGL_Surface *Surface)
  147. {
  148.         OGL_Texture *Texture = static_cast<OGL_Texture*>(Surface);
  149.         Texture->w = Surface->w;
  150.         Texture->h = Surface->h;
  151.         return Texture;
  152. }
  153.  
  154. ////////
  155. //BLIT//
  156. ////////
  157. //glBlendFunc(source_blend, dst_blend)
  158. //GL_ZERO                                               colour is ignored
  159. //GL_ONE                                                full colour is taken into addition
  160. //GL_(DST/SRC)_COLOR                    colour is multiplied by (DST/SRC) color
  161. //GL_ONE_MINUS_(DST/SRC)_COLOR  colour is multiplied by inverted (DST/SRC) color
  162. //GL_(DST/SRC)_ALPHA                    colour is multiplied by (DST/SRC) alpha value
  163. //GL_ONE_MINUS_(DST/SRC)_ALPHA  colour is multiplied by inverted (DST/SRC) alpha value
  164. //overall colour (GL_SRC_ALPHA, GL_ONE) -addative- = (r1*a1,g1*a1,b1*a1)+(r2,g2,b2)
  165. void DrawImage(OGL_Texture *Texture, int dx, int dy, float rot,float scale_x,float scale_y,float alpha,int options){
  166.         if (options & IMG_HFLIP){dx+=Texture->w; scale_x=-1;}
  167.         if (options & IMG_VFLIP){dy+=Texture->h; scale_y=-1;}
  168.         glLoadIdentity();
  169.         glTranslatef(dx, dy, 0.0);
  170.         if (scale_x!=1 && scale_y!=1){glScaled(scale_x, scale_y, 0);}
  171.         if (rot!=0){
  172.                 int tmpw = Texture->w/2;
  173.                 int tmph = Texture->h/2;
  174.                 glTranslatef(tmpw, tmph, 0.0);
  175.                 glRotatef(rot, 0, 0, 1.0);
  176.                 glTranslatef(-tmpw, -tmph, 0.0);
  177.         }
  178.         glEnable(GL_TEXTURE_RECTANGLE_NV);
  179.                 glEnable(GL_BLEND);
  180.                         //additive blending - gray + gray = white
  181.                         if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);}
  182.                         //regular alpha blending - gray + gray = gray
  183.                         else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}
  184.                         //blit
  185.                         glColor4f(1.0f, 1.0f, 1.0f, alpha);
  186.                         glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture->Texture_ID);
  187.                         glBegin(GL_QUADS);
  188.                                 glTexCoord2i(0,0);
  189.                                 glVertex2i(0, 0);
  190.                                 glTexCoord2i(Texture->w,0);
  191.                                 glVertex2i(Texture->w, 0);
  192.                                 glTexCoord2i(Texture->w,Texture->h);
  193.                                 glVertex2i(Texture->w, Texture->h);
  194.                                 glTexCoord2i(0,Texture->h);
  195.                                 glVertex2i(0, Texture->h);
  196.                         glEnd();
  197.                 glDisable(GL_BLEND);
  198.         glDisable(GL_TEXTURE_RECTANGLE_NV);
  199.         glLoadIdentity();
  200. }
  201. void DrawSubImage(OGL_Texture *Texture, int sx, int sy, int sw, int sh, int dx, int dy, float rot,float scale_x,float scale_y,float alpha,int options){
  202.         if (options & IMG_HFLIP){dx+=Texture->w; scale_x=-1;}
  203.         if (options & IMG_VFLIP){dy+=Texture->h; scale_y=-1;}
  204.         glLoadIdentity();
  205.         glTranslatef(dx, dy, 0.0);
  206.         if (scale_x!=1 && scale_y!=1){glScaled(scale_x, scale_y, 0);}
  207.         if (rot!=0){
  208.                 int tmpw = Texture->w/2;
  209.                 int tmph = Texture->h/2;
  210.                 glTranslatef(tmpw, tmph, 0.0);
  211.                 glRotatef(rot, 0, 0, 1.0);
  212.                 glTranslatef(-tmpw, -tmph, 0.0);
  213.         }
  214.         glEnable(GL_TEXTURE_RECTANGLE_NV);
  215.                 glEnable(GL_BLEND);
  216.                         //additive blending - gray + gray = white
  217.                         if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);}
  218.                         //regular alpha blending - gray + gray = gray
  219.                         else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);}
  220.                         //blit
  221.                         glColor4f(1.0,1.0,1.0,alpha);
  222.                         glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture->Texture_ID);
  223.                         glBegin(GL_QUADS);
  224.                                 glTexCoord2i(sx,sy);
  225.                                 glVertex2i(0, 0);
  226.                                 glTexCoord2i(sx+sw,sy);
  227.                                 glVertex2i(sw, 0);
  228.                                 glTexCoord2i(sx+sw,sy+sh);
  229.                                 glVertex2i(sw, sh);
  230.                                 glTexCoord2i(sx,sy+sh);
  231.                                 glVertex2i(0, sh);
  232.                         glEnd();
  233.                 glDisable(GL_BLEND);
  234.         glDisable(GL_TEXTURE_RECTANGLE_NV);
  235.         glLoadIdentity();
  236. }
  237.  
  238. //////////
  239. //COLOUR//
  240. //////////
  241. uint32_t make_col(uint8_t r, uint8_t g, uint8_t b, uint8_t a){
  242.         uint32_t col = 0;
  243.         col |= r;
  244.         col |= uint32_t(g)<<8;
  245.         col |= uint32_t(b)<<16;
  246.         col |= uint32_t(a)<<24;
  247.         //printf("%#X, %d,%d,%d\n", col,r,g,b);
  248.         return col;
  249. }
  250.  
  251. uint32_t make_col(uint8_t r, uint8_t g, uint8_t b){
  252.         return make_col(r,g,b,255);
  253. }
  254.  
  255. ///////////////////
  256. //DRAW PRIMITIVES//
  257. ///////////////////
  258. //pos
  259. void putpixel(OGL_Surface *Surface, int pos, uint32_t col)
  260. {
  261.         Surface->PixData[pos+2] = (col&0x000000FF);//r
  262.         Surface->PixData[pos+1] = (col&0x0000FF00)>>8;//g
  263.         Surface->PixData[pos]   = (col&0x00FF0000)>>16;//b
  264.         if (Surface->bpp != 4){return;}
  265.         Surface->PixData[pos+3] = (col&0xFF000000)>>24;//a
  266. }
  267. void getpixel(OGL_Surface *Surface, int pos, uint32_t &col)
  268. {
  269.         col = 0;
  270.         col |= uint32_t(Surface->PixData[pos+2]);//r
  271.         col |= uint32_t(Surface->PixData[pos+1])<<8;//g
  272.         col |= uint32_t(Surface->PixData[pos]  )<<16;//b
  273.         if (Surface->bpp != 4){return;}
  274.         col |= uint32_t(Surface->PixData[pos+3])<<24;//a
  275. }
  276. //x,y
  277. bool putpixel(OGL_Surface *Surface, int x, int y, uint32_t col)
  278. {
  279.         if(x < 0 || y < 0 || x >= (signed)Surface->w || y >= (signed)Surface->h) {return 0;}
  280.         int pos = (x+(y*Surface->w))*Surface->bpp;
  281.         putpixel(Surface, pos, col);
  282.         return 1;
  283. }
  284. bool getpixel(OGL_Surface *Surface, int x, int y, uint32_t &col)
  285. {
  286.         if(x < 0 || y < 0 || x >= (signed)Surface->w || y >= (signed)Surface->h) {return 0;}
  287.         int pos = (x+(y*Surface->w))*Surface->bpp;
  288.         getpixel(Surface, pos, col);
  289.         return 1;
  290. }
  291. //primitives
  292. void hline(OGL_Surface *Surface, int x, int y, int w, uint32_t col)
  293. {
  294.         if (w<0){w=abs(w);x-=w;}
  295.         for (int i=0;i<w;i++){putpixel(Surface, x+i, y, col);}
  296. }
  297. void vline(OGL_Surface *Surface, int x, int y, int h, uint32_t col)
  298. {
  299.         if (h<0){h=abs(h);y-=h;}
  300.         for (int i=0;i<h;i++){putpixel(Surface, x, y+i, col);}
  301. }
  302. void line(OGL_Surface *Surface, int x1, int y1, int x2, int y2, uint32_t col)
  303. {
  304.         if (x1==x2 && y1==y2){putpixel(Surface,x1,y1, col);return;}
  305.         if (x1==x2){vline(Surface,x1,y1,y2-y1, col);return;}
  306.         if (y1==y2){hline(Surface,x1,y1,x2-x1, col);return;}
  307.         int x = x1;
  308.         int y = y1;
  309.         int maxpos = abs(x2 - x1);//width
  310.         int numadder= abs(y2 - y1);//height
  311.         int num;
  312.         int xstep1, ystep1, xstep2, ystep2;//step direction
  313.         if(x2 >= x1){xstep1 = 1; xstep2 = 0;} else{xstep1 =-1; xstep2 = 0;}
  314.         if(y2 >= y1){ystep1 = 1; ystep2 = 0;} else{ystep1 =-1; ystep2 = 0;}
  315.         //check step direction, true = x axis, false = y axis
  316.         if (maxpos >= numadder){//if width >= height
  317.                 ystep2 = ystep1; ystep1 =0;
  318.         }
  319.         else{
  320.                 num = maxpos; maxpos = numadder; numadder = num;
  321.                 xstep2 = xstep1; xstep1 =0;
  322.         }
  323.         num = maxpos >>1;
  324.         for (int pos = 0; pos <= maxpos; pos++){
  325.                 putpixel(Surface, x, y, col);
  326.                 num += numadder;
  327.                 if (num >= maxpos){
  328.                         num -= maxpos;
  329.                         x += xstep2;
  330.                         y += ystep2;
  331.                 }
  332.                 x += xstep1;
  333.                 y += ystep1;
  334.         }
  335. }
  336.  
  337. void box(OGL_Surface *Surface, int x, int y, int w, int h, uint32_t col)
  338. {
  339.         hline(Surface,x,y,w, col);
  340.         hline(Surface,x,y+h,w, col);
  341.         vline(Surface,x,y,h, col);
  342.         vline(Surface,x+w,y,h, col);
  343. }
  344. void rect(OGL_Surface *Surface, int x, int y, int w, int h, uint32_t col)
  345. {
  346.         if (w<0){w=abs(w);x-=w;}
  347.         if (h<0){h=abs(h);y-=h;}
  348.         for (int i = 0; i<h; i++){
  349.                 for (int i2=0; i2<w; i2++){
  350.                         putpixel(Surface, x+i2, y+i, col);
  351.                 }
  352.         }
  353. }
  354.  
  355. void polyline(OGL_Surface *Surface, unsigned char n, int points[], uint32_t col)
  356. {
  357.         for (int i = 0; i<n+n-3; i+=2){
  358.                 line(Surface, points[i], points[i+1], points[i+2], points[i+3], col);
  359.         }
  360. }
  361. void polygon(OGL_Surface *Surface, unsigned char n, int points[], uint32_t col)
  362. {
  363.         polyline(Surface, n, points, col);
  364.         line(Surface, points[n+n-1], points[n+n], points[0], points[1], col);
  365. }
  366.  
  367. void circle(OGL_Surface *Surface, int x0, int y0, int radius, uint32_t col)
  368. {
  369.         if(radius == 0 || x0 + radius < 0 || x0 - radius >= (signed)Surface->w || y0 + radius < 0 || y0 - radius >= (signed)Surface->h) {return;}
  370.         int x = 0;
  371.         int y = radius;
  372.         //8 points can be plotted at once due to symmetry
  373.         int x1,x2,x3,x4;
  374.         int y1,y2,y3,y4;
  375.         int pos = 0-radius;
  376.         while (x <= y){
  377.                 x1 = x0 + x; x2 = x0 - x; x3 = x0 + y; x4 = x0 - y;//xstart +x,-x,+y,-y
  378.                 y1 = y0 + y; y2 = y0 - y; y3 = y0 + x; y4 = y0 - x;
  379.                 putpixel(Surface, x1, y1, col);
  380.                 putpixel(Surface, x2, y2, col);
  381.                 putpixel(Surface, x3, y3, col);
  382.                 putpixel(Surface, x4, y3, col);
  383.                 if(x > 0){
  384.                         putpixel(Surface, x1, y2, col);
  385.                         putpixel(Surface, x2, y1, col);
  386.                         putpixel(Surface, x3, y4, col);
  387.                         putpixel(Surface, x4, y4, col);
  388.                 }
  389.                 //increment
  390.                 if ((pos += x++<<1)>= 0) {
  391.             pos-= y--<<1;
  392.         }
  393.         }
  394. }
  395. void circle_fill(OGL_Surface *Surface, int x0, int y0, int radius, uint32_t col)
  396. {
  397.         if(radius == 0 || x0 + radius < 0 || x0 - radius >= (signed)Surface->w || y0 + radius < 0 || y0 - radius >= (signed)Surface->h) {return;}
  398.         int x = 0;
  399.         int y = radius;
  400.         int pos = 0-radius;
  401.         while (x <= y){
  402.                 hline(Surface,x0-x, y0 + y, x+x, col);
  403.                 hline(Surface,x0-x, y0 - y, x+x, col);
  404.                 hline(Surface,x0-y, y0 + x, y+y, col);
  405.                 hline(Surface,x0-y, y0 - x, y+y, col);
  406.                 //increment
  407.                 if ((pos += x++<<1)>= 0) {
  408.             pos-= y--<<1;
  409.         }
  410.         }
  411. }