学习OpenGL的一个好玩程序,没想到它的功能那么厉害,有三个文件,虽然不是本人原创,是大神分享的,在这里给大家分享一下
#ifndef _BLADE_H_
#define _BLADE_H_
#include
#include
class Blade
{
public :
int winWidth, winHeight;
GLint mousePosX, mousePosY;
Blade();
~Blade();
void drawBlade(void );
void sampleFadeBlade(void);
void mouse2BladeState(int btn, int state, int x, int y);
void recordOrthoData(GLfloat left, GLfloat right, GLfloat bottom, GLfloat up);
private :
static const int MAXTIMER = 10;
static const int vertexArrHead = 0;
static const int vertexArrTail = 20;
static const int POINTTHRESHOLD = 16;
static const GLint sampleTimerFlag = 0;
static const GLint fadeTimerFlag = 1;
int vertexArrStartPos;
//int vertexArrEndPos;
GLint pointCount;
GLint drawFlag;
GLint mouseDownFlag;
GLfloat bodyVertex[vertexArrTail][2];
GLfloat uniformSideVertex[vertexArrTail][2][2];
GLfloat outerSideVertex[vertexArrTail][2][2];
GLfloat innerSideVertex[vertexArrTail][2][2];
GLfloat bladeThreshold;
clock_t start[MAXTIMER], finish[MAXTIMER];
GLfloat sampleInterval;
GLfloat fadeInterval;
GLfloat orthoLeft;
GLfloat orthoRight;
GLfloat orthoBottom;
GLfloat orthoUp;
void init(void);
void calcSideVertex(GLfloat *startVertex, GLfloat *endVertex, GLfloat returnSideVertex[][2], GLfloat sideWidth, GLfloat end2StartRatio);
void vertexSampling();
GLint isTimeUp(GLint timerFlag, GLfloat timeInterval);
void vertexFading(void );
void recalculateBladeWidth(void );
};
#endif
#include "stdafx.h"
#include "Blade.h"
#include
#include
//#include
#include
//#include
Blade::Blade() { winWidth = 0; winHeight = 0; mousePosX = 0; mousePosY = 0; vertexArrStartPos = 0; //vertexArrEndPos = 0; pointCount = 0; drawFlag = 0; mouseDownFlag = 0; sampleInterval = 0.015f; fadeInterval = 0.02f; bladeThreshold = 0.032f; init(); } Blade::~Blade() {} void Blade::calcSideVertex(GLfloat *startVertex, GLfloat *endVertex, GLfloat returnSideVertex[][2], GLfloat sideWidth, GLfloat end2StartRatio) { GLfloat tmpAngle = 0.0; GLfloat tmpVertex[2] = {0.0f, 0.0f}; GLfloat tmpSideVertex[2][2] = {{0.0f, 0.0f}, {0.0f, 0.0f}}; GLfloat tmpResult = 0.0; tmpAngle = atan((endVertex[1] - startVertex[1])/(endVertex[0] - startVertex[0])); tmpVertex[0] = endVertex[0]-(endVertex[0]-startVertex[0])*end2StartRatio; tmpVertex[1] = endVertex[1]-(endVertex[1]-startVertex[1])*end2StartRatio; if (endVertex[0] > startVertex[0]) { tmpSideVertex[0][0] = tmpVertex[0] + (sideWidth * sin(tmpAngle)); tmpSideVertex[0][1] = tmpVertex[1] - (sideWidth * cos(tmpAngle)); tmpSideVertex[1][0] = tmpVertex[0] - (sideWidth * sin(tmpAngle)); tmpSideVertex[1][1] = tmpVertex[1] + (sideWidth * cos(tmpAngle)); } else { tmpSideVertex[0][0] = tmpVertex[0] - (sideWidth * sin(tmpAngle)); tmpSideVertex[0][1] = tmpVertex[1] + (sideWidth * cos(tmpAngle)); tmpSideVertex[1][0] = tmpVertex[0] + (sideWidth * sin(tmpAngle)); tmpSideVertex[1][1] = tmpVertex[1] - (sideWidth * cos(tmpAngle)); } //判断点在向量的左边还是右边 tmpResult = (startVertex[0] - tmpSideVertex[0][0])*(endVertex[1] - tmpSideVertex[0][1]) - (startVertex[1] - tmpSideVertex[0][1])*(endVertex[0] - tmpSideVertex[0][0]); if (tmpResult > 0.0f) { returnSideVertex[0][0] = tmpSideVertex[1][0]; returnSideVertex[0][1] = tmpSideVertex[1][1]; returnSideVertex[1][0] = tmpSideVertex[0][0]; returnSideVertex[1][1] = tmpSideVertex[0][1]; } else { returnSideVertex[0][0] = tmpSideVertex[0][0]; returnSideVertex[0][1] = tmpSideVertex[0][1]; returnSideVertex[1][0] = tmpSideVertex[1][0]; returnSideVertex[1][1] = tmpSideVertex[1][1]; } } void Blade::init(void) { int i = 0; for (i = 0; i < vertexArrTail; i++) { bodyVertex[i][0] = 0.0f; bodyVertex[i][1] = 0.0f; uniformSideVertex[i][0][0] = 0.0f; uniformSideVertex[i][0][1] = 0.0f; uniformSideVertex[i][1][0] = 0.0f; uniformSideVertex[i][1][1] = 0.0f; outerSideVertex[i][0][0] = 0.0f; outerSideVertex[i][0][1] = 0.0f; outerSideVertex[i][1][0] = 0.0f; outerSideVertex[i][1][1] = 0.0f; innerSideVertex[i][0][0] = 0.0f; innerSideVertex[i][0][1] = 0.0f; innerSideVertex[i][1][0] = 0.0f; innerSideVertex[i][1][1] = 0.0f; } } void Blade::vertexSampling() { int tmpIndex1 = 0, tmpIndex2 = 0; GLfloat uniformX = 0.0f, uniformY = 0.0f; GLfloat realX = 0.0f, realY = 0.0f; drawFlag = 0; pointCount++; uniformX = (GLfloat)mousePosX / (GLfloat)winWidth; uniformY = (GLfloat)(winHeight - mousePosY) / (GLfloat)winHeight; realX = uniformX*(orthoRight - orthoLeft) + orthoLeft; realY = uniformY*(orthoUp - orthoBottom) + orthoBottom; if (pointCount == 0) { bodyVertex[vertexArrStartPos][0] = realX; bodyVertex[vertexArrStartPos][1] = realY; } else { tmpIndex1 = (vertexArrStartPos + pointCount - 1)%vertexArrTail; tmpIndex2 = (tmpIndex1 + 1)%vertexArrTail; bodyVertex[tmpIndex2][0] = realX; bodyVertex[tmpIndex2][1] = realY; calcSideVertex(bodyVertex[tmpIndex1], bodyVertex[tmpIndex2], uniformSideVertex[tmpIndex2], bladeThreshold, 0.4); } if (pointCount >= 3) drawFlag = 1; //vertexArrEndPos++; //if (vertexArrEndPos >= vertexArrTail) // vertexArrEndPos -= vertexArrTail; } GLint Blade::isTimeUp(GLint timerFlag, GLfloat timeInterval) { double duration = 0.0; finish[timerFlag] = clock(); duration = (double)(finish[timerFlag] - start[timerFlag]) / CLOCKS_PER_SEC; if (duration >= timeInterval) { start[timerFlag] = clock(); return 1; } return 0; } void Blade::vertexFading() { vertexArrStartPos++; if (vertexArrStartPos >= vertexArrTail) vertexArrStartPos -= vertexArrTail; pointCount--; if (pointCount <= 2) drawFlag = 0; } void Blade::recalculateBladeWidth(void ) { int i = 0; int tmpIndex = 0; GLfloat ratio = 0.0f; GLfloat tmp[4] = {0.0f, 0.0f, 0.0f, 0.0f}; //reclaculate the blade width for (i = 1; i < pointCount - 1; i++) { tmpIndex = (vertexArrStartPos + i)%vertexArrTail; tmp[0] = uniformSideVertex[tmpIndex][0][0] + uniformSideVertex[tmpIndex][1][0]; tmp[1] = uniformSideVertex[tmpIndex][0][0] - uniformSideVertex[tmpIndex][1][0]; tmp[2] = uniformSideVertex[tmpIndex][0][1] + uniformSideVertex[tmpIndex][1][1]; tmp[3] = uniformSideVertex[tmpIndex][0][1] - uniformSideVertex[tmpIndex][1][1]; if (i == (pointCount-2)) ratio = 1.0; else ratio = (GLfloat)i/(GLfloat)pointCount; outerSideVertex[tmpIndex][0][0] = 0.5*(tmp[0] + ratio*tmp[1]); outerSideVertex[tmpIndex][0][1] = 0.5*(tmp[2] + ratio*tmp[3]); outerSideVertex[tmpIndex][1][0] = 0.5*(tmp[0] - ratio*tmp[1]); outerSideVertex[tmpIndex][1][1] = 0.5*(tmp[2] - ratio*tmp[3]); innerSideVertex[tmpIndex][0][0] = 0.5*(tmp[0] + ratio*2.0/3.0*tmp[1]); innerSideVertex[tmpIndex][0][1] = 0.5*(tmp[2] + ratio*2.0/3.0*tmp[3]); innerSideVertex[tmpIndex][1][0] = 0.5*(tmp[0] - ratio*2.0/3.0*tmp[1]); innerSideVertex[tmpIndex][1][1] = 0.5*(tmp[2] - ratio*2.0/3.0*tmp[3]); } } void Blade::drawBlade() { int i = 0; //printf("%d\n", pointCount); //printf("%d\n", vertexArrStartPos); //printf("Flag:%d\n\n", drawFlag); if (drawFlag == 0){ return; } /*****--------------------------------------*****/ //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //glPolygonMode(GL_FRONT, GL_LINE); /*****--------------------------------------*****/ //draw the outer blade glColor4f(0.2f, 0.2f, 0.9f, 0.5f); glBegin(GL_POLYGON); glVertex2fv(bodyVertex[vertexArrStartPos]); glVertex2fv(outerSideVertex[(vertexArrStartPos+1)%vertexArrTail][0]); glVertex2fv(outerSideVertex[(vertexArrStartPos+1)%vertexArrTail][1]); glEnd(); for (i = 1; i < pointCount - 2; i++) { glBegin(GL_POLYGON); glVertex2fv(outerSideVertex[(vertexArrStartPos + i)%vertexArrTail][0]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glEnd(); glBegin(GL_POLYGON); glVertex2fv(outerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][1]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glVertex2fv(outerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glEnd(); } glBegin(GL_POLYGON); glVertex2fv(outerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][0]); glVertex2fv(bodyVertex[(vertexArrStartPos + pointCount - 1)%vertexArrTail]); glVertex2fv(outerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][1]); glEnd(); //draw the inner blade glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glBegin(GL_POLYGON); glVertex2fv(bodyVertex[vertexArrStartPos]); glVertex2fv(innerSideVertex[(vertexArrStartPos+1)%vertexArrTail][0]); glVertex2fv(innerSideVertex[(vertexArrStartPos+1)%vertexArrTail][1]); glEnd(); for (i = 1; i < pointCount - 2; i++) { glBegin(GL_POLYGON); glVertex2fv(innerSideVertex[(vertexArrStartPos + i)%vertexArrTail][0]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glEnd(); glBegin(GL_POLYGON); glVertex2fv(innerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][1]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i)%vertexArrTail][1]); glVertex2fv(innerSideVertex[(vertexArrStartPos + i + 1)%vertexArrTail][0]); glEnd(); } glBegin(GL_POLYGON); glVertex2fv(innerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][0]); glVertex2fv(bodyVertex[(vertexArrStartPos + pointCount - 1)%vertexArrTail]); glVertex2fv(innerSideVertex[(vertexArrStartPos + pointCount - 2)%vertexArrTail][1]); glEnd(); } void Blade::sampleFadeBlade(void) { if (mouseDownFlag == 1) { sampleInterval = (pointCount <= 2 ? 0.005 : 0.015); if (isTimeUp(sampleTimerFlag, sampleInterval) == 1) { vertexSampling(); recalculateBladeWidth(); glutPostRedisplay(); } } if (pointCount > 0) { fadeInterval = (pointCount >= POINTTHRESHOLD ? 0.0 : 0.016); fadeInterval = (mouseDownFlag == 0 ? 0.0 : fadeInterval); //printf("%f\n", fadeInterval); if (isTimeUp(fadeTimerFlag, fadeInterval) == 1) { vertexFading(); recalculateBladeWidth(); glutPostRedisplay(); } } } void Blade::mouse2BladeState(int btn, int state, int x, int y) { if (btn == GLUT_LEFT_BUTTON) { if (state == GLUT_DOWN) { mousePosX = x; mousePosY = y; mouseDownFlag = 1; start[sampleTimerFlag] = clock(); start[fadeTimerFlag] = clock(); pointCount = 0; } else if (state == GLUT_UP) { mouseDownFlag = 0; } } } void Blade::recordOrthoData(GLfloat left, GLfloat right, GLfloat bottom, GLfloat up) { orthoLeft = left; orthoRight = right; orthoBottom = bottom; orthoUp = up; }
#include "stdafx.h"
#include
#include
#include "Blade.h"
#ifndef _LINUX_
#include
void mySleep(int millisecond) {Sleep(millisecond);};
#else
#include
void mySleep(int millisecond) {sleep((float)millisecond/1000.0);};
#endif
Blade myBlade;
const int sleepTime = 1;
void display(void )
{
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
myBlade.drawBlade();
glutSwapBuffers();
}
void mouseButton(int btn, int state, int x, int y)
{
myBlade.mouse2BladeState(btn, state, x, y);
//if (btn == GLUT_RIGHT_BUTTON)
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
void reshape(int w, int h)
{
myBlade.winWidth = w;
myBlade.winHeight = h;
}
void mouseMove(int x, int y)
{
myBlade.mousePosX = x;
myBlade.mousePosY = y;
}
void idle(void)
{
mySleep(sleepTime);
myBlade.sampleFadeBlade();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(800, 600);
glutCreateWindow("Ninjia blade");
gluOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);
myBlade.recordOrthoData(0.0f, 1.0f, 0.0f, 1.0f);
//gluOrtho2D(0.0f, -1.0f, -2.0f, 1.0f);
//myBlade.recordOrthoData(0.0f, -1.0f, -2.0f, 1.0f);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glutDisplayFunc(&display);
glutMouseFunc(&mouseButton);
glutReshapeFunc(&reshape);
glutMotionFunc(&mouseMove);
glutIdleFunc(&idle);
glutMainLoop();
return 0;
}