Если я правильно понял, у вас есть некоторый плоский 2D многоугольник и то, что добавить к нему некоторую постоянную толщину (как трехмерную сетку).Это выполнимо довольно легко.Как вы правильно поняли, вам нужно сначала триангулировать.Таким образом, вы должны иметь следующие данные:
таблица точек pnt[pnts]
список всех точек вашего объекта.
polygon pol[pols]
(окружность вашего объекта)
только что упорядоченный список индексов точек, ссылающихся на таблицу точек
результат триангуляции fac[facs]
упорядоченный список из 3-х точечных индексов, представляющих все треугольники.
Теперь, чтобы сделать из него сетку, нам нужно сделать следующее:
Скопируйте все точки и вытяните их путем некоторого перевода.
Все эти новые точки будут добавлены в текущую таблицу pnt[pnts]
.Не забудьте запомнить исходный размер таблицы pnts0
, так как это понадобится позже.
копирование / реверс триангуляции.
Противоположностьсторона триангулированного многоугольника будет одинаковой как раз в обратной обмотке многоугольника.Так что просто скопируйте его в fac[facs]
как новые треугольники в обратном порядке индексов ... Не забудьте добавить исходный размер таблицы точек ко всем новым граням.Это будет использовать новые точки ... Из ваших изображений вы уже достигли этой точки.
создайте отсутствующие боковые грани.
Для этого мы можем использовать оригинальный полигон.Поскольку мы только что скопировали точки, мы знаем, что 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:
Здесьэто предварительный просмотр кода выше:
choppynes из-за моего GIF-захвата, рендеринг плавный.Я использовал статическое распределение и на ходу обычные вычисления, поэтому код прост и понятен.Для реальной сделки вам нужно реализовать динамические списки и VAO / VBO ... если вы хотите хорошую производительность