实现了16种roundBox,见图
核心绘制码在RoundBox.h文件:
#ifndef ROUNDBOXRENDER_H
#define ROUNDBOXRENDER_H
// 7/8/2010 RYF
// QQ: 546952710
// Email: dizuo@126.com
struct RoundBoxRender
{
// 产生一个渐变的效果:
// shadetop叠加top
// shadedown叠加到down 可以为负
// rad为圆角的半径
/* linear horizontal shade within button or in outline */
/* view2d scrollers use it */
static void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown)
{
float vec[7][2]= {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169}, {0.707, 0.293},
{0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
float div = maxy - miny;
float coltop[3], coldown[3], color[4];
int a;
/* mult */
for(a = 0; a < 7; a++)
{
vec[a][0] *= rad; vec[a][1] *= rad;
}
/* get current color, needs to be outside of glBegin/End */
glGetFloatv(GL_CURRENT_COLOR, color);
/* 'shade' defines strength of shading */
coltop[0]= color[0]+shadetop; if(coltop[0]>1.0) coltop[0]= 1.0;
coltop[1]= color[1]+shadetop; if(coltop[1]>1.0) coltop[1]= 1.0;
coltop[2]= color[2]+shadetop; if(coltop[2]>1.0) coltop[2]= 1.0;
coldown[0]= color[0]+shadedown; if(coldown[0]<0.0) coldown[0]= 0.0;
coldown[1]= color[1]+shadedown; if(coldown[1]<0.0) coldown[1]= 0.0;
coldown[2]= color[2]+shadedown; if(coldown[2]<0.0) coldown[2]= 0.0;
glShadeModel(GL_SMOOTH);
glBegin(mode);
/* start with corner right-bottom */
if(roundboxtype & 4)
{
round_box_shade_col(coltop, coldown, 0.0);
glVertex2f(maxx-rad, miny);
for(a =0; a < 7; a++)
{
round_box_shade_col(coltop, coldown, vec[a][1]/div);
glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
}
round_box_shade_col(coltop, coldown, rad/div);
glVertex2f(maxx, miny + rad);
}
else
{
round_box_shade_col(coltop, coldown, 0.0);
glVertex2f(maxx, miny);
}
/* corner right-top */
if(roundboxtype & 2)
{
round_box_shade_col(coltop, coldown, (div - rad) / div);
glVertex2f(maxx, maxy-rad);
for(a=0; a<7; a++)
{
round_box_shade_col(coltop, coldown, (div - rad + vec[a][1]) / div);
glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
}
round_box_shade_col(coltop, coldown, 1.0);
glVertex2f(maxx-rad, maxy);
}
else
{
round_box_shade_col(coltop, coldown, 1.0);
glVertex2f(maxx, maxy);
}
/* corner left-top */
if(roundboxtype & 1)
{
round_box_shade_col(coltop, coldown, 1.0);
glVertex2f(minx + rad, maxy);
for(a = 0; a < 7; a++)
{
round_box_shade_col(coltop, coldown, (div - vec[a][1]) / div);
glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
}
round_box_shade_col(coltop, coldown, (div - rad) / div);
glVertex2f(minx, maxy - rad);
}
else
{
round_box_shade_col(coltop, coldown, 1.0);
glVertex2f(minx, maxy);
}
/* corner left-bottom */
if(roundboxtype & 8)
{
round_box_shade_col(coltop, coldown, rad/div);
glVertex2f(minx, miny+rad);
for(a=0; a<7; a++)
{
round_box_shade_col(coltop, coldown, (rad-vec[a][1])/div);
glVertex2f(minx+vec[a][1], miny+rad-vec[a][0]);
}
round_box_shade_col(coltop, coldown, 0.0);
glVertex2f(minx+rad, miny);
}
else
{
round_box_shade_col(coltop, coldown, 0.0);
glVertex2f(minx, miny);
}
glEnd();
glShadeModel(GL_FLAT);
}
static void setType(int nType){
roundboxtype = nType % 16;
}
protected:
static void round_box_shade_col(float *col1, float *col2, float fac)
{
float col[3];
col[0]= (fac*col1[0] + (1.0-fac)*col2[0]);
col[1]= (fac*col1[1] + (1.0-fac)*col2[1]);
col[2]= (fac*col1[2] + (1.0-fac)*col2[2]);
glColor3fv(col);
}
static int roundboxtype;
};
int RoundBoxRender::roundboxtype = 3;
#endif
gl_round_box_shade中mode支持:GL_LINE_LOOP,GL_POLYGON,GL_TRIANGLE_FAN
round_box_shade_col:col1颜色和col2颜色,根据混合因子fac进行混合,产生中间颜色。
主程序基于glut:
#include <cstdio>
#include <cstdlib>
#include <GL/glut.h>
#include <cmath>
#include <ctime>
//#include "BezierLinkRender.h"
#include "RoundBoxRender.h"
//
//global
GLuint gColorStable[] =
{
(0xFF0000), //red
(0xDC143C), //crimson
(0x9400D3), //violet
(0xFFA000), //orange
(0xFFFF00), //yellow
(0xFFD700), //glod
(0x00FF00), //green
(0x90FF90), //lightgreen
(0x006400), //darkgreen
(0x556B2F), //olivegreen //very good color绿橄榄
(0x0000FF), //blue
(0x00008B), //darkblue
(0x4169E1), //royalblue
(0x5555FF), //skyblue
(0x191970), //midnightbue
(0xFF00FF), //fuchsia
(0x00FFFF), //aqua
(0xffb6c1), //pink
(0xFF91A4), //salmonpink
(0x30D5C8), //turquoise
(0x008080), //darkturpuoise
(0xA9A9A9), //gray
(0xD3D3D3), //lightgray
(0x808080) //darkgray
};
float g_fWidth = 500;
float g_fHeight = 500;
float g_fDepth = 100;
float g_fAngle = .0;
int gRoundboxtype = 0;
//
void renderBitmapString2D(float x, float y, void *font, char *string);
void getColorFromTable(GLuint rgb, float vec[3]);
void init(void)
{
RoundBoxRender::setType(gRoundboxtype);
printf("%d/n", gRoundboxtype);
glClearColor (0.9, 0.9, 0.9, 0.0);
glShadeModel (GL_SMOOTH);
}
void display(void)
{
const float slotSize = 30.f;
const float slotColor[] = {0.8f, 0.8f, 0.8f};
const float slotShadowSize = 2.0f;
const float slotShadowAlpha = 0.7;
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, g_fWidth, 0, g_fHeight, 0, g_fDepth);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(80.f, 80.f, 0.f); //整体平移
int xPos(0);
int yPos(0);
int xOffset(0);
int yOffset(0);
for (int i=0; i<16; i++)
{
char buffer[10] = {'/0'};
itoa (i,buffer,10);
int fontWidOffset = i>10 ? 12 : 5; //估算量
int fontHghOffset = 10; //估算量
int boxSize = 60;
float colorVec[3];
getColorFromTable(gColorStable[i], colorVec);
glColor3fv(colorVec);
RoundBoxRender::setType(i);
yOffset = i/4;
xOffset = i%4;
glPushMatrix();
{
glTranslatef(xPos+xOffset*100, yPos+yOffset*100, 0.f);
RoundBoxRender::gl_round_box_shade(GL_POLYGON, 0, 0, boxSize, boxSize, 10, 0.3, 0);
glColor3f(0.f, 0.f, 0.0f);
renderBitmapString2D(boxSize/2-fontWidOffset, boxSize/2-fontHghOffset, GLUT_BITMAP_TIMES_ROMAN_24, buffer);
}glPopMatrix();
}
//glColor3f(1.0f, 1.0f, 0.0f);
//ui_draw_link_bezier(&gRect);
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60,1.0,1.5,20);
glMatrixMode (GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
}
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y)
{
if(button==GLUT_LEFT_BUTTON)
switch(state)
{
case GLUT_DOWN:
break;
case GLUT_UP:
break;
}
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc( mouse );
glutMainLoop();
return 0;
}
void renderBitmapString2D(float x, float y, void *font, char *string)
{
char *c;
// set position to start drawing fonts
glRasterPos2f(x, y);
// loop all the characters in the string
for (c=string; *c != '/0'; c++) {
glutBitmapCharacter(font, *c);
}
}
void getColorFromTable(GLuint rgb, float vec[3])
{
GLubyte r = GLubyte ((rgb >> 16) & 0xFF);
GLubyte g = GLubyte ((rgb >> 8) & 0xFF);
GLubyte b = GLubyte (rgb & 0xFF);
vec[0] = r / 255.0f;
vec[1] = g / 255.0f;
vec[2] = b / 255.0f;
}