angle = 0.61; locX = 2.25; locY =4.85;
swing = tan ( VIEW_WIDTH / 2 );
initTables (); setVideoMode (0x13 );
int start = clock ();
while (Idone ) {
drawView ();
if ( bioskey (1 )) {
float vx = cos ( angle ); float vy = sin ( angle ); float x, y;
switch ( bioskey ( 0 )) {
case LEFT
angle -=5.0*M_PI/180.0; break;
case RIGHT:
angle +=5.0*M_PI/18Q.0; break;
case UP:
x = locX + 0.3 * vx; y = locY + 0.3 * vy;
if ( worldMap [(int) y][(int) x] == " ) {
locX = x; locY = y;
}
break;
case DOWN:
x = locX - 0.3 * vx;
13. Элементы виртуальной реальности у = locY - 0.3 * vy;
if ( worldMap [(int) y][(int) x ] == " ) {
locX = x; locY = y;
}
break; case ESC; done = 1;
}
if ( angle < 0 )
angle += 2 * M_PI;
else
if ( angle >= 2 * M_PI ) angle -= 2 * M_PI;
}
}
float totalTime = ( clock () - start ) / CLKJCK; setVideoMode ( 0x03 );
printf ( "\nFrames rendered : %ld", totalFrames );
printf ( "\nTotal time ( sec ) : %7.2f, totalTime );
printf ( "\nFPS : %7.2f, totalFrames / totalTime );
}
Одним из подводных камней, встречающихся при реализации описанного алгоритма, является так называемый fish-eye-эффект - изображение на экране сильно искажается и вместо прямых линий в местах соединения пола (потолка) со стенами видны дуги. Причина подобного явления кроется в неправильном осуществлении перспективного проектирования (при перспективном проектировании образом прямой линии всегда является прямая).
Рассмотрим несколько столбцов пикселов и соответствующие им лучи (рис. 13.6). Вследствие того что изображение строится на плоском экране, высоты столбцов пикселов, соответствующих стенам, получаются как отношение расстояния до стены к расстоянию до экрана f.
Если столбец соответствует центральному лучу, то ооа эти расстояния совпадают. Если же луч отличается от центрального на угол а, то правильное фокусное расстояние равно f/cos а.
Самым простым способом борьбы с этим явлением является коррекция найденного расстояния d - оно домножается на косинус угла между лучом и направлением взгляда.
Основной процедурой этой программы является draw View, строящая изображение сцены, видимой из точки (locX, /ос У), в заданном направлении ang/e; конечно, ее быстродействие оставляет желать лучшего. Причины этого кроются как в неоптимизированно-сти алгоритма, так и в использовании операций с плавающей точкой (f/oat).