diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..95fcba3 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [contact@daque.me](mailto:contact@daque.me?Subject=Code%20of%20Conduct%20Report). +All complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..77d1dcf --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,177 @@ +# Contributing to ViaRE + +Thanks for reading this! That'd mean, hopefully, that you want to contribute +with us. + +We try to make it possible that, by reading some of our code, you'll recognize +our conventions and style. + +But if you're unsure about it, or you just want to know how we get things done, +you should read this. + +## Contents + +- [**Git Flow**](#git-flow) + - [Commiting](#commiting) + - [Branching](#branching) +- [**Code Style**](#code-style) +- [**Versioning**](#versioning) +- [**GitHub Related**](#github-related) + - [Issues](#issues) + - [Bugs](#bugs) + - [Enhancements](#enhancements) + - [Pull Requests](#pull-requests) +- [**Thanks!**](#thanks) + +## Git Flow + +We use git —surprise!— to control versions. In this section, you can get to +know our workflow in this, and all of our projects. + +### Commiting + +Commited changes should be small, avoiding big chunks of code being created, +modified, or removed. + +Our commiting system is based on modularity. Each one should be able to be +described in one sentence. If you need more than one, maybe you should make +multiple commits. + +Yes, this can cause non—meaningful commits, but it makes easy to track down +bugs and errors. + +If the change of the commit is style related, it doesn't matter the size of the +modified code, as long as it doesn't change functionality. + +### Branching + +We try to follow the branching system published by [Vincent Driessen at nvie](https://nvie.com/posts/a-successful-git-branching-model/). + +`master` only has released versions. + +`develop` is where all approved changes (that are not big enough to make it to +a new version yet) go. + +From develop, we have multiple branches. Branches with meaningful names related +to what is being developed inside each branch. + +A branch name must be short and descriptive, all lowercase. +Again, keep modularity in mind. For branches with multiple words `use-hyphens`. + +Once a new function or a bug-fix is implemented, we [create a Pull Request](#pull-requests) +to merge changes back into `develop`. + +And once we feel that there are enough changes to make a new version of the +project, we [create a Pull Request](#pull-requests) to merge changes into +`master`. + +Each merge into `master` is tagged, meaning there's a new release. +See [Versioning](#versioning). + +## Code Style + +We try to be consistent with our style. When you doubt whether you should write +`blah blah` or `yada yada`, follow the most important rule: +**optimize for readabaility**. + +That said, these are our suggested rules + +- Indent using 4 spaces +- Use spaces after commas (unless separated by newlines): `[1, 2, 3]`, `(a, b, c)`. +- Use spaces after flow control statements: `if ()`, `for ()`, `while ()` +- Use spaces around operators, except unaries: `x + y`, `x == y`, `x++`, `!x`. +- Try to keep the line length at ~85. If exceeded, separate it in different lines. +- `variable_names`, `CONSTANT_NAMES`, `Function_Names`, `StructureNames` +- Write branch names in all lowercase, separeted with hyphens, and avoiding verbs: `graphics-simplification`, `docs`, `population-dynamics` +- Insert new line before curly braces in blocks of code: + +```js + +// Do this +if (condition) +{ + +} + +// Instead of this +if (condition){ + +} +``` + +- Always use curly braces after flow control statements. Even if it's followed +by only one line: + + ```js + // Do this + if (condition) + { + doSomethingInOneLine() + } + + // Instead of this + if (condition) + doSomethingInOneLine() + ``` + +## Versioning + +We follow [SemVer](https://semver.org/). + +Yup, just read it. Nothing to add. + +## GitHub Related + +### Issues + +If you have a question, don't open an issue. You can read the +[FAQ](https://github.com/daque-dev/viare/blob/master/FAQ.md), or send us an e-mail +at [contact@daque.me](mailto:contact@daque.me?Subject=Question) + +Issues are intended for reporting bugs, or discussing new features. + +Fortunately, GitHub allows us to provide an issue template. When you try to file +a new issue, you'll see it. Try to fill it with all the info you can. + +Not all fields are required for every new issue. It depends on whether it is a bug +report, or an enhancement discussion. + +#### Bugs + +The most important thing, is providing the necessary information to allow us to +reproduce the problem. **Try to be as descriptive as possible.** + +Again, the best way to learn how to file an issue, is by taking a look at our +[issue template](https://github.com/daque-dev/viare/issues/new). + +#### Enhancements + +This includes style changes, new features implementation, and general discussion +on how to make ViaRE better. + +We are more permissive on the structure of these issues. Anyways, you should still +try to be as descriptive as possible. + +### Pull Requests + +Firs, you should read [Git Flow](#git-flow) and [Code Style](#code-style) sections. + +Once you have some changes that you'd like to see merged into our codebase, [open a +Pull Request](https://github.com/daque-dev/viare/pull/new/master). We also have +a PR template, that you'll see once you try to open one. + +Again, the most important thing is that you describe what changes you've made, and +why you made them. + +--- + +## Thanks! + +All that said, we will be very thankful and happy if you decide to contribute with +the project. + +Don't be afraid to contribute if you feel you can't fulfil all of the rules in here. + +We will help you to help us. + +Cheers! \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index b1be05d..20974a7 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,33 +1,62 @@ - + + + + + + + + ## Expected Behavior - - + ## Current Behavior - - - -## Possible Solution - - + -## Steps to Reproduce (for bugs) +## Steps to Reproduce 1. 2. -3. -4. ## Context - - + + + ## Your Environment - -* Version used: -* Environment name and version (e.g. PHP 5.4 on nginx 1.9.1): -* Server type and version: -* Operating System and version: -* Link to your project: + + +* ViaRE (release or commit): +* DMD: +* SDL2: +* SDL2_image: +* OpenGL: +* OS: + +## Possible Solution + + + + + + + + + + +## Suggested change + + + + +## Context + + + + +## Possible Implementation Design + + + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fab5004..174d759 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,14 +3,10 @@ ## Description -## Related Issue - - - - - ## Motivation and Context + + ## How Has This Been Tested? diff --git a/README.md b/README.md index 525de27..e8fa342 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ViaRE -[![Travis](https://img.shields.io/travis/viare/viare.svg?style=flat-square)](https://travis-ci.org/viare/viare) -[![Codecov](https://img.shields.io/codecov/c/github/viare/viare.svg?style=flat-square)](https://codecov.io/gh/viare/viare) +[![Travis](https://img.shields.io/travis/daque-dev/viare.svg?style=flat-square)](https://travis-ci.org/daque-dev/viare) +[![Codecov](https://img.shields.io/codecov/c/github/daque-dev/viare.svg?style=flat-square)](https://codecov.io/gh/daque-dev/viare) @@ -53,11 +53,14 @@ $ dub --version --- -ViaRE is built using [SDL2](https://www.libsdl.org/download-2.0.php) and Open GL. +ViaRE is built using [SDL2](https://www.libsdl.org/download-2.0.php), +[SDL2_image](https://www.libsdl.org/projects/SDL_image/)and Open GL. Doing a proper SDL2 installation for development on Windows can be tricky. [This video](https://www.youtube.com/watch?v=ybYMOKEW9IY) could be useful. +To install SDL2_image, follow those same instructions. + To install SDL2 on Linux, follow official [SDL instructions](https://wiki.libsdl.org/Installation). We recommend to follow "The Unix Way", as it will avoid missing .so files. @@ -94,44 +97,22 @@ This will run every `unittest` inside sourcecode. - [**quevangel**](https://github.com/quevangel) - *Initial work* - [**davidomarf**](https://github.com/davidomarf) - *Initial work* -See also the list of [contributors](https://github.com/your/project/contributors) who participated in this project. +See also the list of [contributors](https://github.com/daque-dev/viare/graphs/contributors) who participated in this project. ## License This project is licensed under the MIT License - see [LICENSE.md](LICENSE.md) file for details -## Acknowledgments - -* **Martin O'Leary**, [@mewo2](https://twitter.com/mewo2), for writing an extensive guide -on [generating fantasy maps](http://mewo2.com/notes/terrain/) and [naming languages](http://mewo2.com/notes/naming-language/) -* **Amit Patel**, [@redblobgames](https://twitter.com/redblobgames), for his writing about -[polygonal map generation](http://www-cs-students.stanford.edu/~amitp/game-programming/polygon-map-generation/) - - +As this list is growing bigger and bigger, there's now a separate file [REFERENCES.md](https://github.com/daque-dev/viare/blob/master/REFERENCES.md). +In it, we list all the resources we use to design and build ViaRE. \ No newline at end of file diff --git a/dub.json b/dub.json index 6375ac8..e8bdfc4 100644 --- a/dub.json +++ b/dub.json @@ -11,6 +11,6 @@ "dependencies": { "derelict-sdl2": "~>3.0.0-beta", "derelict-gl3": "~>2.0.0-beta", - "libdaque": "0.2.2" + "libdaque": "~>0.3.1-develop" } } diff --git a/dub.selections.json b/dub.selections.json index 4cbf6a2..0994db9 100644 --- a/dub.selections.json +++ b/dub.selections.json @@ -1,9 +1,9 @@ { "fileVersion": 1, "versions": { - "derelict-gl3": "2.0.0-beta.6", + "derelict-gl3": "2.0.0-beta.7", "derelict-sdl2": "3.0.0-beta.7", "derelict-util": "3.0.0-beta.2", - "libdaque": "0.2.2" + "libdaque": "0.3.1-develop" } } diff --git a/format.sh b/format.sh deleted file mode 100644 index 7704b99..0000000 --- a/format.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -find . -name "*.d" -exec dfmt -i '{}' ';' diff --git a/shaders/perspective-vertex.glsl b/shaders/perspective-vertex.glsl index 751e985..991a65b 100644 --- a/shaders/perspective-vertex.glsl +++ b/shaders/perspective-vertex.glsl @@ -7,6 +7,7 @@ uniform float z_near; uniform float z_far; uniform float alpha; uniform float xy_ratio; +uniform vec3 translation; uniform mat3 rotation; out vec4 v_color; @@ -19,7 +20,9 @@ void main() 0, 0, (z_far + z_near)/(z_far - z_near), -1, 0, 0, 2 * z_far * z_near/(z_far - z_near), 0); - gl_Position = perspective * vec4(in_position, 1); + vec3 rotated = rotation * in_position; + vec3 translated = rotated + translation; + gl_Position = perspective * vec4(translated, 1); v_color = in_color; } diff --git a/source/.editorconfig b/source/.editorconfig deleted file mode 100644 index f71b08a..0000000 --- a/source/.editorconfig +++ /dev/null @@ -1,6 +0,0 @@ -# EditorConfig - -root = true - -[*.d] -indent_style = tab diff --git a/source/app.d b/source/app.d index 7b3b6ba..826759b 100644 --- a/source/app.d +++ b/source/app.d @@ -4,12 +4,8 @@ import std.stdio; import std.file; import std.ascii; -import viare.tests.perspective; -import viare.tests.heightmap; - import daque.math.geometry; void main() { - perspectiveTest(); } diff --git a/source/heightmap/heightfunction.d b/source/heightmap/heightfunction.d index 0027148..a8f6480 100644 --- a/source/heightmap/heightfunction.d +++ b/source/heightmap/heightfunction.d @@ -2,5 +2,5 @@ module viare.heightmap.heightfunction; interface HeightFunction { - double opCall(double x, double y); + double opCall(double x, double y); } diff --git a/source/heightmap/heightmap.d b/source/heightmap/heightmap.d index ee67bd9..e362e29 100644 --- a/source/heightmap/heightmap.d +++ b/source/heightmap/heightmap.d @@ -2,65 +2,86 @@ module viare.heightmap.heightmap; import viare.heightmap.heightfunction; -class HeightMap +class Heightmap { private: - float[][] m_height; - const uint m_xlength; - const uint m_ylength; + float[][] m_height; + const uint m_xlength; + const uint m_ylength; public: - this(uint width, uint height) - { - m_xlength = width; - m_ylength = height; - import std.algorithm; + this(uint width, uint height) + { + m_xlength = width; + m_ylength = height; - m_height.length = width; - m_height.each!((ref column) => column.length = height); - m_height.each!((ref column) => column.each!((ref element) => element = 0)); - } + import std.algorithm; - uint getWidth() - { - return m_xlength; - } + m_height.length = width; + m_height.each!((ref column) => column.length = height); + m_height.each!((ref column) => column.each!((ref element) => element = 0)); + } - uint getHeight() - { - return m_ylength; - } + uint Get_Width() + { + return m_xlength; + } - ref float opIndex(uint i, uint j) - { - return m_height[i][j]; - } + uint Get_Height() + { + return m_ylength; + } - void fillByHeightFunction(HeightFunction heightFunction) - { - for (uint i; i < m_xlength; i++) - for (uint j; j < m_ylength; j++) - this[i, j] = heightFunction(cast(float) i / m_xlength, cast(float) j / m_ylength); - } + ref float opIndex(uint i, uint j) + { + return m_height[i][j]; + } - void normalize() - { - float lowest = this[0, 0], highest = this[0, 0]; + void Fill_By_Height_Function(HeightFunction height_function) + { + for (uint i; i < m_xlength; i++) + { + for (uint j; j < m_ylength; j++) + { + version(Windows) + { + import std.stdio; + writeln(cast(double)i / m_xlength); /// Don't know why. But fixes problem + } + this[i, j] = height_function(cast(double) i / m_xlength, cast(double) j / m_ylength); + } + } + } - for (uint i; i < m_xlength; i++) - for (uint j; j < m_ylength; j++) - { - if (this[i, j] < lowest) - lowest = this[i, j]; - if (this[i, j] > highest) - highest = this[i, j]; - } + void Normalize() + { + float lowest = this[0, 0], highest = this[0, 0]; - immutable maxRelativeHeight = highest - lowest; + for (uint i; i < m_xlength; i++) + { + for (uint j; j < m_ylength; j++) + { + if (this[i, j] < lowest) + { + lowest = this[i, j]; + } - for (uint i; i < m_xlength; i++) - for (uint j; j < m_ylength; j++) - this[i, j] = (this[i, j] - lowest) / maxRelativeHeight; - } + if (this[i, j] > highest) + { + highest = this[i, j]; + } + } + } + + immutable max_relative_height = highest - lowest; + + for (uint i; i < m_xlength; i++) + { + for (uint j; j < m_ylength; j++) + { + this[i, j] = (this[i, j] - lowest) / max_relative_height; + } + } + } } diff --git a/source/heightmap/quev.d b/source/heightmap/quev.d index 21150fe..411dacf 100644 --- a/source/heightmap/quev.d +++ b/source/heightmap/quev.d @@ -8,111 +8,112 @@ import viare.heightmap.heightfunction; struct QuevCenter { - double[2] position; - double weight; - double base; - double exponent; - double zoom; + double[2] position; + double weight; + double base; + double exponent; + double zoom; } interface QuevCentersGenerator { - QuevCenter[] opCall(uint noCenters); + QuevCenter[] opCall(uint noCenters); } class StdQuevCentersGenerator : QuevCentersGenerator { private: - Params m_params; + Parameters m_parameters; public: - struct Params - { - double[2]delegate() positionGenerator; - double delegate() weightGenerator; - double delegate() baseGenerator; - double delegate() exponentGenerator; - double delegate() zoomGenerator; - } - - static Params defaultParams; - - static this() - { - defaultParams.positionGenerator = { - double x = uniform!"[)"(0.0, 1.0); - double y = uniform!"[)"(0.0, 1.0); - double[2] position = [x, y]; - return position; - }; - defaultParams.weightGenerator = { return uniform!"[]"(-1.0, 1.0); }; - defaultParams.baseGenerator = { return uniform!"[]"(20.1, 40.2); }; - defaultParams.exponentGenerator = { return uniform!"[]"(1.2, 1.5); }; - defaultParams.zoomGenerator = { return uniform!"[]"(0.125, 0.175); }; - } - - this(Params params) - { - m_params = params; - } - - this() - { - this(defaultParams); - } - - QuevCenter[] opCall(uint noCenters) - { - QuevCenter[] centers; - for (uint centerNo; centerNo < noCenters; centerNo++) - { - QuevCenter newCenter; - newCenter.position[] = m_params.positionGenerator()[]; - newCenter.weight = m_params.weightGenerator(); - newCenter.base = m_params.baseGenerator(); - newCenter.exponent = m_params.exponentGenerator(); - newCenter.zoom = m_params.zoomGenerator(); - centers ~= newCenter; - } - return centers; - } + struct Parameters + { + double[2]delegate() position_generator; + double delegate() weight_generator; + double delegate() base_generator; + double delegate() exponent_generator; + double delegate() zoom_generator; + } + + static Parameters default_parameters; + + static this() + { + default_parameters.position_generator = { + double x = uniform!"[)"(0.0, 1.0); + double y = uniform!"[)"(0.0, 1.0); + double[2] position = [x, y]; + return position; + }; + default_parameters.weight_generator = { return uniform!"[]"(-1.0, 1.0); }; + default_parameters.base_generator = { return uniform!"[]"(1000.1, 1000.2); }; + default_parameters.exponent_generator = { return uniform!"[]"(1.2, 5.6); }; + default_parameters.zoom_generator = { return uniform!"[]"(0.125, 0.175); }; + } + + this(Parameters parameters) + { + m_parameters = parameters; + } + + this() + { + this(default_parameters); + } + + QuevCenter[] opCall(uint no_centers) + { + QuevCenter[] centers; + for (uint center_number; center_number < no_centers; center_number++) + { + QuevCenter center; + center.position[] = m_parameters.position_generator()[]; + center.weight = m_parameters.weight_generator(); + center.base = m_parameters.base_generator(); + center.exponent = m_parameters.exponent_generator(); + center.zoom = m_parameters.zoom_generator(); + centers ~= center; + } + return centers; + } } class QuevHeightFunction : HeightFunction { private: - QuevCenter[] m_centers; - double[] m_threshholds; + QuevCenter[] m_centers; + double[] m_threshholds; - static immutable epsilon = 0.01; + static immutable epsilon = 0.01; public: - this(QuevCenter[] centers) - { - m_centers.length = centers.length; - m_centers[] = centers[]; - - m_threshholds.length = m_centers.length; - - foreach (uint i, QuevCenter center; m_centers) - { - m_threshholds[i] = center.zoom * pow(-log(epsilon / abs(center.weight)) / log(center.base), - 1.0 / center.exponent); - } - } - - double opCall(double x, double y) - { - double[2] point = [x, y]; - double total = 0.0; - - foreach (uint i, QuevCenter center; m_centers) - { - immutable distanceToCenter = distance!double(point, center.position); - if (distanceToCenter > m_threshholds[i]) - continue; - - total += center.weight * pow(center.base, - -pow(distanceToCenter / center.zoom, center.exponent)); - } - return total; - } + + this(QuevCenter[] centers) + { + m_centers.length = centers.length; + m_centers[] = centers[]; + + m_threshholds.length = m_centers.length; + + foreach (uint i, QuevCenter center; m_centers) + { + m_threshholds[i] = center.zoom * pow(-log(epsilon / abs( + center.weight)) / log(center.base), 1.0 / center.exponent); + } + } + + double opCall(double x, double y) + { + double[2] point = [x, y]; + double total = 0.0; + + foreach (uint i, QuevCenter center; m_centers) + { + immutable distance_to_center = distance!double(point, center.position); + if (distance_to_center > m_threshholds[i]) + continue; + + total += center.weight * pow(center.base, + -pow(distance_to_center / center.zoom, center.exponent)); + } + return total; + } } diff --git a/source/heightmap/renderer.d b/source/heightmap/renderer.d index d14b5f1..d311c91 100644 --- a/source/heightmap/renderer.d +++ b/source/heightmap/renderer.d @@ -5,79 +5,132 @@ import daque.graphics.color; import viare.heightmap.heightmap; -interface HeightMapRenderer +struct WaterTerrainHeightmapRenderSettings { public: - Image render(HeightMap heightMap); + float[3] water_tint = [0.0, 0.0, 1.0], terrain_tint = [0.0, 1.0, 0.0]; + float water_level = 0.0f; + uint divisions = 0x100; } -class WaterTerrainHeightMapRenderer : HeightMapRenderer +struct Vertex { -public: - /++ - Renders a HeightMap into an Image - - Params: - heightMap = heightmap to be rendered - - Returns: - The image on which the heightmap was rendered - +/ - Image render(HeightMap heightMap) - { - immutable heightMapWidth = heightMap.getWidth(); - immutable heightMapHeight = heightMap.getHeight(); - Image image = new Image(heightMapWidth, heightMapHeight); - - for (uint x; x < heightMapWidth; x++) - { - for (uint y; y < heightMapHeight; y++) - { - immutable cellHeight = heightMap[x, y]; - immutable bool isWater = (cellHeight <= m_waterLevel); - immutable float[3] tint = isWater ? m_waterTint : m_terrainTint; - assert(m_divisions != 0); - immutable heightPerDivision = 1.0f / cast(float) m_divisions; - immutable uint division = cellHeight == 1.0f ? m_divisions - 1 - : cast(uint)(cellHeight / heightPerDivision); - immutable float[3] colorFloat = tint[] * (division * heightPerDivision * 0xFF); - - import std.algorithm; - import std.array; - - Color color; - color.component[0 .. 3] = map!(c => cast(ubyte) c)(colorFloat[]).array; - color.component[3] = 0xFF; - - image[x, y] = color.toInt(); - } - } - - return image; - } - - void setWaterLevel(float waterLevel) - { - m_waterLevel = waterLevel; - } - - void setWaterTint(float[3] waterTint) - { - m_waterTint[] = waterTint[]; - } - - void setTerrainTint(float[3] terrainTint) - { - m_terrainTint[] = terrainTint[]; - } - - void setDivisions(uint divisions) - { - m_divisions = divisions; - } - -private: - float[3] m_waterTint, m_terrainTint; - float m_waterLevel; - uint m_divisions = 0x100; + float[3] position; + float[4] color; +} + +Vertex[] Get_Heightmap_Mesh(WaterTerrainHeightmapRenderSettings render_settings, float height, float[2] size, Heightmap heightmap) +{ + immutable heightmap_width = heightmap.Get_Width(); + immutable heightmap_height = heightmap.Get_Height(); + + float[2] Get_Base(uint i, uint j) + { + float[2] base; + base[0] = (i + 1.0f) / (heightmap_width + 1.0f) * size[0] - size[0] * 0.5f; + base[1] = (j + 1.0f) / (heightmap_height + 1.0f) * size[1] - size[1] * 0.5f; + return base; + } + + Vertex Get_Vertex(uint i, uint j) + { + auto base = Get_Base(i, j); + float normal_height = heightmap[i, j]; + float point_height = normal_height * height; + bool is_water = (normal_height <= render_settings.water_level); + auto tint = is_water? render_settings.water_tint: render_settings.terrain_tint; + + immutable height_per_division = 1.0f / cast(float) render_settings.divisions; + immutable uint division = + normal_height == 1.0f ? + render_settings.divisions - 1 + : + cast(uint)(normal_height / height_per_division); + + point_height = height_per_division * division * height; + + Vertex vertex; + vertex.position[] = [base[0], point_height, base[1]]; + vertex.color[0 .. 3] = height_per_division * division * tint[]; + vertex.color[3] = 1.0f; + return vertex; + } + + Vertex[] mesh; + for(uint i; i + 1 < heightmap_width; i++) + { + for(uint j; j + 1 < heightmap_height; j++) + { + Vertex[2][2] vertex; + + for(uint di; di < 2; di++) + { + for(uint dj; dj < 2; dj++) + { + vertex[di][dj] = Get_Vertex(i + di, j + dj); + } + } + + mesh ~= vertex[0][0]; + mesh ~= vertex[1][0]; + mesh ~= vertex[0][1]; + + mesh ~= vertex[1][0]; + mesh ~= vertex[1][1]; + mesh ~= vertex[0][1]; + } + } + + return mesh; +} +/++ + Renders a Heightmap into an Image + + Params: + heightMap = heightmap to be rendered + + Returns: + The image on which the heightmap was rendered ++/ + +Image Render(WaterTerrainHeightmapRenderSettings render_settings, Heightmap heightmap) +{ + immutable heightmap_width = heightmap.Get_Width(); + immutable heightmap_height = heightmap.Get_Height(); + Image image = new Image(heightmap_width, heightmap_height); + + for (uint x; x < heightmap_width; x++) + { + for (uint y; y < heightmap_height; y++) + { + immutable cell_height = heightmap[x, y]; + + immutable bool is_water = (cell_height <= render_settings.water_level); + + immutable float[3] tint = is_water ? render_settings.water_tint : render_settings.terrain_tint; + + assert(render_settings.divisions != 0); + + immutable height_per_division = 1.0f / cast(float) render_settings.divisions; + + immutable uint division = + cell_height == 1.0f? + render_settings.divisions - 1 + : + cast(uint)(cell_height / height_per_division); + + immutable float[3] color_float = tint[] * (division * height_per_division * 0xFF); + + import std.algorithm; + import std.array; + + Color color; + color.component[0 .. 3] = map!(c => cast(ubyte) c)(color_float[]).array; + color.component[3] = 0xFF; + + image[x, y] = color.toInt(); + } + } + + return image; } diff --git a/source/tests/heightmaptest.d b/source/tests/heightmaptest.d deleted file mode 100644 index 123a38e..0000000 --- a/source/tests/heightmaptest.d +++ /dev/null @@ -1,139 +0,0 @@ -// Core of the game -module viare.tests.heightmap; - -import std.stdio; -import std.file; -import std.ascii; -import std.uni; -import std.string; -import std.math; -import std.random; - -import core.thread; - -import derelict.opengl; -import derelict.sdl2.sdl; -import derelict.sdl2.image; - -import daque.math.linear; -import daque.math.geometry; - -import daque.graphics.opengl; -import daque.graphics.sdl; -import daque.graphics.color; -import daque.graphics.image; - -import viare.models; - -import viare.heightmap.quev; -import viare.heightmap.heightmap; -import viare.heightmap.heightfunction; -import viare.heightmap.renderer; - -void heightMapDebugging() -{ - immutable noCenters = uniform!"[]"(100, 200); - QuevCenter[] centers = new StdQuevCentersGenerator()(noCenters); - HeightFunction heightFunction = new QuevHeightFunction(centers); - - double first = heightFunction(0, 0); - double second = heightFunction(0.4, 0.4); - - writeln(first); - writeln(second); -} - -/* -deprecated void heightMapTest() -{ - Window window = new Window("viare", 800, 800); - - // GLSL textureProgram - Program textureProgram = new Program([new Shader(Shader.Type.Vertex, "shaders/texture-vertex.glsl"), - new Shader(Shader.Type.Fragment, "shaders/texture-fragment.glsl")]); - textureProgram.link(); - - // Model setup - Vertex[] squareData = SQUARE_VERTICES.dup; - Vertex[] frontSquareData; - frontSquareData.length = squareData.length; - frontSquareData[] = squareData[]; - import std.algorithm; - frontSquareData.each!((ref v) => v.position[2] += 0.5); - - auto square = new GpuArray!Vertex(SQUARE_VERTICES.dup); - auto frontSquare = new GpuArray!Vertex(frontSquareData); - - // Texture creation - Texture testTexture = new Texture(100, 100); - Texture frontTexture = new Texture(100, 100); - - // Height Function - immutable numberOfCenters = uniform!"[]"(300, 400); - QuevCenter[] centers = new StdQuevCentersGenerator()(numberOfCenters); - HeightFunction heightFunction = new QuevHeightFunction(centers); - - // HeightMap Fill - HeightMap heightMap = new HeightMap(testTexture.width, testTexture.height); - writeln("Calculating heights"); - heightMap.fillByHeightFunction(heightFunction); - writeln("Finished calculating heights"); - heightMap.normalize(); - - // Tints - float[3] blueTint = [0.0f, 0.3f, 0.7]; - float[3] greenTint = [0.0f, 0.7f, 0.5f]; - float[3] whiteTint = [1.0f, 1.0f, 1.0f]; - float[3] brownTint = [0.7f, 0.5f, 0.3f]; - - // HeightMap Rendering Configuration - WaterTerrainHeightMapRenderer renderer = new WaterTerrainHeightMapRenderer(); - renderer.setWaterLevel(0.5); - renderer.setWaterTint(blueTint); - renderer.setTerrainTint(brownTint); - renderer.setDivisions(10); - - // HeightMap rendering - writeln("Rendering"); - Image image = renderer.render(heightMap); - testTexture.updateRegion(0, 0, testTexture.width, testTexture.height, - image.linearize!(MatrixOrder.RowMajor)()); - writeln("Finished rendering"); - - - setTextureUnit(0, testTexture); - setTextureUnit(1, frontTexture); - - glEnable(GL_DEPTH_TEST); - // Drawing operations - while (window.isOpen()) - { - window.clear(); - - textureProgram.use(); - - textureProgram.setUniform1i("sampler", 0); - render(square); - - textureProgram.setUniform1i("sampler", 1); - render(frontSquare); - - window.print(); - - SDL_Event event; - while (SDL_PollEvent(&event)) - { - switch (event.type) - { - case SDL_QUIT: - window.close(); - break; - default: - break; - } - } - } - - return; -} -*/ diff --git a/source/tests/perspectivetest.d b/source/tests/perspectivetest.d deleted file mode 100644 index 3b9b963..0000000 --- a/source/tests/perspectivetest.d +++ /dev/null @@ -1,127 +0,0 @@ -// Core of the game -module viare.tests.perspective; - -import std.stdio; -import std.file; -import std.ascii; -import std.uni; -import std.string; -import std.math; -import std.random; - -import core.thread; - -import derelict.opengl; -import derelict.sdl2.sdl; -import derelict.sdl2.image; - -import daque.math.geometry; -import daque.math.linear; -import daque.math.quaternion; - -import daque.graphics.opengl; -import daque.graphics.color; -import daque.graphics.image; -import daque.graphics.sdl; - -import viare.models; - -import viare.heightmap.quev; -import viare.heightmap.heightmap; -import viare.heightmap.heightfunction; -import viare.heightmap.renderer; - -struct Vertex -{ - float[3] position; - float[4] color; - // dfmt off - static AttributeFormat[] formats = [{ - index: 0, - size : 3, - type : GL_FLOAT, - normalized : GL_FALSE, - stride: Vertex.sizeof, - pointer : cast(void*) Vertex.position.offsetof - }, { - index: 1, - size : 4, - type : GL_FLOAT, - normalized : GL_TRUE, - stride : Vertex.sizeof, - pointer : cast(void*) Vertex.color.offsetof - }]; - // dfmt on -} - -void perspectiveTest() -{ - Window window = new Window("viare perspective test", 800, 600); - - Program perspectiveProgram = new Program(); - Shader vertexShader = new Shader(Shader.Type.Vertex, "shaders/perspective-vertex.glsl"); - Shader fragmentShader = new Shader(Shader.Type.Fragment, "shaders/perspective-fragment.glsl"); - perspectiveProgram.attach(vertexShader); - perspectiveProgram.attach(fragmentShader); - perspectiveProgram.link(); - - int uZn = perspectiveProgram.getUniformLocation("z_near"); - int uZf = perspectiveProgram.getUniformLocation("z_far"); - int alpha = perspectiveProgram.getUniformLocation("alpha"); - int xy_ratio = perspectiveProgram.getUniformLocation("xy_ratio"); - - writeln("uZn location = ", uZn); - writeln("zf location = ", uZf); - - perspectiveProgram.setUniform!(1, "f")(uZn, [1.0f]); - perspectiveProgram.setUniform!(1, "f")(uZf, [10.0f]); - perspectiveProgram.setUniform!(1, "f")(alpha, [45.0f]); - perspectiveProgram.setUniform!(1, "f")(xy_ratio, [800.0f / 600.0f]); - - float gotZf = 0.0f; - perspectiveProgram.getUniform!"f"(uZf, &gotZf); - - writeln("goZf = ", gotZf); - - // dfmt off - Vertex[] vertices = [{ - position: [0, 0, -1.5], - color : [1, 0, 0, 1] - }, { - position: [1, 0, -1.5], - color : [0, 1, 0, 1] - }, { - position: [0, 1, -1.5], - color : [0, 0, 1, 1] - }]; - // dfmt on - - auto gpuVertices = new GpuArray(vertices, cast(uint) vertices.length, Vertex.formats); - - auto dr = Quaternion!float.getRotation([1, 1, 1], 0.01); - - auto rotation = dr; - - while (window.isOpen()) - { - window.clear(); - - perspectiveProgram.use(); - render(gpuVertices); - - window.print(); - SDL_Event event; - while (SDL_PollEvent(&event)) - { - switch (event.type) - { - case SDL_QUIT: - window.close(); - break; - - default: - break; - } - } - } -}