![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
|
Вопрос не столько по Delphi, сколько по WinAPI.
Пишу программку на чистом WinAPI, застопорился на обработке крысиных событий. Сабж: есть некое поле, прорисованное в пространстве (камера под углом ~45 градусов). Надо узнать координаты мыши над этим полем (если она, конечно, над ним). Просчитывать вручную, конечно, можно (благо координаты известны и геометрию знаем), но уж очень не хочется... ![]() |
|
#2
|
||||
|
||||
|
Цитата:
|
|
#3
|
||||
|
||||
|
Поле двигается, вертится, размер формы меняется как угодно, есть полноэкранные и оконные режимы
![]() Я так понимаю, в пакете gl* не предусмотрено получение координат в пространстве по координатам мыши над "камерой"? |
|
#4
|
||||
|
||||
|
Все-таки OpenGL, а не просто WinAPI.
Что то я такое у Краснова видел. Там вроде имеется пример, когда при наведении мышки на объект происходит определённое событие.Ага, нашёл. Смотри, может подойдёт: Код:
{**********************************************************************}
{* Иллюстрация к книге "OpenGL в проектах Delphi" *}
{* Краснов М.В. softgl@chat.ru *}
{**********************************************************************}
{*********************************************************************}
{(c) Copyright 1993, Silicon Graphics, Inc.
ALL RIGHTS RESERVED}
program Select;
uses
Messages, Windows, OpenGL;
const
AppName = 'GL_Select';
MAXOBJS = 20; // максимальное число объектов
MAXSELECT = 4; // размер буфера выбора
{--- запись для хранения объектов ---}
type
TGLObject = record // объект - треугольник
{вершины треугольника}
v1 : Array [0..1] of GLFloat;
v2 : Array [0..1] of GLFloat;
v3 : Array [0..1] of GLFloat;
color : Array [0..2] of GLFloat; // цвет объекта
end;
Var
Window : HWnd;
Message : TMsg;
WindowClass : TWndClass;
windW, windH : GLint;
dc : HDC;
hrc : HGLRC;
ps : TPAINTSTRUCT;
objects : Array [0..MAXOBJS - 1] of TGLObject; // массив объектов
vp : Array [0..3] of GLint;
selectBuf : Array [0..MAXSELECT - 1] of GLuint;// буфер выбора
hit : GLint;
mouseX, mouseY : Integer;
{=======================================================================
Инициализация объектов}
procedure InitObjects;
var
i : GLint ;
x, y : GLfloat ;
begin
For i := 0 to MAXOBJS - 1 do begin
x := random(300) - 150;
y := random(300) - 150;
// вершины треугольника - случайно
objects[i].v1[0] := x + random(50) - 25;
objects[i].v2[0] := x + random(50) - 25;
objects[i].v3[0] := x + random(50) - 25;
objects[i].v1[1] := y + random(50) - 25;
objects[i].v2[1] := y + random(50) - 25;
objects[i].v3[1] := y + random(50) - 25;
// цвета выбираются случайными
objects[i].color[0] := (random(100) + 50) / 150.0;
objects[i].color[1] := (random(100) + 50) / 150.0;
objects[i].color[2] := (random(100) + 50) / 150.0;
end;
end;
{=======================================================================
Рисование массива объектов}
procedure Render (mode : GLenum); // параметр - режим (выбора/рисования)
var
i : GLuint;
begin
For i := 0 to MAXOBJS - 1 do begin
If mode = GL_SELECT then glLoadName(i); // загрузка очередного имени
glColor3fv(@objects[i].color); // цвет для очередного объекта
glBegin(GL_POLYGON); // рисуем треугольник
glVertex2fv(@objects[i].v1);
glVertex2fv(@objects[i].v2);
glVertex2fv(@objects[i].v3);
glEnd;
end;
end;
{=======================================================================
Выбор объекта в точке}
function DoSelect(x : GLint; y : GLint) : GLint;
var
hits : GLint;
begin
glSelectBuffer(MAXSELECT, @selectBuf); // создание буфера выбора
glRenderMode(GL_SELECT); // режим выбора
// режим выбора нужен для работы следующих команд
glInitNames; // инициализация стека имен
glPushName(0); // помещение имени в стек имен
glGetIntegerv(GL_VIEWPORT, @vp);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPickMatrix(x, windH-y, 4, 4, @vp);
gluOrtho2D(-175, 175, -175, 175);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
Render(GL_SELECT); // рисуем массив объектов с выбором
hits := glRenderMode(GL_RENDER);
if hits <= 0
then DoSelect := -1
else DoSelect := selectBuf[3];
end;
{=======================================================================
Изменение цвета объекта номер h}
procedure RecolorTri (h : GLint);
begin
objects[h].color[0] := (random(100) + 50) / 150.0;
objects[h].color[1] := (random(100) + 50) / 150.0;
objects[h].color[2] := (random(100) + 50) / 150.0;
end;
{=======================================================================
Основная процедура рисования картинки}
procedure DrawScene;
begin
glPushMatrix;
glGetIntegerv(GL_VIEWPORT, @vp);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluOrtho2D(-175, 175, -175, 175);
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
Render(GL_RENDER); // рисуем массив объектов без выбора
glPopMatrix;
glFlush;
end;
procedure SetDCPixelFormat (hdc : HDC);
var
pfd : TPIXELFORMATDESCRIPTOR; // данные формата пикселей
nPixelFormat : Integer;
Begin
With pfd do
begin
nSize := sizeof (TPIXELFORMATDESCRIPTOR); // размер структуры
nVersion := 1; // номер версии
dwFlags := PFD_DRAW_TO_WINDOW OR PFD_SUPPORT_OPENGL; // множество битовых флагов, определяющих устройство и интерфейс
iPixelType := PFD_TYPE_RGBA; // режим для изображения цветов
cColorBits := 16; // число битовых плоскостей в каждом буфере цвета
cRedBits := 0; // число битовых плоскостей красного в каждом буфере RGBA
cRedShift := 0; // смещение от начала числа битовых плоскостей красного в каждом буфере RGBA
cGreenBits := 0; // число битовых плоскостей зелёного в каждом буфере RGBA
cGreenShift := 0; // смещение от начала числа битовых плоскостей зелёного в каждом буфере RGBA
cBlueBits := 0; // число битовых плоскостей синего в каждом буфере RGBA
cBlueShift := 0; // смещение от начала числа битовых плоскостей синего в каждом буфере RGBA
cAlphaBits := 0; // число битовых плоскостей альфа в каждом буфере RGBA
cAlphaShift := 0; // смещение от начала числа битовых плоскостей альфа в каждом буфере RGBA
cAccumBits := 0; // общее число битовых плоскостей в буфере аккумулятора
cAccumRedBits := 0; // число битовых плоскостей красного в буфере аккумулятора
cAccumGreenBits := 0; // число битовых плоскостей зелёного в буфере аккумулятора
cAccumBlueBits := 0; // число битовых плоскостей синего в буфере аккумулятора
cAccumAlphaBits := 0; // число битовых плоскостей альфа в буфере аккумулятора
cDepthBits := 32; // размер буфера глубины (ось z)
cStencilBits := 0; // размер буфера трафарета
cAuxBuffers := 0; // число вспомогательных буферов
iLayerType := PFD_MAIN_PLANE;// тип плоскости
bReserved := 0; // число плоскостей переднего и заднего плана
dwLayerMask := 0; //
dwVisibleMask := 0; // индекс или цвет прозрачности нижней плоскости
dwDamageMask := 0; // игнорируется
end;
nPixelFormat := ChoosePixelFormat (hdc, @pfd); // запрос системе - поддерживается ли выбранный формат пикселей
SetPixelFormat (hdc, nPixelFormat, @pfd); // устанавливаем формат пикселей в контексте устройства
End;
function WindowProc (Window : HWnd; Message, WParam : Word;
LParam : LongInt) : LongInt; export; stdcall;
Begin
WindowProc := 0;
case Message of
wm_Destroy : begin
wglMakeCurrent (0, 0);
wglDeleteContext (hrc);
ReleaseDC (Window, DC);
DeleteDC (DC);
PostQuitMessage (0);
Exit;
end;
WM_CREATE: begin
Randomize;
dc := GetDC (Window);
SetDCPixelFormat (dc);
hrc := wglCreateContext (dc);
wglMakeCurrent (dc, hrc);
InitObjects;
end;
WM_SIZE: begin
windW := LOWORD (lParam);
windH := HIWORD (lParam);
glViewport(0, 0, windW, windH);
end;
WM_PAINT: begin
BeginPaint (Window, ps);
DrawScene;
EndPaint (Window, ps);
end;
WM_LBUTTONDOWN: {--- реакция на щелчок мыши ---}
begin
mouseX := LoWord (lParam);
mouseY := HiWord (lParam);
hit := DoSelect(mouseX, mouseY); // номер объекта под курсором
If hit <> -1 then RecolorTri(hit); // перекрашиваем объект
InvalidateRect(Window, nil, False); // обновляем картинку
end;
end; // case
WindowProc := DefWindowProc (Window, Message, WParam, LParam);
End;
Begin
With WindowClass do begin
Style := cs_HRedraw or cs_VRedraw;
lpfnWndProc := @WindowProc;
hCursor := LoadCursor (0, idc_Arrow);
lpszClassName := AppName;
end;
RegisterClass (WindowClass);
Window := CreateWindow (AppName, AppName,
ws_OverlappedWindow or ws_ClipChildren or ws_Clipsiblings,
cw_UseDefault, cw_UseDefault, cw_UseDefault, cw_UseDefault,
HWND_DESKTOP, 0, HInstance, nil);
ShowWindow (Window, CmdShow);
While GetMessage (Message, 0, 0, 0) do begin
TranslateMessage (Message);
DispatchMessage (Message);
end;
End.Последний раз редактировалось angvelem, 23.08.2011 в 02:58. |
|
#5
|
||||
|
||||
|
После недельной работы в C++ минуты 2 вдуплял в код на Delphi...
Ничего так запутано. Будем разбираться... А обязательно объекты? А если их много? Лучше всё-таки координаты... А, забыл сказать. Все координаты поля на нулевой Z-координате. |
|
#6
|
||||
|
||||
|
Цитата:
К сожалению других подобных примеров не встречал, а мне было без надобности. P.S. А код в принципе простой, это после С++ так кажется. ![]() |
|
#7
|
||||
|
||||
|
Ну, вертится и двигается оно исключительно по осям X и Y, а Z-координаты всех точек постоянны.
|
|
#8
|
||||
|
||||
|
Не согласен, когда поле вращается его стороны уходят с нулевой позиции.
|
|
#9
|
||||
|
||||
|
Код:
glPushMatrix(); glRotatef(rotangle,0,0,1); .... glPopMatrix(); /*Возникла ещё одна проблема. При прорисовке текста резко падает яркость. GL_NORMALIZE включен. При замене WGL_FONT_POLYGONS на WGL_FONT_LINES всё нормально, но шрифты не закрашены, что обидно.*/ Проблема решена, такое происходит только при extrusion !=0. Хотя хрен знает, из-за чего так... ![]() Последний раз редактировалось PhoeniX, 23.08.2011 в 04:08. |