V zásade je jedno, či sa bude jednať o reprezentáciu 2D alebo 3D objektov. Odlišnost v zápise je len v počte súradníc, aj keï reprezentácia v 3D je z hľadiska ïalšieho spracovania zložitejšia. Samotná reprezentácia v podstate vychádza z možností zobrazovania grafickej karty počítača. Pomocou grafickej karty sme schopný vykresľovať len body a úsečky, pričom grafickým procesorom je podporované vykresľovanie trojuholníkov. Práve tento trojuholník sa javí z hľadiska reprezentácie ako efektívny, pretože existujú algoritmy, ktoré popisujú jeho vyplňovanie, je možné tiež veľmi efektívne optimalizovať výpočty priesečníkov lúčov s trojuholníkmi. Túto skutočnosť používajú rôzne vykresľovacie (renderovacie) techniky.
Takúto sieť trojuholníkov je možné vidieť napr. na jednoduchom teréne. Intuitívne by nás napadlo vyskladať takúto sieť tak, že zadáme súradnice každého bodu a nejakým spôsobom pospájame jednotlivé body hranami. Ako bolo spomenuté, ideálne je pospájať tieto body ako vrcholy trojuholníka, kde každý trojuholník bude obsahovať teda tri vrcholy (vertexy) a tri hrany (edges).
Hranová reprezentácia
Jeden zo spôsobov akým je možné reprezentovať objekty je tzv. hranová reprezentácia, alebo tiež drátová (wire-frame). Tento typ budeme používať v našom programe, pretože je jednoduchý a názorný. Ide o spôsob, kde zapisujeme do zoznamu súradnice vrcholov a jednotlivé hrany, osobitne. Takto získame zoznam, ktorý bude popisovať geometriu objektu v podobe vrcholov. Lenže, ak si predstavíme 4 vrcholy, tak spôsobov akým môžeme pospájať jednotlivé vrcholy je niekoľko, napr. spojenie môže predstavovať štvorec (obdlžník), ale tiež aj tvar písmenaX alebo spojenie, kde z jedného vrcholu pôjde hrana do všetkých ostatných. Práve na toto odlíšenie potrebujeme ešte ïalší zoznam, ktorý bude popisovať topológiu objektu v podobe hrán, teda ktoré vrcholy budú tvoriť jednotlivé hrany.
Tieto zoznamy sú z matematického hľadiska v podstate množiny obsahujúce informácie o danom objekte. Spolu tieto množiny môžu tvoriť graf, ako matematickú štrukúru, ktorá pozostáva z týchto dvoch množín. Graf je usporiadaná dvojica (V, H), kde V je množina vrcholov a H je množnina hrán, ktorá je navyše ako dvojprvková podmnožina tejto množiny. Dvojprvková preto, pretože obsahuje dvojice vrcholov medzi ktorými sa nachádza hrana.
Napísať a nakresliť takýto graf je možné vo forme diagramu. Máme napr. jeden diagram grafu G_1 = (V_1, H_1), kde V_1 = \left \{ 1,2,3,4,5 \right \} a H_1 = \left \{ \left \{ 1,2 \right \}\left \{ 2,3 \right \}\left \{ 3,4 \right \}\left \{ 4,5 \right \}\left \{ 5,1 \right \} \right \} a diagram grafu G_2 = (V_2, H_2), kde V_2 = \left \{ a,b,c,d,e \right \} a [latex]H_2 = \left \{ \left \{ a,b \right \}\left \{ b,c \right \}\left \{ c,d \right \}\left \{ d,e \right \}\left \{ e,a \right \} \right \}.
drawLine(), ktorá vykreslí úsečku so zadanými súradnicami.
namespace _2D_Renderer
{
class Program
{
static void Main(string[] args)
{
int width = 800;
int height = 600;
Canvas canvas = new Canvas(width, height);
Color background = new Color(0, 0, 0);
Color white = new Color(255, 255, 255);
canvas.clearColor(background);
canvas.drawLine(white, 300, 200, 400, 300);
canvas.render();
System.Diagnostics.Process.Start("Frame.exe", "frame.ppm");
}
}
}
Vizuálne to bude vyzerať nasledovne:drawLine(), bol použitý Bresenhamov algoritmus úsečky, ktorých je na internete kvantum. Pre konkrétnosť uvedieme zdrojový kód daného algoritmu:
public void drawLine(Color color, int x1, int y1, int x2, int y2)
{
if ((x1 - x2) > 0)
{
drawLine(color, x2, y2, x1, y1);
return;
}
if (Math.Abs(y2 - y1) > Math.Abs(x2 - x1))
{
bresteepline(color, y1, x1, y2, x2);
return;
}
int x = x1, y = y1, sum = x2 - x1, Dx = 2 * (x2 - x1), Dy = Math.Abs(2 * (y2 - y1));
int deltaDy = ((y2 - y1) > 0) ? 1 : -1;
for (int i = 0; i <= x2-x1; i++)
{
setPixel(x, y, color);
x++;
sum -= Dy;
if (sum < 0)
{
y = y + deltaDy; sum += Dx;
}
}
}
private void bresteepline(Color color, int x3, int y3, int x4, int y4)
{
if ((x3 - x4) > 0)
{
bresteepline(color, x4, y4, x3, y3);
return;
}
int x = x3, y = y3, sum = x4 - x3, Dx = 2 * (x4 - x3), Dy = Math.Abs(2 * (y4 - y3));
int deltaDy = ((y4 - y3) > 0) ? 1 : -1;
for (int i = 0; i <= x4-x3; i++)
{
setPixel(y, x, color);
x++;
sum -= Dy;
if (sum < 0)
{
y = y + deltaDy; sum += Dx;
}
}
}
Ak by sme chceli vykresliť napr. štvorec, mohli by sme 4x zavolať metódu drawLine() s relevantnými súradnicami vrcholov. Ale ak by sme chceli ponechať súradnice vrcholov a nakresliť jednotlivé úsečky z iných vrcholov museli by sme pomerne pracne prepisovať jednotlivé súradnice vrcholov. Práve pre tento účel bola definovaná matica susednosti a incidencie. Nasledujúci zdrojový kód popisuje ich použitie.
namespace _2D_Renderer
{
class Program
{
static void Main(string[] args)
{
int width = 800;
int height = 600;
Canvas canvas = new Canvas(width, height);
Color background = new Color(0, 0, 0);
Color white = new Color(255, 255, 255);
canvas.clearColor(background);
int[,] mVertices = { { 300, 200 }, { 400, 300 } };
int[,] mIndices = {
{ 0, 1 },
{ 1, 0 }
};
int x1, y1, x2, y2;
for (int i = 0; i < 2; i++)
{
for (int j = i; j < 2; j++)
{
if (mIndices[i, j] == 1)
{
x1 = mVertices[i, 0];
y1 = mVertices[i, 1];
x2 = mVertices[j, 0];
y2 = mVertices[j, 1];
canvas.drawLine(white, x1, y1, x2, y2);
}
}
}
canvas.render();
System.Diagnostics.Process.Start("Frame.exe", "frame.ppm");
}
}
}
Vykreslenie tejto úsečky má rovnaké súradnice ako v predošlom prípade len s tým rozdielom, že sme použili maticu susednosti. Pôvodne sme definovali úsečku so súradnicami, teraz definujeme súradnice v matici vrcholov (mVertices) a kreslíme danú úsečku podľa akejsi šablóny, matice susednosti (mIndices), ktorá určuje, ktoré hrany majú byť vykreslené od jednotlivých vrcholov. V tomto prípade podľa matice susednosti by mal program kresliť úsečku 2x, pretože matica je symetrická, teda od jedného vrcholu k druhému a naopak. Aby zápis korešpondoval s definíciou matice susednosti budeme zapisovať celú maticu susednosti, avšak program reálne kreslí len prvky nad diagonálou tejto matice. Samozrejme, mohli by sme použiť analogicky aj maticu incidencie. Poznámka: Maticu susednosti v programe označujeme ako mIndices, teda ako maticu indexov. Použil som toto pomenovanie známe z knižnice DirectX, kde sa takto označuje matica, ktorá nejakým spôsobom definuje vzťahy medzi vertexami. Použitie pomenovania napr. mAdjacent alebo mAdj by mohlo byť zavádzajúce vzhľadom k tomu, že existuje tzv.adjungovaná matica, čo je transponovaná matica, kde sú navzájom vymenené riadky za stĺpce.
Ono, napr. v OpenGL, ale aj DirectX sa súradnice vrcholov zapisujú do osobitnej metódy, kde sa definuje len jeden vertex (bod), pričom je tiež možné definovať pole vertexov, podobne ako v našom prípade. Priemyselné štandardy už niečo také ako vykresľovanie podľa matice susednosti v takom rozpoložení ako ukazuje tento kód primárne nepoznajú, ale určite by to bolo možné aplikovať na nejaké čiastkové vykresľovanie. Principiálne to tam existuje vo forme dodefinovania vertexu, alebo pri samotnom vykreslení sa určí o aký typ vykreslenia ide, napr. o zoznam (zreťazených) úsečiek, zoznam (zreťazených) trojuholníkov, alebo veárovitý spôsob, kde jeden vrchol prináleží viacerým vrcholom spojených hranou.
Teraz podobným spôsobom môžme vykresliť štvorec, ale aj akékoľvek iné útvary. Ako sme už spomínali, stačí definovať vrcholy a spôsob, akým jednotlivé vrcholy budú pospájané je už na matici susednosti. Nasledujúci zdrojový kód teda ilustruje vykreslenie štvorca:
namespace _2D_Renderer
{
class Program
{
static void Main(string[] args)
{
int width = 800;
int height = 600;
Canvas canvas = new Canvas(width, height);
Color background = new Color(0, 0, 0);
Color white = new Color(255, 255, 255);
canvas.clearColor(background);
int[,] mVertices = { { 300, 200 }, { 400, 200 }, { 300, 300 }, { 400, 300 } };
int[,] mIndices = {
{ 0, 1, 1, 0 },
{ 1, 0, 0, 1 },
{ 1, 0, 0, 1 },
{ 0, 1, 1, 0 }
};
int x1, y1, x2, y2;
for (int i = 0; i < 4; i++)
{
for (int j = i; j < 4; j++)
{
if (mIndices[i, j] == 1)
{
x1 = mVertices[i, 0];
y1 = mVertices[i, 1];
x2 = mVertices[j, 0];
y2 = mVertices[j, 1];
canvas.drawLine(white, x1, y1, x2, y2);
}
}
}
canvas.render();
System.Diagnostics.Process.Start("Frame.exe", "frame.ppm");
}
}
}
Vizuálne to bude vyzerať nasledovne:[1, 2] a [2, 1].Hraničná reprezentácia
Niekedy nie je potrebné zaznamenávať informácie o všetkých hranách objektu, ale len o tých, ktoré sú z hľadiska viditeľnosti prístupné nášmu pohľadu. Ostatné hrany sa ignorujú. To je prípad hraničnej reprezentácie (boundary representation, B-rep). Mohlo by sa zdať, že tento typ rieši určitú problematiku viditeľnosti hrán, avšak je to len zdanie, pretože zadávame len tie hrany, ktoré z hľadiska pohľadu majú byť viditeľné. Teda, popisujeme len plášť objektu (aj keď samotný plášť netvorí plocha, ktorá je nejakým spôsobom definovaná), jeho obrysy. Pri jednoduchých objektoch je táto metóda ešte zvládnuteľná z hľadiska manuálnej selekcie hrán, ale pri zložitejších objektoch to býva časovo náročné.
Jednoduchá a štruktúrovaná plôšková reprezentácia
Plôšková reprezentácia obsahuje informácie o plochách objektu, z ktorého pozostáva. Je to už reálna plocha narozdiel od predchádzajúcej reprezentácie, takže štruktúra obsahuje okrem vrcholov a hrán aj informáciu o plochách. To znamená napr. to, že je možné daný objekt osvetľovať, keďže už obsahuje plochy, a tiež je možné realizovať viditeľnosť jednotlivých častí objektu, aj keď v princípe je možné riešiť viditeľnosť pri akomkoľvek type reprezentácie, ale nie vždy to bude efektívne. V každom prípade budeme môcť zobrazovať objekty na pomerne slušnej optickej úrovni. Lenže z hľadiska vnútornej reprezentácie plôch objektu nám môžu chýbať údaje o type hrán alebo susednosti jednotlivých plôch s inými plochami. Práve tento nedostatok rieši štruktúrovaná reprezentácia, ktorá je známa pod názvom okrídlená hrana (winged-edge), okrídlená preto, pretože jedna hrana spolu so susednými hranami pripomína krídla v tom zmysle, že ku každej jednej hrane ústia v jej vrcholoch práve dve ďalšie hrany, ktorá takto spoločne na čele s danou hranou vizuálne tvoria krídla.Bodová reprezentácia
Objekt môžme popísať aj hranicami bodov, z ktorých pozostáva jeho povrch. Nepotrebujeme vedieť informácie o hranách, ktoré by tak spolu tvorili daný objekt, stačí nám vedieť informácie každého jedného bodu, z ktorého pozostáva objekt. Je to jednoduchšie v tom, že získať informáciu o bode a z neho vytvoriť objekt je menej náročné než získať informácie o hranách, ktoré sa spolupodieľajú na objekte. Jednotlivé body objektu nesú informácie o svojej polohe, normálovom vektore, farbe a ostatných vlastnostiach materiálu alebo svetla. Obyčajne sa tieto body získavajú cestou digitálneho snímania reálnych objektov. Je zrejmé, že táto metóda bude najpresnejšia, ale zároveň najnáročnejšia na pamäťové nároky. V tomto zmysle je to podobné ako pri metóde sledovania lúča, kedy v podstate počítame priesečníky objektov a zobrazujeme jednotlivé body povrchu objektov. Avšak pri týchto metódach existujú rôzne metódy optimalizácie zobrazenia.Pre ostatné typy reprezentácie objektov ako napr. konštruktívna geometria telies, modelovanie pomocou deformácii, objemová reprezentácia, fraktálová geometria, modelovanie krajín alebo časticové systémy budú čiastočne popísané na inom mieste.

.png)

.png)
.png)
.png)



0 comments:
Post a Comment