commit 61ea30e35dbd1a7f63c9a92c142f99ef14df0c07
parent 11f2948558ddf63b8af2c60ae500a6f9329b50d1
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date: Sat, 3 Dec 2011 00:51:06 +0100
Améliorations sur QuadRoutes, utilisation du cm comme unité de base.
Diffstat:
11 files changed, 136 insertions(+), 62 deletions(-)
diff --git a/main.cpp b/main.cpp
@@ -16,12 +16,13 @@ void recursiveSubdivide(Chose* c) {
int main() {
// Générer une tile de base
- int size = 50;
+ int size = 20000;
Vertex ne(size, size, 0);
Vertex se(size, 0, 0);
Vertex sw(0, 0, 0);
Vertex nw(0, size, 0);
Chose* c = new QuadRoutes(ne,se,sw,nw);
+ // c->subdivide();
recursiveSubdivide(c);
new View(c);
diff --git a/rules/batiment.cpp b/rules/batiment.cpp
@@ -17,12 +17,13 @@ bool Batiment::subdivide() {
void Batiment::triangulation() {
triangles.reserve(12);
- int h = hashInRange(seed,0,4,8);
+ int h = hashInRange(seed,0,minHeight,maxHeight);
+ int htoit = hashInRange(seed,0,minHeight/2,maxHeight/2);
Vertex neh = ne + Vertex(0,0,h);
Vertex seh = se + Vertex(0,0,h);
Vertex nwh = nw + Vertex(0,0,h);
Vertex swh = sw + Vertex(0,0,h);
- Vertex toit = (neh + seh + nwh + swh) / 4 + Vertex(0,0,h/2);
+ Vertex toit = (neh + seh + nwh + swh) / 4 + Vertex(0,0,htoit);
// 4 Murs
addTriangle(new Triangle(neh,seh,ne,0xf1,0xe3,0xad)); addTriangle(new Triangle(seh,se,ne,0xf1,0xe3,0xad)); // ne-se-seh-neh
diff --git a/rules/batiment.hh b/rules/batiment.hh
@@ -11,6 +11,9 @@ public:
Vertex sw;
Vertex nw;
public:
+ static const int minHeight = 400;
+ static const int maxHeight = 800;
+public:
Batiment(Vertex ne, Vertex se, Vertex sw, Vertex nw);
int width();
int height();
diff --git a/rules/carrefour.cpp b/rules/carrefour.cpp
@@ -20,6 +20,6 @@ std::ostream& operator<<(std::ostream& os, const Carrefour& c) {
void Carrefour::triangulation() {
triangles.reserve(2);
- addTriangle(new Triangle(ne, nw, sw, 0x80, 0x80, 0x80));
- addTriangle(new Triangle(sw, se, ne, 0x80, 0x80, 0x80));
+ addTriangle(new Triangle(ne, nw, sw, 0x36, 0x36, 0x36));
+ addTriangle(new Triangle(sw, se, ne, 0x36, 0x36, 0x36));
}
diff --git a/rules/quadroutes.cpp b/rules/quadroutes.cpp
@@ -11,25 +11,44 @@ int QuadRoutes::height() { return std::abs(this->ne.y - this->sw.y); }
bool QuadRoutes::subdivide() {
children.reserve(9);
- int minchildsize = 4;
- int lx = std::floor(std::min((nw-ne).norm(), (sw-se).norm()));
- // constraint: lx - maxdelta*2 ≥ minchildsize
- // constraint: maxdelta ≤ lx/4
- int maxdelta = std::min(lx/4, (lx-minchildsize)/2);
- float xpos = (lx/2.f + hashInRange(seed, 0, -maxdelta, maxdelta)) / (float)lx; // xpos \in 0..1
- Vertex n = nw * xpos + ne * (1-xpos);
+
+ // TODO : faire ces calculs sur des Vertex2d.
- int splitXMin = this->sw.x + std::max(4, this->width()*1/4);
- int splitXMax = this->ne.x - std::max(4, this->width()*1/4);
- int splitYMin = this->sw.y + std::max(4, this->height()*1/4);
- int splitYMax = this->ne.y - std::max(4, this->height()*1/4);
- Vertex split(
- hashInRange(this->seed, 0, splitXMin, splitXMax),
- hashInRange(this->seed, 1, splitYMin, splitYMax),
- 0 // TODO
- );
- // TODO : addChild(…);
- addChild(new Carrefour(split + Vertex(1,1,0), split + Vertex(1,-1,0), split + Vertex(-1,-1,0), split + Vertex(-1,1,0)));
+ int slen = (se-sw).norm();
+ int nlen = (ne-nw).norm();
+ int minsnlen = std::min(slen,nlen);
+ // constraint: min(slen, nlen) - maxdelta*2 ≥ minchildsize
+ // constraint: maxdelta ≤ min(slen,nlen)/4
+ 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 n = (nw * nxpos / nlen) + (ne * (nlen - nxpos) / nlen);
+
+ int wlen = (nw-sw).norm();
+ int elen = (ne-se).norm();
+ int minwelen = std::min(wlen,elen);
+ // constraint: min(wlen, elen) - maxdelta*2 ≥ minchildsize
+ // constraint: maxdelta ≤ min(wlen,elen)/4
+ int ymaxdelta = std::min(minwelen/4, (minwelen-minchildsize)/2);
+ float wypos = wlen/2 + hashInRange(seed, 0, -ymaxdelta, ymaxdelta);
+ float eypos = elen/2 + hashInRange(seed, 0, -ymaxdelta, ymaxdelta);
+ Vertex w = (nw * wypos / wlen) + (sw * (wlen - wypos) / wlen);
+ Vertex e = (ne * eypos / elen) + (se * (elen - eypos) / elen);
+
+ 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) ?
+
+ 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);
@@ -37,10 +56,10 @@ bool QuadRoutes::subdivide() {
Vertex roadEndS(split.x, this->sw.y, 0);
Vertex roadEndW(this->sw.x, split.y, 0);
// TODO : addChild(…);
- Route* rn = new Route(roadEndN + Vertex(+1,0,0), split + Vertex(+1,+1,0), split + Vertex(-1,+1,0), roadEndN + Vertex(-1,0,0)); // N
- 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(split + Vertex(+1,-1,0), roadEndS + Vertex(+1,0,0), roadEndS + Vertex(-1,0,0), split + Vertex(-1,-1,0)); // S
- Route* rw = new Route(split + Vertex(-1,+1,0), split + Vertex(-1,-1,0), roadEndW + Vertex(0,-1,0), roadEndW + Vertex(0,+1,0)); // W
+ 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);
@@ -63,7 +82,7 @@ void QuadRoutes::triangulation() {
Chose* QuadRoutes::sub(Vertex ne, Vertex sw) {
Segment rect = Segment(ne,sw);
- if (rect.width() < 10 || rect.height() < 10) {
+ if (rect.width() < minQuadSize || rect.height() < minQuadSize) {
return new Batiment(ne, Vertex(ne.x, sw.y, 0), sw, Vertex(sw.x, ne.y, 0));
} else {
return new QuadRoutes(ne, Vertex(ne.x, sw.y, 0), sw, Vertex(sw.x, ne.y, 0));
diff --git a/rules/quadroutes.hh b/rules/quadroutes.hh
@@ -11,16 +11,19 @@ public:
Vertex sw;
Vertex nw;
public:
+ static const int hrw = 250; // half road width : 2,50m.
+ static const int minchildsize = 1000;
+ static const int minQuadSize = 2500;
+public:
QuadRoutes(Vertex ne, Vertex se, Vertex sw, Vertex nw);
int width();
int height();
virtual bool subdivide();
virtual void triangulation();
-private:
- Chose* sub(Vertex ne, Vertex sw);
-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);
};
diff --git a/rules/route.cpp b/rules/route.cpp
@@ -21,6 +21,6 @@ std::ostream& operator<<(std::ostream& os, const Route& r) {
void Route::triangulation() {
triangles.reserve(2);
- addTriangle(new Triangle(ne, nw, sw, 0x6c, 0x6c, 0x6c));
- addTriangle(new Triangle(sw, se, ne, 0x6c, 0x6c, 0x6c));
+ addTriangle(new Triangle(ne, nw, sw, 0x36, 0x36, 0x36));
+ addTriangle(new Triangle(sw, se, ne, 0x36, 0x36, 0x36));
}
diff --git a/triangle.cpp b/triangle.cpp
@@ -14,25 +14,8 @@ std::ostream& operator<<(std::ostream& os, const Triangle& t) {
}
Vertexf Triangle::normalVector(Vertex v1, Vertex v2, Vertex v3) {
- int ax = v1.x - v2.x;
- int ay = v1.y - v2.y;
- int az = v1.z - v2.z;
- int bx = v2.x - v3.x;
- int by = v2.y - v3.y;
- int bz = v2.z - v3.z;
-
- Vertexf normal;
-
- 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);
-
- normal.x = x/length;
- normal.y = y/length;
- normal.z = z/length;
-
- return normal;
+ Vertexf normal = (v1 - v2)*(v2 - v3);
+ return normal / normal.norm();
}
void Triangle::display() {
@@ -41,16 +24,16 @@ void Triangle::display() {
// glBegin(GL_LINES);
// glColor3ub(255,255,0);
// Vertex v = (v1 + v2 + v3) / 3;
- // glVertex3d(v.x*10,v.y*10,v.z*10);
- // glVertex3d(v.x*10+normal.x*50,v.y*10+normal.y*50,v.z*10+normal.z*50);
+ // glVertex3d(v.x,v.y,v.z);
+ // glVertex3d(v.x+normal.x*50,v.y+normal.y*50,v.z+normal.z*50);
// glEnd( );
// glEnable(GL_LIGHTING);
View::setColor(r,g,b);
glNormal3d(normal.x,normal.y,normal.z);
- glBegin(GL_TRIANGLES);
- glVertex3d(v1.x*10,v1.y*10,v1.z*10);
- glVertex3d(v2.x*10,v2.y*10,v2.z*10);
- glVertex3d(v3.x*10,v3.y*10,v3.z*10);
- glEnd();
+ // glBegin(GL_TRIANGLES);
+ glVertex3d(v1.x,v1.y,v1.z);
+ glVertex3d(v2.x,v2.y,v2.z);
+ glVertex3d(v3.x,v3.y,v3.z);
+ // glEnd();
}
diff --git a/vertex.cpp b/vertex.cpp
@@ -6,6 +6,25 @@ Vertex::Vertex(int x, int y, int z): x(x), y(y), z(z) {}
float Vertex::norm() { return std::sqrt(x*x + y*y + z*z); }
+// TODO : this is 2D only, use Vertex2d.
+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));
+ 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,
+ 0
+ );
+}
+
+Vertex::operator Vertexf() { return Vertexf(x,y,z); }
+
std::ostream& operator<<(std::ostream& os, const Vertex& v) {
return os << "(" << v.x << "," << v.y << "," << v.z << ")";
}
@@ -34,10 +53,22 @@ Vertex operator*(const Vertex& v, const int n) {
return Vertex(v.x * n, v.y * n, v.z * n);
}
+Vertex operator*(const Vertex& u, const Vertex& v) {
+ return Vertex(
+ (u.y * v.z) - (u.z * v.y),
+ (u.z * v.x) - (u.x * v.z),
+ (u.x * v.y) - (u.y * v.x)
+ );
+}
+
Vertex operator/(const Vertex& v, const int n) {
return Vertex(v.x / n, v.y / n, v.z / n);
}
+Vertex operator/(const Vertex& v, const float f) {
+ return Vertex(v.x / f, v.y / f, v.z / f);
+}
+
Vertex Vertex::fromSpherical(float r, float xAngle, float yAngle) {
// http://electron9.phys.utk.edu/vectors/3dcoordinates.htm
return Vertex(
@@ -56,6 +87,8 @@ Vertexf::Vertexf(float x, float y, float z): x(x), y(y), z(z) {}
float Vertexf::norm() { return std::sqrt(x*x + y*y + z*z); }
+Vertexf::operator Vertex() { return Vertex(x,y,z); }
+
std::ostream& operator<<(std::ostream& os, const Vertexf& v) {
return os << "(" << v.x << "," << v.y << "," << v.z << ")";
}
@@ -84,10 +117,22 @@ Vertexf operator*(const Vertexf& v, const int n) {
return Vertexf(v.x * n, v.y * n, v.z * n);
}
+Vertexf operator*(const Vertexf& u, const Vertexf& v) {
+ return Vertexf(
+ (u.y * v.z) - (u.z * v.y),
+ (u.z * v.x) - (u.x * v.z),
+ (u.x * v.y) - (u.y * v.x)
+ );
+}
+
Vertexf operator/(const Vertexf& v, const int n) {
return Vertexf(v.x / n, v.y / n, v.z / n);
}
+Vertexf operator/(const Vertexf& v, const float f) {
+ return Vertexf(v.x / f, v.y / f, v.z / f);
+}
+
Vertexf Vertexf::fromSpherical(float r, float xAngle, float yAngle) {
// http://electron9.phys.utk.edu/vectors/3dcoordinates.htm
return Vertexf(
diff --git a/vertex.hh b/vertex.hh
@@ -15,14 +15,18 @@ class Vertex {
Vertex(int x, int y, int z);
float norm();
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).
public:
+ operator Vertexf();
friend std::ostream& operator<<(std::ostream& os, const Vertex& v);
friend Vertex operator+(const Vertex& u, const Vertex& v);
friend Vertex operator-(const Vertex& u, const Vertex& v);
friend Vertex operator-(const Vertex& v);
friend Vertex operator*(const Vertex& v, const int n);
+ friend Vertex operator*(const Vertex& u, const Vertex& v);
friend Vertex operator/(const Vertex& v, const int n);
+ friend Vertex operator/(const Vertex& v, const float f);
friend Vertex operator+(const Vertex& u, const Vertexf& v);
friend Vertex operator-(const Vertex& u, const Vertexf& v);
};
@@ -40,12 +44,15 @@ class Vertexf {
static Vertexf fromSpherical(float r, float xAngle, float yAngle);
public:
+ operator Vertex();
friend std::ostream& operator<<(std::ostream& os, const Vertexf& v);
friend Vertexf operator+(const Vertexf& u, const Vertexf& v);
friend Vertexf operator-(const Vertexf& u, const Vertexf& v);
friend Vertexf operator-(const Vertexf& v);
friend Vertexf operator*(const Vertexf& v, const int n);
+ friend Vertexf operator*(const Vertexf& u, const Vertexf& v);
friend Vertexf operator/(const Vertexf& v, const int n);
+ friend Vertexf operator/(const Vertexf& v, const float f);
friend Vertexf operator+(const Vertexf& u, const Vertex& v);
friend Vertexf operator-(const Vertexf& u, const Vertex& v);
};
diff --git a/view.cpp b/view.cpp
@@ -1,6 +1,6 @@
#include "all_includes.hh"
-View::View(Chose* root) : root(root), camera(Camera(Vertexf(420,468,151),230,108,40,0.6)) {
+View::View(Chose* root) : root(root), camera(Camera(Vertexf(1000,1000,2000),45,100,1000,0.6)) {
initWindow();
mainLoop();
}
@@ -21,7 +21,7 @@ void View::initWindow() {
SDL_SetVideoMode(windowWidth, windowHeight, 32, SDL_OPENGL);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
- gluPerspective(70,(double)windowWidth/windowHeight,1,10000);
+ gluPerspective(70,(double)windowWidth/windowHeight,1,100000); // back frustum : 1km
glEnable(GL_DEPTH_TEST);
glewInit();
@@ -40,7 +40,7 @@ void View::initWindow() {
}
void View::setLight() {
- float Light1Pos[4] = {0.5f, 1.0f, 1.0f, 0.0f};
+ float Light1Pos[4] = {-0.5f, -1.0f, 1.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.2f, 0.2f, 0.2f, 1.0f};
@@ -88,7 +88,9 @@ void View::renderScene(int lastTime, int currentTime) {
setLight();
//displayAxes();
+ glBegin(GL_TRIANGLES);
root->display();
+ glEnd();
glFlush();
SDL_GL_SwapBuffers();
@@ -189,8 +191,18 @@ void Camera::keyboard(const SDL_KeyboardEvent &eventKey) {
case 'q':
exit(0);
break;
+ case 's':
+ if (eventKey.type != SDL_KEYDOWN) break;
+ moveDist = std::min(50000,std::max(moveDist+1, moveDist*10/9));
+ break;
+ case 'x':
+ if (eventKey.type != SDL_KEYDOWN) break;
+ moveDist = std::max(10, moveDist*9/10);
+ break;
case 'p': // _Print _Position
+ if (eventKey.type != SDL_KEYDOWN) break;
std::cout << *this << std::endl;
+ break;
default:
break;
}