//////////////////////////////////////////////////////////////////////////
//
// COMPUTER GRAPHICS USING OpenGL (Third Edition)
//
// Case 3.2.cpp (Cohen-Sutherland)
//
// Written by Guangzheng Fei
// Creation date: Wed. April. 6, 2011, 0:00
//
// All Rights Reserved.
//
// Cohen-Sutherland 裁剪算法;
//////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include "glut.h"
#include <cmath>
#include <time.h>
const double screenWidth = 640.0;
const double screenHeight = 480.0;
// GLintPoint
typedef struct
{
GLint x, y;
}GLintPoint;
// RealRect
typedef struct
{
GLint l, r, b, t;
}RealRect;
GLintPoint P1, P2;
RealRect W;
bool mode;
////////////////////////////////////setWindow/////////////////////////////
void setWindow(GLdouble left, GLdouble right, GLdouble buttom, GLdouble top)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(left, right, buttom, top);
}
////////////////////////////////////setViewport///////////////////////////
void setViewport(GLint left, GLint right, GLint bottom, GLint top)
{
glViewport(left, bottom, right - left, top - bottom);
}
////////////////////////////////////myInit/////////////////////////////////
void myInit(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0,1.0,1.0,0.0);
glColor3f(0.0,0.0,0.0);
glLineWidth(2.0);
}
///////////////////////////////////setCode/////////////////////////////////
void setCode(GLintPoint p, unsigned char &code)
{
code = 0;
if(p.x<W.l) code|=8;
if(p.y>W.t) code|=4;
if(p.x>W.r) code|=2;
if(p.y<W.b) code|=1;
}
///////////////////////////////////ChopLine////////////////////////////////
void ChopLine(GLintPoint &p, unsigned char code, float dely, float delx)
{
if (code & 8)// 左边;
{
p.y+=(GLint)((W.l-p.x) * dely/delx);
p.x = W.l;
}
else if (code & 2)// 右边;
{
p.y+=(GLint)((W.r-p.x) * dely/delx);
p.x = W.r;
}
else if (code & 1)// 下边;
{
p.x+=(GLint)((W.b-p.y) * delx/dely);
p.y = W.b;
}
else if (code & 4)// 上边;
{
p.x+=(GLint)((W.t-p.y) * delx/dely);
p.y = W.t;
}
}
///////////////////////////////////clipSegment/////////////////////////////
bool clipSegment(GLintPoint &p1, GLintPoint &p2)
{
unsigned char code1, code2;
do
{
setCode(p1,code1);
setCode(p2,code2);
if (!(code1|code2)) return 1; // 完全可见
if (code1&code2) return 0; // 显然不可见
if (code1)
ChopLine(p1,code1,(float)(p2.y-p1.y),(float)(p2.x-p1.x));
else
ChopLine(p2,code2,(float)(p2.y-p1.y),(float)(p2.x-p1.x));
} while (1);
}
///////////////////////////////////myDisplay///////////////////////////////
void myDisplay()
{
GLintPoint
p1 = {(GLint)screenWidth/3, (GLint)screenHeight/3},
p2 = {(GLint)screenWidth*2/3, (GLint)screenHeight*2/3};
RealRect w = {p1.x, p2.x, p1.y, p2.y};
W = w;
srand((unsigned int)time(0));
glClear(GL_COLOR_BUFFER_BIT);
// 以下绘制一个矩形
glBegin(GL_LINE_LOOP);
glVertex2i(W.l, W.b);
glVertex2i(W.l, W.t);
glVertex2i(W.r, W.t);
glVertex2i(W.r, W.b);
glEnd();
p1 = P1; p2 = P2;
if (clipSegment(p1, p2)) // 裁剪后窗口内有可见部分
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES); // 先完整地绘制这条线段
glVertex2i(p1.x, p1.y);
glVertex2i(p2.x, p2.y);
glEnd();
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINES); // 再用覆盖的方式绘制两段不可见线段
glVertex2i(p1.x, p1.y);
glVertex2i(P1.x, P1.y);
glVertex2i(p2.x, p2.y);
glVertex2i(P2.x, P2.y);
glEnd();
}
else // 线段完全不可见
{
glBegin(GL_LINES); // 直接绘制这条原始线段
glVertex2i(P1.x, P1.y);
glVertex2i(P2.x, P2.y);
glEnd();
}
glutSwapBuffers();
}
///////////////////////////////////myMouse////////////////////////////////
void myMouse(GLint button, GLint state, GLint x, GLint y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
P1.x = x;
P1.y = screenHeight - y;
}
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{
mode = !mode;
P2.x = x;
P2.y = screenHeight - y;
}
glutPostRedisplay();
}
///////////////////////////////////myPassiveMouse/////////////////////////
void myPassiveMouse(GLint x, GLint y)
{
if (mode)
{
P2.x = x; P2.y = screenHeight - y;
glutPostRedisplay();
}
}
///////////////////////////////////main///////////////////////////////////
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize((int)screenWidth,(int)screenHeight);
glutInitWindowPosition(100,150);
glutCreateWindow("Cohen-Sutherland");
setWindow(0.0,screenWidth,0.0,screenHeight);//必须在glutCreateWindow之后执行;
myInit();
glutDisplayFunc(myDisplay);
glutMouseFunc(myMouse);
glutPassiveMotionFunc(myPassiveMouse);
glutMainLoop();
}
评论0