Moteur 3d hardcoder (fenetre sdl)

Soyez le premier à donner votre avis sur cette source.

Vue 8 615 fois - Téléchargée 827 fois

Description

se moteur, qui n'utilise aucunne fonction 3D toute faite, a pour but (ludique) la comprention du fonctionnement de la 3D : rotation d'objet (trigo), effet de persepective (pythagore), l'eclairage (vecteurs et normal), les loadeur de map (fichier ascii .ase vers memoire) ...

le source est portable =)

il n'est pas tres documenter car se serai trop long et sa restera comme sa

Source / Exemple :


/*****************************************************************************/
/*																			 */
/* fichier	: moteur.c									version : V2.1		 */
/* projet	: moteur									date :	24/05/2005	 */
/* par		: aerith														 */
/*																			 */
/* mini moteur 3D															 */
/*																			 */
/*****************************************************************************/

#include	"moteur.h"

SDL_Surface *pScreen;

char 	*gettok(const char *pData, int iPos, char *pCar)
{
	static char	Data[NBCARLINE];
	char *	Token;
	int		i;
	strcpy(Data, pData);
	for(Token = strtok(Data, pCar), i = 0; Token && (i < iPos); ++i, Token = strtok(0, pCar));

	return Token;
}

void	Load(char *pFichier, mesh *pMesh)
{
	FILE 	*Fichier;
	char	Data[NBCARLINE];

	Fichier = fopen(pFichier, "r");
	if(!Fichier)
	{
		perror("erreur map non trouver\n");
		exit(1);
	}

	while(!feof(Fichier))
	{
		if(fgets(Data, NBCARLINE, Fichier))
		{
			if(strcmp(gettok(Data, 0, ":* \t\n\""), "MESH_NUMVERTEX") == 0)
			{
				pMesh->NumVertex 	= atoi(gettok(Data, 1, ":* \t\n\""));
				pMesh->Vertex		= malloc(sizeof(vertex) * (pMesh->NumVertex + 1));
			}
			if(strcmp(gettok(Data, 0, ":* \t\n\""), "MESH_NUMFACES") == 0)
			{
				pMesh->NumFace 	= atoi(gettok(Data, 1, ":* \t\n\""));
				pMesh->Faces	= malloc(sizeof(face) * (pMesh->NumFace + 1));
			}
			if (strcmp(gettok(Data, 0, ":* \t\n"), "MESH_VERTEX") == 0)
			{
				pMesh->Vertex[atoi(gettok(Data, 1, ":* \t\n"))].v3D.x = (float)atof(gettok(Data, 2, ":* \t\n"));
				pMesh->Vertex[atoi(gettok(Data, 1, ":* \t\n"))].v3D.y = (float)atof(gettok(Data, 3, ":* \t\n"));
				pMesh->Vertex[atoi(gettok(Data, 1, ":* \t\n"))].v3D.z = (float)atof(gettok(Data, 4, ":* \t\n"));
			}
			if (strcmp(gettok(Data, 0, ":* \t\n"), "MESH_FACE") == 0)
			{
				pMesh->Faces[atoi(gettok(Data, 1, ":* \t\n"))].a = atoi(gettok(Data, 3, ":* \t\n"));
				pMesh->Faces[atoi(gettok(Data, 1, ":* \t\n"))].b = atoi(gettok(Data, 5, ":* \t\n"));
				pMesh->Faces[atoi(gettok(Data, 1, ":* \t\n"))].c = atoi(gettok(Data, 7, ":* \t\n"));
			}
			if (strcmp(gettok(Data, 0, ":* \t\n"), "MESH_FACENORMAL") == 0)
			{
				pMesh->Faces[atoi(gettok(Data, 1, ":* \t\n"))].normal.x = (float)atof(gettok(Data, 2, ":* \t\n"));
				pMesh->Faces[atoi(gettok(Data, 1, ":* \t\n"))].normal.y = (float)atof(gettok(Data, 3, ":* \t\n"));
				pMesh->Faces[atoi(gettok(Data, 1, ":* \t\n"))].normal.z = (float)atof(gettok(Data, 4, ":* \t\n"));
			}
		}
	}
	fclose(Fichier);
}

void	Init(char *pFichier, option *pOption)
{
	FILE 	*Fichier;
	char	Data[NBCARLINE];

	pOption->Zoom		= 10;
	pOption->Cliping	= 50;
	pOption->Camera.x	= 0;
	pOption->Camera.y	= 0;
	pOption->Camera.z	= 100;
	pOption->Rotate.a	= 0;
	pOption->Rotate.x	= 0;
	pOption->Rotate.y	= 0;
	pOption->Rotate.z	= 0;
	pOption->Light		= 1;
	pOption->Lcolor.i	= 100;
	pOption->Lcolor.r	= 255;
	pOption->Lcolor.g	= 255;
	pOption->Lcolor.b	= 255;
	pOption->Render		= 1;
	pOption->Allface	= 0;
	pOption->WindowX	= 320;
	pOption->WindowY	= 240;
	pOption->Color		= 16;
	strcpy(pOption->Title, "m3d");
	pOption->Triface	= 1;

	Fichier = fopen(pFichier, "r");
	if(!Fichier)
	{
		perror("erreur fichier init inexistant\n");
		exit(2);
	}

	while(!feof(Fichier))
	{
		if(fgets(Data, NBCARLINE, Fichier) != NULL)
		{
			if(!(Data[0] == '\\' && Data[1] == '\\') && Data[0] != '\n')
			{
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "zoom") == 0)
					pOption->Zoom		= (float)atof(gettok(Data, 1, "=: \t\n\""));
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "cliping") == 0)
					pOption->Cliping	= (float)atof(gettok(Data, 1, "=: \t\n\""));
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "camera") == 0)
				{
					pOption->Camera.x	= (float)atof(gettok(Data, 1, "=: \t\n\""));
					pOption->Camera.y	= (float)atof(gettok(Data, 2, "=: \t\n\""));
					pOption->Camera.z	= (float)atof(gettok(Data, 3, "=: \t\n\""));
				}
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "rotate") == 0)
				{
					pOption->Rotate.a	= (float)atof(gettok(Data, 1, "=: \t\n\""));
					pOption->Rotate.x	= (float)atof(gettok(Data, 2, "=: \t\n\""));
					pOption->Rotate.y	= (float)atof(gettok(Data, 3, "=: \t\n\""));
					pOption->Rotate.z	= (float)atof(gettok(Data, 4, "=: \t\n\""));
				}
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "light") == 0)
					pOption->Light	= atoi(gettok(Data, 1, "=: \t\n\""));
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "lcolor") == 0)
				{
					pOption->Lcolor.i	= atoi(gettok(Data, 1, "=: \t\n\""));
					pOption->Lcolor.r	= atoi(gettok(Data, 2, "=: \t\n\""));
					pOption->Lcolor.g	= atoi(gettok(Data, 3, "=: \t\n\""));
					pOption->Lcolor.b	= atoi(gettok(Data, 4, "=: \t\n\""));
				}
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "render") == 0)
					pOption->Render	= atoi(gettok(Data, 1, "=: \t\n\""));
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "allface") == 0)
					pOption->Allface	= atoi(gettok(Data, 1, "=: \t\n\""));
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "window") == 0)
				{
					pOption->WindowX	= atoi(gettok(Data, 1, "=: \t\n\""));
					pOption->WindowY	= atoi(gettok(Data, 2, "=: \t\n\""));
					pOption->Color		= atoi(gettok(Data, 3, "=: \t\n\""));
				}
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "title") == 0)
					strcpy(pOption->Title, gettok(Data, 1, "=: \t\n\""));
				if(strcmp(gettok(Data, 0, "=: \t\n\""), "triface") == 0)
					pOption->Triface	= atoi(gettok(Data, 1, "=: \t\n\""));
			}
		}
	}
	fclose(Fichier);
	
	if(SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		perror("erreur init SDL\n");
		exit(3);
	}

	atexit(SDL_Quit);

	pScreen = SDL_SetVideoMode(pOption->WindowX, pOption->WindowY,
		pOption->Color, SDL_SWSURFACE | SDL_DOUBLEBUF);
	if(!pScreen)
	{
		perror("erreur creation screen\n");
		exit(4);
	}
	SDL_WM_SetCaption(pOption->Title, NULL);

	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);	
}

void	Point(vecteur p1, int r, int g, int b)
{
	Uint16 *Pointer;

	if((p1.x > 0) && (p1.x < (float)pScreen->w) && (p1.y > 0) && (p1.y < (float)pScreen->h))
	{
		Pointer = (Uint16*)pScreen->pixels + ((pScreen->pitch / 2 * (int)p1.y) + (int)p1.x);

  • Pointer = SDL_MapRGB(pScreen->format, (Uint8)r, (Uint8)g, (Uint8)b);
} } void Line(vecteur p1, vecteur p2, int r, int g, int b) { vecteur p; float d; if(abs((int)(p1.x - p2.x)) > abs((int)(p1.y - p2.y))) { if(p1.x > p2.x) { p = p1; p1 = p2; p2 = p; } d = (p1.y - p2.y) / (p1.x - p2.x); for(; p1.x <= p2.x; p1.x++, p1.y += d) Point(p1, r, g, b); } else { if(p1.y > p2.y) { p = p1; p1 = p2; p2 = p; } d = (p1.x - p2.x) / (p1.y - p2.y); for(; p1.y <= p2.y; p1.x += d, p1.y++) Point(p1, r, g, b); } } void Triangle(vecteur p1, vecteur p2, vecteur p3, int r, int g, int b) { vecteur p; float d; if(abs((int)(p2.x - p3.x)) > abs((int)(p2.y - p3.y))) { if(p2.x > p3.x) { p = p2; p2 = p3; p3 = p; } d = (p2.y - p3.y) / (p2.x - p3.x); for(; p2.x <= p3.x; p2.x++, p2.y += d) Line(p1, p2, r, g, b); } else { if(p2.y > p3.y) { p = p2; p2 = p3; p3 = p; } d = (p2.x - p3.x) / (p2.y - p3.y); for(;p2.y <= p3.y; p2.x += d, p2.y++) Line(p1, p2, r, g, b); } } void Render(mesh *pMesh, option *pOption) { float cosT = (float)cos(pOption->Rotate.a); float sinT = (float)sin(pOption->Rotate.a); float cosT1 = 1 - cosT; float cosT2 = 1 + cosT; float xs = pOption->Rotate.x * sinT; float ys = pOption->Rotate.y * sinT; float zs = pOption->Rotate.z * sinT; float ex1 = cosT + cosT1 * (pOption->Rotate.x * pOption->Rotate.x); float ex2 = cosT1 * pOption->Rotate.x * pOption->Rotate.y - zs; float ex3 = cosT1 * pOption->Rotate.x * pOption->Rotate.z + ys; float ey1 = cosT2 * pOption->Rotate.x * pOption->Rotate.y + zs; float ey2 = cosT + cosT1 * (pOption->Rotate.y * pOption->Rotate.y); float ey3 = cosT1 * pOption->Rotate.y * pOption->Rotate.z - xs; float ez1 = cosT2 * pOption->Rotate.x * pOption->Rotate.z - ys; float ez2 = cosT1 * pOption->Rotate.y * pOption->Rotate.z + xs; float ez3 = cosT + cosT1 * (pOption->Rotate.z * pOption->Rotate.z); int i, j, n; float m, o; vecteur vt; face ft; clock_t start; static int Fpsc = 0; static int Fpsa = 0; int Fps = 0; Uint32 Color; light couleur; char Titre[256]; start = clock(); couleur.r = 255; couleur.g = 255; couleur.b = 255; for(i = 0; i < pMesh->NumVertex; i++) { pMesh->Vertex[i].v3D.x = ex1 * pMesh->Vertex[i].v3D.x + ex2 * pMesh->Vertex[i].v3D.y + ex3 * pMesh->Vertex[i].v3D.z; pMesh->Vertex[i].v3D.y = ey1 * pMesh->Vertex[i].v3D.x + ey2 * pMesh->Vertex[i].v3D.y + ey3 * pMesh->Vertex[i].v3D.z; pMesh->Vertex[i].v3D.z = ez1 * pMesh->Vertex[i].v3D.x + ez2 * pMesh->Vertex[i].v3D.y + ez3 * pMesh->Vertex[i].v3D.z; pMesh->Vertex[i].v2D.x = (pMesh->Vertex[i].v3D.x + pOption->Camera.x) * pOption->Zoom / ((pMesh->Vertex[i].v3D.z + pOption->Camera.z) / pOption->Cliping) + (pOption->WindowX / 2); pMesh->Vertex[i].v2D.y = (pMesh->Vertex[i].v3D.y + pOption->Camera.y) * pOption->Zoom / ((pMesh->Vertex[i].v3D.z + pOption->Camera.z) / pOption->Cliping) + (pOption->WindowY / 2); } for(i = 0; i < pMesh->NumFace; i++) { pMesh->Faces[i].normal.x = ex1 * pMesh->Faces[i].normal.x + ex2 * pMesh->Faces[i].normal.y + ex3 * pMesh->Faces[i].normal.z; pMesh->Faces[i].normal.y = ey1 * pMesh->Faces[i].normal.x + ey2 * pMesh->Faces[i].normal.y + ey3 * pMesh->Faces[i].normal.z; pMesh->Faces[i].normal.z = ez1 * pMesh->Faces[i].normal.x + ez2 * pMesh->Faces[i].normal.y + ez3 * pMesh->Faces[i].normal.z; pMesh->Faces[i].centre.x = (pMesh->Vertex[pMesh->Faces[i].a].v3D.x + pMesh->Vertex[pMesh->Faces[i].b].v3D.x + pMesh->Vertex[pMesh->Faces[i].c].v3D.x) / 3; pMesh->Faces[i].centre.y = (pMesh->Vertex[pMesh->Faces[i].a].v3D.y + pMesh->Vertex[pMesh->Faces[i].b].v3D.y + pMesh->Vertex[pMesh->Faces[i].c].v3D.y) / 3; pMesh->Faces[i].centre.z = (pMesh->Vertex[pMesh->Faces[i].a].v3D.z + pMesh->Vertex[pMesh->Faces[i].b].v3D.z + pMesh->Vertex[pMesh->Faces[i].c].v3D.z) / 3; vt.x = abs((int)(pOption->Camera.x - pMesh->Faces[i].centre.x)); vt.y = abs((int)(pOption->Camera.y - pMesh->Faces[i].centre.y)); vt.z = abs((int)(pOption->Camera.z - pMesh->Faces[i].centre.z)); pMesh->Faces[i].dist = (int)sqrt((vt.x * vt.x) + (vt.y * vt.y) + (vt.z * vt.z)); } if(pOption->Triface) { for(i = 0; i < (pMesh->NumFace - 1); i++) { for(j = i + 1; j < pMesh->NumFace; j++) { if(pMesh->Faces[i].dist > pMesh->Faces[j].dist) { memcpy((void *)&ft, (void *)&pMesh->Faces[i], sizeof(face)); memcpy((void *)&pMesh->Faces[i], (void *)&pMesh->Faces[j], sizeof(face)); memcpy((void *)&pMesh->Faces[j], (void *)&ft, sizeof(face)); } } } } Color = SDL_MapRGB(pScreen->format, 0, 0, 0); SDL_FillRect(pScreen, NULL, Color); if(SDL_MUSTLOCK(pScreen)) if(SDL_LockSurface(pScreen) < 0) return; vt.x = (int)(pOption->Camera.x * pOption->Camera.x); vt.y = (int)(pOption->Camera.y * pOption->Camera.y); vt.z = (int)(pOption->Camera.z * pOption->Camera.z); n = sqrt(vt.x + vt.y + vt.z); for(i = 0; i < pMesh->NumFace; i++) { vt.x = (pOption->Camera.x / n) + pMesh->Faces[i].normal.x; vt.y = (pOption->Camera.y / n) + pMesh->Faces[i].normal.y; vt.z = (pOption->Camera.z / n) + pMesh->Faces[i].normal.z; m = sqrt((vt.x * vt.x) + (vt.y * vt.y) + (vt.z * vt.z)); if(pOption->Light) { o = ((float)pOption->Lcolor.i / (float)pMesh->Faces[i].dist) / m; couleur.r = (int)(pOption->Lcolor.r * o); couleur.g = (int)(pOption->Lcolor.g * o); couleur.b = (int)(pOption->Lcolor.b * o); if(couleur.r > 255) couleur.r = 255; else if(couleur.r < 0) couleur.r = 0; if(couleur.g > 255) couleur.g = 255; else if(couleur.g < 0) couleur.g = 0; if(couleur.b > 255) couleur.b = 255; else if(couleur.b < 0) couleur.b = 0; } if((pMesh->Faces[i].normal.z <= 0) || pOption->Allface) { if(!pOption->Render) { Triangle(pMesh->Vertex[pMesh->Faces[i].a].v2D, pMesh->Vertex[pMesh->Faces[i].b].v2D, pMesh->Vertex[pMesh->Faces[i].c].v2D, couleur.r, couleur.g, couleur.b); } else { if(pOption->Render == 2) { Point(pMesh->Vertex[pMesh->Faces[i].a].v2D, couleur.r, couleur.g, couleur.b); } else { Line(pMesh->Vertex[pMesh->Faces[i].a].v2D, pMesh->Vertex[pMesh->Faces[i].b].v2D, couleur.r, couleur.g, couleur.b); Line(pMesh->Vertex[pMesh->Faces[i].b].v2D, pMesh->Vertex[pMesh->Faces[i].c].v2D, couleur.r, couleur.g, couleur.b); Line(pMesh->Vertex[pMesh->Faces[i].c].v2D, pMesh->Vertex[pMesh->Faces[i].a].v2D, couleur.r, couleur.g, couleur.b); } } } } if(SDL_MUSTLOCK(pScreen)) SDL_UnlockSurface(pScreen); SDL_Flip(pScreen); Fps = CLOCKS_PER_SEC / (clock() - start + 1); Fpsc++; Fpsa += Fps; if(Fpsc > Fps) { Fpsc = 1; Fpsa = Fps; sprintf(Titre, "%s - fps : %i", pOption->Title, Fpsa / Fpsc); SDL_WM_SetCaption(Titre, NULL); } }

Conclusion :


y a un .c de test en plus

lisez le readme :p

oui je sais y a mieu que SDL, mais je ne veux pas de truc tout fait !

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Cyberboy2054
Messages postés
173
Date d'inscription
jeudi 20 décembre 2001
Statut
Membre
Dernière intervention
22 août 2008
-
Trop fort.
Ya plein de trucs a apprendre la dedans, meme si ca rame (16fps).
Encore bravo.
cs_aerith
Messages postés
54
Date d'inscription
lundi 17 mars 2003
Statut
Membre
Dernière intervention
12 mars 2006
-
lol vi sa rame un peut
Hylvenir
Messages postés
364
Date d'inscription
mercredi 11 février 2004
Statut
Membre
Dernière intervention
5 octobre 2006
2 -
D'abord bravo, c'est pas mal. J'ai réussi à la compiler sous Linux.
Il y a quand même quelques détails embêtant quand même.
Les rotations ne s'arrêtent pas, l'objet ne n'affiche plus,...
Donc je reste mitigé ( pourquoi pas de Makefile ?, pourquoi founir
la SDL ?, pourquoi tu colles tes fichiers init dans ce foutu réprépertoire Debug, ...)

Sinon, je suis bloqué à 99fps... quelque soit le modèle (et ça me ferait mal)
Je regrette de ne pas connaitre mieux la 3D et ce format pour te proposer des solutions.
cs_Kirua
Messages postés
3006
Date d'inscription
dimanche 14 avril 2002
Statut
Membre
Dernière intervention
31 décembre 2008
-
Hylvenir, ton écran est probablement cadencé à 100Hz et le V-Sync est activé. De ce fait, l'affichage est limité à 100FPS (à peu près) tt simplement parce qu'il est inutile de calculer 300 frames pour n'en afficher physiquement que 100.

Juste une petite note: un but "lucratif" ça veut dire que ce que tu recherches est l'argent ;-) Je suppose que tu voulais dire éducatif ou formatif?

bonne journée!

kirua
cs_aerith
Messages postés
54
Date d'inscription
lundi 17 mars 2003
Statut
Membre
Dernière intervention
12 mars 2006
-
En effet j'ai du me tromper de mot :p, je voulai dire ludique =)

Pour se qui est du makefile, je ne suis pas sous nux et je ne sais pas les faire, tous se qui est dans Debug sont les fichiers necessaire au fonctionnement sous windows (ormis les .lib).
Pour se qui est de la rotation continu, c'est l'autolook, appuyer sur "shift gauche" pour l'activer ou non, lire le readme !

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.