English
Welcome
Kecy
Programování
3D - Engine
Guestbook
Odkazy
Downloady
O autorovi
Napiš mi
Mailform
box_cz 3D - Engine - OpenGL 02 - malý dárek box_cz

Mno netrvalo dlouho a jsem tu znova. Tentokrát to ale bohužel nebude o OpenGL ... Minule jsem pro vás psal modul, generující nějaký 3D fraktál - a dost jsem se u toho navztekal, protože jsem si musel napřed napsat všechny možné operace s vektory a potom je dost nejapně volat. Přecijen už je to nějaká doba, kdy jsem něco dělal v čistém C (že by úkoly do školy?) Takže tentokrát pro vás mám malý dáreček ve formě několika zdrojáků pro práci s 3D objekty. (ano! slyšíte dobře - swine dává něco zadarmo!)

Teď vás ale možná zaskočilo že se mi nelíbilo programovat v "čistém C". Je sice fajn, ale muset pořád dookola vypisovat "a.x = b.x + c.x; a.y + b.y .." není zrovna příjemné. Teď už to není ani moc didaktické, protože už víte, jak jednotlivé operace s vektory udělat - teď by se spíš hodilo mít možnost operace nějak přehledně zapsat. V tom nám vychází vstříc C++. (ne, teď si nervěte uši - nemusíte se učit C++ abyste dál rozuměli našemu seriálu - jen přibude pár souborů, kterým možná nebudete rozumět, ale určitě si je zvyknete používat) Tak půjdeme na věc ...


/*
 |       ***  Vector math  ***      |
 |   Copyright © -tHE SWINe- 2005   |
 |             Vector.h             |
*/

#ifndef __VECTOR2_INCLUDED
#define __VECTOR2_INCLUDED

#ifndef for
#define for if(0) {} else for
#endif

extern float const Pi; // 3.1415926535897932384626433832795028841971f

extern const float f_epsilon; // 0.01f
extern const float f_edge_epsilon; // 0.05f

template <class T> struct Vector3 {
    T x, y, z;

    inline Vector3();
    inline Vector3(T t_x, T t_y, T t_z);
    inline T Len() const;
    inline T Len2() const;
    inline T operator [](int n_index) const;
    inline T &operator [](int n_index);
    inline void Normalize();
    inline void Normalize(T t_len);
    inline Vector3<T> operator + (const Vector3<T> &r_vec) const;
    inline Vector3<T> operator - (const Vector3<T> &r_vec) const;
    inline Vector3<T> operator - () const;
    inline Vector3<T> operator * (T t) const;
    inline Vector3<T> operator += (const Vector3<T> &r_vec);
    inline Vector3<T> operator -= (const Vector3<T> &r_vec);
    inline Vector3<T> operator *= (T t);
    inline T operator / (const Vector3<T> &r_vec) const; // dot product
    inline Vector3<T> operator * (const Vector3<T> &r_vec) const; // cross product
    inline int operator == (const Vector3<T> &r_vec) const;
    inline Vector3<T> operator *= (const Vector3<T> &r_vec); // cross product
    void print() const;
};

typedef Vector3<float> Vector3f;
typedef Vector3<int> Vector3i;
typedef Vector3<short> Vector3s;

template <class T> struct Vector2 {
    T x, y;

    inline Vector2();
    inline Vector2(T t_x, T t_y);
    inline T Len() const;
    inline T Len2() const;
    inline T operator [](int n_index) const;
    inline T &operator [](int n_index);
    inline void Normalize();
    inline void Normalize(T t_len);
    inline Vector2<T> operator + (const Vector2<T> &r_vec) const;
    inline Vector2<T> operator - (const Vector2<T> &r_vec) const;
    inline Vector2<T> operator - () const;
    inline Vector2<T> operator * (T t) const;
    inline Vector2<T> operator += (const Vector2<T> &r_vec);
    inline Vector2<T> operator -= (const Vector2<T> &r_vec);
    inline Vector2<T> operator *= (T t);
    inline T operator / (const Vector2<T> &r_vec) const; // dot product
};

typedef Vector2<float> Vector2f;
typedef Vector2<int> Vector2i;
typedef Vector2<short> Vector2s;

template <class T> struct Vector4 {
    T x, y, z, w;

    inline Vector4();
    inline Vector4(T t_x, T t_y, T t_z, T t_w);
    inline T Len() const;
    inline T Len2() const;
    inline T operator [](int n_index) const;
    inline T &operator [](int n_index);
    inline void Normalize();
    inline void Normalize(T t_len);
    inline Vector4<T> operator + (const Vector4<T> &r_vec) const;
    inline Vector4<T> operator - (const Vector4<T> &r_vec) const;
    inline Vector4<T> operator - () const;
    inline Vector4<T> operator * (T t) const;
    inline Vector4<T> operator += (const Vector4<T> &r_vec);
    inline Vector4<T> operator -= (const Vector4<T> &r_vec);
    inline Vector4<T> operator *= (T t);
    inline T operator / (const Vector4<T> &r_vec) const; // dot product
};

typedef Vector4<float> Vector4f;
typedef Vector4<float> Color4f;

enum EPlanePos {
    plane_Front,
    plane_Back,
    plane_Onplane,
    plane_Split
};

struct Planef {
    Vector3f v_normal;
    float f_dist;

    class CRayIsParallel_Exception {};

    inline Planef() {}
    Planef(const Vector3f &v_pos, const Vector3f &v_norm);
    Planef(const Vector3f &v_u, const Vector3f &v_v, const Vector3f &v_pos);
    EPlanePos n_Tri_Pos(const Vector3f &v_a, const Vector3f &v_b,
       const Vector3f &v_c) const;
    EPlanePos n_Tri_PosEx(const Vector3f &v_a, const Vector3f &v_b,
       const Vector3f &v_c, float f_epsilon_ex) const;
    EPlanePos n_Vector_Pos(const Vector3f &v_vec) const;
    EPlanePos n_Vector_PosEx(const Vector3f &v_vec, float f_epsilon_ex) const;
    float f_Vector_Dist(const Vector3f &v_vec) const;
    float f_Vector_Dot(const Vector3f &v_vec) const;
    Vector3f v_Intersect_Ray(const Vector3f &v_org, const Vector3f &v_dir) const;
    float f_Intersect_Ray_t(const Vector3f &v_org, const Vector3f &v_dir) const;
    int operator == (const Planef &t_plane) const;
};

struct Matrix4f {
    float f[4][4];

    void Init();
    void Translate(const Vector3f &v_dir);
    void Scale(float f_scale);
    void Scale(const Vector3f &v_scale);
    void RotateX(float f_angle);
    void RotateY(float f_angle);
    void RotateZ(float f_angle);
    Matrix4f operator * (const Matrix4f &mat) const;
    void operator *= (const Matrix4f &mat);
    void operator = (const Matrix4f &mat);
    void Inverse();
    Vector3f v_Transform_Pos(const Vector3f &v_vec) const;
    Vector3f v_Transform_Dir(const Vector3f &v_vec) const;

protected:
    void _Self_Mult(const Matrix4f &mat);
};

class TVertexStruct {
public:
    Vector3f v_pos;

    inline Vector3f v_Pos() const;
    inline Vector3f &v_Pos();
    TVertexStruct Lerp(float t, TVertexStruct &r_right);
};

class TVertex : public TVertexStruct {
public:
    int n_flag;
    // must be integer-type to be able to hold indices/id-s
    // it has no long-term purpose, it's rather temp variable
    Vector3f v_pos;
    Vector3f v_normal;
    Vector3f v_texcoord[4];
    Vector4f v_color;

    inline Vector3f v_Pos() const;
    inline Vector3f &v_Pos();
    TVertex Lerp(float t, TVertex &r_right);
};

template <class TVertexStruct>
class CPolygon {
protected:
    std::vector<TVertexStruct> m_vertex_list;
    Planef m_t_normal;

public:
    void Delete();
    int Add_Vertex(TVertexStruct v_vertex);
    int Add_Vertex(const TVertexStruct *p_vertex, int n_num);
    void Delete_Vertices(int n_index, int n_count);
    inline int n_Vertex_Num() const;
    inline TVertexStruct &r_Vertex(int n_index);
    inline const TVertexStruct t_Vertex(int n_index) const;
    const Vector3f v_Center() const;
    const Vector3f v_NearestPoint(Vector3f v_point) const;
    int Calc_Normal();
    inline Planef &r_Normal();
    inline const Planef t_Normal() const;
    EPlanePos n_Plane_Pos(const Planef &t_plane) const;
    EPlanePos n_Plane_PosEx(const Planef &t_plane, float f_epsilon_ex) const;
    int Cut(const Planef &t_plane, EPlanePos n_desired_half);
    int CutEx(const Planef &t_plane, EPlanePos n_desired_half, float f_epsilon_ex);
    int Split(const Planef &t_plane,
       CPolygon<TVertexStruct> &r_new_poly, EPlanePos n_desired_half);
    int b_Contain_Point(Vector3f v_point) const;
    int Write(FILE *p_file) const;
    int Read(FILE *p_file);
    int operator = (const CPolygon<TVertexStruct> &r_poly);
    void Reverb();
    int b_Overlap(const CPolygon<TVertexStruct> &r_poly) const;
    int b_IsTiny() const;
    int b_IsTinyEx(float f_edge_epsilon_ex, float f_epsilon_ex) const;
};

#endif // __VECTOR2_INCLUDED

Co to bylo!? Mno klid ... to si vysvětlíme. Na začátku máme konstanty jako Pi (ludolfovo číslo), f_epsilon (nejmenší rozdíl se kterým budeme počítat - menší rozdíl pro nás bude nula - hodí se pro porovnávání pozic, atd ... matematický koprocesor totiž není zrovna přesná věc, když zajdete do detailů ... takové logaritmické pravítko ... ale ... pardon, už zase vzpomínám na staré dobré časy s dokonalou slečnou) a f_edge_epsilon (nejdelší hrana - je dobré je mít spíš delší, než epsilon - ale to je jen otázka stability) Taky tam máme takovou zběsilou definici for. Znamená to, že když předhodíme kompilátoru smyčku "for(int i = ...", tak po něm chceme, aby proměnná i byla vidět jen ve smyčce for, ale za ní už ne. To je takový nejapný zvyk prvních verzí MSVC, v dalších release už tuhle definici přihodili do nějakých std. inkludů.

To bysme měli. Ale pak tam je "template struct Vector3". Slovo template znamená šablona a zmíněný řádek znamená že děláme šablonu struktury Vector3 a že kdekoliv se objeví T, bude to šablonový typ. Šablona sama o sobě nejde vytvořit, musíme napřed říct jakým typem chceme nahradit T. Takže můžeme mít vektory počítající s floaty, s double nebo s čímkoliv jiným. Vector3 je třírozměrný vektor. Projdeme si jeho funkce:

  • Vector3() - vytvoření vektoru bez parametrů. Volá se když napíšete "Vector3 v;"
  • Vector3(x, y, z) - s parametry. Volá se když napíšete:

Vector3 nahoru(0, 1, 0);
// volá se teď (s parametry 0, 1 a 0)

Vector3 v;
v = Vector3(1, 2, 3) // ... a teď (s parametry 1, 2 a 3)
// když chcete něco naplnit hodnotou vektoru,
// už to nemusíte rozepisovat!
  • T operator[](int n_index) const - vrátí souřadnici s indexem, tzn. pro nulu vrátí x, pro jedničku y a pro dvojku z. je to přetížený operátor, což znamená že pokud se operátor [] normálně chová u pointerů jako určení hodnoty na nějakém indexu, u Vector3 se schová jako volání téhle funkce a vrací její hodnotu. tzn.:

Vector3 v(3, 5, 7);

float f = v[1]; // f = 5
  • T &operator[](int n_index) - stejná funkce, ale můžete do ní zapisovat, tzn.:

Vector3 v(1, 2, 3);

v[0] = 9; // v = [9, 2, 3]
  • T Len() const - spočítá délku vektoru (const za funkcí znamená, že funkce nemodifikuje vnitřní data vektoru)
  • T Len2() const - délka vektoru, umocněná na druhou
  • void Normalize() - normalizuje vektor, tzn. upraví délku vektoru na 1 (beze změny směru)
  • void Normalize(T len) - normlizuje vektor na určenou délku
  • Vector3 operator + (const Vector3 &r_vec) const - operátor sčítání vektorů
  • Vector3 operator - (const Vector3 &r_vec) const - operátor odčítání vektorů
  • Vector3 operator - () const - unární minus pro vektor
  • Vector3 operator * (T t) const - operátor násobení pro vektor a číslo
  • Vector3 operator += (const Vector3 &r_vec) - operátor přičtení k vektoru
  • Vector3 operator -= (const Vector3 &r_vec) - operátor odčečtení od vektoru
  • Vector3 operator *= (T t) const - operátor vynásobení vektoru číslem
  • T operator / (const Vector3 &r_vec) const - operátor skalárního součinu
  • Vector3 operator * (const Vector3 &r_vec) const - operátor vektorového součinu
  • Vector3 operator *= (const Vector3 &r_vec) const - operátor vektorového součinu
  • int operator == (const Vector3 &r_vec) - operátor porovnávání vektorů
  • void print() const - vytiskne hodnotu vektoru pomocí printf()

To je, čo? Takže teď už nemusím vypisovat všechny operace, když chci sečíst dva vektory! Už prostě jen napíšu "a + b" .. a je to! Za koncem struktury máte ukázané, jak se vybírají v šabloně typy. My budeme používat nejčastěji Vector3 s float jako šablonovým typem, který jsme pojmenovali Vector3f

Dál jsou tam ještě dvojrozměrný vektor Vector2 a čtyřrozměrný vektor Vector4, které jsou psané ve stejném duchu, takže je demokraticky vynechám.

Potom jsem vám nadělil strukturu pro rovinu Planef, kterou už jsem se ani neobtěžoval dělat jako šablonu, protože s ničím jiným, než s floatem (nebo s doublem který nepoužíváme) nemá smysl počítat roviny (kvůli přesnosti - u vektorů se to dá ještě překousnout) Vidíme, že rovina má normálový vektor v_normal a kolmou vzdálenost od nuly f_dist. Potom tam je jakási CRayIsParallel_Exception, k té se dostaneme později. Teď opět seznam funkcí s popisem:

  • Planef() - vytvoření nové roviny, nedělá nic
  • Planef(const Vector3f &v_pos, const Vector3f &v_norm) - vytvoří rovinu z pozice a normály (normálu nechá jak je - neupravuje ji na jednotkovou velikost)
  • Planef(const Vector3f &v_u, const Vector3f &v_v, const Vector3f &v_pos) - vytvoří rovinu ze dvou vektorů, na ní ležících a pozice
  • EPlanePos n_Tri_Pos(const Vector3f &v_a, const Vector3f &v_b, const Vector3f &v_c) const; - vrátí hodnotu, odpovídající relativní pozici trojúhelníka mezi vrcholy v_a, v_b a v_c. Možnosti jsou plane_Front - leží vepředu, plane_Back - leží vzadu, plane_Onplane - leží na rovině a plane_Split - rovina jím prochází
  • EPlanePos n_Tri_PosEx(const Vector3f &v_a, const Vector3f &v_b, const Vector3f &v_c, float f_epsilon_ex) const; - stejná funkce, jen si můžete vybrat jak velká vzdálenost bodu od roviny se bude počítat jako že bod na ní leží
  • EPlanePos n_Vector_Pos(const Vector3f &v_vec) const; - vrátí hodnotu, odpovídající relativní pozici bodu v_vec. Možnosti jsou plane_Front - leží vepředu, plane_Back - leží vzadu, plane_Onplane - leží na rovině a plane_Split - rovina jím prochází
  • EPlanePos n_Vector_PosEx(const Vector3f &v_vec, float f_epsilon_ex) const; - stejná funkce, jen si můžete vybrat jak velká vzdálenost bodu od roviny se bude počítat jako že bod na ní leží
  • Vector3f v_Intersect_Ray(const Vector3f &v_org, const Vector3f &v_dir) const; - vrátí průsečík roviny paprskem, procházejícím bodem v_org směrem v_dir. Tady se může stát, že vektor je rovnoběžný s rovinou, ale funkce nemá jak o tom dát vědět - proto tam je ta CRayIsParrallel_Exception - výjimka. V kódu to vypadá takhle:

Planef p; // rovina
Vector3f org, dir; // paprsek
Vector3f intersection; // průsečík

try {
    intersection = p.v_Intersect_Ray(org, dir);
    // zkusíme ...
} catch(CRayIsParallel_Exception) {
    // ... a sem se dostaneme, pokud byl paprsek rovnoběžný
}
  • float f_Intersect_Ray_t(const Vector3f &v_org, const Vector3f &v_dir) const; - stejná funkce, jen vrátí číslo, kterým musíme vynásobit v_dir a přičíst k v_org, abysme dostali průsečík
  • int operator ==(const Planef &r_plane) const - operátor porovnávání rovin (pracuje s přesností f_epsilon !!)

Tím bysme měli sfouklou rovinu. Následouje matice, se kterou můžeme provádět už známé triky:

  • void Init() - spočítá jednotkovou matici
  • void Translate(const Vector3f &v_dir) - posune matici (po vlastních osách) o vektor
  • void Scale(float f_scale) - zvětší matici ve všech směrech stejným poměrem
  • void Scale(const Vector3f &v_scale) - zvětší matici v každém směru jinak
  • void RotateX(float f_angle) - rotuje okolo osy x, v radiánech
  • void RotateY(float f_angle) - rotuje okolo osy y, v radiánech
  • void RotateZ(float f_angle) - rotuje okolo osy z, v radiánech
  • Matrix4f operator * (const Matrix4f &mat) const - operátor ásobení matic
  • void operator *= (const Matrix4f &mat) - operátor vynásobení matice
  • void operator = (const Matrix4f &mat) - operátor kopírování matic
  • void Inverse() - spočítá onverzní matici
  • Vector3f v_Transform_Pos(const Vector3f &v_vec) const - transformuje vektor, jako by to byla pozice (w = 1)
  • Vector3f v_Transform_Dir(const Vector3f &v_vec) const - transformuje vektor, jako by to byl směr (w = 0)

Matice by pro vás neměla být nic nového, stejně jako ostatně všechno co jsme probrali. Tohle by vás ale mohlo aspo'n maličko vytrhnout (dávejte při tom pozor, nerad bych přišel o čtenáře - tím spíš, že nebezpečí vytržení hrozí hlavně těm pozorným a ti jsou sakra vzácní (teď už víte proč :o))) Máme tu strukturu pro polygon, která umí spoustu věcí jako třeba:

  • void Delete() - smaže svoje data (dělá to taky trochu automaticky, třeba když zrušíte pole tak se v něm všechny polygony samy smažou, nebo když program opustí funkci, kde byla nějaká proměnná typu polygon)
  • int Add_Vertex(TVertexStruct v_vertex) - přidá vrchol
  • int Add_Vertex(const TVertexStruct *p_vertex, int n_num) - přidá pole vrcholů
  • void Delete_Vertices(int n_index, int n_count) - ubere vrchol(y)
  • inline int n_Vertex_Num() const - vrátí kolik má vrcholů
  • inline TVertexStruct &r_Vertex(int n_index) - vrátí vrchol s indexem n_index, můžeme do něj i zapisovat
  • inline const TVertexStruct t_Vertex(int n_index) const - vrátí vrchol s indexem n_index, můžeme jej jen číst
  • const Vector3f v_Center() const - vrátí pozici středu polygonu
  • const Vector3f v_NearestPoint(Vector3f v_point) const - vrátí nejbližší bod, ležící na polygonu, k bodu v_point - užitečné třeba pro detekci kolizí - ukážeme
  • int Calc_Normal() - spočítá si normálu (pozor - může vrátit false, pokud si myslí že polygon je špatně definovaný a nedokáže si to spočítat sám)
  • inline Planef &r_Normal() - vrátí normálu, můžeme i zapisovat
  • inline const Planef t_Normal() const - vrátí normálu, jen pro čtení
  • EPlanePos n_Plane_Pos(const Planef &t_plane) const - vrátí pozici oproti rovině t_plane
  • EPlanePos n_Plane_PosEx(const Planef &t_plane, float f_epsilon_ex) const - stejná funkce, jen můžete počítat s jiným epsilonem
  • int Cut(const Planef &t_plane, EPlanePos n_desired_half) - rozdělí polygon rovinou t_plane, přičemž z něj zůstane jen půlka na straně n_desired_half, což může být plane_Front (vepředu) nebo plane_Back (vzadu) Funkce dobře zvládá i nekonvexní polygony (což se ale bohužel o ostatních dost dobře říct nedá)
  • int CutEx(const Planef &t_plane, EPlanePos n_desired_half, float f_epsilon_ex) - stejná funkce, jen zase můžete určit epsilon
  • int Split(const Planef &t_plane, CPolygon &r_new_poly, EPlanePos n_desired_half) - rozdělí polygon, přičemž půlku si nechá a druhou půlku zkopíruje do r_new_poly
  • int b_Contain_Point(Vector3f v_point) const - vrátí tru, pokud bod v_point leží uvnitř polygonu (netestuje ale jestli leží i v rovině - to musíte udělat sami, pokud potřebujete)
  • int Write(FILE *p_file) const - zapíše data polygonu do souboru
  • int Read(FILE *p_file) - přečte data polygonu ze souboru
  • int operator = (const CPolygon &r_poly) - operátor kopírování polygonů (tady to ušetří spoustu práce, protože si to samo přealokuje pole vrcholů, a vůbec je to šikovné)
  • void Reverb() - přehodí pořadí vrcholů. nedělá ale nic s normálou (měli byste vynásobit normálový vektor a vzdálenost od nuly minus jedničkou)
  • int b_Overlap(const CPolygon &r_poly) const - vrátí true, pokud se polygony překrývají (opět netestuje, jestli leží ve stejné rovině)
  • int b_IsTiny() const - vrátí true, pokud je polygon shledán malým. to je užitečné když chcete smazat polygony, které by jinak přinášely nestabilitu například tím že už jsou tak malé že se nedá s určitostí spočítat normála (víceméně pro BSP)
  • int b_IsTinyEx(float f_edge_epsilon_ex, float f_epsilon_ex) const - stejná funkce, jen si nastavujete jak přísní budeme a jak velké vzdálenosti označíme za malé

Já vím ... to vás asi nějak zvlášť nebere. Ale opravdu jsem nechtěl přijít o ty čtenáře, až jim teď řeknu že to je jen půlka dárečku a že pro vás mám ještě brutálně optimalizovanou knihovnu, umožňující vytváření různých gometrických útvarů... (Mno a jak slyším ty lidi padat ze židlí tak si říkám že to zase nevyšlo :*( )

Když říkám "brutálně optimalizovanou", myslím tím, že dokáže eliminovat nadbytečné vrcholy nebo najít sousední polygony řádově za 0.05 sekundy. (na mém prastarém AthlonXP2000+, objekt s 5000 vrcholy a 4500 polygony) Pokud normálně prohledáváte pole prvek za prvkem, dá to kolem dvou a půl sekundy - jen tak pro srovnání abyste věděli že máte být ohromeni :o).

Struktura se jmenuje TGeometry a umí následující spoustu věcí:

  • void Delete() - smazat se
  • inline Vector3f v_Bound_Min() - minimální souřadnice bounding boxu (podle potřeby se samy přepočítávají, když něco změníte a potom se na ně ptáte)
  • inline Vector3f v_Bound_Max() - maximální souřadnice bounding boxu
  • inline int n_Vertex_Num() const - počet vrcholů
  • inline int n_Polygon_Num() const - počet polygonů
  • inline const TVertex t_Vertex(int n_index) const - vrchol jen pro čtení
  • inline CRefPolygon t_Polygon(int n_index) const - polygon jen pro čtení
  • inline TVertex &r_Vertex(int n_index) - vrchol i pro zápis
  • inline CRefPolygon &r_Polygon(int n_index) - polygon i pro zápis
  • const std::vector *p_PolygonNeighbours(int n_index, int n_edge) - sousedi polygonu n_index na jeho hraně n_edge
  • void DeletePolygons(int n_index, int n_count = 1) - smaž polygon(y)
  • int DeleteVertices(int n_index, int n_count = 1) - smaž vertex(y)
  • TVertex *p_AddVertex(TVertex t_vertex) - přidej vertex
  • TRefVertex t_AddRefVertex(TVertex t_vertex) - jiný způsob přidávání vertexů, tuhle funkci používá CPolygon, když (třeba při půlení rovinou) v něm vznikne nový vertex
  • int Create_Box(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, int n_tess_x = 1, int n_tess_y = 1, int n_tess_z = 1) - vytvoří krabici se středem ve v_org, vektorovou bází v_x, v_y, v_z (tzn. můžete dělat různě velké a otočené boxy) a přerozdělený po ose x na n_tess_x sekcí, po y na n_tess_y a po z na n_tess_z
  • int Create_Grid(Vector3f v_org, Vector3f v_x, Vector3f v_y, int n_material, int n_tess_x = 16, int n_tess_y = 16) - vytvoří rovinu, parametry mají (ve všech funkcích) stejný význam jako u Create_Box
  • int Create_Terrain(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, int n_tess_x, int n_tess_y, unsigned char *p_heightmap_grayscale, int n_width, int n_height) - vytvoří rovinu, kterou navíc vymodeluje grayscale heightmapou
  • int Create_Cylinder(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, int n_cap_material, int n_tess_r = 12, int n_tess_a = 1, int n_tess_cap = 1) - vytvoří válec; tady je zajímavost u n_tess_cap, což je přerozdělení "čepiček". to může být buď menší než nula a žádné čepičky se nedělají, nebo nula a vytvoří se čepička s minimálním počtem trojúhelníků, nebo číslo větší jak nula a vytvoří se hezká segmentovaná čepička, vhodná pro další modelování
  • int Create_Tube(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, float f_inner_r, int n_material, int n_cap_material, int n_tess_r = 12, int n_tess_a = 1) - vytvoří trubku; f_inner_r je relativní poloměr vnitřní stěny. pokud ho zadáte větší než nula, trubka bude mít polygony obrácené "dovnitř"
  • int Create_Cone(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, int n_cap_material, int n_tess_r = 12, int n_tess_a = 1, int n_tess_cap = 1) - vytvoří kužel
  • int Create_Sphere(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, int n_tess_r = 24, int n_tess_a = 12) - vytvoří kouli
  • int Create_Hemisphere(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, int n_cap_material, int n_tess_r = 24, int n_tess_a = 6, int n_tess_cap = 1) - vytvoří polokouli, možnost přidat dospod čepičku
  • int Create_Torus(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material, float f_inner_r, int n_tess_r = 30, int n_tess_sub_r = 12) - vytvoří torus (prstenec)
  • int Create_Octagon(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material) - vytvoří osmistěn
  • int Create_Tetragon(Vector3f v_org, Vector3f v_x, Vector3f v_y, Vector3f v_z, int n_material) - vytvoří čtyřstěn
  • std::vector*> *p_VertexMergeTable(int b_compare_position_only, float f_epsilon_ex) - vytvoří tabulku skupin vrcholů se stejnou pozicí (pokud je b_compare_posiion_only == true), nebo tabulku skupin stejných vrcholů
  • int FindNeighbours() - najde sousedy; není potřeba volat, zavolá se automaticky když chcete sousedy číst
  • int MakeTris() - rozbije polygony výhradně na trojúhelníky
  • int Tesselate(int n_times, float f_normal_tension) - rekurzivně rozděluje polygony, paramter f_normal_tension umožňuje přerozdělené polygony vytlačit ve směru normály a vyhladit tak povrch
  • int Cut(Planef t_plane, EPlanePos n_desired_half, TGeometry *p_other_half = 0) - rozdělí geometrii na dvě půlky
  • int b_IsClosed() const - vrátí true, pokud je geometrie uzavřený objekt (Eulerovo pravidlo)
  • int Hollow(float f_hollow_size) - udělá v každém objektu díru, síla stěn je f_hollow_size
  • int Boolean(const TGeometry *p_geometry, int b_mesh_a, int b_mesh_b, int b_mesh_ab) - booleovská operace - umožňuje sčítat, odčítat nebo protínat objekty
  • int OptimizeVertices(float f_epsilon_ex) - zničí nadbytečné vrcholy
  • int OptimizeTris(int *p_poly_list, int n_poly_num) - optimalizuje vybrané trojúhelníky a nechává je jako trojúhelníky
  • int OptimizeTrisLossy(int n_target_poly_count) - optimalizuje všechno až do té doby, dokud nemá kýžený počet polygonů n_target_poly_count - určeno spíš pro modely, než pro svět
  • int Optimize(int *p_poly_list, int n_poly_num) - optimalizuje vybrané polygony, spojuje je do co největších konvexních polygonů, aby jich bylo co nejmíň
  • int operator = (const TGeometry &r_geometry) - operátor pro kopírování
  • int operator += (const TGeometry &r_geometry) - operátor pro přidávání

Pořád nemůžu uvěřit tomu že jsem to sem dal jen tak ... dalo mi fakt hodně práce to napsat tak doufám že to oceníte ... Tady je ukázka vygenerovaných objektů, které se samozřejmě generují i s normálami, normálami ve vrcholech (pro hladké stínování) a souřadnicemi textur:

primitivní objekty

Ještě jeden detail, jaký má vliv parametr n_cap_tess, pokud ho funkce má: (zleva doprava je n_cap_tess 3, 1, 0 a -1)

teslace čepičky

Mno, tak jsme zase u konce, příště zase pro změnu poladíme OpenGL ... Stahujte, používejte, re-distribuujte - a zkuste občas přidat odkaz nebo poděkování (aby se nezapomnělo kdo je tu swine) když to někam dotáhnete ... Mějte se optimálně!

Demo pro swiní geometrickou knihovnu

-tHE SWINe-


zpět


Valid HTML 4.01!
Valid HTML 4.01