Tessellate terrain chunks at optimal level, using projected bounding box
This commit is contained in:
parent
3e42320c3f
commit
390fa99bab
1 changed files with 64 additions and 11 deletions
|
@ -3,6 +3,8 @@
|
||||||
#include "ter_raster.h"
|
#include "ter_raster.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "../tools/boundingbox.h"
|
||||||
#include "../renderer.h"
|
#include "../renderer.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -61,8 +63,25 @@ static void _renderQuad(Renderer* renderer, double x, double z, double size, dou
|
||||||
|
|
||||||
void terrainTessellateChunk(Renderer* renderer, TerrainChunkInfo* chunk, int detail)
|
void terrainTessellateChunk(Renderer* renderer, TerrainChunkInfo* chunk, int detail)
|
||||||
{
|
{
|
||||||
/* TODO Tessellate ! */
|
if (detail < 1)
|
||||||
_renderQuad(renderer, chunk->point_nw.x, chunk->point_nw.z, chunk->point_ne.x - chunk->point_nw.x, renderer->water->getHeightInfo(renderer).min_height);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double water_height = renderer->water->getHeightInfo(renderer).min_height;
|
||||||
|
|
||||||
|
double startx = chunk->point_nw.x;
|
||||||
|
double startz = chunk->point_nw.z;
|
||||||
|
double size = (chunk->point_ne.x - chunk->point_nw.x) / (double)detail;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < detail; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < detail; j++)
|
||||||
|
{
|
||||||
|
_renderQuad(renderer, startx + (double)i * size, startz + (double)j * size, size, water_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _getChunk(Renderer* renderer, TerrainChunkInfo* chunk, double x, double z, double size, double water_height, int displaced)
|
static void _getChunk(Renderer* renderer, TerrainChunkInfo* chunk, double x, double z, double size, double water_height, int displaced)
|
||||||
|
@ -72,15 +91,49 @@ static void _getChunk(Renderer* renderer, TerrainChunkInfo* chunk, double x, dou
|
||||||
chunk->point_se = renderer->terrain->getResult(renderer, x + size, 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;
|
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) */
|
double displacement_power;
|
||||||
|
if (displaced)
|
||||||
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 */
|
displacement_power = 0.0;
|
||||||
chunk->detail_hint = 5;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
displacement_power = texturesGetMaximalDisplacement(renderer->textures->definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBox box;
|
||||||
|
boundingBoxReset(&box);
|
||||||
|
if (displacement_power > 0.0)
|
||||||
|
{
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_nw, v3(-displacement_power, displacement_power, -displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_nw, v3(-displacement_power, -displacement_power, -displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_sw, v3(-displacement_power, displacement_power, displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_sw, v3(-displacement_power, -displacement_power, displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_se, v3(displacement_power, displacement_power, displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_se, v3(displacement_power, -displacement_power, displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_ne, v3(displacement_power, displacement_power, -displacement_power)));
|
||||||
|
boundingBoxPushPoint(&box, v3Add(chunk->point_ne, v3(displacement_power, -displacement_power, -displacement_power)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boundingBoxPushPoint(&box, chunk->point_nw);
|
||||||
|
boundingBoxPushPoint(&box, chunk->point_sw);
|
||||||
|
boundingBoxPushPoint(&box, chunk->point_se);
|
||||||
|
boundingBoxPushPoint(&box, chunk->point_ne);
|
||||||
|
}
|
||||||
|
|
||||||
|
int coverage = cameraIsUnprojectedBoxInView(renderer->render_camera, &box);
|
||||||
|
if (coverage > 0)
|
||||||
|
{
|
||||||
|
chunk->detail_hint = (int)ceil(sqrt((double)coverage) / (double)(21 - 2 * renderer->render_quality));
|
||||||
|
if (chunk->detail_hint > 5 * renderer->render_quality)
|
||||||
|
{
|
||||||
|
chunk->detail_hint = 5 * renderer->render_quality;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not in view */
|
||||||
chunk->detail_hint = -1;
|
chunk->detail_hint = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,9 +143,6 @@ void terrainGetTessellationInfo(Renderer* renderer, FuncTerrainTessellationCallb
|
||||||
TerrainChunkInfo chunk;
|
TerrainChunkInfo chunk;
|
||||||
int chunk_factor, chunk_count, i;
|
int chunk_factor, chunk_count, i;
|
||||||
Vector3 cam = renderer->getCameraLocation(renderer, VECTOR_ZERO);
|
Vector3 cam = renderer->getCameraLocation(renderer, VECTOR_ZERO);
|
||||||
double cx = cam.x;
|
|
||||||
double cz = cam.z;
|
|
||||||
double water_height;
|
|
||||||
double progress;
|
double progress;
|
||||||
double radius_int, radius_ext;
|
double radius_int, radius_ext;
|
||||||
double base_chunk_size, chunk_size;
|
double base_chunk_size, chunk_size;
|
||||||
|
@ -106,7 +156,10 @@ void terrainGetTessellationInfo(Renderer* renderer, FuncTerrainTessellationCallb
|
||||||
chunk_size = base_chunk_size;
|
chunk_size = base_chunk_size;
|
||||||
progress = 0.0; /* TODO */
|
progress = 0.0; /* TODO */
|
||||||
|
|
||||||
water_height = renderer->water->getHeightInfo(renderer).min_height;
|
double cx = cam.x - fmod(cam.x, base_chunk_size);
|
||||||
|
double cz = cam.z - fmod(cam.x, base_chunk_size);
|
||||||
|
|
||||||
|
double water_height = renderer->water->getHeightInfo(renderer).min_height;
|
||||||
|
|
||||||
while (radius_int < 5000.0)
|
while (radius_int < 5000.0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue