⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csg.cpp

📁 一个演示正二十面体与球的(OR)组合(AND)组合(SUB)组合等的工程,编译,运行都需要glut
💻 CPP
字号:
/*   *  Constructive Solid Geometry program based on information from the *  Advanced OpenGL Rendering course at SIGGRAPH '96 by David Blythe and *  Tom McReynolds.  Click right mouse button for menu. * *  author: Nate Robins *  email: ndr@pobox.com *  www: http://www.pobox.com/~ndr *//* includes */#include <GL/glut.h>#include <math.h>#include "trackball.h"////////////////////////////////////
int spinning = 0, moving = 0;
int beginx, beginy;
int W = 800, H = 800;
float curquat[4];
float lastquat[4];
int scaling;
float scalefactor = 1.0;

void
recalcModelView(void)
{
  GLfloat m[4][4];

  glPopMatrix();
  glPushMatrix();
  build_rotmatrix(m, curquat);
  glMultMatrixf(&m[0][0]);
  //if (scalefactor == 1.0) {
//    glEnable(GL_NORMALIZE);
//  } else {
 ///   glEnable(GL_NORMALIZE);
 // }
}
void tbMouse(int button, int state, int x, int y )
{  
 	
  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
    spinning = 0;
    glutIdleFunc(0);
    moving = 1;
    beginx = x;
    beginy = y;
    if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
      scaling = 1;
    } else {
      scaling = 0;
    }
  }
  if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
    moving = 0;
  }
}
void
animate(void)
{
  add_quats(lastquat, curquat, curquat);
  glutPostRedisplay();
}

/***************************************** myGlutMotion() **********/

void tbMotion(int x, int y )
{
  if (scaling) {
    scalefactor = scalefactor * (1.0 + (((float) (beginy - y)) / H));
    beginx = x;
    beginy = y;
    glutPostRedisplay();
    return;
  }
  if (moving) {
    trackball(lastquat,
      (2.0 * beginx - W) / W,
      (H - 2.0 * beginy) / H,
      (2.0 * x - W) / W,
      (H - 2.0 * y) / H
      );
    beginx = x;
    beginy = y;
    spinning = 1;
    glutIdleFunc(animate);
  }

	
  //glutPostRedisplay();
}
/////////////////////////////////////* defines */#define SPHERE 1#define CONE   2#define CUBE   3/* csgOperation *  types of CSG operations  */typedef enum {    CSG_A,    CSG_B,    CSG_A_OR_B,    CSG_A_AND_B,    CSG_A_SUB_B,    CSG_B_SUB_A} csgOperation;/* globals */GLint Width;GLint Height;GLfloat zoom = 0.0;GLboolean cube_picked   = GL_FALSE;GLboolean sphere_picked = GL_FALSE;GLboolean cone_picked   = GL_FALSE;GLboolean selection     = GL_FALSE;	/* rendering to selection buffer */#define SELECT_BUFFER 32GLuint select_buffer[SELECT_BUFFER];	/* selection buffer */GLfloat cone_x = 0.0;GLfloat cone_y = 0.0;GLfloat cone_z = 0.0;GLfloat cube_x = 0.0;GLfloat cube_y = 0.0;GLfloat cube_z = 0.0;GLfloat sphere_x = 0.0;GLfloat sphere_y = 0.0;GLfloat sphere_z = 0.0;GLint mouse_state = -1;GLint mouse_button = -1;csgOperation Op = CSG_A_OR_B;void (*A)(void);void (*B)(void);/* functions *//* one() *  draw a single object */void one(void(*a)(void)){  glEnable(GL_DEPTH_TEST);  a();  glDisable(GL_DEPTH_TEST);}/* or() *  boolean A or B (draw wherever A or B) *  algorithm: simple, just draw both with depth test enabled */void or(void(*a)(void), void(*b)()){    glPushAttrib(GL_ALL_ATTRIB_BITS);  /* TODO - should just push depth */    glEnable(GL_DEPTH_TEST);    a(); b();    glPopAttrib();}/* inside() *  sets stencil buffer to show the part of A *  (front or back face according to 'face') *  that is inside of B. */void inside(void(*a)(void), void(*b)(void), GLenum face, GLenum test){    /* draw A into depth buffer, but not into color buffer */    glEnable(GL_DEPTH_TEST);    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);    glCullFace(face);    a();        /* use stencil buffer to find the parts of A that are inside of B     * by first incrementing the stencil buffer wherever B's front faces     * are...     */    glDepthMask(GL_FALSE);    glEnable(GL_STENCIL_TEST);    glStencilFunc(GL_ALWAYS, 0, 0);    glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);    glCullFace(GL_BACK);    b();    /* ...then decrement the stencil buffer wherever B's back faces are */    glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);    glCullFace(GL_FRONT);    b();    /* now draw the part of A that is inside of B */    glDepthMask(GL_TRUE);    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);    glStencilFunc(test, 0, 1);    glDisable(GL_DEPTH_TEST);    glCullFace(face);    a();    /* reset stencil test */    glDisable(GL_STENCIL_TEST);}/* fixup() *  fixes up the depth buffer with A's depth values */void fixup(void(*a)(void)){    /* fix up the depth buffer */    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);    glEnable(GL_DEPTH_TEST);    glDisable(GL_STENCIL_TEST);    glDepthFunc(GL_ALWAYS);    a();    /* reset depth func */    glDepthFunc(GL_LESS);}/* and() *  boolean A and B (draw wherever A intersects B) *  algorithm: find where A is inside B, then find where *             B is inside A */void and(void(*a)(void), void(*b)(void)){    inside(a, b, GL_BACK, GL_NOTEQUAL);#if 1  /* set to 0 for faster, but incorrect results */    fixup(b);#endif    inside(b, a, GL_BACK, GL_NOTEQUAL);}/* * sub() *  boolean A subtract B (draw wherever A is and B is NOT) *  algorithm: find where a is inside B, then find where *             the BACK faces of B are NOT in A */void sub(void(*a)(void), void(*b)(void)){    inside(a, b, GL_FRONT, GL_NOTEQUAL);#if 1  /* set to 0 for faster, but incorrect results */    fixup(b);#endif    inside(b, a, GL_BACK, GL_EQUAL);}/* sphere() *  draw a yellow sphere */void sphere(void){    glLoadName(2);    glPushMatrix();    glTranslatef(sphere_x, sphere_y, sphere_z);    glColor3f(1.0, 1.0, 0.0);
    glutSolidSphere(0.85, 46, 46);    glPopMatrix();}/* cube() *  draw a red cube */void cube(void){    glLoadName(1);    glPushMatrix();    glTranslatef(cube_x, cube_y, cube_z);    glColor3f(1.0, 0.0, 0.0);
	glRotatef(58.0, 1.0, 0.0, 0.0);    glutSolidIcosahedron();    glPopMatrix();}/* cone() *  draw a green cone */void cone(void){    glLoadName(3);    glPushMatrix();    glTranslatef(cone_x, cone_y, cone_z);    glColor3f(0.0, 1.0, 0.0);    glTranslatef(0.0, 0.0, -1.0);    glutSolidCone(0.50, 3.0, 26, 26);    glRotatef(180.0, 1.0, 0.0, 0.0);    glutSolidCone(0.50, 0.0, 26, 1);    glPopMatrix();}void init(void){    GLfloat lightposition[] = { -9.0, 9.0, 9.0, 0.0 };    //tbInit(GLUT_LEFT_BUTTON);    glSelectBuffer(SELECT_BUFFER, select_buffer);    glDepthFunc(GL_LESS);    glEnable(GL_DEPTH_TEST);    glEnable(GL_LIGHT0);    glEnable(GL_LIGHTING);    glLightfv(GL_LIGHT0, GL_POSITION, lightposition);    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);    glEnable(GL_COLOR_MATERIAL);    glEnable(GL_CULL_FACE);    glClearColor(0.0, 0.0, 1.0, 0.0);}void reshape(int width, int height){    Width = width;    Height = height;    //tbReshape(width, height);    glViewport(0, 0, width, height);        glMatrixMode(GL_PROJECTION);    glLoadIdentity();
	if(width<=height)
	    glFrustum(-0.50, 0.50, -0.50*height/width, 
	      0.50*height/width, 74, 256);
	else
	    glFrustum(-0.50*width/height, 0.50*width/height, -0.50, 
	      0.50, 74, 256);    glMatrixMode(GL_MODELVIEW);    glLoadIdentity();    glTranslatef(0.0, 0.0, -200.0 + zoom);}void display(void){  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);  recalcModelView();  glPushMatrix();  //tbMatrix();    switch(Op) {  case CSG_A:    one(A);    break;  case CSG_B:    one(B);    break;  case CSG_A_OR_B:    or(A, B);    break;  case CSG_A_AND_B:    and(A, B);    break;  case CSG_A_SUB_B:    sub(A, B);    break;  case CSG_B_SUB_A:    sub(B, A);    break;  }    glPopMatrix();    if (!selection)    glutSwapBuffers();}GLuintpick(int x, int y){  GLuint    i, hits, num_names, picked;  GLuint*   p;  GLboolean save;  GLuint    depth = (GLuint)-1;  GLint     viewport[4];  /* get the current viewport parameters */  glGetIntegerv(GL_VIEWPORT, viewport);  /* set the render mode to selection */  glRenderMode(GL_SELECT);  selection = GL_TRUE;  glInitNames();  glPushName(0);  /* setup a picking matrix and render into selection buffer */  glMatrixMode(GL_PROJECTION);  glPushMatrix();  glLoadIdentity();  gluPickMatrix(x, viewport[3] - y, 5.0, 5.0, viewport);  glFrustum(-3.0, 3.0, -3.0, 3.0, 64, 256);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  glTranslatef(0.0, 0.0, -200.0 + zoom);  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);  glPushMatrix();  //tbMatrix();  or(A, B);  glPopMatrix();  glMatrixMode(GL_PROJECTION);  glPopMatrix();  glMatrixMode(GL_MODELVIEW);  hits = glRenderMode(GL_RENDER);  selection = GL_FALSE;  p = select_buffer;  picked = 0;  for (i = 0; i < hits; i++) {    save = GL_FALSE;    num_names = *p;			/* number of names in this hit */    p++;    if (*p <= depth) {			/* check the 1st depth value */      depth = *p;      save = GL_TRUE;    }    p++;    if (*p <= depth) {			/* check the 2nd depth value */      depth = *p;      save = GL_TRUE;    }    p++;    if (save)      picked = *p;    p += num_names;			/* skip over the rest of the names */  }  return picked;}void keyboard(unsigned char key, int x, int y){    switch(key) {    case 'c':	if(A == cube && B == sphere) {	    A = sphere;	    B = cone;	} else if(A == sphere && B == cone) {	    A = cone;	    B = cube;	} else { /* if(A == cone && B = cube) */	    A = cube;	    B = sphere;	}	break;    case 'a':	Op = CSG_A;	break;    case 'b':	Op = CSG_B;	break;    case '|':	Op = CSG_A_OR_B;	break;    case '&':	Op = CSG_A_AND_B;	break;    case '-':	Op = CSG_A_SUB_B;	break;    case '_':	Op = CSG_B_SUB_A;	break;    case 'z':	zoom -= 6.0;	reshape(Width, Height);	break;    case 'Z':	zoom += 6.0;	reshape(Width, Height);	break;    case 27:	exit(0);	break;    case '\r':	break;    default:	return;    }    glutPostRedisplay();}voidmouse(int button, int state, int x, int y){  mouse_state = state;  mouse_button = button;  tbMouse(button, state, x, y);  if (button == GLUT_MIDDLE_BUTTON) {    switch (pick(x, y)) {    case 1:      cube_picked = GL_TRUE;      sphere_picked = GL_FALSE;      cone_picked = GL_FALSE;      break;          case 2:      sphere_picked = GL_TRUE;      cube_picked = GL_FALSE;      cone_picked = GL_FALSE;      break;          case 3:      cone_picked = GL_TRUE;      sphere_picked = GL_FALSE;      cube_picked = GL_FALSE;      break;          default:      sphere_picked = GL_FALSE;      cube_picked = GL_FALSE;      cone_picked = GL_FALSE;      break;    }  }  glutPostRedisplay();}GLvoidcross(GLfloat* u, GLfloat* v, GLfloat* n){  /* compute the cross product (u x v for right-handed [ccw]) */  n[0] = u[1] * v[2] - u[2] * v[1];  n[1] = u[2] * v[0] - u[0] * v[2];  n[2] = u[0] * v[1] - u[1] * v[0];}GLfloatnormalize(GLfloat* n){  GLfloat l;  /* normalize */  l = (GLfloat)sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);  n[0] /= l;  n[1] /= l;  n[2] /= l;  return l;}voidmotion(int x, int y){  GLdouble model[4*4];  GLdouble proj[4*4];  GLint view[4];  GLdouble pan_x, pan_y, pan_z;  tbMotion(x, y);  if (mouse_state == GLUT_DOWN && mouse_button == GLUT_MIDDLE_BUTTON) {    glGetDoublev(GL_MODELVIEW_MATRIX, model);    glGetDoublev(GL_PROJECTION_MATRIX, proj);    glGetIntegerv(GL_VIEWPORT, view);    gluProject((GLdouble)x, (GLdouble)y, 0.0,		 model, proj, view,		 &pan_x, &pan_y, &pan_z);    gluUnProject((GLdouble)x, (GLdouble)y, pan_z,		 model, proj, view,		 &pan_x, &pan_y, &pan_z);    pan_y = -pan_y;    if (sphere_picked) {      sphere_x = pan_x;      sphere_y = pan_y;      sphere_z = pan_z;    } else if (cone_picked) {      cone_x = pan_x;      cone_y = pan_y;      cone_z = pan_z;    } else if (cube_picked) {      cube_x = pan_x;      cube_y = pan_y;      cube_z = pan_z;    }  }  glutPostRedisplay();}void menu(int item){    keyboard((unsigned char)item, 0, 0);}void main(int argc, char** argv){    int ops, zoom;    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);    glutInitWindowSize(400,400);
    glutInitWindowPosition(200,100);    glutCreateWindow("CSG Operations Demo");    trackball(curquat, 0.0, 0.0, 0.0, 0.0);    glutDisplayFunc(display);    glutReshapeFunc(reshape);    glutKeyboardFunc(keyboard);    glutMouseFunc(mouse);    glutMotionFunc(motion);    ops = glutCreateMenu(menu);    glutAddMenuEntry("A only          (a)", 'a');    glutAddMenuEntry("B only          (b)", 'b');    glutAddMenuEntry("A or B          (|)", '|');    glutAddMenuEntry("A and B         (&)", '&');    glutAddMenuEntry("A sub B         (-)", '-');    glutAddMenuEntry("B sub A         (_)", '_');    zoom = glutCreateMenu(menu);    glutAddMenuEntry("Zoom decrease   (z)", 'z');    glutAddMenuEntry("Zoom increase   (Z)", 'Z');    glutCreateMenu(menu);    glutAddMenuEntry("CSG Operations Demo", '\0');    glutAddMenuEntry("                   ", '\0');    glutAddSubMenu(  "Operations         ", ops);    glutAddSubMenu(  "Zoom               ", zoom);    glutAddMenuEntry("                   ", '\0');    glutAddMenuEntry("Change shapes   (c)", 'c');    glutAddMenuEntry("                   ", '\0');    glutAddMenuEntry("Quit          (Esc)", '\033');    glutAttachMenu(GLUT_RIGHT_BUTTON);    init();    A = cube;    B = sphere;    glutMainLoop();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -