voxel_object::voxel_object(const variant& node) // The initializer list should NOT read from 'node'. It should only // set up default values. Read from node in the body. : translation_(0.0f), rotation_(0.0f), scale_(1.0f), cycle_(0), paused_(false), is_mouseover_(false) { if(node.has_key("type")) { const std::string type = node["type"].as_string(); const voxel_object* prototype = voxel_object_type::get(type)->prototype(); if(prototype) { *this = *prototype; } type_ = type; } if(!shader_ || node.has_key("shader")) { shader_ = gles2::shader_program::get_global(node["shader"].as_string())->shader(); } if(!model_ || node.has_key("model")) { std::map<variant,variant> m; m[variant("model")] = variant(model_path_get_or_die(node["model"].as_string())); model_.reset(new voxel_model(variant(&m))); model_->set_animation("stand"); } if(node.has_key("translation")) { translation_ = variant_to_vec3(node["translation"]); } if(node.has_key("rotation")) { rotation_ = variant_to_vec3(node["rotation"]); } if(node.has_key("scale")) { if(node["scale"].is_decimal()) { float scale = float(node["scale"].as_decimal().as_float()); scale_ = glm::vec3(scale, scale, scale); } else { scale_ = variant_to_vec3(node["scale"]); } } if(node.has_key("widgets")) { if(node["widgets"].is_list()) { for(int n = 0; n != node["widgets"].num_elements(); ++n) { widgets_.insert(widget_factory::create(node["widgets"][n], this)); } } } a_normal_ = shader_->get_fixed_attribute("normal"); mvp_matrix_ = shader_->get_fixed_uniform("mvp_matrix"); }
std::map<std::string, AttachmentPoint> read_attachment_points(const variant& v) { std::map<std::string, AttachmentPoint> result; for(auto p : v.as_map()) { AttachmentPoint point; point.name = p.first.as_string(); point.layer = p.second["layer"].as_string(); point.pivot = p.second["pivot"].as_string(); if(p.second["rotations"].is_list()) { for(auto rotation_node : p.second["rotations"].as_list()) { AttachmentPointRotation rotation; rotation.direction = variant_to_vec3(rotation_node["direction"]); rotation.amount = rotation_node["rotation"].as_decimal().as_float(); point.rotations.push_back(rotation); } } result[point.name] = point; } return result; }
void voxel_model::process_animation(GLfloat advance) { if(!anim_) { return; } if(anim_->duration > 0 && anim_time_ > anim_->duration) { set_animation("stand"); } anim_time_ += advance; const GLfloat TransitionTime = 0.5f; GLfloat ratio = 1.0f; if(old_anim_) { if(anim_time_ >= TransitionTime) { old_anim_.reset(); old_anim_time_ = 0.0f; } else { old_anim_time_ += advance; if(old_anim_->duration > 0.0f && old_anim_time_ > old_anim_->duration) { old_anim_time_ = old_anim_->duration; } ratio = anim_time_ / TransitionTime; } } clear_transforms(); game_logic::map_formula_callable_ptr callable(new game_logic::map_formula_callable); if(old_anim_) { callable->add("time", variant(decimal(old_anim_time_))); for(const AnimationTransform& transform : old_anim_->transforms) { glm::vec3 translate; if(transform.translation_formula) { const variant result = transform.translation_formula->execute(*callable); translate = variant_to_vec3(result)*(1.0f - ratio); } GLfloat rotation = 0.0; if(transform.rotation_formula) { rotation = transform.rotation_formula->execute(*callable).as_decimal().as_float(); } get_child(transform.layer)->accumulate_rotation(transform.pivot_src, transform.pivot_dst, rotation*(1.0-ratio), translate, transform.children_only); } } callable->add("time", variant(decimal(anim_time_))); for(const AnimationTransform& transform : anim_->transforms) { glm::vec3 translate; if(transform.translation_formula) { const variant result = transform.translation_formula->execute(*callable); translate = variant_to_vec3(result) * ratio; } GLfloat rotation = 0.0; if(transform.rotation_formula) { rotation = transform.rotation_formula->execute(*callable).as_decimal().as_float(); } get_child(transform.layer)->accumulate_rotation(transform.pivot_src, transform.pivot_dst, rotation*ratio, translate, transform.children_only); } generate_geometry(); }
Renderable::Renderable(const variant& node) : order_(0), position_(0.0f), rotation_(1.0f, 0.0f, 0.0f, 0.0f), scale_(1.0f), shader_(ShaderProgram::getSystemDefault()), enabled_(true), ignore_global_model_(false), derived_position_(0.0f), derived_rotation_(), derived_scale_(1.0f) { if(!node.is_map()) { return; } if(node.has_key("ignore_global_model")) { ignore_global_model_ = node["ignore_global_model"].as_bool(false); } if(node.has_key("order")) { order_ = node["order"].as_int32(); } // XXX set other stuff here, tbd if(node.has_key("blend")) { setBlendMode(KRE::BlendMode(node["blend"])); } if(node.has_key("blend_equation")) { setBlendEquation(KRE::BlendEquation(node["blend_equation"])); } else if(node.has_key("blend_eq")) { setBlendEquation(KRE::BlendEquation(node["blend_eq"])); } if(node.has_key("rotation")) { const variant& rot = node["rotation"]; if(rot.is_numeric()) { // Assume it's a simple rotation around z-axis setRotation(rot.as_float(), glm::vec3(0.f,0.f,1.f)); } else if(rot.is_list()) { // Either a single rotation formatted as [angle,[x,y,z]] or a list of three euler angles if(rot.num_elements() == 2) { ASSERT_LOG(rot[1].is_list() && rot[1].num_elements() == 3, "Format for a single rotation is [angle, [x,y,z]]"); setRotation(rot[0].as_float(), variant_to_vec3(rot[1])); } else if(rot.num_elements() == 3) { setRotation(rot[0].as_float(), glm::vec3(1.,0.,0.)); setRotation(rot[1].as_float(), glm::vec3(0.,1.,0.)); setRotation(rot[2].as_float(), glm::vec3(0.,0.,1.)); } else { ASSERT_LOG(false, "Need a list of three (x/y/z rotations) or 2 elements (angle, [axis])"); } } } if(node.has_key("translation") || node.has_key("position")) { const variant& pos = node.has_key("translation") ? node["translation"] : node["position"]; ASSERT_LOG(pos.is_list() && (pos.num_elements() == 2 || pos.num_elements() == 3), "'translation'/'position' attribute should have 2 [x,y] or 3 [x,y,z] elements."); if(pos.num_elements() == 3) { setPosition(variant_to_vec3(pos)); } else { setPosition(pos[0].as_float(), pos[1].as_float()); } } if(node.has_key("scale")) { const variant& sc = node["scale"]; if(sc.is_numeric()) { const float scale = sc.as_float(); setScale(scale, scale, scale); } else if(sc.is_list()) { float xs = 1.0f; float ys = 1.0f; float zs = 1.0f; if(sc.num_elements() == 1) { xs = sc[0].as_float(); } else if(sc.num_elements() == 2) { xs = sc[0].as_float(); ys = sc[1].as_float(); } else if(sc.num_elements() == 3) { xs = sc[0].as_float(); ys = sc[1].as_float(); zs = sc[2].as_float(); } setScale(xs, ys, zs); } else { ASSERT_LOG(false, "Scale should be a number of a list of up to three elements."); } } if(node.has_key("color")) { setColor(KRE::Color(node["color"])); } if(node.has_key("texture")) { texture_ = Texture::createTexture(node["texture"]); } else if(node.has_key("image")) { texture_ = Texture::createTexture(node["image"]); } if(node.has_key("depth_check")) { setDepthEnable(node["depth_check"].as_bool()); } if(node.has_key("depth_write")) { setDepthWrite(node["depth_write"].as_bool()); } // XXX add depth function. if(node.has_key("use_lighting")) { enableLighting(node["use_lighting"].as_bool()); } }