Subdivision bâtiments triangulaires.
This commit is contained in:
parent
4b258d1cc6
commit
8db867a104
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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é
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
16
rules/mur.hh
16
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
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ private:
|
|||
void centre();
|
||||
void hauteur();
|
||||
void trapeze();
|
||||
void batiments();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -3,16 +3,6 @@
|
|||
|
||||
#include "all_includes.hh"
|
||||
|
||||
class TerrainTri : public Chose {
|
||||
private :
|
||||
Triangle c;
|
||||
|
||||
public :
|
||||
TerrainTri(Triangle _c);
|
||||
virtual void triangulation();
|
||||
virtual void getBoundingBoxPoints();
|
||||
};
|
||||
|
||||
class TerrainQuad : public Chose {
|
||||
private :
|
||||
Quad c;
|
||||
|
@ -25,4 +15,16 @@ class TerrainQuad : public Chose {
|
|||
virtual void getBoundingBoxPoints();
|
||||
};
|
||||
|
||||
class TerrainTri : public Chose {
|
||||
private :
|
||||
Triangle c;
|
||||
bool addTrees;
|
||||
|
||||
public :
|
||||
TerrainTri(Triangle _c, bool _addTrees = true);
|
||||
virtual void split();
|
||||
virtual void triangulation();
|
||||
virtual void getBoundingBoxPoints();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
3
view.cpp
3
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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user