Premier affichage 3D.

This commit is contained in:
Georges Dupéron 2011-11-28 11:42:44 +01:00
parent f5cc3dc243
commit 0d467384f3
17 changed files with 258 additions and 49 deletions

View File

@ -4,7 +4,8 @@ CCWARN=-Wall -Wextra -Werror
# -flto (nécessite GCC 4.5) -m32 ou -m64 # -flto (nécessite GCC 4.5) -m32 ou -m64
CFLAGS=-O3 -g3 -I. $(CCWARN) CFLAGS=-O3 -g3 -I. $(CCWARN)
OBJECTS = main.o hash.o segment.o vertex.o triangle.o rules/chose.o rules/rectangleroutes.o rules/route.o rules/carrefour.o rules/batiment.o OBJECTS = main.o view.o hash.o segment.o vertex.o triangle.o rules/chose.o rules/rectangleroutes.o rules/route.o rules/carrefour.o rules/batiment.o
LIBS = -lm -lGL -lGLU -lSDL -lGLEW
EXECUTABLE = city EXECUTABLE = city
.PHONY: test .PHONY: test
@ -18,8 +19,8 @@ all: $(EXECUTABLE)
clean: clean:
rm -f $(EXECUTABLE) $(OBJECTS) $(OBJECTS:.o=.d) rm -f $(EXECUTABLE) $(OBJECTS) $(OBJECTS:.o=.d)
city: $(OBJECTS) $(EXECUTABLE): $(OBJECTS)
$(CXX) -lm $^ -o $@ $(CXX) $(LIBS) $^ -o $@
-include $(OBJECTS:.o=.d) -include $(OBJECTS:.o=.d)

View File

@ -8,11 +8,17 @@ class Chose;
#include <cmath> #include <cmath>
#include <vector> #include <vector>
#include <SDL/SDL.h>
#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include "vertex.hh" #include "vertex.hh"
#include "segment.hh" #include "segment.hh"
#include "triangle.hh" #include "triangle.hh"
#include "directions.hh" #include "directions.hh"
#include "hash.hh" #include "hash.hh"
#include "view.hh"
#include "rules/chose.hh" #include "rules/chose.hh"
#include "rules/batiment.hh" #include "rules/batiment.hh"

View File

@ -1,18 +1,27 @@
#include "all_includes.hh" #include "all_includes.hh"
// TODO : bâtiments.
// TODO : split route en 2 triangles.
// TODO : split bâtiment en faces, puis en triangles. // TODO : split bâtiment en faces, puis en triangles.
// TODO : probabilités des différents types de bâtiments. // TODO : probabilités des différents types de bâtiments.
// TODO : midpoint displacement sur les probabilités des différents types de bâtiments. // TODO : midpoint displacement sur les probabilités des différents types de bâtiments.
// TODO : largeur des routes : ??? // TODO : largeur des routes : ???
void recursiveSubdivide(Chose* c) {
if (c->subdivide()) {
std::vector<Chose*>::iterator it;
for (it = c->children.begin(); it != c->children.end(); ++it) {
recursiveSubdivide(*it);
}
}
}
int main() { int main() {
// Générer une tile de base // Générer une tile de base
Vertex ne(100, 100, 0); Vertex ne(1000, 1000, 0);
Vertex sw(0, 0, 0); Vertex sw(0, 0, 0);
RectangleRoutes r(ne, sw); RectangleRoutes* r = new RectangleRoutes(ne, sw);
r.subdivide(); recursiveSubdivide(r);
new View(r);
// tile.subdivide tant qu'on n'a pas le niveau de détail désiré. // tile.subdivide tant qu'on n'a pas le niveau de détail désiré.
return 0; return 0;
} }

View File

@ -1,19 +1,21 @@
#include "all_includes.hh" #include "all_includes.hh"
Batiment::Batiment(Vertex ne, Vertex sw) : ne(ne), sw(sw) { Batiment::Batiment(Vertex ne, Vertex sw) : Chose(), ne(ne), sw(sw) {
std::cout << this << std::endl; addEntropy(ne, sw);
triangulation();
} }
int Batiment::width() { return this->ne.x - this->sw.x; } int Batiment::width() { return this->ne.x - this->sw.x; }
int Batiment::height() { return this->ne.y - this->sw.y; } int Batiment::height() { return this->ne.y - this->sw.y; }
void Batiment::subdivide() { bool Batiment::subdivide() {
// TODO : rien ? // TODO : rien ?
return false;
} }
void Batiment::triangulation() { void Batiment::triangulation() {
initTriangles(12); triangles.reserve(12);
// abcd sont les quatre coins du bâtiment. // abcd sont les quatre coins du bâtiment.
Vertex a = this->ne; Vertex a = this->ne;

View File

@ -13,7 +13,7 @@ public:
Batiment(Vertex ne, Vertex sw); Batiment(Vertex ne, Vertex sw);
int width(); int width();
int height(); int height();
virtual void subdivide(); virtual bool subdivide();
virtual void triangulation(); virtual void triangulation();
}; };

View File

@ -1,15 +1,16 @@
#include "carrefour.hh" #include "carrefour.hh"
Carrefour::Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw) { Carrefour::Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Chose() {
corners[NE]=ne; corners[NE]=ne;
corners[SE]=se; corners[SE]=se;
corners[SW]=sw; corners[SW]=sw;
corners[NW]=nw; corners[NW]=nw;
std::cout << this << std::endl; triangulation();
} }
void Carrefour::subdivide() { bool Carrefour::subdivide() {
// TODO // TODO
return false;
} }
std::ostream& operator<<(std::ostream& os, const Carrefour* c) { std::ostream& operator<<(std::ostream& os, const Carrefour* c) {
@ -21,7 +22,7 @@ std::ostream& operator<<(std::ostream& os, const Carrefour& c) {
} }
void Carrefour::triangulation() { void Carrefour::triangulation() {
initTriangles(2); triangles.reserve(2);
addTriangle(new Triangle(corners[SW], corners[NW], corners[NE])); addTriangle(new Triangle(corners[SW], corners[NW], corners[NE]));
addTriangle(new Triangle(corners[SW], corners[SE], corners[NE])); addTriangle(new Triangle(corners[SW], corners[SE], corners[NE]));
} }

View File

@ -3,12 +3,12 @@
#include "all_includes.hh" #include "all_includes.hh"
class Carrefour : Chose { class Carrefour : public Chose {
public: public:
Vertex corners[4]; Vertex corners[4];
public: public:
Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw); Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw);
virtual void subdivide(); virtual bool subdivide();
virtual void triangulation(); virtual void triangulation();
public: public:
friend std::ostream& operator<<(std::ostream& os, const Carrefour& c); friend std::ostream& operator<<(std::ostream& os, const Carrefour& c);

View File

@ -1,6 +1,6 @@
#include "all_includes.hh" #include "all_includes.hh"
Chose::Chose() : seed(initialSeed) {} Chose::Chose() : seed(initialSeed), children() {}
std::ostream& operator<<(std::ostream& os, const Chose* r) { std::ostream& operator<<(std::ostream& os, const Chose* r) {
return os << *r; return os << *r;
@ -11,14 +11,6 @@ std::ostream& operator<<(std::ostream& os, const Chose& r) {
return os << "Chose"; return os << "Chose";
} }
void Chose::initChildren(int n) {
children = std::vector<Chose*>(n);
}
void Chose::initTriangles(int n) {
triangles = std::vector<Triangle*>(n);
}
void Chose::addChild(Chose* c) { void Chose::addChild(Chose* c) {
children.push_back(c); children.push_back(c);
// TODO : Ajouter c dans une file d'attente des éléments pouvant être split. // TODO : Ajouter c dans une file d'attente des éléments pouvant être split.
@ -28,3 +20,17 @@ void Chose::addTriangle(Triangle* t) {
triangles.push_back(t); triangles.push_back(t);
// TODO : Ajouter t dans la liste des triangles à envoyer au GPU. // TODO : Ajouter t dans la liste des triangles à envoyer au GPU.
} }
void Chose::display() {
if (children.size() > 0) {
std::vector<Chose*>::iterator it;
for (it = children.begin(); it != children.end(); ++it) {
(*it)->display();
}
} else {
std::vector<Triangle*>::iterator it;
for (it = triangles.begin(); it != triangles.end(); ++it) {
(*it)->display();
}
}
}

View File

@ -20,12 +20,11 @@ public:
inline void addEntropy(Vertex v1, Vertex v2) { addEntropy(v1); addEntropy(v2); } inline void addEntropy(Vertex v1, Vertex v2) { addEntropy(v1); addEntropy(v2); }
inline void addEntropy(Vertex v1, Vertex v2, Vertex v3) { addEntropy(v1, v2); addEntropy(v3); } inline void addEntropy(Vertex v1, Vertex v2, Vertex v3) { addEntropy(v1, v2); addEntropy(v3); }
inline void addEntropy(Vertex v1, Vertex v2, Vertex v3, Vertex v4) { addEntropy(v1, v2); addEntropy(v3, v4); } inline void addEntropy(Vertex v1, Vertex v2, Vertex v3, Vertex v4) { addEntropy(v1, v2); addEntropy(v3, v4); }
void initChildren(int n);
void initTriangles(int n);
void addChild(Chose* c); void addChild(Chose* c);
void addTriangle(Triangle* t); void addTriangle(Triangle* t);
virtual void subdivide() = 0; virtual bool subdivide() = 0;
virtual void triangulation() = 0; virtual void triangulation() = 0;
void display();
}; };
std::ostream& operator<<(std::ostream& os, const Chose& r); std::ostream& operator<<(std::ostream& os, const Chose& r);

View File

@ -1,25 +1,23 @@
#include "all_includes.hh" #include "all_includes.hh"
RectangleRoutes::RectangleRoutes(Vertex ne, Vertex sw) : ne(ne), sw(sw) { RectangleRoutes::RectangleRoutes(Vertex ne, Vertex sw) : Chose(), ne(ne), sw(sw) {
addEntropy(ne); addEntropy(ne, sw);
addEntropy(sw); triangulation();
std::cout << this << std::endl;
} }
int RectangleRoutes::width() { return std::abs(this->ne.x - this->sw.x); } int RectangleRoutes::width() { return std::abs(this->ne.x - this->sw.x); }
int RectangleRoutes::height() { return std::abs(this->ne.y - this->sw.y); } int RectangleRoutes::height() { return std::abs(this->ne.y - this->sw.y); }
void RectangleRoutes::subdivide() { bool RectangleRoutes::subdivide() {
initChildren(9); children.reserve(9);
Vertex split( Vertex split(
hashInRange(this->seed, 0, this->sw.x + this->width()*1/4, this->sw.x + this->width()*3/4), hashInRange(this->seed, 0, this->sw.x + this->width()*1/4, this->sw.x + this->width()*3/4),
hashInRange(this->seed, 1, this->sw.y + this->height()*1/4, this->sw.y + this->height()*3/4), hashInRange(this->seed, 1, this->sw.y + this->height()*1/4, this->sw.y + this->height()*3/4),
0 // TODO 0 // TODO
); );
// TODO : addChild(…); // TODO : addChild(…);
new Carrefour(split + Vertex(1,1,0), split + Vertex(1,-1,0), split + Vertex(-1,-1,0), split + Vertex(-1,1,0)); addChild(new Carrefour(split + Vertex(1,1,0), split + Vertex(1,-1,0), split + Vertex(-1,-1,0), split + Vertex(-1,1,0)));
// routes au NESW du carrefour // routes au NESW du carrefour
// TODO : la plupart des zéros en z sont faux… // TODO : la plupart des zéros en z sont faux…
Vertex roadEndN(split.x, this->ne.y, 0); Vertex roadEndN(split.x, this->ne.y, 0);
@ -31,15 +29,20 @@ void RectangleRoutes::subdivide() {
Route* re = new Route(roadEndE + Vertex(0,+1,0), roadEndE + Vertex(0,-1,0), split + Vertex(+1,-1,0), split + Vertex(+1,+1,0)); // E Route* re = new Route(roadEndE + Vertex(0,+1,0), roadEndE + Vertex(0,-1,0), split + Vertex(+1,-1,0), split + Vertex(+1,+1,0)); // E
Route* rs = new Route(roadEndS + Vertex(+1,0,0), roadEndS + Vertex(-1,0,0), split + Vertex(-1,-1,0), split + Vertex(+1,-1,0)); // S Route* rs = new Route(roadEndS + Vertex(+1,0,0), roadEndS + Vertex(-1,0,0), split + Vertex(-1,-1,0), split + Vertex(+1,-1,0)); // S
Route* rw = new Route(roadEndW + Vertex(0,-1,0), roadEndW + Vertex(0,+1,0), split + Vertex(-1,+1,0), split + Vertex(-1,-1,0)); // W Route* rw = new Route(roadEndW + Vertex(0,-1,0), roadEndW + Vertex(0,+1,0), split + Vertex(-1,+1,0), split + Vertex(-1,-1,0)); // W
addChild(rn);
addChild(re);
addChild(rs);
addChild(rw);
// Sous-quartiers // Sous-quartiers
addChild(sub(rn->corners[NE], re->corners[NE])); // sous-quartier NE addChild(sub(rn->corners[NE], re->corners[NE])); // sous-quartier NE
addChild(sub(re->corners[SE], rs->corners[SE])); // sous-quartier SE addChild(sub(re->corners[SE], rs->corners[SE])); // sous-quartier SE
addChild(sub(rs->corners[SW], rw->corners[SW])); // sous-quartier SW addChild(sub(rs->corners[SW], rw->corners[SW])); // sous-quartier SW
addChild(sub(rw->corners[NW], rn->corners[NW])); // sous-quartier NW addChild(sub(rw->corners[NW], rn->corners[NW])); // sous-quartier NW
return true;
} }
void RectangleRoutes::triangulation() { void RectangleRoutes::triangulation() {
initTriangles(2); triangles.reserve(2);
Vertex nw(this->sw.x, this->ne.y, 0); Vertex nw(this->sw.x, this->ne.y, 0);
Vertex se(this->ne.x, this->sw.y, 0); Vertex se(this->ne.x, this->sw.y, 0);
addTriangle(new Triangle(this->sw, nw, this->ne)); addTriangle(new Triangle(this->sw, nw, this->ne));

View File

@ -4,7 +4,7 @@
#include "all_includes.hh" #include "all_includes.hh"
// RectangleRoutes est un quadrilatère de routes avec des angles aux coins égaux à 90°. // RectangleRoutes est un quadrilatère de routes avec des angles aux coins égaux à 90°.
class RectangleRoutes : Chose { class RectangleRoutes : public Chose {
public: public:
Vertex ne; Vertex ne;
Vertex sw; Vertex sw;
@ -12,7 +12,7 @@ public:
RectangleRoutes(Vertex ne, Vertex sw); RectangleRoutes(Vertex ne, Vertex sw);
int width(); int width();
int height(); int height();
virtual void subdivide(); virtual bool subdivide();
virtual void triangulation(); virtual void triangulation();
private: private:
Chose* sub(Vertex ne, Vertex sw); Chose* sub(Vertex ne, Vertex sw);

View File

@ -2,16 +2,17 @@
#include "../vertex.hh" #include "../vertex.hh"
#include "../directions.hh" #include "../directions.hh"
Route::Route(Vertex ne, Vertex se, Vertex sw, Vertex nw) { Route::Route(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Chose() {
corners[NE]=ne; corners[NE]=ne;
corners[SE]=se; corners[SE]=se;
corners[SW]=sw; corners[SW]=sw;
corners[NW]=nw; corners[NW]=nw;
std::cout << this << std::endl; triangulation();
} }
void Route::subdivide() { bool Route::subdivide() {
// TODO // TODO
return false;
} }
std::ostream& operator<<(std::ostream& os, const Route* r) { std::ostream& operator<<(std::ostream& os, const Route* r) {
@ -23,7 +24,7 @@ std::ostream& operator<<(std::ostream& os, const Route& r) {
} }
void Route::triangulation() { void Route::triangulation() {
initTriangles(2); triangles.reserve(2);
addTriangle(new Triangle(corners[SW], corners[NW], corners[NE])); addTriangle(new Triangle(corners[SW], corners[NW], corners[NE]));
addTriangle(new Triangle(corners[SW], corners[SE], corners[NE])); addTriangle(new Triangle(corners[SW], corners[SE], corners[NE]));
} }

View File

@ -3,12 +3,12 @@
#include "all_includes.hh" #include "all_includes.hh"
class Route : Chose { class Route : public Chose {
public: public:
Vertex corners[4]; Vertex corners[4];
public: public:
Route(Vertex ne, Vertex se, Vertex sw, Vertex nw); Route(Vertex ne, Vertex se, Vertex sw, Vertex nw);
virtual void subdivide(); virtual bool subdivide();
virtual void triangulation(); virtual void triangulation();
public: public:
friend std::ostream& operator<<(std::ostream& os, const Route& r); friend std::ostream& operator<<(std::ostream& os, const Route& r);

View File

@ -1,9 +1,21 @@
#include "all_includes.hh" #include "all_includes.hh"
Triangle::Triangle(Vertex a, Vertex b, Vertex c): a(a), b(b), c(c) { Triangle::Triangle(Vertex a, Vertex b, Vertex c): a(a), b(b), c(c) {
std::cout << this << std::endl; // TODO : calcul de la normale.
normal = Vertex(0,0,1);
}
std::ostream& operator<<(std::ostream& os, const Triangle* t) {
return os << *t;
} }
std::ostream& operator<<(std::ostream& os, const Triangle& t) { std::ostream& operator<<(std::ostream& os, const Triangle& t) {
return os << "Triangle " << t.a << "--" << t.b << "--" << t.c << "-- cycle"; return os << "Triangle " << t.a << "--" << t.b << "--" << t.c << "-- cycle";
} }
void Triangle::display() {
glNormal3d(normal.x,normal.y,normal.z);
glVertex3d(a.x,a.y,a.z);
glVertex3d(b.x,b.y,b.z);
glVertex3d(c.x,c.y,c.z);
}

View File

@ -8,9 +8,12 @@ public:
Vertex a; Vertex a;
Vertex b; Vertex b;
Vertex c; Vertex c;
Vertex normal;
public: public:
Triangle(Vertex a, Vertex b, Vertex c); Triangle(Vertex a, Vertex b, Vertex c);
void display();
public: public:
friend std::ostream& operator<<(std::ostream& os, const Triangle* t);
friend std::ostream& operator<<(std::ostream& os, const Triangle& t); friend std::ostream& operator<<(std::ostream& os, const Triangle& t);
}; };

131
view.cpp Normal file
View File

@ -0,0 +1,131 @@
#include "all_includes.hh"
View::View(Chose* root) : root(root), cameraDist(300), xSight(0), ySight(0), zSight(0), xAngle(0), yAngle(0), moveDist(10) {
initWindow();
mainLoop();
}
void View::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;
}
void View::displayAxes() {
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 View::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);
displayAxes();
glBegin(GL_TRIANGLES);
root->display();
glEnd();
glFlush();
SDL_GL_SwapBuffers();
}
void View::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();
}

35
view.hh Normal file
View File

@ -0,0 +1,35 @@
#ifndef _VIEW_HH_
#define _VIEW_HH_
#include "all_includes.hh"
// TODO :
// flycam : le centre ne bouge pas, la souris contrôle l'angle de vue x & y
// les flèches avant/arrière permettent d'avancer/reculer.
// Calcul correct des normales dans triangle.cpp
// Prendre en compte tous les évènements X en attente avant de relancer le rendu.
class View {
private:
Chose* root;
static const int windowWidth = 1024;
static const int windowHeight = 768;
int cameraDist;
int xSight;
int ySight;
int zSight;
float xAngle;
float yAngle;
int moveDist;
public:
View(Chose* root);
void initWindow();
void mainLoop();
void renderScene();
void displayAxes();
};
#endif