void PackJTML(std::string const & jtml_name) { Timer timer; ResIdentifierPtr jtml = ResLoader::Instance().Open(jtml_name); KlayGE::XMLDocument doc; XMLNodePtr root = doc.Parse(jtml); uint32_t n = root->AttribInt("num_tiles", 2048); uint32_t num_tiles = 1; while (num_tiles * 2 <= n) { num_tiles *= 2; } uint32_t tile_size = root->AttribInt("tile_size", 128); std::string fmt_str = root->AttribString("format", ""); ElementFormat format = EF_ARGB8; if ("ARGB8" == fmt_str) { format = EF_ARGB8; } else if ("ABGR8" == fmt_str) { format = EF_ABGR8; } uint32_t pixel_size = NumFormatBytes(format); JudaTexturePtr juda_tex = MakeSharedPtr<JudaTexture>(num_tiles, tile_size, format); uint32_t level = juda_tex->TreeLevels() - 1; RenderFactory& rf = Context::Instance().RenderFactoryInstance(); uint32_t attr = 0; for (XMLNodePtr node = root->FirstNode("image"); node; node = node->NextSibling("image"), ++ attr) { timer.restart(); std::string name = node->AttribString("name", ""); int32_t x = node->AttribInt("x", 0); int32_t y = node->AttribInt("y", 0); std::string address_u_str = node->AttribString("address_u", "wrap"); std::string address_v_str = node->AttribString("address_v", "wrap"); Color border_clr; border_clr.r() = node->AttribFloat("border_r", 0.0f); border_clr.g() = node->AttribFloat("border_g", 0.0f); border_clr.b() = node->AttribFloat("border_b", 0.0f); border_clr.a() = node->AttribFloat("border_a", 0.0f); uint32_t border_clr_u8; switch (format) { case EF_ARGB8: border_clr_u8 = border_clr.ARGB(); break; case EF_ABGR8: border_clr_u8 = border_clr.ABGR(); break; default: border_clr_u8 = 0; break; } TexAddressingMode addr_u, addr_v; std::shared_ptr<address_calculator> calc_u, calc_v; if ("mirror" == address_u_str) { addr_u = TAM_Mirror; calc_u = address_calculators[TAM_Mirror]; } else if ("clamp" == address_u_str) { addr_u = TAM_Clamp; calc_u = address_calculators[TAM_Clamp]; } else if ("border" == address_u_str) { addr_u = TAM_Border; calc_u = address_calculators[TAM_Border]; } else { addr_u = TAM_Wrap; calc_u = address_calculators[TAM_Wrap]; } if ("mirror" == address_v_str) { addr_v = TAM_Mirror; calc_v = address_calculators[TAM_Mirror]; } else if ("clamp" == address_v_str) { addr_v = TAM_Clamp; calc_v = address_calculators[TAM_Clamp]; } else if ("border" == address_v_str) { addr_v = TAM_Border; calc_v = address_calculators[TAM_Border]; } else { addr_v = TAM_Wrap; calc_v = address_calculators[TAM_Wrap]; } cout << "Processing " << name << "... "; TexturePtr src_texture = SyncLoadTexture(name, EAH_CPU_Read | EAH_CPU_Write); if (src_texture->Type() != Texture::TT_2D) { cout << "Texture " << name << "is not 2D texture. Skipped." << endl; continue; } uint32_t in_width = src_texture->Width(0); uint32_t in_height = src_texture->Height(0); TexturePtr texture = rf.MakeTexture2D(in_width, in_height, 1, 1, format, 1, 0, EAH_CPU_Read | EAH_CPU_Write); src_texture->CopyToTexture(*texture); Texture::Mapper mapper(*texture, 0, 0, TMA_Read_Only, 0, 0, in_width, in_height); uint8_t const * in_data_p = mapper.Pointer<uint8_t>(); int32_t in_num_tiles_x = std::min((in_width + tile_size - 1) / tile_size, num_tiles); int32_t in_num_tiles_y = std::min((in_height + tile_size - 1) / tile_size, num_tiles); int32_t beg_tile_x = 0; int32_t end_tile_x = std::min(static_cast<int32_t>(x + in_num_tiles_x), static_cast<int32_t>(num_tiles)) - x; int32_t beg_tile_y = 0; int32_t end_tile_y = std::min(static_cast<int32_t>(y + in_num_tiles_y), static_cast<int32_t>(num_tiles)) - y; juda_tex->AddImageEntry(name, x, y, in_num_tiles_x, in_num_tiles_y, addr_u, addr_v, border_clr); std::vector<std::vector<uint8_t>> tiles; std::vector<uint32_t> tile_ids; std::vector<uint32_t> tile_attrs; for (int32_t by = beg_tile_y; by < end_tile_y; ++ by) { tiles.clear(); tile_ids.clear(); tile_attrs.clear(); for (int32_t bx = beg_tile_x; bx < end_tile_x; ++ bx) { uint32_t xindex = bx - beg_tile_x; tiles.push_back(std::vector<uint8_t>(tile_size * tile_size * pixel_size, 0)); tile_ids.push_back(juda_tex->EncodeTileID(level, bx + x, by + y)); tile_attrs.push_back(attr); for (size_t dy = 0; dy < tile_size; ++ dy) { int32_t tex_y = (*calc_v)(static_cast<int32_t>(by * tile_size + dy), in_height); if (tex_y >= 0) { for (size_t dx = 0; dx < tile_size; ++ dx) { int32_t tex_x = (*calc_u)(static_cast<int32_t>(bx * tile_size + dx), in_width); if (tex_x >= 0) { std::memcpy(&tiles[xindex][(dy * tile_size + dx) * pixel_size], &in_data_p[tex_y * mapper.RowPitch() + tex_x * pixel_size], pixel_size); } else { std::memcpy(&tiles[xindex][(dy * tile_size + dx) * pixel_size], &border_clr_u8, pixel_size); } } } else { for (size_t dx = 0; dx < tile_size; ++ dx) { std::memcpy(&tiles[xindex][(dy * tile_size + dx) * pixel_size], &border_clr_u8, pixel_size); } } } } juda_tex->CommitTiles(tiles, tile_ids, tile_attrs); } cout << "Takes " << timer.elapsed() << "s" << endl; } cout << "Total tiles: " << ((1UL << (juda_tex->TreeLevels() * 2)) - 1) / (4 - 1) << endl; cout << "Non empty tiles: " << juda_tex->NumNonEmptyNodes() << endl; cout << "Tree depth: " << juda_tex->TreeLevels() << endl; std::string base_name = jtml_name.substr(0, jtml_name.find_last_of('.')); cout << "Saving... "; timer.restart(); SaveJudaTexture(juda_tex, base_name + ".jdt"); cout << "Takes " << timer.elapsed() << "s" << endl << endl; }
void SubThreadStage() { ResIdentifierPtr psmm_input = ResLoader::Instance().Open(ps_desc_.res_name); KlayGE::XMLDocument doc; XMLNodePtr root = doc.Parse(psmm_input); { XMLNodePtr particle_node = root->FirstNode("particle"); { XMLNodePtr alpha_node = particle_node->FirstNode("alpha"); ps_desc_.ps_data->particle_alpha_from_tex = alpha_node->Attrib("from")->ValueString(); ps_desc_.ps_data->particle_alpha_to_tex = alpha_node->Attrib("to")->ValueString(); } { XMLNodePtr color_node = particle_node->FirstNode("color"); { Color from; XMLAttributePtr attr = color_node->Attrib("from"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); from[i] = static_cast<float>(atof(strs[i].c_str())); } else { from[i] = 0; } } } from.a() = 1; ps_desc_.ps_data->particle_color_from = from; Color to; attr = color_node->Attrib("to"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); to[i] = static_cast<float>(atof(strs[i].c_str())); } else { to[i] = 0; } } } to.a() = 1; ps_desc_.ps_data->particle_color_to = to; } } } { XMLNodePtr emitter_node = root->FirstNode("emitter"); XMLAttributePtr type_attr = emitter_node->Attrib("type"); if (type_attr) { ps_desc_.ps_data->emitter_type = type_attr->ValueString(); } else { ps_desc_.ps_data->emitter_type = "point"; } XMLNodePtr freq_node = emitter_node->FirstNode("frequency"); if (freq_node) { XMLAttributePtr attr = freq_node->Attrib("value"); ps_desc_.ps_data->frequency = attr->ValueFloat(); } XMLNodePtr angle_node = emitter_node->FirstNode("angle"); if (angle_node) { XMLAttributePtr attr = angle_node->Attrib("value"); ps_desc_.ps_data->angle = attr->ValueInt() * DEG2RAD; } XMLNodePtr pos_node = emitter_node->FirstNode("pos"); if (pos_node) { float3 min_pos(0, 0, 0); XMLAttributePtr attr = pos_node->Attrib("min"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); min_pos[i] = static_cast<float>(atof(strs[i].c_str())); } else { min_pos[i] = 0; } } } ps_desc_.ps_data->min_pos = min_pos; float3 max_pos(0, 0, 0); attr = pos_node->Attrib("max"); if (attr) { std::vector<std::string> strs; boost::algorithm::split(strs, attr->ValueString(), boost::is_any_of(" ")); for (size_t i = 0; i < 3; ++ i) { if (i < strs.size()) { boost::algorithm::trim(strs[i]); max_pos[i] = static_cast<float>(atof(strs[i].c_str())); } else { max_pos[i] = 0; } } } ps_desc_.ps_data->max_pos = max_pos; } XMLNodePtr vel_node = emitter_node->FirstNode("vel"); if (vel_node) { XMLAttributePtr attr = vel_node->Attrib("min"); ps_desc_.ps_data->min_vel = attr->ValueFloat(); attr = vel_node->Attrib("max"); ps_desc_.ps_data->max_vel = attr->ValueFloat(); } XMLNodePtr life_node = emitter_node->FirstNode("life"); if (life_node) { XMLAttributePtr attr = life_node->Attrib("min"); ps_desc_.ps_data->min_life = attr->ValueFloat(); attr = life_node->Attrib("max"); ps_desc_.ps_data->max_life = attr->ValueFloat(); } } { XMLNodePtr updater_node = root->FirstNode("updater"); XMLAttributePtr type_attr = updater_node->Attrib("type"); if (type_attr) { ps_desc_.ps_data->updater_type = type_attr->ValueString(); } else { ps_desc_.ps_data->updater_type = "polyline"; } if ("polyline" == ps_desc_.ps_data->updater_type) { for (XMLNodePtr node = updater_node->FirstNode("curve"); node; node = node->NextSibling("curve")) { std::vector<float2> xys; for (XMLNodePtr ctrl_point_node = node->FirstNode("ctrl_point"); ctrl_point_node; ctrl_point_node = ctrl_point_node->NextSibling("ctrl_point")) { XMLAttributePtr attr_x = ctrl_point_node->Attrib("x"); XMLAttributePtr attr_y = ctrl_point_node->Attrib("y"); xys.push_back(float2(attr_x->ValueFloat(), attr_y->ValueFloat())); } XMLAttributePtr attr = node->Attrib("name"); size_t const name_hash = RT_HASH(attr->ValueString().c_str()); if (CT_HASH("size_over_life") == name_hash) { ps_desc_.ps_data->size_over_life_ctrl_pts = xys; } else if (CT_HASH("mass_over_life") == name_hash) { ps_desc_.ps_data->mass_over_life_ctrl_pts = xys; } else if (CT_HASH("opacity_over_life") == name_hash) { ps_desc_.ps_data->opacity_over_life_ctrl_pts = xys; } } } } RenderFactory& rf = Context::Instance().RenderFactoryInstance(); RenderDeviceCaps const & caps = rf.RenderEngineInstance().DeviceCaps(); if (caps.multithread_res_creating_support) { this->MainThreadStage(); } }