Построение координат 2D-карты в 3D-проекции OpenGL - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь преобразовать 2D-карту, созданную в моем редакторе карт, в 3D-графику с OpenGL.Это моя карта, сгенерированная в моем редакторе карт:

Map editor

Эти вершины относятся к моей координате мира с декартовым происхождением (вверху рисунка), и яПрименяю эту формулу, чтобы преобразовать ее в объектную координату OpenGL:

Размер мира: 800x600

x = (X / 800) -0.5
y = (Y / 600) -0.5

Получение такого результата:

(Первая грань объекта)

−0.48625, 0.068333333
0.12625, 0.07
0.12875, −0.481666667
−0.4875, −0.486666667

При построении этого буфера вершин в OpenGL я получил очень странный результат.Итак, как я могу получить 3D-модель из этих позиций вершин?Как эта картинка:

Box room

Я рендеринг OpenGL в режиме треугольников и использую этот пример в качестве начальной точки: https://github.com/JoeyDeVries/LearnOpenGL/blob/master/src/1.getting_started/7.4.camera_class/camera_class.cpp

Используя формулу преобразования + тесселяцию Earcut (https://github.com/mapbox/earcut.hpp), Я наконец-то правильно отрисовал этот прямоугольник внутри OpenGL. С двумя плоскостями, отличными только осью Z, теперь проблема в том, как визуализировать его боковые стороны после Earcutпросто работает с 2D координатами ...

Planes

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Если я правильно понял, у вас есть некоторый плоский 2D многоугольник и то, что добавить к нему некоторую постоянную толщину (как трехмерную сетку).Это выполнимо довольно легко.Как вы правильно поняли, вам нужно сначала триангулировать.Таким образом, вы должны иметь следующие данные:

  1. таблица точек pnt[pnts]

    список всех точек вашего объекта.

  2. polygon pol[pols] (окружность вашего объекта)

    только что упорядоченный список индексов точек, ссылающихся на таблицу точек

  3. результат триангуляции fac[facs]

    упорядоченный список из 3-х точечных индексов, представляющих все треугольники.

Теперь, чтобы сделать из него сетку, нам нужно сделать следующее:

  1. Скопируйте все точки и вытяните их путем некоторого перевода.

    Все эти новые точки будут добавлены в текущую таблицу pnt[pnts].Не забудьте запомнить исходный размер таблицы pnts0, так как это понадобится позже.

  2. копирование / реверс триангуляции.

    Противоположностьсторона триангулированного многоугольника будет одинаковой как раз в обратной обмотке многоугольника.Так что просто скопируйте его в fac[facs] как новые треугольники в обратном порядке индексов ... Не забудьте добавить исходный размер таблицы точек ко всем новым граням.Это будет использовать новые точки ... Из ваших изображений вы уже достигли этой точки.

  3. создайте отсутствующие боковые грани.

    Для этого мы можем использовать оригинальный полигон.Поскольку мы только что скопировали точки, мы знаем, что pnt[3*i] противоположно pnt[pnts0+3*i].Таким образом, мы просто создаем треугольные грани, соединяющие противоположные края многоугольника.

Вот небольшой пример C ++, который я сейчас использовал для этого:

//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
const int N=128;
int pnts=6*3;                   // 3* number of points
float pnt[N]=                   // x,y per each point
    {
    -0.5,-0.5,0.0,              //   6 ------ 9
    -0.4, 0.0,0.0,              //    +      +
    -0.5,+0.5,0.0,              //     3   12
    +0.5,+0.5,0.0,              //    +      +
    +0.4, 0.0,0.0,              //   0 ----- 15
    +0.5,-0.5,0.0,
    };
int pol[N]={ 0,3,6,9,12,15 }, pols=6; // original polygon (3*pnt index), number of its vertexes
int fac[N]=                     // triangulation result (3*pnt index)
    {
    0,3,15,
    3,12,15,
    3,6,12,
    6,9,12,
    }, facs=4*3;                // number of triangles*3
//---------------------------------------------------------------------------
void extrude(float dz)
    {
    int i,i0,pnts0=pnts;
    // copy and reverse triangulation
    for (i=0;i<facs;i++)
     fac[facs+facs-1-i]=fac[i]+pnts; facs+=facs;
    // duplicate points
    for (i=0;i<pnts;i++) pnt[pnts0+i]=pnt[i]; pnts+=pnts;
    // extrude points
    for (i=      2;i<pnts0;i+=3) pnt[i]-=dz;
    for (         ;i<pnts ;i+=3) pnt[i]+=dz;
    // side faces
    for (i0=pols-1,i=0;i<pols;i0=i,i++)
        {
        fac[facs]=pol[i ]+pnts0; facs++;
        fac[facs]=pol[i ];       facs++;
        fac[facs]=pol[i0];       facs++;

        fac[facs]=pol[i0]+pnts0; facs++;
        fac[facs]=pol[i ]+pnts0; facs++;
        fac[facs]=pol[i0];       facs++;
        }
    }
//---------------------------------------------------------------------------
void gl_draw()
    {
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_CULL_FACE);
    glFrontFace(GL_CCW);
    glEnable(GL_COLOR_MATERIAL);
/*
    glPolygonMode(GL_FRONT,GL_FILL);
    glPolygonMode(GL_BACK,GL_LINE);
    glDisable(GL_CULL_FACE);
*/

    // set view
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0,0.0,-5.0);
    static float ang=0.0;
    glRotatef(ang,0.2,0.7,0.1); ang+=5.0; if (ang>=360.0) ang-=360.0;

    // render mesh
    float *p0,*p1,*p2,n[3],a[3],b[3],c;
    glColor3f(0.7,0.7,0.7);

    glBegin(GL_TRIANGLES);
    for (int i=0;i+3<=facs;i+=3)
        {
        // points
        p0=pnt+fac[i+0];
        p1=pnt+fac[i+1];
        p2=pnt+fac[i+2];
        // compute normal
        a[0]=p1[0]-p0[0]; a[1]=p1[1]-p0[1]; a[2]=p1[2]-p0[2];
        b[0]=p2[0]-p1[0]; b[1]=p2[1]-p1[1]; b[2]=p2[2]-p1[2];
        n[0]=(a[1]*b[2])-(a[2]*b[1]);
        n[1]=(a[2]*b[0])-(a[0]*b[2]);
        n[2]=(a[0]*b[1])-(a[1]*b[0]);
        c=1.0/sqrt((n[0]*n[0])+(n[1]*n[1])+(n[2]*n[2]));
        n[0]*=c; n[1]*=c; n[2]*=c;
        // render
        glNormal3fv(n);
        glVertex3fv(p0);
        glVertex3fv(p1);
        glVertex3fv(p2);
        }
    glEnd();

//  glFlush();
    glFinish();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    {
    // Init of program
    gl_init(Handle);    // init OpenGL
    extrude(0.2);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
    // Exit of program
    gl_exit();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    // repaint
    gl_draw();
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
    {
    // resize
    gl_resize(ClientWidth,ClientHeight);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::tim_redrawTimer(TObject *Sender)
    {
    gl_draw();
    }
//---------------------------------------------------------------------------

Он основан на VCL , поэтому игнорируйте все VCL напишите и перенесите нужные вам события и GL context в соответствии с вашим стилем программирования.Единственные важные вещи здесь:

таблицы pnt,fac,pol, которые содержат входные данные и последние также выводят.extrude(dz) создаст сетку (назовите ее только один раз!), А gl_draw отобразит таблицы как сетку (используя старый стиль GL API для простоты).

Для GLЯ использовал свой gl_simple.h, который вы можете найти в соответствующем QA:

Здесьэто предварительный просмотр кода выше:

preview

choppynes из-за моего GIF-захвата, рендеринг плавный.Я использовал статическое распределение и на ходу обычные вычисления, поэтому код прост и понятен.Для реальной сделки вам нужно реализовать динамические списки и VAO / VBO ... если вы хотите хорошую производительность

0 голосов
/ 11 июня 2018

Трудно понять наверняка, но, похоже, ваш объект имеет только две визуализированные грани, потому что вы не добавили другие грани в индекс.

Поскольку у вас есть вершины, но вам также нужноскажи есть треугольники для сторон.Если это треугольники, вам нужно нарисовать 16 треугольников.Если вы не используете индекс, вам нужно продублировать свои вершины для каждого треугольника и в итоге получить 48 вершин для рисования.

Что касается алгоритма колошения для работы в 3D, если вы точно знаетечто у вашего многоугольника есть все точки в одном плане, вы можете взять 3 вершины, вывести его план и создать матрицу преобразования, чтобы привести все эти точки к (x, y, 0), что похоже на 2D координаты.

...