Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c45ab48
Showing
8 changed files
with
1,354 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Islands | ||
|
||
This project is a demonstration of an algorithm to randomly generate islands on a map. | ||
|
||
|
||
## Installation | ||
|
||
In order to build this software, you will need to install : | ||
* A C++ compiler supporting the C++11 standard such as GCC >= 4.8. | ||
* Qt4, available at [qt-project](http://qt-project.org/downloads). Qt5 was not tested yet, but it should be compatible. | ||
* OpenGL and GLU libraries. | ||
|
||
|
||
## Usage | ||
|
||
The demo displays the result in a window. You can navigate through the map using the following commands : | ||
* mouse click and drag : translation on the map | ||
* mouse wheel : zoom in and out | ||
* CTRL + mouse wheel : rotation of the map | ||
|
||
Feel free to test several sets of parameters in `main.cpp` ! | ||
|
||
|
||
## Algorithm | ||
|
||
To generate islands, the following method was used. | ||
* The map can be seen as a honeycomb where each cell is given a score (initially one). We fill part of these cells with particles at random. | ||
* Whenever we add a particle in a cell, it modifies the scores of the neighboring cells, which is proportional to the probability of the apparition of a new particle. Thus, particles tend to stay close together. | ||
* At the end of this process, we obtain islands made of groups of particles. We convert the scores into a heightmap which is displayed on screen. | ||
|
||
This method can be adapted to create a forest (if we see particles as trees), or random ressources on a map. | ||
|
||
|
||
## License | ||
|
||
*Copyright (C) 2014 G. Endignoux* | ||
|
||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. | ||
|
||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License along with this program. If not, see [www.gnu.org/licenses/gpl-3.0.txt](http://www.gnu.org/licenses/gpl-3.0.txt). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
/* | ||
Islands - an algorithm to generate a random map of islands. | ||
Copyright (C) 2014 G. Endignoux | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.txt | ||
*/ | ||
|
||
#include <cmath> | ||
#include <GL/glu.h> | ||
|
||
#include "glwidget.hpp" | ||
|
||
GLWidget::GLWidget(unsigned int width, unsigned int height, const std::vector<double>& values, QWidget* parent) : | ||
QGLWidget(parent), | ||
mWidth(width), | ||
mHeight(height), | ||
mValues(values) | ||
{ | ||
xTrans = width / 2.0; | ||
yTrans = -std::sqrt(3) * height / 4.0; | ||
zoom = 100; | ||
rot = 0; | ||
mCtrl = false; | ||
} | ||
|
||
GLWidget::~GLWidget() | ||
{ | ||
if (mIslands) | ||
glDeleteLists(mIslands, 1); | ||
} | ||
|
||
|
||
// Initialize OpenGL. | ||
void GLWidget::initializeGL() | ||
{ | ||
mIslands = makeIslands(); | ||
|
||
glEnable(GL_DEPTH_TEST); | ||
glEnable(GL_NORMALIZE); | ||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | ||
} | ||
|
||
// Repaint the view. | ||
void GLWidget::paintGL() | ||
{ | ||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | ||
|
||
glLoadIdentity(); | ||
gluLookAt(xTrans, yTrans + zoom * std::sin(rot * std::atan(1) / 45.0), zoom * std::cos(rot * std::atan(1) / 45.0), | ||
xTrans, yTrans, 0, | ||
0, std::cos(rot * std::atan(1) / 45.0), -std::sin(rot * std::atan(1) / 45.0)); | ||
|
||
glCallList(mIslands); | ||
glPopMatrix(); | ||
} | ||
|
||
// Resize the view. | ||
void GLWidget::resizeGL(int width, int height) | ||
{ | ||
glViewport(0, 0, width, height); | ||
|
||
glMatrixMode(GL_PROJECTION); | ||
glLoadIdentity(); | ||
glFrustum(-5.0, +5.0, -5.0, 5.0, 5.0, 1000.0); | ||
glMatrixMode(GL_MODELVIEW); | ||
glLoadIdentity(); | ||
glTranslated(0.0, 0.0, -40.0); | ||
} | ||
|
||
|
||
// Mouse operations. | ||
void GLWidget::mousePressEvent(QMouseEvent* event) | ||
{ | ||
mMousePos = event->pos(); | ||
event->accept(); | ||
} | ||
|
||
// Translate the view. | ||
void GLWidget::mouseMoveEvent(QMouseEvent* event) | ||
{ | ||
int dx = event->x() - mMousePos.x(); | ||
int dy = event->y() - mMousePos.y(); | ||
|
||
if (event->buttons() & Qt::LeftButton) | ||
{ | ||
xTrans -= dx / 5; | ||
yTrans += dy / 5; | ||
updateGL(); | ||
} | ||
|
||
mMousePos = event->pos(); | ||
event->accept(); | ||
} | ||
|
||
// Change zoom/rotation. | ||
void GLWidget::wheelEvent(QWheelEvent* event) | ||
{ | ||
if (mCtrl) | ||
{ | ||
rot += event->delta() / 30; | ||
|
||
while (rot < 0) | ||
rot += 360; | ||
while (rot > 360) | ||
rot -= 360; | ||
} | ||
else | ||
{ | ||
double z = zoom - event->delta() / 6; | ||
if (z > 0) | ||
zoom = z; | ||
} | ||
|
||
updateGL(); | ||
event->accept(); | ||
} | ||
|
||
// Check if CTRL is pressed. | ||
void GLWidget::keyPressEvent(QKeyEvent* event) | ||
{ | ||
if (event->key() == Qt::Key_Control) | ||
{ | ||
mCtrl = true; | ||
event->accept(); | ||
} | ||
else | ||
event->ignore(); | ||
} | ||
|
||
void GLWidget::keyReleaseEvent(QKeyEvent* event) | ||
{ | ||
if (event->key() == Qt::Key_Control) | ||
{ | ||
mCtrl = false; | ||
event->accept(); | ||
} | ||
else | ||
event->ignore(); | ||
} | ||
|
||
|
||
// Create the mesh of islands. | ||
GLuint GLWidget::makeIslands() | ||
{ | ||
GLuint list = glGenLists(1); | ||
glNewList(list, GL_COMPILE); | ||
|
||
glBegin(GL_TRIANGLES); | ||
for (unsigned int x = 0 ; x < mWidth ; ++x) | ||
{ | ||
for (unsigned int y = 0 ; y + 1 < mHeight ; ++y) | ||
{ | ||
double val = (mValues[x * mHeight + y] - 1) / 5; | ||
if (val > 0) | ||
glColor3ub( | ||
0xC0 * (1 - 1.25 * val) + 0x20 * 1.25 * val, | ||
0xC0 * (1 - 1.25 * val) + 0xA0 * 1.25 * val, | ||
0x78 * (1 - 1.25 * val) + 0x08 * 1.25 * val); | ||
else | ||
glColor3ub( | ||
0xC0 * (4 * val + 1) - 0x00 * 4 * val, | ||
0xC0 * (4 * val + 1) - 0x50 * 4 * val, | ||
0x78 * (4 * val + 1) - 0xA0 * 4 * val); | ||
|
||
static const double msqrt3 = -std::sqrt(3); | ||
|
||
if (y % 2) | ||
{ | ||
if (x + 1 < mWidth) | ||
{ | ||
glVertex3d( | ||
x, | ||
msqrt3 * y / (double)2, | ||
mValues[x * mHeight + y]); | ||
glVertex3d( | ||
x + 1, | ||
msqrt3 * y / (double)2, | ||
mValues[(x + 1) * mHeight + y]); | ||
glVertex3d( | ||
x + 1 / (double)2, | ||
msqrt3 * (y + 1) / (double)2, | ||
mValues[x * mHeight + y + 1]); | ||
} | ||
if (x > 0) | ||
{ | ||
glVertex3d( | ||
x, | ||
msqrt3 * y / (double)2, | ||
mValues[x * mHeight + y]); | ||
glVertex3d( | ||
x + 1 / (double)2, | ||
msqrt3 * (y + 1) / (double)2, | ||
mValues[x * mHeight + y + 1]); | ||
glVertex3d( | ||
x - 1 / (double)2, | ||
msqrt3 * (y + 1) / (double)2, | ||
mValues[(x - 1) * mHeight + y + 1]); | ||
} | ||
} | ||
else | ||
{ | ||
if (x + 1 < mWidth) | ||
{ | ||
glVertex3d( | ||
x + 1 / (double)2, | ||
msqrt3 * y / (double)2, | ||
mValues[x * mHeight + y]); | ||
glVertex3d( | ||
x + 3 / (double)2, | ||
msqrt3 * y / (double)2, | ||
mValues[(x + 1) * mHeight + y]); | ||
glVertex3d( | ||
x + 1, | ||
msqrt3 * (y + 1) / (double)2, | ||
mValues[(x + 1) * mHeight + y + 1]); | ||
|
||
|
||
glVertex3d( | ||
x + 1 / (double)2, | ||
msqrt3 * y / (double)2, | ||
mValues[x * mHeight + y]); | ||
glVertex3d( | ||
x + 1, | ||
msqrt3 * (y + 1) / (double)2, | ||
mValues[(x + 1) * mHeight + y + 1]); | ||
glVertex3d( | ||
x, | ||
msqrt3 * (y + 1) / (double)2, | ||
mValues[x * mHeight + y + 1]); | ||
} | ||
} | ||
} | ||
} | ||
glEnd(); | ||
|
||
glEndList(); | ||
return list; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
Islands - an algorithm to generate a random map of islands. | ||
Copyright (C) 2014 G. Endignoux | ||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.txt | ||
*/ | ||
|
||
#ifndef GLWIDGET_HPP | ||
#define GLWIDGET_HPP | ||
|
||
#include <QWidget> | ||
#include <QtOpenGL/QtOpenGL> | ||
|
||
// Widget to display the heightmap of islands with opengl. | ||
class GLWidget : public QGLWidget | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
GLWidget(unsigned int width, unsigned int height, const std::vector<double>& values, QWidget* parent = 0); | ||
~GLWidget(); | ||
|
||
private: | ||
// opengl operations | ||
void initializeGL(); | ||
void paintGL(); | ||
void resizeGL(int width, int height); | ||
// Mouse & keybord control | ||
void mousePressEvent(QMouseEvent* event); | ||
void mouseMoveEvent(QMouseEvent* event); | ||
void wheelEvent(QWheelEvent* event); | ||
void keyPressEvent(QKeyEvent* event); | ||
void keyReleaseEvent(QKeyEvent* event); | ||
|
||
// create the heightmap in opengl | ||
GLuint makeIslands(); | ||
|
||
// Heightmap. | ||
unsigned int mWidth; | ||
unsigned int mHeight; | ||
std::vector<double> mValues; | ||
|
||
// Mesh of islands. | ||
GLuint mIslands; | ||
|
||
// View. | ||
double xTrans; | ||
double yTrans; | ||
double zoom; | ||
double rot; | ||
|
||
// Whether CTRL is pressed on keyboard. | ||
bool mCtrl; | ||
// Position of mouse. | ||
QPoint mMousePos; | ||
}; | ||
|
||
#endif // GLWIDGET_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Islands - an algorithm to generate a random map of islands. | ||
# Copyright (C) 2014 G. Endignoux | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.txt | ||
|
||
TARGET = islands | ||
TEMPLATE = app | ||
|
||
QT += opengl | ||
LIBS += -lGLU | ||
|
||
QMAKE_CXXFLAGS += --std=c++11 | ||
|
||
SOURCES += main.cpp \ | ||
glwidget.cpp \ | ||
population.cpp | ||
|
||
HEADERS += \ | ||
glwidget.hpp \ | ||
population.hpp |
Oops, something went wrong.