commit 0d467384f3cf7b5543cb3c7e75a478558e41bd0e
parent f5cc3dc243b1d2be7e736f5156edcd73b020f13d
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date: Mon, 28 Nov 2011 11:42:44 +0100
Premier affichage 3D.
Diffstat:
17 files changed, 258 insertions(+), 49 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,7 +4,8 @@ CCWARN=-Wall -Wextra -Werror
# -flto (nécessite GCC 4.5) -m32 ou -m64
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
.PHONY: test
@@ -18,8 +19,8 @@ all: $(EXECUTABLE)
clean:
rm -f $(EXECUTABLE) $(OBJECTS) $(OBJECTS:.o=.d)
-city: $(OBJECTS)
- $(CXX) -lm $^ -o $@
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) $(LIBS) $^ -o $@
-include $(OBJECTS:.o=.d)
diff --git a/all_includes.hh b/all_includes.hh
@@ -8,11 +8,17 @@ class Chose;
#include <cmath>
#include <vector>
+#include <SDL/SDL.h>
+#include <GL/glew.h>
+#include <GL/glu.h>
+#include <GL/gl.h>
+
#include "vertex.hh"
#include "segment.hh"
#include "triangle.hh"
#include "directions.hh"
#include "hash.hh"
+#include "view.hh"
#include "rules/chose.hh"
#include "rules/batiment.hh"
diff --git a/main.cpp b/main.cpp
@@ -1,18 +1,27 @@
#include "all_includes.hh"
-// TODO : bâtiments.
-// TODO : split route en 2 triangles.
// TODO : split bâtiment en faces, puis en triangles.
// 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 : 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() {
// Générer une tile de base
- Vertex ne(100, 100, 0);
+ Vertex ne(1000, 1000, 0);
Vertex sw(0, 0, 0);
- RectangleRoutes r(ne, sw);
- r.subdivide();
+ RectangleRoutes* r = new RectangleRoutes(ne, sw);
+ recursiveSubdivide(r);
+
+ new View(r);
// tile.subdivide tant qu'on n'a pas le niveau de détail désiré.
return 0;
}
diff --git a/rules/batiment.cpp b/rules/batiment.cpp
@@ -1,19 +1,21 @@
#include "all_includes.hh"
-Batiment::Batiment(Vertex ne, Vertex sw) : ne(ne), sw(sw) {
- std::cout << this << std::endl;
+Batiment::Batiment(Vertex ne, Vertex sw) : Chose(), ne(ne), sw(sw) {
+ addEntropy(ne, sw);
+ triangulation();
}
int Batiment::width() { return this->ne.x - this->sw.x; }
int Batiment::height() { return this->ne.y - this->sw.y; }
-void Batiment::subdivide() {
+bool Batiment::subdivide() {
// TODO : rien ?
+ return false;
}
void Batiment::triangulation() {
- initTriangles(12);
+ triangles.reserve(12);
// abcd sont les quatre coins du bâtiment.
Vertex a = this->ne;
diff --git a/rules/batiment.hh b/rules/batiment.hh
@@ -13,7 +13,7 @@ public:
Batiment(Vertex ne, Vertex sw);
int width();
int height();
- virtual void subdivide();
+ virtual bool subdivide();
virtual void triangulation();
};
diff --git a/rules/carrefour.cpp b/rules/carrefour.cpp
@@ -1,15 +1,16 @@
#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[SE]=se;
corners[SW]=sw;
corners[NW]=nw;
- std::cout << this << std::endl;
+ triangulation();
}
-void Carrefour::subdivide() {
+bool Carrefour::subdivide() {
// TODO
+ return false;
}
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() {
- initTriangles(2);
+ triangles.reserve(2);
addTriangle(new Triangle(corners[SW], corners[NW], corners[NE]));
addTriangle(new Triangle(corners[SW], corners[SE], corners[NE]));
}
diff --git a/rules/carrefour.hh b/rules/carrefour.hh
@@ -3,12 +3,12 @@
#include "all_includes.hh"
-class Carrefour : Chose {
+class Carrefour : public Chose {
public:
Vertex corners[4];
public:
Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw);
- virtual void subdivide();
+ virtual bool subdivide();
virtual void triangulation();
public:
friend std::ostream& operator<<(std::ostream& os, const Carrefour& c);
diff --git a/rules/chose.cpp b/rules/chose.cpp
@@ -1,6 +1,6 @@
#include "all_includes.hh"
-Chose::Chose() : seed(initialSeed) {}
+Chose::Chose() : seed(initialSeed), children() {}
std::ostream& operator<<(std::ostream& os, const Chose* r) {
return os << *r;
@@ -11,14 +11,6 @@ std::ostream& operator<<(std::ostream& os, const Chose& r) {
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) {
children.push_back(c);
// 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);
// 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();
+ }
+ }
+}
diff --git a/rules/chose.hh b/rules/chose.hh
@@ -20,12 +20,11 @@ public:
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, Vertex v4) { addEntropy(v1, v2); addEntropy(v3, v4); }
- void initChildren(int n);
- void initTriangles(int n);
void addChild(Chose* c);
void addTriangle(Triangle* t);
- virtual void subdivide() = 0;
+ virtual bool subdivide() = 0;
virtual void triangulation() = 0;
+ void display();
};
std::ostream& operator<<(std::ostream& os, const Chose& r);
diff --git a/rules/rectangleroutes.cpp b/rules/rectangleroutes.cpp
@@ -1,25 +1,23 @@
#include "all_includes.hh"
-RectangleRoutes::RectangleRoutes(Vertex ne, Vertex sw) : ne(ne), sw(sw) {
- addEntropy(ne);
- addEntropy(sw);
- std::cout << this << std::endl;
+RectangleRoutes::RectangleRoutes(Vertex ne, Vertex sw) : Chose(), ne(ne), sw(sw) {
+ addEntropy(ne, sw);
+ triangulation();
}
int RectangleRoutes::width() { return std::abs(this->ne.x - this->sw.x); }
int RectangleRoutes::height() { return std::abs(this->ne.y - this->sw.y); }
-void RectangleRoutes::subdivide() {
- initChildren(9);
-
+bool RectangleRoutes::subdivide() {
+ children.reserve(9);
Vertex split(
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),
0 // TODO
);
// 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
// TODO : la plupart des zéros en z sont faux…
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* 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
+ addChild(rn);
+ addChild(re);
+ addChild(rs);
+ addChild(rw);
// Sous-quartiers
addChild(sub(rn->corners[NE], re->corners[NE])); // sous-quartier NE
addChild(sub(re->corners[SE], rs->corners[SE])); // sous-quartier SE
addChild(sub(rs->corners[SW], rw->corners[SW])); // sous-quartier SW
addChild(sub(rw->corners[NW], rn->corners[NW])); // sous-quartier NW
+ return true;
}
void RectangleRoutes::triangulation() {
- initTriangles(2);
+ triangles.reserve(2);
Vertex nw(this->sw.x, this->ne.y, 0);
Vertex se(this->ne.x, this->sw.y, 0);
addTriangle(new Triangle(this->sw, nw, this->ne));
diff --git a/rules/rectangleroutes.hh b/rules/rectangleroutes.hh
@@ -4,7 +4,7 @@
#include "all_includes.hh"
// RectangleRoutes est un quadrilatère de routes avec des angles aux coins égaux à 90°.
-class RectangleRoutes : Chose {
+class RectangleRoutes : public Chose {
public:
Vertex ne;
Vertex sw;
@@ -12,7 +12,7 @@ public:
RectangleRoutes(Vertex ne, Vertex sw);
int width();
int height();
- virtual void subdivide();
+ virtual bool subdivide();
virtual void triangulation();
private:
Chose* sub(Vertex ne, Vertex sw);
diff --git a/rules/route.cpp b/rules/route.cpp
@@ -2,16 +2,17 @@
#include "../vertex.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[SE]=se;
corners[SW]=sw;
corners[NW]=nw;
- std::cout << this << std::endl;
+ triangulation();
}
-void Route::subdivide() {
+bool Route::subdivide() {
// TODO
+ return false;
}
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() {
- initTriangles(2);
+ triangles.reserve(2);
addTriangle(new Triangle(corners[SW], corners[NW], corners[NE]));
addTriangle(new Triangle(corners[SW], corners[SE], corners[NE]));
}
diff --git a/rules/route.hh b/rules/route.hh
@@ -3,12 +3,12 @@
#include "all_includes.hh"
-class Route : Chose {
+class Route : public Chose {
public:
Vertex corners[4];
public:
Route(Vertex ne, Vertex se, Vertex sw, Vertex nw);
- virtual void subdivide();
+ virtual bool subdivide();
virtual void triangulation();
public:
friend std::ostream& operator<<(std::ostream& os, const Route& r);
diff --git a/triangle.cpp b/triangle.cpp
@@ -1,9 +1,21 @@
#include "all_includes.hh"
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) {
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);
+}
diff --git a/triangle.hh b/triangle.hh
@@ -8,9 +8,12 @@ public:
Vertex a;
Vertex b;
Vertex c;
+ Vertex normal;
public:
Triangle(Vertex a, Vertex b, Vertex c);
+ void display();
public:
+ friend std::ostream& operator<<(std::ostream& os, const Triangle* t);
friend std::ostream& operator<<(std::ostream& os, const Triangle& t);
};
diff --git a/view.cpp b/view.cpp
@@ -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();
+}
diff --git a/view.hh b/view.hh
@@ -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