Хобрук: Ваш путь к мастерству в программировании

Частицы OpenGL, помогите контролировать направление

Я пытаюсь изменить этот образец Digiben, чтобы получить эффект частиц, которые генерируются из пятна (точки удара) и всплывают вверх, как искры огня. В образце частицы вращаются по кругу... Я попытался удалить функции косинуса/синуса и заменить их обычным glTranslate с увеличением значения Y, но я просто не могу получить никаких реальных результатов... кто-нибудь может указать примерно, где я должен добавить/изменить перевод в этом коде, чтобы получить этот результат?

void ParticleMgr::init(){
    tex.Load("part.bmp");
    GLfloat angle = 0; // A particle's angle
    GLfloat speed = 0; // A particle's speed
    // Create all the particles
    for(int i = 0; i < P_MAX; i++)
    {
        speed = float(rand()%50 + 450); // Make a random speed
        // Init the particle with a random speed
        InitParticle(particle[i],speed,angle);
        angle += 360 / (float)P_MAX; // Increment the angle so when all the particles are
                                     // initialized they will be equally positioned in a
                                     // circular fashion
    }
}
void ParticleMgr::InitParticle(PARTICLE &particle, GLfloat sss, GLfloat aaa)
{
    particle.speed = sss; // Set the particle's speed
    particle.angle = aaa; // Set the particle's current angle of rotation
    // Randomly set the particles color
    particle.red = rand()%255;
    particle.green = rand()%255;
    particle.blue = rand()%255;
}
void ParticleMgr::DrawParticle(const PARTICLE &particle)
{
    tex.Use();
    // Calculate the current x any y positions of the particle based on the particle's
    // current angle -- This will make the particles move in a "circular pattern"
    GLfloat xPos = sinf(particle.angle); 
    GLfloat yPos = cosf(particle.angle);
    // Translate to the x and y position and the #defined PDEPTH (particle depth)
    glTranslatef(xPos,yPos,PDEPTH);
    // Draw the first quad
    glBegin(GL_QUADS);
        glTexCoord2f(0,0);
        glVertex3f(-5, 5, 0);
        glTexCoord2f(1,0);
        glVertex3f(5, 5, 0);
        glTexCoord2f(1,1);
        glVertex3f(5, -5, 0);
        glTexCoord2f(0,1);
        glVertex3f(-5, -5, 0);
    glEnd(); // Done drawing quad
    // Draw the SECOND part of our particle
    tex.Use();
    glRotatef(particle.angle,0,0,1); // Rotate around the z-axis (depth axis)
    //glTranslatef(0, particle.angle, 0);
    // Draw the second quad
    glBegin(GL_QUADS);
        glTexCoord2f(0,0);
        glVertex3f(-4, 4, 0);
        glTexCoord2f(1,0);
        glVertex3f(4, 4, 0);
        glTexCoord2f(1,1);
        glVertex3f(4, -4, 0);
        glTexCoord2f(0,1);
        glVertex3f(-4, -4, 0);
    glEnd(); // Done drawing quad
    // Translate back to where we began
    glTranslatef(-xPos,-yPos,-PDEPTH);
}
void ParticleMgr::run(){
    for(int i = 0; i < P_MAX; i++)
    {
        DrawParticle(particle[i]);
        // Increment the particle's angle
        particle[i].angle += ANGLE_INC;
    }
}

А пока я добавляю glPushMatrix(), glTranslate(x, y, z) в функцию run() выше, прямо перед циклом, с x,y,z в качестве позиции врага для размещения его поверх враг... это лучшее место для этого?

Спасибо за любой вклад!

16.11.2011

  • Можете ли вы также показать измененный код, который вы пытались использовать, который не использует sin и cos? 17.11.2011
  • Я понимаю, что при каждом проходе частица[i].angle увеличивается, поэтому я заменил glTranslatef(xPos,yPos,PDEPTH); на glTranslatef(0,particle[i].angle,PDEPTH);, чтобы, надеюсь, получить ускорение по Y, но я получаю частицы, разбросанные по всему пространству во всех направлениях..... 17.11.2011
  • Если вы используете glTranslatef, постарайтесь не использовать glRotatef, так как это приведет к рассеянию. Как только вы заставите перевод работать, начните снова вводить повороты и будьте осторожны с порядком, в котором вы делаете вещи, перевод, за которым следует поворот, - это не то же самое, что поворот, за которым следует перевод. 17.11.2011

Ответы:


1

Использование glTranslate и glRotate таким образом фактически снизит производительность вашей программы. OpenGL не является графом сцены, поэтому функции манипулирования матрицами напрямую влияют на процесс рисования, т.е. они не устанавливают «состояние объекта». Проблема, с которой вы столкнулись, заключается в том, что умножение матрицы на матрицу 4 × 4 включает 64 умножения и 16 сложений. Таким образом, вы тратите в 96 раз больше вычислительной мощности на перемещение частицы, чем просто напрямую обновляете положение вершины.

Теперь к вашей проблеме: как я уже говорил вам, glTranslate работает с (глобальным) матричным состоянием одной из 4 выбираемых матриц. И эффекты накапливаются, т.е. каждый glTranslate будет начинаться с матрицы, оставленной предыдущим glTranslate. OpenGL предоставляет стек матриц, в который можно поместить копию текущей матрицы для работы, а затем извлечь ее, чтобы вернуться в предыдущее состояние.

Однако: манипуляции с матрицами были удалены из ядра OpenGL-3, а позже полностью. Работа с матрицами OpenGL никогда не ускорялась (за исключением одной конкретной графической рабочей станции, выпущенной SGI примерно в 1996 году). Сегодня это анахронизм, так как каждая респектабельная программа, работающая с 3D-геометрией, использовала гораздо более сложные манипуляции с матрицами либо собственной реализацией, либо сторонней библиотекой. Стек матриц OpenGL был просто избыточен. Поэтому я настоятельно рекомендую вам забыть о функциях манипулирования матрицами OpenGL и создавать свои собственные.

17.11.2011
  • Две функции управления матрицами: glPushMatrix(opengl.org/sdk/docs/ man/xhtml/glPushMatrix.xml) и glPopMatrix(opengl .org/sdk/docs/man/xhtml/glPushMatrix.xml) 17.11.2011
  • Ну, вы не должны использовать их для этого конкретного сценария. Производительность будет ужасной. 17.11.2011
  • Идея состоит в том, чтобы заставить что-то работать, а затем беспокоиться об эффективности. В противном случае вы можете потратить целую вечность, пытаясь найти идеальное решение. 17.11.2011
  • @EthanSteinberg: У него уже было что-то работающее, а именно выполнение движения частиц в соответствии с настройкой положения вершины, что в данном случае является лучшим методом. 17.11.2011
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

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

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

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

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..