Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: 3D oppaita

Sivun loppuun

mika132 [02.05.2012 22:54:02]

#

Olen saanut erillaisia oppaita. Lukenut ja pähkäillyt. Latasin Visual C++ kääntäjän, koska lähes kaikki 3D oppaat on tehty kyseiselle ohjelmalle. No en kuitenkaan saa tolkkua tuosta. Luin 2 viikon ajan noita erillaisia oppaita ja katsoin koodeja ja käytin testi ohjelmia ja yritin muokata testiohjelmia, mutta en onnistu edes siinä, että saisin kuution mikä ei pyöri. En käytä OpenGL koska en sitä saanut millään toimimaan vaan DirectX.. Löysin netistä perus ohjelman missä on alustettu joitan funktioita ja tehty ikkuna jnejne, mutta minulla ei ole mitään käsitystä, koska missään oppaassa en sitä näe, että miten voidaan piirtää neliö.

Siitä ei ole mitään apua, että luen oppaita, koska kaikki on vanhentuneita. Tai tuoretta en ainakaan ole löytänyt.. Tietääkö joku jotain opasta? On kaikkia recourse.h tiedostoja, missä on paljon jotain #define tietoa, mutta missään ei selitetä mitä nekään meinaa. Olisin kiitollinen jostian oppaasta, ja ehkä pienestä selityksestä. :)


Sitten tietääkö joku jotain helpohkoa 3D moottoria. Tällä hetkellä harjoitus projektinani on maailma, missä luon neliöitä ja siellä voisi liikkua (kyllä sain idean minecraftista) ajattelin, että sellaisen toteutus olisi helpointa harjoitus mielessä?

johku90 [02.05.2012 23:53:42]

#

Itse olen aika vasta opetellut käyttämään openGL:ää. Sen harjoitteluun voisin antaa hyviä vinkkejä.

mika132 kirjoitti:

Latasin Visual C++ kääntäjän, koska lähes kaikki 3D oppaat on tehty kyseiselle ohjelmalle

Ei kait kääntäjän pitäisi hirveästi vaikuttaa käytettävään koodiin, vai enkö vain ymmärtänyt jotakin? 3d-ohjelmointia voi kyllä sujuvasti harjoittaa kaikilla kääntäjillä.

Miksi et saanut openGL:ää toimimaan? Jos vielä kokeilisit, ja kääntyisit mainion oppaan puoleen. SDL on todellakin ihan hyvä vaihtoehto ikkunan ja inputien hallitsemiseen. Toinen hyvä, mitä itsekin olen käyttänyt, on GLFW. Täällä neuvotaan ikkunan luonti, ja juurikin se neliön piirtäminen GLFW:n avulla.

Itse openGL:ää voi hyvin treenata NeHen tutoriaaleilla.

Edit: Muistithan linkittää openGl:n oikein? Muutenhan se ei mene kääntäjästä läpi.

Joku stackoverflowissa kirjoitti:

You don't need to download anything to use OpenGL. Just add

#include <gl/GL.h>
#include <gl/GLU.h>
to the top of your source file. And you also need to link the libraries, which in MSVC can be done like this:

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
With the header files provided with microsoft, you are stuck with version 1.1 of ogl. I suggest getting the latest extension headers from the OpenGL website, as well as something like GLEW. This will give you access to the latest available functions and constants in OpenGL.

MinGW:llä vastaavasti käännettäessä lisätään parametrit -lopengl32 ja -lglu32.
Jos käytät sdl:ää tai glfw:tä, niin nekin pitää linkittää samalla tavalla. Jos kääntäjä valittaa, ettei löydä lib-tiedostoja, niin silloin ne ovat hukassa :) Lataa ne jostakin ja lisää kääntäjän lib-kansioon.

mika132 [03.05.2012 01:32:24]

#

aa.. Nyt sain opengl toimimaan. Kiitos.

Menin oppaan liittyen SDL lävitse ja toimii. :) Seuraavaksi alkaakin kysymys, että miten koko systeemi voidaan muuttaa 3D muotoon? pystytäänkö siinä vielä käyttämään SDL. Miten se edes tapahtuu?

Edit: Esim tällä hetkellä NeHe ohjeiden mukaan saan tuon "ChoosePixelFormat(hDC,&pfd)" funktiosta virheen.

Virhe on:
E:/Mika/CPP/Newest/3D/main.cpp:375: undefined reference to `ChoosePixelFormat@8'

Ja lisää erroria tulee:
E:/Mika/CPP/Newest/3D/main.cpp:382: undefined reference to `SetPixelFormat@12'
obj\Debug\main.o: In function `WinMain@16':
E:/Mika/CPP/Newest/3D/main.cpp:522: undefined reference to `SwapBuffers@4'


Ps. Tietääkö kukaan opasta maailma generaattoriin? Peli tekisi itsestään käynnistyessä 3D maailman nimenomaan kuutioista?

Anaatti [03.05.2012 10:04:18]

#

Tottakai voit käyttää SDL:ää myös 3D:ssä. SDL:hän ei tee tässä tapauksessa mitään muuta, kuin avaa ikkunan grafiikan osalta ja OpenGL hoitaa kaiken piirtämisen eli myös 3D:n. gluPerspective on funktio, jolla saat luotua kolmiulotteisen perspektiivin esim seuraavasti:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, 800.0 / 600.0, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);

Sitten vain piirrät esim seuraavasti:

glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-1, -1, -1);
glVertex3f(1, -1, -1);
glVertex3f(-1, 1, -1);
glVertex3f(1, 1, -1);
glEnd();

3D maailmassa on siis käytössä x-, y- ja z-koordinaatit ja niiden hahmottaminen voi olla aluksi melko vaikeaa. Ylläolevalla pätkällä pitäisi uskoakseni kuitenkin ilmestyä jotain ruudulle.

Jos vielä kaipaat jotain valmista matskua, jota saa vapaasti käyttää, niin olen itse vääntänyt jonkin verran juttuja juurikin SDL + OpenGL yhdistelmällä. Täältä löytyy.

johku90 [03.05.2012 11:14:54]

#

Jos siis käytät SDL:ää, niin sinun ei tarvitse luoda ikkunaa noin vaikeasti, kuin tuolla nehen tutoriaaleissa. Voit aivan rauhassa keskittyä openGL-koodiin :)

Tuo maailmageneraattori kannattaa yrittää kehittää itse. Jos maailma koostuu kuutioista, niin silloin se kannattaa tehdä tiilipohjaiseksi. 3d-maailmassa näitä tiiliä vain on useammassa kerroksessa.

Lumpio- [03.05.2012 11:32:39]

#

mika132 kirjoitti:

Ps. Tietääkö kukaan opasta maailma generaattoriin? Peli tekisi itsestään käynnistyessä 3D maailman nimenomaan kuutioista?

Onko siinä nyt mitään hauskaa jos kaikkeen on valmis opas? Hauska osahan on keksiä itse ja toteuttaa.

User137 [03.05.2012 12:51:03]

#

mika132 kirjoitti:

Sitten tietääkö joku jotain helpohkoa 3D moottoria. Tällä hetkellä harjoitus projektinani on maailma, missä luon neliöitä ja siellä voisi liikkua (kyllä sain idean minecraftista) ajattelin, että sellaisen toteutus olisi helpointa harjoitus mielessä?

3D-pelimaailma ei koskaan ole helppo projekti. Minecraft on paljon vaikeampi tehdä kuin luulisi. Jos nyt yksinkertaistaa, niin saat opetella 3D:tä ainakin vuoden jotta ymmärrys siihen riittäisi. Ei siihen omatkaan taidot taida vielä riittää vaikka monta 3D-tyylistä peliä olenkin tehnyt.

Tai no, joku yksinkertanen ruudukko voi tosiaan olla helpoimmasta päästä, jos ei edes animaatiota ole.

mika132 [03.05.2012 18:11:56]

#

Anaatti kirjoitti:

Tottakai voit käyttää SDL:ää myös 3D:ssä. SDL:hän ei tee tässä tapauksessa mitään muuta, kuin avaa ikkunan grafiikan osalta ja OpenGL hoitaa kaiken piirtämisen eli myös 3D:n. gluPerspective on funktio, jolla saat luotua kolmiulotteisen perspektiivin esim seuraavasti:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, 800.0 / 600.0, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);

Sitten vain piirrät esim seuraavasti:

glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-1, -1, -1);
glVertex3f(1, -1, -1);
glVertex3f(-1, 1, -1);
glVertex3f(1, 1, -1);
glEnd();

3D maailmassa on siis käytössä x-, y- ja z-koordinaatit ja niiden hahmottaminen voi olla aluksi melko vaikeaa. Ylläolevalla pätkällä pitäisi uskoakseni kuitenkin ilmestyä jotain ruudulle.

Jos vielä kaipaat jotain valmista matskua, jota saa vapaasti käyttää, niin olen itse vääntänyt jonkin verran juttuja juurikin SDL + OpenGL yhdistelmällä. Täältä löytyy.

Okei. Tutustuin 3D maailmaan ohjelmallasi "Ray tracer" ongelma muodostui siinä, että prosessorin syönti on maksimissaan kokoajan ja peli aivan jäässä. Tein yhden SDL oppimani asian eli:

        while (pelin_kello + ajan_muutos <= sekunnit()) {
			pelin_kello += ajan_muutos;
			piirretty = false;
        }

		if (piirretty) {
		    odota();
		} else {

Tuon viritelmän ja muutin ajan_muutos muuttujan. 0.04 ja odota() funktiossa on SDL_Delay(250)
sain prosessorin käytön tippumaan 49.. mutta melko pian nousi takaisin 50%. (50% on täysi teho koska tupla ydin)
No sitten skaalasin 10x ohjelman. Grafiikka meni tosi suttuiseksi, mutta prossu syönti tippui 45%. Pätkii edelleen hieman, mutta grafiikasta ei saa mitään selvää. Onko vinkkiä, että mistä tuo pätkiminen johtuu? Miten voisin vielä sitä yrittää parantaa.

Ja toisekseen ruutu luodaan HW_SuRFACEEN eli näytönohjaimen muistiin? Miten se vaikuttaa prosessorin syöntiin. Eli grafiikassa vika ei ainakaan ole. (1024mb näytönohjain) ja prosessorikin on 2,8GHz, ettei sekään kyllä tuossa PITÄISI kesken loppua?

Anaatti [03.05.2012 18:36:33]

#

Ikävä tuottaa pettymys, mutta kyseinen ohjelma ei käytä OpenGL:ää. Olisi näköjään pitänyt mainita, että tuolta löytyvät 'Landscape generator' ja 'Four dimensional demonstration' ovat ne, jotka käyttävät OpenGL:ää. Kyllähän sen koodeista näkee ja viimeistään readmestä lukee, että ei ole OpenGL:ää. Muutenkin ray tracerit perinteisesti toimivat prosessorilla ja eivät ole reaaliaikaisia.

mika132 [03.05.2012 22:56:56]

#

3D:tä tänään harjoitellut ja sain väsättyä pienoisen pelimoottorin mikä tekee kuutioita 4kpl.. Ongelma on siinä, että mikä olisi järkevä tapa tallentaa kuutioita? Tuo on hyvin kamalaa kun tuota:

    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f( 1.0f, 1.0f,-1.0f);
    glVertex3f(-1.0f, 1.0f,-1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f( 1.0f, 1.0f, 1.0f);)

    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f( 1.0f,-1.0f, 1.0f);
    glVertex3f(-1.0f,-1.0f, 1.0f);
    glVertex3f(-1.0f,-1.0f,-1.0f);
    glVertex3f( 1.0f,-1.0f,-1.0f);

    glColor3f(0.0f,1.0f,0.0f);
    glVertex3f( 1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f, 1.0f, 1.0f);
    glVertex3f(-1.0f,-1.0f, 1.0f);
    glVertex3f( 1.0f,-1.0f, 1.0f);
.
.
.
.

koodia on noin 200 riviä. Eli mikä olisi hyvä tapa tallentaa joku kuutio?

Sitten kysymys kaksi. Kuutioista näkee läpi? Minulla on vihreä, punainen, sininen, violetti ja keltainen kuutio ja ne ovat linjassa. Jos menen esim vihreän kuution taakse näen sen läpi punaisen sinisen violetin ja keltaisen. Miten tuollaisen saisi pois?

johku90 [03.05.2012 23:39:10]

#

mika132 kirjoitti:

Eli mikä olisi hyvä tapa tallentaa joku kuutio?

Kokeile tehdä funktio, joka piirtää halutun kokoisen kuution. Piirtämiskohdan voi siirtää glTranslatef()-funktiolla, jonka jälkeen kutsut kuutiofunktiota.

void drawCube(float width, float r, float g, float b){

    glColor3f(r, g, b);

    glBegin(GL_QUADS);
    glVertex3f(0, 0, 0);
    glVertex3f(width, 0, 0);
    glVertex3f(width, width, 0);
    glVertex3f(0, width, 0);
    glEnd();

    // tähän perään vielä loput viisi tahkoa..
}

Sitten piirtovaiheessa kutakuinkin näin:

glPushMatrix();
glTranslatef(x, y, z);
drawCube(2.0, 0.6, 0.2, 0.2);
glPopMatrix();

Tuo siis piirtää punertavan kuution kohtaan x y z

User137 [04.05.2012 00:04:48]

#

glBegin, glEnd käyttöä kannattaa välttää silloin kun mahdollista. Laita siis edes kaikki kuution sivut yhden glBegin-glEnd lohkon sisään, ei kuuden eri. Menee hitaammaks muuten.

Syvyystarkistuksen saa päälle sanomalla ohjelmalle glEnable(GL_DEPTH_BUFFER). Ennen piirtoa kun tyhjennät ruudun glClear:lla, niin yhdistät väripuskuriin tai-bittioperaatiolla GL_DEPTH_BUFFER_BIT. Noista termeistä löytyy myös varmasti esimerkkejä googlella.

mika132 [04.05.2012 01:51:53]

#

Kiitoksia. Tässä nyt alkanut tosiaan hieman pääsemään kärryille ja yritin tekstuureita asennuttaa, mutta niissä on ongelma. Kuutioni on täysin valkoinen vaikka yritän NeHe:n ohjeiden mukaan asennuttaa siihen laatikon ulkokuorta. Viitsisikö joku sanoa missä vika:

main funktiossa on tälläinen kohta:

	if (TextureImage[0]=SDL_LoadBMP("img/Crate.bmp"))
	{
		Status=TRUE;

		glGenTextures(3, &texture[1]);
		glBindTexture(GL_TEXTURE_2D, texture[1]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->w, TextureImage[0]->h, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]);
	} else {
        return 3;
	}

loopissa on piirto funktio ja piirtofunktio sisältää melkoisen sekamelskan:

void piirra(void)
{
//    glTranslatef(posx + cos(yaw) * cos(pitch), posy + sin(pitch), posz + sin(yaw) * cos(pitch));             // Move Left And Into The Screen
	// Kolmio; kulmien värit annetaan näppärästi osoittimena
    glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
    gluLookAt(posx, posy, posz, posx + cos(yaw) * cos(pitch), posy + sin(pitch), posz + sin(yaw) * cos(pitch), 0, 1, 0);

	glBindTexture(GL_TEXTURE_2D, texture[1]);
	glBegin(GL_QUADS);
		// Front Face
		glNormal3f( 0.0f, 0.0f, 2.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		// Back Face
		glNormal3f( 0.0f, 0.0f,-2.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		// Top Face
		glNormal3f( 0.0f, 1.0f, 0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		// Bottom Face
		glNormal3f( 0.0f,-1.0f, 0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		// Right face
		glNormal3f( 1.0f, 0.0f, 0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		// Left Face
		glNormal3f(-1.0f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
	glEnd();

	if (kaksoispuskurointi) {
		SDL_GL_SwapBuffers();
	}
}

Tuolla saan piirrettyä siis kuution, mutta se on valkoinen.. Ei mitään tekstuuria. Missä vika siis on?

User137 [04.05.2012 02:53:01]

#

Nämä ei kuulu piirra()-funktioon. Niitä ei tarvitse suorittaa kuin kerran ohjelman alussa, kun OpenGL on alustettu.

        glEnable(GL_TEXTURE_2D);
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

En tiedä tarkkaan SDL:n käytöstä tuossa, mutta ainakin osoitat pikselidatan suoraan muuttujaan TextureImage[0]. Olisko sillä joku TextureImage[0]->data tai vastaava?

Metabolix [04.05.2012 02:58:06]

#

Tekstuurin latauksesta on malli koodivinkissäni. Käytä sitä äläkä kikkaile omiasi, kun et vielä osaa.

mika132 [04.05.2012 16:27:44]

#

Käytin koodivinkkiäsi ja NeHen textuuri opasta. texture[1] tulostin konsoliin ja sen arvo on 1. Silti ei näy kuin pelkkä valkoinen kuutio.

Muutin nuo enablet ja shadet yms alustus funktioon. Muuten koodi on samallaista, mutta ei näy kuin valkoinen kuutio.

Anaatti [04.05.2012 17:18:34]

#

Heitäppä vielä seuraavat sinne alustusfunktioon, jollei jo ole:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Itsellä ainakin tekstuurit näkyy pelkkänä valkoisena ilman tuota GL_BLEND:iä.

User137 [04.05.2012 18:56:12]

#

Et sanonut mitään tuon gluBuild2DMipmaps() korjaamisesta. Se viimeinen parametri pitää viitata pikselidataan, ei tekstuurin tietueeseen. Ensimmäisen pikselin väri varmaan määräytyy jostain kuvan leveys-arvosta :D Loput luetaankin varaamattomalta alueelta.

ps. Koodivinkissä lukee apu->pixels.

mika132 [09.05.2012 01:27:51]

#

Nyt alkaa kyllä hermo palamaan. Pyöritellyt ja käännellyt ja edelleen valkoinen kuutio 3D maailmassani. Tällä hetkellä näyttää tältä:

void alusta(void)
{
	// Ensin pitää hoitaa SDL aluilleen
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
		printf("Virhe: SDL_Init: %s\n", SDL_GetError());
		exit(virhe = 1);
	}

	// Sitten asetetaan OpenGL:lle parametrit
	// Väreille tietty bittimäärä
	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, VARIN_BITIT);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, VARIN_BITIT);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, VARIN_BITIT);
	// Syvyyspuskurille jotain...
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, SYVYYS);
	// Kaksoispuskurointi käyttöön
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	// Käynnistetään video. Pintaa ei tarvitse ottaa muistiin.
	if (SDL_SetVideoMode(LEVEYS, KORKEUS, 0, SDL_OPENGL | IKKUNALIPPU) == NULL) {
		printf("Virhe: SDL_SetVideoMode: %s\n", SDL_GetError());
		exit(virhe = 2);
	}

	// Katsellaan, millaiset asetukset saatiin aikaan
	SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &syvyys);
	SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &kaksoispuskurointi);
	if (syvyys > SYVYYS) {
		printf("Syvyys on toivottua suurempi \\o/. Pyydettiin %d, saatiinkin %d...\n", SYVYYS, syvyys);
	} else if (syvyys < SYVYYS) {
		printf("Syvyys on toivottua pienempi :(. Haluttiin %d, saatiinkin %d...\n", SYVYYS, syvyys);
	}
	if (!kaksoispuskurointi) {
		printf("Ei ole kaksoispuskuria! Qu'est-ce que c'est que cela? O_o\n");
		printf("Nyt voi sattua hassuja...\n");
	}
    glMatrixMode(GL_PROJECTION);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
	glEnable(GL_DEPTH_TEST);
    glLoadIdentity();
    gluPerspective(85.0, 600.0 / 400.0, 0.1, 400.0);
    glMatrixMode(GL_MODELVIEW);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
	glClearDepth(1.0f);
	// Rullataan vielä viestit läpi ja nollataan aikalaskuri
	if (hoida_viestit() != 0) {
		exit(virhe = 0);
	}
	laske_kulunut_aika();
}

void piirra(void)
{
//    glTranslatef(posx + cos(yaw) * cos(pitch), posy + sin(pitch), posz + sin(yaw) * cos(pitch));             // Move Left And Into The Screen
	// Kolmio; kulmien värit annetaan näppärästi osoittimena
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
    gluLookAt(posx, posy, posz, posx + cos(yaw) * cos(pitch), posy + sin(pitch), posz + sin(yaw) * cos(pitch), 0, 1, 0);
    glBindTexture(GL_TEXTURE_2D, tex);
	glBegin(GL_QUADS);
		// Front Face
		glNormal3f( 0.0f, 0.0f, 2.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		// Back Face
		glNormal3f( 0.0f, 0.0f,-2.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		// Top Face
		glNormal3f( 0.0f, 1.0f, 0.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		// Bottom Face
		glNormal3f( 0.0f,-1.0f, 0.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		// Right face
		glNormal3f( 1.0f, 0.0f, 0.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		// Left Face
		glNormal3f(-1.0f, 0.0f, 0.0f);
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
	glEnd();

	// Piirrokset esille
	if (kaksoispuskurointi) {
		SDL_GL_SwapBuffers();
	}
}

ja main funktiossa:

// SDL kaipaa toisinaan mainille parametreja, vaikkei niitä käytettäisi
int main(int argc, char **argv)
{
atexit(lopetusfunktio);
	SDL_Event event;
	alusta();
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    kuva = SDL_LoadBMP("img/Crate.bmp");

    if (MySDL_glTexImage2D(kuva) != 0) {
      fprintf(stderr, "Virhe.\n");
      return 1;
    }
    SDL_FreeSurface(kuva);
	float napit;
	float mousex;
	float mousey;
	bool focus, prevfocus = false;
	int starttime = SDL_GetTicks() - DELAY;
	int endtime = 0;
    SDL_WarpMouse(LEVEYS / 2, KORKEUS / 2);
	while (hoida_viestit() == 0) {
        laske_kulunut_aika();
		piirra();
		endtime = SDL_GetTicks() - starttime;
		if(DELAY - endtime > 0) SDL_Delay(DELAY - endtime);
		else starttime = SDL_GetTicks() - DELAY;
	}
    glDeleteTextures(1, &tex);
	return virhe = 0;
}

ja MySDL_glTexImage2D() on täysin samallainen kuin koodivinkissä.

Spongi [09.05.2012 02:50:33]

#

Laita mainissa olevan glBindTexturen jälkeen nämä (ennen MySDL_glTexImage2D-kutsua):

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

QPRocky [09.05.2012 04:07:47]

#

Miksi et lataisi jotain 3D engineä, esim Ogre tai Irrlicht. Harvempi koodari taitaa tehdä pelejä suoraan rajapintaa hyväksi käyttämällä.

User137 [09.05.2012 09:43:38]

#

edit: Onko MySDL_glTexImage2D() tarkalleen oppaasta vai muokattu?

Ja 1 huomattava kohta siellä on GL_RGBA. Kuvanlataajan tulis kyllä osata ensinnä käyttää GL_RGB-tekstuureja, ja läpinäkyvyyttä tarvittaessa. Se vie kuitenkin 25% enemmän muistia, eikä BMP tue läpinäkyvyyttä.

Toiseks, millasta kuvaa yrität ladata ohjelmalla? Minkä kokoinen Crate.bmp on (leveys ja korkeus)? Turvallisinta käyttää kokoja jotka on 2:n potensseja ja mieluiten pienempiä kun 4096 pikseliä.

johku90 [09.05.2012 09:47:17]

#

User137 kirjoitti:

glBegin, glEnd käyttöä kannattaa välttää silloin kun mahdollista. Laita siis edes kaikki kuution sivut yhden glBegin-glEnd lohkon sisään, ei kuuden eri. Menee hitaammaks muuten.

Aina oppii uutta!

mika132 kirjoitti:

edelleen valkoinen kuutio 3D maailmassani

Oletko varma, että ohjelma saa kuvan ladattua? Onko kuvan nimi esimerkiksi oikein :D

Kokeileppa laittaa tällainen kohta tuonne alustus-funktioon:

glEnable(GL_COLOR);

Saattaapi olla kyllä, että se on aina vakiona enablena.

Metabolix [09.05.2012 16:33:33]

#

Oikea ratkaisu on tuo Sponjin mainitsema eli koon muuttamiseen käytettävien suodatinten asettaminen.

johku90 kirjoitti:

Kokeileppa laittaa tällainen kohta tuonne alustus-funktioon:

glEnable(GL_COLOR);

Kokeile itse selvittää asioita edes vähän, ettei tarvitse täyttä soopaa syöttää muille. GL_COLOR ei kelpaa glEnable-funktiolle. GL_COLOR on glMatrixMode-funktion parametri.

User137 kirjoitti:

Ja 1 huomattava kohta siellä [MySDL_glTexImage2D-funktiossa] on GL_RGBA.

Minusta siinä ei ole mitään erityisen huomattavaa. Funktio muuttaa kuvat automaattisesti tähän muotoon, ja aloittelijalle ei liene optimoinnilla mitään väliä. Funktio myös palauttaa virhekoodin, jos kuvaa ei ole tai koko ei kelpaa. Ongelma ei siis varmasti ole tekstuurin latauksessa, koska siihen liittyvät tarkistukset ovat kohdallaan.

User137 [09.05.2012 17:11:26]

#

Itseasiassa isojen kuvien kohdalla tarkistuksia ei ole. glError():a ei kutsuta missään vaiheessa, saati tutkita 3D-kortin kykyjä :) Ja menee tietty alkeellisissa ohjelmissa turhuuksiin. SDL pystynee lataamaan isojakin kuvia keskusmuistiin, mutta kun siirretään OpenGL:n kautta 3D-kortille niin voi olla eri asia.

Jep, nuo glTexParameteri():t luulis laittavan kuvan näkymään. Se esiintyi mikan aiemmassa koodissa ja "muistelin" sen sisältyvän koodivinkin funktioon.

mika132 [09.05.2012 23:51:08]

#

Terve! Ajattelin kysyä, että miten 3D maailmassa voidaan tutkia mitä kuutiota hiirellä osoitetaan? Hiiri on keskitetty nättöön joten pystyykö pitchiä tai perspectiviä tai jotain käyttämään hyödyksi? Olisiko pientä vihjausta.

(ja muutin taulukko map tiedot vectoreiksi.)

Muutin myös sen glTexImage2D funktion GL_RGBA kohdan GL_RGB.. Nopeutui huomattavasti, mutta kuutioit olivat värjättyjä pieneltä suikaleelta. Ja ehkä jos en paljon väärin nähnyt ne jopa olivat kyseiset kuvat, mutta tosi pienenä. Tällä hetkellähän kuvieni koko on 256x256.. En viitsisi isontaa kylläkään yhtään joten mikä sen aiheuttaa?

Metabolix [10.05.2012 00:08:53]

#

mika132 kirjoitti:

Ajattelin kysyä, että miten 3D maailmassa voidaan tutkia mitä kuutiota hiirellä osoitetaan?

Joudut perehtymään kohtalaisen hyvin 3D-matematiikkaan. Näytön keskellä olevat objektit onneksi löytyvät melko helposti yksinkertaisilla vektorilaskuilla samoista arvoista, joita käytät gluLookAt-funktion kanssa.

mika132 kirjoitti:

Muutin myös sen glTexImage2D funktion GL_RGBA kohdan GL_RGB.

Jos muutat GL_RGBA-kohtaa, pitää tietenkin muuttaa koko latausfunktiota, jotta apu->pixels olisi oikeassa muodossa. User137 kuitenkin neuvoi minusta väärin: tuohon kohtaan ei ole tarpeen koskea. Ensisijaisesti kannattaa ottaa ohjelmastasi GL_BLEND pois käytöstä, jos et tarvitse sitä. Lisäksi voit vaihtaa glTexImage2D:n kolmanneksi parametriksi (internalFormat, nyt 4) arvon GL_RGB tai GL_COMPRESSED_RGB.

User137 [10.05.2012 03:29:20]

#

Jep, GL_RGB ja GL_RGBA mainihin vaan mahdollista parantelua varten myöhemmin. Pikselidata funktiossa oli GL_RGBA muodossa, joten et voi "tuosta vain" vaihtaa GL_RGB:tä. Tuskin noin pienessä ohjelmassa sen takia huomaa mitään tehollista eroa. Piirtonopeuteen sen ei pitäisi vaikuttaa, muistin käyttöön ja latausaikoihin jonkin verran.

mika132 kirjoitti:

(ja muutin taulukko map tiedot vectoreiksi.)

Teit taas omiasi. Kysele vaan jos nuo aiemmat ohjeet ei toimi, kun niissä ei pitäisi olla mitään vikaa.

Itseasiassa hiirellä klikkailuun ei välttämättä tarvitse paljoa matematiikkaa. Aihe on varmasti vaikea mutta jos se kiinnostaa niin:
http://content.gpwiki.org/index.php/OpenGL:Tutorials:Picking

Ja jotain apuja voi löytyä mun pelikirjaston lähdekoodista, joka tosin ei ole C++:aa:
http://code.google.com/p/nxpascal/source/browse/#svn/trunk/src
Varoitus: tuolla on taas paljon asiaa jolla saa helposti pään sekaisin.
(Oma lähestymistapa hiirellä klikkailuun tuolla koodissa on kyllä 3D-matematiikkaa. suora-kolmio törmäystarkasteluja. Sillä on muutamia etuja "pick"-tekniikkaan nähden.)

Metabolix [10.05.2012 03:35:17]

#

User137: glTexImage2D ottaa erikseen parametrit datan syöttömuodosta ja sisäisestä säilytysmuodosta. OpenGL:n pitäisi muuttaa data saman tien sisäiseen säilytysmuotoon, joka voi olla eri kuin syöttömuoto. Ei kai silloin RGBA:n käyttö syöttömuotona ei vaikuta myöhempään nopeuteen tai muistinkäyttöön mitenkään?

Nyt käsillä olevan ohjelman nopeudesta sanon vielä sen verran, että "miten piirretään 400000 kuutiota nopeasti" on täysin väärä kysymys. Oikea kysymys on, "miten piirretään vain näkyvät kuutiot". Siihen ei jälleen ole mitään maagista keinoa tai vinkkiä, vaan pitää opetella laskemaan ja ohjelmoimaan. Algoritmi-ideoita voi hakea Wikipediasta.

User137 [10.05.2012 04:00:39]

#

Tekstuurinlataus-funktio joka käsittelee neljää tavua per pikseli, tekee enemmän kuin funktio joka käsittelee vain kolmea. Kun kuvalle on varattu alpha-kanava 3D-kortin muistissa, niin se tarvitsee sen yhden tavun enemmän per pikseli. 1024x1024 tekstuurilla se tarkoittaa 1Mt enemmän muistia, jossa RGB-kanavat vie yht. sen 3Mt.

GL_RGBA on samalla myös säilytysmuoto. Sen jälkeenhän kun glTexImage2D() on kutsuttu, niin alkuperäisen datan voi tuhota samantien. Se on kopioitu 3D-kortille sellaisenaan.

glTexImage2D(GL_TEXTURE_2D, 0, 4, apu->w, apu->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, apu->pixels);

Tuossa luku 4 meinaa sisäistä formaattia; 4 tavua per pikseli, järjestyksessä GL_RGBA, ja tavallisilla positiivisilla tavuilla.

Pitäs kai nukkuakin... se on kyllä yliarvostettua.

Metabolix [10.05.2012 05:01:12]

#

Ehkä tässä on jokin väärinkäsitys. Annanpa esimerkin.

glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, apu->w, apu->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, apu->pixels);

Tällä kutsulla data syötetään muodossa GL_RGBA mutta OpenGL kopioi sen 3D-kortille muodossa GL_COMPRESSED_RGB (tai lähimmässä tuetussa muodossa). GL_RGBA ei siis missään nimessä ole samalla myös OpenGL:n säilytysmuoto, vaan säilytysmuoto on tässä GL_COMPRESSED_RGB. OpenGL muuntaa datan automaattisesti.

Toki alkuperäisessä koodissa käytetty säilytysmuoto 4 on sama asia kuin GL_RGBA, mutta koska mika132 ei varmasti ennestään tiedä tätä, on hyvin harhaanjohtavaa väittää, että GL_RGBA olisi "samalla" yhtään mitään muuta kuin tiedon muoto SDL-pinnalla ja täten muoto, jossa OpenGL lukee tiedon muistista.

mika132 [10.05.2012 16:52:47]

#

Katselin hieman oppaita ja päätin yrittää vinkkien kautta, mutta pienoinen ongelma iski heti.. camera x,y,z on ihan eri kuin blockien.. Mitä tälle asialle voisi tehdä?

Eli tarkistan joka akselin näin:
if (posx + cos(yaw) * cos(pitch) == blocks->x) {

Tulostin nuo konsoliin ja sinne tulostui:
Camera_keskikohta_x = 16,6267 | Blocks->x = 8
Camera_keskikohta_x = 16,7165 | Blocks->x = 9
Camera_keskikohta_x = 21,118 | Blocks->x = 10

En ihmettele ettei hiiren ykkösnappi tehoa kuutioon, koska tarkistukseni eivät todellakaan menneet läpi, koska akselit ovat ihan eri pisteissä, vaikka kävelen kyseisen blockin päällä.. Mikä ohjeeksi?


Ps..
Päivitin hieman järjestelmää. nyt kuutiot katoaa, mutta Ne katoaa vierimmäisestä ruudusta. Tai taaimmasta. Tämä miten koitan nyt tehdä sitä ei luultavasti ole mikään fiksu tapa?

            if (!painettu) {
                if (Muuttujat::mnapit & SDL_BUTTON(1)) {
                    if (posx + cos(yaw) * cos(pitch) >= blocks->x-0.2 and posx + cos(yaw) * cos(pitch) <= blocks->x+0.5) {
                        if (posy >= blocks->y-4 and posy <= blocks->y+2) {
                            if (posz + sin(yaw) * cos(pitch) * cos(pitch) >= blocks->z-0.2 and posz + sin(yaw) * cos(pitch) * cos(pitch) <= blocks->z+0.5) {
                                if (Muuttujat::mx >= 0 and Muuttujat::my >= 0) {
                                    blocks->is_map=false; //tämä on tallenne, että piirretäänkö kuvaa karttaan.
//this_x, y, z ovat vain konsoli tarkistusta varten. Ei tarvitse välittää.
                                    this_x=blocks->x;
                                    this_y=blocks->y;
                                    this_z=blocks->z;
                                    painettu=true;
                                }
                            }
                        }
                    }
                }
            }

User137 [10.05.2012 20:29:23]

#

Entä jos tekisit harjotusmielessä ensin vaikka Tetriksen tai Arkanoidin 3D:nä? Ei vaadita kuin nuolinäppäimet ja 1-2 lisänappia.

Se kuinka pahasti tuo ylläoleva if-hässäkkä menee päin puuta, minulla ei riitä sanoja sen kuvaamiseen.

mika132 [11.05.2012 18:45:18]

#

Mietein, että mitä arvoja siitä puuttuu? Miten se menee päin puuta? Lasken kameran osoitus suunnan mihin x, y, z akseliin se katsoo ja tsekkaan blockin siitä pisteestä. Käytännössä se toimii, mutta poistaa väärän kuution (eli vieressä olevan) ja muutenkin järkeiltyäni ei tule toimimaan.

Osaan minä napit käsitellä. Mielestäni tämä on hyvä harjoitus projekti kahdestakin syystä. Yksi: Kaikki tulee tässä. Nappi käsittelyt vectorit generaattorit laskut fysiikka yms.. Kaikki on nyt reilassa, mutta tuo, että miten se lasketaan mitä kuutioita katsotaan on hakusessa.

Väsäsin jopa pienen 3D fysiikka efektin kyseiseen peliin. :) Eli hyppy / putoamis efektin jos alla ei ole kuutioita. Tämä vain nyt tökkii.

User137 [11.05.2012 21:50:33]

#

Olisko kuvakaappausta? Tuosta ei ilmene kunnolla mitä yrität tehdä. Se vaikuttaa ongelmalta joka vaatii joko 3D-matematiikkaa tai jo mainitsemaani "pick" tapaa, josta tutoriaali-linkki yllä.

Tuosta purkkavirityksestä, jos esim käännät kameraa 180 astetta, niin lukuväli kääntyy päinvastoin. Tuo koskee XZ-tasolla kääntymistä.

3D-matemaattinen tapa osoittaa jotain kappaletta hiirellä, on esim:
- Käyttää apuna gluUnProject()-funktiota ja laskea suora joka kulkee 3D-avaruudessa hiiren sijainnista ruudulla kohti ääretöntä.
- Laskea saadun säteen ja pintojen leikkauspiste. Tämä on koordinaatti johon hiiri osoittaa. Se voi olla esim XZ-taso origosta, tai kukin kuution sivuista yksi kerrallaan. Mitä sitten halutaankin osoittaa.

Spongi [12.05.2012 16:00:23]

#

Oon kyllä sitä mieltä että sun kannattais opetella tuota ohjelmointia, lähinnä sitä miten rakennat ohjelmias. Mikä ihmeen järki on esimerkiks jossain Muuttujat-nimiavaruudessa?

mika132 [13.05.2012 00:09:18]

#

hmm. Mietein tässä että kameran kulmia (pitch ja yaw) hyödyksi käyttäen eikö pitäisi olla jokin ihan yksinkertainen laskukaava laskea mihin päin katsotaan? Ja katseesta ensimmäinen blocki (tallennettu vectoreihin) kohde valitaan ja odotetaan, että painetaanko jotain?

Katsesuunnanhan osaan nyt tehdä kun olen tuohon kameran perpektiiviin tutustunut, mutta miten sitä voisi tuossa hyötykättää? Hiiri on pakko keskistetty keskelle joten hiiri ei liiku mihinkään muualle kuin keskellä ikkunaa.

Eli miten voitaisi katsoa suunta. Olen joskus kuullut kyseiseen asiaan liittyvän kaavan josta muistelin, että sellainen on olemassa ja esimerkkinä taisi olla mies ja pallo ja siihen liittyvä laskenta, mutta en muista siitä mitään sen enempää.

User137 [14.05.2012 13:19:45]

#

Onko tämä tilanne jossa ollaan? http://i47.tinypic.com/4kw5lg.png
Tuo olis 2D-ongelma, mutta ei ihan simppeli sekään. Eli yrität laskea mihin blockiin kameran keskipiste osuu? Merkkasin tuossa punasella blockit joita laskennan EI pitäisi huomioida, jos kameraa käännettäisiin vain tuolla sinisellä alueella.


Sivun alkuun

Vastaus

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

Tietoa sivustosta