[ AmberSkyNet VR ]Текст, один текст... В консоли, в логах.. Пора чего-нибудь графическое
сотворить уже... Например - менеджер графики. Думаю, что далее его
интерфейсы всё-таки будут немного меняться, а пока предлагаю вашему вниманию
первое приближение... Отрисовками небесного куба, сфер, спрайтов, анимированых трёхмерных моделей, итп
будут заниматься отдельные классы - представления вида элементов сцены.
Они будут формировать данные в доступном для отрисовки менеджером графики формате -
в виде вертексов, нормалей, текстурных координат. Причём не обязательно одному классу
представления вида элемента сцены будет соответствовать один элемент для графического
менеджера. IBaseObject и его реализацияНо для начала - введём базовый объект. Набор его функций позволит нам добавлять функциональность в классы без больших изменений интерфейса. Как это работает покажем это чуть ниже, на примере класса материала для нашего графического менеджера. class IBaseObject { public: virtual ~IBaseObject(){}; // получить имя базового класса virtual std::string GetBaseClass() =0; // получить тип объекта - имя реализации базового класса virtual std::string GetType() =0; // получить имя объекта virtual std::string GetName() =0; // функции установки/чтения указателей на менеджеры и пр. virtual void SetPtrParam(const std::string& param_name, void *param_value) =0; virtual void *GetPtrParam(const std::string& param_name) =0; virtual void DelPtrParam(const std::string& param_name) =0; // функции установки/чтения переменных virtual void SetParam(const std::string& param_name,const std::string& param_value) =0; virtual std::string GetParam(const std::string& param_name) =0; virtual void DelParam(const std::string& param_name) =0; }; Функция GetBaseClass возвращает имя базового класса объекта. Ну, например класс реализации
менеджера GUI возвратит значение "GUI Manager" Да, напоминает набор функций в IEngine. Возможно в будущем так и сделаю - наследую IEngine от него. Класс BaseObject реализует некоторую функциональность интерфейсного класса IEngine по установке/удалению указателей и переменных. Поэтому в описании BaseObject.h есть секция protected с хранящимися в ней списками переменных и указателей в виде std:map. Жаль,что не удалось в папке include собрать заголовки только абстрактных классов :(( Впрочем реализация BaseObject.h всё равно скрыта в asnCommon и по идее может быть недоступна сферическому разработчику в вакууме, который вдруг ни с того ни с сего захочет использовать наш движок для написания своей программы. IDrawObjectНапишем интерфейс объекта отрисовки, который будет связующим звеном между данными
внешней программы и нашим граф. менеджером. Указатель на него и будет посылаться нашему
графическому менеджеру в команде Draw(). Конечно можно передавать указатели на данные прямо
в наш менеджер (скажем, в ту же команду Draw()), но в этом случае менеджер будет каждый раз
заново подключать одни и те же текстуры, устанавливать указатели на массивы, включать/выключать
освещение объекта, устанавливать переменные среды в соответствии с материалом объекта. Как всегда - сначала интерфейс. // виды буферов enum ASN_DATA_Buffer{ ASN_DATA_VERTEX_BUFF=0, ASN_DATA_NORMAL_BUFF, ASN_DATA_COLOR_BUFF, ASN_DATA_UV_BUFF, }; class IDrawObject{ public: // материал virtual bool SetMaterial(IMaterial *Material)=0; // буфер данных - в одном массиве храним вертексы, нормали, текстурные координаты // на вход подаём указатель на буфер, размер одного элемента, кол-во элементов в буфере virtual bool SetDataBuffer(void *buffer, unsigned int element_size, unsigned int buf_size)=0; // задаём сдвиг данных virtual bool SetDataOffset(ASN_DATA_Buffer buffer_type, unsigned int data_offset)=0; // буфер индекса virtual bool SetIndexBuffer(void *buffer, unsigned int element_size, unsigned int buf_size)=0; }; Функция SetMaterial присваивает объекту определённый материал. О материалах будет чуть ниже. Функция SetDataBuffer устанавливает указатель на массив данных, которые будут
отрисованы. Во входных параметрах функции указывается размер
структуры, которая хранит в себе один вертекс (возможно, с нормалями и текстурными
координатами). Пояснение: пусть данные хранятся у нас в таком виде Функция SetIndexBuffer устанавливает указатель на массив с индексами, указывающими какие данные отрисовывть из массива данных. Смещение в данном случае указывать не требуется, т.к. массив состоит только из индексов. IDeviceТак как в SDL очень тесно интегрированы ввод и отрисовка мы тоже сделаем для этого единый менеджер - менеджер графики и ввода. Поэтому интерфейс у него будет несколько совмещённый: // события, получаемые через функцию GetInput() enum ASN_INPUT_EVENTS_Types { ASN_NONE, // NULL ASN_EVNT_EMPTY, ASN_EVNT_KEYPRESSED, //нажата кнопка ASN_EVNT_KEYUP, //отжата кнопка ASN_EVNT_MOUSEMOVE, //мышка сдвинулась ASN_EVNT_MOUSEDOWN, //нажата кнопка мышки ASN_EVNT_MOUSEUP, //отжата кнопка мышки ASN_MOUSE_BUTTON_LEFT, //нажата левая кнопка мышки ASN_MOUSE_BUTTON_RIGHT, //нажата правая кнопка мышки ASN_MOUSE_BUTTON_MIDDLE, //нажата средняя кнопка мышки ASN_MOUSE_WHEEL_UP, //колёсико мышки вертится вверх ASN_MOUSE_WHEEL_WHEELDOWN, //колёсико мышки вертится вниз ASN_QUIT, // закрытие Device }; // типы граф. режимов - 2d, 3d enum ASN_GRAPH_MODE_Types { ASN_GRAPH_2D, ASN_GRAPH_3D, }; class IDevice { public: virtual ~IDevice(){}; // инициализация графики virtual bool Init(int width=640, int height=480, int bpp=32, int param=0)=0; // установка режима - 2d, 3d virtual bool SetMode(ASN_GRAPH_MODE_Types Typ)=0; // читаем события из очереди virtual int GetInput()=0; // начало отрисовки сцены virtual void StartDraw()=0; // рисуем объект virtual bool DrawObject(IDrawObject *SceneElem)=0; // заканчиваем отрисовку сцены virtual void EndDraw()=0; // материалы virtual IMaterial *AddMaterial (const void* MaterialInfo)=0; virtual IMaterial *GetMaterial (const std::string& MaterialName)=0; // меши отрисовки virtual IDrawObject *CreateDrawObject(const std::string& SceneElemInfo)=0; virtual IDrawObject *GetDrawObject(const std::string& SceneElemName)=0; // позиционирование // работа с мышкой // перевод координат мышки в мировые координаты virtual void MouseToWorld(int mouse_x, int mouse_y, CVector& p1, CVector& p2)=0; // работа с мышкой virtual void CenterMouse(bool ShowCursor)=0; //позиционирование // получаем матрицы virtual void GetMatrixs(double *Model_Matrix, double *Project_Matrix)=0; // устанавливаем матрицы virtual void SetMatrixs(double *Model_Matrix, double *Project_Matrix)=0; // вращаем на XYZ virtual void Rotate(CVector& Point1)=0; // двигаем на XYZ virtual void Move(const CVector& Point1)=0; // масштабируем на XYZ virtual void SetScale(const CVector& Point1)=0; // помещаем матрицы в стек virtual void PushMatrix()=0; // забираем матрицы из стека virtual void PopMatrix()=0; // FPS - считается в EndDraw() int FPS; // интервал между фреймами для корректной скорости анимации float FrameInterval; // код последней нажатой клавиши int LastKey; // код последней нажатой клавиши в unicode unsigned short UnicodeKey; // положение мышки на экране int mouse_x; int mouse_y; unsigned char mouse_butt; }; Некоторые значения (fps, код нажатой клавиши, координаты мышки) доступны напрямую, без вызовов функций - это в данном случае считаю ненужным. Граф. менеджер производит экземпляры классов СMaterial и СDrawObject и выдаёт их через функции AddMaterial и CreateDrawObject. Если мы вдруг захотим использовать уже имеющийся материал или объект отрисовки, то можем получить указатель на него по его имени - при помощи функций GetMaterial и GetObject. Пока в функции AddMaterial и AddDrawObject подаётся только указатель на имя материала, потом - сделаю нормальный парсер входных значений и буду подавать входные параметры через знак-разделитель |, как это было в предыдущей реинкарнации движка.. может быть... IMaterial и дальнейшее развитие CMaterialГрафический менеджер возвращает экземпляр класса CMaterial под видом интерейсного класса IMaterial, поэтому public-поля класса, хорошо видимые менеджером графики, будут невидимы для внешней прогаммы. Это даст нам возможность как угодно менять строение класса материала, изменения потребуется внести только в пределах классов модуля DeviceGL. Все остальные классы движка и внешней программы останутся без изменений. CMaterial на данный момент реализует только хранение текстуры. Одной. Без бампа,
параметров диффузного, зеркального цвета, итп.. Не всё сразу, я думаю... Текстура задаётся
при помощи вызова функции Если вдруг мы захотим сделать мультитекстурирование, то достаточно будет добавить в класс
CMaterial указатель на дополнительную текстуру, учесть установку переменных, связанных
с мультитекстурированием и доработать в DeviceGL вывод мешей с несколькими текстурами. myMaterial->SetParam("Texture1","graystone.png"); Посмотрим... Может быть потом вынесу из CDeviceGL функцию установки параметров окружения в соответствии с материалом в класс материала. Это позволит создавать материалы разных типов (например - с бампом и без, с параметрами освещения, итп) и не проверять в CDeviceGL что установлено а что нет в классе материала... Взаимодействие с граф. менеджеромEngine после разбора ini-файла читает значение переменной [Modules]DeviceManager
и пытается загрузить через систему плагинов графический менеджер с таким названием. Полученный
указатель запоминается в указателях окружения с именем DeviceManager.
Для обращения к менеджеру во внешних программах можно использовать
определённое через макрос в файле IDevice.h слово DEVICER. Например, получить значение FPS
можно вот так: Переменные окружения: Изменения в исходникахinclude/: Добавлен интерфейсы IBaseObject.h, BaseObject.h, IDevice.h, IDrawObject.h, IMaterial.h src/asnMain/:Небольшая демка с летающими "бубликами", показывающий как использовать всё то, что было описано выше. Класс формирования геометрии тора взят из примера на сайте 3dsteps.narod.ru, но где-то подобное я уже видел еще... src/asnEngine/: добавлена инициализация графического менеджера. src/asnDeviceGL/: Новый плагин - менеджер графической системы и ввода/вывода с реализацией материалов и объектов отрисовки. Исходники этого шага выложены в SVN. Скачать их можно набрав команду: svn co https://svn.sourceforge.net/svnroot/ambernet/tags/AmberSkyNet-0.7 ambernet_0.7 |