Вообщем решил заняться разработкой движка, так, для себя, утолить свой интерес в этой теме.. и возникают вопросы по организации - комуто могут показаться очень глупыми но тем не менее прошу не ругаться матом)и заранее благодарю за ответы
итак первый вопрос скорее по с++ чем по опенг и состоит вот в чем - я хочу организовать на с++ схему подобную в Jogl(opengl для Java), его задумка в следующем - есть некий класс , например Autodrawable в котором есть метод Run , все рисуемые объекты наследуются от него и коды всех ихних отрисовок находится в ихних методах Run унаследованных от Autodrawable, чтоб не писать их всех в одной куче.
Каким образом родитель Autodrawable может вызвать методы Run всех потомков ?
Ветки(потомки здесь не уместны, т.к. не о наследовании речь идет, а об иерархической структуре) должны при создании помещать себя во внутренний список родителя.
Соответственно родитель перебирает свой список и делает то что нужно над каждым элементом.
Позднее связывание, сделай метод виртуальным, лучше класс предок вообще абстрактным сделать.
class A { public: virtual void Draw() = 0; }; class B : public A { public: void Draw( ); }; void B::Draw( ) { }
Не прочитал слова ВСЕХ ПОТОМКОВ.
Я думал здесь вопрос про интерфейс класса.
Делаешь массив из указателей на абстрактный класс от которого всё наследуешь, вызываешь для всех его элементов метод по очереди.
class CWorld { private: vector<A*> EntityArray; public: void RenderLikeABitch(); }; void CWorld::RenderLikeABitch( ) { for( size_t i( 0); i<EntityArray.size( ); i++ ) EntityArray[i]->Draw( ); }
спасибо , все вышло)
теперь следующая цепочка вопросов, немного теории самого опенгл=)мне интересно что нужно делать для каждого объекта отдельно, а что можно сделать 1 раз для всех
1)каждый объект должен находится в отдельном VAO?
2)одна шейдерная программа может выводит много объектов?
3)юниформ glUniformMatrix4fv используется 1 раз для всех обьектов?или в каждом обьекте использовать собственный?
4)у каждого обьекта собственная modelMatrix ,все остальные только в 1 экземпляре?(projectionMatrix,modelViewProjectionMatrix ,viewMatrix,viewProjectionMatrix)
cybernoise
1. Можно и так.
2. Сам шейдер ничего не выводит, разные шейдеры используются на разных этапах рендера.
Геометрические на этапе обработки примитивов
Вершинные на этапе обработки вершин
Пиксельные на этапе рисования пикселей
3. Это функция передачи матрицы в шейдер.
4. Всё это на твой вкус, можно вообще без матриц.
Обычно:
Модельная матрица отвечает за трансформацию объекта.
Проекционная матрица отвечает за перспективное преобразование.
Видовая матрица - матрица камеры. (взгляда)
теперь новая проблемма, собрал класс Block который должен выводить на экран куб.В класе 3 метода -Init, ObjRender - отрисовка и Update - вращение и рендер в основную матрицу.Изначально все было хорошо, но когда создал второй куб то увидел что рисуется только один - последний созданный. Проморочился весь день и так и не смог вывести 2 куба на экран (( Подскажите в чем может быть проблема?
сразу приведу код :
#ifndef BLOCK_H #define BLOCK_H class Block : public AutoDrawable { public: GLuint positionLocation,texcoordLocation; float s;// половина размера куба Block(float Size) { s=Size; } void Init( GLuint Program) { float Positions[24][3] = { {-s, s, s}, { s, s, s}, { s,-s, s}, {-s,-s, s}, // front { s, s,-s}, {-s, s,-s}, {-s,-s,-s}, { s,-s,-s}, // back {-s, s,-s}, { s, s,-s}, { s, s, s}, {-s, s, s}, // top { s,-s,-s}, {-s,-s,-s}, {-s,-s, s}, { s,-s, s}, // bottom {-s, s,-s}, {-s, s, s}, {-s,-s, s}, {-s,-s,-s}, // left { s, s, s}, { s, s,-s}, { s,-s,-s}, { s,-s, s} // right }; // текстурные координаты куба float Texcoords[24][2] = { {0.0f,1.0f}, {1.0f,1.0f}, {1.0f,0.0f}, {0.0f,0.0f}, // front {0.0f,1.0f}, {1.0f,1.0f}, {1.0f,0.0f}, {0.0f,0.0f}, // back {0.0f,1.0f}, {1.0f,1.0f}, {1.0f,0.0f}, {0.0f,0.0f}, // top {0.0f,1.0f}, {1.0f,1.0f}, {1.0f,0.0f}, {0.0f,0.0f}, // bottom {0.0f,1.0f}, {1.0f,1.0f}, {1.0f,0.0f}, {0.0f,0.0f}, // left {0.0f,1.0f}, {1.0f,1.0f}, {1.0f,0.0f}, {0.0f,0.0f} // right }; // индексы вершин куба в порядке против часовой стрелки uint32 Indices[36] = { 0, 3, 1, 1, 3, 2, // front 4, 7, 5, 5, 7, 6, // back 8,11, 9, 9,11,10, // top 12,15,13, 13,15,14, // bottom 16,19,17, 17,19,18, // left 20,23,21, 21,23,22 // right }; //VAO обьявлен в родителе Autodrawable glGenVertexArrays( 1, &VAO); glBindVertexArray( VAO); glGenBuffers( 3, VBO); // индекс вершинного атрибута 'position' из шейдерной программы positionLocation = glGetAttribLocation( Program, "position"); if ( positionLocation != -1) {// начинаем работу с буфером для координат вершин куба glBindBuffer( GL_ARRAY_BUFFER, VBO[0]); // поместим в буфер координаты вершин куба glBufferData( GL_ARRAY_BUFFER, 24 * ( 3 * sizeof( float)),Positions, GL_STATIC_DRAW); // назначим на атрибут параметры доступа к VBO glVertexAttribPointer( positionLocation, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float), 0); // разрешим использование атрибута glEnableVertexAttribArray( positionLocation); } // индекс вершинного атрибута 'texcoord' из шейдерной программы texcoordLocation = glGetAttribLocation( Program, "texcoord"); if ( texcoordLocation != -1) { // начинаем работу с буфером для текстурных координат куба glBindBuffer( GL_ARRAY_BUFFER, VBO[1]); // поместим в буфер текстурные координаты куба glBufferData( GL_ARRAY_BUFFER, 24 * ( 2 * sizeof( float)),Texcoords, GL_STATIC_DRAW); // назначим на атрибут параметры доступа к VBO glVertexAttribPointer( texcoordLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof( float), 0); // разрешим использование атрибута glEnableVertexAttribArray( texcoordLocation); } // начинаем работу с индексным буфером glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, VBO[2]); // поместим в буфер индексы вершин куба glBufferData( GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof( uint32),Indices, GL_STATIC_DRAW); } void ObjRender( ) { glBindVertexArray( VAO); glDrawElements( GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL); } void Update( Matrix4& MVPM,Matrix4& VPM,Matrix4& MM,float timer) { if ( ( Rotation[1] += 3.0f * timer) > 360.0f) Rotation[1] -= 360.0f; if ( ( Rotation[2] += 1.0f * timer) > 360.0f) Rotation[2] -= 360.0f; // рассчитаем матрицу преобразования координат вершин куба Rotate( MM, Rotation[0], Rotation[1], Rotation[2]); Render( MVPM, VPM, MM); } }; #endif /* BLOCK_H */
в майне все вызывается так :
Block B1(3); Block B2( 1); // инициализаця OpenGL bool GLWindowInit( const GLWindow *window) { ... ... colorTexture = TextureCreateTGA( "Textures/1.tga"); // делаем активным текстурный юнит 0 и назначаем на него текстуру glActiveTexture( GL_TEXTURE0); glBindTexture( GL_TEXTURE_2D, colorTexture); // создадим шейдерную программу и шейдеры для нее shaderProgram = ShaderCreateFromFile( "Shaders/1", ST_VERTEX | ST_FRAGMENT); ShaderBind( shaderProgram); Perspective( projectionMatrix, 45.0f,( float)window->width / ( float)window->height, 1.f, 10.0f); Translate( viewMatrix, 0.0f, 0.0f, -4.0f); Render( viewProjectionMatrix, projectionMatrix, viewMatrix); // получим индекс матрицы modelViewProjectionMatrixLocation = glGetUniformLocation( shaderProgram, "modelViewProjectionMatrix"); // получим индекс текстурного самплера из шейдерной программы и свяжем его с текстурным юнитом 0 if ( ( colorTextureLocation = glGetUniformLocation( shaderProgram, "colorTexture")) != -1) glUniform1i( colorTextureLocation, 0); //вызывает метод Init всех созданных потомков AutoDrawable::InitObjects( shaderProgram); return true; } // функция рендера void GLWindowRender( const GLWindow *window) { glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ShaderON( shaderProgram); // передаем в шейдер матрицу преобразования координат вершин glUniformMatrix4fv( modelViewProjectionMatrixLocation, 1, GL_TRUE, modelViewProjectionMatrix); // вызывает ObjRender всех потомков AutoDrawable::RenderObjects( ); } void GLWindowUpdate( const GLWindow *window, double deltaTime) { AutoDrawable::UpdateObjects( modelViewProjectionMatrix,viewProjectionMatrix,modelMatrix,( float)deltaTime); }
Хорошее место для начала - http://www.songho.ca/opengl/gl_mvc.html
Там описана теория и есть маленькие демонстрационные программы. А тут можно посмотреть, как он это использует на практике - http://www.songho.ca/opengl/files/matrixProjection.zip http://www.songho.ca/opengl/files/matrixModelView.zip
итак господа, прошу помочь с очередным наверное глупым вопросом)
вот в чем задумка - нужно унаследовать возможность двигать объект.
Есть 2 класса, Cube и Moveable, в Cube есть поле position , в Moveable есть метод Move который использует этот position. Как это можно организовать? чтоб все выглядело примерно так :
class Cube : Moveable
{
vec3 position;
...
...
};
class Moveable
{
...
void Move (...)
{
// тут используется position
}
...
}
Если необходимо разбить классы подобным образом, то надо ввести тогда и третий класс, отвечающий за расположение объекта:
class Transform
{
vec3 pos;
};
далее от него наследовать Moveable и делать необходимые преобразования над позицией объекта. Cube уже наследовать от Moveable.
правка.
Я бы оставил преобразования над позицией объекта в классе Transform. Смысла нет от простого хранения полей.
спасибо, думаю так и сделаю
просто было интересно или из родителя можно както обращяться к полям наследников
Тема в архиве.