Ответы пользователя по тегу OpenGL
  • Как увеличить максимальный размер точки в opengl?

    @makaleks
    Доки
    Тут сказано, что от платформы зависит, какой максимальный размер может быть у сглаженной точки, гарантируя только поддержку размера 1. Параграф перед Notes - там всё.
    В opengl всё скачет от треугольников, так почему бы не использовать GL_TRIANGLE_FAN? Эти вычисления всё равно будут - либо на вашей стороне, либо на стороне opengl. Списки отображения (glList) позволят произвести вычисления всего один раз для некоторого сглаживания (на сколько частей круг делить), а glScale позволит масштабировать до тех пор, пока не станут видны отдельные отрезки. Используйте вершинные массивы (glDrawElements), чтобы не обращаться к видеокарте по двадцать раз для одного объекта, т.к. так никто не делает. Всё описано в OpenGL Red Book, у которой даже перевод есть.
    Ответ написан
    Комментировать
  • OpenGL, как связать прыжки персонажа с нажатием мыши?

    @makaleks
    Не углублён в вопрос (пробовал только с OpenGL v1.1) но предложение есть.
    Во главном цикле приложения (1) Вы рисуете каждый нужный Вам объект. Объект имеет поле(2), описывающее его состояние. Событие может менять(3) состояние, а перед отрисовкой над объектом производится какое-то изменение (маленький кусочек подпрыгивания)(4). Некоторые состояния имеют ограничение по длительности - нужна степень выполнения (н-р по времени), т.е. во время обработки надо проверять: "а, может, хватит? если да, произвести преобразование последний раз, и сбросить состояние на 'не активное'". По вопросу вроде всё.

    Возможные уточнения:
    1) Библиотеки, обеспечивающие OpenGL окно и регистрацию событий, могут иметь функцию типа WaitEvents(), которая заморозит текущий поток до наступления события, следовательно, убьёт анимацию. От такого метода придётся отказаться, пока анимация может наступать.
    2) Можно в структуре иметь список структур, описывающих обработку состояния. По мере активаний/деактиваций состояний список можно увеличивать/уменьшать.
    3) Вы уже умеете выбирать объект по щелчку мыши? В OpenGL Red Book описано, как пользоваться буфером обратного вызова: передаём в OpenGL массив, указываем его размеры. С помощью преобразований OpenGL Включаем буфер. Далее в цикле [ => загрузить имя (число) => нарисовать объект => ]. На самом экране ничего не появится, даже если сделать SwapBuffers(). Выключаем буфер - эта функция вернёт нам число попаданий - сколько "имён" было нарисовано. Ещё раз - мы на невидимом экране произвели зум в указателю мыши до масштаба порядка пикселя и нарисовали все объекты на сцене. Если после вызова glLoadName(i) на экране что-то появилось - записать информацию в буфер. Теперь в буфере определённом формате записано, что было нарисовано с доп. информацией, типа значения координаты z (помогает в сложном 3D). Старый код:
    gliuButton* gliuCallBackStafGL(double mouseX, double mouseY)
    {
    	if (!gliuButtonStore.stackSize)// мой стек кнопок. кнопки хранятся блоками.
    	{
    		return;
    	}
    
    	glPushMatrix();	// сохраним матрицу, чтобы ничего не испортить
    	GLuint buf[8] = { 0 };
    	glSelectBuffer(8, buf);
    
    	glLoadIdentity();	// координаты объектов я задавал в экранных координатах
    					// => стандартные координаты [-1;1]x[-1;1] будут охватывать 4 пикселя
    	glTranslatef(-mouseX, -mouseY, 0);
    
    	glRenderMode(GL_SELECT);	// включаем буфер
    	glInitNames();
    	glPushName(0);		// не помню, для чего именно это нужно, но иначе не работает
    
    	unsigned i = 0;
    	// сложности с хранением блоками
    	struct _gliuStackElemSet_buttonPtr *ptr = gliuButtonStore.current;
    	gliuButton **cur;
    	if (!ptr->_bsize)
    	{
    		ptr = ptr->_before;
    	}
    	cur = &ptr->_buf[ptr->_bsize - 1];
    
    	for (i = 0; i < gliuButtonStore.stackSize; i++)
    	{
    		glLoadName(i);	// загрузить имя
    		glRecti((*cur)->labelPart->x, (*cur)->labelPart->y, (*cur)->labelPart->x + (*cur)->labelPart->width, (*cur)->labelPart->y + (*cur)->labelPart->height);	// вместо кнопки - просто прямоугольник
    		if (cur != ptr->_buf)
    		{
    			cur--;
    		}
    		else
    		{
    			ptr = ptr->_before;
    		}
    	}
    	glPopName();
    
    	// сколько попаданий?
    	int hits = glRenderMode(GL_RENDER);
    
    	if (hits>0)
    	{
    		ptr = gliuButtonStore.current;
    		if (!ptr->_bsize)
    		{
    			ptr = ptr->_before;
    		}
    		cur = &ptr->_buf[ptr->_bsize - 1];
    
    		for (i = 0; i < gliuButtonStore.stackSize; i++)
    		{
    			if (i == buf[3])
    			{
    				// именно в buf[3] хранится "имя"
    				// полезно изучить всё содержимое buf
    				break;
    			}
    			if (cur != ptr->_buf)
    			{
    				cur--;
    			}
    			else
    			{
    				ptr = ptr->_before;
    			}
    		}
    		glPopMatrix();
    		return *cur;
    	}
    	else 
    	{
    		glPopMatrix();
    		return 0;
    	}
    }

    4) Список активных обработчиков состояний можно для единообразия заполнять структурами из: значение степени выполнения (int) + указатель на функцию, принимающую этот int и void* указатель на объект

    P.S.
    Не хотите ли перебраться на C++? В нём реализовано несколько возможностей, которые упрощают разработку (классы, их методы, перегрузка, шаблоны), например, позволяют абстрагировать интерфейс от реализации (наследование, виртуальные функции). Есть литература по приёмам организации кода ("Паттерны проектирования" от Банды Четырёх). Совместим с Си. "Полный справочник по C++" Шилдта расскажет о Си и С++ - по нему удобно искать. И да, во многих компиляторах C++ уже реализованы потоки C++11, что позволяет без подключения сторонних библиотек и Sleep() (только! винда) ставить приложение на паузу.
    P.P.S.
    Вроде ответ дан, кидайте доп. вопросы в комментарии.
    Ответ написан
    Комментировать
  • Почему трясётся обект в OpenGL?

    @makaleks
    Класс Camera использует перспективу?
    Не исключено, что неверные расчёты происходят постоянно, но заметны они становятся только при приближении (более заметно) либо при активных движениях на расстоянии (что заметить будет непросто при непрерывном перемещении).
    Ответ написан
    Комментировать
  • OpenGL цветовые индексы или реализация glDrawPixels с праметром GL_BITMAP. Как?

    @makaleks Автор вопроса
    Спасибо за ответы)
    Если кому надо:

    Задание цветового индекса является платформо-зависимой операцией.
    У пользователей GLUT есть
    glutSetColor(int cell,
    GLfloat red, GLfloat green, GLfloat blue);

    Другой способ лежит через GL_MAP_COLOR
    Пример:
    unsigned char bitmap[] = { 0x00, 0x00, 0x00, 0x00,
    	0x00, 0x00, 0x00, 0x00,
    	0x00, 0x00, 0x00, 0x00,
    	0x00, 0xFF, 0xFF, 0x00,
    	0x03, 0xFF, 0xFF, 0xC0,
    	0x07, 0xFF, 0xFF, 0xE0,
    	0x0F, 0x80, 0x01, 0xF0,
    	0x1E, 0x00, 0x00, 0xF8,
    	0x1C, 0x00, 0x00, 0x38,
    	0x3C, 0x7E, 0x7E, 0x3C,
    	0x38, 0x0E, 0x70, 0x1C,
    	0x39, 0xF0, 0x0F, 0x9C,
    	0x38, 0x00, 0x00, 0x1C,
    	0x38, 0x00, 0x00, 0x1C,
    	0x38, 0x38, 0x1C, 0x1C,
    	0x38, 0xFE, 0x7F, 0x1C,
    	0x38, 0xC6, 0x63, 0x1C,
    	0x38, 0xD6, 0x6B, 0x1C,
    	0x38, 0xD6, 0x6B, 0x1C,
    	0x38, 0xC6, 0x63, 0x1C,
    	0x38, 0xFE, 0x7F, 0x1C,
    	0x38, 0x7C, 0x3E, 0x1C,
    	0x3C, 0x00, 0x00, 0x3C,
    	0x3C, 0x00, 0x00, 0x3C,
    	0x7E, 0x00, 0x00, 0x7E,
    	0x7F, 0x80, 0x01, 0xFE,
    	0x77, 0xFF, 0xFF, 0xEE,
    	0x63, 0xFF, 0xFF, 0xC7,
    	0xE7, 0xFF, 0xFF, 0xE7,
    	0xFF, 0xF0, 0x0F, 0xFF,
    	0xFF, 0x00, 0x01, 0xFF,
    	0xF0, 0x00, 0x00, 0x0F
    };
    void draw(){
    	glClearColor(1, 1, 0, 1);//жёлтым
    	glClear(GL_COLOR_BUFFER_BIT);//закрасить
    	glPixelTransferi(GL_MAP_COLOR, 1);//использоваь карту
    	float map[2] = { 1, 0 };//пусть...
    		//...все единицы закрашивают в чёрный, а все нули - в белый цвета...
    		glPixelMapfv(GL_PIXEL_MAP_I_TO_R, 2, map);
    		glPixelMapfv(GL_PIXEL_MAP_I_TO_G, 2, map);
    		glPixelMapfv(GL_PIXEL_MAP_I_TO_B, 2, map);
    	//...и все нули будут прозрачными
    	map[0] = 0, map[1] = 1;
    	glPixelMapfv(GL_PIXEL_MAP_I_TO_A, 2, map);
    	//Итого: для единиц действует цвет glColor4f(0,0,0,1), а для нулей будет glColor4f(1,1,1,0)
    
    	glRasterPos2i(-160, -160);//позиция от центра экрана в пикселях ( не забыть вызвать glOrtho(...) )
    	glPixelZoom(10, 10);//теперь работает
    
    /*этот блок*/		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    /*лучше поставить*/	glEnable(GL_BLEND);					//прозрачность
    /*в начале программы*/	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);	//определяется компонентом ALPHA
    	glDrawPixels(32, 32, GL_COLOR_INDEX, GL_BITMAP, bitmap);//рисовать 32x32 bitmap, где кадый бит определяет цветовой индекс "0" или "1"
    
    	glPixelTransferi(GL_MAP_COLOR, 0);//не использовать карту
    }

    2b74cc08dc274662aebbbd40563885b8.PNG
    Ответ написан
    Комментировать
  • Как удалить список отображения в OpenGL?

    @makaleks Автор вопроса
    Удаление списков отображения - void glDeleteLists(GLuint list,GLsizei range);
    Проверить занятость идентификатора - GLboolean glIsList(GLuint list);
    Использование идентификатора старого списка при создании нового якобы ведёт к простой перезаписи
    Ответ написан
    Комментировать
  • Как перевести координаты мыши, полученные glutMouseFunc в координаты OpenGL?

    @makaleks
    так я перевожу в центр
    my_x=-x+app.width/2;
    my_y=-app.height/2+y;
    , где app - моя структура, хранящая высоту и ширину окна, аint x,y; - переменные с координатами мыши

    И если я правильно понял, Вам нужно прибавить width/2 и height/2 в соответствующих местах
    Ответ написан
    Комментировать