summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--messages.cpp129
-rw-r--r--messages.h65
-rw-r--r--terrain_cache.cpp73
-rw-r--r--terrain_cache.h51
-rw-r--r--terrain_loader.cpp58
-rw-r--r--terrain_loader.h27
-rw-r--r--vector.cpp150
-rw-r--r--vector.h50
8 files changed, 603 insertions, 0 deletions
diff --git a/messages.cpp b/messages.cpp
new file mode 100644
index 0000000..7bff612
--- /dev/null
+++ b/messages.cpp
@@ -0,0 +1,129 @@
+#include "messages.h"
+
+using namespace message;
+
+/* MessageBase */
+
+MessageBase::MessageBase() {
+ type = MSG_TYPE_NONE;
+}
+
+void MessageBase::send(boost::asio::ip::tcp::socket& socket) {
+ boost::asio::write(socket, boost::asio::buffer(&type, sizeof(type)));
+ boost::asio::write(socket, b);
+}
+
+std::size_t MessageBase::payload_size() {
+ return 0;
+}
+
+void MessageBase::read(boost::asio::ip::tcp::socket& socket) {
+ boost::asio::streambuf::mutable_buffers_type buf = b.prepare(payload_size());
+ std::size_t size = boost::asio::read(socket, buf);
+ b.commit(size);
+}
+
+uint8_t MessageBase::read_type(boost::asio::ip::tcp::socket& socket) {
+ uint8_t type;
+ boost::asio::read(socket, boost::asio::buffer(&type, sizeof(uint8_t)));
+
+ return type;
+}
+
+/* Hello */
+
+Hello::Hello() {
+ type = MSG_TYPE_HELLO;
+}
+
+Hello::Hello(uint8_t version) {
+ type = MSG_TYPE_HELLO;
+
+ std::ostream os(&b);
+ os.write((const char*)&version, sizeof(version));
+}
+
+std::size_t Hello::payload_size() {
+ return sizeof(uint8_t);
+}
+
+uint8_t Hello::read_version() {
+ std::istream is(&b);
+ uint8_t version;
+ is.read((char*)&version, sizeof(version));
+ b.consume(sizeof(version));
+
+ return version;
+}
+
+/* Pos */
+
+Pos::Pos() {
+ type = MSG_TYPE_POS;
+}
+
+Pos::Pos(float x, float y, float z) {
+ type = MSG_TYPE_POS;
+
+ std::ostream os(&b);
+ os.write((const char*)&x, sizeof(x));
+ os.write((const char*)&y, sizeof(y));
+ os.write((const char*)&z, sizeof(z));
+}
+
+std::size_t Pos::payload_size() {
+ return sizeof(float)*3;
+}
+
+void Pos::get_pos(float& x, float& y, float& z) {
+ std::istream is(&b);
+ is.read((char*)&x, sizeof(x));
+ is.read((char*)&y, sizeof(y));
+ is.read((char*)&z, sizeof(z));
+}
+
+/* Chunk */
+
+Chunk::Chunk() {
+ type = MSG_TYPE_CHUNK;
+
+ got_coords = false;
+}
+
+Chunk::Chunk(int64_t x, int64_t y) {
+ type = MSG_TYPE_CHUNK;
+
+ std::ostream os(&b);
+ os.write((const char*)&x, sizeof(x));
+ os.write((const char*)&y, sizeof(y));
+
+ got_coords = true;
+}
+
+// TODO: move this elsewhere
+const int chunk_size = 32;
+const int chunk_size_total = chunk_size + 3;
+
+std::size_t Chunk::payload_size() {
+ return (got_coords ? sizeof(float)*chunk_size_total*chunk_size_total : sizeof(int64_t)*2);
+}
+
+void Chunk::set_data(float *data) {
+ std::ostream os(&b);
+ os.write((const char*)data, sizeof(float)*chunk_size_total*chunk_size_total);
+}
+
+float* Chunk::get_data() {
+ float *data = new float[chunk_size_total*chunk_size_total];
+ std::istream is(&b);
+ is.read((char*)data, sizeof(float)*chunk_size_total*chunk_size_total);
+
+ return data;
+}
+
+void Chunk::get_coords(int64_t& x, int64_t& y) {
+ std::istream is(&b);
+ is.read((char*)&x, sizeof(x));
+ is.read((char*)&y, sizeof(y));
+ got_coords = true;
+}
diff --git a/messages.h b/messages.h
new file mode 100644
index 0000000..021c175
--- /dev/null
+++ b/messages.h
@@ -0,0 +1,65 @@
+#ifndef MESSAGES_H
+#define MESSAGES_H
+
+#include <boost/asio.hpp>
+
+namespace message {
+
+enum MessageType {
+ MSG_TYPE_NONE = 0,
+ MSG_TYPE_HELLO,
+ MSG_TYPE_POS,
+ MSG_TYPE_CHUNK
+};
+
+class MessageBase {
+ protected:
+ uint8_t type;
+ boost::asio::streambuf b;
+
+ public:
+ MessageBase();
+ virtual ~MessageBase() {};
+
+ void send(boost::asio::ip::tcp::socket& socket);
+ virtual std::size_t payload_size();
+ virtual void read(boost::asio::ip::tcp::socket& socket);
+
+ static uint8_t read_type(boost::asio::ip::tcp::socket& socket);
+};
+
+class Hello : public MessageBase {
+ public:
+ Hello();
+ Hello(uint8_t version);
+
+ virtual std::size_t payload_size();
+ uint8_t read_version();
+};
+
+class Pos : public MessageBase {
+ public:
+ Pos();
+ Pos(float x, float y, float z);
+
+ virtual std::size_t payload_size();
+ void get_pos(float& x, float& y, float& z);
+};
+
+class Chunk : public MessageBase {
+ protected:
+ bool got_coords;
+
+ public:
+ Chunk();
+ Chunk(int64_t x, int64_t y);
+
+ virtual std::size_t payload_size();
+ void set_data(float *data);
+ float* get_data();
+ void get_coords(int64_t& x, int64_t& y);
+};
+
+}
+
+#endif
diff --git a/terrain_cache.cpp b/terrain_cache.cpp
new file mode 100644
index 0000000..01cc161
--- /dev/null
+++ b/terrain_cache.cpp
@@ -0,0 +1,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();
+}
diff --git a/terrain_cache.h b/terrain_cache.h
new file mode 100644
index 0000000..dcc4f34
--- /dev/null
+++ b/terrain_cache.h
@@ -0,0 +1,51 @@
+#ifndef TERRAIN_CACHE_H
+#define TERRAIN_CACHE_H
+
+#include "terrain_loader.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <map>
+#include <cstddef>
+
+class TerrainCache;
+
+struct TerrainCacheObject {
+ typedef boost::shared_ptr<TerrainCacheObject> p;
+
+ TerrainCache *cache;
+ float *heights;
+ int64_t x, y;
+ unsigned int width, height;
+
+ TerrainCacheObject(TerrainCache *cache, int64_t x, int64_t y, unsigned int width, unsigned int height, float *heights = NULL);
+ virtual ~TerrainCacheObject();
+};
+
+class TerrainCache {
+ friend class TerrainCacheObject;
+
+ private:
+ typedef std::pair<int64_t, int64_t> intpair;
+ typedef std::map<intpair, TerrainCacheObject::p> cache_map;
+
+ cache_map caches;
+ size_t max_size;
+
+ TerrainCacheObject::p make_object(int64_t x, int64_t y, unsigned int width, unsigned int height, float *heights = NULL);
+
+ public:
+ typedef boost::shared_ptr<TerrainCache> p;
+
+ TerrainCache(fs::path root, size_t max_size);
+ TerrainCache(TerrainLoader::p loader, size_t max_size);
+ virtual ~TerrainCache();
+
+ TerrainLoader::p tl;
+
+ TerrainCacheObject::p get_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height);
+ void add_chunk(float *heights, int64_t x, int64_t y, unsigned int width, unsigned int height);
+ size_t get_size();
+};
+
+#endif
diff --git a/terrain_loader.cpp b/terrain_loader.cpp
new file mode 100644
index 0000000..ef61e1e
--- /dev/null
+++ b/terrain_loader.cpp
@@ -0,0 +1,58 @@
+#include "terrain_loader.h"
+
+#include <boost/format.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include <stdexcept>
+
+TerrainLoader::TerrainLoader(fs::path root) {
+ this->root = root;
+}
+
+TerrainLoader::~TerrainLoader() {
+}
+float *TerrainLoader::get_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height) {
+ if(has_chunk(x, y))
+ return load_chunk(x, y, width, height);
+ return NULL;
+}
+
+bool TerrainLoader::has_chunk(int64_t x, int64_t y) {
+ return fs::exists(root / (boost::format("%d.%d.chunk") % x % y).str());
+}
+
+// TODO: Handle big-endian platforms
+void TerrainLoader::save_chunk(float *chunk, int64_t x, int64_t y, unsigned int width, unsigned int height) {
+ fs::path p = root / (boost::format("%d.%d.chunk") % x % y).str();
+ fs::ofstream os(p, std::ios::out | std::ios::binary);
+
+ uint64_t w = width;
+ uint64_t h = height;
+ os.write((const char*)&w, sizeof(w));
+ os.write((const char*)&h, sizeof(h));
+
+ os.write((const char*)chunk, width*height * sizeof(float));
+ os.close();
+}
+
+// TODO: Handle big-endian platforms
+// NOTE: assumes width <= chunk_size+1, likewise for height
+float *TerrainLoader::load_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height) {
+ fs::path p = root / (boost::format("%d.%d.chunk") % x % y).str();
+ fs::ifstream is(p, std::ios::in | std::ios::binary);
+
+ uint64_t w, h;
+ w = h = 0;
+ is.read((char*)&w, sizeof(w));
+ is.read((char*)&h, sizeof(h));
+
+ // TODO: should return w and h, fix calling code
+ if(w != width || h != height)
+ throw std::runtime_error("width or height doesn't match");
+
+ float *chunk = new float[width*height];
+ is.read((char*)chunk, width*height*sizeof(float));
+ is.close();
+
+ return chunk;
+}
diff --git a/terrain_loader.h b/terrain_loader.h
new file mode 100644
index 0000000..f99fb09
--- /dev/null
+++ b/terrain_loader.h
@@ -0,0 +1,27 @@
+#ifndef TERRAIN_LOADER_H
+#define TERRAIN_LOADER_H
+
+#include <boost/filesystem.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace fs = boost::filesystem;
+
+class TerrainLoader {
+ private:
+ fs::path root;
+
+ public:
+ typedef boost::shared_ptr<TerrainLoader> p;
+
+ TerrainLoader(fs::path root);
+ virtual ~TerrainLoader();
+
+ float *generate_heights(int64_t x, int64_t y, unsigned int width, unsigned int height);
+ virtual float *get_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height);
+ bool has_chunk(int64_t x, int64_t y);
+ void save_chunk(float *chunk, int64_t x, int64_t y, unsigned int width, unsigned int height);
+ float *load_chunk(int64_t x, int64_t y, unsigned int width, unsigned int height);
+
+};
+
+#endif
diff --git a/vector.cpp b/vector.cpp
new file mode 100644
index 0000000..cf2c164
--- /dev/null
+++ b/vector.cpp
@@ -0,0 +1,150 @@
+#include "vector.h"
+
+#include <boost/format.hpp>
+
+#include <cmath>
+#include <string>
+
+Vector2::Vector2() {
+ x = y = 0;
+}
+
+Vector2::Vector2(const Vector2& v) {
+ x = v.x;
+ y = v.y;
+}
+
+Vector2::Vector2(float x, float y) {
+ this->x = x;
+ this->y = y;
+}
+
+bool Vector2::operator==(const Vector2& v) const {
+ return x == v.x && y == v.y;
+}
+
+Vector2& Vector2::operator+=(const Vector2& v) {
+ x += v.x;
+ y += v.y;
+ return *this;
+}
+
+Vector2 Vector2::operator+(const Vector2& v) {
+ return Vector2(*this) += v;
+}
+
+Vector2& Vector2::operator-=(const Vector2& v) {
+ x -= v.x;
+ y -= v.y;
+ return *this;
+}
+
+Vector2 Vector2::operator-(const Vector2& v) {
+ return Vector2(*this) -= v;
+}
+
+Vector2& Vector2::operator*=(const float f) {
+ x *= f;
+ y *= f;
+ return *this;
+}
+
+Vector2& Vector2::operator/=(const float f) {
+ x /= f;
+ y /= f;
+ return *this;
+}
+
+float Vector2::length() {
+ return sqrtf(x*x + y*y);
+}
+
+std::string Vector2::str() {
+ return (boost::format("[%.2f %.2f]") % x % y).str();
+}
+
+/**
+ * Vector3
+ */
+
+Vector3::Vector3() {
+ x = y = z = 0;
+}
+
+Vector3::Vector3(const Vector3& v) : Vector2(v) {
+ z = v.z;
+}
+
+Vector3::Vector3(float x, float y, float z) : Vector2(x, y) {
+ this->z = z;
+}
+
+bool Vector3::operator==(const Vector3& v) {
+ return x == v.x && y == v.y && z == v.z;
+}
+
+Vector3& Vector3::operator+=(const Vector3& v) {
+ x += v.x;
+ y += v.y;
+ z += v.z;
+ return *this;
+}
+
+Vector3 Vector3::operator+(const Vector3& v) {
+ return Vector3(*this) += v;
+}
+
+Vector3& Vector3::operator-=(const Vector3& v) {
+ x -= v.x;
+ y -= v.y;
+ z -= v.z;
+ return *this;
+}
+
+Vector3 Vector3::operator-(const Vector3& v) {
+ return Vector3(*this) -= v;
+}
+
+Vector3& Vector3::operator*=(const float f) {
+ x *= f;
+ y *= f;
+ z *= f;
+ return *this;
+}
+
+Vector3 Vector3::operator*(const float f) {
+ return Vector3(*this) *= f;
+}
+
+Vector3& Vector3::operator/=(const float f) {
+ x /= f;
+ y /= f;
+ z /= f;
+ return *this;
+}
+
+Vector3 Vector3::operator/(const float f) {
+ return Vector3(*this) /= f;
+}
+
+Vector3 Vector3::cross(const Vector3& v) {
+ return Vector3(y*v.z - z*v.y,
+ z*v.x - x*v.z,
+ x*v.y - y*v.x);
+}
+
+float Vector3::dot(const Vector3& v) {
+ return x*v.x + y*v.y + z*v.z;
+}
+
+Vector2 Vector3::xz() {
+ return Vector2(x, z);
+}
+
+float Vector3::length() {
+ return sqrtf(x*x + y*y + z*z);
+}
+
+std::string Vector3::str() {
+ return (boost::format("[%.2f %.2f %.2f]") % x % y % z).str();
+}
diff --git a/vector.h b/vector.h
new file mode 100644
index 0000000..a2a3192
--- /dev/null
+++ b/vector.h
@@ -0,0 +1,50 @@
+#ifndef VECTOR_H
+#define VECTOR_H
+
+#include <boost/shared_ptr.hpp>
+
+#include <string>
+
+class Vector2 {
+ public:
+ float x, y;
+
+ Vector2();
+ Vector2(const Vector2& v);
+ Vector2(float x, float y);
+ bool operator==(const Vector2& v) const;
+ Vector2& operator+=(const Vector2& v);
+ Vector2 operator+(const Vector2& v);
+ Vector2& operator-=(const Vector2& v);
+ Vector2 operator-(const Vector2& v);
+ Vector2& operator*=(const float f);
+ Vector2& operator/=(const float f);
+ float length();
+ std::string str();
+};
+
+class Vector3 : public Vector2 {
+ public:
+ typedef boost::shared_ptr<Vector3> p;
+ float z;
+
+ Vector3();
+ Vector3(const Vector3& v);
+ Vector3(float x, float y, float z);
+ bool operator==(const Vector3& v);
+ Vector3& operator+=(const Vector3& v);
+ Vector3 operator+(const Vector3& v);
+ Vector3& operator-=(const Vector3& v);
+ Vector3 operator-(const Vector3& v);
+ Vector3& operator*=(const float f);
+ Vector3 operator*(const float f);
+ Vector3& operator/=(const float f);
+ Vector3 operator/(const float f);
+ Vector3 cross(const Vector3& v);
+ float dot(const Vector3& v);
+ Vector2 xz();
+ float length();
+ std::string str();
+};
+
+#endif