#include #include #include using namespace std; #include "Draw.h" /////////////// //OGL Texture// /////////////// OGL_Texture::OGL_Texture(){ w=h=0; texture_generated = false; Texture_ID = 0; } OGL_Texture::~OGL_Texture(){ if (Texture_ID){glDeleteTextures(1,&Texture_ID);}//0 is not a valid texture id } void OGL_Texture::gen_texture(uint16_t width, uint16_t height, uint8_t *PixData){ if (width==0 || height==0){printf("ERROR! WIDTH OR HEIGHT OF TEXTURE == 0"); exit(1);} //delete old texture if existing if (texture_generated && Texture_ID){ glDeleteTextures(1,&Texture_ID); } w = width; h = height; //generate texture glGenTextures(1,&Texture_ID); if (Texture_ID==0){printf("ERROR IN TEXTURE GENERATION! NO DEVICE CONTEXT?"); exit(1);} glEnable(GL_TEXTURE_RECTANGLE_NV); glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture_ID); //2d texture, level of detail, number of components (3=rgb), w,h, border, byte order, data format, data glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, PixData); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glDisable(GL_TEXTURE_RECTANGLE_NV); texture_generated = true; } /////////////// //OGL Surface// /////////////// OGL_Surface::OGL_Surface(){ texture_generated = false; bpp=4; w=h=0; PixData = nullptr; } OGL_Surface::~OGL_Surface(){ if (PixData != nullptr) {delete [] PixData;} } void OGL_Surface::Create_Surface(uint16_t set_w,uint16_t set_h, char set_bpp){ if (set_bpp==24){bpp=3;} if (set_bpp==32){bpp=4;} // if surface already exists and width or height change delete old texture if (texture_generated && (w != set_w || h != set_h)){ glDeleteTextures(1,&Texture_ID); texture_generated = false; } // if surface already exists delete old data if (PixData != nullptr) {delete [] PixData;} w = set_w; h = set_h; bpp = set_bpp; PixData = new uint8_t[w*h*bpp]; memset(PixData,255, w*h*bpp); } void OGL_Surface::Clear_Surface(uint8_t r, uint8_t g, uint8_t b, uint8_t a){ if (r == g && g == b && bpp==3){ memset(PixData, r, w*h*bpp); } else if (r == g && g == b && b == a && bpp==4){ memset(PixData, r, w*h*bpp); } else{ unsigned int pos = 0; while (pos(Surface); Texture->w = Surface->w; Texture->h = Surface->h; return Texture; } //////// //BLIT// //////// //glBlendFunc(source_blend, dst_blend) //GL_ZERO colour is ignored //GL_ONE full colour is taken into addition //GL_(DST/SRC)_COLOR colour is multiplied by (DST/SRC) color //GL_ONE_MINUS_(DST/SRC)_COLOR colour is multiplied by inverted (DST/SRC) color //GL_(DST/SRC)_ALPHA colour is multiplied by (DST/SRC) alpha value //GL_ONE_MINUS_(DST/SRC)_ALPHA colour is multiplied by inverted (DST/SRC) alpha value //overall colour (GL_SRC_ALPHA, GL_ONE) -addative- = (r1*a1,g1*a1,b1*a1)+(r2,g2,b2) void DrawImage(OGL_Texture *Texture, int dx, int dy, float rot,float scale_x,float scale_y,float alpha,int options){ if (options & IMG_HFLIP){dx+=Texture->w; scale_x=-1;} if (options & IMG_VFLIP){dy+=Texture->h; scale_y=-1;} glLoadIdentity(); glTranslatef(dx, dy, 0.0); if (scale_x!=1 && scale_y!=1){glScaled(scale_x, scale_y, 0);} if (rot!=0){ int tmpw = Texture->w/2; int tmph = Texture->h/2; glTranslatef(tmpw, tmph, 0.0); glRotatef(rot, 0, 0, 1.0); glTranslatef(-tmpw, -tmph, 0.0); } glEnable(GL_TEXTURE_RECTANGLE_NV); glEnable(GL_BLEND); //additive blending - gray + gray = white if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);} //regular alpha blending - gray + gray = gray else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);} //blit glColor4f(1.0f, 1.0f, 1.0f, alpha); glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture->Texture_ID); glBegin(GL_QUADS); glTexCoord2i(0,0); glVertex2i(0, 0); glTexCoord2i(Texture->w,0); glVertex2i(Texture->w, 0); glTexCoord2i(Texture->w,Texture->h); glVertex2i(Texture->w, Texture->h); glTexCoord2i(0,Texture->h); glVertex2i(0, Texture->h); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_RECTANGLE_NV); glLoadIdentity(); } 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){ if (options & IMG_HFLIP){dx+=Texture->w; scale_x=-1;} if (options & IMG_VFLIP){dy+=Texture->h; scale_y=-1;} glLoadIdentity(); glTranslatef(dx, dy, 0.0); if (scale_x!=1 && scale_y!=1){glScaled(scale_x, scale_y, 0);} if (rot!=0){ int tmpw = Texture->w/2; int tmph = Texture->h/2; glTranslatef(tmpw, tmph, 0.0); glRotatef(rot, 0, 0, 1.0); glTranslatef(-tmpw, -tmph, 0.0); } glEnable(GL_TEXTURE_RECTANGLE_NV); glEnable(GL_BLEND); //additive blending - gray + gray = white if (options &= IMG_ADD_BLEND){glBlendFunc(GL_SRC_ALPHA, GL_ONE);} //regular alpha blending - gray + gray = gray else{glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);} //blit glColor4f(1.0,1.0,1.0,alpha); glBindTexture(GL_TEXTURE_RECTANGLE_NV, Texture->Texture_ID); glBegin(GL_QUADS); glTexCoord2i(sx,sy); glVertex2i(0, 0); glTexCoord2i(sx+sw,sy); glVertex2i(sw, 0); glTexCoord2i(sx+sw,sy+sh); glVertex2i(sw, sh); glTexCoord2i(sx,sy+sh); glVertex2i(0, sh); glEnd(); glDisable(GL_BLEND); glDisable(GL_TEXTURE_RECTANGLE_NV); glLoadIdentity(); } ////////// //COLOUR// ////////// uint32_t make_col(uint8_t r, uint8_t g, uint8_t b, uint8_t a){ uint32_t col = 0; col |= r; col |= uint32_t(g)<<8; col |= uint32_t(b)<<16; col |= uint32_t(a)<<24; //printf("%#X, %d,%d,%d\n", col,r,g,b); return col; } uint32_t make_col(uint8_t r, uint8_t g, uint8_t b){ return make_col(r,g,b,255); } /////////////////// //DRAW PRIMITIVES// /////////////////// //pos void putpixel(OGL_Surface *Surface, int pos, uint32_t col) { Surface->PixData[pos+2] = (col&0x000000FF);//r Surface->PixData[pos+1] = (col&0x0000FF00)>>8;//g Surface->PixData[pos] = (col&0x00FF0000)>>16;//b if (Surface->bpp != 4){return;} Surface->PixData[pos+3] = (col&0xFF000000)>>24;//a } void getpixel(OGL_Surface *Surface, int pos, uint32_t &col) { col = 0; col |= uint32_t(Surface->PixData[pos+2]);//r col |= uint32_t(Surface->PixData[pos+1])<<8;//g col |= uint32_t(Surface->PixData[pos] )<<16;//b if (Surface->bpp != 4){return;} col |= uint32_t(Surface->PixData[pos+3])<<24;//a } //x,y bool putpixel(OGL_Surface *Surface, int x, int y, uint32_t col) { if(x < 0 || y < 0 || x >= (signed)Surface->w || y >= (signed)Surface->h) {return 0;} int pos = (x+(y*Surface->w))*Surface->bpp; putpixel(Surface, pos, col); return 1; } bool getpixel(OGL_Surface *Surface, int x, int y, uint32_t &col) { if(x < 0 || y < 0 || x >= (signed)Surface->w || y >= (signed)Surface->h) {return 0;} int pos = (x+(y*Surface->w))*Surface->bpp; getpixel(Surface, pos, col); return 1; } //primitives void hline(OGL_Surface *Surface, int x, int y, int w, uint32_t col) { if (w<0){w=abs(w);x-=w;} for (int i=0;i= x1){xstep1 = 1; xstep2 = 0;} else{xstep1 =-1; xstep2 = 0;} if(y2 >= y1){ystep1 = 1; ystep2 = 0;} else{ystep1 =-1; ystep2 = 0;} //check step direction, true = x axis, false = y axis if (maxpos >= numadder){//if width >= height ystep2 = ystep1; ystep1 =0; } else{ num = maxpos; maxpos = numadder; numadder = num; xstep2 = xstep1; xstep1 =0; } num = maxpos >>1; for (int pos = 0; pos <= maxpos; pos++){ putpixel(Surface, x, y, col); num += numadder; if (num >= maxpos){ num -= maxpos; x += xstep2; y += ystep2; } x += xstep1; y += ystep1; } } void box(OGL_Surface *Surface, int x, int y, int w, int h, uint32_t col) { hline(Surface,x,y,w, col); hline(Surface,x,y+h,w, col); vline(Surface,x,y,h, col); vline(Surface,x+w,y,h, col); } void rect(OGL_Surface *Surface, int x, int y, int w, int h, uint32_t col) { if (w<0){w=abs(w);x-=w;} if (h<0){h=abs(h);y-=h;} for (int i = 0; i= (signed)Surface->w || y0 + radius < 0 || y0 - radius >= (signed)Surface->h) {return;} int x = 0; int y = radius; //8 points can be plotted at once due to symmetry int x1,x2,x3,x4; int y1,y2,y3,y4; int pos = 0-radius; while (x <= y){ x1 = x0 + x; x2 = x0 - x; x3 = x0 + y; x4 = x0 - y;//xstart +x,-x,+y,-y y1 = y0 + y; y2 = y0 - y; y3 = y0 + x; y4 = y0 - x; putpixel(Surface, x1, y1, col); putpixel(Surface, x2, y2, col); putpixel(Surface, x3, y3, col); putpixel(Surface, x4, y3, col); if(x > 0){ putpixel(Surface, x1, y2, col); putpixel(Surface, x2, y1, col); putpixel(Surface, x3, y4, col); putpixel(Surface, x4, y4, col); } //increment if ((pos += x++<<1)>= 0) { pos-= y--<<1; } } } void circle_fill(OGL_Surface *Surface, int x0, int y0, int radius, uint32_t col) { if(radius == 0 || x0 + radius < 0 || x0 - radius >= (signed)Surface->w || y0 + radius < 0 || y0 - radius >= (signed)Surface->h) {return;} int x = 0; int y = radius; int pos = 0-radius; while (x <= y){ hline(Surface,x0-x, y0 + y, x+x, col); hline(Surface,x0-x, y0 - y, x+x, col); hline(Surface,x0-y, y0 + x, y+y, col); hline(Surface,x0-y, y0 - x, y+y, col); //increment if ((pos += x++<<1)>= 0) { pos-= y--<<1; } } }