diff --git a/all_includes.hh b/all_includes.hh index d3e3e7b..42d55bc 100644 --- a/all_includes.hh +++ b/all_includes.hh @@ -20,9 +20,9 @@ class Chose; #include #include -#include "geometry/angle.hh" #include "geometry/directions.hh" #include "geometry/vertex.hh" +#include "geometry/angle.hh" #include "geometry/segment.hh" #include "geometry/triangle.hh" #include "geometry/quad.hh" @@ -38,6 +38,7 @@ class Chose; #include "rules/chose.hh" #include "rules/architecture/couleursDimensions.hh" +#include "rules/architecture/arbre.hh" #include "rules/architecture/arche.hh" #include "rules/architecture/batiment.hh" #include "rules/architecture/quartier.hh" diff --git a/geometry/angle.cpp b/geometry/angle.cpp index 41b1ed7..55f2f3c 100644 --- a/geometry/angle.cpp +++ b/geometry/angle.cpp @@ -2,3 +2,19 @@ float Angle::r2d(float rad) { return rad / Pi * 180; } float Angle::d2r(float deg) { return deg / 180 * Pi; } + +Angle3D::Angle3D() : h(Vertex(1,0,0)), l(Vertex(0,1,0)), u(Vertex(0,0,1)) {} +Angle3D::Angle3D(Vertex _h, Vertex _l, Vertex _u) : h(_h), l(_l), u(_u) {} + +// Formules : http://www.nbb.cornell.edu/neurobio/land/OldStudentProjects/cs490-94to95/hwchen/ +Angle3D Angle3D::rotateH(float angle) const { + return Angle3D(h, l*std::cos(angle) + u*std::sin(angle), l*-std::sin(angle) + u*std::cos(angle)); +} + +Angle3D Angle3D::rotateL(float angle) const { + return Angle3D(h*std::cos(angle) + u*std::sin(angle), l, h*-std::sin(angle) + u*std::cos(angle)); +} + +Angle3D Angle3D::rotateU(float angle) const { + return Angle3D(h*std::cos(angle) + l*-std::sin(angle), h*std::sin(angle) + l*std::cos(angle), u); +} diff --git a/geometry/angle.hh b/geometry/angle.hh index 19f312c..6da7635 100644 --- a/geometry/angle.hh +++ b/geometry/angle.hh @@ -1,6 +1,8 @@ #ifndef _GEOMETRY_ANGLE_HH_ #define _GEOMETRY_ANGLE_HH_ +#include "all_includes.hh" + namespace Angle { const double dPi = 3.141592653589793238462643383279; const float Pi = (float)(dPi); @@ -8,4 +10,16 @@ namespace Angle { float d2r(float deg); } +class Angle3D { +public: + Vertex h; + Vertex l; + Vertex u; + Angle3D(); + Angle3D(Vertex _h, Vertex _l, Vertex _u); + Angle3D rotateH(float angle) const; + Angle3D rotateL(float angle) const; + Angle3D rotateU(float angle) const; +}; + #endif diff --git a/geometry/quad.cpp b/geometry/quad.cpp index 39088f5..6aed4b0 100644 --- a/geometry/quad.cpp +++ b/geometry/quad.cpp @@ -243,3 +243,11 @@ Quad Quad::offsetNormal(float offset) const { Vertex Quad::normal() const { return Triangle(c[NE], c[SE], c[SW]).normal(); } + +Vertex Quad::normalizedNormal() const { + return Triangle(c[NE], c[SE], c[SW]).normalizedNormal(); +} + +Vertex Quad::moyenne() const { + return ((c[NE] + c[SE] + c[SW] + c[NW]) / 4.f); +} diff --git a/geometry/quad.hh b/geometry/quad.hh index 94b5993..6c31e29 100644 --- a/geometry/quad.hh +++ b/geometry/quad.hh @@ -51,6 +51,8 @@ class Quad { Quad insetProportionnal(float prop); Quad offsetNormal(float offset) const; Vertex normal() const; + Vertex normalizedNormal() const; + Vertex moyenne() const; }; diff --git a/geometry/vertex.cpp b/geometry/vertex.cpp index e46c526..93ae5f1 100644 --- a/geometry/vertex.cpp +++ b/geometry/vertex.cpp @@ -21,6 +21,10 @@ Vertex Vertex::setNorm(float n) const { return (*this * n / norm()); } +Vertex Vertex::normalize() const { + return (*this / norm()); +} + float Vertex::cosAngle(Vertex v) const { // http://www.developpez.net/forums/d202580/applications/developpement-2d-3d-jeux/contribuez/faq-mat-quat-ajout-calculs-vectoriels/ return ((this->x*v.x + this->y*v.y + this->z*v.z) / (norm()*v.norm())); diff --git a/geometry/vertex.hh b/geometry/vertex.hh index 8bc2532..39ffb51 100644 --- a/geometry/vertex.hh +++ b/geometry/vertex.hh @@ -15,6 +15,7 @@ class Vertex { float norm() const; Vertex projectOn(Vertex v) const; Vertex setNorm(float n) const; + Vertex normalize() const; float cosAngle(Vertex v) const; // cosinus de l'angle entre this et v. float angle(Vertex v) const; // Angle entre this et v. static Vertex fromSpherical(float r, float xAngle, float yAngle); @@ -24,7 +25,7 @@ class Vertex { 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 float n); + friend Vertex operator*(const Vertex& v, const float n); // Cross product friend Vertex operator*(const Vertex& u, const Vertex& v); friend Vertex operator/(const Vertex& v, const float f); }; diff --git a/rules/architecture/arbre.cpp b/rules/architecture/arbre.cpp new file mode 100644 index 0000000..a1e9cc5 --- /dev/null +++ b/rules/architecture/arbre.cpp @@ -0,0 +1,97 @@ +#include "all_includes.hh" + +Arbre::Arbre(Vertex _start, Triangle plane) : start(_start), type(ARBRE) { + addEntropy(start); + addEntropy(plane); + + Vertex h = plane.normalizedNormal(); + Vertex l = (plane[TOP] - plane[LEFT]).normalize(); + Vertex u = h * l; + + rotation = Angle3D(h, l, u); + rotation = rotation.rotateH(floatInRange(seed, -3, 0, 2*Angle::Pi)); + rotation = rotation.rotateU(floatInRange(seed, -4, Angle::d2r(-10), Angle::d2r(10))); + length = floatInRange(seed, -5, 3*100, 4*100); +} + +Arbre::Arbre(Vertex _start, Angle3D _rotation, float _length, Type _type) : start(_start), rotation(_rotation), length(_length), type(_type) { + addEntropy(start, rotation.h, rotation.l, rotation.u); + addEntropy(length); + addEntropy((int)(type)); +} + +bool Arbre::split() { + if (type == ARBRE && length > floatInRange(seed, -1, 10, 20)) { + int nbBranches = 2 + (hash2(seed, -2) % 3); + for (int i = 0; i < nbBranches; i++) { + Vertex bStart = end(floatInRange(seed, 4*i, 0.7f, 0.9f)); + Angle3D rot = rotation; + rot = rot.rotateH(Angle::d2r(floatInRange(seed, 4*i+1, 25.f, 37.f) + i*(360.f / (float)nbBranches))); + rot = rot.rotateU(Angle::d2r(floatInRange(seed, 4*i+2, 35.f, 55.f))); + float len = length * floatInRange(seed, 4*i+3, tauxMax()*2.f/3.f, tauxMax()); + addChild(new Arbre(bStart, rot, len, ARBRE)); + } + addChild(new Arbre(start, rotation, length, TRONC)); + } + return true; +} + +void Arbre::triangulation() { + if (type == ARBRE || type == TRONC) tronc(); + if (type == ARBRE) feuille(); +} + +void Arbre::getBoundingBoxPoints() { + // TODO + Vertex u = rotation.u * limitLength() / 2.f; + Vertex l = rotation.l * limitLength() / 2.f; + Quad c(start +u +l, start -u +l, start -u -l, start +u -l); + addBBPoints(c, length + limitLength()); +} + +float Arbre::LODFactor() { + return 4.f; +} + +Vertex Arbre::end(float position) const { + return (start + rotation.h * length * position); +} + +float Arbre::tauxMax() { + return 0.6f; +} +const float Arbre::limitLengthFactor = calcLimitLengthFactor(); +float Arbre::calcLimitLengthFactor() { + float limit = 0; + for (float i = 1; i > 0.001; i = i * tauxMax()) + limit += i; + return limit - 1; +} + +float Arbre::limitLength() const { + return length * limitLengthFactor; +} + +float Arbre::maxRadius(float length) { + return length * (1+limitLengthFactor); +} + +void Arbre::tronc() { + float radius = length/16; + Vertex hTronc = end(1.f) - start; + Vertex uTronc = rotation.u * radius; + Vertex lTronc = rotation.l * radius; + Quad cTronc(start +uTronc +lTronc, start -uTronc +lTronc, start -uTronc -lTronc, start +uTronc -lTronc); + addGPUQuad(cTronc + hTronc, Couleurs::tronc); + addGPUFourQuads(cTronc, cTronc + hTronc, Couleurs::tronc); +} + +void Arbre::feuille() { + Vertex hFeuillage = rotation.h * limitLength(); + Vertex uFeuillage = rotation.u * limitLength() / 2.f; + Vertex lFeuillage = rotation.l * limitLength() / 2.f; + Vertex startFeuillage = end(1.f); + + Quad cFeuillage(startFeuillage +uFeuillage +lFeuillage, startFeuillage -uFeuillage +lFeuillage, startFeuillage -uFeuillage -lFeuillage, startFeuillage +uFeuillage -lFeuillage); + addGPUOcto(cFeuillage, cFeuillage + hFeuillage, Couleurs::feuillage); +} diff --git a/rules/architecture/arbre.hh b/rules/architecture/arbre.hh new file mode 100644 index 0000000..8e074f1 --- /dev/null +++ b/rules/architecture/arbre.hh @@ -0,0 +1,34 @@ +#ifndef _RULES_ARCHITECTURE_ARBRE_HH_ +#define _RULES_ARCHITECTURE_ARBRE_HH_ + +#include "all_includes.hh" + +class Arbre : public Chose { +public: + enum Type { + ARBRE, + TRONC + }; +private: + Vertex start; + Angle3D rotation; + float length; + Type type; + Vertex end(float position) const; + float limitLength() const; + static float tauxMax(); + static float calcLimitLengthFactor(); + static const float limitLengthFactor; +public: + static float maxRadius(float length); + Arbre(Vertex _start, Triangle plane); + Arbre(Vertex _start, Angle3D _rotation, float _length, Type _type = ARBRE); + virtual bool split(); + virtual void triangulation(); + virtual void getBoundingBoxPoints(); + virtual float LODFactor(); + void tronc(); + void feuille(); +}; + +#endif diff --git a/rules/architecture/batiment.cpp b/rules/architecture/batiment.cpp index 0dc8767..34548e3 100644 --- a/rules/architecture/batiment.cpp +++ b/rules/architecture/batiment.cpp @@ -6,7 +6,7 @@ BatimentQuad_::BatimentQuad_(Quad _c, bool _isSub, bool _we, bool _ws, bool _ww, } bool BatimentQuad_::split() { - int minSurface = 100 * 100 * 10; + int minSurface = 100 * 100 * 100; Quad q = c; //Quad q = c << c.maxLengthSide(); if(c.maxLengthNS() < c.maxLengthEW()) { diff --git a/rules/architecture/couleursDimensions.hh b/rules/architecture/couleursDimensions.hh index 06e7c56..6ba0a50 100644 --- a/rules/architecture/couleursDimensions.hh +++ b/rules/architecture/couleursDimensions.hh @@ -24,7 +24,9 @@ public: static const unsigned int route = 0x363636; static const unsigned int trottoir = 0x666666; static const unsigned int bordureTrottoir = 0xAAAAAA; - static const unsigned int herbe = 0x0c4010; // 11AA22 + static const unsigned int herbe = 0x0c4010; + static const unsigned int feuillage = 0x11AA22; + static const unsigned int tronc = 0x906050; static const unsigned int cielHaut = 0x3c14ff; static const unsigned int cielBas = 0x7F7FFF; static const unsigned int fog; // définie dans couleurs.cpp . diff --git a/rules/architecture/quartier.cpp b/rules/architecture/quartier.cpp index d2243fc..7afb614 100644 --- a/rules/architecture/quartier.cpp +++ b/rules/architecture/quartier.cpp @@ -135,6 +135,18 @@ void QuartierQuad::batiments() { addChild(new BatimentQuad_(qbatiments)); } else { addChild(new TerrainQuad(qbatiments)); + Vertex p1 = qbatiments.insetProportionnal(0.7).randomPoint(seed, 1); + Vertex p2 = qbatiments.insetProportionnal(0.7).randomPoint(seed, 2); + Vertex p3 = qbatiments.insetProportionnal(0.7).randomPoint(seed, 3); + if (proba(seed, 4, 3, 4)) { + addChild(new Arbre(p1, Triangle(qbatiments[NE], qbatiments[SE], qbatiments[SW]))); + if (proba(seed, 5, 3, 4) && Segment(p1,p2).length() > 3 * 100) { + addChild(new Arbre(p2, Triangle(qbatiments[NE], qbatiments[SE], qbatiments[SW]))); + if (proba(seed, 6, 3, 4) && Segment(p2,p3).length() > 3 * 100 && Segment(p1,p3).length() > 3 * 100) { + addChild(new Arbre(p3, Triangle(qbatiments[NE], qbatiments[SE], qbatiments[SW]))); + } + } + } } } diff --git a/rules/architecture/toit.cpp b/rules/architecture/toit.cpp index a18c119..12a9d95 100644 --- a/rules/architecture/toit.cpp +++ b/rules/architecture/toit.cpp @@ -12,12 +12,12 @@ void ToitQuad::getBoundingBoxPoints() { } void ToitQuad::triangulation() { - switch (hash2(seed, -1) % 4) { + switch (hash2(seed, -1) % 5) { case 0: pointCentral(); break; - // TODO : deuxPoints() et deuxPointsVerticaux() ne génèrent pas des quad où les 4 points sont sur le même plan. - case 1: deuxPoints(); break; - case 2: deuxPointsVerticaux(); break; - case 3: + case 1: quatrePoints(); break; + case 2: deuxPoints(); break; + case 3: deuxPointsVerticaux(); break; + case 4: default: plat(); break; } } @@ -29,6 +29,13 @@ void ToitQuad::pointCentral() { addGPUTriangle(c[SE+i], center, c[NE+i], Couleurs::toit); } +void ToitQuad::quatrePoints() { + Quad ch = c.offsetNormal(height).insetNESW(c.minLength() / 3.f); // TODO : insetProportional + addGPUQuad(ch, Couleurs::toit); + for (int i = 0; i < 4; i++) + addGPUQuad(ch[NE+i], c[NE+i], c[SE+i], ch[SE+i], Couleurs::toit); +} + void ToitQuad::deuxPoints() { // Orienter c dans le sens de la longueur d'est en ouest. Quad q = c >> ((c.maxLengthNS() > c.maxLengthEW()) ? 1 : 0); @@ -111,7 +118,7 @@ void ToitTri::troisPoints() { Triangle th = c.offsetNormal(height).insetLTR(c.minLength() / 3.f); addGPUTriangle(th, Couleurs::toit); for (int i = 0; i < 3; i++) - addGPUQuad(c[LEFT], c[TOP], th[TOP], th[LEFT], Couleurs::toit); + addGPUQuad(c[LEFT+i], c[TOP+i], th[TOP+i], th[LEFT+i], Couleurs::toit); } void ToitTri::unPointVertical() { diff --git a/rules/architecture/toit.hh b/rules/architecture/toit.hh index d9f0537..d4cb700 100644 --- a/rules/architecture/toit.hh +++ b/rules/architecture/toit.hh @@ -13,6 +13,7 @@ public: virtual void getBoundingBoxPoints(); private: void pointCentral(); + void quatrePoints(); void deuxPoints(); void deuxPointsVerticaux(); void plat(); diff --git a/rules/chose.cpp b/rules/chose.cpp index 9aa9980..ed04014 100644 --- a/rules/chose.cpp +++ b/rules/chose.cpp @@ -48,6 +48,11 @@ void Chose::addGPUQuad(Quad q, unsigned int rgb) { addGPUQuad(q[NE], q[SE], q[SW], q[NW], rgb); } +void Chose::addGPUFourQuads(Quad q, Quad qh, unsigned int rgb) { + for (int i = 0; i < 4; i++) + addGPUQuad(Quad(qh[NE+i], q[NE+i], q[SE+i], qh[SE+i]), rgb); +} + void Chose::addGPUOcto(Vertex ne, Vertex se, Vertex sw, Vertex nw, Vertex neh, Vertex seh, Vertex swh, Vertex nwh, unsigned int rgb) { addGPUOcto(Quad(ne,se,sw,nw), Quad(neh,seh,swh,nwh), rgb); @@ -131,8 +136,8 @@ void Chose::addBBPoints(const Quad q, float height) { } void Chose::updateAABB() { - float splitFactor = 5.f; - float mergeFactor = 6.f; + float splitFactor = 5.f * LODFactor(); + float mergeFactor = 6.f * LODFactor(); float nonFacingFactor = 2.f/3.f; lod.firstBBPoint = true; getBoundingBoxPoints(); @@ -153,6 +158,10 @@ void Chose::updateAABB() { } } +float Chose::LODFactor() { + return 1.f; +} + // DEBUG void Chose::drawAABB() { addGPUOcto( diff --git a/rules/chose.hh b/rules/chose.hh index f6dfe22..4e35a4c 100644 --- a/rules/chose.hh +++ b/rules/chose.hh @@ -28,6 +28,7 @@ protected : void addBBPoints(const Quad q); void addBBPoints(const Quad q, float height); virtual void getBoundingBoxPoints() = 0; + virtual float LODFactor(); Chose(); ~Chose(); inline void addEntropy(unsigned int x1) { @@ -66,6 +67,7 @@ protected : void addGPUTriangle(Triangle t, unsigned int rgb); void addGPUQuad(Vertex ne, Vertex se, Vertex sw, Vertex nw, unsigned int rgb); void addGPUQuad(Quad q, unsigned int rgb); + void addGPUFourQuads(Quad q, Quad qh, unsigned int rgb); void addGPUOcto(Vertex ne, Vertex se, Vertex sw, Vertex nw, Vertex neh, Vertex seh, Vertex swh, Vertex nwh, unsigned int rgb);