//////////////////////////////////////////////////////////////////////
//
// 名称: OPGLTorus.cpp
//
// 功能: 动态彩色圆环实现
//
// 注释:用SDK编制的OPENGL动态彩色圆环
//
// 编写: 徐景周
//
// 日期:2002.4.8
//
//
////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#if !defined(M_PI)
#define M_PI 3.14159265f
#endif
char *className = "OPENGL";
char *windowName = "OPENGL彩色圆环编程示例";
int winX = 0, winY = 0;
int winWidth =300, winHeight = 300;
HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;
//GLint fogMode; // 雾效果
GLfloat fScaleNum; // 缩放比例
BOOL bScale;
// 管理颜色索引的结构
struct colorIndexState
{
GLfloat amb[3]; // 环境光颜色(斜面底面)
GLfloat diff[3]; // 漫反射光颜色(斜面中面)
GLfloat spec[3]; // 镜面射光颜色(斜面底面)
GLfloat ratio; // 漫反射光与镜面反射的比例
GLint indexes[3]; // 在调色板中的位置
};
// 数组中每一项表示调色板中的每一个颜色值,下标值用来索引每一个颜色集合
#define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))
struct colorIndexState colors[] =
{
{
{ 0.0f, 0.0f, 0.0f },
{ 0.1f, 0.6f, 0.3f },
{ 1.0f, 1.0f, 1.0f },
0.75f,
{ 0, 0, 0 },
},
{
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.2f, 0.5f },
{ 1.0f, 1.0f, 1.0f },
0.75f,
{ 0, 0, 0 },
},
{
{ 0.0f, 0.05f, 0.05f },
{ 0.6f, 0.0f, 0.8f },
{ 1.0f, 1.0f, 1.0f },
0.75f,
{ 0, 0, 0 },
},
};
// 绘制圆环
void drawTorus(void)
{
int numMajor = 32;
int numMinor = 24;
float majorRadius = 0.6f;
float minorRadius = 0.2f;
double majorStep = 2.0f * M_PI/numMajor;
double minorStep = 2.0f * M_PI/numMinor;
int i, j;
for(i=0; i<numMajor; ++i)
{
double a0 = i * majorStep;
double a1 = a0 + majorStep;
GLfloat x0 = (GLfloat) cos(a0);
GLfloat y0 = (GLfloat) sin(a0);
GLfloat x1 = (GLfloat) cos(a1);
GLfloat y1 = (GLfloat) sin(a1);
if(i & 1)
glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[0].indexes);
else
glMaterialiv(GL_FRONT, GL_COLOR_INDEXES, colors[1].indexes);
glBegin(GL_TRIANGLE_STRIP);
for(j=0; j<= numMinor; ++j)
{
double b = j * minorStep;
GLfloat c = (GLfloat)cos(b);
GLfloat r = minorRadius * c + majorRadius;
GLfloat z = minorRadius * (GLfloat)sin(b);
glNormal3f(x0*c, y0*c, z/minorRadius);
glVertex3f(x0*r, y0*r, z);
glNormal3f(x1*c, y1*c, z/minorRadius);
glVertex3f(x1*r, y1*r, z);
}
glEnd();
}
}
// 设置投影方式
void setProjection(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(winWidth > winHeight)
{
GLfloat aspect = (GLfloat)winWidth / (GLfloat)winHeight;
glFrustum(-0.5f*aspect, 0.5f*aspect, -0.5f, 0.5f, 1.0f, 3.0f);
}
else
{
GLfloat aspect = (GLfloat)winHeight / (GLfloat)winWidth;
glFrustum(-0.5f, 0.5f, -0.5f*aspect, 0.5f*aspect, 1.0f, 3.0f);
}
glMatrixMode(GL_MODELVIEW);
}
// 初始化操作
void init(void)
{
GLfloat matShine = 20.00f;
GLfloat light0Pos[4] = { 0.70f, 0.70f, 1.25f, 0.00f};
glClearIndex((GLfloat)colors[2].indexes[1]);
setProjection();
glTranslatef(0.0f, 0.0f, -2.0f);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,matShine);
glLightfv(GL_LIGHT0, GL_POSITION, light0Pos);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
fScaleNum = 1.0; // 缩放比例
bScale = FALSE; // 是否缩放
// 设置雾效果
/* glEnable(GL_FOG);
{
GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0};
fogMode = GL_EXP;
glFogi(GL_FOG_MODE, fogMode);
glFogfv(GL_FOG_COLOR, fogColor);
glFogf(GL_FOG_START, 0.0);
glFogf(GL_FOG_END, 4.0);
glHint(GL_FOG_HINT, GL_NICEST);
glClearColor(0.5, 0.5, 0.5, 1.0);
}
*/
}
// 重绘圆环
void doRedraw(void)
{
static GLfloat x, y, z;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(x, 1.0f, 0.0f, 0.0f);
glRotatef(y, 0.0f, 1.0f, 0.0f);
glRotatef(z, 0.0f, 0.0f, 1.0f);
glScalef(fScaleNum, fScaleNum, fScaleNum);
drawTorus();
glPopMatrix();
SwapBuffers(hDC);
x += 5.0f;
if( x > 360.0f)
x -= 360.0f;
y += 7.0f;
if( y > 360.0f)
y -= 360.0f;
z += 9.0f;
if( z > 360.0f)
z -= 360.0f;
}
// 空闲时重绘旋转彩色圆环
void (*idleFunc) (void);
void redraw(void)
{
idleFunc = doRedraw;
}
// 窗体大小改变时,重设投影和视口
void resize(void)
{
setProjection();
glViewport(0, 0, winWidth,winHeight);
}
// 设置逻辑调色板
void setupPalette(HDC hDC)
{
PIXELFORMATDESCRIPTOR pfd;
LOGPALETTE* pPal;
int pixelFormat = GetPixelFormat(hDC);
int paletteSize;
DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
// 是否需要一个调色板
if(pfd.dwFlags & PFD_NEED_PALETTE || pfd.iPixelType == PFD_TYPE_COLORINDEX)
{
paletteSize = 1 << pfd.cColorBits;
if(paletteSize > 4096)
paletteSize = 4096;
}
else
return;
pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
pPal->palVersion = 0x300;
pPal->palNumEntries = paletteSize;
{
int numRamps = NUM_COLORS;
int rampSize = (paletteSize / 20) / numRamps;
int extra = (paletteSize / 20) / (numRamps * rampSize);
int i,r;
// 从当前系统调色板中拷贝数据来初始化静态入口
GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
// 用所需颜色填充非静态入口
for(r=0; r < numRamps; ++r)
{
int rampBase = r * rampSize +10;
PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
int diffSize = (int)(rampSize * colors[r].ratio);
int specSize = rampSize - diffSize;
for(i=0; i < rampSize; ++i)
{
GLfloat *c0,*c1;
GLint a;
if(i < diffSize)
{
c0 = colors[r].amb;
c1 = colors[r].diff;
a = (i * 255) / (diffSize -1);
}
else
{
c0 = colors[r].diff;
c1 = colors[r].spec;
a = ((i - diffSize) * 255) / (specSize -1);
}
pe[i].peRed = (BYTE)(a * (c1[0] - c0[0]) + 255 * c0[0]);
pe[i].peGreen = (BYTE)(a * (c1[1] - c0[1]) + 255 * c0[1]);
pe[i].peBlue = (BYTE)(a * (c1[2] - c0[2]) + 255 * c0[2]);
pe[i].peFlags = PC_NOCOLLAPSE;
}
colors[r].indexes[0] = rampBase;
colors[r].indexes[1] = rampBase + (diffSize -1);
colors[r].indexes[2] = rampBase + (rampSize -1);
}
// 初始化其它非静态入口
for(i=0; i < extra; ++i)
{
int index = numRamps * rampSize + 10 +i;
PALETTEENTRY *pe = &pPal->palPalEntry[index];
pe->peRed = (BYTE) 0;
pe->peGreen = (BYTE) 0;
pe->peBlue = (BYTE) 0;
pe->peFlags = PC_NOCOLLAPSE;
}
}
hPalette = CreatePalette(pPal);
free(pPal);
if(hPalette)
{
SelectPalette(hDC, hPalette, FALSE);
RealizePalette(hDC);
}
}
// 设置像素格式
void setupPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // 结构大小
1, // 版本号
PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
PFD_TYPE_COLORINDEX, // 颜色索引模式
8, // 8位颜色深度
0,0,0,0,0,0, // 忽略颜色位
0, // 没有非透明缓存
0, // ALPHA位数
0, // 累积缓存
0,0,0,0, // 累积缓存位数
16, // 深度缓存
0, // 模板缓存
0, // 辅助缓存
PFD_MAIN_PLANE, // 主层
0, // 保留
0,0,0, // 不设置层,可见性及损毁掩模
};
int SelectedPixelFormat;
BOOL retVal;