terrain_tessellation: Started new tessellation system
This commit is contained in:
parent
039e4bb3cb
commit
48494f9e18
3 changed files with 116 additions and 27 deletions
|
@ -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);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "public.h"
|
||||
#include "private.h"
|
||||
#include "ter_raster.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#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))
|
||||
for (i = 0; i < chunk_count - 1; i++)
|
||||
{
|
||||
_getChunk(renderer, &chunk, cx - radius_ext + chunk_size * i, cz - radius_ext, chunk_size, water_height, displaced);
|
||||
if (!callback(renderer, &chunk, progress))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < chunk_count - 1; i++)
|
||||
_getChunk(renderer, &chunk, cx + radius_int, cz - radius_ext + chunk_size * i, chunk_size, water_height, displaced);
|
||||
if (!callback(renderer, &chunk, progress))
|
||||
{
|
||||
_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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (chunk_count % 64 == 0 && chunk_size / radius_int < visible_chunk_size)
|
||||
_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 (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);
|
||||
}
|
||||
|
|
42
src/rendering/terrain/ter_raster.h
Normal file
42
src/rendering/terrain/ter_raster.h
Normal file
|
@ -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
|
Loading…
Reference in a new issue