/*
* 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 32
GLuint 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();
}
GLuint
pick(int x, int y)
{
GLuint i, hits, num_names, picked;
GLuint* p;
GLboolean save;
GLuint depth = (GLuint)-1;
GLint viewport[4];
/* get the current
csg.rar_csg_sub
版权申诉
146 浏览量
2022-09-21
03:41:15
上传
评论
收藏 78KB RAR 举报
钱亚锋
- 粉丝: 90
- 资源: 1万+