Как быстро рисовать bmp в перспективе без OpenGL и DirectX

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Как быстро рисовать bmp в перспективе без OpenGL и DirectX

Сообщение Sheleh » 01.12.2010 09:39:47

Делаю тайловый (как googlemap) картографический двиг. Пока все работает в плоскости экрана, но есть мысль выводить карту под наклоном для придания эффекта перспективы. И вот возникает вопрос: как нарисовать квадратное изображение по новым изометрическим координатам. Может уже есть какая-нибудь функция типа DrawStretch, но рисующая BitMap не по двум точкам, а по 4-м?

Изображение Изображение
Последний раз редактировалось Sheleh 06.12.2010 11:01:03, всего редактировалось 2 раз(а).
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение Mr.Smart » 01.12.2010 09:48:44

Вам же предложили воспользоваться OpenGL. Почему упрямитесь?
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение Sheleh » 01.12.2010 10:28:57

Вам же предложили воспользоваться OpenGL. Почему упрямитесь?
Потому что:
1. Ни разу не работал с OpenGL;
2. OpenGL, что работает под windows не компилируется под WinCE;
3. Не могу найти OpenGL, кторый бы работал на любом WM устройстве. Даже просто набирая в поисковике слова OpenGL+Lazarus+WinCE не находится ничего внятного.
4. Хочется поломать мозг с преобразованием плоских координат в изометрические;
5. Я пишу не 3D шутер, а всего лишь обычную плоскость с наклоном, так что возможно и не требуется использование вычислительной мощи видеоустройств;
6. Да и осталось всего лишь придумать как выводить картинку в свободном вращении/искажении.
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение Nik » 01.12.2010 10:38:30

6. Да и осталось всего лишь придумать как выводить картинку в свободном вращении/искажении.

Попробуйте поискать алгоритм такого преобразования изображений. В Сети наверняка есть (не факт, что для Delphi/Lazarus).
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение zub » 01.12.2010 14:52:39

первая картинка - без перспективы, такого эффекта ка на второй не будет
но есть мысль выводить карту под наклоном для придания эффекта перспективы

эффект перспективы без собственно перспективы не получить. выводить под наконом - получится под наклоном вся вся картинка (т.е. сплюснутая), а не ближние объекты больше, дальние меньше.
пошарте http://www.crossgl.com/aggpas/aggpas-demo.htm, там вроде было перспективное искажение растров.

также можно погуглить алгоритмы текстурирования
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение Sheleh » 01.12.2010 15:31:29

эффект перспективы без собственно перспективы не получить. выводить под наконом - получится под наклоном вся вся картинка (т.е. сплюснутая), а не ближние объекты больше, дальние меньше.
Да это понятно. Я надеюсь добиться эффекта с помощью сетки. Чем дальше, тем чаще будет сетка, как на втором рисунке. Вроде должно получится.
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение Sheleh » 03.12.2010 15:49:28

решил попробовать самостоятельно реализовать процедуру пространственного искажения хотя бы безо всяких сглаживаний. Для начала заменил
ImageLayer.Canvas.Draw(x,y,BmpCache[]);

попиксельным копированием изображения обычными методами:
for i:=0 to 255 do
for j:=0 to 255 do
begin
ImageLayer.canvas.pixels[i+x,j+y]:=BmpCache[].canvas.pixels[i,j];
end;


В ответ получил страшенные тормоза, и в связи с этим назрел новый вопрос: как быстро считать пиксель из TBitmap и вывести его на TImage.canvas? Желательно что бы это работало и для Win32 и для WinCE
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение .wOvAN » 03.12.2010 16:44:16

Sheleh Выводить на TImage.canvas нужно уже готовую картинку, а пиксели копировать на невидимый битмап. Это вероятно ускорит процесс.
.wOvAN
постоялец
 
Сообщения: 118
Зарегистрирован: 16.04.2010 06:36:12

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение FedeX » 03.12.2010 18:20:21

И для попиксельной обработки производительнее будет если использовать TLazIntfImage - в папке с лазарусом (Examples) есть пример как это использовать, там есть прямой доступ к памяти изображения. В Делфи был аналогично производительный способ доступа к памяти изображения через сканлайны битовой карты, но в Лазарусе отчего-то сделали иначе..
Аватара пользователя
FedeX
постоялец
 
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение alexrayne » 04.12.2010 15:38:03

Mr.Smart писал(а):Потому что:1. Ни разу не работал с OpenGL;

Ну а directX почему неустраивает? на старых вендах он был даже пошустрее опенГЛа, ибо опенГЛ был сделан как обертка директа.

Добавлено спустя 2 минуты 9 секунд:
Я етот вопрос к тому что упаритесь вы попиксельно картинку перспективить, вы добьетесь того что страшные тормоза станут просто тормозами, думаете что этого вам хватит?
alexrayne
постоялец
 
Сообщения: 125
Зарегистрирован: 03.12.2008 16:56:26

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение Sheleh » 06.12.2010 10:48:13

FedeX писал(а):И для попиксельной обработки производительнее будет если использовать TLazIntfImage - в папке с лазарусом (Examples) есть пример как это использовать, там есть прямой доступ к памяти изображения. В Делфи был аналогично производительный способ доступа к памяти изображения через сканлайны битовой карты, но в Лазарусе отчего-то сделали иначе..
Попробовал, работа с пикселями вроде не тормозная, но вот что бы результат вывести на канаву сначала надо сформировать битмап
TempIntfImg.CreateBitmaps(ImgHandle,ImgMaskHandle,true);
, что происходит достаточно долго.

В общем я нашел более простой альтернативный способ прямого доступа к пикселям битмапа - API функция CreateDIBSection (win32, wince). В аттаче находится пример, демонстрирующий производительность (белый шум) на Delphi (у меня 6-ка стоит). Но я не могу перенести его на лазарус, он не узнает структуру tagBITMAPINFO, которая должна находится в модуле Windows. Господа специалисты, помогите добавить эту структуру
var
BInfo: tagBITMAPINFO; Error: Identifier not found "tagBITMAPINFO"
begin
// Создание DIB
BInfo.bmiHeader.biSize := sizeof(tagBITMAPINFOHEADER);
BInfo.bmiHeader.biWidth := SX;
BInfo.bmiHeader.biHeight := -SY;
BInfo.bmiHeader.biPlanes := 1;
BInfo.bmiHeader.biBitCount := 32;
BInfo.bmiHeader.biCompression := BI_RGB;
ScrBitmap := TBitmap.Create();
ScrBitmap.Handle := CreateDIBSection(ScrBitmap.Canvas.Handle, BInfo, DIB_RGB_COLORS, Scr, 0, 0);
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

Re: Как рисовать bitmap на канаве в виде трапеции (к примеру)

Сообщение FedeX » 06.12.2010 11:05:34

просто подключи модуль bmpcomn.pp ,там есть эта структура, хотя и называеться TBitMapInfoHeader. Просто tagBITMAPINFO содержит ее в себе и вроде больше ничего кроме неё, возможно ввиду того, что в заголовке битмапа могут быть ещё иные данные (но как правило их нет). Это только предположение - давно с винапи не работал.
Аватара пользователя
FedeX
постоялец
 
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Re: Как быстро рисовать bmp в перспективе без OpenGL и DirectX

Сообщение Sheleh » 06.12.2010 12:00:26

FedeX
Вот, согласно предположению, действительно есть в TBitMapInfoHeader нужные записи:
var
BInfo: TBitMapInfoHeader;
//tagBITMAPINFO;
begin
// Создание DIB
SX := aSX; SY := aSY;
BInfo.Size:=sizeof(BInfo);
BInfo.Width := SX;
BInfo.Height := -SY;
BInfo.Planes := 1;
BInfo.BitCount := 32;
BInfo.Compression := BI_RGB;
ScrBitmap := TBitmap.Create();
ScrBitmap.Handle := CreateDIBSection(ScrBitmap.Canvas.Handle, BInfo, DIB_RGB_COLORS, Scr, 0, 0);

Только теперь компилятор ругается на несоответствие типов:
Error: Call by var for arg no. 2 has to match exactly: Got "TBitMapInfoHeader" expected "BITMAPINFO"
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

Re: Как быстро рисовать bmp в перспективе без OpenGL и DirectX

Сообщение FedeX » 06.12.2010 12:12:47

Вообщем я не правильно предположил tagBITMAPINFO содержит ещё поле bmiColors : array[0..0] of RGBQUAD; которое правда действительно можно опустить если изображение не содержит палитры..
http://msdn.microsoft.com/en-us/library/dd183375%28VS.85%29.aspx.
Я ещё раз воспользовался полнотекстовым поиском по файловой системе (из JEdit) и обнаружил правильную структуру соответствующую tagBITMAPINFO - BITMAPINFO. Она находиться в файле struct.inc который поидее должен быть подключен к модулю Windows . Попробуй просто в заголовке своего модуля или в другом месте написать: {$IFDEF FPC}type tagBITMAPINFO=TBITMAPINFO;{$ENDIF}
Аватара пользователя
FedeX
постоялец
 
Сообщения: 422
Зарегистрирован: 27.03.2006 09:25:34
Откуда: украина, житомир

Re: Как быстро рисовать bmp в перспективе без OpenGL и DirectX

Сообщение Sheleh » 06.12.2010 12:23:54

написал во так:
procedure TForm1.CreateBitmap(aSX, aSY: Integer);
var
BInfo: TBitmapInfo;
begin
// Создание DIB
SX := aSX; SY := aSY;
BInfo.bmiHeader.biSize := sizeof(BitmapInfo.bmiHeader);
BInfo.bmiHeader.biWidth := SX;
BInfo.bmiHeader.biHeight := -SY;
BInfo.bmiHeader.biPlanes := 1;
BInfo.bmiHeader.biBitCount := 32;
BInfo.bmiHeader.biCompression := BI_RGB;
ScrBitmap := TBitmap.Create();
ScrBitmap.Handle := CreateDIBSection(ScrBitmap.Canvas.Handle, BInfo, DIB_RGB_COLORS, Scr, 0, 0);
ZeroMemory(Scr, SX * SY * 4);
end;

Работает на 100%

Добавлено спустя 2 часа 12 минут 33 секунды:
Ура!!!

В общем сделал пока так: кэш тайлов теперь храню не в TBitmap, а в TLazIntfImage - из него быстрее всего считывать пиксели, а вывожу на канаву с помощью CreateDIBSection. На разрешении 1280х1024 есть небольшая задержка движения изображения за указателем, но это уже совсем не те тормоза, которые были раньше. Плюс для каждого пикселя у меня происходит проверка, что бы он не зашел за границы экрана, а это 4 условия с операциями сложения. Это надо будет оптимизировать и продумать возможность использования 8-ми битных изображений.
Sheleh
новенький
 
Сообщения: 24
Зарегистрирован: 12.11.2010 18:31:07

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 38

Рейтинг@Mail.ru