commit 8db867a1046322d63c436a8ecced4dc672325ea4
parent 4b258d1cc6db22cd968c8049fd6588765e859173
Author: Georges Dupéron <jahvascriptmaniac+github@free.fr>
Date: Fri, 20 Jan 2012 13:46:24 +0100
Subdivision bâtiments triangulaires.
Diffstat:
14 files changed, 239 insertions(+), 45 deletions(-)
diff --git a/geometry/triangle.hh b/geometry/triangle.hh
@@ -41,4 +41,29 @@ public :
Triangle insetProportionnal(float prop);
};
+class TriBool {
+ private:
+ bool c[3];
+
+ public :
+ TriBool();
+ TriBool(bool leftside, bool rightside, bool base) {
+ c[LEFTSIDE] = leftside;
+ c[RIGHTSIDE] = rightside;
+ c[BASE] = base;
+ };
+ inline bool& operator[] (CoteTriangle x) {
+ return c[x];
+ }
+ inline const bool& operator[] (CoteTriangle x) const {
+ return c[x];
+ }
+ inline TriBool operator>> (int rot) const {
+ return TriBool(c[LEFTSIDE - rot], c[RIGHTSIDE - rot], c[BASE - rot]);
+ }
+ inline TriBool operator<< (int rot) const {
+ return TriBool(c[LEFTSIDE + rot], c[RIGHTSIDE + rot], c[BASE + rot]);
+ }
+};
+
#endif
diff --git a/rules/batiment.cpp b/rules/batiment.cpp
@@ -63,7 +63,6 @@ void BatimentQuad::sousBatiments() {
}
void BatimentQuad::etages() {
- // TODO : indiquer aux bâtiments où est-ce qu'ils peuvent faire des fenêtres.
float randEtages = floatInRange(seed, 0, 0.f, 1.f);
int nbEtages = 1 + (int)(randEtages * randEtages * (Dimensions::maxEtages - 1));
Quad q = c; // c.insetNESW(30)
@@ -91,21 +90,92 @@ void BatimentQuad::getBoundingBoxPoints() {
addBBPoints(c, Dimensions::hauteurEtage * 2 + Dimensions::hauteurToit);
}
-BatimentTri_::BatimentTri_(Triangle _c) : Chose(), c(_c) {
+BatimentTri::BatimentTri(Triangle _c, bool _isSub, TriBool _w)
+ : Chose(), c(_c), isSub(_isSub), w(_w) {
addEntropy(c);
+ for (int i = 0; i < 3; i++)
+ addEntropy(w[LEFTSIDE+i] ? 0 : 1);
}
-void BatimentTri_::split() {
- // TODO : BatimentTri::split()
+void BatimentTri::split() {
+ if (!isSub) {
+ bordureRouteTrottoir();
+ } else {
+ if (w[LEFTSIDE] || w[RIGHTSIDE] || w[BASE]) {
+ if (c.surface() > 2 * Dimensions::minSurfaceSousBatiment) {
+ sousBatiments();
+ } else {
+ etages();
+ }
+ } else {
+ addChild(new TerrainTri(c));
+ }
+ }
}
-void BatimentTri_::triangulation() {
+void BatimentTri::triangulation() {
Triangle th = c.offsetNormal(Dimensions::hauteurEtage * 2 + Dimensions::hauteurToit);
addGPUTriangle(th, Couleurs::toit);
for (int i = 0; i < 3; i++)
addGPUQuad(Quad(c[LEFT+i], c[TOP+i], th[TOP+i], th[LEFT+i]), Couleurs::mur);
}
-void BatimentTri_::getBoundingBoxPoints() {
+void BatimentTri::getBoundingBoxPoints() {
addBBPoints(c, Dimensions::hauteurEtage * 2 + Dimensions::hauteurToit);
}
+
+void BatimentTri::bordureRouteTrottoir() {
+ Triangle tinterieur = c.insetLTR(Dimensions::largeurRoute + Dimensions::largeurTrottoir);
+ Triangle tbatiments = tinterieur.offsetNormal(Dimensions::hauteurTrottoir);
+
+ for (int i = 0; i < 4; i++) {
+ addChild(new RouteTrottoirQuad(Quad(c[LEFT+i],c[TOP+i],tinterieur[TOP+i],tinterieur[LEFT+i])));
+ }
+
+ bool anglesAcceptable = c.minAngle() > Angle::d2r(90-60) && c.maxAngle() < Angle::d2r(90+60);
+
+ if (anglesAcceptable && proba(seed, 0, 0.95f)) {
+ addChild(new BatimentTri(tbatiments, true));
+ } else {
+ addChild(new TerrainTri(tbatiments));
+ }
+}
+
+void BatimentTri::sousBatiments() {
+ Triangle t = c << c.minAngleCorner();
+ TriBool tb = w << c.minAngleCorner();
+
+ // TODO : ajuster pour que la distance c[LEFT] -- left et c[LEFT] -- base soit similaire.
+ Vertex left = Segment(t[LEFT], t[TOP]).randomPos(seed, 0, 1.f/3.f, 2.f/3.f);
+ float dLeft = Segment(t[LEFT], left).length();
+ float posBase = dLeft / Segment(t[LEFT], t[RIGHT]).length();
+ if (posBase < 0.3f) posBase = 0.2f;
+ else if (posBase > 0.7f) posBase = 0.8f;
+ Vertex base = Segment(t[RIGHT], t[LEFT]).randomPos(seed, 1, posBase - 0.1f, posBase + 0.1f);
+
+ bool small = t.surface() < 4 * Dimensions::minSurfaceSousBatiment;
+
+ if (small && (tb[LEFTSIDE] || tb[RIGHTSIDE]) && proba(seed, 2, 0.3f)) {
+ addChild(new TerrainTri(Triangle(base, t[LEFT], left)));
+ addChild(new BatimentQuad(Quad(base, left, t[TOP], t[RIGHT]), true, QuadBool(true, w[LEFTSIDE], w[RIGHTSIDE], w[BASE])));
+ } else if (small && (tb[LEFTSIDE] || tb[RIGHTSIDE] || tb[BASE]) && proba(seed, 2, 0.3f)) {
+ addChild(new BatimentTri(Triangle(base, t[LEFT], left), true, TriBool(w[BASE], w[LEFTSIDE], true)));
+ addChild(new TerrainQuad(Quad(base, left, t[TOP], t[RIGHT])));
+ } else {
+ addChild(new BatimentTri(Triangle(base, t[LEFT], left), true, TriBool(w[BASE], w[LEFTSIDE], false)));
+ addChild(new BatimentQuad(Quad(base, left, t[TOP], t[RIGHT]), true, QuadBool(false, w[LEFTSIDE], w[RIGHTSIDE], w[BASE])));
+ }
+}
+
+void BatimentTri::etages() {
+ float randEtages = floatInRange(seed, 0, 0.f, 1.f);
+ int nbEtages = 1 + (int)(randEtages * randEtages * (Dimensions::maxEtages - 1));
+ Triangle t = c; // c.insetNESW(30)
+ Triangle th;
+ for (int i = 0; i < nbEtages; i++) {
+ th = t.offsetNormal(floatInRange(seed, 1+i, Dimensions::hauteurEtage*0.9f, Dimensions::hauteurEtage*1.1f));
+ addChild(new EtageTri(t, th, w, i, nbEtages));
+ t = th;
+ }
+ addChild(new ToitTri(th, Dimensions::hauteurToit));
+}
diff --git a/rules/batiment.hh b/rules/batiment.hh
@@ -20,11 +20,17 @@ public:
BatimentQuad* isSubdivision(bool val);
};
-class BatimentTri_ : public Chose {
+class BatimentTri : public Chose {
+private:
Triangle c;
+ bool isSub;
+ TriBool w;
+ void bordureRouteTrottoir();
+ void sousBatiments();
+ void etages();
public:
- BatimentTri_(Triangle _c);
+ BatimentTri(Triangle _c, bool _isSub = false, TriBool _w = TriBool(true, true, true));
virtual void split();
virtual void triangulation();
virtual void getBoundingBoxPoints();
diff --git a/rules/couleursDimensions.hh b/rules/couleursDimensions.hh
@@ -45,7 +45,7 @@ public:
static const unsigned int hauteurTrottoir = 20;
static const unsigned int hauteurMaxBatiment = hauteurTrottoir + hauteurEtage * 2 + hauteurToit;
static const unsigned int minSurfaceSousBatiment = 100 * 100*100; // 100 m²
- static const unsigned int minRayonPlace = 50 * 100; // 60 m
+ static const unsigned int minRayonPlace = 30 * 100; // 60 m
static const unsigned int maxRayonPlace = 2 * minRayonPlace; // 60 m
// Qualité
diff --git a/rules/etage.cpp b/rules/etage.cpp
@@ -68,3 +68,43 @@ void EtageQuad::triangulation() {
addGPUQuad(ch.offsetNormal(-30), Couleurs::plafond);
addGPUQuad(c, Couleurs::plancher);
}
+
+EtageTri::EtageTri(Triangle _c, Triangle _ch, TriBool _w, int _etage, int _nbEtages) : Chose(), c(_c), ch(_ch), w(_w), etage(_etage), nbEtages(_nbEtages) {
+ addEntropy(c);
+ addEntropy(ch);
+ for (int i = 0; i < 3; i++)
+ addEntropy(w[LEFTSIDE+i] ? 0 : 1);
+}
+
+void EtageTri::getBoundingBoxPoints() {
+ addBBPoints(c);
+ addBBPoints(ch);
+}
+
+void EtageTri::split() {
+ Triangle small = c.insetLTR(28);
+ Triangle smallh = ch.insetLTR(28);
+
+ TriBool d(false,false,false);
+
+ if(etage == 0) {
+ if(w[LEFTSIDE]) d[LEFTSIDE] = true;
+ else if(w[RIGHTSIDE]) d[RIGHTSIDE] = true;
+ else if(w[BASE]) d[BASE] = true;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ Quad q = Quad(c[TOP+i], small[TOP+i], small[LEFT+i], c[LEFT+i]);
+ Quad qh = Quad(ch[TOP+i], smallh[TOP+i], smallh[LEFT+i], ch[LEFT+i]);
+ addChild(new MurQuad(q, qh, w[LEFTSIDE+i]^d[LEFTSIDE+i],false,false,d[LEFTSIDE+i]));
+ }
+
+ addChild(new PlancherPlafondTri(c, PlancherPlafondTri::PLANCHER));
+ addChild(new PlancherPlafondTri(ch.offsetNormal(-10), PlancherPlafondTri::PLAFOND));
+}
+
+void EtageTri::triangulation() {
+ addGPUThreeQuads(c,ch, Couleurs::mur);
+ addGPUTriangle(ch.offsetNormal(-30), Couleurs::plafond);
+ addGPUTriangle(c, Couleurs::plancher);
+}
diff --git a/rules/etage.hh b/rules/etage.hh
@@ -3,7 +3,6 @@
#include "all_includes.hh"
-
class EtageQuad : public Chose {
private :
Quad c;
@@ -19,4 +18,19 @@ class EtageQuad : public Chose {
virtual void getBoundingBoxPoints();
};
+class EtageTri : public Chose {
+ private :
+ Triangle c;
+ Triangle ch;
+ TriBool w;
+ int etage;
+ int nbEtages;
+
+ public :
+ EtageTri(Triangle c, Triangle ch, TriBool _w, int _etage, int _nbEtages);
+ virtual void split();
+ virtual void triangulation();
+ virtual void getBoundingBoxPoints();
+};
+
#endif
diff --git a/rules/mur.cpp b/rules/mur.cpp
@@ -75,3 +75,19 @@ void PlancherPlafond::triangulation() {
void PlancherPlafond::getBoundingBoxPoints() {
addBBPoints(c);
}
+
+PlancherPlafondTri::PlancherPlafondTri(Triangle _c, Type _type) : Chose(), c(_c), type(_type) {
+ addEntropy(c);
+ addEntropy((int)type);
+}
+
+void PlancherPlafondTri::triangulation() {
+ unsigned int clr = Couleurs::plancher;
+ if (type == PLAFOND)
+ clr = Couleurs::plafond;
+ addGPUTriangle(c, clr);
+}
+
+void PlancherPlafondTri::getBoundingBoxPoints() {
+ addBBPoints(c);
+}
diff --git a/rules/mur.hh b/rules/mur.hh
@@ -39,5 +39,21 @@ public:
virtual void getBoundingBoxPoints();
};
+class PlancherPlafondTri: public Chose {
+public:
+ enum Type {
+ PLANCHER,
+ PLAFOND
+ };
+private:
+ Triangle c;
+ Type type;
+
+public:
+ PlancherPlafondTri(Triangle _c, Type _type);
+ virtual void triangulation();
+ virtual void getBoundingBoxPoints();
+};
+
#endif
diff --git a/rules/quartier.cpp b/rules/quartier.cpp
@@ -163,8 +163,8 @@ void QuartierTri::getBoundingBoxPoints() {
}
void QuartierTri::split() {
- bool small = c.minLength() < 6000;
- bool big = c.maxLength() >= 10000;
+ bool small = c.minLength() < 80 * 100;
+ bool big = c.maxLength() >= 150 * 100;
float minAngle = c.minAngle();
float maxAngle = c.maxAngle();
bool equilateral = maxAngle < Angle::d2r(60+15) && minAngle > Angle::d2r(60-15);
@@ -172,7 +172,7 @@ void QuartierTri::split() {
bool angleAigu = minAngle < Angle::d2r(30);
bool anglesAcceptable = !angleAigu && !angleObtus;
if (!big && proba(seed, -1, 0.05f)) {
- batiments(); // TODO : addChild(new BatimentTri_(c));
+ addChild(new BatimentTri(c));
} else if (big && anglesAcceptable) {
switch (hash2(seed, -2) % 3) {
case 0: centre(); break;
@@ -187,7 +187,7 @@ void QuartierTri::split() {
} else if (!small) {
trapeze();
} else {
- batiments(); // TODO : addChild(new BatimentTri_(c));
+ addChild(new BatimentTri(c));
}
}
@@ -228,24 +228,3 @@ void QuartierTri::trapeze() {
addChild(new QuartierTri(Triangle(base, t[LEFT], left)));
addChild(new QuartierQuad(Quad(base, left, t[TOP], t[RIGHT])));
}
-
-void QuartierTri::batiments() {
- Triangle tinterieur = c.insetLTR(Dimensions::largeurRoute + Dimensions::largeurTrottoir);
- Triangle tbatiments = tinterieur.offsetNormal(Dimensions::hauteurTrottoir);
-
- for (int i = 0; i < 3; i++) {
- addChild(new RouteTrottoirQuad(Quad(c[LEFT+i],c[TOP+i],tinterieur[TOP+i],tinterieur[LEFT+i])));
- }
-
- bool small = tbatiments.minLength() < 3000;
- bool big = tbatiments.maxLength() >= 5000;
- bool anglesAcceptable = tbatiments.minAngle() > Angle::d2r(30) && tbatiments.maxAngle() < Angle::d2r(120);
-
- if (!big && proba(seed, 0, 0.05f)) {
- addChild(new TerrainTri(tbatiments));
- } else if (small && anglesAcceptable) {
- addChild(new BatimentTri_(tbatiments));
- } else {
- addChild(new TerrainTri(tbatiments));
- }
-}
diff --git a/rules/quartier.hh b/rules/quartier.hh
@@ -34,7 +34,6 @@ private:
void centre();
void hauteur();
void trapeze();
- void batiments();
};
#endif
diff --git a/rules/terrain.cpp b/rules/terrain.cpp
@@ -37,10 +37,35 @@ void TerrainQuad::triangulation() {
addGPUQuad(c, Couleurs::herbe);
}
-TerrainTri::TerrainTri(Triangle _c) : Chose(), c(_c) {
+TerrainTri::TerrainTri(Triangle _c, bool _addTrees) : Chose(), c(_c), addTrees(_addTrees) {
addEntropy(c);
}
+void TerrainTri::split() {
+ if (!addTrees) return;
+
+ addChild(new TerrainTri(c, false));
+
+ Vertex p[10];
+ int maxNArbres = std::min(10, (int)(c.surface() / (7.f*7.f*100.f*100.f)));
+ int pi = 0;
+ int nArbres = hash2(seed, -1) % (maxNArbres + 1);
+ for (int essai = 0; essai < nArbres * 2 && pi < nArbres; essai++) {
+ p[pi] = c.insetProportionnal(0.7f).randomPoint(seed, essai);
+ bool success = true;
+ for (int j = 0; j < pi; j++) {
+ if (Segment(p[j], p[pi]).length() < 3 * 100) {
+ success = false;
+ break;
+ }
+ }
+ if (success) pi++;
+ }
+ for (int i = 0; i < pi; i++) {
+ addChild(new Arbre(p[i], c));
+ }
+}
+
void TerrainTri::getBoundingBoxPoints() {
addBBPoints(c);
}
diff --git a/rules/terrain.hh b/rules/terrain.hh
@@ -3,23 +3,25 @@
#include "all_includes.hh"
-class TerrainTri : public Chose {
+class TerrainQuad : public Chose {
private :
- Triangle c;
+ Quad c;
+ bool addTrees;
public :
- TerrainTri(Triangle _c);
+ TerrainQuad(Quad _c, bool _addTrees = true);
+ virtual void split();
virtual void triangulation();
virtual void getBoundingBoxPoints();
};
-class TerrainQuad : public Chose {
+class TerrainTri : public Chose {
private :
- Quad c;
+ Triangle c;
bool addTrees;
public :
- TerrainQuad(Quad _c, bool _addTrees = true);
+ TerrainTri(Triangle _c, bool _addTrees = true);
virtual void split();
virtual void triangulation();
virtual void getBoundingBoxPoints();
diff --git a/rules/toit.cpp b/rules/toit.cpp
@@ -12,6 +12,8 @@ void ToitQuad::getBoundingBoxPoints() {
}
void ToitQuad::triangulation() {
+ // TODO : si angles pas acceptables, plat().
+ // TODO : toit plat : surélever.
switch (hash2(seed, -1) % 5) {
case 0: pointCentral(); break;
case 1: quatrePoints(); break;
@@ -97,6 +99,7 @@ void ToitTri::getBoundingBoxPoints() {
}
void ToitTri::triangulation() {
+ plat(); return;
switch (hash2(seed, -1) % 5) {
case 0: pointCentral(); break;
case 1: troisPoints(); break;
diff --git a/view.cpp b/view.cpp
@@ -300,6 +300,7 @@ void Camera::keyboard(const SDL_KeyboardEvent &eventKey) {
up = true;
break;
case 'e' :
+ moveSensitivity = 1500;
autoPilot = true;
break;
case 'z' :
@@ -350,7 +351,6 @@ void Camera::animation(int elapsedTime) {
float diff = ((float)(elapsedTime+1)/1000.f)*(float)moveSensitivity;
if (autoPilot) {
- moveSensitivity = 1500;
float dx = floatInRange(frame/16, 42, -0.5, 0.5);
float olddx = floatInRange(frame/16 - 1, 42, -0.5, 0.5);
float mix = ((float)(frame % 16) / 16.f);
@@ -359,7 +359,6 @@ void Camera::animation(int elapsedTime) {
cameraCenter = cameraCenter + Vertex::fromSpherical(diff, yAngle, xAngle);
cameraCenter.z = oldz;
cameraCenter.z += std::min(20.f, std::max(-20.f, 1750 - cameraCenter.z));
- return;
}
if(up)