Advertisement
Guest User

draw.cpp

a guest
Jul 5th, 2012
693
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.51 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement