?

Log in

No account? Create an account

Пн, 6 авг, 2007, 20:13
Пиксельные новости

Как происходит процесс рисования пиксельного дома? Я фотографирую его со всех сторон «на пленере», а потом дома пытаюсь восстановить трёхмерную модель. Чтобы модель была точной, помимо фотографий нужно как-то промерить расстояния. Рассматривались разные способы, но не один не подходил: измерять в шагах (очень неточно), измерять рулеткой (точно, но обалдеешь), купить лазерный дальномер или какой-нибудь GPS (не спортивно). Поэтому до сих пор я делал это просто на глазок.

И вот, наконец, лучший способ найден — измерять расстояния в тратуарных плитках. В Протвино они лежит практически повсеместно, размер имеет одинаковый, и, что приятно, удобный: например, секция стандартного девятиэтажного дома в ширину имеет ровно восемь плиток.

Ещё очень важно выбрать правильный масштаб для рисования, чтобы всё аккуратно ложилось на «точечки» (поскольку dithering принципиально не используется). Оказалось, что каким-то чудом я выбрал практически идеальный масштаб: ровно два пиксела на плитку. И угадал с размерами домов — всё сошлось с результатами измерений один в один. Вот с третьей школой промахнулся, конечно. Но не сильно.

А помимо домов, в городе ещё растут деревья. И, в отличие от домов, они все разные. Спрашивается, как их рисовать?

А для этого надо вспомнить, что мы программисты, и вооружиться древним, как Scientific American, фрактальным алгоритмом рисования деревьев. Смысл его в том, что дерево имеет выраженную рекурсивную структуру. Пусть процедура нарисует нам кусок ствола, а затем вызовем её саму пару раз под разными углами из той точки, в которую пришли. Вот двоичное дерево и готово.

А вот как выглядит такая программка на Пёрле (ActiveState Perl + GD), чтобы было понятно, о чём речь:

use GD;

$im = new GD::Image(200,200);
$white = $im->colorAllocate(255,255,255);
$black = $im->colorAllocate(0,0,0);
$im->transparent($white);

sub tree {
  my ($x,$y,$len,$a,$level) = @_;

  my $x1 = $x + $len * cos($a);
  my $y1 = $y + $len * sin($a);
  $im->line($x,$y,$x1,$y1,$black);

  if ($level > 0) {
    tree($x1,$y1,$len-$len*rand(0.3),$a-rand(0.3),$level-1);
    tree($x1,$y1,$len-$len*rand(0.3),$a+rand(0.3),$level-1);
  }
}

tree(100,200,25,-3.14/2,10);

open(PIC,">tree.png") or die("Cannot open file for writing");
binmode PIC;
print PIC $im->png;
close PIC;

Осталась малость: подкрутить её так, чтобы получалось нечто, похожее, скажем, на берёзу. Вот лучшее, чего я пока добился:

Для этого пришлось научить программу выпускать веточки с разной вероятностью и под определённым углом в зависимости от текущего уровня, а также заставить ствол тянуться кверху, а листочки — книзу.

На самом деле, настройка такой программы — очень увлекательное занятие. Чувствуешь себя эдаким Мичуриным, способным вырастить на сосне яблоки. Программисты, принимайте участие в конкурсе на лучшее дерево!

Пн, 6 авг, 2007 16:37 (UTC)
_pk_sly

у меня GD не ставится 8(

ppm ругается что все area - readonly

Вт, 7 авг, 2007 07:04 (UTC)
egorius

Мне, похоже, повезло, у меня Пёрл старенький. А тебе, наверное, надо новый раздел инициализировать? см.

Вт, 7 авг, 2007 08:45 (UTC)
_pk_sly

да, я специально поставил самый последний.
хотел метапрограммированием побаловаться (Filter::Simple и т.п.), а эта хрень появилась только в версии 5.8

раньше стоял Перл из стандартного дистрибутива.

"см" не помогло - мучил, мучил его.. оказалось тупо что на файлах стоял атрибут read-only :) снял - свё встало.

кусты прикольные получаются :)

Вт, 7 авг, 2007 11:26 (UTC)
_pk_sly

Егор, а есть модуль, аналогичный OpenGL или DirectX?
Вроде, в GD было что-то.

Или хотя бы с GDI-функциями?

Вт, 7 авг, 2007 11:41 (UTC)
egorius

Без понятия, если честно. Я и про GD-то только неделю назад узнал, когда понадобилось :)

Вт, 7 авг, 2007 11:53 (UTC)
_pk_sly

О!
вспомнил.
там же есть Tk!

спасибо :)

Пн, 6 авг, 2007 19:35 (UTC)
tnt23

аатлична!