Доброго времени суток. Моделируется процесс обработки детали на токарном станке. Заготовка является сплошным телом цилиндрической формы. Необходимо показать процесс снятия припуска, т.е. очередного слоя, подлежащего удалению. Сразу отмечу, что не имею опыта работы с OpenGL, поэтому буду благодарен любой критике касательно логики программы. Мой алгоритм такой:
1) Заполнил в цикле заготовку как сплошное тело, т.е. в буквальном смысле винтовой линией чертил вершину, установив для нее (вершины) крупный размер (glPointSize). Естественно, уменьшал радиус винтовой линии после каждого прохода. Весь этот цикл писал в буфер трафарета, как бы заполняя всю сплошную область единичками.
2) Снял припуск, т.е. прошел винтовой линией в цикле часть заготовки, заполняя данную область в буфере трафарета двойками. Таким образом, получил в буфере трафарета обработанную деталь (т.е. то, что осталось от заготовки), заполненную единицами, а слой припуска - двойками.
Теперь вопрос. Как показать область в буфере трафарета, заполненную единицами?
Понятно, что очищал буферы цвета и глубины и настраивал вывод glStencilFunc(GL_EQUAL, 1, 255). Пробовал проходить винтовой линией в цикле, как будто заново рисуя заготовку, надеясь, что останется область, где только единицы. Однако облать, заполненная двойками, не позволяет просматривать то, что осталось за ней, т.е. часть области, заполненную единицами. Экспериментировал с буфером глубины, однако результата не добился.
Код:
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include "gl\gl.h"
#include "gl\glu.h"
#include "gl\glut.h"
#include "gl\glaux.h"
// Определяется константа со значением PI
#define GL_PI 3.1415f
void SetupRC (void)
{
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClearStencil(0);
}
// Вызывается для рисования сцены
void RenderScene (void)
{
GLfloat x, y, z, angle; // Здесь хранятся координаты и углы
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glPushMatrix ();
glRotatef ( 45.0, 1.0f, 0.0f, 0.0f );
glRotatef ( 60.0, 0.0f, 1.0f, 0.0f );
glTranslated (0, 0, -70);
glEnable(GL_POINT_SMOOTH);
glEnable( GL_STENCIL_TEST ); // разрешаем тест трафарета
glStencilFunc( GL_ALWAYS, 1, 0 );
glStencilOp( GL_KEEP, GL_REPLACE, GL_REPLACE );
glColor4f( 0.75f, 0.75f, 0.75f, 1.0f );
GLfloat a = 120.0f, r = 30.0f, l = 25.0f, ang = 0.0f;
glPointSize(10.0);
z = 0.0f;
angle = 0.0f;
while ( r > 0 ) {
while ( z <= a ) {
x = ( r ) * sin( angle );
y = ( r ) * cos( angle );
glBegin( GL_POINTS );
glVertex3f( x, y, z );
glEnd();
angle += 0.017f;
// торец 1
if ( angle <= 2*GL_PI ) {
z = 0.0f;
continue;
}
z = 0.3 * angle;
// торец 2
if ( z >= a && ang <= 2*GL_PI ) {
z = a;
ang += 0.017f;
continue;
}
}
z = 0.0f;
angle = 0.0f;
ang = 0.0f;
r -= 1.0f;
}
glStencilFunc(GL_ALWAYS, 2, 0);
glStencilOp( GL_KEEP, GL_REPLACE, GL_REPLACE );
glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
// снимаем припуск
z = 0.0f;
angle = 0.0f;
r = 30.0f;
while ( z <= l ) {
x = ( r ) * sin( angle );
y = ( r ) * cos( angle );
glBegin( GL_POINTS );
glVertex3f( x, y, z );
glEnd();
angle += 0.017f;
z = 0.3 * angle;
}
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glStencilFunc(GL_EQUAL, 1, 255);
glColor4f( 0.75f, 0.75f, 0.75f, 1.0f );
a = 120.0f, r = 30.0f, l = 25.0f, ang = 0.0f;
z = 0.0f;
angle = 0.0f;
while ( r > 0 ) {
/*
glDepthFunc( GL_ALWAYS );
//glDepthMask(GL_TRUE);
if ( r == 30.0f ) {
glDepthFunc( GL_NEVER );
//glDepthMask(GL_FALSE);
}; */
while ( z <= a ) {
x = ( r ) * sin( angle );
y = ( r ) * cos( angle );
glBegin( GL_POINTS );
glVertex3f( x, y, z );
glEnd();
angle += 0.017f;
// торец 1
if ( angle <= 2*GL_PI ) {
z = 0.0f;
continue;
}
z = 0.3 * angle;
// торец 2
if ( z >= a && ang <= 2*GL_PI ) {
z = a;
ang += 0.017f;
continue;
}
}
z = 0.0f;
angle = 0.0f;
ang = 0.0f;
r -= 1.0f;
}
glutSwapBuffers();
glPopMatrix();
}
//---------------------------------------------------------------------//
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat nRange = 100.0f;
if (h == 0) {
h = 1;
}
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h) {
glOrtho (-nRange, nRange, -nRange * h / w, nRange * h / w,
-nRange, nRange);
}
else
glOrtho (-nRange * w / h, nRange * w / h, -nRange, nRange,
-nRange, nRange);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//--------------------------------------------------------------------//
void Keyboard(unsigned char key, int x, int y)
{
#define ESCAPE '\033'
if (key == ESCAPE)
exit(0);
}
//-------------------------------------------------------------------//
void main(int argc, char* argv[])
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_STENCIL | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(380, 170);
glutCreateWindow("Process");
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutKeyboardFunc(Keyboard);
SetupRC ();
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}