#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <cstdio>
#include <cmath>
#include "GL/ImmediateMode.h"
BEGIN_NAMESPACE
#define DECLARE_GL_FUNCTION(type, name) \
type name;
DECLARE_ALL_GL_FUNCTIONS
#undef DECLARE_GL_FUNCTION
// Now load the various GL extension functions we use
#define DECLARE_GL_FUNCTION(type, name) \
name = (type)wglGetProcAddress(#name); \
if (glGetError() != GL_NO_ERROR) { \
printf("GL Error getting proc address for %s\n", #name); \
}
void glLoadExtensions()
{
DECLARE_ALL_GL_FUNCTIONS
}
#undef DECLARE_GL_FUNCTION
void glCheckErrors()
{
GLenum result = glGetError();
if (result != GL_NO_ERROR)
{
printf("GL Error\n");
}
}
void glSetColor(uint32_t a_color)
{
glColor4ub((a_color >> 16) & 0xff, (a_color >> 8) & 0xff, a_color & 0xff, (a_color >> 24) & 0xff);
}
static void glLineHelper(float x1, float y1, float x2, float y2)
{
glVertex2f(x1, y1);
glVertex2f(x2, y2);
}
void glDrawLine(float x1, float y1, float x2, float y2, uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_LINES);
glLineHelper(x1, y1, x2, y2);
glEnd();
glCheckErrors();
}
static void glBezierCurveHelper(float p1[2], float cp1[2], float cp2[2], float p2[2])
{
const int subDivisions = 32;
/*
int mid = (x1 + x2) / 2;
Mat4x4f coeffients = { { 1,-3,3,-1, 0,3,-6,3, 0,0,3,-3, 0,0,0,1 } };
//Mat4x4f coeffients = { { 1,0,0,0, -3,3,0,0, 3,-6,3,0, -1,3,-3,1 } };
Mat4x4f points = { { x1,y1,0,0, mid,y1,0,0, mid,y2,0,0, x2,y2,0,0 } };
Mat4x4f factors = MatrixMult(points, coeffients);
*/
for (int i = 0; i < subDivisions; ++i)
{
float t[2] = { float(i) / subDivisions, float(i+1) / subDivisions };
/*
Vec4f ts = { { 1,t,t*t,t*t*t } };
Vec4f res = Transform(factors, ts);
Vec4f t2s = { { 1,t2,t2*t2,t2*t2*t2 } };
Vec4f res2 = Transform(factors, t2s);
glDrawLine(res.v[0], res.v[1], res2.v[0], res2.v[1], a_color);
*/
float b[2][2];
for (int j = 0; j < 2; ++j)
for (int c = 0; c < 2; ++c)
b[j][c] = p1[c]*(1-t[j])*(1-t[j])*(1-t[j])+
cp1[c]*3*(1-t[j])*(1-t[j])*t[j]+
cp2[c]*3*(1-t[j])*t[j]*t[j]+
p2[c]*t[j]*t[j]*t[j];
glLineHelper(b[0][0], b[0][1], b[1][0], b[1][1]);
}
}
void glDrawBezierCurve(float p1[2], float cp1[2], float cp2[2], float p2[2], uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_LINE_STRIP);
glBezierCurveHelper(p1, cp1, cp2, p2);
glEnd();
glCheckErrors();
}
void glDrawCurvedLine(float x1, float y1, float x2, float y2, uint32_t a_color)
{
float halfW = fabs((x2 - x1) / 2.0f);
float p1[2] = { x1, y1 }, cp1[2] = { x1+halfW, y1 }, cp2[2] = { x2-halfW, y2 }, p2[2] = { x2, y2 };
glDrawBezierCurve(p1, cp1, cp2, p2, a_color);
}
void glDrawRect(float x1, float y1, float x2, float y2, uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_LINES);
glLineHelper(x1, y1, x2, y1);
glLineHelper(x2, y1, x2, y2);
glLineHelper(x2, y2, x1, y2);
glLineHelper(x1, y2, x1, y1);
glEnd();
glCheckErrors();
}
void glDrawFillRect(float x1, float y1, float x2, float y2, uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_QUADS);
glVertex3f(x1, y1, 0.0f);
glVertex3f(x2, y1, 0.0f);
glVertex3f(x2, y2, 0.0f);
glVertex3f(x1, y2, 0.0f);
glEnd();
glCheckErrors();
}
static void glDrawCircleHelper(GLenum mode, float x1, float y1, float size, uint32_t a_color)
{
//glDrawRect(x1, y1, x1+size, y1+size, a_color);
glSetColor(a_color);
glBegin(mode);
const int subDivisions = 64;
float centerX = x1 + size * 0.5f;
float centerY = y1 + size * 0.5f;
float pi = 2.0f*acos(0.0f);
for (int i = 0; i < subDivisions; ++i)
{
float x1 = centerX + size*0.5f*cos((i*2.0f*pi)/subDivisions) + 0.5f;
float y1 = centerY + size*0.5f*sin((i*2.0f*pi)/subDivisions) + 0.5f;
float x2 = centerX + size*0.5f*cos(((i+1)*2.0f*pi)/subDivisions) + 0.5f;
float y2 = centerY + size*0.5f*sin(((i+1)*2.0f*pi)/subDivisions) + 0.5f;
glLineHelper(x1, y1, x2, y2);
}
glEnd();
glCheckErrors();
}
void glDrawCircle(float x1, float y1, float size, uint32_t a_color)
{
glDrawCircleHelper(GL_LINES, x1, y1, size, a_color);
}
void glDrawFilledCircle(float x1, float y1, float size, uint32_t a_color)
{
glDrawCircleHelper(GL_TRIANGLE_FAN, x1, y1, size, a_color);
}
static void glDrawRoundedRectHelper(float x1, float y1, float x2, float y2, float radius)
{
/*
float p[4][4][2] = {
{ { x1, y1+radius }, { x1, y1 }, { x1, y1 }, { x1+radius, y1 } },
{ { x2, y1+radius }, { x2, y1 }, { x2, y1 }, { x2-radius, y1 } },
{ { x1, y2-radius }, { x1, y2 }, { x1, y2 }, { x1+radius, y2 } },
{ { x2, y2-radius }, { x2, y2 }, { x2, y2 }, { x2-radius, y2 } },
};
*/
float p[4][4][2] = {
{ { x1+0.5f, y1+radius }, { x1, y1 }, { x1, y1 }, { x1+radius, y1+0.5f } },
{ { x2-radius, y1+0.5f }, { x2, y1 }, { x2, y1 }, { x2-0.5f, y1+radius } },
{ { x2-0.5f, y2-radius }, { x2, y2 }, { x2, y2 }, { x2-radius, y2-0.5f } },
{ { x1+radius, y2-0.5f }, { x1, y2 }, { x1, y2 }, { x1+0.5f, y2-radius } },
};
for (int i = 0; i < 4; ++i) {
glBezierCurveHelper(p[i][0], p[i][1], p[i][2], p[i][3]);
glLineHelper(p[i][3][0], p[i][3][1], p[(i+1)&3][0][0], p[(i+1)&3][0][1]);
}
}
void glDrawRoundedRect(float x1, float y1, float x2, float y2, float radius, uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_LINES);
glDrawRoundedRectHelper(x1, y1, x2, y2, radius);
glEnd();
glCheckErrors();
}
void glDrawFillRoundedRect(float x1, float y1, float x2, float y2, float radius, uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_TRIANGLE_FAN);
glDrawRoundedRectHelper(x1, y1, x2, y2, radius);
glEnd();
glCheckErrors();
}
void glDrawFillTitleBar(float x1, float y1, float x2, float y2, float radius, uint32_t a_color)
{
glSetColor(a_color);
glBegin(GL_TRIANGLE_FAN);
float p[2][4][2] = {
{ { x1, y1+radius }, { x1, y1 }, { x1, y1 }, { x1+radius, y1 } },
{ { x2-radius, y1 }, { x2, y1 }, { x2, y1 }, { x2, y1+radius } },
};
//for (int i = 0; i < 4; ++i)
int i = 0;
glBezierCurveHelper(p[i][0], p[i][1], p[i][2], p[i][3]);
glLineHelper(x1+radius, y1, x2-radius, y1);
i = 1;
glBezierCurveHelper(p[i][0], p[i][1], p[i][2], p[i][3]);
glLineHelper(x2, y1+radius, x2, y2);
glLineHelper(x2, y2, x1, y2);
glLineHelper(x1, y2, x1, y1+radius);
glEnd();
glCheckErrors();
}
// Needed for textures with OpenGL
unsigned nextPowerOfTwo(unsigned int a_value)
{
for (unsigned i = 0; i < 32; ++i)
{
unsigned powerOfTwo = 1 << i;
if (powerOfTwo >= a_value)
return powerOfTwo;
}
return 1 << 31;
}
void glDrawTarget(float x, float y, CUTE::CUTE_PaintTarget a_target, GLuint a_texture)
{
int w = a_target.m_strideBytes/4;
int h = nextPowerOfTwo(a_target.m_height);
#if 1
glEnable(GL_TEXTURE_2D);
glCheckErrors();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, a_texture);
glCheckErrors();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_BGRA_EXT, GL_UNSIGNED_BYTE, a_target.m_pixels);
glCheckErrors();
glBegin(GL_QUADS);
float x2 = float(a_target.m_width) / w;
float y2 = float(a_target.m_height) / h;
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, 0.0f);
glTexCoord2f( x2, 0.0f); glVertex3f(x+a_target.m_width, y, 0.0f);
glTexCoord2f( x2, y2); glVertex3f(x+a_target.m_width, y+a_target.m_height, 0.0f);
glTexCoord2f(0.0f, y2); glVertex3f(x, y+a_target.m_height, 0.0f);
glEnd();
glCheckErrors();
//glFlush();
//glCheckErrors();
glDisable(GL_TEXTURE_2D);
#else
//glPixelZoom(g_zoomFactor, -g_zoomFactor);
glRasterPos2f(x, y);
glDrawPixels(w, h, GL_BGRA_EXT, GL_UNSIGNED_BYTE, a_target.m_pixels);
#endif
glCheckErrors();
}
void glDrawShadowText(int x, int y, const char* text)
{
glDrawText(x+1, y, text, 0xff000000, 0xffffffff, 17, false);
}
void glDrawDot(float x, float y)
{
glDrawFilledCircle(x-7, y, 14, 0xf06060f0);
glDrawCircle(x-7, y, 14, 0xa0202020);
}
void glDrawStyledCurvedLine(float x1, float y1, float x2, float y2, float scale, bool highlighted)
{
// TODO: fix the line joins - eg miter, bevel etc join types.
// Need to turn lines in to triangle strips or something like that. Probably only the bezier case matters at the moment.
glLineWidth(5.0f * scale);
glDrawCurvedLine(x1, y1, x2, y2, 0x40000000);
uint32_t col = highlighted ? 0x50ff901a : 0x4ff0f0f0;
glLineWidth(2.0f * scale);
glDrawCurvedLine(x1, y1, x2, y2, col);
glLineWidth(1.0f);
glCheckErrors();
}
END_NAMESPACE