330 lines
12 KiB
C++
330 lines
12 KiB
C++
|
#ifndef _MODEL_OBJECT_HPP_
|
||
|
#define _MODEL_OBJECT_HPP_
|
||
|
|
||
|
#include <functional>
|
||
|
|
||
|
#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<ModelBasic>(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<ModelBasic>(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<ModelBasic>(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<ModelBasic>(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<ModelBasic>(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<ModelBasic>(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<std::shared_ptr<ModelBasic>> 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<int32_t, int32_t> pos() { return std::make_pair(posx, posy); }
|
||
|
std::pair<int32_t, int32_t> 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<ModelBasic>(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<MDLUnits> obj, int32_t x, int32_t y) {
|
||
|
auto fid = uindex(x, y);
|
||
|
if(objects[fid].lock() != nullptr)
|
||
|
return;
|
||
|
objects[fid] = obj;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<MDLUnits> 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<int32_t, float> status;
|
||
|
std::vector<std::shared_ptr<ModelBasic>> units;
|
||
|
std::weak_ptr<MDLUnits> 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<ModelBasic>(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<ModelBasic>(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<void()>& 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<std::shared_ptr<ModelBasic>> units;
|
||
|
rs::list<std::function<bool(float)>> updator;
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|