commit d84338912130e13f747cf3a752e73256013012a8
parent 9036e2dea0b40eac2c4d07152ca076a692dd547f
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date: Sat, 3 Dec 2011 19:39:28 +0100
QuadRoutes marche, il faut juste pouvoir déplacer un peu les vertex NESW en gardant les contraintes d'angles valides.
Diffstat:
15 files changed, 142 insertions(+), 79 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,8 +1,4 @@
-simple-terrain
-display
-roam
-roads
city
-*.o
-*.d
-.*.d
+all.cpp
+all_includes.hh.d
+all_includes.hh.gch
diff --git a/Makefile b/Makefile
@@ -2,27 +2,27 @@ CXX=g++
# -ansi -pedantic -Wconversion
CCWARN=-Wall -Wextra -Werror
# -flto (nécessite GCC 4.5) -m32 ou -m64
-CFLAGS=-O3 -g3 -I. $(CCWARN)
+CFLAGS=-O0 -I. $(CCWARN)
-OBJECTS = main.o view.o hash.o segment.o vertex.o triangle.o rules/chose.o rules/rectangleroutes.o rules/quadroutes.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/quad.o rules/quadroutes.o rules/route.o rules/carrefour.o rules/batiment.o
LIBS = -lm -lGL -lGLU -lSDL -lGLEW
EXECUTABLE = city
-.PHONY: test
-test: all
- ./$(EXECUTABLE)
-
.PHONY: all
all: $(EXECUTABLE)
+ ./$(EXECUTABLE)
.PHONY: clean
clean:
- rm -f $(EXECUTABLE) $(OBJECTS) $(OBJECTS:.o=.d)
-
-$(EXECUTABLE): $(OBJECTS)
- $(CXX) $(LIBS) $^ -o $@
+ rm -f $(EXECUTABLE) all_includes.hh.d all_includes.hh.gch all.cpp
--include $(OBJECTS:.o=.d)
+$(EXECUTABLE): $(OBJECTS:.o=.cpp) all_includes.hh.gch Makefile
+ @:> all.cpp
+ @$(foreach FILE,$(OBJECTS:.o=.cpp),echo '#include "'"$(FILE)"'"' >> all.cpp;)
+ $(CXX) $(LIBS) $(CFLAGS) all.cpp -o $@
+ @rm all.cpp
-%.o: %.cpp Makefile
- $(CXX) -MMD -MF $(@:.o=.d) -c $< $(CFLAGS) -o $@
+-include all_includes.hh.d
+all_includes.hh.d:
+all_includes.hh.gch: all_includes.hh Makefile
+ $(CXX) $(CFLAGS) -MMD -MF all_includes.hh.d all_includes.hh -o all_includes.hh.gch
diff --git a/README.markdown b/README.markdown
@@ -1,8 +1,8 @@
Minimal requirements
====================
-* imagemagick
-* gcc
+* g++
+* GNU make
How to test this program ?
==========================
diff --git a/all_includes.hh b/all_includes.hh
@@ -1,6 +1,8 @@
#ifndef _ALL_INCLUDES_HH_
#define _ALL_INCLUDES_HH_
+typedef long long int64;
+
class Chose;
#include <iostream>
@@ -21,6 +23,7 @@ class Chose;
#include "view.hh"
#include "rules/chose.hh"
+#include "rules/quad.hh"
#include "rules/batiment.hh"
#include "rules/carrefour.hh"
#include "rules/route.hh"
diff --git a/directions.hh b/directions.hh
@@ -1,18 +1,18 @@
#ifndef _DIRECTIONS_HH_
#define _DIRECTIONS_HH_
-typedef enum Cardinaux {
+typedef enum Cardinal {
N = 0,
E = 1,
S = 2,
W = 3
-} Cardinaux;
+} Cardinal;
-typedef enum Diagonales {
+typedef enum Coin {
NE = 0,
SE = 1,
SW = 2,
NW = 3
-} Diagonales;
+} Coin;
#endif
diff --git a/main.cpp b/main.cpp
@@ -16,11 +16,12 @@ void recursiveSubdivide(Chose* c) {
int main() {
// Générer une tile de base
+ std::cout << "Initial seed = " << Chose::initialSeed << std::endl;
int size = 20000;
Vertex ne(size, size, 0);
Vertex se(size, 0, 0);
Vertex sw(0, 0, 0);
- Vertex nw(0, size, 0);
+ Vertex nw(0, size*2, 0);
Chose* c = new QuadRoutes(ne,se,sw,nw);
// c->subdivide();
recursiveSubdivide(c);
diff --git a/rules/carrefour.cpp b/rules/carrefour.cpp
@@ -1,4 +1,4 @@
-#include "carrefour.hh"
+#include "all_includes.hh"
Carrefour::Carrefour(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Chose(), ne(ne), se(se), sw(sw), nw(nw) {
addEntropy(ne,se,sw,nw);
diff --git a/rules/quad.cpp b/rules/quad.cpp
@@ -0,0 +1,31 @@
+#include "all_includes.hh"
+
+Quad::Quad(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Chose(), ne(ne), se(se), sw(sw), nw(nw) {
+ addEntropy(ne,se,sw,nw);
+ // triangulation();
+}
+
+Vertex& Quad::corner(Coin corner, int rotation) {
+ switch ((corner + rotation) & 3) {
+ case NE: return ne;
+ case SE: return se;
+ case SW: return sw;
+ default: return nw;
+ }
+}
+
+void Quad::offset(/*Cardinal*/int side, int offset) {
+ Vertex voffset = (corner(NE,side)-corner(NW,side)).perpendicular().setNorm(offset);
+ corner(NE,side) = corner(NE,side) + voffset.projectOn(corner(NE,side)-corner(SE,side));
+ corner(NW,side) = corner(NW,side) + voffset.projectOn(corner(NW,side)-corner(SW,side));
+}
+
+bool Quad::subdivide() {
+ return false;
+}
+
+void Quad::triangulation() {
+ triangles.reserve(2);
+ addTriangle(new Triangle(ne, nw, sw, 0xc0, 0xc0, 0xc0));
+ addTriangle(new Triangle(sw, se, ne, 0xc0, 0xc0, 0xc0));
+}
diff --git a/rules/quad.hh b/rules/quad.hh
@@ -0,0 +1,22 @@
+#ifndef _RULES_QUAD_HH_
+#define _RULES_QUAD_HH_
+
+#include "all_includes.hh"
+
+// Quad est un quadrilatère
+class Quad : public Chose {
+public:
+ Vertex ne;
+ Vertex se;
+ Vertex sw;
+ Vertex nw;
+public:
+ Quad(Vertex ne, Vertex se, Vertex sw, Vertex nw);
+ virtual bool subdivide();
+ virtual void triangulation();
+ void offset(/*Cardinal*/int side, int n);
+ Vertex& corner(Coin corner, int rotation);
+};
+
+
+#endif
diff --git a/rules/quadroutes.cpp b/rules/quadroutes.cpp
@@ -22,7 +22,7 @@ bool QuadRoutes::subdivide() {
int xmaxdelta = std::min(minsnlen/4, (minsnlen-minchildsize)/2);
float sxpos = slen/2 + hashInRange(seed, 0, -xmaxdelta, xmaxdelta);
float nxpos = nlen/2 + hashInRange(seed, 0, -xmaxdelta, xmaxdelta);
- Vertex s = (sw * sxpos / slen) + (se * (slen - nxpos) / slen);
+ Vertex s = (sw * sxpos / slen) + (se * (slen - sxpos) / slen);
Vertex n = (nw * nxpos / nlen) + (ne * (nlen - nxpos) / nlen);
int wlen = (nw-sw).norm();
@@ -38,54 +38,44 @@ bool QuadRoutes::subdivide() {
Vertex split = intersection(s,n,w,e);
- // TODO : Pour offset les points des extrémités de la route w--split :
- // Vertex offset = vecteur perpendiculaire w--split, de longueur hrw.
- // Projeter `offset` sur split--n, et ajouter le résultat à split.
- // Projeter `offset` sur w--nw, et ajouter le résultat à w.
-
- // Projeter u sur v : (u scalaire v) / v.norm().
- // scalaire(u,v) = u.norm() * v.norm() * cos(angle(u,v))
- // Donc projeter u sur v : u.norm() * cos(angle(u,v))
- // TODO : comment calculer l'angle(u,v) ?
+ // Créer 4 quad (qne, qse, qsw, qnw), puis :
+ Quad q[4] = {
+ Quad(ne, e, split, n),
+ Quad(se, s, split, e),
+ Quad(sw, w, split, s),
+ Quad(nw, n, split, w),
+ };
+ for (int c = NE; c <= NW; ++c) {
+ q[c].offset(W,-hrw); q[c].offset(S,-hrw);
+ }
- addChild(new Carrefour(split + Vertex(hrw,hrw,0), split + Vertex(hrw,-hrw,0), split + Vertex(-hrw,-hrw,0), split + Vertex(-hrw,hrw,0)));
- // routes au NESW du carrefour
- // TODO : la plupart des zéros en z sont faux…
- Vertex roadEndN(split.x, this->ne.y, 0);
- Vertex roadEndE(this->ne.x, split.y, 0);
- Vertex roadEndS(split.x, this->sw.y, 0);
- Vertex roadEndW(this->sw.x, split.y, 0);
- // TODO : addChild(…);
- Route* rn = new Route(roadEndN + Vertex(+hrw,0,0), split + Vertex(+hrw,+hrw,0), split + Vertex(-hrw,+hrw,0), roadEndN + Vertex(-hrw,0,0)); // N
- Route* re = new Route(roadEndE + Vertex(0,+hrw,0), roadEndE + Vertex(0,-hrw,0), split + Vertex(+hrw,-hrw,0), split + Vertex(+hrw,+hrw,0)); // E
- Route* rs = new Route(split + Vertex(+hrw,-hrw,0), roadEndS + Vertex(+hrw,0,0), roadEndS + Vertex(-hrw,0,0), split + Vertex(-hrw,-hrw,0)); // S
- Route* rw = new Route(split + Vertex(-hrw,+hrw,0), split + Vertex(-hrw,-hrw,0), roadEndW + Vertex(0,-hrw,0), roadEndW + Vertex(0,+hrw,0)); // W
- addChild(rn);
- addChild(re);
- addChild(rs);
- addChild(rw);
- // Sous-quartiers
- addChild(sub(ne, re->nw)); // sous-quartier NE
- addChild(sub(re->se, rs->se)); // sous-quartier SE
- addChild(sub(rs->nw, sw)); // sous-quartier SW
- addChild(sub(rn->nw, rw->nw)); // sous-quartier NW
+ addChild(new Carrefour(q[NE].sw, q[SE].sw, q[SW].sw, q[NW].sw));
+ addChild(new Route(q[NW].se, q[NE].nw, q[NE].sw, q[NW].sw));
+ addChild(new Route(q[NE].se, q[SE].nw, q[SE].sw, q[NE].sw));
+ addChild(new Route(q[SE].se, q[SW].nw, q[SW].sw, q[SE].sw));
+ addChild(new Route(q[SW].se, q[NW].nw, q[NW].sw, q[SW].sw));
+ addChild(sub(q[NE].ne, q[NE].se, q[NE].sw, q[NE].nw));
+ addChild(sub(q[SE].ne, q[SE].se, q[SE].sw, q[SE].nw));
+ addChild(sub(q[SW].ne, q[SW].se, q[SW].sw, q[SW].nw));
+ addChild(sub(q[NW].ne, q[NW].se, q[NW].sw, q[NW].nw));
+
return true;
}
void QuadRoutes::triangulation() {
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->ne, nw, this->sw, 0xc0, 0xc0, 0xc0));
- addTriangle(new Triangle(this->sw, se, this->ne, 0xc0, 0xc0, 0xc0));
+ addTriangle(new Triangle(ne, nw, sw, 0xc0, 0xc0, 0xc0));
+ addTriangle(new Triangle(sw, se, ne, 0xc0, 0xc0, 0xc0));
}
-Chose* QuadRoutes::sub(Vertex ne, Vertex sw) {
- Segment rect = Segment(ne,sw);
- if (rect.width() < minQuadSize || rect.height() < minQuadSize) {
- return new Batiment(ne, Vertex(ne.x, sw.y, 0), sw, Vertex(sw.x, ne.y, 0));
+Chose* QuadRoutes::sub(Vertex ne, Vertex se, Vertex sw, Vertex nw) {
+ if ((ne - se).norm() < minQuadSize ||
+ (se - sw).norm() < minQuadSize ||
+ (sw - nw).norm() < minQuadSize ||
+ (nw - ne).norm() < minQuadSize) {
+ return new Batiment(ne, se, sw, nw);
} else {
- return new QuadRoutes(ne, Vertex(ne.x, sw.y, 0), sw, Vertex(sw.x, ne.y, 0));
+ return new QuadRoutes(ne, se, sw, nw);
}
}
diff --git a/rules/quadroutes.hh b/rules/quadroutes.hh
@@ -23,7 +23,7 @@ public:
friend std::ostream& operator<<(std::ostream& os, const QuadRoutes& r);
friend std::ostream& operator<<(std::ostream& os, const QuadRoutes* r);
private:
- Chose* sub(Vertex ne, Vertex sw);
+ Chose* sub(Vertex ne, Vertex se, Vertex sw, Vertex nw);
};
diff --git a/rules/route.cpp b/rules/route.cpp
@@ -1,6 +1,4 @@
-#include "route.hh"
-#include "../vertex.hh"
-#include "../directions.hh"
+#include "all_includes.hh"
Route::Route(Vertex ne, Vertex se, Vertex sw, Vertex nw) : Chose(), ne(ne), se(se), sw(sw), nw(nw) {
triangulation();
diff --git a/vertex.cpp b/vertex.cpp
@@ -11,11 +11,11 @@ Vertex intersection(Vertex a, Vertex b, Vertex c, Vertex d) {
// Note : si les deux lignes sont parallèles, on risque fort
// d'avoir une division par zéro.
// http://en.wikipedia.org/wiki/Line-line_intersection
- long long x1 = a.x; long long y1 = a.y;
- long long x2 = b.x; long long y2 = b.y;
- long long x3 = c.x; long long y3 = c.y;
- long long x4 = d.x; long long y4 = d.y;
- long long denominator = ((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4));
+ int64 x1 = a.x; int64 y1 = a.y;
+ int64 x2 = b.x; int64 y2 = b.y;
+ int64 x3 = c.x; int64 y3 = c.y;
+ int64 x4 = d.x; int64 y4 = d.y;
+ int64 denominator = ((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4));
return Vertex(
((x1*y2-y1*x2)*(x3-x4) - (x1-x2)*(x3*y4-y3*x4)) / denominator,
((x1*y2-y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4)) / denominator,
@@ -23,6 +23,23 @@ Vertex intersection(Vertex a, Vertex b, Vertex c, Vertex d) {
);
}
+Vertex Vertex::projectOn(Vertex v) {
+ // http://www.developpez.net/forums/d202580/applications/developpement-2d-3d-jeux/contribuez/faq-mat-quat-ajout-calculs-vectoriels/
+ int64 scalaire = this->x*v.x + this->y*v.y;
+ int64 normecarre = v.norm();
+ normecarre *= normecarre;
+ return Vertex(((int64)v.x) * scalaire / normecarre, ((int64)v.y) * scalaire / normecarre, 0);
+}
+
+Vertex Vertex::setNorm(int n) {
+ int64 current = norm();
+ return Vertex((int64)x * (int64)n / current, (int64)y * (int64)n / current, 0);
+}
+
+Vertex Vertex::perpendicular() {
+ return Vertex(-y, x, 0);
+}
+
Vertex::operator Vertexf() { return Vertexf(x,y,z); }
std::ostream& operator<<(std::ostream& os, const Vertex& v) {
diff --git a/vertex.hh b/vertex.hh
@@ -14,6 +14,9 @@ class Vertex {
Vertex();
Vertex(int x, int y, int z);
float norm();
+ Vertex projectOn(Vertex v);
+ Vertex setNorm(int n);
+ Vertex perpendicular(); // Perpendiculaire 2D dans le sens contraire des aiguilles d'une montre.
static Vertex fromSpherical(float r, float xAngle, float yAngle);
friend Vertex intersection(Vertex a, Vertex b, Vertex c, Vertex d); // Intersection entre (a,b) et (c,d).
diff --git a/view.cpp b/view.cpp
@@ -1,6 +1,7 @@
#include "all_includes.hh"
-View::View(Chose* root) : root(root), camera(Camera(Vertexf(1000,1000,2000),45,100,1000,0.6)) {
+// camera(Camera(Vertexf(1000,1000,2000),45,100,1000,0.6)
+View::View(Chose* root) : root(root), camera(Camera(Vertexf(13126,19103,30539),90,179,1000,0.6)) {
initWindow();
mainLoop();
}
@@ -27,7 +28,7 @@ void View::initWindow() {
float MatSpec[4] = {0.0f, 0.0f, 0.0f, 1.0f};
float MatDif[4] = {0.5f, 0.5f, 0.5f, 1.0f};
- float MatAmb[4] = {0.4f, 0.4f, 0.4f, 1.0f};
+ float MatAmb[4] = {0.3f, 0.3f, 0.6f, 1.0f};
float shininess = 128.0f;
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,MatSpec);
@@ -157,6 +158,7 @@ void Camera::setCamera() {
void Camera::mouseMotion(const SDL_MouseMotionEvent &event) {
xAngle -= event.xrel*mouseSensitivity;
yAngle += event.yrel*mouseSensitivity;
+ xAngle = std::fmod(xAngle + 360, 360);
if(yAngle > 179)
yAngle = 179;
else if(yAngle < 1)