Я пытался начать писать движок, на Visual C++, под DirectX, для чего-нибудь вроде, скажем SeriuosSam. Создал класс CEngine, куда запихнул только инициализацию Direct3D. Дальше надо бы как-нибудь придумать хранение объектов. И тут вот что: Во-первых, поскольку текстуры на объектах везде разные, т.е., например, циллиндр, сделать под бочку - с боков одна текстура, на кругах - другая, так вот, текстуры разные, а рендер делается так: SetStreamSource (.....), потом SetTexture (......), ну и Draw. И что прикажете делать? (Блин, аж возмущаюсь). Группировать вертексы в буффере/массиве по текстурам? (т.е., например - 9 вертексов - одна текстура, и больше нигде такой нет, за ними, 15 вертексов - другая текстура и т.д.) и рендерить отдельным вызовом каждую группу? Ну, тут ладно ещё, если говорить о статичной сцене, гдё всё можно засунуть в один вертексный буффер. А если подвижные модели? Для каждой свой буффер вертексов, да ещё делить каждый буффер на группы по текстурам? Микрософт рекомендует пореже менять StreamSource, и стараться делать поменьше вызовов Draw...Primitive (насколько я помню из хелпа). Может быть это нормально, именно так и делают, но я не хочу пробовать, а то окажется, что это извращение, что никто так не делает....
Подскажите, где взять сырцы движка, или статью какую-нибудь где описано как тут быть, или сами скажите что-нибудь?
PS: Пришёл товарищ, стали скидываться мозгами, договорились до того, что вобщем там сплошная жопа, надо начинать с программы "Hello World!" :)
juriy9
Чего-то у тебя больно много конкретики. Поабстрактнее надо мыслить, когда начинаешь писать движок. Прикинь сначала, какие виды объектов у тебя будут в двигле, сгруппируй их по свойствам, начни прикидывать мегакласс-родитель, реализуюший "концепцию универсального объекта" :-). Да, всякая мелочь типа класса рендера, прочей байды. А там уж и скриптовая система с менеджером ресурсов подоспеют.
А ещё попутно придётся решать проблемы простенькой визуализации, ведения логов, отладки/тестирования алгоритмов (тут может помочь скриптовая система).
Начинают с нескольких своих тестовых програм и с изучения доступных тестов из интернета ...
На основе этого уже моно пытаться опыт отдельных тестов сводить в единую прогу и развивать ее.
Хе хе я начал с классов типа таймер, обработка ввода, вектора, сейчас камеру сделать пытаюсь
Вот кастрированно-абстрактная версия моего движка под OpenGL. Если заменить класс OpenGLViewer на Direct3DViewer, то получится под DirectX.
-------------------------------------------------------------------
Application <- Viewer <- Scene <- Objects //Общая схема работы движка ( только главные классы )
^ ^ ^
| | |
Reader OpenGLViewer FileManager
^
|
DirectInputReader
-------------------------------------------------------------------
class Application
{
private:
Viewer* viewer;
Reader* reader;
bool update ( );
public:
Application ( Viewer* viewer, Reader* reader );
void mainLoop ( );
bool isOk ( )
{
return viewer -> isOK ( ) && reader -> isOK ( );
}
};
void Application :: mainLoop ( )
{
...
while ( true )
{
...
Control ( );
if ( !update ( ) )
return;
...
viewer -> draw ( );
...
}
...
}
class Viewer
{
protected:
Scene* scene;
public:
virtual void draw ( );
virtual bool isOK ( );
};
class OpenGLViewer: public Viewer
{
private:
HWND hWnd;
HDC DC;
HGLRC RC;
void initContext ( HWND theHWnd );
void initGLState ( );
void buildTextures ( );
public:
OpenGLView ( HWND theHWnd, Scene* theScene )
{
hWnd = theHWnd;
scene = theScene;
initContext ( hWnd );
intGLState ( );
buildTextures ( );
}
~OpenGLView ( );
virtual void draw ( );
virtual bool isOk ( )
{
return hWnd != NULL && DC != NULL && RC != NULL && scene -> isOK ( );
}
};
-------------------------------------------------------------------
int WinMain ( ... )
{
...
Scene scene ( "test_map" );
OpenGLViewer viewer ( hWnd, scene );
DirectInputReader reader ( ... );
Application app ( viewer, reader );
if ( app -> isOK ( ) )
app -> mainLoop ( );
return 0;
}
-------------------------------------------------------------------
v3kt0r
Да, довольно абстрактно, только вот от buildTextures веет конкретикой.
Zloy
Какая абстракция, друг мой, ты что?! Абстрагировать можно, когда есть, что обобщать. Для этого нужен опыт. Опыт приобретается в конкретной деятельности. Вот после того, как человек напишет с десяток программ hello world, ну слегка посложнее, там, с текстурами, шейдерами, прикиньте, сетевую версию hello world:)... мдя, о чём это я? Вот тогда уже сможет раскидать всё по структурам, классам, модулям и функциям. А пока сладовало бы написать пару простеньких прог, вроде летающего гвоздя над ландшафтом, или прыгающих шариков на плоскости(!), чтобы пощупать руками, как это работает и делается(или кто чем пишет). Иначе, по собственному опыту знаю, если сразу начинать писать двигло, без опыта, и большое, то там такая жопа будет... не то, что полная, а очень-очень жирная:)
v3kt0r
kronos_vano
Я вообще с некоторого времени решил оказаться от использования таких классов, как CApplication, CEngine, CEngineManager, CManagerManager.:) Это красиво, но это замедляет работу, усложняет код и требует больше времени на разработку. Сейчас у меня всё вообще на функциях. Функция Init(), Run(), DrawScene(), Это отнюдь не мешает, даже в большом проекте. ООП надо использовать там, где оно необходимо.
juriy9
У меня так:
Все вершины хранятся в вершинном буфере. В одном.
struct CFace{//Треугольник int indices[3] }; typedef vector<CFace> CFaceList ;//массив треугольников class CPortion//Порция для рендеринга - Набор треугольников с одинаковой текстурой { public: uint tex1,tex2;//1-я и 2-я текстуры CFaceList faces; };
Получается, что бочка должна состоять из 2х порций: 1)бока, с одной текстурой, и 2)дно - с другой.
Да Вы что тут все!!!
Сначала нада разработать блок схему, иначе всё обречено на провал.
Uranius
Да, я согласен, что незачем писать например такие классы, как Vertex, TexCoord и прочая мелюзга. У меня они все как struct.
Но! Классы для работы приложения я писал исходя из принципа наследования и переопределения виртуальных функций.
Пример: в классе Application есть ссылка на абстрактный класс Viewer. От Viewer'а унаследован класс OpenGLViewer, при этом сохранен интерфейс класса. В Application -> mainLoop ( ) вызывается метод Viewer -> draw ( ). Говоря проще Application наплевать на то как будет реализован метод draw ( ) и какой дочерний метод Viewer'а будет использован. Это определяется на этапе выполнения программы и дает возможность подключать новые классы унаследованные от Viewer'а, такие как Direct3DViewer. Кроме того позволяет разрабатывать классы отдельно друг от друга и не думать о взаимосвязи их архитектуры.
P.S. Кстати подобная схема используется в больших коммерчиских проектах. Там, как известно, люди не хотят разбираться в тонкостях того, что написали их коллеги по цеху.
sinoby
Я и привел упрощенную блок схему. Она в самом верху!
v3kt0r
О!, незаметил, просто когда схема без овалов, квадратов и ромбов, я как то не понимаю ((
Uranius
Да мы похожи по мыслям!!, ненадо усложнять и всюду втыкать ООП..
лично у меня тоже всё на функциях, никаких менеджеров, это только усложняет на начальном этапе, оно потом само придёт.
с написания спецификации и ТЗ.
далее - проектирование..
v3kt0r
struct = class {public: }
class = struct {private: }
Тема в архиве.