Améliorations sur QuadRoutes, utilisation du cm comme unité de base.
This commit is contained in:
parent
11f2948558
commit
61ea30e35d
3
main.cpp
3
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,6 +10,9 @@ public:
|
|||
Vertex se;
|
||||
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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -10,17 +10,20 @@ public:
|
|||
Vertex se;
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
35
triangle.cpp
35
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();
|
||||
}
|
||||
|
|
45
vertex.cpp
45
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(
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
18
view.cpp
18
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user