Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
gendx committed Nov 15, 2014
0 parents commit c45ab48
Show file tree
Hide file tree
Showing 8 changed files with 1,354 additions and 0 deletions.
675 changes: 675 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions README.md
@@ -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).

249 changes: 249 additions & 0 deletions src/glwidget.cpp
@@ -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;
}
69 changes: 69 additions & 0 deletions src/glwidget.hpp
@@ -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
31 changes: 31 additions & 0 deletions src/islands.pro
@@ -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

0 comments on commit c45ab48

Please sign in to comment.