Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <cstring>
- 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<w*h*bpp){
- PixData[pos++] = r;
- PixData[pos++] = g;
- PixData[pos++] = b;
- if(bpp==4){PixData[pos++] = a;}
- }
- }
- }
- void OGL_Surface::Set_Surface_AlphaKey(uint8_t r, uint8_t g, uint8_t b)
- {
- if(bpp!=4){printf("trying to set alphakey on bpp that does not support alpha\n");return;}
- int pos = 0;
- for (unsigned int y = 0; y<h; y++){
- for (unsigned int x = 0; x<w; x++){
- if ((PixData[pos]==r) && (PixData[pos+1]==b) && (PixData[pos+2] == b)){
- PixData[pos+3]= 0;//if colour = alphakey set alpha channel to 0
- }
- pos+=4;
- }
- }
- }
- void OGL_Surface::gen_texture(){
- if (w==0 || h==0){printf("ERROR! WIDTH OR HEIGHT OF SURFACE == 0"); exit(1);}
- //Power of two texture support
- uint32_t width = w;
- uint32_t height= h;
- //only generate a texture once
- if (!texture_generated){
- 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);
- //glTexImage2D respecifies the entire texture, changing its size, deleting the previous data etc.
- //only do this if texture doesn't exist or if w/h change
- if (!texture_generated){
- switch (bpp){
- //2d texture, level of detail, number of components (3=rgb), w,h, border, byte order, data format, data
- case 3: glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, PixData); break;
- case 4: glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width, height, 0, GL_BGRA,GL_UNSIGNED_BYTE, PixData); break;
- }
- }
- //glTexSubImage2D only modifies pixel data within the texture.
- //do this when pixels need to be updated
- else{
- switch (bpp){
- //2d texture, level of detail, xoffset,yoffset, w,h, byte order, data format, data
- case 3: glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, GL_BGR, GL_UNSIGNED_BYTE, PixData); break;
- case 4: glTexSubImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height, GL_BGRA,GL_UNSIGNED_BYTE, PixData); break;
- }
- }
- 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_Texture *Texture_Cast(OGL_Surface *Surface)
- {
- OGL_Texture *Texture = static_cast<OGL_Texture*>(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<w;i++){putpixel(Surface, x+i, y, col);}
- }
- void vline(OGL_Surface *Surface, int x, int y, int h, uint32_t col)
- {
- if (h<0){h=abs(h);y-=h;}
- for (int i=0;i<h;i++){putpixel(Surface, x, y+i, col);}
- }
- void line(OGL_Surface *Surface, int x1, int y1, int x2, int y2, uint32_t col)
- {
- if (x1==x2 && y1==y2){putpixel(Surface,x1,y1, col);return;}
- if (x1==x2){vline(Surface,x1,y1,y2-y1, col);return;}
- if (y1==y2){hline(Surface,x1,y1,x2-x1, col);return;}
- int x = x1;
- int y = y1;
- int maxpos = abs(x2 - x1);//width
- int numadder= abs(y2 - y1);//height
- int num;
- int xstep1, ystep1, xstep2, ystep2;//step direction
- if(x2 >= 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<h; i++){
- for (int i2=0; i2<w; i2++){
- putpixel(Surface, x+i2, y+i, col);
- }
- }
- }
- void polyline(OGL_Surface *Surface, unsigned char n, int points[], uint32_t col)
- {
- for (int i = 0; i<n+n-3; i+=2){
- line(Surface, points[i], points[i+1], points[i+2], points[i+3], col);
- }
- }
- void polygon(OGL_Surface *Surface, unsigned char n, int points[], uint32_t col)
- {
- polyline(Surface, n, points, col);
- line(Surface, points[n+n-1], points[n+n], points[0], points[1], col);
- }
- void circle(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;
- //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;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement