www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 9036e2dea0b40eac2c4d07152ca076a692dd547f
parent 61ea30e35dbd1a7f63c9a92c142f99ef14df0c07
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date:   Sat,  3 Dec 2011 15:19:44 +0100

Nettoyage des anciens fichiers .c qui ne sont plus utilisés.

Diffstat:
Ddisplay.c | 271-------------------------------------------------------------------------------
Ddisplay.h | 30------------------------------
Droads.c | 562-------------------------------------------------------------------------------
Droads.h | 96-------------------------------------------------------------------------------
Droads.md | 225-------------------------------------------------------------------------------
Droam.c | 318-------------------------------------------------------------------------------
Droam.h | 32--------------------------------
Dsimple-terrain.c | 122-------------------------------------------------------------------------------
Dsquare.c | 305-------------------------------------------------------------------------------
Dsquare.h | 20--------------------
Dterrain.md | 49-------------------------------------------------
11 files changed, 0 insertions(+), 2030 deletions(-)

diff --git a/display.c b/display.c @@ -1,271 +0,0 @@ -#include "display.h" - -int initWindow() { - SDL_Init(SDL_INIT_VIDEO); - SDL_WM_SetCaption("Sortie terrain OpenGL",NULL); - SDL_SetVideoMode(windowWidth, windowHeight, 32, SDL_OPENGL); - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - gluPerspective(70,(double)windowWidth/windowHeight,1,10000); - glEnable(GL_DEPTH_TEST); - glewInit(); - - float MatSpec[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - float MatDif[4] = {0.0f, 0.5f, 0.0f, 1.0f}; - float MatAmb[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - - float Light1Pos[4] = {0.0f, 1.0f, 0.0f, 0.0f}; - float Light1Dif[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - float Light1Spec[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - float Light1Amb[4] = {0.4f, 0.4f, 0.4f, 1.0f}; - float shininess = 128.0f; - - glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec); - glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,MatDif); - glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,MatAmb); - glMaterialfv(GL_FRONT,GL_SHININESS,&shininess); - - glLightfv(GL_LIGHT0, GL_DIFFUSE, Light1Dif); - glLightfv(GL_LIGHT0, GL_SPECULAR, Light1Spec); - glLightfv(GL_LIGHT0, GL_AMBIENT, Light1Amb); - glLightfv(GL_LIGHT0, GL_POSITION, Light1Pos); - - glEnable(GL_LIGHTING); // Active l'éclairage - glEnable(GL_LIGHT0); // Active la lumière 0; - - return 0; -} - - -int mainLoop() { - short continuer = 1; - SDL_Event event; - - while (continuer) { - SDL_WaitEvent(&event); - switch(event.type) { - case SDL_QUIT: - continuer = 0; - break; - case SDL_KEYDOWN: - switch(event.key.keysym.sym) { - case SDLK_DOWN: - ySight -= moveDist; - break; - case SDLK_UP: - ySight += moveDist; - break; - case SDLK_LEFT: - xSight -= moveDist; - break; - case SDLK_RIGHT: - xSight += moveDist; - break; - - default: - break; - } - break; - - case SDL_MOUSEMOTION: - xAngle = ((event.motion.x-windowWidth/2)*340/(windowWidth)); - yAngle = (event.motion.y-windowHeight/2)*340/(windowHeight); - break; - - default: - break; - } - - renderScene(); - } - - SDL_Quit(); - - return 0; -} - - -void drawAxes() { - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glBegin(GL_LINES); - glColor3ub(255,0,0); - glVertex3f(0.0f, 0.0f, 0.0f); // origin of the line - glVertex3f(2500.0f, 0.0f, 0.0f); // ending point of the line - glEnd( ); - - glBegin(GL_LINES); - glColor3ub(0,255,0); - glVertex3f(0.0f, 0.0f, 0.0f); // origin of the line - glVertex3f(0.0f, 2500.0f, 0.0f); // ending point of the line - glEnd( ); - - glBegin(GL_LINES); - glColor3ub(0,0,255); - glVertex3f(0.0f, 0.0f, 0.0f); // origin of the line - glVertex3f(0.0f, 0.0f, -2500.0f); // ending point of the line - glEnd( ); - glEnable(GL_LIGHTING); -} - - -void renderScene() { - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - //gluLookAt(1024,512,1356,1024,512,0,0,1,0); - - //glClearColor(1,1,1,1); // pour un fond blanc - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ; - - //gluLookAt(0,0,cameraDist, 0, 0, 0,0,1,0); - glTranslated(-xSight,-ySight,-(zSight+cameraDist)); - glRotatef(-yAngle,1,0,0); - glRotatef(-xAngle,0,0,1); - - - drawAxes(); - displayQTTree(qtn); - - glFlush(); - SDL_GL_SwapBuffers(); -} - -void displayQTTree(QTNode *qn) { - QT_enumerate(qn); - //qn = qn; -} - -/* -int nbTriangles(Triangle *t) { - int sum = 0; - - if(t->tLeftChild == NULL) { - return 1; - } - else { - sum += nbTriangles(t->tLeftChild); - sum += nbTriangles(t->tRightChild); - } - - return sum; -}*/ - -/* -void insertValues(Triangle *t,int *vertices) { - if(t->tLeftChild == NULL) { - vertices[9*nbVertex] = t->vLeft->x; - vertices[9*nbVertex+1] = t->vLeft->y; - vertices[9*nbVertex+2] = t->vLeft->z; - vertices[9*nbVertex+3] = t->vApex->x; - vertices[9*nbVertex+4] = t->vApex->y; - vertices[9*nbVertex+5] = t->vApex->z; - vertices[9*nbVertex+6] = t->vRight->x; - vertices[9*nbVertex+7] = t->vRight->y; - vertices[9*nbVertex+8] = t->vRight->z; - nbVertex++; - } - else { - insertValues(t->tLeftChild,vertices); - insertValues(t->tRightChild,vertices); - } -}*/ - -/* -void displayTree2() { - glVertexAttribPointer(0, 3, GL_INT, GL_FALSE, 0, vertices); - glEnableVertexAttribArray(0); - glColor3ub(255,255,255); - glDrawArrays(GL_LINE_LOOP,0, nbVertex*3); -}*/ - -int max3(int x,int y,int z) { - if(x < y && x < z) return x; - if(y < x && y < z) return y; - if(z < x && z < y) return z; - return 0; -} -/* -void setNormals(Triangle *t) { - if(t->tLeftChild == NULL) { - int ax = t->vLeft->x - t->vApex->x; - int ay = t->vLeft->y - t->vApex->y; - int az = t->vLeft->z - t->vApex->z; - int bx = t->vApex->x - t->vRight->x; - int by = t->vApex->y - t->vRight->y; - int bz = t->vApex->z - t->vRight->z; - - float x = (float)((ay * bz) - (az * by)); - float y = (float)((az * bx) - (ax * bz)); - float z = -(float)((ax * by) - (ay * bx)); - float length = sqrt(x*x + y*y + z*z); - - length = length; - x = x/length; - y = y/length; - z = z/length; - - t->vLeft->xNormal = x; - t->vLeft->yNormal = y; - t->vLeft->zNormal = z; - t->vRight->xNormal = x; - t->vRight->yNormal = y; - t->vRight->zNormal = z; - t->vApex->xNormal = x; - t->vApex->yNormal = y; - t->vApex->zNormal = z; - } - else { - setNormals(t->tLeftChild); - setNormals(t->tRightChild); - } -} - -void displayTree(Triangle *t) { - if(t->tLeftChild == NULL) { - glNormal3f(t->vLeft->xNormal,t->vLeft->yNormal,t->vLeft->zNormal); - //glNormal3f(0.075722,0.077664,0.99812); - glBegin(GL_TRIANGLES); - glVertex3d(t->vLeft->x,t->vLeft->y,t->vLeft->z); - glVertex3d(t->vApex->x,t->vApex->y,t->vApex->z); - glVertex3d(t->vRight->x,t->vRight->y,t->vRight->z); - glEnd(); - } - else { - displayTree(t->tLeftChild); - displayTree(t->tRightChild); - } -}*/ - - -int main() { - initWindow(); - qtn = QT_example(); - //nbVertex = nbTriangles(t); - //printf("nombre de triangles : %d\n",nbVertex); - - // Calcul des normales des traingles. - //setNormals(t); - - // Réorganisation des sommets pour l'affichage optimisé. - //vertices = (int*) malloc(sizeof(int) * nbTriangles(t)*9+1); - //insertValues(t,vertices); - - mainLoop(); - - // Pour afficher le terrain : - /* int x; */ - /* int y; */ - /* #define SIZE 1024 */ - /* printf("P5 %d %d 255\n", SIZE, SIZE); */ - /* for (y = 0; y < SIZE; y++) { */ - /* for (x = 0; x < SIZE; x++) { */ - /* //int bit = y / (SIZE/32); */ - /* //int h = hash2(x, 300+y); */ - /* //if (y % (SIZE/32) == 0) h = 0; */ - /* //printf("%c", ((h >> (31-bit)) & 1) * 255); */ - /* //printf("%c", interpolation(256+x, 256+y, 256, 256, 512, 512, 0, 255, 255, 255)); */ - /* printf("%c", get_z(x,y)); */ - /* } */ - /* } */ - return 0; -} diff --git a/display.h b/display.h @@ -1,30 +0,0 @@ -#include <SDL/SDL.h> -#include <GL/glew.h> -#include <GL/glu.h> -#include "square.h" -#include <math.h> - -int initWindow(); -int mainLoop(); -void renderScene(); -void displayQTTree(QTNode *qn); -//void setNormals(Triangle *t); -//void displayTree(Triangle *t); -//void displayTree2(); -void Draw_Axes (); - -QTNode *qtn; -int *vertices; -int windowWidth = 1024; -int windowHeight = 768; -int nbVertex = 0; - -int cameraDist = 3000; - -int xSight = 0; -int ySight = 0; -int zSight = 0; - -float xAngle = 0; -float yAngle = 0; -int moveDist = 128; diff --git a/roads.c b/roads.c @@ -1,562 +0,0 @@ -#include "roads.h" - -void svg_start(int w, int h) { - printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); - printf("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"%d\" height=\"%d\">", w, h); -} - -void svg_end() { - printf("</svg>"); -} - -void svg_line(Vertex* a, Vertex* b, short color) { - if(color == 0) - printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"grey\" />", a->x, a->y, b->x, b->y); - else if(color == 1) - printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"#A0A000\" />", a->x, a->y, b->x, b->y); - else if(color == 2) - printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"blue\" />", a->x, a->y, b->x, b->y); - else - printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"black\" />", a->x, a->y, b->x, b->y); -} - -void svg_circle(int x, int y, int r) { - printf("<circle cx=\"%d\" cy=\"%d\" r=\"%d\" stroke=\"black\" stroke-width=\"2\" fill=\"red\"/>",x,y,r); -} - -void roads(Polygon* quartier) { - quartier = quartier; - Vertex center = { .x=400, .y=300 }; - svg_line(&center, &(quartier[0]),6); -} - - - - -/* Fonctions de Yoann suffixée par "Y" */ - -/* Initialisation de la liste de routes. - */ -void initRoadslIst(int nb){ - roadsList = (roadPointY**) malloc(sizeof(roadPointY*)*nb); -} - - -/* La route est constituée d'une série de points, chaque point contient un nœd de route qui peut-être propre à cette route comme - * appartenir à plusieurs routes. Le nœd contient un Vertex qui permet de le positionner sur la carte. Il contient également - * le nombre et les portions de routes auxquelles il appartient. - */ - -// Transforme des coordonnées du plan en coordonées du tableau sur x. -int toX(Vertex *v) { - int x = v->x*(nbXSubDivision)/quarterWidth; - if(x >= nbXSubDivision) return 0; - return x; -} - - -// Transforme des coordonnées du plan en coordonées du tableau sur y. -int toY(Vertex *v) { - int y = v->y*(nbYSubDivision)/quarterHeight; - if(y >= nbYSubDivision) return 0; - return y; -} - - -/* Convertion de coordonnées polaires en coordonnées cartésiennes. - * @param Vertex* origin : Origine du vecteur. - * @param short angle : Angle. - * @param short length : Taille du vecteur. - * @return struct cartesianCoord* : Les coordonnées cartésiennes du point d'arrivée. - */ -cartesianCoord* ptc(Vertex *origin, short angle, short length) { - cartesianCoord *cc = (cartesianCoord*) malloc(sizeof(cartesianCoord)); - cc->x = origin->x + cos(M_PI*angle/180)*length; - cc->y = origin->y + sin(M_PI*angle/180)*length; - - return cc; -} - - -/* Convertion de coordonnées cartésiennes en coordonnées polaires. - * @param Vertex* origin : Origine du vecteur. - * @param Vertex* end : Fin du vecteur. - * @return struct polarCoord* : Les coordonnées polaires du point d'arrivée. - */ -polarCoord* ctp(Vertex *origin, Vertex *end) { - polarCoord *pc = (polarCoord*) malloc(sizeof(polarCoord)); - pc->length = distBetween(origin,end); - pc->angle = acos((float)(end->x-origin->x)/(float)pc->length)*180/M_PI; - if(end->y < origin->y) - pc->angle = 360-pc->angle; - return pc; -} - - -/* Initialise la grille de nœuds. - * @param int width : Largeur du quartier à remplir. - * @param int height : Hauteur du quartier à remplir. - * @param int maxSegmentSize : Taille maximale d'un segment de route. - */ -void grid_initvGrid(int width, int height, int segmentSize) { - int xSize, ySize; - xSize = (int)(width/segmentSize); - ySize = (int)(height/segmentSize); - - vGrid = (Vertex****) malloc(sizeof(Vertex***)*xSize); - int i,j,k; - - maxSegmentSize = segmentSize; - nbXSubDivision = xSize; - nbYSubDivision = ySize; - quarterWidth = width; - quarterHeight = height; - - for(i=0;i<xSize;i++) { - vGrid[i] = (Vertex***) malloc(sizeof(Vertex**)*ySize); - for(j=0;j<ySize;j++) { - vGrid[i][j] = (Vertex**) malloc(sizeof(Vertex*)*maxNodesInGrid); - for(k=0;k<maxNodesInGrid;k++) - vGrid[i][j][k] = NULL; - } - } -} - - -/* Détermine si il existe une intersection entre deux segments de droite. Dans le cas - * ou une intersection existe les coordonnées du point d'intersection sont retournées. - * Dans le cas contraire la fonction retourne NULL. - * @param Vertex *va : Point de départ du premier segment. - * @param Vertex *vb : Point d'arrivé du premier segment. - * @param Vertex *ua : Point de départ du second segment. - * @param Vertex *vb : Point d'arrivé du second segment. - * @return Vertex* : Coordonnées du point d'intersection si il existe, sinon NULL. - */ -Vertex* intersectionBetween(Segment *sega, Segment *segb) { - if(sega == NULL || segb == NULL) - return NULL; - - sega = sega; - segb = segb; - Vertex *inter = (Vertex*) malloc(sizeof(Vertex)); - float m, k; // Coordonnées de l'intersection des vecteurs sur les droites. - int Ix, Iy, Jx, Jy; // Vecteur I et J corespondant au segment v et u; - Vertex *va, *vb, *ua, *ub; - - va = sega->u; - vb = sega->v; - ua = segb->u; - ub = segb->v; - - Ix = vb->x - va->x; - Iy = vb->y - va->y; - Jx = ub->x - ua->x; - Jy = ub->y - ua->y; - - m = (float)(-(-Ix*va->y+Ix*ua->y+Iy*va->x-Iy*ua->x))/(float)(Ix*Jy-Iy*Jx); - k = (float)(-(va->x*Jy-ua->x*Jy-Jx*va->y+Jx*ua->y))/(float)(Ix*Jy-Iy*Jx); - - if(m < 1 && m > 0 && k < 1 && k > 0) { - inter->x = va->x + k * Ix; - inter->y = va->y + k * Iy; - } - else - return NULL; - - return inter; -} - - -void grid_drawGrid() { - int i, j; - - for(i=0;i<nbXSubDivision-1;i++) - for(j=0;j<nbYSubDivision-1;j++) { - Vertex v = { .x = i*maxSegmentSize, .y = j*maxSegmentSize }; - Vertex u = { .x = (i+1)*maxSegmentSize, .y = j*maxSegmentSize }; - svg_line(&v,&u,0); - u.x = i*maxSegmentSize; - u.y = (j+1)*maxSegmentSize; - svg_line(&v,&u,0); - } -} - - -short grid_insertVertex(Vertex *vtx) { - if(vtx == NULL) - return 0; - - int i; - for(i=0;i<maxNodesInGrid;i++) { - if(vGrid[toX(vtx)][toY(vtx)][i] == NULL) { - vGrid[toX(vtx)][toY(vtx)][i] = vtx; - return 1; - } - } - - return 0; -} - - -/* Retourne le nœd le plus proche dans un certain voisinage. Si aucun nœd n'est trouvé alors - * la fonction renvoie NULL. - * @param Vertex *v : Le nœd pour lequel on souhaite trouver un nœd proche. - * @return roadNodeY* : le nœd de route le plus proche. - */ -Vertex* grid_getNearestVertex(Vertex *v) { - Vertex **vtx; - Vertex *nearestVertex = NULL; - int i,j; - int x = toX(v); - int y = toY(v); - int distance = maxSegmentSize*2; - Vertex *tmp = NULL; - int count = 0; - - for(i=x-1; i<x+2; i++) { - for(j=y-1; j<y+2; j++,count++) { - if(i >= 0 && i < nbXSubDivision && y >= 0 && y < nbYSubDivision) { - - vtx = grid_getNearVertices2(i,j); - - int ind; - - for(tmp = vtx[0], ind = 0; tmp != NULL && ind < maxNodesInGrid; tmp = vtx[ind++]) { - int dist = distBetween(v,tmp); - if(dist < distance) { - distance = dist; - nearestVertex = tmp; - } - - tmp = vtx[i]; - } - } - } - } - - return nearestVertex; -} - - -Vertex* insertSegment(Segment *seg, int lag) { - int segLength = distBetween(seg->u, seg->v); - float coef = ((float)segLength-lag)/(float)segLength; - Vertex *nearestVertex = NULL; - Vertex tmpEnd, *va, *vb; - int intersec = 0; // Booléen si intersection = 1 sinon = 0; - - va = seg->u; - vb = seg->v; - - seg = seg; - lag = lag; - // ------- TODO à compléter et à vérifier. - /*Segment **segs = grid_getNearSegments(rpb->rn->v->x,rpb->rn->v->y); - Segment *seg = segs[0]; - int s = 0; - - while(seg != NULL) { - Vertex *intersection = intersectionBetween(rpb->rn->v,rne->v,seg->u,seg->v); - - if(intersection != NULL) { - // Créer un nœd, l'insérer au segment qui à causé l'intersection. - // Ce nœd deviens le point d'arriver du segment à placer : rne; - intersec = 1; - } - seg = segs[s++]; - }*/ - // ------- - if(intersec == 0) { - tmpEnd.x = va->x + coef*(vb->x - va->x); - tmpEnd.y = va->y + coef*(vb->y - va->y); - - nearestVertex = grid_getNearestVertex(&tmpEnd); - - if(nearestVertex != NULL && distBetween(nearestVertex,vb) < lag) - vb = nearestVertex; - } - - grid_insertVertex(va); - grid_insertVertex(vb); - return NULL; -} - - -int distBetween(Vertex *v, Vertex *u) { - return sqrt((v->x-u->x)*(v->x-u->x)+(v->y-u->y)*(v->y-u->y)); -} - -Vertex** grid_getNearVertices(Vertex *v) { - return vGrid[toX(v)][toY(v)]; -} - - -Vertex** grid_getNearVertices2(int x, int y) { - return vGrid[x][y]; -} - - -/* Récupère tout les segement potentiellement sécant avec un segment ayant pour arrivée x et y. - */ -void grid_getNearSegments(Map *m, int x, int y) { - Vertex **vtx, *tmpVtx; - Segment *tmpSegs; - int i, j, s, k; - - s = 0; - Vertex vv = {.x = x, .y = y}; - x = toX(&vv); - y = toY(&vv); - - m->segments2_firstFree = 0; - - for(i=x-1;i<x+2;i++) { - for(j=y-1;j<y+2;j++) { - if(x >= 0 && x < nbXSubDivision && y >= 0 && y < nbYSubDivision) { - vtx = grid_getNearVertices2(i,j); - k = 0; - tmpVtx = vtx[0]; - //fprintf(stderr,"Bonjour\n"); - // TODO Tester si le segment existe déjà dans la liste pour ne pas l'insérer en double. - - while(tmpVtx != NULL) { - if(m->segments_firstFree >= segments_array_size) - return; - - for(tmpSegs = tmpVtx->s; tmpSegs != NULL; tmpSegs = tmpSegs->nextU) { - m->segments2[m->segments2_firstFree++] = tmpSegs; - } - - for(tmpSegs = tmpVtx->s; tmpSegs != NULL; tmpSegs = tmpSegs->nextV) { - m->segments2[m->segments2_firstFree++] = tmpSegs; - } - - tmpVtx = vtx[k++]; - } - } - } - } -} - - - - - - -// Algo « champs de force » -typedef struct FVector { float x; float y; } FVector; -inline FVector fVector_substract(FVector a, FVector b) { return (FVector){ .x = a.x - b.x, .y = a.y - b.y }; } -inline FVector fVector_add(FVector a, FVector b) { return (FVector){ .x = a.x + b.x, .y = a.y + b.y }; } -inline FVector fVector_rotate90(FVector v) { return (FVector){ .x = -v.y, .y = v.x }; } - -typedef struct FSegment { FVector from; FVector to; } FSegment; -inline void fsegment_display(FSegment s) { - printf("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\" />", s.from.x, s.from.y, s.to.x, s.to.y); -} - - -// TODO : dimensionner correctement le tableau. -#define FSegmentArray_SIZE 1024 -typedef struct FSegmentArray { FSegment seg[FSegmentArray_SIZE]; int firstUnseen; int firstFree; /* + CollisionGrid collision; */ } FSegmentArray; -inline void fSegmentArray_push(FSegmentArray* a, FSegment s) { - // TODO : check for collisions. - if (a->firstFree >= FSegmentArray_SIZE) return; - a->seg[a->firstFree++] = s; -} -inline FSegment fSegmentArray_pop(FSegmentArray* a) { - return a->seg[a->firstUnseen++]; -} - - -/* Choisir des champs de force. `f(x,y,vecteur)` renvoie tous les - * vecteurs de routes qu'on peut faire partir du point `(x,y)`, - * lorsqu'on y arrive par la direction `vecteur`. */ -// champ de force "ligne droite". -// TODO : devrait prendre un segment en paramètre. -void f(FSegment s, FSegmentArray* a) { - FVector delta = fVector_substract(s.to, s.from); - FSegment newS = { - .from = s.to, - .to = fVector_add(s.to, delta), - }; - // TODO : s'accrocher aux points proches, et ne pas ajouter le segment à la queue si on s'accroche à un point existant. - // TODO : ne pas utiliser des segments dans la file d'attente, mais juste des vertex, dont on peut énumérer les segments. - fSegmentArray_push(a, newS); - FSegment newS2 = { - .from = s.to, - .to = fVector_add(s.to, fVector_rotate90(delta)), - }; - newS2.to.y += 3; - fSegmentArray_push(a, newS2); -} - -/* ***************************** */ -// Nouvelle version : - - -Segment* segment_to(Map* m, Vertex* u, int x, int y) { - if(m->vertices_firstFree >= vertices_array_size) - return NULL; - - Vertex* v; - Vertex tmp = { .x = x, .y = y}; - Vertex *nearest = grid_getNearestVertex(&tmp); - - if(nearest != NULL && distBetween(&tmp,nearest) < 5) { - v = nearest; - v->x = x; - v->y = y; - v->s = NULL; - } - else { - v = &(m->vertices[m->vertices_firstFree++]); - v->x = x; - v->y = y; - v->s = NULL; - grid_insertVertex(v); - } - - if(v == NULL || m->segments_firstFree >= segments_array_size) - return NULL; - - // Code pour le calcul d'intersections. - - int distance = 1000; - int i; - Segment tmpSeg = { .u = u, .v = v}; - Segment *segmentCut = NULL; - Vertex *coordInter = NULL; - - grid_getNearSegments(m,u->x,u->y); - - for(i = 0; i < m->segments2_firstFree; i++) { - Vertex *intersection = intersectionBetween(m->segments2[i],&tmpSeg); - if(intersection != NULL && distBetween(u,intersection) < distance) { - distance = distBetween(u, intersection); - segmentCut = m->segments2[i]; - coordInter = intersection; - } - } - - if(segmentCut != NULL) { - Vertex *vInter = &(m->vertices[m->vertices_firstFree++]); - Segment *segmentPartA = segmentCut; - Segment *segmentPartB = &(m->segments[m->segments_firstFree++]); - - vInter->x = coordInter->x; - vInter->y = coordInter->y; - - segmentPartA->v = vInter; - - segmentPartB->u = vInter; - segmentPartB->nextU = NULL; - segmentPartB->v = segmentPartA->v; - segmentPartB->nextV = segmentPartA->nextV; - - segmentPartA->nextV = NULL; - - v = vInter; - m->vertices_firstFree--; - } - - Segment* s = &(m->segments[m->segments_firstFree++]); - s->u = u; - s->v = v; - /*s->nextU = u->s; - s->nextV = v->s; - u->s = s;*/ - v->s = s; - - return s; -} - -void fv(Map* m, Vertex *from) { - // Tracer une ou des routes, en utilisant segment_to. - if(from->s == NULL) - return; - - Vertex *existing = from->s->u == from ? from->s->v : from->s->u; - // Segment dans la continuation - //Vertex new1 = vertex_add(from, vertex_substract(from, existing)); // from + (from - existing) - Vertex new1 = { .x = from->x + (from->x - existing->x), - .y = from->y + (from->y - existing->y), - .s = NULL }; - - // Segment perpendiculaire - polarCoord *polar = ctp(existing,from); - polar->angle += 90; - - cartesianCoord *c = ptc(from,polar->angle,polar->length); - Vertex new2 = { .x = c->x, .y = c->y}; - - segment_to(m, from, new1.x, new1.y); - segment_to(m, from, new2.x, new2.y); -} - -void segment_display(Segment* s) { - printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"black\" />", - s->u->x, s->u->y, s->v->x, s->v->y); -} - -void forceFields() { - Map m; - m.segments2_firstFree = 0; - m.vertices[0] = (Vertex){ .x = 400, .y = 300, .s = NULL}; - m.vertices[1] = (Vertex){ .x = 401, .y = 309, .s = NULL}; - m.vertices_firstUnseen = 1; - m.vertices_firstFree = 2; - - m.segments[0] = (Segment){ .u = &(m.vertices[0]), .v = &(m.vertices[1]), .nextU = NULL, .nextV = NULL}; - m.vertices[0].s = NULL; - m.vertices[1].s = &(m.segments[0]); - m.segments_firstFree = 1; - - grid_initvGrid(800, 600, 10); - // TODO : insérer vertices[0] dans la grille. - grid_insertVertex(&(m.vertices[0])); - grid_insertVertex(&(m.vertices[1])); - - int i; - while(m.vertices_firstFree < vertices_array_size-2) { - //fprintf(stderr,"passage %d\n",i); - if(m.vertices_firstUnseen >= m.vertices_firstFree) { - break; - } - - fv(&m, &(m.vertices[m.vertices_firstUnseen++])); - } - - grid_drawGrid(); - for (i = 0; i < m.segments_firstFree; i++) { - //fprintf(stderr,"Dessin du segment %d\n",i); - segment_display(&(m.segments[i])); - } -} - -int main() { - Vertex points[] = { - { .x=10, .y=10 }, - { .x=790, .y=10 }, - { .x=600, .y=300 }, - { .x=790, .y=590 }, - { .x=10, .y=590 }, - }; - int n = 5; - - svg_start(800,600); - //carreY(); - forceFields(); - - //int i; - //for (i = 0; i < n; i++) { -// svg_line(&(points[i]), &(points[(i+1)%n])); -// } - -// grid_drawGrid(); - -n=n; - //roads(points); - points[0] = points[0]; - svg_end(); - return 0; -} diff --git a/roads.h b/roads.h @@ -1,96 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -typedef struct Vertex { - int x; - int y; - struct Segment* s; -} Vertex; - -typedef struct Segment { - Vertex *u; - Vertex *v; - struct Segment* nextU; - struct Segment* nextV; -} Segment; - -typedef Vertex Polygon; - -/* Cette structure définie un nœd de route. Le nœd contient la liste de toute les intersections. - */ -typedef struct roadNodeY { - Vertex *v; - short nbIntersec; - struct intersectionY **intersec; -} roadNodeY; - -typedef struct roadPointY { - struct roadPointY *first; - struct roadPointY *next; - struct roadPointY *previous; - roadNodeY *rn; -} roadPointY; - -/* Définition d'une intersection. Permet de savoir quelle route est concernée par cette intersection. - * Elle permet également de changer la navigation por parcourir une nouvelle route. - * */ -typedef struct intersectionY { - roadPointY *roadId; // Premier point de la route qui lui sert d'identifiant. - roadNodeY *next; // Nœd de la route juste après l'intersection. - roadNodeY *previous; // Nœd de la route juste avant l'intersection. - int zIndex; // Index sur l'axe z de la route. -} intersectionY; - -typedef struct cartesianCoord { - int x; // Coordonnées sur x. - int y; // Coordonnées sur y. -} cartesianCoord; - -typedef struct polarCoord { - int angle; // Angle en degrès. - int length; // Norme du vecteur. -} polarCoord; - -typedef struct roadSet { - roadPointY *roadId; // Identifiant de la route. - roadPointY *rpc; // Nœd courrant. -} roadStep; - -#define vertices_array_size 800 -#define segments_array_size 1024 -typedef struct Map { - Vertex vertices[vertices_array_size]; - Segment segments[segments_array_size]; - Segment* segments2[segments_array_size]; // Stockage temporaire d'un sous ensemble de segments. - int vertices_firstUnseen; - int vertices_firstFree; - int segments_firstFree; - int segments2_firstFree; - // TODO : champ grid & co. On peut même l'utiliser à la place de - // vertices. -} Map; - -Vertex ****vGrid; -roadPointY **roadsList; -short nbXSubDivision; -short nbYSubDivision; -short maxSegmentSize; -short maxNodesInGrid = 16; -int quarterWidth; -int quarterHeight; - -int toX(Vertex*); -int toY(Vertex*); -void grid_initNodesGrid(int w, int h, int maxSegmentSize); -short grid_insertVertex(Vertex *rn); -int distBetween(Vertex *v, Vertex *u); -Vertex** grid_getNearVertices(Vertex *v); -Vertex** grid_getNearVertices2(int x, int y); -Vertex* grid_getNearestVertex(Vertex *v); -void grid_drawGrid(); - -cartesianCoord* ptc(Vertex *origin, short angle, short length); -polarCoord* ctp(Vertex *origin, Vertex *end); - -void grid_getNearSegments(Map*, int x, int y); diff --git a/roads.md b/roads.md @@ -1,225 +0,0 @@ -Réseaux de routes/quartiers -=========================== - -On part d'un quartier qu'on subdivise en plus petits quartiers en y -trançant des rues. - -Un quartier est un polygone (pas forcément convexe !). Sur les côtés -du polygone, des routes entrantes et sortantes peuvent être -marquées. La somme des entrées (+) et sorties (-) du polygone est -nulle. - -Concentrique ------------- - -C'est équivalent à dé-polariser le repère et construire un « mur » -(sorte de grille avec beaucoup d'horizontales de grande longueur). - -Il faut trouver un algorithme de construction de mur, puis le -re-polariser afin de pouvoir le lancer avec plusieurs centres. - -Grille ------- - -Algo 1 - -* Choisir un angle. -* Tracer des routes suivant cet angle et cet angle + 90°. -* Les routes doivent pouvoir être assez longues (le tracé doit - survivre à une intersection). - -Algo 2 - -* Choisir un angle. -* Tracer des petits segments de route suivant l'angle et l'angle+90° -* Inhiber la subdivision de segments (ne pas les couper en deux). -* Raccrocher les bouts des routes à des points proches si possible (et - tant qu'on ne dévie pas trop en angle). - -Algo 3 -* Prendre une grille carrée / rectangulaire. -* La tourner d'un certain angle. -* Rattacher au bord du quartier les segments de la grille qui le - croisent. -* Supprimer aléatoirement certains segments, en gardant le graphe - connexe. - -Algo 4 -* Choisir un angle pour dessiner les croix. -* Dessiner une grosse croix avec des angles de 90° entre les segments, - ± au milieu du quartier. -* Subdiviser de la même manière les quatre (ou plus si le quartier - d'origine n'est pas convexe) quartiers ainsi créés, en gardant le - même angle (petites variations possibles). - -« Mur » -------- - -Comme une grille, mais les angles ne sont pas vraiment à 90°, et il y -a beaucoup de longues rues dans l'une ou l'autre des directions. - - .________________________. - | | | | | - |___|________|______|____| - | | |______| - |_________|_______| | - |______|__________|______| - -TODO : trouver un algo pour générer des « murs » - -Arborescent ------------ - -On subdivise le quartier en polygones plus ou moins réguliers (grille, -voronoi, …), et on fait partir un arbre depuis un point, qu'on étend -jusqu'à avoir touché tous les polygones. Chaque polygone est un -sous-quartier. - -Il est possible de s'arrêter avant d'avoir touché tous les polygones, -auquel cas il faut regrouper les polygones non touchés avec d'autres -pour qu'ils forment un seul quartier. - -Courbes de niveau ------------------ - -Faire des routes suivant les courbes de niveau, avec la possibilité de -monter ou descendre très légèrement pour rejoindre une autre ligne. - -* Partir d'un point, et choisir le point à X de distance qui minimise - le dénivellé -* Continuer à partir du point ainsi créé, en s'interdisant les retours - en arrière trop brutaux -* Arrêter la ligne quand le dénivellé devient trop important, ou quand - on rejoint une autre ligne. - -Calculs nécessaires -=================== - -Polygones ---------- - -Il faut pouvoir, à partir d'une liste de lignes, déterminer les -polygones ainsi découpés (ou bien maintenir un arbre de polygones -qu'on découpe au fur et à mesure qu'on trace des lignes traversant un -polygone), pour connaître les sous-quartiers créés en traçant les -routes. - -Points proches --------------- - -Énumérer les points proches d'un point donné. - -Pour cela, faire un quadtree (un arbre avec 4 fils à chaque noeud) -représentant des carrés composés de quatre carrés, et stocker dans -chaque noeud s'il contient des points dans son sous-arbre ou non. Les -noeuds feuille listent les points qu'ils contiennent. Quand on dépasse -un certain seuil pour le nombre de points contenus dans un noeud -feuille, on le subdivise. - -Lignes proches --------------- - -Énumérer les lignes proches d'un point donné. - -Quand on ajoute un point au graphe des routes, on l'insère à la bonne -position dans le quadtree. - -Quand on trace un segment entre deux points, on indique sa présence -dans tous les noeuds qu'il traverse. *TODO* : cela coûte cher en temps -et en espace ! - -Autre possibilité : forcer les routes à être sur le bord de polygones -(comme les rivières). Quand on veut tracer une route quelque part, on -subdivise le polygone contenant pour que le nouveau point soit sommet -d'au moins un des polygones, et la route côté de ce polygone. - -Intérieur d'un polygone --------------------- - -Pouvoir sélectionner aléatoirement des points à l'intérieur d'un -polygone (pour pouvoir faire les centres des réseaux concentriques par -exemple). - -Angles et vecteurs ------------------- - -Pouvoir ajouter un vecteur à un point, appliquer une rotation sur le -vecteur… - -Algo déformation de coordonées -============================== - -Partir d'une grille idéale carrée et appliquer des déformations de -coordonnées dessus, plus une fonction de densité de points (taille des -bâtiments). Dé-transformer la fonction de densité de points, -l'utiliser pour générer la grille parfaite avec des densités -différentes, puis transformer cette grille. - -Algo champs de force -==================== - -Variables : -* `vertices` est le tableau des vertices. Il se comporte comme une - fifo : les vertex qui y sont ajoutés sont en attente de traitement. -* `segments` est le tableau des segments de route. - -Algo : -* Choisir des champs de force. `f(vertex)` ajoute aux tableaux les - segments de route qu'on peut faire partir du point `(x,y)`. -* Initialiser le tableau de stockage des vertices `vertices` à vide. -* Initialiser le tableau de stockage des segments `segments` à vide. -* Choisir un point de départ aléatoire, et insérer `(x,y)` dans - `vertices`. -* Tant qu'on n'a pas traité tous les vertices : - * Prendre le premier point `(x,y)` non traité de `vertices`. - * f(x,y). - -Algo de f(x,y) : -* Pour chaque segment que l'on souhaite ajouter à partir de `(x,y)` : - * Insérer le nouveau vertex dans la grille ou en prendre l'existant. - * Si on inère le vertex, l'ajouter à `vertices`. - * Ajouter le segment à `segments`. - -Représentation simpliste des segments et routes -=============================================== - -* Dans chaque vertex, avoir un pointeur vers un des segments auxquels - il appartient. -* Dans chaque segment, avoir un pointeur vers le segment de même - origine suivant dans le sens des aiguilles d'une montre. -* Dans chaque segment, avoir un pointeur vers le segment de même - extrémité suivant dans le sens des aiguilles d'une montre. - -Algorithme de maintien des polygones -==================================== - -* Partir du périmètre du polygone de base. -* Lorsqu'on ajoute un segment partant d'un point de ce périmètre, - étendre ce périmètre pour qu'il fasse l'aller-retour sur le segment. -* Lorsqu'on ajoute un segment reliant deux points existants du - périmètre, séparer le périmètre en deux : le périmètre passant par - le côté gauche du segment, et celui passant par le côté droit du - segment. -* TODO : gestion possible des « trous » ? (càd quand on ajoute un - segment qui n'est pas relié au périmètre). Serait pratique pour - pouvoir ajouter certains gros bâtiments avant la création des - routes. - -Snapping des segments de route -============================== - -Invariants : -* Un segment qui part d'une case arrive forcément dans une des cases - adjacentes. -* Il n'y a qu'un seul vertex par case. - -Maintien des invariants : -* Si nécessaire, ralonger ou raccourcir les segments. -* Lorsqu'un segment atterrit dans une des cases voisines, s'il y a - déjà un vertex, il s'y raccroche, sinon on crée l'unique vertex de - la case. - -Idées en vrac : -* Densité de probabilité de split (= créer de nouvelles routes à - partir du point). Par exemple : 10% de chance de faire un split par - mètre = en moyenne, un split tous les 10 mètres ? diff --git a/roam.c b/roam.c @@ -1,318 +0,0 @@ -#include "roam.h" -#include "hash.h" - -/* Implémentation de ROAM - * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.22.1811&rep=rep1&type=pdf - * - * Triangle T (apex, vLeft, vRight) - * . vApex - * /|\ - * / | \ - * tLeftChild / 90° \ tRightChild - * / | \ - * / 45°|45° \ - * vLeft ._____._____. vRight - * vCenter - * - * Le triangle T contient le champ `vCenter`, qui permet de construire - * ses sous-triangles tLeftChild (vCenter, vApex, vLeft) et - * tRightChild (vCenter, vRight, vApex), du moment qu'on connait - * vApex, vLeft et vRight quand on manipule T. On les connaît car on a - * traversé récursivement ses triangles parents avant d'y arriver. - * - * T est le tParent de tLeftChild et tRightChild. - * - * Voisins : - * - * Le tBaseNeighbor de T est le triangle en-dessous, qui partage son - * côté (vLeft,vRight). - * - * Le tLeftNeighbor de T est le triangle à gauche, qui partage son - * côté (vApex,vLeft). - * - * Le tRightNeighbor de T est le triangle à droite, qui partage son - * côté (vApex,vRight). - * - */ - - -/* Permet de récupérer la taille de la base du triangle (hypoténuse).*/ -// TODO Optimisze la fonction pour éviter la racine carée. -int getFirstTriangleSize(Triangle* t) { - return sqrt(((t->vRight->x - t->vLeft->x)^2) + ((t->vRight->y - t->vLeft->y)^2)); -} - -/* Interpolation linéaire entre deux points. - * (x,y) est le point dont on veut connaître la valeur - * (x1,y1)--(x2,y2) est le carré dont on connaît les valeurs - * ne,se,so,no sont les valeurs aux coins nord/sud-est/ouest du carré. */ -// A optimiser par aproximation. -// Optimiser aussi le fait que la distance entre xy1 et xy2 est une puissance de 2, donc on peut faire un simple décalage. -// Peut être réalisé par une multiplication de matrice (donc sur le GPU) : http://en.wikipedia.org/wiki/Bilinear_interpolation -int interpolation(int x, int y, int x1, int y1, int x2, int y2, int ne, int se, int so, int no) { - int ret = 0; - // on multiplie chaque coin par la superficie du rectangle formé par (x,y) et ce coin. - ret += so * (x2-x) * (y-y1); - ret += no * (x2-x) * (y2-y); - ret += ne * (x-x1) * (y2-y); - ret += se * (x-x1) * (y-y1); - return ret / ((x2-x1) * (y2-y1)); -} - -// renvoie un z entre 0 et 255 -int get_z(int x, int y) { - x = x; /* Unused */ - y = y; /* Unused */ - int z = 0; - int level; - int maxlevel = 6; - for (level = maxlevel; level >= 0; level--) { - int step = (1 << level); - int mask = step - 1; - int zmax = 2*step - 1; - int x1 = x & ~mask; - int y1 = y & ~mask; - int x2 = x1 + step; - int y2 = y1 + step; - z += interpolation(x, y, x1, y1, x2, y2, hash3(level, x2, y1) & zmax, hash3(level, x2, y2) & zmax, hash3(level, x1, y2) & zmax, hash3(level, x1, y1) & zmax); - } - // ici le résultat est entre 0 (inclus) et 2^(2+maxlevel) (non inclus) - // On normalise sur [0,256[ sachant que 256 == 2^8. - if (maxlevel > 6) - z = z >> (-6+maxlevel); - else if (maxlevel != 6) - z = z << (6-maxlevel); - return z; -} - -void triangle_split(Triangle* t) { - Triangle* b; /* base neighbor */ - Vertex* c; /* center vertex */ - Triangle* subTLeft; - Triangle* subTRight; - Triangle* subBLeft; - Triangle* subBRight; - - b = t->tBaseNeighbor; - if (b != NULL) - if (b->tBaseNeighbor != t) - /* T and its base neighbor aren't of the same LOD. */ - triangle_split(b); - b = t->tBaseNeighbor; - - c = (Vertex*)malloc(sizeof(Vertex)); - c->x = (t->vLeft->x + t->vRight->x) / 2; - c->y = (t->vLeft->y + t->vRight->y) / 2; - c->z = get_z(c->x, c->y); - - subTLeft = (Triangle*)malloc(sizeof(Triangle)); - subTRight = (Triangle*)malloc(sizeof(Triangle)); - if (b != NULL) { - subBLeft = (Triangle*)malloc(sizeof(Triangle)); - subBRight = (Triangle*)malloc(sizeof(Triangle)); - } else { - subBLeft = NULL; - subBRight = NULL; - } - - /* subTLeft */ - { - /* Vertices */ - subTLeft->vApex = c; - subTLeft->vLeft = t->vApex; - subTLeft->vRight = t->vLeft; - /* Children */ - subTLeft->tLeftChild = NULL; - subTLeft->tRightChild = NULL; - /* To neighbors */ - subTLeft->tBaseNeighbor = t->tLeftNeighbor; - subTLeft->tLeftNeighbor = subTRight; - subTLeft->tRightNeighbor = subBRight; - /* Parent */ - subTLeft->tParent = t; - /* From neighbors */ - if (t->tLeftNeighbor != NULL) { - if (t->tLeftNeighbor->tBaseNeighbor == t) { - t->tLeftNeighbor->tBaseNeighbor = subTLeft; - } else { - t->tLeftNeighbor->tRightNeighbor = subTLeft; - } - } - } - /* subTRight */ - { - /* Vertices */ - subTRight->vApex = c; - subTRight->vLeft = t->vRight; - subTRight->vRight = t->vApex; - /* Children */ - subTRight->tLeftChild = NULL; - subTRight->tRightChild = NULL; - /* To neighbors */ - subTRight->tBaseNeighbor = t->tRightNeighbor; - subTRight->tLeftNeighbor = subBLeft; - subTRight->tRightNeighbor = subTLeft; - /* Parent */ - subTRight->tParent = t; - /* From neighbors */ - if (t->tRightNeighbor != NULL) { - if (t->tRightNeighbor->tBaseNeighbor == t) { - t->tRightNeighbor->tBaseNeighbor = subTRight; - } else { - t->tRightNeighbor->tLeftNeighbor = subTRight; - } - } - } - /* subBLeft */ - if (b != NULL) { - /* Vertices */ - subBLeft->vApex = c; - subBLeft->vLeft = b->vApex; - subBLeft->vRight = t->vRight; /* == b->vLeft, mais a plus de chances d'être dans le cache, non ? */ - /* Children */ - subBLeft->tLeftChild = NULL; - subBLeft->tRightChild = NULL; - /* To neighbors */ - subBLeft->tBaseNeighbor = b->tLeftNeighbor; - subBLeft->tLeftNeighbor = subBRight; - subBLeft->tRightNeighbor = subTRight; - /* Parent */ - subBLeft->tParent = t; - /* From neighbors */ - if (b->tLeftNeighbor != NULL) { - if (b->tLeftNeighbor->tBaseNeighbor == b) { - b->tLeftNeighbor->tBaseNeighbor = subBLeft; - } else { - b->tLeftNeighbor->tRightNeighbor = subBLeft; - } - } - } - /* subBRight */ - if (b != NULL) { - /* Vertices */ - subBRight->vApex = c; - subBRight->vLeft = t->vLeft; /* == b->vRight, mais a plus de chances d'être dans le cache, non ? */ - subBRight->vRight = b->vApex; - /* Children */ - subBRight->tLeftChild = NULL; - subBRight->tRightChild = NULL; - /* To neighbors */ - subBRight->tBaseNeighbor = b->tRightNeighbor; - subBRight->tLeftNeighbor = subTLeft; - subBRight->tRightNeighbor = subBLeft; - /* Parent */ - subBRight->tParent = t; - /* From neighbors */ - if (b->tRightNeighbor != NULL) { - if (b->tRightNeighbor->tBaseNeighbor == b) { - b->tRightNeighbor->tBaseNeighbor = subBRight; - } else { - b->tRightNeighbor->tLeftNeighbor = subBRight; - } - } - } - t->tLeftChild = subTLeft; - t->tRightChild = subTRight; - if (b != NULL) { - b->tLeftChild = subBLeft; - b->tRightChild = subBRight; - } -} - -void triangle_merge(Triangle* t, Triangle* b) { - t = t; - b = b; - /* TODO : free récursivement les triangles… Peut-être pas - * nécessaire vu qu'on peut les garbage-collecter en quelque sorte - * lorsqu'on envoie tous les triangles à la carte (on verra ceux - * qu'on n'envoie pas). - */ - t->tLeftChild = NULL; - t->tRightChild = NULL; - b->tLeftChild = NULL; - b->tRightChild = NULL; -} - -/* TODO : MinMax Heap : http://www.diku.dk/forskning/performance-engineering/Jesper/heaplab/heapsurvey_html/node11.html - * TODO : flexible memory usage : http://www.diku.dk/forskning/performance-engineering/Jesper/heaplab/heapsurvey_html/node15.html - * TODO : pour l'instant les comparaisons se font sur les adresses ! - */ - -/* Index des éléments du tas dans le tableau de stockage. - * 0 - * 1 2 - * 3 4 5 6 - * 7 8 9 . . . . . - */ - -#define HEAP_PARENT(x) (((x)-1)/2) -#define HEAP_LEFT_CHILD(x) ((x)*2+1) -#define HEAP_RIGHT_CHILD(x) ((x)*2+2) -#define SWAP(type, a, b) do { type SWAP_temp = (a); (a) = (b); (b) = SWAP_temp; } while (0) -/* Insère `node` dans `heap`. - * @param n : nombre de `node`s déjà dans le `heap`. - */ -void maxheap_insert(Triangle** heap, Triangle* node, unsigned int n) { - heap[n] = node; - unsigned int x = n; - while (x != 0 && heap[x] > heap[HEAP_PARENT(x)]) { - SWAP(Triangle*, heap[x], heap[HEAP_PARENT(x)]); - } -} - -/* Récupère le plus grand élément de `heap`. - * @param n : nombre de `node`s déjà dans le `heap`. - */ -Triangle* maxheap_pop_max(Triangle** heap, unsigned int n) { - Triangle* ret = heap[0]; - heap[0] = heap[n]; - unsigned int x = 0; - while (x != n && - (heap[x] < heap[HEAP_LEFT_CHILD(x)] || heap[x] < heap[HEAP_RIGHT_CHILD(x)])) { - if (heap[HEAP_LEFT_CHILD(x)] > heap[HEAP_RIGHT_CHILD(x)]) { - SWAP(Triangle*, heap[x], heap[HEAP_LEFT_CHILD(x)]); - } else { - /* échanger right et x */ - SWAP(Triangle*, heap[x], heap[HEAP_RIGHT_CHILD(x)]); - } - } - return ret; -} - -void recursiveSplit(Triangle* t, int n) { - if (n == 0) return; - if (t->tLeftChild == NULL) { // t is not already split - triangle_split(t); - } - recursiveSplit(t->tLeftChild, n-1); - recursiveSplit(t->tRightChild, n-1); -} - -Triangle* initDefaultExample() { - Triangle* t = (Triangle*)malloc(sizeof(Triangle)); - Vertex* vApex = (Vertex*)malloc(sizeof(Vertex)); - Vertex* vLeft = (Vertex*)malloc(sizeof(Vertex)); - Vertex* vRight = (Vertex*)malloc(sizeof(Vertex)); - - vApex->x = 256; vApex->y = 256; vApex->z = get_z(256,256); - vLeft->x = 0; vLeft->y = 0; vLeft->z = get_z(0,0); - vRight->x = 512; vRight->y = 0; vRight->z = get_z(512,0); - - t->vApex = vApex; - t->vLeft = vLeft; - t->vRight = vRight; - t->tLeftChild = NULL; - t->tRightChild = NULL; - t->tBaseNeighbor = NULL; - t->tLeftNeighbor = NULL; - t->tRightNeighbor = NULL; - t->tParent = NULL; - - recursiveSplit(t, 10); - /* triangle_split(t); */ - /* triangle_split(t->tLeftChild); */ - /* triangle_split(t->tLeftChild->tLeftChild); */ - /* triangle_split(t->tLeftChild->tRightChild); */ - - return t; -} diff --git a/roam.h b/roam.h @@ -1,32 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -typedef struct Vertex { - int x; - int y; - int z; - float xNormal; - float yNormal; - float zNormal; - int refCount; - struct Vertex* next[4]; - /* Ajouter des champs ici. */ -} Vertex; - -typedef struct Triangle { - Vertex* vApex; - Vertex* vLeft; - Vertex* vRight; - struct Triangle* tLeftChild; - struct Triangle* tRightChild; - struct Triangle* tBaseNeighbor; - struct Triangle* tLeftNeighbor; - struct Triangle* tRightNeighbor; - struct Triangle* tParent; -} Triangle; - -Triangle* initDefaultExample(); -int interpolation(int x, int y, int x1, int y1, int x2, int y2, int ne, int se, int so, int no); -unsigned int hash2(unsigned int a, unsigned int b); -int get_z(int x, int y); diff --git a/simple-terrain.c b/simple-terrain.c @@ -1,122 +0,0 @@ -#include <stdio.h> -#include <math.h> - -#define SIZE 512 -// best value for MAX_DETAIL is 8 -#define MAX_DETAIL 8 - -int bsr(int x) { - asm volatile("bsr %0, %0" : "=r" (x) : "0" (x) : "0"); - return x; -} - -int random_from_rec2(int a, int b, int c) { - b += a; // b = a + b // 2 bytes - a *= b; // a = a * (a + b) // 2 bytes - b ^= a; // b = (a + b) ^ (a * (a + b)) // 2 bytes - a += 211; // a = (a * (a + b)) + 5 // 2-3 bytes ; 211 is wonderfull. - b /= 2; // b = ((a + b) ^ (a * (a + b))) / 2 // 2 bytes - - if (c == 0) -// return a >> 2; // 3 bytes :( , but we can do with >>1 or even without. - return a >> 1; - return random_from_rec2(a, b, c-1); -} - -unsigned char random_from(int a, int b) { - return (random_from_rec2(a, b, 1)) & 0xff; -} - -/* Alternate method to compute a single detail level for z. - // This square - z = random_from(xd, yd); - - // x interpolation - zb = random_from(xd + 1, yd); - z += ((zb-z) * (x & mask)) >> detail; - - // y interpolation - zc = random_from(xd, yd + 1); - zb = random_from(xd + 1, yd + 1); - zc += ((zb-zc) * (x & mask)) >> detail; - z += ((zc-z) * (y & mask)) >> detail; -*/ - -int get_z(int x, int y) { - int detail, mask; - int xd, yd; - int z00, z01, z10, z11; - int xm, ym, mxm, mym; - unsigned int z, ztot; - - ztot = 0; - for (detail = 0; detail < MAX_DETAIL; detail++) { - x++; // slightly blurs vertical - y++; // and horizontal artifacts. - - mask = (1<<detail) - 1; - xd = x >> detail; - yd = y >> detail; - - if (0 == 0) { - // Method one - z00 = random_from(xd + 0, yd + 0); - z01 = random_from(xd + 0, yd + 1); - z10 = random_from(xd + 1, yd + 0); - z11 = random_from(xd + 1, yd + 1); - - xm = ((xd + 1) << detail) - x; - ym = ((yd + 1) << detail) - y; - mxm = (1 << detail) - xm; - mym = (1 << detail) - ym; - - z = 0; - z += z00 * xm * ym ; - z += z01 * xm * mym; - z += z10 * mxm * ym ; - z += z11 * mxm * mym; - - z >>= ((detail * 2) + (MAX_DETAIL - detail)); - // Method two - } else { - // Alternate method - int zb, zc; - // This square - z = random_from(xd, yd); - - // x interpolation - zb = random_from(xd, yd + 1); - z += ((zb-z) * (y & mask)) >> detail; - - // y interpolation - zc = random_from(xd + 1, yd); - zb = random_from(xd + 1, yd + 1); - zc += ((zb-zc) * (y & mask)) >> detail; - z += ((zc-z) * (x & mask)) >> detail; - - z >>= 0; - // Alternate method - } - - // add this detail level - ztot += z; - } - //x = x - MAX_DETAIL; // when using x++ and y++ - //y = y - MAX_DETAIL; // to reduce artifacts. - - return ztot & 0xff; -} - -int main(int argc, char** argv) { - int y; - int x; - if (argc != 1) { - fprintf(stderr, "Aide :\n"); - fprintf(stderr, "Utilisez ./simple-terrain | display pour visualiser la sortie.\n"); - fprintf(stderr, "Utilisez ./simple-terrain > fichier.pnm pour sauvegarder.\n"); - } - printf("P5 %d %d 255\n", SIZE, SIZE); - for (y=SIZE-1; y>=0; y--) - for (x=0; x<SIZE; x++) - printf("%c", (char)get_z(x,y)); -} diff --git a/square.c b/square.c @@ -1,305 +0,0 @@ -#include "square.h" - -// Positionne v à (xx,yy) et calcule z. Met ref_count à 0. -inline void init_vertex(Vertex* v, int x, int y) { - v->refCount = 0; - v->x = x; - v->y = y; - v->z = get_z(x,y); -} - -// ROTATE4(x,r) == x+r % 4 -#define ROTATE4(x,r) ((x+r) & 3) - -// L'ordre dans les tableaux est toujours {ne,se,so,no} ou bien {n,e,s,o}. -typedef enum QTQuadrant { QT_NE = 0, QT_SE = 1, QT_SO = 2, QT_NO = 3 } QTQuadrant; -typedef enum QTCardinal { QT_N = 0, QT_E = 1, QT_S = 2, QT_O = 3 } QTCardinal; - -#define ROT_NE (ROTATE4(QT_NE, r)) -#define ROT_SE (ROTATE4(QT_SE, r)) -#define ROT_SO (ROTATE4(QT_SO, r)) -#define ROT_NO (ROTATE4(QT_NO, r)) - -#define ROT_N (ROTATE4(QT_N, r)) -#define ROT_E (ROTATE4(QT_E, r)) -#define ROT_S (ROTATE4(QT_S, r)) -#define ROT_O (ROTATE4(QT_O, r)) - - -static inline void vertex_link_create(Vertex* a, Vertex* b, QTCardinal directionAB) { - //printf("vertex_link_create %x to %x direction %d (N=%d)\n", (int)a, (int)b, directionAB, QT_N); - if (a != NULL) a->next[directionAB] = b; - if (b != NULL) b->next[ROTATE4(directionAB, 2)] = a; -} - -static inline void vertex_link_between(Vertex* vnew, Vertex* a, Vertex* b, QTCardinal directionAB) { - vertex_link_create(a, vnew, directionAB); - vertex_link_create(vnew, b, directionAB); -} - -static inline void vertex_link_remove(Vertex* v) { - vertex_link_create(v->next[QT_S], v->next[QT_N], QT_N); - vertex_link_create(v->next[QT_O], v->next[QT_E], QT_E); -} - -static inline void qtnode_link_create(QTNode* a, QTNode* b) { - if (a != NULL) a->nextNode = b; - if (b != NULL) b->previousNode = a; -} - -inline Vertex* use_vertex(Vertex* v) { v->refCount++; return v; } -inline void unuse_vertex(Vertex* v) { - // TODO : assert(v->refCount > 0); - if (--(v->refCount) == 0) { - // Supprime le vertex des listes de parcours. - vertex_link_remove(v); - free(v); - } -} - -void QT_split(QTNode* parent) { - // Ne pas split un noeud déjà split. - if (parent->children[QT_NE] != NULL) return; - - int r; - QTNode* q[4]; - for (r = 0; r < 4; r++) { - q[ROT_NE] = malloc(sizeof(QTNode)); - } - - Vertex* new_vertices[4]; - for (r = 0; r < 4; r++) { - // réutiliser le vertex existant (parent->top_neighbor->se_child->so ou bien parent->top_neighbor->so_child->se) - if (parent->neighbors[ROT_N] != NULL && parent->neighbors[ROT_N]->children[ROT_SE] != NULL) { - new_vertices[ROT_N] = parent->neighbors[ROT_N]->children[ROT_SE]->vertices[ROT_SO]; - } else { - new_vertices[ROT_N] = (Vertex*)malloc(sizeof(Vertex)); - // Insère le nouveau vertex entre les deux coins de parent. - vertex_link_between(new_vertices[ROT_N], parent->vertices[ROT_NO], parent->vertices[ROT_NE], ROT_E); - // place le nouveau vertex après center. - vertex_link_create(parent->center, new_vertices[ROT_N], ROT_N); - // Définit x,y,z et ref_count. - switch (r) { // TODO : Devrait être factorisé. - case 0: init_vertex(new_vertices[0], parent->center->x, parent->vertices[QT_NE]->y); break; - case 1: init_vertex(new_vertices[1], parent->vertices[QT_SE]->x, parent->center->y); break; - case 2: init_vertex(new_vertices[2], parent->center->x, parent->vertices[QT_SO]->y); break; - case 3: init_vertex(new_vertices[3], parent->vertices[QT_NO]->x, parent->center->y); break; - } - } - } - - for (r = 0; r < 4; r++) { // Dans le corps de la boucle, positions pour le quadrant ne. - q[ROT_NE]->center = malloc(sizeof(Vertex)); - // Pas besoin d'insérer center dans une des listes : à sa création il ne sera accédé dans aucun parcours de périmètre. - // Coordonnées du centre de qne = moyenne du center et de parent->vertices[QT_NE]. - init_vertex(q[ROT_NE]->center, (parent->center->x + parent->vertices[ROT_NE]->x) / 2, (parent->center->y + parent->vertices[ROT_NE]->y) / 2); - use_vertex(q[ROT_NE]->center); - - q[ROT_NE]->vertices[ROT_NE] = use_vertex(parent->vertices[ROT_NE]); - q[ROT_NE]->vertices[ROT_SE] = use_vertex(new_vertices[ROT_E]); - q[ROT_NE]->vertices[ROT_SO] = use_vertex(parent->center); - q[ROT_NE]->vertices[ROT_NO] = use_vertex(new_vertices[ROT_N]); - - q[ROT_NE]->children[ROT_NE] = NULL; - q[ROT_NE]->children[ROT_SE] = NULL; - q[ROT_NE]->children[ROT_SO] = NULL; - q[ROT_NE]->children[ROT_NO] = NULL; - - // Si le voisin du haut de parent a un se_child, c'est le voisin du haut de qne. - if (parent->neighbors[ROT_N] != NULL) { - q[ROT_NE]->neighbors[ROT_N] = parent->neighbors[ROT_N]->children[ROT_SE]; - if (parent->neighbors[ROT_N]->children[ROT_SE] != NULL) - parent->neighbors[ROT_N]->children[ROT_SE]->neighbors[ROT_S] = q[ROT_NE]; - } else { - q[ROT_NE]->neighbors[ROT_N] = NULL; - } - // Si le voisin de droite de parent a un no_child, c'est le voisin de droite de qne. - if (parent->neighbors[ROT_E] != NULL) { - q[ROT_NE]->neighbors[ROT_E] = parent->neighbors[ROT_E]->children[ROT_NO]; - if (parent->neighbors[ROT_E]->children[ROT_NO] != NULL) - parent->neighbors[ROT_E]->children[ROT_NO]->neighbors[ROT_O] = q[ROT_NE]; - } else { - q[ROT_NE]->neighbors[ROT_E] = NULL; - } - q[ROT_NE]->neighbors[ROT_S] = q[ROT_SE]; - q[ROT_NE]->neighbors[ROT_O] = q[ROT_NO]; - - parent->children[ROT_NE] = q[ROT_NE]; - } - - // remplacer parent par ses quatre enfants dans la liste d'énumération de tous les QTNode feuilles. - qtnode_link_create(parent->previousNode, q[QT_NO]); - qtnode_link_create(q[QT_NO], q[QT_NE]); - qtnode_link_create(q[QT_NE], q[QT_SE]); - qtnode_link_create(q[QT_SE], q[QT_SO]); - qtnode_link_create(q[QT_SO], parent->nextNode); - - // TODO : set minLOD = maxLOD = parent->LOD + 1; // À moins que ça soit le parcours récursif de màj du mesh qui écrive cette information ? -} - -void QT_merge(QTNode* parent) { - // Ne pas merge un noeud sans enfants. - if (parent->children[QT_NE] == NULL) return; - - qtnode_link_create(parent->children[QT_NO]->previousNode, parent); - qtnode_link_create(parent, parent->children[QT_SO]->nextNode); - - int r; - for (r = 0; r < 4; r++) { - // Merge récursif des enfants. - QT_merge(parent->children[ROT_NE]); - - // reset à NULL les voisins qui pointaient vers des enfants. - if (parent->neighbors[ROT_N] != NULL) - if (parent->neighbors[ROT_N]->children[ROT_SE] != NULL) - parent->neighbors[ROT_N]->children[ROT_SE]->neighbors[ROT_S] = NULL; - if (parent->neighbors[ROT_E] != NULL) - if (parent->neighbors[ROT_E]->children[ROT_NO] != NULL) - parent->neighbors[ROT_E]->children[ROT_NO]->neighbors[ROT_O] = NULL; - - unuse_vertex(parent->children[ROT_NE]->center); - int i; - for (i = 0; i < 4; i++) - unuse_vertex(parent->children[ROT_NE]->vertices[i]); - - free(parent->children[ROT_NE]); - parent->children[ROT_NE] = NULL; - } -} - -QTNode* QT_baseNode() { - int i; - QTNode* q = malloc(sizeof(QTNode)); - Vertex* _v = (Vertex*) malloc(sizeof(Vertex)*5); - Vertex* v[5]; for (i = 0; i < 5; i++) v[i] = &(_v[i]); - - vertex_link_create(v[1], v[2], QT_S); - vertex_link_create(v[2], v[3], QT_O); - vertex_link_create(v[3], v[4], QT_N); - vertex_link_create(v[4], v[1], QT_E); - - init_vertex(v[0], 0, 0); - init_vertex(v[1], +1024, -1024); - init_vertex(v[2], +1024, +1024); - init_vertex(v[3], -1024, +1024); - init_vertex(v[4], -1024, -1024); - - q->center = use_vertex(v[0]); - - for (i = 0; i < 4; i++) { - q->vertices[i] = use_vertex(v[i+1]); - q->children[i] = NULL; - q->neighbors[i] = NULL; - } - - qtnode_link_create(q, NULL); - qtnode_link_create(NULL, q); - - q->minLOD = 0; - q->maxLOD = 0; - - return q; -} - -void vertex_print(Vertex* v) { - v=v; - //printf("vertex %x(%d,%d,%d) N=%x E=%x S=%x O=%x\n", (unsigned int)v, v->x, v->y, v->z, (int)v->next[QT_N], (int)v->next[QT_E], (int)v->next[QT_S], (int)v->next[QT_O]); -} - -void qtnode_print(QTNode* n) { - //printf("node %x center=", (unsigned int)n); - vertex_print(n->center); -} - -void setNormal(Vertex *center, Vertex *va, Vertex *v) { - int ax = va->x - center->x; - int ay = va->y - center->y; - int az = va->z - center->z; - int bx = center->x - v->x; - int by = center->y - v->y; - int bz = center->z - v->z; - - float x = (float)((ay * bz) - (az * by)); - float y = (float)((az * bx) - (ax * bz)); - float z = -(float)((ax * by) - (ay * bx)); - float length = sqrt(x*x + y*y + z*z); - - length = length; - x = x/length; - y = y/length; - z = z/length; - - /*va = center; - glDisable(GL_LIGHTING); - glDisable(GL_TEXTURE_2D); - glColor3ub(255,255,255); - glBegin(GL_LINES); - glVertex3f(va->x,va->y,va->z); - glVertex3f(va->x+500*x,va->y+500*y,va->z+500*z); - glEnd(); - glEnable(GL_LIGHTING);*/ - glNormal3f(x,y,-z); -} - -// first est le QTNode le plus en haut à gauche (NO). Par la suite, on -// pourra créer un first artificiel qui évitera la descente récursive -// jusqu'au NO le plus petit. -void QT_enumerate(QTNode* first) { - //printf("\nFRAME\n\n"); - while (first->children[QT_NO] != NULL) - first = first->children[QT_NO]; - - QTNode* n; - int r; - int i=0; - Vertex* v; - Vertex *center; - Vertex *va = NULL; - - for (n = first; n != NULL; n = n->nextNode) { - qtnode_print(n); - - glBegin(GL_TRIANGLE_FAN); - setNormal(n->vertices[QT_NE],n->vertices[QT_SO],n->vertices[QT_SE]); - // envoyer le vertex central - center = n->center; - setNormal(center,n->vertices[ROT_NO],n->vertices[ROT_NO]->next[ROT_E]); - glVertex3f(center->x,center->y,center->z); - - // Pour chaque côté - for (r = 0, i = 0; r < 4; r++) { - // On parcourt tous les vertices le long du côté. - for (v = n->vertices[ROT_NO]; v != n->vertices[ROT_NE]; i++, v = v->next[ROT_E]) { - if(i <= 1){ - va = v; - //setNormal(center,n->vertices[QT_SO],v); - } - else { - setNormal(center,va,v); - va = v; - } - - glVertex3f(v->x,v->y,v->z); - // envoyer un vertex du fan : - //(void)(v); - } - } - - // Nécessaire ssi on fait un TRIANGLE_FAN et qu'on ne peut pas lui dire de fermer la boucle. - // On renvoie le 1er vertex du bord : - (void)(n->vertices[QT_NO]); - setNormal(center,va,n->vertices[QT_NO]); - glVertex3f(n->vertices[QT_NO]->x,n->vertices[QT_NO]->y,n->vertices[QT_NO]->z); - glEnd(); - } -} - -QTNode* QT_example() { - QTNode* q = QT_baseNode(); - QT_split(q); - QT_split(q->children[QT_NO]); - QT_split(q->children[QT_NO]->children[QT_SE]); - QT_split(q->children[QT_NO]->children[QT_SE]->children[QT_SO]); - QT_split(q->children[QT_NO]->children[QT_SE]->children[QT_NE]); - return q; -} diff --git a/square.h b/square.h @@ -1,20 +0,0 @@ -// get_z() -#include "roam.h" -#include <GL/gl.h> - -// QuadTree Node. -typedef struct QTNode { - Vertex* center; - Vertex* vertices[4]; - struct QTNode* children[4]; - struct QTNode* neighbors[4]; - // linked list across all nodes, for traversal when we display them. - struct QTNode* nextNode; - struct QTNode* previousNode; - unsigned int minLOD; - unsigned int maxLOD; -} QTNode; - -QTNode* QT_example(); -void QT_enumerate(QTNode* first); -void QT_split(QTNode* parent); diff --git a/terrain.md b/terrain.md @@ -1,49 +0,0 @@ -Liens ------ - -* [Différents algos](http://www.sluniverse.com/php/vb/project-development/34994-automatically-generated-terrain-map.html) : Ridged Perlin Noise, Hills Algorithm, Craters, Erosion. -* [Plein d'algos](http://planetgenesis.sourceforge.net/docs15/noise/noise.html#tileworley) dont plusieurs basés sur une sorte de voronoi donc à priori trop lents. -* Affichage avec Ogre : [forum](http://www.ogre3d.org/forums/viewtopic.php?f=5&t=67177&p=442222), [doc](http://www.ogre3d.org/docs/api/html/classOgre_1_1BillboardSet.html) - -Perlin noise ------------- - -Ridged Perlin Noise -------------------- - -[Démo de Ridged Perlin Noise](http://www.inear.se/2010/04/ridged-perlin-noise/) - - // Fait des crêtes de montagnes ou vallées. - abs(perlinNoise()); - -Hills Algorithm ---------------- - -Inverse de craters : on ajoute plein de cercles : - - repeat 1000 times : - r=random(); - cx=random(); - cy=random(); - terrain[x][y] += r**2 + ((x-cx)**2 – (y-cy)**2) - -Craters -------- - -Soustraire des cercles (profondeur = f(distance au centre)) au terrain -existant. -Ou : générer un terrain nu, et soustraire plein de cercles aléatoirs. - -Erosion -------- - -Modélisation correcte : trop lent. À la place, outil "courbes" de gimp. - -Rivières -======== - -[Pathfinding pour créer des rivières](http://www.umbrarumregnum.net/articles/creating-rivers). -Si on utilise une méthode de coût qui favorise de passer par un petit -bout de bruit plutôt que de le contourner, mais favorise le -contournement pour une grosse accumulation de bruit, on pourra même -simuler l'érosion qui efface les méandres trop petits.