#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>
// Глобальные переменные
int WindW, WindH;
int i, frames = 0, time2, elapsedTime;
int isDrawMenu = 0, isDMProc = 0, lab = 3;
int oldx, oldy, mtn = 0;
float mBlend = 0.0;
bool isByTimer = false;
GLfloat alpha = 0.0f, beta = 0.0f, automat = 0.0f;
void timf(int) // Idle function
{
isByTimer = true;
glutTimerFunc(40, timf, 0); // Set up timer for 40ms, about 25 fps
glutPostRedisplay(); // Redraw windows
}
void Reshape(int width, int height) // Reshape function
{
glViewport(0, 0, width, height);
/*glMatrixMode(GL_PROJECTION);
glLoadIdentity();
*/gluOrtho2D(-1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
WindW = width;
WindH = height;
}
void DrawCubes(int ft, float basic)
{
GLfloat diffCoeff [] = {0.2, 0.4, 0.9, 1.0};
GLfloat splrCoeff [] = {1.0, 1.0, 1.0, 1.0};
GLfloat angle = 0.0f;
// Создаем кубики
while (angle <= 360.0)
{
if ( ft )
{
glPushMatrix();
glRotatef(angle + basic, 0.0f, 0.0f, 1.0f);
glTranslatef(0.8f, 0.0f, 1.0f);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffCoeff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, splrCoeff);
glutSolidCube(0.4f * (1.0f - mBlend));
glPopMatrix();
}
glPushMatrix();
glRotatef(angle + basic, 0.0f, 0.0f, 1.0f);
glTranslatef(0.5f, 0.0f, 1.0f);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffCoeff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, splrCoeff);
glutSolidCube(0.4f * (1.0f - mBlend));
glPopMatrix();
angle += 30.0f;
ft = !ft;
}
}
void DrawScene(GLfloat base)
{
glPushMatrix();
glScalef(0.5, 0.5, 0.5);
glRotatef(automat, 1.0f, 1.0f, 1.0f);
glPushMatrix();
glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
DrawCubes(0, base);
glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
DrawCubes(0, base);
glPopMatrix();
glPushMatrix();
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
DrawCubes(0, -base);
glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
DrawCubes(0, -base);
glPopMatrix();
glPopMatrix();
}
void Draw2D(void)
{
float mB = mBlend * mBlend;
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
glLineWidth(2);
glPushMatrix();
glScalef(1.0,mBlend,1.0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(2);
glEnable(GL_POLYGON_STIPPLE);
glPolygonMode(GL_FRONT, GL_FILL);
glColor4f(0.2f, 0.2f, 0.2f, 0.5f * mB);
glRectf(-0.7f, -0.7f, 0.7f, 0.7f);
glColor4f(0.2f, 0.2f, 0.2f, 0.5f * mB);
glRectf(-0.75f, -0.75f, 0.75f, 0.75f);
glDisable(GL_POLYGON_STIPPLE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f * mB);
// Линии, по очереди
glBegin(GL_LINE_STRIP);
glVertex2f(-0.6f, -0.6f);
glVertex2f(-0.1f, -0.6f);
glVertex2f(-0.6f, -0.35f);
glVertex2f(-0.1f, -0.35f);
glVertex2f(-0.6f, -0.1f);
glVertex2f(-0.1f, -0.1f);
glEnd();
// Линии, циклом
glBegin(GL_LINE_LOOP);
glVertex2f(0.6f, -0.6f);
glVertex2f(0.1f, -0.6f);
glVertex2f(0.6f, -0.35f);
glVertex2f(0.1f, -0.35f);
glVertex2f(0.6f, -0.1f);
glVertex2f(0.1f, -0.1f);
glEnd();
// Треугольники
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(0.1f, 0.35f);
glVertex2f(0.2f, 0.1f);
glVertex2f(0.2f, 0.6f);
glVertex2f(0.5f, 0.1f);
glVertex2f(0.5f, 0.6f);
glVertex2f(0.6f, 0.35f);
glEnd();
// Треугольники
glBegin(GL_QUAD_STRIP);
glVertex2f(-0.1f, 0.35f);
glVertex2f(-0.2f, 0.1f);
glVertex2f(-0.2f, 0.6f);
glVertex2f(-0.5f, 0.1f);
glVertex2f(-0.5f, 0.6f);
glVertex2f(-0.6f, 0.35f);
glEnd();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glPopMatrix();
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
void Draw(void) // Window redraw function
{
GLfloat whiteColor [] = {1.0, 1.0, 1.0, 1.0};
isByTimer = false;
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glColor3f (0, 1, 0);
GLfloat light1 [] = {-10.0, -10.0, -10.0, 1.0};
glLightfv(GL_LIGHT1, GL_POSITION, light1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, whiteColor);
glEnable(GL_LIGHT1);
// Крутим шестеренки
glPushMatrix();
glRotatef(alpha, 1.0f, 0.0f, 0.0f);
glRotatef(beta , 0.0f, 1.0f, 0.0f);
DrawScene(automat);
glPopMatrix();
// Отключаем свет и 3D
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
if ( !mtn ) {
automat += 1;
if (automat > 359) automat = 0;
}
// Далее рисуем Меню
if ( isDrawMenu || mBlend > 0.0 ) Draw2D();
// Выводим FPS
frames++;
if(!(frames % 5))
{
int time2 = glutGet( GLUT_ELAPSED_TIME );
char str[256];
float fps = (float) frames / (0.001 *(time2 - elapsedTime));
elapsedTime = time2;
frames = 0;
sprintf ( str, "Лабораторная %d (Сидристый Ст. А. 2341): FPS = %5.2f", lab, fps );
glutSetWindowTitle( str );
}
if( mBlend >= 1.0 && isDrawMenu ) isDMProc = 0;
if( mBlend <= 0.0 && !isDrawMenu ) isDMProc = 0;
if( isDMProc ) mBlend += ( isDrawMenu ? 1.0 : (-1.0) ) * 0.16333;
glFlush();
}
void kbFunc(unsigned char key, int x, int y)
{
if ( key == ' ' ) {
isDrawMenu = (isDrawMenu == 0 ? 1 : 0 );
lab = (isDrawMenu == 0 ? 3 : 1 );
//mBlend = float(!isDrawMenu);
isDMProc = 1;
}
}
void motion (int x, int y)
{
if(mtn)
{
alpha += (oldy - y) / 3.0;
beta += (oldx - x) / 3.0;
oldy = y;
oldx = x;
}
}
void mouse (int button, int state, int x, int y)
{
if ( button == GLUT_LEFT_BUTTON )
{
if (!mtn) { oldx = x; oldy = y; }
mtn = ( state == GLUT_DOWN );
}
}
int main(int argc, char *argv[])
{
WindW = 400;
WindH = 400;
glutInit(&argc, argv);
glutInitWindowSize(WindW, WindH);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
(void)glutCreateWindow("Лабораторная 1");
glutReshapeFunc ( Reshape ); // Set up reshape function
glutDisplayFunc ( Draw ); // Set up redisplay function
glutTimerFunc ( 40, timf, 0 ); // Set up timer for 40ms, about 25 fps
glutMouseFunc ( mouse );
glutMotionFunc ( motion );
glutKeyboardFunc ( kbFunc );
glClearColor(0, 0, 0, 0);
isByTimer = true;
glutMainLoop();
return 0;
}
Подозрительно низкая скорость... OpenGL
Правда, на каждой отрисовке перегенерирую всю сцену, но я понять не могу, как сделать 4 крутящиеся шестеренки без полной перегенерации...
Итак... Крутится 2 шестеренки, сгенерированные из кубиков (через 30 градусов по внутреннему диаметру, и через 60 по внешнему). И так 4 штуки. Все поворачиваю / двигаю /меняю через glScalef, glRotatef, glTransformf.
В полноэкранном режиме FPS равен 3 (!!!), в мелком окошке 200х200 доходит до 20. Но, понятно что что-то не так... Тормоза дикие... Почему, не понимаю... Весь код ниже. Помогите glutSolidTeapot'у...... Плиз...
Тут прога, крутит шестерни (физики нет). Если нажать пробел, выскочит 2D окошко.
И еще вопрос: как сделать так чтобы наложить друг на друга несколько полупрозрачных объектов? А то я рисую два, нормально. На третьем траблы. (Белые линии в окне при появлении / сокрытии)
Заранее ОЧЕНЬ благодарен...
Код:
1.Зачем тебе GLUT - тебе нужна переносимость на разные ОСи? Если пишешь под
конктрктную ОС используй её API.
2. Не увидел у тебя двоной буфферизации (может плохо смотрел) - ну и следственно: нету синхронизации с частотой монитора (если время кадра не кратно обновлению монитора - это еще тормоза (только при двойно буфферизации - некоторые функции переключения буфферов ждут
обновления экрана)).
3. Для визуализации одинаковых шестерёнок используй списки отображения (Dispaly Lists).
----------------------------------------------
По какому из этих пунктов написать подробней?
По двойной буферизации... Не понял... А как тогда надо?
GLUT двоиная буфферизация так и задаётся, но
я невижу где у тебя буфферы переключаются.
GLUT сам выполняет функцию SwapBuffers()?
-----------------------------------------------
У тебя есть возможность писать на чистом WinAPI +
OpenGL или надо обязон GLUT использовать?
-----------------------------------------------
До выходных время есть? - Я бы в выходные
переписал твой код посвоему и посмотрел бы как у меня поидёт. А то я GLUTом то никогда не пользуюсь.
Поворот выполняй при помощи вертексного шейдера - это два.
Чем меньше glBegin()/glEnd(), тем быстрее - это три.
Проверь так же вывод fps. Возможно sprintf - тормозит все. Точно не скажу - надо проверить. Я таких функций никогда не юзаю. :)
И ещё задние грани отсекай там, где не используешь полупрозрачность (да даже если и используещь, ситуации, где тебе нужен именно двусторонний материал, можно по пальцам сосчитать). Вместо флага GL_FRONT_AND_BACK используй GL_FRONT.
Ну 3Д я отрубаю когда не пользуюсь и прозрачность тут врубается только когда надо...
Тут основная ф-ия - Draw. В в зависимости от режима основной будет либо DrawScene (шестеренки) либо полупрозрачность ( Draw2D - меню поверх всего ). DrawCubes рисует шестеренку.
Насчет переключения буферов - это делается в основной ф-ии ( Draw ). Тут написано glFlush(); но у меня сейчас - glutSwapBuffers(); Скорость та же, ничего не меняется.
А вообще в качестве библиотеки (LIB файлов при компиляции) использую MesaGL и GLUT Mesa. Но она существует довольно давно и вещь довольно крутая, так что думаю, дело не в ней...
GLUT мне действительно нужен для переносимости. Хотя если окажется что собака порылась именно в GLUT, придется писать разные main.cpp чтоб стыковать с разными оконными системами разных ОС...
GL_FRONT_AND_BACK я использую для отрисовки каркаса некоторых фигур (но не пугайтесь, фичу с отрисовкой линий треугольниками я знаю, каркасы работают только в 2D, в 3D они отключены...)
sprintf сильно тормозить не должен... За N лет существования стандартной библиотеки я думаю, он оптимизирован :) да и параметров там не много... Да и проверял я уже... :)
Огромное спасибо за ответы... Буду рад если bave посмотрит на выходных, очень рад :)
я заменил на GL_BACK (почему-то GL_FRONT выдал задние стороны) особого прироста производительности не нашел...
С видяхой заранее все нормаьльно... DOOM III идет без тормозов...
WinApi дает 90 FPS... Победа!
Только не понятно почему перестали грани давать разную освещенность, т.е. при любом угле наклона цвет один...