Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Проекты > Проекты C++

Ответ
 
Опции темы
Старый 28.12.2013, 03:08   #46
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Сообщение от Samodelkin Посмотреть сообщение
С таким форматом ничего не выйдет - нужно разработать другой формат, который хранит данные о карте в форме отрезков. Возможно для удобства потребуется редактор таких карт.
в zero tolerance тоже 2д-массив карты, просто каждый элемент массива может принимать значения от 00 до FF... но кривизна не произвольная.



(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Samodelkin (28.12.2013)
Старый 28.12.2013, 18:37   #47
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 978
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: raycasting

Я думал над таким решением и мне кажется оно будет со временем усложнять код, ведь здесь используется ветвление - на каждый случай есть своя реализация как его обсчитать. И чем больше будет вариантов стен и их углов (а также еще и текстур или еще чего-то) - тем более запутанный будет становиться код.

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

Конечно ты можешь хранить карту в таком массиве, а перед расчетом лучей преобразовать ее в отрезки, но зачем лишние конвертации если можно сразу хранить и редактировать в отрезках.

Если ты уверен на 100%, что кроме стен под углом 45 тебе ничего не понадобиться, то можешь остановиться на этом варианте.

В любом случае тебе придется делать редактор, потому что править такой массив данных прямо в коде весьма утомительно.
(Offline)
 
Ответить с цитированием
Старый 28.12.2013, 22:41   #48
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Если ты уверен на 100%, что кроме стен под углом 45 тебе ничего не понадобиться, то можешь остановиться на этом варианте.
Да, уверен.

В любом случае тебе придется делать редактор, потому что править такой массив данных прямо в коде весьма утомительно.
Сделать такой редактор не проблема... Но нужно спрва разобраться с этим движком. Пол и потолок всё-таки пришлось убрать. Ещё сделаю где-то на 1/4 экрана интерфейс, заодно меньше пикселей придётся обновлять на экране.

Щас не могу разобраться, как изменить точку схода перспективы, то есть поставить камеру выше. В процедуре рисования спрайтов это задаётся отдельным дефайном, а как быть со стенками не знаю.
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 00:55   #49
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Samodelkin, видал в твоём проЭкте сделана фишка "затенение в глубину" (или туман, если инверсия)

Как сделать это в том движке, на который я глаз положил ?
Там в зависимости от переменной drawStart нужно произвести операцию тонирования со столбцом пикселей текстуры.
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 03:05   #50
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 978
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: raycasting

К сожалению всё руки не доходят посмотреть тот движок, хотя я заметил там несколько классных фич которые надо бы перенять.

Вот мой код:
/*
================================================================================
rc2d::FogCompute
================================================================================
*/
auto rc::rc2d::FogCompute( Pyramid::Vector3f& outColor, const Pyramid::Vector3f& inColor, float rayLen ) const noexcept ->void {
    if ( rayLen > desc.fogMaxClamp ) {
        rayLen = desc.fogMaxClamp;
    } else if ( rayLen < desc.fogMinClamp ) {
        rayLen = desc.fogMinClamp;
    }
    float fogValue = ( rayLen - desc.fogMinClamp ) / ( desc.fogMaxClamp - desc.fogMinClamp );
    fogValue *= desc.fogFactor;
    outColor = inColor + ( desc.fogColor * fogValue );
    outColor.Saturate(); 
}
Сразу замечу что представление цвета я храню в 3д векторе типа float и уже непосредственно при записи в пиксел я конвертирую в uint32. В твоём случае (для возможности игры на mmx и более старых машинах) так лучше не делать.

outColor - результирующий цвет.
inColor - исходный цвет.
rayLen - длина луча до стены (или пола/потолка).

Первая часть функции это условия чтобы регулировать на каком расстоянии туман начинается и на каком он достигает своего максимального значения ( desc.fogMinClamp и desc.fogMaxClamp соответственно ).

Между этими значениями происходит линейная интерполяция, которая осуществляется в следующей строке кода и записывается в fogValue. Результат будет в диапазоне 0.0f - 1.0f.

Затем идет домножение на desc.fogFactor чтобы нормализованное значение изменить таким образом в соответствии с решением задуманным дизайнером.

Дальше мы умножаем на desc.fogColor чтобы задать цвет туману и прибавляем результат цвета к исходному inColor цвету пиксела.

Затем функция Saturate просто обрезает (не нормализует) значения вектора в диапазон [0.0f; 1.0f] - это аналогично функции saturate или clamp( x, 0.0f, 1.0f ) из HLSL.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
alko (29.12.2013)
Старый 29.12.2013, 13:29   #51
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

всё очень печально
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра)
Комп как бы намекает, что это всё плохая затея.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Samodelkin (29.12.2013)
Старый 29.12.2013, 17:26   #52
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 978
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: raycasting

Сообщение от alko Посмотреть сообщение
всё очень печально
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра)
Комп как бы намекает, что это всё плохая затея.
Ну как я уже выше написал мой код расчитан на новое железо и хорошую графику

Попробуй вот так (код я не проверял и не компилировал):
uint32_t fog( const uint32_t inColor, const uint32_t rayLen, const uint8_t factor ) {
	uint16_t color[ 3 ];
	color[ 0 ] = ( char )( inColor >> 8 );
	color[ 1 ] = ( char )( inColor >> 16 );
	color[ 2 ] = ( char )( inColor >> 24 );

	if ( rayLen < ( 256 << factor ) - 256 ) {
		color[ 0 ] += ( rayLen >> factor );
		color[ 1 ] += ( rayLen >> factor );
		color[ 2 ] += ( rayLen >> factor );
		if ( color[ 0 ] >= 256 ) color[ 0 ] = 255;
		if ( color[ 1 ] >= 256 ) color[ 1 ] = 255;
		if ( color[ 2 ] >= 256 ) color[ 2 ] = 255;
		uint32_t outColor = 0;
		outColor |= ( ( ( char )color[ 0 ] ) >> 8 );
		outColor |= ( ( ( char )color[ 1 ] ) >> 16 );
		outColor |= ( ( ( char )color[ 2 ] ) >> 24 );
		return outColor;
	} else {
		return 0xffffff00;
	}
}
factor сначала задавай 0, а потом 1 и выше до 7 включительно.

Тут главное не напутать с форматом цвета. Например согласно little endian 4 байтное число 0xaabbccdd на самом деле записывается в память в обратном порядке - ddccbbaa. Таким образом при преобразовании типа, например в 2 байтное число оно превратится в ddcc, то есть 0xccdd если в нормальном представлении. Так что я код написал что у тебя в памяти идет ARGB в таком порядке, то есть в 4 байтном числе это 0xBGRA. Однако операторы сдвига как раз работают с числами в нормальном представлении, то есть для числа 0xaabbccdd если применить >> 24 то будет ожидаемое aa, а не какое то значине справа от числа, так что я просто написал чтобы было понятно как работает внутри

Да кстати расширение mmx (а также sse в более новых машинах) может работать с упакованными значениями - и видимо они здесь как раз кстати подойдут, но я пока сам так еще не делал.
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 19:34   #53
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Сообщение от alko Посмотреть сообщение
Запускал только-что на пентиуме вариант без пола и потолка - 4 кадра в секунду (если в обзор попадает спрайт - 3 кадра).
Это даже без тонирования в глубину.
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 20:07   #54
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Дело не в рейкастинге... Дело в самом quickCG.
Попробовал написать элементарное Хыллоу Ворлд, где будет закрашиваться экран и выводится отмасштабированный в два раза спрайт. И таки шо ви думаете? Эта хрень рисуется тоже 4 кадра пер секонд. (на пентиуме, разумеется... На моём ноуте 150 кадров в секунду)

#ifdef __cplusplus
    #include <cstdlib>
#else
    #include <stdlib.h>
#endif

#include <SDL.h>

#include <cmath>
#include <string>
#include <vector>
#include <iostream>

#include "quickcg.h"
using namespace QuickCG;

#define screenWidth 800
#define screenHeight 600

struct Sprite
{
  float x;
  float y;
  int texture;
};

Sprite sprite[50];

int main(int argc, char *argv[])
{
     double time = 0;
  double oldTime = 0;
    std::vector<Uint32> texture[11];
    unsigned long tw, th;
    Uint32 buffer[screenWidth][screenHeight];
    loadImage(texture[0], tw, th, "rc/gg1.png");

    screen(800, 600, 1, "Metallix zone");

    while(!done())
    {
        int i=0;
  for(int xx=0;xx<800;xx++)
  for(int yy=0;yy<600;yy++)
  buffer[xx][yy]= 0x0f00f0;
        int x=rand()%500,y=rand()%100;
        for(int xx=0;xx<128;xx++){

        for(int yy=0;yy<64;yy++){
        Uint32 color = texture[0][i];
        i++;

        if(color!=0xffffffff)for(int i=0; i<2 ; i++)
        for(int k=0; k<2 ; k++)
        buffer[yy*2+i+x][xx*2+k+y]=color<<8;}
        }
        drawBuffer(buffer[0]);

              oldTime = time;
    time = getTicks();
    double frameTime = (time - oldTime) / 1000.0;
    print(1.0 / frameTime); 
        redraw();
    }
}
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 20:18   #55
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

И тут дело даже не в выборке пикселей из png-картинки.
Тут дело в выводе пикселя, каким бы он ни был.
Там даже обычное заполнение сплошным цветом - 4-5 кадров в секунду.
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 22:45   #56
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 978
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: raycasting

В топку этот quickCG значит. Зачем он нужен? Я у себя рендер делал целиком сам, затем готовый фрейм с помощью SDL 1.2 выводил на экран. Еще лучше заюзать OpenGL или D3D напрямую, даже если не использовать аппаратные плюшки, я просто не в курсе как делали во времена MMX, возможно напрямую VGA юзали. Через чего кстати видеокарта подключена на твоем компе? Может там шина PCI или AGP старая и медленная и менять пиксели из системы очень медленно? Либо алгоритм не самый лучший, например при программировании VGA напрямую есть режим отображения видеопамяти на системную - я так делал когда пробовал написать бутлоадер с графическим интерфейсом через графику BIOS.

Тут тебе видимо тоже рекомендуют на шейдеры перенести

Короче просто попробуй сделать хело ворлд вместе с SDL и посмотреть как на нем будет. Если медленно тогда придется искать другие способы взаимодействия с видеокартой.
(Offline)
 
Ответить с цитированием
Старый 29.12.2013, 23:21   #57
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Через чего кстати видеокарта подключена на твоем компе? Может там шина PCI или AGP старая и медленная и менять пиксели из системы очень медленно?
Видяха PCI ati Rage II. Из api поддерживается только DX 5.0 , и то - для галочки. Tomb Raider на софтверном рендеринге ЦП и то быстрее рисует, нежели та видяха на DX. Она очень медленно текстурирует. А если кубик без текстур вращать - то она быстрее это делает, чем проц.

Тут тебе видимо тоже рекомендуют на шейдеры перенести
Ага. Всех уже задолбал этим рейкастингом.

А какие есть ещё API помимо SDL, чтоб шустро выводить пиксель на экран при помощи ЦП ?

Короче просто попробуй сделать хело ворлд вместе с SDL
quickCG - это набор функций, которые юзают непосредственно SDL. Только якобы быстрее... А на деле - эххх....
http://lodev.org/cgtutor/quickcg.html

Последний раз редактировалось alko, 30.12.2013 в 01:49.
(Offline)
 
Ответить с цитированием
Старый 30.12.2013, 02:29   #58
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 978
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: raycasting

Подожди, тут нужно структурировать:

SDL является прослойкой между приложением и directx для windows или xlib|opengl для linux. Поэтому в твоем случае directx юзается всеравно. quickcg получается еще одной надстройкой над sdl, и если даже он использует sdl каким то хитрым способом, то это в любом случае медленнее чем dx. поэтому если у тебя на видеокарте медленный dx то у тебя sdl быстрей не будет.

Теперь о софтварном рендере. Монитор у тебя всеравно подключен к видеокарте и она в любом случае принимает участие в формировании изображения. Видеокарта соеденина с матплатой посредством agp, pci или pci-express (что там на mmx было?) и это обычно является самым узким местом. Преимущество аппаратного ускорения в том что все текстуры, вершинные буферы и прочая инфа один раз загружается в видеопамять (если не считать изменений и синхронизаций) и затем кадры формируются уже внутри видяхи не затрагивая шину разъема. В случае софтварного рендера у тебя кадр формируется в раме, и значит тебе нужно каждый раз новый кадр переправлять по разъему чтобы видяха его вывела на экран. вот. тут все решает размер этого кадра, то есть его разрешение, глубина цвета и прочие атрибуты.

Если же ты будешь прогать через vga напрямую то тебе даже не нужны ни ось, ни всякие gapi, то есть никакого оверхеда, а так как тебе нужно только копировать кадры из рамы в видяху, минимальных возможностей vga должно быть достаточно. Но там все через асм. И вобщем судя по твоим отчетам о скорости dx на старых компах, я еще больше убеждаюсь что игры тогда программировали именно так - напрямую, без юзания gapi.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
alko (30.12.2013)
Старый 30.12.2013, 13:47   #59
alko
Оператор ЭВМ
 
Регистрация: 21.12.2013
Сообщений: 20
Написано 10 полезных сообщений
(для 10 пользователей)
Ответ: raycasting

Даже не знаю где бы инфу черпануть по перебросу содержимого системного ОЗУ в видео-память на асме. + инициализировать граф. режим надо.
На моём излюбленном спектруме это делалось 5-тью 6-тью инструкциями... IBM-PC куда сложнее в этом плане, при том что большинство инструкций - целые макрокоманды.

Более того, прежде чем перебрасывать содержимое оперы, надо как-то ещё туда и записать само изображение... Быть может SDL даже в буфер медленно записывает.

Хотя не. Кое-что нашёл по VGA-CGA-EGA. Читану на досуге.
http://www.codenet.ru/cat/Applicatio...ESA-Standarts/

Последний раз редактировалось alko, 30.12.2013 в 16:44.
(Offline)
 
Ответить с цитированием
Старый 30.12.2013, 21:55   #60
Samodelkin
Мастер
 
Регистрация: 12.01.2009
Сообщений: 978
Написано 388 полезных сообщений
(для 631 пользователей)
Ответ: raycasting

В режиме VGA ничего перебрасывать не надо, точней там идет отображение адресного пространства, ты пишешь в определенные адреса как в обычное ОЗУ, а система сама перегоняет это в видеопамять.

Ты видимо неправильно SDL использовал. Нужно создать фрейм буфер в ОЗУ через обычный malloc например и обращаться к нему как к двумерному массиву:
uint32_t* buffer = ( uint32_t* )malloc( 320 * 240 * sizeof( uint32_t ) );
buffer[ 100 ][ 200 ] = 0xaabbccdd; // обращение как в 2д массиву (порядок: высота, ширина)
*( buffer + 100 * 320 + 201 ) = 0xaabbccdd; // обращение посредством адресной арифметики (тоже самое по сути)
И затем достаточно сделать только ОДИН вызов SDL чтобы он весь буфер скопировал в видеопамять и вывел на экран. Если ты будешь вызывать каждый раз чтобы записать по одному пикселу то конечно всё будет очень медленно.

Вот я у себя целый класс FrameBuffer сделал чтобы работать с фреймами внутри ОЗУ.

ЗЫ: Размеры массивов в С++ ограничены, поэтому именно через malloc / free лучше с буферами работать.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 11:06.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com