paysages : Terrain painting (WIP).

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@494 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2013-01-14 13:28:42 +00:00 committed by ThunderK
parent 5cad0fb39a
commit 4c72cb5ded
7 changed files with 150 additions and 58 deletions

View file

@ -32,6 +32,8 @@ WidgetHeightMap::WidgetHeightMap(QWidget *parent, TerrainDefinition* terrain):
_last_time = QDateTime::currentDateTime(); _last_time = QDateTime::currentDateTime();
_mouse_moved = false; _mouse_moved = false;
_position_x = 0;
_position_z = 0;
_angle_h = 0.0; _angle_h = 0.0;
_angle_v = 0.3; _angle_v = 0.3;
@ -351,6 +353,7 @@ void WidgetHeightMap::updateVertexInfo()
{ {
int rx = HEIGHTMAP_RESOLUTION; int rx = HEIGHTMAP_RESOLUTION;
int rz = HEIGHTMAP_RESOLUTION; int rz = HEIGHTMAP_RESOLUTION;
int dx, dz;
_VertexInfo* old_vertices = _vertices; _VertexInfo* old_vertices = _vertices;
_vertices = new _VertexInfo[rx * rz]; _vertices = new _VertexInfo[rx * rz];
@ -363,10 +366,13 @@ void WidgetHeightMap::updateVertexInfo()
{ {
_VertexInfo* vertex = _vertices + z * rx + x; _VertexInfo* vertex = _vertices + z * rx + x;
vertex->point.x = (double)x; dx = _position_x + x - rx / 2;
vertex->point.z = (double)z; dz = _position_z + z - rz / 2;
vertex->point.y = terrainGetGridHeight(_terrain, x, z, 1); vertex->point.x = (double)dx;
vertex->point.z = (double)dz;
vertex->point.y = terrainGetGridHeight(_terrain, dx, dz, 1);
} }
} }

View file

@ -65,6 +65,8 @@ private:
QDateTime _last_time; QDateTime _last_time;
bool _mouse_moved; bool _mouse_moved;
int _position_x;
int _position_z;
double _angle_h; double _angle_h;
double _angle_v; double _angle_v;

View file

@ -25,7 +25,7 @@ static TerrainDefinition* _createDefinition()
definition->scaling = 1.0; definition->scaling = 1.0;
definition->shadow_smoothing = 0.0; definition->shadow_smoothing = 0.0;
definition->height_map = terrainHeightMapCreate(); definition->height_map = terrainHeightMapCreate(definition);
definition->_height_noise = noiseCreateGenerator(); definition->_height_noise = noiseCreateGenerator();

View file

@ -4,17 +4,20 @@
* Terrain height map painting. * Terrain height map painting.
*/ */
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "../tools/memory.h"
TerrainHeightMap* terrainHeightMapCreate() TerrainHeightMap* terrainHeightMapCreate(TerrainDefinition* terrain)
{ {
TerrainHeightMap* result; TerrainHeightMap* result;
result = malloc(sizeof(TerrainHeightMap)); result = malloc(sizeof(TerrainHeightMap));
result->terrain = terrain;
result->fixed_count = 0; result->fixed_count = 0;
result->fixed_data = malloc(sizeof(TerrainHeightMapData)); result->fixed_data = malloc(sizeof(TerrainHeightMapChunk));
result->floating_used = 0; result->floating_used = 0;
result->floating_data.data = malloc(sizeof(double)); result->floating_data.data = malloc(sizeof(double));
@ -40,7 +43,7 @@ static void _setFixedCount(TerrainHeightMap* heightmap, int new_count)
if (new_count > old_count) if (new_count > old_count)
{ {
heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapData) * new_count); heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapChunk) * new_count);
for (i = old_count; i < new_count; i++) for (i = old_count; i < new_count; i++)
{ {
heightmap->fixed_data[i].data = malloc(sizeof(double)); heightmap->fixed_data[i].data = malloc(sizeof(double));
@ -54,7 +57,7 @@ static void _setFixedCount(TerrainHeightMap* heightmap, int new_count)
} }
if (new_count > 0) if (new_count > 0)
{ {
heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapData) * new_count); heightmap->fixed_data = realloc(heightmap->fixed_data, sizeof(TerrainHeightMapChunk) * new_count);
} }
} }
@ -65,19 +68,20 @@ void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destinatio
{ {
int i; int i;
destination->terrain = source->terrain;
_setFixedCount(destination, source->fixed_count); _setFixedCount(destination, source->fixed_count);
for (i = 0; i < destination->fixed_count; i++) for (i = 0; i < destination->fixed_count; i++)
{ {
destination->fixed_data[i].xstart = source->fixed_data[i].xstart; TerrainHeightMapChunk* chunk = destination->fixed_data + i;
destination->fixed_data[i].xsize = source->fixed_data[i].xsize;
destination->fixed_data[i].zstart = source->fixed_data[i].zstart; chunk->rect = chunk->rect;
destination->fixed_data[i].zsize = source->fixed_data[i].zsize; if (chunk->rect.xsize * chunk->rect.zsize > 0)
if (destination->fixed_data[i].xsize * destination->fixed_data[i].zsize > 0)
{ {
destination->fixed_data[i].data = realloc(destination->fixed_data[i].data, sizeof(double) * destination->fixed_data[i].xsize * destination->fixed_data[i].zsize); chunk->data = realloc(chunk->data, sizeof(double) * chunk->rect.xsize * chunk->rect.zsize);
} }
memcpy(destination->fixed_data[i].data, source->fixed_data[i].data, sizeof(double) * destination->fixed_data[i].xsize * destination->fixed_data[i].zsize); memcpy(chunk->data, chunk->data, sizeof(double) * chunk->rect.xsize * chunk->rect.zsize);
} }
destination->floating_used = 0; destination->floating_used = 0;
@ -90,13 +94,17 @@ void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap)
packWriteInt(stream, &heightmap->fixed_count); packWriteInt(stream, &heightmap->fixed_count);
for (i = 0; i < heightmap->fixed_count; i++) for (i = 0; i < heightmap->fixed_count; i++)
{ {
packWriteInt(stream, &heightmap->fixed_data[i].xstart); TerrainHeightMapChunk* chunk = heightmap->fixed_data + i;
packWriteInt(stream, &heightmap->fixed_data[i].xsize);
packWriteInt(stream, &heightmap->fixed_data[i].zstart); packWriteInt(stream, &chunk->rect.xstart);
packWriteInt(stream, &heightmap->fixed_data[i].zsize); packWriteInt(stream, &chunk->rect.xend);
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize; j++) packWriteInt(stream, &chunk->rect.xsize);
packWriteInt(stream, &chunk->rect.zstart);
packWriteInt(stream, &chunk->rect.zend);
packWriteInt(stream, &chunk->rect.zsize);
for (j = 0; j < chunk->rect.xsize * chunk->rect.zsize; j++)
{ {
packWriteDouble(stream, &heightmap->fixed_data[i].data[j]); packWriteDouble(stream, &chunk->data[j]);
} }
} }
} }
@ -110,26 +118,30 @@ void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
for (i = 0; i < heightmap->fixed_count; i++) for (i = 0; i < heightmap->fixed_count; i++)
{ {
packReadInt(stream, &heightmap->fixed_data[i].xstart); TerrainHeightMapChunk* chunk = heightmap->fixed_data + i;
packReadInt(stream, &heightmap->fixed_data[i].xsize);
packReadInt(stream, &heightmap->fixed_data[i].zstart); packReadInt(stream, &chunk->rect.xstart);
packReadInt(stream, &heightmap->fixed_data[i].zsize); packReadInt(stream, &chunk->rect.xend);
if (heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize > 0) packReadInt(stream, &chunk->rect.xsize);
packReadInt(stream, &chunk->rect.zstart);
packReadInt(stream, &chunk->rect.zend);
packReadInt(stream, &chunk->rect.zsize);
if (chunk->rect.xsize * chunk->rect.zsize > 0)
{ {
heightmap->fixed_data[i].data = realloc(heightmap->fixed_data[i].data, sizeof(double) * heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize); chunk->data = realloc(chunk->data, sizeof(double) * chunk->rect.xsize * chunk->rect.zsize);
} }
for (j = 0; j < heightmap->fixed_data[i].xsize * heightmap->fixed_data[i].zsize; j++) for (j = 0; j < chunk->rect.xsize * chunk->rect.zsize; j++)
{ {
packReadDouble(stream, &heightmap->fixed_data[i].data[j]); packReadDouble(stream, &chunk->data[j]);
} }
} }
heightmap->floating_used = 0; heightmap->floating_used = 0;
} }
static inline int _checkDataHit(TerrainHeightMapData* data, double x, double z, double* result) static inline int _checkDataHit(TerrainHeightMapChunk* chunk, double x, double z, double* result)
{ {
if (x > (double)data->xstart && x < (double)(data->xstart + data->xsize) && z > (double)data->zstart && z < (double)(data->zstart + data->zsize)) if (x > (double)chunk->rect.xstart && x < (double)chunk->rect.xend && z > (double)chunk->rect.zstart && z < (double)chunk->rect.zend)
{ {
/* TODO Get interpolated value */ /* TODO Get interpolated value */
*result = 0.0; *result = 0.0;
@ -163,38 +175,72 @@ int terrainHeightmapGetHeight(TerrainHeightMap* heightmap, double x, double z, d
} }
} }
static inline void _resetRect(TerrainHeightMap* heightmap, int x1, int x2, int z1, int z2)
{
int x, z;
for (x = x1; x <= x2; x++)
{
for (z = z1; z <= z2; z++)
{
heightmap->floating_data.data[z * heightmap->floating_data.rect.xsize + x] = terrainGetGridHeight(heightmap->terrain, x + heightmap->floating_data.rect.xstart, z + heightmap->floating_data.rect.zstart, 1);
}
}
}
static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush) static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush)
{ {
double cx = brush->relative_x;
double cz = brush->relative_z;
double s = brush->smoothed_size + brush->hard_radius; double s = brush->smoothed_size + brush->hard_radius;
double sx = s; int x1 = (int)floor(brush->relative_x - s);
double sz = s; int x2 = (int)ceil(brush->relative_x + s);
int z1 = (int)floor(brush->relative_z - s);
int x1 = (int)floor(cx - sx); int z2 = (int)ceil(brush->relative_z + s);
int x2 = (int)ceil(cx + sx);
int z1 = (int)floor(cz - sz);
int z2 = (int)ceil(cz + sz);
/* Prepare floating data */ /* Prepare floating data */
if (heightmap->floating_used) if (heightmap->floating_used)
{ {
/* Grow floating area */ int gx1 = (x1 < heightmap->floating_data.rect.xstart) ? heightmap->floating_data.rect.xstart - x1 : 0;
/* TODO */ int gx2 = (x2 > heightmap->floating_data.rect.xend) ? x2 - heightmap->floating_data.rect.xend : 0;
int gz1 = (z1 < heightmap->floating_data.rect.zstart) ? heightmap->floating_data.rect.zstart - z1 : 0;
int gz2 = (z2 > heightmap->floating_data.rect.zend) ? z2 - heightmap->floating_data.rect.zend : 0;
if (gx1 || gx2 || gz1 || gz2)
{
/* Floating area needs growing */
int new_width = heightmap->floating_data.rect.xsize + gx1 + gx2;
int new_height = heightmap->floating_data.rect.zsize + gz1 + gz2;
heightmap->floating_data.data = memory2dRealloc(heightmap->floating_data.data, sizeof(double), heightmap->floating_data.rect.xsize, heightmap->floating_data.rect.zsize, new_width, new_height, gx1, gz1);
heightmap->floating_data.rect.xstart -= gx1;
heightmap->floating_data.rect.xend += gx2;
heightmap->floating_data.rect.xsize += gx1 + gx2;
heightmap->floating_data.rect.zstart -= gz1;
heightmap->floating_data.rect.zend += gz2;
heightmap->floating_data.rect.zsize += gz1 + gz2;
_resetRect(heightmap, 0, new_width - 1, 0, gz1 - 1);
_resetRect(heightmap, 0, new_width - 1, new_height - gz2 + 1, new_height - 1);
_resetRect(heightmap, 0, gx1 - 1, gz1, new_height - gz2);
_resetRect(heightmap, new_width - gx2 + 1, new_width - 1, gz1, new_height - gz2);
}
} }
else else
{ {
/* Init flaoting area */ /* Init floating area */
heightmap->floating_used = 1; heightmap->floating_data.rect.xstart = x1;
heightmap->floating_data.xstart = x1; heightmap->floating_data.rect.xend = x2;
heightmap->floating_data.xsize = x2 - x1 + 1; heightmap->floating_data.rect.xsize = x2 - x1 + 1;
heightmap->floating_data.zstart = z1; heightmap->floating_data.rect.zstart = z1;
heightmap->floating_data.zsize = z2 - z1 + 1; heightmap->floating_data.rect.zend = z2;
heightmap->floating_data.rect.zsize = z2 - z1 + 1;
size_t new_size; size_t new_size;
new_size = sizeof(double) * heightmap->floating_data.xsize * heightmap->floating_data.zsize; new_size = sizeof(double) * heightmap->floating_data.rect.xsize * heightmap->floating_data.rect.zsize;
heightmap->floating_data.data = realloc(heightmap->floating_data.data, new_size); heightmap->floating_data.data = realloc(heightmap->floating_data.data, new_size);
memset(heightmap->floating_data.data, 0, new_size);
_resetRect(heightmap, 0, 0, heightmap->floating_data.rect.xsize - 1, heightmap->floating_data.rect.zsize - 1);
heightmap->floating_used = 1;
} }
} }

View file

@ -5,22 +5,27 @@
typedef struct typedef struct
{ {
int xstart; struct {
int zstart; int xstart;
int xsize; int xend;
int zsize; int xsize;
int zstart;
int zend;
int zsize;
} rect;
double* data; double* data;
} TerrainHeightMapData; } TerrainHeightMapChunk;
struct TerrainHeightMap struct TerrainHeightMap
{ {
TerrainDefinition* terrain;
int fixed_count; int fixed_count;
TerrainHeightMapData* fixed_data; TerrainHeightMapChunk* fixed_data;
int floating_used; int floating_used;
TerrainHeightMapData floating_data; TerrainHeightMapChunk floating_data;
}; };
TerrainHeightMap* terrainHeightMapCreate(); TerrainHeightMap* terrainHeightMapCreate(TerrainDefinition* definition);
void terrainHeightmapDelete(TerrainHeightMap* heightmap); void terrainHeightmapDelete(TerrainHeightMap* heightmap);
void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination); void terrainHeightmapCopy(TerrainHeightMap* source, TerrainHeightMap* destination);
void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap); void terrainHeightmapSave(PackStream* stream, TerrainHeightMap* heightmap);

View file

@ -0,0 +1,14 @@
#include "memory.h"
#include <assert.h>
void* memory2dRealloc(void* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset)
{
/* TODO Move remaining part*/
return realloc(data, datasize * newxsize * newysize);
}
void memory2dScrolling(void* data, int datasize, int xsize, int ysize, int xoffset, int yoffset)
{
/* TODO */
}

View file

@ -0,0 +1,19 @@
#ifndef _PAYSAGES_TOOLS_MEMORY_H_
#define _PAYSAGES_TOOLS_MEMORY_H_
/*
* Memory tools.
*/
#ifdef __cplusplus
extern "C" {
#endif
void* memory2dRealloc(void* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset);
void memory2dScrolling(void* data, int datasize, int xsize, int ysize, int xoffset, int yoffset);
#ifdef __cplusplus
}
#endif
#endif