OpenGL communityФорумВопросы по программированию

Помогите разобратся

#0
19:56, 20 янв 2013

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

итак первый вопрос скорее по с++ чем по опенг и состоит вот в чем - я хочу организовать на с++ схему подобную в Jogl(opengl для Java), его задумка в следующем - есть некий класс , например Autodrawable в котором есть метод Run , все рисуемые объекты наследуются от него и коды всех ихних отрисовок находится в ихних методах Run унаследованных от Autodrawable, чтоб не писать их всех в одной куче.
Каким образом родитель Autodrawable может вызвать методы Run всех потомков ?

#1
19:59, 20 янв 2013

Ветки(потомки здесь не уместны, т.к. не о наследовании речь идет, а об иерархической структуре) должны при создании помещать себя во внутренний список родителя.
Соответственно родитель перебирает свой список и делает то что нужно над каждым элементом.

#2
20:00, 20 янв 2013

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

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();
}
#3
23:51, 20 янв 2013

спасибо , все вышло)
теперь следующая цепочка вопросов, немного теории самого опенгл=)мне интересно что нужно делать для каждого объекта отдельно, а что можно сделать 1 раз для всех

1)каждый объект должен находится в отдельном VAO?
2)одна шейдерная программа может выводит много объектов?
3)юниформ glUniformMatrix4fv используется 1 раз для всех обьектов?или в каждом обьекте использовать собственный?
4)у каждого обьекта собственная modelMatrix ,все остальные только в 1 экземпляре?(projectionMatrix,modelViewProjectionMatrix ,viewMatrix,viewProjectionMatrix)

#4
12:57, 21 янв 2013

cybernoise
1. Можно и так.
2. Сам шейдер ничего не выводит, разные шейдеры используются на разных этапах рендера.
Геометрические на этапе обработки примитивов
Вершинные на этапе обработки вершин
Пиксельные на этапе рисования пикселей

3. Это функция передачи матрицы в шейдер.
4. Всё это на твой вкус, можно вообще без матриц.
Обычно:
Модельная матрица отвечает за трансформацию объекта.
Проекционная матрица отвечает за перспективное преобразование.
Видовая матрица - матрица камеры. (взгляда)

#5
0:05, 22 янв 2013

теперь новая проблемма, собрал класс 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);
}
#6
0:47, 22 янв 2013

Хорошее место для начала - http://www.songho.ca/opengl/gl_mvc.html
Там описана теория и есть маленькие демонстрационные программы. А тут можно посмотреть, как он это использует на практике - http://www.songho.ca/opengl/files/matrixProjection.zip http://www.songho.ca/opengl/files/matrixModelView.zip

#7
16:16, 1 мар 2013

итак господа, прошу помочь с очередным наверное глупым вопросом)
вот в чем задумка - нужно унаследовать возможность двигать объект. 
Есть 2 класса, Cube и Moveable, в Cube есть поле position , в Moveable есть метод Move который использует этот position. Как это можно организовать? чтоб все выглядело примерно так :

class Cube : Moveable
{
vec3 position;
...
...

};


class Moveable
{
...
void Move (...)
{
  // тут используется position
}
...
}

#8
19:59, 1 мар 2013

Если необходимо разбить классы подобным образом, то надо ввести тогда и третий класс, отвечающий за расположение объекта:

class Transform
{
  vec3 pos;
};

далее от него наследовать Moveable и делать необходимые преобразования над позицией объекта. Cube уже наследовать от Moveable.

правка.
Я бы оставил преобразования над позицией объекта в классе Transform. Смысла нет от простого хранения полей.

#9
21:07, 1 мар 2013

спасибо, думаю так и сделаю
просто было интересно или из родителя можно както обращяться к полям наследников

OpenGL communityФорумВопросы по программированию

Тема в архиве.