#ifndef _MODEL_OBJECT_HPP_ #define _MODEL_OBJECT_HPP_ #include #include "rusty.hpp" #include "basic_model.hpp" class SceneMgr { }; class ModelBasic { public: ModelBasic(ModelUnit u, VertCollection& v) : unit(u), vc(v) {} const VertexAttribute& get_attribute() { return vc.all_attributes()[index[0]]; } ModelBasic& set_attribute_index(uint32_t idx) { index[0] = idx; auto& vertices = vc.all_vertices(); for(uint32_t i = unit.vert_offset; i < unit.vert_offset + unit.vert_count; ++i) vertices[i].index[0] = idx; return *this; } ModelBasic& set_texture_index(uint32_t idx) { index[1] = idx; auto& vertices = vc.all_vertices(); for(uint32_t i = unit.vert_offset; i < unit.vert_offset + unit.vert_count; ++i) vertices[i].index[1] = idx; return *this; } uint32_t att_index() { return index[0]; } uint32_t tex_index() { return index[1]; } ModelUnit model_info() { return unit; } ModelBasic& set_matrix(tmath::fmat4 mat) { vc.all_attributes()[index[0]].matrix = mat; vc.all_attributes()[index[0]].nmatrix = mat.homo_inverse().transpose(); return *this; } ModelBasic& set_matrix_no_normal(tmath::fmat4 mat) { vc.all_attributes()[index[0]].matrix = mat; return *this; } ModelBasic& set_color(tmath::fvec4 color) { vc.all_attributes()[index[0]].color = color; return *this; } ModelBasic& set_mixcolor(tmath::fvec4 color) { vc.all_attributes()[index[0]].mixcolor = color; return *this; } private: ModelUnit unit; uint32_t index[2]; VertCollection& vc; }; class ModelObject { public: virtual bool update(double tm) = 0; }; namespace mdo { class MDLAxis : public ModelObject { public: MDLAxis(VertCollection& collection) { auto m1 = collection.gen_cylinder(0.05f, 0.05f, 1.0f, 16, 1); auto ptr1 = std::make_shared(m1, collection); ptr1->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().rotatey(pi * 0.5f)) .set_color({1.0f, 0.0f, 0.0f, 1.0f}); units.push_back(ptr1); auto m2 = collection.gen_cylinder(0.05f, 0.05f, 1.0f, 16, 1); auto ptr2 = std::make_shared(m2, collection); ptr2->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().rotatex(pi * -0.5f)) .set_color({0.0f, 0.85f, 0.3f, 1.0f}); units.push_back(ptr2); auto m3 = collection.gen_cylinder(0.05f, 0.05f, 1.0f, 16, 1); auto ptr3 = std::make_shared(m3, collection); ptr3->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity()) .set_color({0.0f, 0.2f, 1.0f, 1.0f}); units.push_back(ptr3); auto m4 = collection.gen_cylinder(0.1f, 0.0f, 0.2f, 16, 1); auto ptr4 = std::make_shared(m4, collection); ptr4->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().rotatey(pi * 0.5f).translate(1.0f, 0.0f, 0.0f)) .set_color({1.0f, 0.0f, 0.0f, 1.0f}); units.push_back(ptr4); auto m5 = collection.gen_cylinder(0.1f, 0.0f, 0.2f, 16, 1); auto ptr5 = std::make_shared(m5, collection); ptr5->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().rotatex(pi * -0.5f).translate(0.0f, 1.0f, 0.0f)) .set_color({0.0f, 0.85f, 0.3f, 1.0f}); units.push_back(ptr5); auto m6 = collection.gen_cylinder(0.1f, 0.0f, 0.2f, 16, 1); auto ptr6 = std::make_shared(m6, collection); ptr6->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().translate(0.0f, 0.0f, 1.0f)) .set_color({0.0f, 0.2f, 1.0f, 1.0f}); units.push_back(ptr6); } bool update(double tm) override { return false; } private: std::vector> units; }; class MDLUnits : public ModelObject { public: static tmath::fvec3 pos_center(int32_t x, int32_t y) { return tmath::fvec3{0.25f + x * 0.5f, 0.25f + (31 - y) * 0.5f, 0.0f}; } std::pair pos() { return std::make_pair(posx, posy); } std::pair target_pos() { return std::make_pair(tposx, tposy); } void set_pos(int32_t x, int32_t y) { posx = x; posy = y; auto pc = pos_center(x, y); self_matrix = tmath::fmat4::identity().translate(pc[0], pc[1], pc[2]); self_matrix_updated = true; } void set_target_pos(int32_t x, int32_t y) { tposx = x; tposy = y; } virtual void move_to(int32_t x, int32_t y, float tm) = 0; virtual void attack(MDLUnits&, float tm) = 0; virtual void damage(MDLUnits&, float tm) = 0; bool update(double tm) override { last_update = tm; self_matrix_updated = false; return false; } protected: int32_t posx; int32_t posy; int32_t tposx; int32_t tposy; float last_update = 0.0f; bool self_matrix_updated = false; tmath::fmat4 self_matrix; }; class MDLField : public ModelObject { public: MDLField(VertCollection& collection) { float tw = 1.0f / 32; float th = 1.0f / 32; for(uint32_t y = 0; y < 32; ++y) { for(uint32_t x = 0; x < 32; ++x) { auto m = collection.gen_square(tw * x, th * y, tw, th); auto ptr = std::make_shared(m, collection); ptr->set_attribute_index(collection.allocate_attribute_index()) .set_matrix_no_normal(tmath::fmat4::identity().scale(0.25f, 0.25f, 1.0f).translate(0.25f + x * 0.5f, 0.25f + y * 0.5f, 0.0f)) .set_texture_index(1); units.push_back(ptr); } } } bool update(double tm) override { if(hindex != -1) { units[hindex]->set_mixcolor({1.0f, 1.0f, 1.0f, std::sin((float)tm * 32.0f / pi) * 0.4f + 0.5f}); } auto iter = status.begin(); while(iter != status.end()) { auto cur = iter++; float delta = (tm - cur->second) * 2.0f; auto mc = units[cur->first]->get_attribute().mixcolor; if(mc[3] > delta) { mc[3] = mc[3] - delta; units[cur->first]->set_mixcolor(mc); cur->second = tm; } else { mc[3] = 0.0f; units[cur->first]->set_mixcolor(mc); status.erase(cur); } } last_update = tm; return false; } void mouse_point(float x, float y) { int32_t idx = -1; if(x > 0.0f && x < 16.0f && y > 0.0f && y < 16.0f) { int32_t bx = (int32_t)(x * 2.0f); int32_t by = (int32_t)(y * 2.0f); idx = bx + by * 32; } if(hindex == idx) return; status.erase(idx); if(hindex != -1) { status[hindex] = last_update; units[hindex]->set_mixcolor({1.0f, 1.0f, 1.0f, 0.9f}); } hindex = idx; } void mouse_press(bool up) { } void add_object(std::weak_ptr obj, int32_t x, int32_t y) { auto fid = uindex(x, y); if(objects[fid].lock() != nullptr) return; objects[fid] = obj; } std::shared_ptr get_unit(int32_t x, int32_t y) { return objects[uindex(x, y)].lock(); } static int32_t uindex(int32_t x, int32_t y) { return x + (31 - y) * 32; } private: int32_t hindex = -1; float last_update = 0.0f; rs::unordered_map status; std::vector> units; std::weak_ptr objects[1024]; }; class MDLUnit1 : public MDLUnits { public: MDLUnit1(VertCollection& collection) { auto m1 = collection.gen_solid_of_revolution(0.0f, 1.0f, [](float z){ return (z - 0.55f) * (z - 0.55f)* 0.5f + 0.1f; }, 32, 32); auto ptr1 = std::make_shared(m1, collection); ptr1->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().scale(1.0f, 1.0f, 0.5f)) .set_color({0.0f, 0.8f, 0.3f, 1.0f}); units.push_back(ptr1); auto m2 = collection.gen_octahedron(); auto ptr2 = std::make_shared(m2, collection); ptr2->set_attribute_index(collection.allocate_attribute_index()) .set_matrix(tmath::fmat4::identity().scale(0.2f, 0.2f, 0.4f).translate(0.0f, 0.0f, 1.0f)) .set_color({0.7f, 0.1f, 0.3f, 0.8f}); units.push_back(ptr2); } bool update(double tm) override { bool updated = self_matrix_updated; MDLUnits::update(tm); for(auto iter = updator.begin(); iter != updator.end();) { if((*iter)(tm)) updator.erase(iter++); else iter++; } if(updated) units[0]->set_matrix(self_matrix * tmath::fmat4::identity().scale(0.6f, 0.6f, 0.5f)); units[1]->set_matrix(self_matrix * tmath::fmat4::identity().scale(0.15f, 0.15f, 0.2f).rotatez(tm * 2.0f).translate(0.0f, 0.0f, 0.8f)); return !updator.empty(); } void move_to(int32_t x, int32_t y, float tm) { auto cur = pos_center(posx, posy); auto end = pos_center(x, y); posx = x; posy = y; add_move(cur, end, tm, {0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, nullptr); } void attack(MDLUnits& u, float tm) { auto [x, y] = u.pos(); auto cur = pos_center(posx, posy); auto src = pos_center(x, y); auto end = cur + (src - cur) * 0.8f; add_move(cur, end, tm * 0.5f, {0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, [this, &u, tm, end, cur](){ u.damage(*this, 0.2f); add_move(end, cur, tm * 0.5f, {0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, nullptr); }); } void damage(MDLUnits& u, float tm) { auto [fx, fy] = u.pos(); auto cur = pos_center(posx, posy); auto src = pos_center(fx, fy); auto end = cur + (cur - src) * 0.25f; add_move(cur, end, tm * 0.5f, {1.0f, 1.0f, 1.0f}, 0.0f, 0.9f, [this, tm, end, cur](){ add_move(end, cur, tm * 0.5f, {1.0f, 1.0f, 1.0f}, 0.9f, 0.0f, nullptr); }); } void add_move(tmath::fvec3 from, tmath::fvec3 to, float tm, tmath::fvec3 mc, float a1, float a2, const std::function& end_cb) { updator.push_back([this, from, to, st = last_update, tm, mc, a1, a2, end_cb](float t){ auto h = std::sqrt((to[0] - from[0]) * (to[0] - from[0]) + (to[1] - from[1]) * (to[1] - from[1]))* 1.0f; if(t >= st + tm) { if(end_cb) end_cb(); for(auto& m : units) m->set_mixcolor({mc[0], mc[1], mc[2], a2}); self_matrix = tmath::fmat4::identity().translate(to[0], to[1], to[2]); self_matrix_updated = true; return true; } else { float factor = (t - st) / tm; auto pos = from + (to - from) * factor; for(auto& m : units) m->set_mixcolor({mc[0], mc[1], mc[2], a1 + (a2 - a1) * factor}); self_matrix = tmath::fmat4::identity().translate(pos[0], pos[1], (factor - 0.5f) * (0.5f - factor) * h + h * 0.25f); self_matrix_updated = true; return false; } }); } private: std::vector> units; rs::list> updator; }; } #endif