Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: SDL & OpenGL ongelma

InvalidCo [28.04.2007 17:44:29]

#

Koodasin tuossa SDL & OpenGL ohjelmaa (kiitos Metabolixille tutoriaalista) ja kun käänsin ja ajoin, ei näytölle ilmestynytkään tarkoituksenmukaisia kymmentä viivaa. Mikäs tässä on siis vikana?

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include <cmath>

//milliseconds per frame tai jotain sen suuntaista
#define WANTED_MSPF 50

//screen-surfeissi
SDL_Surface *screen;

//aikasäädöt
static Uint32 wanha,uusi;

//pelin sisälläololoopin tarkistusbittisäätöjutskafoo
bool ingame;

//vähän niinku viewport, emt
class camera {
	public:
		int x,y,w,h,s;
		void translate();
		camera();
		~camera();
};

void camera::translate() {
	glLoadIdentity();

}

camera::camera() {
}

camera::~camera() {
}
//ukkeli, eli sellane viiva
class dude {
	public:
		int x,y,a;
		void draw(camera Kamera);
		dude();
		dude(int x,int y);
		~dude();
};
//piirtofunktio
void dude::draw(camera Kamera) {
	glBegin(GL_LINES);
		glVertex3i(x,y,0);
		glVertex3i(x+(cos(a)*10),y+(sin(a)*10),0);
	glEnd();
}

dude::dude() {
}

dude::dude(int x,int y) {
}

dude::~dude() {
}

//tyypit
dude dudes[10];
camera viewiportti;

SDL_Event tapahtuma;

Uint8 *napit;

void handleEvents() {
	SDL_PollEvent(&tapahtuma);
	if (tapahtuma.type==SDL_QUIT) exit(0);
}


//aika kesken TODO: cos&sinfunktiosäädöt
void handleKeyPresses() {
	napit=SDL_GetKeyState(NULL);
	if(napit[SDLK_UP]) dudes[0].y--;
	if(napit[SDLK_DOWN]) dudes[0].y++;
	if(napit[SDLK_LEFT]) dudes[0].x--;
	if(napit[SDLK_RIGHT]) dudes[0].x++;
	if(napit[SDLK_ESCAPE]) ingame=false;
}
//funktio jonka pitäis piirtää sälät näytölle
void drawStuff() {
	for(int i=0;i<10;i++)
		dudes[i].draw(viewiportti);
}

//ladataan säädöt
void loadglstuff() {
	glViewport(0,0,800,600);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,800.0f/600.0f,0.1f,100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	viewiportti.x=0;
	viewiportti.y=0;
	viewiportti.w=800;
	viewiportti.h=600;
	viewiportti.s=0;

	for(int i=0;i<10;i++)
		dudes[i] = dude(i,i);
}

int main(int argc,char *argv[]) {
	printf("Starting...\n");
	if(SDL_Init(SDL_INIT_VIDEO)) {
		fprintf(stderr,"SDL didn't work! %s\n",SDL_GetError());
		exit(1);
	}
	atexit(SDL_Quit);

	screen=SDL_SetVideoMode(800,600,0,SDL_FULLSCREEN|SDL_OPENGL);
	printf("Screen has been set.\n");

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE,8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,16);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
	printf("Attributes have been set.\n");

	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f,0.0f,0.0f,0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	loadglstuff();
	printf("GL funcs have been set.\n");
	ingame=true;

	while(ingame) {
		drawStuff();

		SDL_GL_SwapBuffers();
		//Wait a second.
		wanha=uusi;
		handleKeyPresses();
		handleEvents();
		while((uusi-wanha)<WANTED_MSPF) {
			//handleKeyPresses();
			//handleEvents();
			uusi=SDL_GetTicks();
		}
	}

	exit(1);
	return 0;
}

Metabolix [30.04.2007 00:51:22]

#

Pikaisella vilkaisulla näyttäisi, että z-koordinaatti piirtovaiheessa on nolla. Perspektiivi kuitenkin alkaa vasta 0.1:stä (kuten sen itse asetat). Täytyy siis piirtää z-koordinaattien 0.1 ja 100.0 väliin. (Suosittelen noiden vaihtamista hieman lähemmäs ykköstä, vaikkapa 0.2 ja 16.0.)

Jos et kaipaa perspektiiviä (jos teet 2D:tä), kannattaa ottaa selvää glOrtho-funktion toiminnasta.

InvalidCo [01.05.2007 01:51:49]

#

Kiitos todella, todella paljon! Sain ansiostasi tietää, miksi kaikki projektini, joissa olen yrittänyt käyttää OpenGL:ää ovat menneet nurin! :DD Kiitos!

Miksi muuten suosittelet että vaihtaisin nuo luvut lähemmäksi ykköstä? Onko siitä jotakin muutakin hyötyä kuin se, ettei kone piirrä niitä aivan kauimpina olevia objekteja?

Metabolix [01.05.2007 13:09:53]

#

Syvyyspuskurissa arvot skaalataan välille [0, 1] käsittääkseni jokseenkin tällaisella kaavalla:
z = (1/Zn - 1/Z) / (1/Zn - 1/Zf), missä Zn ja Zf ovat siis nuo annettavat arvot ja iso Z on piirrettävän pisteen z-koordinaatti (ja pieni z syvyyspuskuriin laitettava arvo).

Luonnollisesti lukujen tarkkuus on rajallinen. Parhaimmillaankin 8-bittiseen syvyyspuskuriin saa enintään 256 eri arvoa, 16-bittiseen 65536 ja 24-bittiseen 16777216. Jos tuo äsken skaalattu arvo laajennetaan näille lukualueille suoralla kertolaskulla, tulee tällaisia tuloksia:

Zn = 0.1, Zf = 100.0, Syvyyspuskuri 8 bittiä:
  0.1 =>   0
  0.5 => 204
  1.0 => 229
 20.0 => 253
 21.0 => 254
100.0 => 255

Näissä nyt oli vain 8-bittinen syvyyspuskuri, isommilla tietenkin tarkkuus paranee. Kuitenkin tästä selviää ajatus. 8-bittisellä puskurilla ja noilla perspektiiviarvoilla kaikki 20:tä syvemmällä olevat kappaleet menevät jo päällekkäin. 16-bittiselläkin puskurilla näyttäisi tulevan arvoja tuossa kohti niin harvakseltaan, että kappaleet voivat piirtyä vähän niin ja näin. Zn-arvon nostaminen vaikkapa 0.5:een näyttäisi suunnilleen viisinkertaistavan tarkkuuden tuossa 20:n kohdalla. Nykyään toki 24-bittisetkin syvyyspuskurit ovat yleisiä, ja niillä ongelma on taas vain yhden kahdessadasviideskymmeneskuudesosan entisestä, mutta ei ole kauan siitäkään, kun 16-bittinen puskuri piti erikseen napsauttaa asetuksista käyttöön.

No, itse varmasti huomaat, jos säätöön tulee tarvetta. Nytpä ainakin tiedät, mistä on kyse, jos tulee vastaan tapauksia, jossa kaukana olevista kappaleista näkyy vääriä asioita toisten läpi. Voi olla, ettei tuota edes tule vastaan - ennen kuin joku kokeilee vanhemmalla näytönohjaimella, joka tukee vain 8- tai 16-bittistä puskuria. ;)

Sellainen vielä, että OpenGL:n kanssa SDL_SetVideoModen palautusarvo on jokseenkin turha ottaa talteen. :)

Vastaus

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

Tietoa sivustosta