#ifndef BASE_CLASS_H #define BASE_CLASS_H #define GLM_ENABLE_EXPERIMENTAL #include #include #include #include #include struct Vertex { vec3 pos; vec2 texCoord; bool operator==(const Vertex& other) const { return pos == other.pos && texCoord == other.texCoord; } };// Can't use __attribute__((packed)) due to non-POD vec2 and vec3 namespace std { template<> struct hash { size_t operator()(Vertex const& vertex) const { return ((hash()(vertex.pos) ^ (hash()(vertex.texCoord) << 1))); } }; } EXTERN unsigned int generic_program INIT(-1); struct GameObject { unsigned int vbuf, ebuf, tbuf, lbuf, vtbuf; unsigned int vertex_shader; unsigned int fragment_shader; unsigned int program; unsigned int vertex_attrib; unsigned int tex_attrib; unsigned int mvp_uniform; unsigned int tex_uniform; unsigned int element_count; unsigned int tex; const char *name; bool solid = false; bool invisible = false; bool dangerous = false; bool hostile = false; float radius = 1.0; vector locations; GameObject(const char *n) : name(n) {} virtual void movement() {}; virtual bool dangerous_at(vec4 loc) {return false;}; virtual void contact_at(size_t idx) {}; virtual float find_floor() {return -1000.0f;}; virtual void activate(float x, float y, float z) {}; bool init_from_object(const char *objfilename, vec3 (*input_transform)(float x, float y, float z) = 0); bool in_contact_radial_location(float x, float y, float z, int idx){ float dx = locations[idx].x - x; float dy = locations[idx].y - y; float dz = locations[idx].z - z; return (dx * dx + dy * dy + dz * dz) < (radius * radius); } virtual bool in_contact_location(float x, float y, float z, int i) { return in_contact_radial_location(x, y, z, i); } int in_contact(float x, float y, float z){ for(int i = 0; i < locations.size(); i++){ if(in_contact_location(x, y, z, i)) return i; } return -1; } virtual bool init() = 0; void draw_object(const mat4 &vp); bool setup_shaders(const char *vertex, const char *fragment); bool setup_standard_shaders(); bool setup_texture(const char *filename); bool setup_locations(){ glGenBuffers(1, &lbuf); update_locations(); return true; } virtual bool update_locations(){ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lbuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vec4) * locations.size(), locations.data(), GL_STATIC_DRAW); return true; } virtual void draw(mat4 vp) = 0; }; struct GenericObject : public GameObject { const char *objfile; const char *texfile; GenericObject(const char *n, const char *of, const char *tf) : GameObject(n), objfile(of), texfile(tf) {} bool init() override { init_from_object(objfile); setup_standard_shaders(); setup_texture(texfile); setup_locations(); return true; } void draw(mat4 vp){ draw_object(vp); } }; struct MovingGameObject : public GameObject { vector velocity; MovingGameObject(const char *name) : GameObject(name) {} void addnew_radial(float x, float y, float z, float speed, float heading, float elevation){ float vx = speed * cos(elevation) * cos(heading); float vy = speed * sin(elevation); float vz = speed * cos(elevation) * sin(heading); addnew_direct(x, y, z, vx, vy, vz); } void addnew_direct(float x, float y, float z, float vx, float vy, float vz){ locations.push_back(vec4(x, y, z, 0)); velocity.push_back(vec4(vx, vy, vz, 500)); } void addnew_direct(vec4 location, vec4 v){ locations.push_back(location); velocity.push_back(v); } void remove(size_t i){ velocity[i] = velocity[velocity.size() - 1]; velocity.pop_back(); locations[i] = locations[locations.size() - 1]; locations.pop_back(); } }; #endif