paysages : Terrain painting improvements (WIP).
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@553 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
ae19273d18
commit
306a3fdd0b
5 changed files with 158 additions and 79 deletions
|
@ -2,13 +2,12 @@
|
|||
|
||||
#include <QTime>
|
||||
#include <QMouseEvent>
|
||||
#include <QWidget>
|
||||
#include <math.h>
|
||||
#include <GL/glu.h>
|
||||
#include <qt4/QtGui/qwidget.h>
|
||||
#include "tools.h"
|
||||
|
||||
#define HEIGHTMAP_RESOLUTION 256
|
||||
#define CAMERA_DISTANCE 200.0
|
||||
|
||||
WidgetHeightMap::WidgetHeightMap(QWidget *parent, TerrainDefinition* terrain):
|
||||
QGLWidget(parent)
|
||||
|
@ -39,7 +38,8 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, TerrainDefinition* terrain):
|
|||
_position_x = 0;
|
||||
_position_z = 0;
|
||||
_angle_h = 0.0;
|
||||
_angle_v = 0.8;
|
||||
_angle_v = 1.4;
|
||||
_distance = 100.0;
|
||||
|
||||
_brush_x = 0.0;
|
||||
_brush_z = 0.0;
|
||||
|
@ -365,7 +365,7 @@ void WidgetHeightMap::paintGL()
|
|||
// Place camera
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
gluLookAt(CAMERA_DISTANCE * cos(_angle_h) * cos(_angle_v), CAMERA_DISTANCE * sin(_angle_v), -CAMERA_DISTANCE * sin(_angle_h) * cos(_angle_v), 0.0, 0.0, 0.0, -cos(_angle_h) * sin(_angle_v), cos(_angle_v), sin(_angle_h) * sin(_angle_v));
|
||||
gluLookAt(_distance * cos(_angle_h) * cos(_angle_v), _distance * sin(_angle_v), -_distance * sin(_angle_h) * cos(_angle_v), 0.0, 0.0, 0.0, -cos(_angle_h) * sin(_angle_v), cos(_angle_v), sin(_angle_h) * sin(_angle_v));
|
||||
|
||||
// Place lights
|
||||
GLfloat light_position[] = { 40.0, 40.0, 40.0, 0.0 };
|
||||
|
|
|
@ -77,6 +77,7 @@ private:
|
|||
int _position_z;
|
||||
double _angle_h;
|
||||
double _angle_v;
|
||||
double _distance;
|
||||
|
||||
double _brush_x;
|
||||
double _brush_z;
|
||||
|
|
|
@ -375,7 +375,7 @@ double terrainGetGridHeight(TerrainDefinition* definition, int x, int z, int wit
|
|||
{
|
||||
double height;
|
||||
|
||||
if (!with_painting || !terrainHeightmapGetHeight(definition->height_map, (double)x, (double)z, &height))
|
||||
if (!with_painting || !terrainHeightmapGetGridHeight(definition->height_map, x, z, &height))
|
||||
{
|
||||
height = noiseGet2DTotal(definition->_height_noise, (double)x, (double)z);
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ double terrainGetInterpolatedHeight(TerrainDefinition* definition, double x, dou
|
|||
x /= definition->scaling;
|
||||
z /= definition->scaling;
|
||||
|
||||
if (!with_painting || !terrainHeightmapGetHeight(definition->height_map, x, z, &height))
|
||||
if (!with_painting || !terrainHeightmapGetInterpolatedHeight(definition->height_map, x, z, &height))
|
||||
{
|
||||
height = noiseGet2DTotal(definition->_height_noise, x, z);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
int z;
|
||||
int memsize;
|
||||
int pixel_groups_count;
|
||||
HeightMapPixelGroup* pixel_groups;
|
||||
} HeightMapRow;
|
||||
|
@ -45,6 +44,7 @@ static void _initData(HeightMapData* data)
|
|||
{
|
||||
data->rows_count = 0;
|
||||
data->rows = malloc(1);
|
||||
data->memsize = 0;
|
||||
}
|
||||
|
||||
static void _clearData(HeightMapData* data)
|
||||
|
@ -60,6 +60,7 @@ static void _clearData(HeightMapData* data)
|
|||
}
|
||||
data->rows_count = 0;
|
||||
data->rows = realloc(data->rows, 1);
|
||||
data->memsize = 0;
|
||||
}
|
||||
|
||||
static void _deleteData(HeightMapData* data)
|
||||
|
@ -70,9 +71,36 @@ static void _deleteData(HeightMapData* data)
|
|||
|
||||
static void _copyData(HeightMapData* source, HeightMapData* destination)
|
||||
{
|
||||
int i, j, n;
|
||||
size_t size;
|
||||
|
||||
_clearData(destination);
|
||||
|
||||
/* TODO */
|
||||
destination->rows_count = source->rows_count;
|
||||
if (destination->rows_count > 0)
|
||||
{
|
||||
size = sizeof(HeightMapRow) * destination->rows_count;
|
||||
destination->rows = realloc(destination->rows, size);
|
||||
destination->memsize += size;
|
||||
for (i = 0; i < destination->rows_count; i++)
|
||||
{
|
||||
destination->rows[i].z = source->rows[i].z;
|
||||
destination->rows[i].pixel_groups_count = source->rows[i].pixel_groups_count;
|
||||
size = sizeof(HeightMapPixelGroup) * destination->rows[i].pixel_groups_count;
|
||||
destination->rows[i].pixel_groups = malloc(size);
|
||||
destination->memsize += size;
|
||||
for (j = 0; j < destination->rows[i].pixel_groups_count; j++)
|
||||
{
|
||||
destination->rows[i].pixel_groups[j].xstart = source->rows[i].pixel_groups[j].xstart;
|
||||
destination->rows[i].pixel_groups[j].xend = source->rows[i].pixel_groups[j].xend;
|
||||
n = destination->rows[i].pixel_groups[j].xend - destination->rows[i].pixel_groups[j].xstart;
|
||||
size = sizeof(double) * n;
|
||||
destination->rows[i].pixel_groups[j].height = malloc(size);
|
||||
destination->memsize += size;
|
||||
memcpy(destination->rows[i].pixel_groups[j].height, source->rows[i].pixel_groups[j].height, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _saveData(PackStream* stream, HeightMapData* data)
|
||||
|
@ -98,25 +126,35 @@ static void _saveData(PackStream* stream, HeightMapData* data)
|
|||
static void _loadData(PackStream* stream, HeightMapData* data)
|
||||
{
|
||||
int i, j, k, n;
|
||||
size_t size;
|
||||
|
||||
_clearData(data);
|
||||
|
||||
packReadInt(stream, &data->rows_count);
|
||||
data->rows = realloc(data->rows, sizeof(HeightMapRow) * data->rows_count);
|
||||
for (i = 0; i < data->rows_count; i++)
|
||||
if (data->rows_count > 0)
|
||||
{
|
||||
packReadInt(stream, &data->rows[i].z);
|
||||
packReadInt(stream, &data->rows[i].pixel_groups_count);
|
||||
data->rows[i].pixel_groups = malloc(sizeof(HeightMapPixelGroup) * data->rows[i].pixel_groups_count);
|
||||
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
|
||||
size = sizeof(HeightMapRow) * data->rows_count;
|
||||
data->rows = realloc(data->rows, size);
|
||||
data->memsize += size;
|
||||
for (i = 0; i < data->rows_count; i++)
|
||||
{
|
||||
packReadInt(stream, &data->rows[i].pixel_groups[j].xstart);
|
||||
packReadInt(stream, &data->rows[i].pixel_groups[j].xend);
|
||||
n = data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart;
|
||||
data->rows[i].pixel_groups[j].height = malloc(sizeof(double) * n);
|
||||
for (k = 0; k < n; k++)
|
||||
packReadInt(stream, &data->rows[i].z);
|
||||
packReadInt(stream, &data->rows[i].pixel_groups_count);
|
||||
size = sizeof(HeightMapPixelGroup) * data->rows[i].pixel_groups_count;
|
||||
data->rows[i].pixel_groups = malloc(size);
|
||||
data->memsize += size;
|
||||
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
|
||||
{
|
||||
packReadDouble(stream, &data->rows[i].pixel_groups[j].height[k]);
|
||||
packReadInt(stream, &data->rows[i].pixel_groups[j].xstart);
|
||||
packReadInt(stream, &data->rows[i].pixel_groups[j].xend);
|
||||
n = data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart;
|
||||
size = sizeof(double) * n;
|
||||
data->rows[i].pixel_groups[j].height = malloc(size);
|
||||
data->memsize += size;
|
||||
for (k = 0; k < n; k++)
|
||||
{
|
||||
packReadDouble(stream, &data->rows[i].pixel_groups[j].height[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +165,7 @@ static void _loadData(PackStream* stream, HeightMapData* data)
|
|||
* If the location is not already in the heightmap, it is initialized with the terrain height.
|
||||
* This method will grow the heightmap as necessary (if 'grow' is set to false, NULL will be returned on missing pixels).
|
||||
*/
|
||||
static double* _getDataPointer(HeightMapData* data, int x, int z, TerrainDefinition* terrain, int grow)
|
||||
static double* _getDataPointer(HeightMapData* data, int x, int z, HeightMapData* fallback, TerrainDefinition* terrain, int grow)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -152,6 +190,7 @@ static double* _getDataPointer(HeightMapData* data, int x, int z, TerrainDefinit
|
|||
row->pixel_groups = malloc(1);
|
||||
|
||||
data->rows_count++;
|
||||
data->memsize += sizeof(HeightMapRow);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -192,6 +231,7 @@ static double* _getDataPointer(HeightMapData* data, int x, int z, TerrainDefinit
|
|||
pixel = pixel_group->height;
|
||||
|
||||
row->pixel_groups_count++;
|
||||
data->memsize += sizeof(HeightMapPixelGroup) + sizeof(double);
|
||||
}
|
||||
else if (x == pixel_group->xstart - 1)
|
||||
{
|
||||
|
@ -203,6 +243,7 @@ static double* _getDataPointer(HeightMapData* data, int x, int z, TerrainDefinit
|
|||
/* Extend the rowgroup at start */
|
||||
pixel_group->xstart--;
|
||||
pixel = naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, 0);
|
||||
data->memsize += sizeof(double);
|
||||
}
|
||||
else if (x == pixel_group->xend + 1)
|
||||
{
|
||||
|
@ -214,6 +255,7 @@ static double* _getDataPointer(HeightMapData* data, int x, int z, TerrainDefinit
|
|||
/* Extend the rowgroup at end */
|
||||
pixel_group->xend++;
|
||||
pixel = naiveArrayInsert((void**)&pixel_group->height, sizeof(double), pixel_group->xend - pixel_group->xstart, pixel_group->xend - pixel_group->xstart);
|
||||
data->memsize += sizeof(double);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -224,9 +266,24 @@ static double* _getDataPointer(HeightMapData* data, int x, int z, TerrainDefinit
|
|||
}
|
||||
|
||||
/* Reset pixel if it had been added */
|
||||
if (added && terrain)
|
||||
if (added && (terrain || fallback))
|
||||
{
|
||||
*pixel = terrainGetGridHeight(terrain, x, z, 0);
|
||||
if (fallback)
|
||||
{
|
||||
double* dpointer = _getDataPointer(fallback, x, z, NULL, terrain, 0);
|
||||
if (dpointer)
|
||||
{
|
||||
*pixel = *dpointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pixel = terrainGetGridHeight(terrain, x, z, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pixel = terrainGetGridHeight(terrain, x, z, 0);
|
||||
}
|
||||
}
|
||||
return pixel;
|
||||
}
|
||||
|
@ -269,53 +326,71 @@ void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
|
|||
_clearData(&heightmap->brush_data);
|
||||
}
|
||||
|
||||
static inline int _getInterpolatedValue(HeightMapData* data, double x, double z, double* result, TerrainDefinition* terrain)
|
||||
int terrainHeightmapGetGridHeight(TerrainHeightMap* heightmap, int x, int z, double* result)
|
||||
{
|
||||
/*if ((int)floor(x) >= chunk->rect.xstart && (int)floor(x) <= chunk->rect.xend && (int)floor(z) >= (double)chunk->rect.zstart && (int)floor(z) <= (double)chunk->rect.zend)
|
||||
double* dpointer;
|
||||
dpointer = _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0);
|
||||
if (dpointer)
|
||||
{
|
||||
double stencil[16];
|
||||
int ix, iz, cx, cz;
|
||||
int xmax = chunk->rect.xsize - 1;
|
||||
int zmax = chunk->rect.zsize - 1;
|
||||
int xlow;
|
||||
int zlow;
|
||||
|
||||
x -= chunk->rect.xstart;
|
||||
z -= chunk->rect.zstart;
|
||||
|
||||
xlow = floor(x);
|
||||
zlow = floor(z);
|
||||
|
||||
for (ix = xlow - 1; ix <= xlow + 2; ix++)
|
||||
{
|
||||
for (iz = zlow - 1; iz <= zlow + 2; iz++)
|
||||
{
|
||||
cx = ix < 0 ? 0 : ix;
|
||||
cx = cx > xmax ? xmax : cx;
|
||||
cz = iz < 0 ? 0 : iz;
|
||||
cz = cz > zmax ? zmax : cz;
|
||||
stencil[(iz - (zlow - 1)) * 4 + ix - (xlow - 1)] = chunk->data[cz * chunk->rect.xsize + cx];
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
*result = toolsBicubicInterpolate(stencil, x - (double)xlow, z - (double)zlow);
|
||||
}
|
||||
|
||||
*result = *dpointer;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}*/
|
||||
return 0;
|
||||
dpointer = _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0);
|
||||
if (dpointer)
|
||||
{
|
||||
*result = *dpointer;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int terrainHeightmapGetHeight(TerrainHeightMap* heightmap, double x, double z, double* result)
|
||||
int terrainHeightmapGetInterpolatedHeight(TerrainHeightMap* heightmap, double x, double z, double* result)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
int ix, iz;
|
||||
int xlow;
|
||||
int zlow;
|
||||
|
||||
xlow = floor(x);
|
||||
zlow = floor(z);
|
||||
|
||||
int hit = 0;
|
||||
for (ix = xlow - 1; ix <= xlow + 2 && !hit; ix++)
|
||||
{
|
||||
for (iz = zlow - 1; iz <= zlow + 2 && !hit; iz++)
|
||||
{
|
||||
if (_getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0))
|
||||
{
|
||||
hit = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit && result)
|
||||
{
|
||||
double stencil[16];
|
||||
double value;
|
||||
for (ix = xlow - 1; ix <= xlow + 2; ix++)
|
||||
{
|
||||
for (iz = zlow - 1; iz <= zlow + 2; iz++)
|
||||
{
|
||||
if (!terrainHeightmapGetGridHeight(heightmap, ix, iz, &value))
|
||||
{
|
||||
value = terrainGetGridHeight(heightmap->terrain, ix, iz, 0);
|
||||
}
|
||||
stencil[(iz - (zlow - 1)) * 4 + ix - (xlow - 1)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
*result = toolsBicubicInterpolate(stencil, x - (double)xlow, z - (double)zlow);
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
static inline IntegerRect _getBrushRect(TerrainBrush* brush)
|
||||
|
@ -341,25 +416,12 @@ static inline int _isInRect(IntegerRect rect, int x, int z)
|
|||
|
||||
size_t terrainGetMemoryStats(TerrainDefinition* definition)
|
||||
{
|
||||
TerrainHeightMap* heightmap = definition->height_map;
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
/*if (heightmap->floating_used)
|
||||
{
|
||||
result += sizeof(double) * heightmap->floating_data.rect.xsize * heightmap->floating_data.rect.zsize;
|
||||
}
|
||||
for (i = 0; i < heightmap->fixed_count; i++)
|
||||
{
|
||||
result += sizeof(double) * heightmap->fixed_data[i].rect.xsize * heightmap->fixed_data[i].rect.zsize;
|
||||
}*/
|
||||
|
||||
return result;
|
||||
return definition->height_map->merged_data.memsize + definition->height_map->brush_data.memsize;
|
||||
}
|
||||
|
||||
int terrainIsPainted(TerrainHeightMap* heightmap, int x, int z)
|
||||
{
|
||||
return _getDataPointer(&heightmap->brush_data, x, z, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, 0);
|
||||
return _getDataPointer(&heightmap->brush_data, x, z, NULL, NULL, 0) || _getDataPointer(&heightmap->merged_data, x, z, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
typedef double (*BrushCallback)(TerrainHeightMap* heightmap, TerrainBrush* brush, double x, double z, double basevalue, double influence, double force, void* data);
|
||||
|
@ -394,7 +456,7 @@ static inline void _applyBrush(TerrainHeightMap* heightmap, TerrainBrush* brush,
|
|||
influence = 1.0;
|
||||
}
|
||||
|
||||
double* dpointer = _getDataPointer(&heightmap->brush_data, x, z, heightmap->terrain, 1);
|
||||
double* dpointer = _getDataPointer(&heightmap->brush_data, x, z, &heightmap->merged_data, heightmap->terrain, 1);
|
||||
*dpointer = callback(heightmap, brush, dx, dz, *dpointer, influence, force, data);
|
||||
}
|
||||
}
|
||||
|
@ -467,5 +529,20 @@ void terrainBrushReset(TerrainHeightMap* heightmap, TerrainBrush* brush, double
|
|||
|
||||
void terrainEndBrushStroke(TerrainHeightMap* heightmap)
|
||||
{
|
||||
/* TODO Merge data */
|
||||
int i, j, k;
|
||||
HeightMapData* data = &heightmap->brush_data;
|
||||
|
||||
for (i = 0; i < data->rows_count; i++)
|
||||
{
|
||||
for (j = 0; j < data->rows[i].pixel_groups_count; j++)
|
||||
{
|
||||
for (k = 0; k < data->rows[i].pixel_groups[j].xend - data->rows[i].pixel_groups[j].xstart; k++)
|
||||
{
|
||||
double* dpointer = _getDataPointer(&heightmap->merged_data, data->rows[i].pixel_groups[j].xstart + k, data->rows[i].z, NULL, NULL, 1);
|
||||
*dpointer = data->rows[i].pixel_groups[j].height[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_clearData(&heightmap->brush_data);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ void terrainHeightmapDelete(TerrainHeightMap* heightmap);
|
|||
void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination);
|
||||
void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap);
|
||||
void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap);
|
||||
int terrainHeightmapGetHeight(TerrainHeightMap* heightmap, double x, double z, double* result);
|
||||
int terrainHeightmapGetInterpolatedHeight(TerrainHeightMap* heightmap, double x, double z, double* result);
|
||||
int terrainHeightmapGetGridHeight(TerrainHeightMap* heightmap, int x, int z, double* result);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue