summaryrefslogtreecommitdiff
path: root/terrain_cache.cpp
blob: 01cc161edd2dd6ba775edbd6f251701aae3cc4d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "terrain_cache.h"

/* TerrainCacheObject */

TerrainCacheObject::TerrainCacheObject(TerrainCache *cache, int64_t x, int64_t y, unsigned int width, unsigned int height, float *heights) {
	this->cache = cache;
	this->x = x;
	this->y = y;
	this->width = width;
	this->height = height;
	if(heights)
		this->heights = heights;
	else
		this->heights = cache->tl->get_chunk(x, y, width, height);
}

TerrainCacheObject::~TerrainCacheObject() {
	cache->tl->save_chunk(heights, x, y, width, height);
	delete[] heights;
}

/* TerrainCache */

TerrainCache::TerrainCache(fs::path root, size_t max_size) {
	this->max_size = max_size;
	tl = TerrainLoader::p(new TerrainLoader(root));
}

TerrainCache::TerrainCache(TerrainLoader::p loader, size_t max_size) {
	this->max_size = max_size;
	tl = loader;
}

TerrainCache::~TerrainCache() {
	caches.clear();
}

TerrainCacheObject::p TerrainCache::make_object(int64_t x, int64_t y, unsigned int width, unsigned int height, float *heights) {
	TerrainCacheObject::p ob(new TerrainCacheObject(this, x, y, width, height, heights));

	if(caches.size() >= max_size) {
		for(cache_map::iterator it = caches.begin(); it != caches.end(); it++) {
			if(it->second.use_count() == 1) {
				caches.erase(it);
				break;
			}
		}
	}

	caches.insert(std::pair<intpair, TerrainCacheObject::p>(intpair(x, y), ob));
	return ob;
}

TerrainCacheObject::p TerrainCache::get_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height) {
	cache_map::iterator it = caches.find(intpair(x, y));
	if(it != caches.end())
		return it->second;

	return make_object(x, y, width, height);
}

void TerrainCache::add_chunk(float *heights, int64_t x, int64_t y, unsigned int width, unsigned int height) {
	cache_map::iterator it = caches.find(intpair(x, y));
	if(it != caches.end())
		caches.erase(it);

	tl->save_chunk(heights, x, y, width, height);
	make_object(x, y, width, height, heights);
}

size_t TerrainCache::get_size() {
	return caches.size();
}