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 !
as tu bien integrer les .lib, le dll et le .h au projet ?
je suis debutant et g pris le code pour l'etudier, le discequer, bref en faire une analyse. mais rien de plus frustrant(et "inutile") que d'arriver sur un code ... que l'on arrive pas a faire tourner. es que quelqu'un pourait m'aider a decoder les erreurs. voila, g vc++ et quand je lance la compilation, il me marque:
--------------------Configuration: test - Win32 Debug--------------------
Linking...
test.obj : error LNK2001: unresolved external symbol _SDL_GetKeyState
test.obj : error LNK2001: unresolved external symbol _SDL_PollEvent
test.obj : error LNK2001: unresolved external symbol _SDL_EnableKeyRepeat
test.obj : error LNK2001: unresolved external symbol _SDL_WM_SetCaption
test.obj : error LNK2001: unresolved external symbol _SDL_SetVideoMode
test.obj : error LNK2001: unresolved external symbol _SDL_Quit
test.obj : error LNK2001: unresolved external symbol _SDL_Init
test.obj : error LNK2001: unresolved external symbol _SDL_MapRGB
test.obj : error LNK2001: unresolved external symbol _SDL_Flip
test.obj : error LNK2001: unresolved external symbol _SDL_FillRect
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/test.exe : fatal error LNK1120: 11 unresolved externals
Error executing link.exe.
test.exe - 12 error(s), 0 warning(s)
Pourquoi ? a quoi cela correspont ? me manque t-il des lib ou de .h ? ...
D'avance merci
Gignops
de toute façon je passe a opengl
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.