From 48494f9e180afc9bc03bc4da95b0cbc20eb44b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Wed, 26 Jun 2013 17:28:21 +0200 Subject: [PATCH] terrain_tessellation: Started new tessellation system --- src/rendering/terrain/public.h | 1 - src/rendering/terrain/ter_raster.c | 100 +++++++++++++++++++++-------- src/rendering/terrain/ter_raster.h | 42 ++++++++++++ 3 files changed, 116 insertions(+), 27 deletions(-) create mode 100644 src/rendering/terrain/ter_raster.h diff --git a/src/rendering/terrain/public.h b/src/rendering/terrain/public.h index dddf26f..ff9fc08 100644 --- a/src/rendering/terrain/public.h +++ b/src/rendering/terrain/public.h @@ -62,7 +62,6 @@ extern StandardDefinition TerrainDefinitionClass; extern StandardRenderer TerrainRendererClass; void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset); -void terrainRenderSurface(Renderer* renderer); double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int with_painting); double terrainGetInterpolatedHeight(TerrainDefinition* definition, double x, double z, int scaled, int with_painting); size_t terrainGetMemoryStats(TerrainDefinition* definition); diff --git a/src/rendering/terrain/ter_raster.c b/src/rendering/terrain/ter_raster.c index 7109435..93e934b 100644 --- a/src/rendering/terrain/ter_raster.c +++ b/src/rendering/terrain/ter_raster.c @@ -1,5 +1,6 @@ #include "public.h" #include "private.h" +#include "ter_raster.h" #include #include "../renderer.h" @@ -34,7 +35,7 @@ static void _renderQuad(Renderer* renderer, double x, double z, double size, dou Vector3 ov1, ov2, ov3, ov4; Vector3 dv1, dv2, dv3, dv4; - ov1.y = ov2.y = ov3.y = ov4.y; + ov1.y = ov2.y = ov3.y = ov4.y = 0.0; ov1.x = x; ov1.z = z; @@ -58,56 +59,103 @@ static void _renderQuad(Renderer* renderer, double x, double z, double size, dou } } -void terrainRenderSurface(Renderer* renderer) +void terrainTessellateChunk(Renderer* renderer, TerrainChunkInfo* chunk, int detail) { + /* TODO Tessellate ! */ + _renderQuad(renderer, chunk->point_nw.x, chunk->point_nw.z, chunk->point_ne.x - chunk->point_nw.x, renderer->water->getHeightInfo(renderer).min_height); +} + +static void _getChunk(Renderer* renderer, TerrainChunkInfo* chunk, double x, double z, double size, double water_height, int displaced) +{ + chunk->point_nw = renderer->terrain->getResult(renderer, x, z, 1, displaced).location; + chunk->point_sw = renderer->terrain->getResult(renderer, x, z + size, 1, displaced).location; + chunk->point_se = renderer->terrain->getResult(renderer, x + size, z + size, 1, displaced).location; + chunk->point_ne = renderer->terrain->getResult(renderer, x + size, z, 1, displaced).location; + + /* TODO If displaced == 0, the detail_hint may be inaccurate (water and screen culling) */ + + if (chunk->point_nw.y >= water_height || chunk->point_sw.y >= water_height || chunk->point_se.y >= water_height || chunk->point_ne.y >= water_height) + { + /* TODO */ + chunk->detail_hint = 5; + } + else + { + chunk->detail_hint = -1; + } +} + +void terrainGetTessellationInfo(Renderer* renderer, FuncTerrainTessellationCallback callback, int displaced) +{ + TerrainChunkInfo chunk; int chunk_factor, chunk_count, i; Vector3 cam = renderer->getCameraLocation(renderer, VECTOR_ZERO); double cx = cam.x; double cz = cam.z; - double min_chunk_size, visible_chunk_size; - double radius_int, radius_ext, chunk_size; double water_height; + double progress; + double radius_int, radius_ext; + double base_chunk_size, chunk_size; - min_chunk_size = 0.2 / (double)renderer->render_quality; - visible_chunk_size = 0.1 / (double)renderer->render_quality; - if (renderer->render_quality > 7) - { - min_chunk_size *= 0.25; - visible_chunk_size *= 0.25; - } + base_chunk_size = 5.0 / (double)renderer->render_quality; chunk_factor = 1; chunk_count = 2; radius_int = 0.0; - radius_ext = min_chunk_size; - chunk_size = min_chunk_size; + radius_ext = base_chunk_size; + chunk_size = base_chunk_size; + progress = 0.0; /* TODO */ - water_height = renderer->water->getHeightInfo(renderer).max_height; + water_height = renderer->water->getHeightInfo(renderer).min_height; while (radius_int < 5000.0) { - if (!renderer->addRenderProgress(renderer, 0.0)) - { - return; - } - for (i = 0; i < chunk_count - 1; i++) { - _renderQuad(renderer, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, water_height); - _renderQuad(renderer, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, water_height); - _renderQuad(renderer, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, water_height); - _renderQuad(renderer, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, water_height); + _getChunk(renderer, &chunk, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, water_height, displaced); + if (!callback(renderer, &chunk, progress)) + { + return; + } + + _getChunk(renderer, &chunk, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, water_height, displaced); + if (!callback(renderer, &chunk, progress)) + { + return; + } + + _getChunk(renderer, &chunk, cx + radius_int - chunk_size * i, cz + radius_int, chunk_size, water_height, displaced); + if (!callback(renderer, &chunk, progress)) + { + return; + } + + _getChunk(renderer, &chunk, cx - radius_ext, cz + radius_int - chunk_size * i, chunk_size, water_height, displaced); + if (!callback(renderer, &chunk, progress)) + { + return; + } } - if (chunk_count % 64 == 0 && chunk_size / radius_int < visible_chunk_size) + if (radius_int > 20.0 && chunk_count % 64 == 0 && (double)chunk_factor < radius_int / 20.0) { chunk_count /= 2; chunk_factor *= 2; - /* TODO Fill in gaps with triangles */ } chunk_count += 2; - chunk_size = min_chunk_size * chunk_factor; + chunk_size = base_chunk_size * chunk_factor; radius_int = radius_ext; radius_ext += chunk_size; } } + +static int _standardTessellationCallback(Renderer* renderer, TerrainChunkInfo* chunk, double progress) +{ + terrainTessellateChunk(renderer, chunk, chunk->detail_hint); + return !renderer->render_interrupt; +} + +void terrainRenderSurface(Renderer* renderer) +{ + terrainGetTessellationInfo(renderer, _standardTessellationCallback, 0); +} diff --git a/src/rendering/terrain/ter_raster.h b/src/rendering/terrain/ter_raster.h new file mode 100644 index 0000000..a113f17 --- /dev/null +++ b/src/rendering/terrain/ter_raster.h @@ -0,0 +1,42 @@ +#ifndef _RENDERING_TERRAIN_RASTER_H_ +#define _RENDERING_TERRAIN_RASTER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + Vector3 point_nw; + Vector3 point_sw; + Vector3 point_se; + Vector3 point_ne; + int detail_hint; +} TerrainChunkInfo; + +typedef int (*FuncTerrainTessellationCallback)(Renderer* renderer, TerrainChunkInfo* chunk, double progress); + +/** + * Tessellate the terrain, yielding chunks information. + * + * The terrain will be broken in chunks, most detailed near the camera. + */ +void terrainGetTessellationInfo(Renderer* renderer, FuncTerrainTessellationCallback callback, int displaced); + +/** + * Tessellate a terrain chunk, pushing the quads in the render area. + */ +void terrainTessellateChunk(Renderer* renderer, TerrainChunkInfo* chunk, int detail); + +/** + * Start the final rasterization of terrain. + * + * This will push the rasterized quads in the render area, waiting for post process. + */ +void terrainRenderSurface(Renderer* renderer); + +#ifdef __cplusplus +} +#endif + +#endif