Полный исходный текст на языке C++ двух библиотек (DLL) с моделями блоков, создающих панели в окне родительской подсистемы.
Первая библиотека содержит модель, создающую и обслуживающую пустую панель (во второй библиотеке будет добавлено формирование на этой панели трехмерного изображения с помощью OpenGL).
// Панели блоков в окне подсистемы - первый пример #include <windows.h> #include <RdsDef.h> // Подготовка описаний сервисных функций #define RDS_SERV_FUNC_BODY GetInterfaceFunctions #include <RdsFunc.h> // Глобальная переменная для значения ошибки double DoubleErrorValue; //========== Главная функция DLL ========== int WINAPI DllMain(HINSTANCE /*hinst*/, unsigned long reason, void* /*lpReserved*/) { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL { // Получение доступа к функциям RDS if(!GetInterfaceFunctions()) RDS_SERV_ERROR_MSGW // Сообщение: старая версия RDS else rdsGetHugeDouble(&DoubleErrorValue); } return 1; } //========= Конец главной функции ========= //================================================= // Личная область данных блока //================================================= class TOpenGLInstr { private: RDS_TIMERID RefreshTimer; // Таймер обновления public: RDS_HOBJECT Panel; // Объект-панель // Сохранение параметров блока void SaveText(void); // Загрузка параметров блока void LoadText(char *text); // Создание таймера обновления void CreateRefreshTimer(RDS_BHANDLE parent); // Конструктор класса TOpenGLInstr(void); // Деструктор класса ~TOpenGLInstr(); }; //================================================= // Конструктор класса личной области данных // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" TOpenGLInstr::TOpenGLInstr(void) { // Создаем панель в окне подсистемы Panel=rdsPANCreate(0,0,0,300,300, RDS_PAN_F_SCALABLE|RDS_PAN_F_BORDER| RDS_PAN_F_SIZEABLE|RDS_PAN_F_MOVEABLE| RDS_PAN_F_CAPTION|RDS_PAN_F_HIDDEN| RDS_PAN_F_PAINTMSG, "Прибор"); // Инициализируем идентификатор еще не созданного таймера RefreshTimer=NULL; } //================================================= // Деструктор класса личной области данных TOpenGLInstr::~TOpenGLInstr() { // Удаление панели if(Panel) rdsDeleteObject(Panel); // Удаление таймера if(RefreshTimer) rdsDeleteBlockTimer(RefreshTimer); } //================================================= // Создание таймера обновления панели void TOpenGLInstr::CreateRefreshTimer(RDS_BHANDLE parent) { // Структура для получения переметров окна подсистемы RDS_EDITORPARAMETERS WinParams; // Определение интервала обновления окна подсистемы WinParams.servSize=sizeof(RDS_EDITORPARAMETERS); rdsGetEditorParameters(parent,&WinParams); // Интервал - в WinParams.RefreshDelay // Создание таймера RefreshTimer=rdsSetBlockTimer(RefreshTimer, // Идентификатор WinParams.RefreshDelay, // Интервал RDS_TIMERM_LOOP | RDS_TIMERS_WINREF | RDS_TIMERF_FIXFREQ, // Режим и флаги TRUE); // Запустить таймер } //================================================= // Функция сохранения параметров блока void TOpenGLInstr::SaveText(void) { RDS_HOBJECT ini; // Идентификатор вспомогательного объекта // При сохранении блока в отдельный файл на диске параметры // панели записывать не нужно if(rdsGetSystemInt(RDS_GSISAVELOADACTION)==RDS_LS_SAVETOFILE) return; // Создание вспомогательного объекта для работы с данными ini=rdsINICreateTextHolder(TRUE); // Параметры записываются в секцию "[Window]" rdsSetObjectStr(ini,RDS_HINI_CREATESECTION,0,"Window"); // Получение параметров панели и запись их в объект rdsINIWriteInt(ini,"Left",rdsGetObjectInt(Panel,RDS_PAN_LEFT,0)); rdsINIWriteInt(ini,"Top",rdsGetObjectInt(Panel,RDS_PAN_TOP,0)); rdsINIWriteInt(ini,"Width",rdsGetObjectInt(Panel,RDS_PAN_WIDTH,0)); rdsINIWriteInt(ini,"Height",rdsGetObjectInt(Panel,RDS_PAN_HEIGHT,0)); rdsINIWriteInt(ini,"Visible",rdsGetObjectInt(Panel,RDS_PAN_VISIBLE,0)); // Сохранение получившегося текста в файл, в который в данный // момент идет запись rdsCommandObject(ini,RDS_HINI_SAVEBLOCKTEXT); // Удаление вспомогательного объекта rdsDeleteObject(ini); } //================================================= // Функция загрузки параметров блока void TOpenGLInstr::LoadText(char *text) { RDS_HOBJECT ini; // Идентификатор вспомогательного объекта // Создание вспомогательного объекта для работы с данными ini=rdsINICreateTextHolder(TRUE); // Запись в объект полученного от RDS текста с параметрами блока rdsSetObjectStr(ini,RDS_HINI_SETTEXT,0,text); // Установка "[Window]" в качестве текущей секции и чтение // из нее пяти целых параметров if(rdsINIOpenSection(ini,"Window")) { rdsSetObjectInt(Panel,RDS_PAN_LEFT,0, rdsINIReadInt(ini,"Left",0)); rdsSetObjectInt(Panel,RDS_PAN_TOP,0, rdsINIReadInt(ini,"Top",0)); rdsSetObjectInt(Panel,RDS_PAN_WIDTH,0, rdsINIReadInt(ini,"Width",0)); rdsSetObjectInt(Panel,RDS_PAN_HEIGHT,0, rdsINIReadInt(ini,"Height",0)); rdsSetObjectInt(Panel,RDS_PAN_VISIBLE,0, rdsINIReadInt(ini,"Visible",0)); } // Удаление вспомогательного объекта rdsDeleteObject(ini); } //================================================= // Модель блока с панелью extern "C" __declspec(dllexport) int RDSCALL OpenGLInstr( int CallMode, RDS_PBLOCKDATA BlockData, LPVOID ExtParam) { // Указатель на личную область, приведенный к нужному типу TOpenGLInstr *data=(TOpenGLInstr*)(BlockData->BlockData); // Вспомогательная – указатель на структуру параметров при // действиях с панелью (будет использована в реакциях) RDS_PPANOPERATION param; switch(CallMode) { // Инициализация блока case RDS_BFM_INIT: // Создание личной области данных // (при этом в конструкторе будет создана панель) BlockData->BlockData=data=new TOpenGLInstr(); break; // Очистка данных блока case RDS_BFM_CLEANUP: // В деструкторе класса панель будет уничтожена delete data; break; // Запуск расчета case RDS_BFM_STARTCALC: // Создание таймера обновления data->CreateRefreshTimer(BlockData->Parent); break; // Вызов функции настройки или двойной щелчок // левой кнопки мыши case RDS_BFM_SETUP: case RDS_BFM_MOUSEDBLCLICK: // Показать панель rdsSetObjectInt(data->Panel,RDS_PAN_VISIBLE,0,1); break; // Сохранение параметров блока case RDS_BFM_SAVETXT: data->SaveText(); break; // Загрузка параметров блока case RDS_BFM_LOADTXT: data->LoadText((char*)ExtParam); break; // Действия с панелью case RDS_BFM_BLOCKPANEL: // Приведение указателя на структуру, переданного в // ExtParam, к нужному типу param=(RDS_PPANOPERATION)ExtParam; // Разные действия в зависимости от операции с панелью switch(param->Operation) { // Создание оконного объекта для панели case RDS_PANOP_CREATE: // Здесь будет инициализация рисования на панели break; // Уничтожение оконного объекта панели case RDS_PANOP_DESTROY: // Здесь будет очистка инициализированного break; // Размер панели изменен case RDS_PANOP_RESIZED: // Здесь будет реакция на изменение размера // и перерисовка панели break; // Необходимо перерисовать изображение case RDS_PANOP_PAINT: // Здесь будет перерисовка панели break; } break; // Необходимо обновить окна блока (вызывается таймером) case RDS_BFM_WINREFRESH: // Здесь будет перерисовка панели break; } return RDS_BFR_DONE; } //=================================================
Эта же библиотека с добавленными функциями формирования трехмерного изображения (добавки выделены цветом).
// Панели блоков в окне подсистемы - OpenGL #include <windows.h>#include <math.h> #include <gl/gl.h> #include <gl/glu.h>#include <RdsDef.h> // Подготовка описаний сервисных функций #define RDS_SERV_FUNC_BODY GetInterfaceFunctions #include <RdsFunc.h> // Глобальная переменная для значения ошибки double DoubleErrorValue; //========== Главная функция DLL ========== int WINAPI DllMain(HINSTANCE /*hinst*/, unsigned long reason, void* /*lpReserved*/) { if(reason==DLL_PROCESS_ATTACH) // Загрузка DLL { // Получение доступа к функциям RDS if(!GetInterfaceFunctions()) RDS_SERV_ERROR_MSGW // Сообщение: старая версия RDS else rdsGetHugeDouble(&DoubleErrorValue); } return 1; } //========= Конец главной функции ========= //================================================= // Личная область данных блока //================================================= class TOpenGLInstr { private:HGLRC Hrc; // Контекст OpenGLRDS_TIMERID RefreshTimer; // Таймер обновления public: RDS_HOBJECT Panel; // Объект-панель// Настройка вывода изображения на панель void InitWindow(HWND window); // Отключение OpenGL void Clear(void); // Рисование трехмерной сцены void RenderScene(double Dir,double List,double Pitch);// Сохранение параметров блока void SaveText(void); // Загрузка параметров блока void LoadText(char *text); // Создание таймера обновления void CreateRefreshTimer(RDS_BHANDLE parent); // Конструктор класса TOpenGLInstr(void); // Деструктор класса ~TOpenGLInstr(); }; //=================================================// Вычисление нормали к треугольнику // p1,p2,p3 – массивы координат вершин {x,y,z} // norm – массив, в котором возвращаются вычисленные // координаты нормали void NormalToTriangle(GLfloat *p1,GLfloat *p2, GLfloat *p3,GLfloat *norm) { double m[3],a[3],b[3],R; // Вспомогательные переменные // Символические имена для координат векторов #define x 0 #define y 1 #define z 2 // Вычисляем векторное произведение векторов // a (p1->p2) и b (p1->p3) for(int i=0;i<3;i++) { a[i]=p2[i]-p1[i]; b[i]=p3[i]-p1[i]; } m[x]=a[y]*b[z]-a[z]*b[y]; m[y]=a[z]*b[x]-a[x]*b[z]; m[z]=a[x]*b[y]-a[y]*b[x]; // Длина получившегося вектора R=sqrt(m[x]*m[x]+m[y]*m[y]+m[z]*m[z]); // Приводим вектор к единичной длине for(int i=0;i<3;i++) norm[i]=(GLfloat)(m[i]/R); // Отмена макроопределений символических имен координат #undef x #undef y #undef z } //=================================================// Построение треугольника p1-p2-p3 void DrawTriangleGL(GLfloat *p1,GLfloat *p2,GLfloat *p3) { GLfloat norm[3]; // Массив для вычисления нормали // Вычислить нормаль NormalToTriangle(p1,p2,p3,norm); // Установить нормаль в OpenGL glNormal3fv(norm); // Задать три точки треугольника glVertex3fv(p1); glVertex3fv(p2); glVertex3fv(p3); } //=================================================// Рисование окружности в OpenGL void DrawCircleGL(GLfloat R,int N,GLfloat cR,GLfloat cG,GLfloat cB) { double aStep=(2.0*M_PI)/N; // Шаг ломаной по углу, радиан // Массивы для задания материала GLfloat MaterialAmbDiff[4], MaterialSpecular[4]={1.0,1.0,1.0,1.0}; // Запись цвета материала в массив MaterialAmbDiff[0]=cR; MaterialAmbDiff[1]=cG; MaterialAmbDiff[2]=cB; MaterialAmbDiff[3]=1.0; // Непрозрачный // Установка отражающих свойств (материала) фигуры glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, MaterialAmbDiff); glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS, 50.0); glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,MaterialSpecular); // Нормаль – по оси Z (окружность в плоскости XY) glNormal3f(0.0,0.0,1.0); // Рисуем замкнутую ломаную линию glBegin(GL_LINE_LOOP); for(int j=0;j<N;j++) // Цикл по углу { double a=aStep*j; // Угол double x=R*cos(a),y=R*sin(a); // Координаты точки glVertex3f((GLfloat)x,(GLfloat)y,0); } glEnd(); } //=================================================// Рисование центрального объекта блока void DrawArrowGL(double R,double l,double w,double h,double b) { // Массивы для координат точек фигуры GLfloat p1[3],p2[3],p3[3],p4[3]; // Материал – дно и корма (белый цвет) GLfloat MaterialBack[] = {1.0, 1.0, 1.0, 1.0}; // Материал – левый борт (красный цвет) GLfloat MaterialLeft[] = {1.0, 0.5, 0.5, 1.0}; // Материал – правый борт (зеленый цвет) GLfloat MaterialRight[] = {0.5, 1.0, 0.5, 1.0}; // Символические имена для координат точек #define x 0 #define y 1 #define z 2 // Вычисление координат точек фигуры p1[x]=0; p1[y]=R; p1[z]=0; p2[x]=-w; p2[y]=R-l; p2[z]=0; p3[x]=w; p3[y]=p2[y]; p3[z]=0; p4[x]=0; p4[y]=p2[y]+b; p4[z]=h; // Построение граней glBegin(GL_TRIANGLES); // Свойства материала – общие для всех glMaterialf(GL_FRONT,GL_SHININESS,20.0); // Свойства материала – корма и дно glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,MaterialBack); glMaterialfv(GL_FRONT,GL_SPECULAR,MaterialBack); // Нижний треугольник (дно) DrawTriangleGL(p1,p3,p2); // Задний треугольник (корма) DrawTriangleGL(p2,p3,p4); // Свойства материала – левый борт glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,MaterialLeft); glMaterialfv(GL_FRONT,GL_SPECULAR,MaterialLeft); // Левый передний треугольник DrawTriangleGL(p2,p4,p1); // Свойства материала – правый борт glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,MaterialRight); glMaterialfv(GL_FRONT,GL_SPECULAR,MaterialRight); // Правый передний треугольник DrawTriangleGL(p4,p3,p1); glEnd(); // Отмена макроопределений символических имен координат #undef x #undef y #undef z } //=================================================// Конструктор класса личной области данных // ВАЖНО: Исходный текст программы должен быть записан в UTF8, // в противном случае необходимо использовать версии функций // с суффиксом "W" и символьные константы с префиксом "L" TOpenGLInstr::TOpenGLInstr(void) { // Создаем панель в окне подсистемы Panel=rdsPANCreate(0,0,0,300,300, RDS_PAN_F_SCALABLE|RDS_PAN_F_BORDER| RDS_PAN_F_SIZEABLE|RDS_PAN_F_MOVEABLE| RDS_PAN_F_CAPTION|RDS_PAN_F_HIDDEN| RDS_PAN_F_PAINTMSG, "Прибор"); // Инициализируем идентификатор еще не созданного таймера RefreshTimer=NULL; } //================================================= // Деструктор класса личной области данных TOpenGLInstr::~TOpenGLInstr() { // Удаление панели if(Panel) rdsDeleteObject(Panel); // Удаление таймера if(RefreshTimer) rdsDeleteBlockTimer(RefreshTimer); } //================================================= // Создание таймера обновления панели void TOpenGLInstr::CreateRefreshTimer(RDS_BHANDLE parent) { // Структура для получения переметров окна подсистемы RDS_EDITORPARAMETERS WinParams; // Определение интервала обновления окна подсистемы WinParams.servSize=sizeof(RDS_EDITORPARAMETERS); rdsGetEditorParameters(parent,&WinParams); // Интервал - в WinParams.RefreshDelay // Создание таймера RefreshTimer=rdsSetBlockTimer(RefreshTimer, // Идентификатор WinParams.RefreshDelay, // Интервал RDS_TIMERM_LOOP | RDS_TIMERS_WINREF | RDS_TIMERF_FIXFREQ, // Режим и флаги TRUE); // Запустить таймер } //================================================= // Функция сохранения параметров блока void TOpenGLInstr::SaveText(void) { RDS_HOBJECT ini; // Идентификатор вспомогательного объекта // При сохранении блока в отдельный файл на диске параметры // панели записывать не нужно if(rdsGetSystemInt(RDS_GSISAVELOADACTION)==RDS_LS_SAVETOFILE) return; // Создание вспомогательного объекта для работы с данными ini=rdsINICreateTextHolder(TRUE); // Параметры записываются в секцию "[Window]" rdsSetObjectStr(ini,RDS_HINI_CREATESECTION,0,"Window"); // Получение параметров панели и запись их в объект rdsINIWriteInt(ini,"Left",rdsGetObjectInt(Panel,RDS_PAN_LEFT,0)); rdsINIWriteInt(ini,"Top",rdsGetObjectInt(Panel,RDS_PAN_TOP,0)); rdsINIWriteInt(ini,"Width",rdsGetObjectInt(Panel,RDS_PAN_WIDTH,0)); rdsINIWriteInt(ini,"Height",rdsGetObjectInt(Panel,RDS_PAN_HEIGHT,0)); rdsINIWriteInt(ini,"Visible",rdsGetObjectInt(Panel,RDS_PAN_VISIBLE,0)); // Сохранение получившегося текста в файл, в который в данный // момент идет запись rdsCommandObject(ini,RDS_HINI_SAVEBLOCKTEXT); // Удаление вспомогательного объекта rdsDeleteObject(ini); } //================================================= // Функция загрузки параметров блока void TOpenGLInstr::LoadText(char *text) { RDS_HOBJECT ini; // Идентификатор вспомогательного объекта // Создание вспомогательного объекта для работы с данными ini=rdsINICreateTextHolder(TRUE); // Запись в объект полученного от RDS текста с параметрами блока rdsSetObjectStr(ini,RDS_HINI_SETTEXT,0,text); // Установка "[Window]" в качестве текущей секции и чтение // из нее пяти целых параметров if(rdsINIOpenSection(ini,"Window")) { rdsSetObjectInt(Panel,RDS_PAN_LEFT,0, rdsINIReadInt(ini,"Left",0)); rdsSetObjectInt(Panel,RDS_PAN_TOP,0, rdsINIReadInt(ini,"Top",0)); rdsSetObjectInt(Panel,RDS_PAN_WIDTH,0, rdsINIReadInt(ini,"Width",0)); rdsSetObjectInt(Panel,RDS_PAN_HEIGHT,0, rdsINIReadInt(ini,"Height",0)); rdsSetObjectInt(Panel,RDS_PAN_VISIBLE,0, rdsINIReadInt(ini,"Visible",0)); } // Удаление вспомогательного объекта rdsDeleteObject(ini); } //=================================================// Настройка вывода изображения на панель void TOpenGLInstr::InitWindow(HWND window) { HDC Hdc; // Контекст устройства Windows // Структура для установки формата изображения PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Размер структуры 1, // Номер версии PFD_DRAW_TO_WINDOW | // Вывод в окно PFD_SUPPORT_OPENGL | // Поддержка OpenGL PFD_DOUBLEBUFFER, // Двойная буферизация PFD_TYPE_RGBA, // Формат цвета – RGBA 24, // Глубина цвета – 24 бита 0,0,0,0,0,0, // (здесь не используется) 0,0,0,0,0,0,0, // (здесь не используется) 32, // Z-буфер - 32 бита 0,0, // (здесь не используется) PFD_MAIN_PLANE, // Главный слой 0, // Зарезервировано 0,0, // Маски слоев (не исп.) }; int PixelFormat; // Получение контекста оконного объекта Hdc=GetDC(window); // Установка формата изображения по структуре pfd PixelFormat=ChoosePixelFormat(Hdc,&pfd); SetPixelFormat(Hdc,PixelFormat,&pfd); // Создание контекста OpenGL Hrc=wglCreateContext(Hdc); // Установка этого контекста в качестве текущего wglMakeCurrent(Hdc,Hrc); } //=================================================// Отключение OpenGL void TOpenGLInstr::Clear() { // Отключение текущего контекста OpenGL wglMakeCurrent(NULL,NULL); // Уничтожение созданного контекста wglDeleteContext(Hrc); } //=================================================// Служебная функция – настройка параметров OpenGL BOOL TOpenGLInstr::SetupGLParams(HDC *pHdc) { // Параметры перспективной проекции const GLfloat zNear=0.1; // Ближняя плоскость отсечения const GLfloat zFar=1000.0; // Дальняя плоскость отсечения const GLfloat vAngle=30.0; // Угол зрения HDC Hdc; // Контекст устройства (окна) Windows // Расположение источника освещения const double lightDistance=500.0; // Расстояние до объекта const double lightRotation=-55.0; // Азимут в градусах const double lightPitch=45.0; // Угол места в градусах // Вспомогательные переменные RDS_PANDESCRIPTION descr; int width,height; GLfloat array[4]; double l_r,l_p; // Получение описания панели и дескриптора ее окна descr.servSize=sizeof(RDS_PANDESCRIPTION); if(!RDS(Panel,&descr)) // Не удалось return FALSE; if(descr.Handle==NULL) // Нет оконного объекта return FALSE; // Проверка высоты и ширины панели if(descr.Height==0 || descr.Width==0) return FALSE; // Негде рисовать // Получение контекста окна и передача в вызвавшую функцию // его через параметр-указатель Hdc=GetDC(descr.Handle); if(pHdc) *pHdc=Hdc; // Установка контекста Hrc, созданного при инициализации, // в качестве текущего if(!wglMakeCurrent(Hdc,Hrc)) return FALSE; // Не удалось // Уcтановка различных параметров, влияющих на качество рисования // и способ закраски многоугольников glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glHint(GL_POLYGON_SMOOTH_HINT,GL_FASTEST); glEnable(GL_POINT_SMOOTH); glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.0f,0.0f,0.0f,1.0f); // Цвет фона - черный glClearDepth(1.0); // Значение для очистки Z-буфера //----------- Установка освещения ---------- // Общее рассеянное освещение array[0]=array[1]=array[2]=0.5; // Белый, интенсивность 0.5 array[3]=1.0; glLightModelfv(GL_LIGHT_MODEL_AMBIENT,array); // Вычисление координат источника света l_r=(lightRotation*M_PI)/180.0; l_p=(lightPitch*M_PI)/180.0; array[0]=(GLfloat)(lightDistance*cos(l_p)*sin(l_r)); // X array[1]=(GLfloat)(lightDistance*sin(l_p)); // Y array[2]=(GLfloat)(lightDistance*cos(l_p)*cos(l_r)); // Z array[3]=0.0; glLightfv(GL_LIGHT0,GL_POSITION,array); // Рассеянное освещение от источника отсутствует array[0]=array[1]=array[2]=0.0; // Отсутствует - интенсивность 0 array[3]=1.0; glLightfv(GL_LIGHT0,GL_AMBIENT,array); // Другие виды освещения – белый цвет array[0]=array[1]=array[2]=0.5; // Белый, интенсивность 0.5 glLightfv(GL_LIGHT0,GL_DIFFUSE,array); glLightfv(GL_LIGHT0,GL_SPECULAR,array); // Включение источника света glEnable(GL_LIGHT0); // Разрешение расчета освещения glEnable(GL_LIGHTING); // Режим расчета “затенения" glShadeModel(GL_SMOOTH); // Способ расчета освещения glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); //------------------------------------------ // Установка области окна для рисования glViewport(0,0,descr.Width,descr.Height); // Настройка перспективной проекции на эту область glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(vAngle, (GLfloat)descr.Width/(GLfloat)descr.Height, zNear,zFar); // Переключение на матрицу моделей (для рисования объектов) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return TRUE; // Установка параметров успешно завершена } //=================================================// Рисование трехмерной сцены void TOpenGLInstr::RenderScene(double Dir,double List,double Pitch) { HDC Hdc; // Контекст устройства Windows // Угол места камеры в градусах const GLfloat Camera_Pitch=-50.0; // Расстояние до камеры const GLfloat Camera_Distance=300.0; // Настройка параметров OpenGL и получение контекста окна if(!SetupGLParams(&Hdc)) return; // Очистка буфера изображения и Z-буфера glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Записать матрицу трансформаций в стек glPushMatrix(); // Трансформации камеры glTranslatef(0.0,0.0,-Camera_Distance); // Отодвигаем от камеры glRotatef(Camera_Pitch,1,0,0); // Поворачиваем // Рисование неподвижной зеленой (0,1,0) окружности DrawCircleGL(60,100,0.0,1.0,0.0); if(Dir!=DoubleErrorValue && List!=DoubleErrorValue && Pitch!=DoubleErrorValue) // Можно рисовать { // Поворот на угол курса if(Dir!=0.0) glRotatef(Dir,0,0,1); // Поворот на угол дифферента if(Pitch!=0.0) glRotatef(Pitch,1,0,0); // Поворот на угол крена if(List!=0.0) glRotatef(-List,0,1,0); // Рисование подвижной белой (1,1,1) окружности DrawCircleGL(55,100,1.0,1.0,1.0); // Рисование центрального объекта DrawArrowGL(50,80,30,10,10); } // Восстановить матрицу трансформаций из стека glPopMatrix(); // Завершить незавершенное рисование, если нужно glFlush(); // Поменять местами видимый и рабочий буферы SwapBuffers(Hdc); } //=================================================// Модель блока с панелью extern "C" __declspec(dllexport) int RDSCALL OpenGLInstr( int CallMode, RDS_PBLOCKDATA BlockData, LPVOID ExtParam) {// Макроопределения для статических переменных #define pStart ((char *)(BlockData->VarTreeData)) #define Start (*((char *)(pStart))) #define Ready (*((char *)(pStart+RDS_VSZ_S))) #define Dir (*((double *)(pStart+2*RDS_VSZ_S))) #define List (*((double *)(pStart+2*RDS_VSZ_S+RDS_VSZ_D))) #define Pitch (*((double *)(pStart+2*RDS_VSZ_S+2*RDS_VSZ_D)))// Указатель на личную область, приведенный к нужному типу TOpenGLInstr *data=(TOpenGLInstr*)(BlockData->BlockData); // Вспомогательная – указатель на структуру параметров при // действиях с панелью (будет использована в реакциях) RDS_PPANOPERATION param; switch(CallMode) { // Инициализация блока case RDS_BFM_INIT: // Создание личной области данных // (при этом в конструкторе будет создана панель) BlockData->BlockData=data=new TOpenGLInstr(); break; // Очистка данных блока case RDS_BFM_CLEANUP: // В деструкторе класса панель будет уничтожена delete data; break;// Проверка типа переменных case RDS_BFM_VARCHECK: if(strcmp((char*)ExtParam,"{SSDDD}")) return RDS_BFR_BADVARSMSG; return RDS_BFR_DONE;// Запуск расчета case RDS_BFM_STARTCALC: // Создание таймера обновления data->CreateRefreshTimer(BlockData->Parent); break; // Вызов функции настройки или двойной щелчок // левой кнопки мыши case RDS_BFM_SETUP: case RDS_BFM_MOUSEDBLCLICK: // Показать панель rdsSetObjectInt(data->Panel,RDS_PAN_VISIBLE,0,1); break; // Сохранение параметров блока case RDS_BFM_SAVETXT: data->SaveText(); break; // Загрузка параметров блока case RDS_BFM_LOADTXT: data->LoadText((char*)ExtParam); break; // Действия с панелью case RDS_BFM_BLOCKPANEL: // Приведение указателя на структуру, переданного в // ExtParam, к нужному типу param=(RDS_PPANOPERATION)ExtParam; // Разные действия в зависимости от операции с панелью switch(param->Operation) { // Создание оконного объекта для панели case RDS_PANOP_CREATE: // Настройка вывода изображения на панель data->InitWindow(param->Panel->Handle); break; // Уничтожение оконного объекта панели case RDS_PANOP_DESTROY: // Отключение OpenGL data->Clear(); break; // Размер панели изменен case RDS_PANOP_RESIZED: // При изменении размера – просто перерисовка data->RenderScene(Dir,List,Pitch); break; // Необходимо перерисовать изображение case RDS_PANOP_PAINT: data->RenderScene(Dir,List,Pitch); break; } break; // Необходимо обновить окна блока (вызывается таймером) case RDS_BFM_WINREFRESH: // Перерисовка изображения data->RenderScene(Dir,List,Pitch); break; } return RDS_BFR_DONE;// Отмена макроопределений #undef Pitch #undef List #undef Dir #undef Ready #undef Start #undef pStart} //=================================================