Kirjautuminen

Haku

Tehtävät

Keskustelu: Yleinen keskustelu: OpenGL:n käyttämä formaatti?

Sivun loppuun

Tumpelo [28.08.2006 15:08:18]

#

Mietin tässä että pystyykö millään 3D mallinnusohjelmalla, kuten Blenderillä, tallentamaan tiedoston siihen formaattiin mitä OpenGl käyttää, jolloin pystyisi aina objektien koodit copy pastettamaan suoraan koodiin, ettei joutuisi itse kirjoittamaan sitä. Puhun siis tästä:

glBegin(GL_QUADS);
	glTexCoord2f(1.0f, 1.0f); glVertex3f( -30.0f, -0.1f, -90.0f);
	glTexCoord2f(1.0f, 0.0f); glVertex3f( -30.0f, 45.0f, -90.0f);
	glTexCoord2f(0.0f, 0.0f); glVertex3f( 30.0f, 45.0f, -90.0f);
	glTexCoord2f(0.0f, 1.0f); glVertex3f( 30.0f, -0.1f, -90.0f);
glEnd();

Toivottavasti ymmärsitte mitä tarkoitan...

Pöytälamppu [28.08.2006 15:40:51]

#

Google "blender to opengl":

http://www.blender3d.com/forum/viewtopic.php?t­=5349&sid=88cf08af9db69c13699767a0edc82b10

tuolla on linkki ja ohjeet johonkin ohjelmaan, jonka pitäisi tehdä objekteista koodia.

Meitsi [28.08.2006 16:03:58]

#

Tuo ei kyllä ole järkevin tapa (no, helpoin ainakin), mutta tulevaisuudessa kannattaa opetella jokin toinen tapa, etenkin jos malleja alkaa tulla monia, ja ne monimutkaistuvat.

Zach [28.08.2006 19:53:47]

#

En nyt tuosta helpoimmastakaan menisi ihan sanomaan. Kun ohjelmassa alkaa tarvia useampia 3d-objekteja, joissa on jo tuhansia verteksejä, niiden koodaaminen koodin joukkoon on hankalaa ja hidasta. Kannattava ratkaisu on opetella jokin Blenderin tms. tukema tiedostoformaatti, jolle sitten kirjoittaa ohjelmaansa lataajan - kun sitten muuttaa 3d-objekteja, riittää muutosten näkymiseen omassa ohjelmassa vain Blenderissä tallentaminen. Esim. Wavefront OBJ on helppo tekstitiedostomuoto, jonka käsittelystä selviää yksinkertaisimmillaan parilla kymmenellä rivillä koodia.

Objekteja varten luodaan ainakin taso- ja verteksi-luokat. 3d-tiedostosta haetaan ensin verteksien koordinaatit (+ normaalit ym.), jotka tallennetaan verteksi-tyyppiseen taulukkoon. Myöhemmässä vaiheessa tiedostosta saa selville jokaisen tason verteksien järjestysnumerot, jotka tallennetaan sitten taso-taulukkoon. Piirtovaiheessa kaikki tasot ja niiden verteksit käydään läpi sitten parissa sisäkkäisessä silmukassa.

Tumpelo [29.08.2006 18:06:53]

#

Zach kirjoitti:

En nyt tuosta helpoimmastakaan menisi ihan sanomaan. Kun ohjelmassa alkaa tarvia useampia 3d-objekteja, joissa on jo tuhansia verteksejä, niiden koodaaminen koodin joukkoon on hankalaa ja hidasta. Esim. Wavefront OBJ on helppo tekstitiedostomuoto, jonka käsittelystä selviää yksinkertaisimmillaan parilla kymmenellä rivillä koodia.

Ok, otan sitten nyt projektiksi ottaa käyttöön tuon .obj tiedostojuzkan. Mutta en oikein tiedä mistä aloittaa, joten voisitko avustaa hiukan?

# Blender OBJ File: untitled.blend
# www.blender.org
mtllib untitled.mtl
o Cube_Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
usemtl Material
s off
f 1 2 3 4
f 5 8 7 6
f 1 5 6 2
f 2 6 7 3
f 3 7 8 4
f 5 1 4 8

Tuossa on kuution koodi. Ymmärtänen tuosta tuon verteksi osion, mutta mitä noilla face-jutuilla tekee? Eikös OpenGL tarvitse vain nuo verteksijutut jotta piirtäminen on mahdollista? Ja voisitko olla niin ystävällinen että laitat vaikka esimerkki koodin siitä miten tuosta luettaisiin tiedot ja piirrettäisiin, se auttaisi huomattavasti.

panttu [29.08.2006 21:36:08]

#

Ikös OpenGL:ssä ole minkäänlaista valmista luku funktioita, joka osaisi lukea tuon samaan tapaan, kuin DirectX:n Mesh luokalla.

Zach [29.08.2006 22:59:43]

#

panttu kirjoitti:

Ikös OpenGL:ssä ole minkäänlaista valmista luku funktioita, joka osaisi lukea tuon samaan tapaan, kuin DirectX:n Mesh luokalla.

Ei ole, onneksi. Ihmiset vain laiskistuvat käyttämällä valmiita importtereita ja käyttävät samalla turhan mutkikkaita tallennusformaatteja. Itse tekemällä oppii...(tai sitten ei)

Tumpelo, käytät varmaankin C++:aa? No, perusteet ovat kutakuinkin samat ainakin kaikissa olio-ohjelmointikielissä.

Em. luokat on yksinkertaisimmillaan tämännäköisiä:

class Verteksi
{
   float _x, _y, _x;
  public:
   Verteksi(float x, float y, float z);
   float haeX();
   float haeX();
   float haeX();
};

class Taso
{
   Verteksi _verteksit[4];
  public:
   Taso(Verteksi verteksit[4]);
   Verteksi& haeVerteksit();
};

Kun sitten luetaan tiedostoa, kannattaa ensin tallentaa verteksien koordinaatit Verteksi-taulukkoon, tai mieluummin vaikka
Vector
-säiliöön. Eli luodaan silmukan sisällä uusi Verteksi, jonka arvot luetaan ja joka lisätään taulukkoon, kunnes rivin ensimmäinen "sana" ei enää ole "v". Sitten luodaan uuden silmukan sisällä uusia Taso:ja ja annetaan konstruktorin parametriksi 4-alkioinen taulukko, johon on siirretty "f":n jälkeisten numeroiden ilmoittamat verteksit. Esim. ensimmäiseen tasoon kuuluu ensimmäinen, toinen, kolmas ja neljäs verteksi. Myös Tasot kannattaa pitää Vector-säiliössä, jolloin niitä on helppo lisätä ja poistaa. Taso-luokan konstruktori luonnollisesti tallentaa sille annetut Verteksit omiksi jäseniksiin.

Tumpelo kirjoitti:

Ymmärtänen tuosta tuon verteksi osion, mutta mitä noilla face-jutuilla tekee?

Jep, yksinkertaisilla malleilla mitään ei huomaakaan. Verteksien piirtojärjestys on kuitenkin aika tärkeä asia, minkä huomaa nopeasti kantapään kautta...Tasoluokka pitää ne järjestyksessä. Tämä on välttämätöntä jos aikoo myöhemmin lisätä tekstuureita, valaistusta, törmäystarkistusta tms.

Piirtovaiheessa käydään ensin kaikki tasot silmukassa läpi, ja tämän sisällä piirretään yksittäiset verteksit, esim.

for (int i=0; i<tasot.size(); ++i)
{
   glBegin(GL_QUADS);
   for (int j=0; j<4; ++j)
   {
      glVertex3f(tasot[i].haeVerteksit()[j].haeX(),
                 tasot[i].haeVerteksit()[j].haeY(),
                 tasot[i].haeVerteksit()[j].haeZ());
   }
   glEnd();
}

Tumpelo [30.08.2006 17:38:46]

#

Nyt kyllä tuli aivoissa overflow. Perehdyn noihin joskus ajan kanssa, tuollainen tietomäärä pitää sulatella rauhassa. ^-^

Zach [30.08.2006 18:00:33]

#

:D Voipi olla. Voit koettaa päästä jyvälle jättämällä ensin tasot huomiotta, eli tallennat vaan verteksit taulukkoon ja sitten piirrät ne vaikka pisteinä (glBegin(GL_POINTS)) yhdessä silmukassa.

Metabolix [30.08.2006 20:28:05]

#

Sitten vielä kannattaa pitää mielessä, että tehokasta ohjelmaa ei tuollaisilla luokilla tehdä. Vektori (verteksi) kannattaa ehdottomasti pitää vain yksinkertaisessa structissa, jotta sästyy turhilta funktiokutsuilta sun muilta.

Kuten tuolla varmasti sanottiinkin, missään nimessä ei kannata ohjelman koodiin kirjoittaa malleja ja muita, siitä ei tule mitään. Ne pitää voida ladata tiedostosta, ja jos niitä ei voi väännellä, tulee pelistä helposti aika tönkkö (ellei se aivan palikkapeliksi ole tarkoitettu), eli vakioita kulmien koordinaatit eivät ainakaan voi olla.

arcatan [31.08.2006 06:49:56]

#

Metabolix kirjoitti:

Sitten vielä kannattaa pitää mielessä, että tehokasta ohjelmaa ei tuollaisilla luokilla tehdä. Vektori (verteksi) kannattaa ehdottomasti pitää vain yksinkertaisessa structissa, jotta sästyy turhilta funktiokutsuilta sun muilta.

Mutta eikö luokka ilman minkäänmoisia metodeja, konstruktoreja ja destruktoreja ajaisi saman asian kuin struct? Tämä on tietty tarkistamatonta tietoa, joku voisi korjata.

kayttaja-4976 [31.08.2006 16:17:10]

#

BOOL ReadMesh ()						// Reads The Contents Of The "model.txt" File
{
	FILE *In = fopen ("Data\\model.txt", "rb");		// Open The File

	if (!In)
		return FALSE;					// Return FALSE If File Not Opened

	fread (&polyNum, sizeof (int), 1, In);			// Read The Header (i.e. Number Of Polygons)

	polyData = new POLYGON [polyNum];			// Allocate The Memory

	fread (&polyData[0], sizeof (POLYGON) * polyNum, 1, In);// Read In All Polygon Data

	fclose (In);						// Close The File

	return TRUE;						// It Worked
}

Tuollainen löytyi osoitteesta http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=37 . Voisi olla myös hauskaa tietää miten fileet ovat tehty, mutta eiköhän se tuota kahlatessa tule selville.

Sisuaski [01.09.2006 23:49:22]

#

arcatan kirjoitti:

Metabolix kirjoitti:

Sitten vielä kannattaa pitää mielessä, että tehokasta ohjelmaa ei tuollaisilla luokilla tehdä. Vektori (verteksi) kannattaa ehdottomasti pitää vain yksinkertaisessa structissa, jotta sästyy turhilta funktiokutsuilta sun muilta.

Mutta eikö luokka ilman minkäänmoisia metodeja, konstruktoreja ja destruktoreja ajaisi saman asian kuin struct? Tämä on tietty tarkistamatonta tietoa, joku voisi korjata.

Käsittääkseni luokan ja struktin ainoa ero C++:ssa on, että strukti on "oletuksena" (ennen ensimmäistä public/protected/private-määrettä) public ja luokka privaatti.
Itse kyllä käytän stukteja ja luokkia tosiaan vähän tuohon tyyliin, että pikku datakasat pidän stukteina ja vasta isommista kokonaisuuksista teen luokkia, vaikka pelkkä muotoseikkahan tämä vain on.

Ei tuossa annetussa verteksiluokassa mielestäni sinänsä juuri muuta vikaa ole, kuin että nuo funktiot kannattaisi tosiaan inlineä metabolixin varoittamien turhien funktiokutsujen välttämiseksi.

Itse kyllä toteuttaisin opengl:lää varten verteksiluokan hieman eri tavalla taulukon avulla, koska monissa opengl:n toteutuksissa taulukon lähettäminen funktioille on hieman nopeampaa, ja se varmistaa toimivuuden glVertexPointer-funktiota käytettäessä. Suunnilleen näin siis:

template<typename T>
struct Vertex3
{
        Vertex3(const T& x, const T& y, const T& z)
                {arr[0]=x; arr[1]=y; arr[2]=z;}

        inline T& X() { return arr[0]; }
        inline T& Y() { return arr[1]; }
        inline T& Z() { return arr[2]; }
        inline const T& X() const { return arr[0]; }
        inline const T& Y() const { return arr[1]; }
        inline const T& Z() const { return arr[2]; }

        inline const T* get_arr() const { return arr; }

private:
        T arr[3];       // nopeaa opengl:lle lähettämistä varten
};

kayttaja-4976 [02.09.2006 10:52:18]

#

Eli siis teki millä ohjelmalla hyvänsä (anim8or, Blender, 3D Studio Max), niin ne osaavat tallentaa jotenkin niin että pystyy lukemaan filusta vain verteksien sijainnit? Tuolleenko tuo mallinnuksen lukeminen menee?

Metabolix [02.09.2006 13:18:16]

#

Kyllä ne inline-funktiotkin ovat hitaita, kun niitä käyttää tuollaisiin turhiin asioihin kuin arvojen lukemiseen ja kirjoittamiseen. Erinnäisistä syistä väsäsin omaan projektiini liukulukuluokan, joka siis sisälsi yhden liukulukumuuttujan ja äärimmäisen yksinkertaiset inline-funktiot kaikille peruslaskutoimituksille, ja ohjelman nopeus putosi noin kolmannekseen alkuperäisestä. Ainakin MinGW-GCC:llä käännettynä inline-funktiotkin aiheuttavat funktiokutsuja ja muuta turhaa tavaraa, jolloin ohjelma luonnollisesti hidastuu.

Toki taulukon lähettäminen on nopeampaa, kun tarvitsee laittaa pinoon vain yksi osoitin niiden kolmen liukuluvun sijaan. Tästä ei kuitenkaan tullut merkittävää nopeudenmuutosta sen paremmin Windowsissa kuin Linuxissakaan. Sitä paitsi lopputulos on sama sekä taulukolla että structilla, osoitin kolmijäseniseen structiin on sama kuin kolmijäseninen taulukko.

Useimmat mallinnusohjelmat tykkäävät eniten omasta tiedostomuodostaan, ja useissa tapauksissa kyseisen muodon lukeminen ei ole aivan helppoa, monet tiedostomuodot ovat myös enemmän tai vähemmän suljettuja. Lisäksi näissä tiedostoissa tapaa olla paljon turhaa tavaraa mukana. Oma formaatti on siis varsin hyvä idea, pitää vain saada jotenkin mallinnusohjelmasta ulos selvää tavaraa. Selkokieliset muodot taas ovat valitettavan usein liiankin rajoittuneita. Pelkän mallin saa helposti ulos monista ohjelmista DirectX:n X-formaatissa, joka usein on tekstimuotoinen ja helposti muokattavissa omaan käyttöön, tai jonkinlaisessa raakamuodossa (Raw Triangle Data taisi löytyä Anim8orista tai Wings3d:stä). Blender osaa tallentaa Cal3D-muotoon, joka voisi olla harvinaisen käyttökelpoinen (sisältää kerrankin kylliksi ominaisuuksia), jos vain saisi väännettyä koordinaatiston oikein päin (pitää taas joskus kokeilla). Juuri muihin en ole vielä ihmeemmin tutustunut.

kayttaja-4976 [02.09.2006 19:47:19]

#

Voin kyllä tehdä oman formaatin. Olisi vain kiva tietää mitä sinne tulee laittaa jotta ohjelma voi käsitellä sitä ja siitä saisi sen kolmedee mallin.

[muutatietoa]
Edit: Kelpaisiko http://www.gamedev.net/download/redbook.pdf OpenGL-oppaaksi
[/muutatietoa]

Metabolix [02.09.2006 23:37:33]

#

No juuri sitä, mitä normaalisti OpenGL:llä piirrät, eli kaikkein eniten juuri kärkien koordinaatteja. Esimerkiksi kuution voisi tallentaa näin:

8
1.0 1.0 1.0
-1.0 1.0 1.0
-1.0 -1.0 1.0
1.0 -1.0 1.0
1.0 1.0 -1.0
-1.0 1.0 -1.0
-1.0 -1.0 -1.0
1.0 -1.0 -1.0
12
0 1 2
0 2 3
4 0 3
4 3 7
5 4 7
5 7 6
1 5 2
1 2 6
3 2 6
3 6 7
4 5 1
4 1 0

Ensin kerrotaan kärkien määrä ja kärkien koordinaatit. Sitten kerrotaan kolmioiden määrä ja niiden kärkien numerot. Kolmion etupuoli on se, jolta katsottuna kärjet on lueteltu vastapäivään, ja usein toinen puoli jätetään kokonaan piirtämättä. Tämän formaatin lukeminen on sitten varsin yksinkertaista: luetaan kärkien määrä ja taulukkoon niiden koordinaatit, sitten kolmioiden määrä ja niiden kärjet. Piirtäminen tapahtuu silmukassa: käydään läpi kaikki kolmiot, jokaisen kohdalla syötetään OpenGL:lle vastaavien kärkien sijainnit.

Mutkikkaampiin asioihin sitten tarvitsee hieman mutkikkaampia formaatteja. Esimerkiksi teksturointia varten pitää tallentaa tekstuurikoordinaatit.

Mainittakoon vielä, että tuo kuutiomallinnos on nyt tehty päässä, ja kun OpenGL ei tahdo tässä kannettavalla näköjään toimia, en voi kolmioiden oikeellisuutta testata. Eli en vastaa kolmioiden asennoista. :)

kayttaja-4976 [03.09.2006 09:09:44]

#

Ja sitten vielä voi siinä fileessä mainita kunkin pinnan värin jotta se näyttäisi hienolta? Pystyyköhän Anim8or tähän?

Tumpelo [03.09.2006 10:30:35]

#

No aloin nyt toteuttamaan .obj (Wavefront Object) tiedoston lukua ja itse tiedoston lukeminen onnistuu mainiosti, nyt vain pitäisi saada tallennettua verteksit ja tasot jonnekin. Miten ne saisi tallennettua kätevästi? Tässä täytyy ottaa huomioon että sitä ei ennalta tiedetä että kuinka monta verteksilukua jne pitää tallentaa. Niitä voi tulla 10 tai 10 000.

Zach [03.09.2006 11:00:35]

#

C++ Standart Template Libraryn (STL) Vector-tietosäiliö on nimenomaan sellaiseen kätevä. Siihen voi alustuksen jälkeen lisätä ajon aikana uusia jäseniä, eikä tarvitse välittää taulukon koon kasvattamisesta. Esim.

#include <vector>

using namespace std;

struct Verteksi
{
   float x,y,z;
};

int main()
{
   Vector<Verteksi> verteksit;
   //luodaan Vector-olio, jonka yhden alkion koko on Verteksi-structin mukainen.

   Verteksi v = {0.0f, 12.0f, 31.0f};
   verteksit.push_back(v);
   //lisätään v verteksit-säiliön viimeiseksi jäseneksi

   //typerä silmukka, joka esittää vielä Vectoriin lisäämistä
   for (int i=0; i<5; ++i)
   {
      v.x = i;
      v.y = i*2;
      v.z = i*3 +2;
      verteksit.push_back(v);
   }

   //alkioihin voi viitata samalla tavalla kuin taulukoissa
   Verteksi uusi = verteksit[4];

   return 0;
}

Esim. silmukoita varten Vectorin nykyisen koon saa selville size()-funktiolla.

Metabolix [03.09.2006 11:09:23]

#

Tuo on vähän paha piirre formaatissa noin tehokkaan lukemisen kannalta. Paras tapa on käyttää lukemisvaiheessa jonkinlaista laajenevaa tietorakennetta, joka sitten lukemisen loputtua säädetään kuntoon tehokasta käyttöä varten. Jos C++ on käytössä, vector voi olla varteenotettava vaihtoehto, muuten käsipelillä laajennettava taulukko (C:ssä realloc-funktiolla esimerkiksi 128 alkiota suuremmaksi aina kerrallaan). Ensimmäisessäkin tapauksessa käyttäisin sitten lukemisen jälkeen perinteisiä muistinpaloja ilman mitään ylimääräistä tavaraa: näitä optimointeja on tullut harrastettua, ja vector oli merkittävä hidaste, kun tietoja piti käyttää. Toki siinä vaiheessa, kun tietoa ei enää lisätä, voi ottaa osoittimen ensimmäiseen alkioon, jolloin sitä voi käyttää yhtä tehokkaasti kuin tavallistakin taulukkoa.

Ja Zach muistaa, että vector kirjoitetaan pienellä. ;)

Tumpelo [03.09.2006 12:13:52]

#

Nojoo, päädyin tekemään sellaisen systeemin että lisään käsin jokaisen obj tiedoston alkuun verteksien määrän, sitten looppi luo tarpeeksi ison taulukon johon sitten lisäilen verteksit. Yksinkertainen ja toimiva, ehkä nopeakin systeemi?

Metabolix [03.09.2006 12:27:50]

#

Mutta epäkäytännöllinen sinänsä, että joudut käsin muuttelemaan. Kannattaa nyt jonkinlainen muunnosohjelma ainakin tehdä ellei muuta. Helpostikos ne erilailla alkavat rivit laskee.

Tumpelo [03.09.2006 12:44:54]

#

Metabolix kirjoitti:

Mutta epäkäytännöllinen sinänsä, että joudut käsin muuttelemaan. Kannattaa nyt jonkinlainen muunnosohjelma ainakin tehdä ellei muuta. Helpostikos ne erilailla alkavat rivit laskee.

Eipä tuo pahemmin työtä tuo, Blenderistä näkee verteksien määrän ja sen vaan lyö sitten tiedoston alkuun tyyliin "ve 123".

Metabolix [03.09.2006 13:22:41]

#

Kun nuo Blenderistä tulevat kuitenkin Python-skripteillä ulos, niin sinnehän voisi vaikka lisätä skriptiin ne pari kriittistä riviä... ;)

Zach [03.09.2006 13:49:34]

#

Metabolix kirjoitti:

Ja Zach muistaa, että vector kirjoitetaan pienellä. ;)

Katos vaan, jäänyt Javasta toi iso kirjain :S

kayttaja-4976 [03.09.2006 21:11:47]

#

Voisiko joku infota minua mitä pitää tehdä tällä tavalla:

1. Tee filee
2. Lue filee
3. Piirrä filee

Haluaisin 3Dnoobina tietää mitä kaikkea tuohon tarvitaan. Pointti: En kysy valmista koodia.

Sisuaski [04.09.2006 20:59:28]

#

Metabolix kirjoitti:

Kyllä ne inline-funktiotkin ovat hitaita, kun niitä käyttää tuollaisiin turhiin asioihin kuin arvojen lukemiseen ja kirjoittamiseen. Erinnäisistä syistä väsäsin omaan projektiini liukulukuluokan, joka siis sisälsi yhden liukulukumuuttujan ja äärimmäisen yksinkertaiset inline-funktiot kaikille peruslaskutoimituksille, ja ohjelman nopeus putosi noin kolmannekseen alkuperäisestä. Ainakin MinGW-GCC:llä käännettynä inline-funktiotkin aiheuttavat funktiokutsuja ja muuta turhaa tavaraa, jolloin ohjelma luonnollisesti hidastuu.

Toki taulukon lähettäminen on nopeampaa, kun tarvitsee laittaa pinoon vain yksi osoitin niiden kolmen liukuluvun sijaan. Tästä ei kuitenkaan tullut merkittävää nopeudenmuutosta sen paremmin Windowsissa kuin Linuxissakaan. Sitä paitsi lopputulos on sama sekä taulukolla että structilla, osoitin kolmijäseniseen structiin on sama kuin kolmijäseninen taulukko.

Monesti sanotaan, että kääntäjä tietää koodaajaa paremmin, mikä on nopeaa. Tämä pätee myös GCC:n kohdalla, mutta vain jos pyydät sitä tekemään niin.
Optimoimattomana tekemäsi vertailu on hieman "epäreilu", koska näytät jo itsekin huomanneen, että gcc jättää inlinet monesti kokonaan huomioimatta, mikäli optimointitaso on -O1:tä alhaisempi (en ole jaksanut selvittää että mistä tietystä flagista tämä riippuu). Ja ainakin omasta mielestäni kääntäjän optimointi on ihan perusjuttuja (juuri tämän "kääntäjä tietää koodaajaa paremmin"-argumentin perusteella) eikä mitään vain 4k-introkoodaajien epävakaita härpäkkeitä.

Piti tottakai kokeilla itsekin tuota liukulukuluokkatestiäsi, ja GCC tosiaan teki optimoimattomana ohjelmasta ruman purkan sen kanssa verrattuna tavallista floattia käyttävään, ja ainakin omalla testikoodillani oli ~1/3 hitaampi. Sen sijaan jo -O1-flagin kanssa GCC 4.1.1:n tuottamien assemblykoodien ero jäi tasan seuraavaan:

--- float.t	2006-09-04 20:45:29.000000000 +0300
+++ float.f	2006-09-04 20:45:21.000000000 +0300
@@ -29,10 +29,10 @@
 .L2:
 	fld	%st(2)
 	fmul	%st(3), %st
-	fld	%st(0)
-	fmul	%st(4), %st
-	fld	%st(1)
-	fadd	%st(5), %st
+	fld	%st(3)
+	fmul	%st(1), %st
+	fld	%st(4)
+	fadd	%st(2), %st
 	fdivrp	%st, %st(1)
 	fld	%st(3)
 	fsub	%st(5), %st

- eli toisinsanoen ei oikein mitään eroa.

Tuossa taulukon turhuudessa taidat kyllä olla oikeassa. Ajattelin jotenkin, että jos struktit olisi jaettu erikokoisiin palasiin kuin sizeof(float), niin ohjelma ei enää toimisikaan samalla tavalla kolmella erillisellä muuttujalla, mutta kaipa se suunnilleen samalla tavalla menee jokaisella alustalla josta liukulukusuoritin ja OpenGL löytyvät.
Taulukon lähettämisessä oli mielessä lähinnä se, että OpenGL Red Bookissa muistaakseni sanottiin, että jotkut libGL:n implementtaukset pystyvät toimimaan nopeammin näin, mutta en sitten tiedä, että miten monissa ajureissa näin on käytännössä.

Metabolix [05.09.2006 08:47:49]

#

Kiinnostavaa, minulla ero jäi nimittäin nopeudessa näkyvän suureksi, vaikka käytin -O2:sta kyseisessä ohjelmassa. Kääntäjä oli Dev-C++:n mukana tuleva MinGW-GCC-versio, olisiko 3.3 suunnilleen. Täytynee vielä ihmetellä lisää.

Tumpelo [05.09.2006 18:20:54]

#

int DrawObject(int Object)
{
	int loop = 0;
	int Verteksi, Verteksi2, Verteksi3, Verteksi4;

	while(loop < Object0Face[0][0])
	{
		loop += 1;

		Verteksi = Object0Face[loop][0];
		Verteksi2 = Object0Face[loop][1];
		Verteksi3 = Object0Face[loop][2];
		Verteksi4 = Object0Face[loop][3];

		glBegin(GL_QUADS);
	glTexCoord2f(1.0f, 1.0f); glVertex3f( Object0[Verteksi][0], Object0[Verteksi][1], Object0[Verteksi][2]);
	glTexCoord2f(1.0f, 0.0f); glVertex3f( Object0[Verteksi2][0], Object0[Verteksi2][1], Object0[Verteksi2][2]);
	glTexCoord2f(0.0f, 0.0f); glVertex3f( Object0[Verteksi3][0], Object0[Verteksi3][1], Object0[Verteksi3][2]);
	glTexCoord2f(0.0f, 1.0f); glVertex3f( Object0[Verteksi4][0], Object0[Verteksi4][1], Object0[Verteksi4][2]);
		glEnd();

	}

   	return(1);
}

Onko tuossa koodissa jotain hassusti, kun kääntäjä antaa tuon takia segmentti virheen..?

EDIT: Voiko johtua siitä että nuo Object0[Verteksi4][0] yms jutut ei sisällä äffää niissä, vaikka ne on GLfloatteja?

Zach [05.09.2006 19:29:08]

#

Tumpelo kirjoitti:

EDIT: Voiko johtua siitä että nuo Object0[Verteksi4][0] yms jutut ei sisällä äffää niissä, vaikka ne on GLfloatteja?

Niillä f:llä taitaa olla väliä ainoastaan tyyppimuunnoksissa, luvun arvoon ne eivät vaikuta. Virheenä on todennäköisesti, että loop kasvaa liian isoksi viimeisessä kierroksessa - jos sen arvo on yhden pienempi kuin tuo Object0Face[0][0], silmukkaa jatketaan, mutta loop kasvaa heti sen jälkeen ja viittaa jo taulukon ulkopuolelle. Rivin "loop += 1;" siirtäminen silmukan loppuun auttanee. Ja ilmoittaako tuo ObjectOFace[0][0] varmasti tasojen määrän?

Tumpelo [05.09.2006 19:40:43]

#

Zach kirjoitti:

Tumpelo kirjoitti:

EDIT: Voiko johtua siitä että nuo Object0[Verteksi4][0] yms jutut ei sisällä äffää niissä, vaikka ne on GLfloatteja?

Niillä f:llä taitaa olla väliä ainoastaan tyyppimuunnoksissa, luvun arvoon ne eivät vaikuta. Virheenä on todennäköisesti, että loop kasvaa liian isoksi viimeisessä kierroksessa - jos sen arvo on yhden pienempi kuin tuo Object0Face[0][0], silmukkaa jatketaan, mutta loop kasvaa heti sen jälkeen ja viittaa jo taulukon ulkopuolelle. Rivin "loop += 1;" siirtäminen silmukan loppuun auttanee. Ja ilmoittaako tuo ObjectOFace[0][0] varmasti tasojen määrän?

Noissa ei ollut vikaa, mutta funktiossa joka lukee tasot ja vektorit muistiin oli pieni viba - tasot tallennettiin floattina vaikka taulukko oli intti.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta