bool MapGeometryLoader::Build() { eqLogMessage(LogTrace, "Attempting to load %s.eqg as a standard eqg.", m_zoneName.c_str()); std::string filePath = m_eqPath + "\\" + m_zoneName; EQEmu::EQGLoader eqg; std::vector<std::shared_ptr<EQEmu::EQG::Geometry>> eqg_models; std::vector<std::shared_ptr<EQEmu::Placeable>> eqg_placables; std::vector<std::shared_ptr<EQEmu::EQG::Region>> eqg_regions; std::vector<std::shared_ptr<EQEmu::Light>> eqg_lights; if (eqg.Load(filePath, eqg_models, eqg_placables, eqg_regions, eqg_lights)) { return CompileEQG(eqg_models, eqg_placables, eqg_regions, eqg_lights); } eqLogMessage(LogTrace, "Attempting to load %s.eqg as a v4 eqg.", m_zoneName.c_str()); EQEmu::EQG4Loader eqg4; if (eqg4.Load(filePath, terrain)) { return CompileEQGv4(); } eqLogMessage(LogTrace, "Attempting to load %s.s3d as a standard s3d.", m_zoneName.c_str()); EQEmu::S3DLoader s3d; std::vector<EQEmu::S3D::WLDFragment> zone_frags; std::vector<EQEmu::S3D::WLDFragment> zone_object_frags; std::vector<EQEmu::S3D::WLDFragment> object_frags; if (!s3d.ParseWLDFile(filePath + ".s3d", m_zoneName + ".wld", zone_frags)) { return false; } if (!s3d.ParseWLDFile(filePath + ".s3d", "objects.wld", zone_object_frags)) { return false; } if (!s3d.ParseWLDFile(filePath + "_obj.s3d", m_zoneName + "_obj.wld", object_frags)) { return false; } return CompileS3D(zone_frags, zone_object_frags, object_frags); }
bool EQEmu::EQGLoader::Load(std::string file, std::vector<std::shared_ptr<EQG::Geometry>> &models, std::vector<std::shared_ptr<Placeable>> &placeables, std::vector<std::shared_ptr<EQG::Region>> ®ions, std::vector<std::shared_ptr<Light>> &lights) { // find zon file EQEmu::PFS::Archive archive; if(!archive.Open(file + ".eqg")) { eqLogMessage(LogTrace, "Failed to open %s.eqg as a standard eqg file because the file does not exist.", file.c_str()); return false; } std::vector<char> zon; bool zon_found = false; std::vector<std::string> files; archive.GetFilenames("zon", files); if(files.size() == 0) { if (GetZon(file + ".zon", zon)) { zon_found = true; } } else { for(auto &f : files) { if(archive.Get(f, zon)) { if(zon[0] == 'E' && zon[1] == 'Q' && zon[2] == 'T' && zon[3] == 'Z' && zon[4] == 'P') { eqLogMessage(LogWarn, "Unable to parse the zone file, is a eqgv4."); return false; } zon_found = true; } } } if (!zon_found) { eqLogMessage(LogError, "Failed to open %s.eqg because the %s.zon file could not be found.", file.c_str(), file.c_str()); return false; } eqLogMessage(LogTrace, "Parsing zone file."); if (!ParseZon(archive, zon, models, placeables, regions, lights)) { //if we couldn't parse the zon file then it's probably eqg4 eqLogMessage(LogWarn, "Unable to parse the zone file, probably eqgv4 style file."); return false; } return true; }
bool Map::Build(std::string zone_name, bool ignore_collide_tex) { LoadIgnore(zone_name); eqLogMessage(LogTrace, "Attempting to load %s.eqg as a standard eqg.", zone_name.c_str()); EQEmu::EQGLoader eqg; std::vector<std::shared_ptr<EQEmu::EQG::Geometry>> eqg_models; std::vector<std::shared_ptr<EQEmu::Placeable>> eqg_placables; std::vector<std::shared_ptr<EQEmu::EQG::Region>> eqg_regions; std::vector<std::shared_ptr<EQEmu::Light>> eqg_lights; if (eqg.Load(zone_name, eqg_models, eqg_placables, eqg_regions, eqg_lights)) { return CompileEQG(eqg_models, eqg_placables, eqg_regions, eqg_lights); } eqLogMessage(LogTrace, "Attempting to load %s.eqg as a v4 eqg.", zone_name.c_str()); EQEmu::EQG4Loader eqg4; if (eqg4.Load(zone_name, terrain)) { return CompileEQGv4(); } eqLogMessage(LogTrace, "Attempting to load %s.s3d as a standard s3d.", zone_name.c_str()); EQEmu::S3DLoader s3d; std::vector<EQEmu::S3D::WLDFragment> zone_frags; std::vector<EQEmu::S3D::WLDFragment> zone_object_frags; std::vector<EQEmu::S3D::WLDFragment> object_frags; if (!s3d.ParseWLDFile(zone_name + ".s3d", zone_name + ".wld", zone_frags)) { return false; } if (!s3d.ParseWLDFile(zone_name + ".s3d", "objects.wld", zone_object_frags)) { return false; } if (!s3d.ParseWLDFile(zone_name + "_obj.s3d", zone_name + "_obj.wld", object_frags)) { return false; } return CompileS3D(zone_frags, zone_object_frags, object_frags, ignore_collide_tex); }
bool Map::CompileEQG( std::vector<std::shared_ptr<EQEmu::EQG::Geometry>> &models, std::vector<std::shared_ptr<EQEmu::Placeable>> &placeables, std::vector<std::shared_ptr<EQEmu::EQG::Region>> ®ions, std::vector<std::shared_ptr<EQEmu::Light>> &lights ) { collide_verts.clear(); collide_indices.clear(); non_collide_verts.clear(); non_collide_indices.clear(); current_collide_index = 0; current_non_collide_index = 0; collide_vert_to_index.clear(); non_collide_vert_to_index.clear(); map_models.clear(); map_eqg_models.clear(); map_placeables.clear(); for(uint32_t i = 0; i < placeables.size(); ++i) { std::shared_ptr<EQEmu::Placeable> &plac = placeables[i]; std::shared_ptr<EQEmu::EQG::Geometry> model; bool is_ter = false; if(plac->GetName().substr(0, 3).compare("TER") == 0 || plac->GetFileName().substr(plac->GetFileName().length() - 4, 4).compare(".ter") == 0) is_ter = true; for(uint32_t j = 0; j < models.size(); ++j) { if(models[j]->GetName().compare(plac->GetFileName()) == 0) { model = models[j]; break; } } if (!model) { eqLogMessage(LogWarn, "Could not find placeable %s.", plac->GetFileName().c_str()); continue; } float offset_x = plac->GetX(); float offset_y = plac->GetY(); float offset_z = plac->GetZ(); float rot_x = plac->GetRotateX() * 3.14159f / 180.0f; float rot_y = plac->GetRotateY() * 3.14159f / 180.0f; float rot_z = plac->GetRotateZ() * 3.14159f / 180.0f; float scale_x = plac->GetScaleX(); float scale_y = plac->GetScaleY(); float scale_z = plac->GetScaleZ(); if(!is_ter) { if (map_eqg_models.count(model->GetName()) == 0) { map_eqg_models[model->GetName()] = model; } std::shared_ptr<EQEmu::Placeable> gen_plac(new EQEmu::Placeable()); gen_plac->SetFileName(model->GetName()); gen_plac->SetLocation(offset_x, offset_y, offset_z); gen_plac->SetRotation(rot_x, rot_y, rot_z); gen_plac->SetScale(scale_x, scale_y, scale_z); map_placeables.push_back(gen_plac); eqLogMessage(LogTrace, "Adding placeable %s at (%f, %f, %f)", model->GetName().c_str(), offset_x, offset_y, offset_z); continue; } auto &mod_polys = model->GetPolygons(); auto &mod_verts = model->GetVertices(); for (uint32_t j = 0; j < mod_polys.size(); ++j) { auto ¤t_poly = mod_polys[j]; auto v1 = mod_verts[current_poly.verts[0]]; auto v2 = mod_verts[current_poly.verts[1]]; auto v3 = mod_verts[current_poly.verts[2]]; float t = v1.pos.x; v1.pos.x = v1.pos.y; v1.pos.y = t; t = v2.pos.x; v2.pos.x = v2.pos.y; v2.pos.y = t; t = v3.pos.x; v3.pos.x = v3.pos.y; v3.pos.y = t; if (current_poly.flags & 0x01) AddFace(v1.pos, v2.pos, v3.pos, false); else AddFace(v1.pos, v2.pos, v3.pos, true); } } return true; }
bool Map::Write(std::string filename) { //if there are no verts and no terrain if ((collide_verts.size() == 0 && collide_indices.size() == 0 && non_collide_verts.size() == 0 && non_collide_indices.size() == 0) && !terrain) { eqLogMessage(LogError, "Failed to write %s because the map to build has no information to write.", filename.c_str()); return false; } FILE *f = fopen(filename.c_str(), "wb"); if(!f) { eqLogMessage(LogError, "Failed to write %s because the file could not be opened to write.", filename.c_str()); return false; } uint32_t version = 0x02000000; if (fwrite(&version, sizeof(uint32_t), 1, f) != 1) { eqLogMessage(LogError, "Failed to write %s because the version header could not be written.", filename.c_str()); fclose(f); return false; } std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); uint32_t collide_vert_count = (uint32_t)collide_verts.size(); uint32_t collide_ind_count = (uint32_t)collide_indices.size(); uint32_t non_collide_vert_count = (uint32_t)non_collide_verts.size(); uint32_t non_collide_ind_count = (uint32_t)non_collide_indices.size(); uint32_t model_count = (uint32_t)(map_models.size() + map_eqg_models.size()); uint32_t plac_count = (uint32_t)map_placeables.size(); uint32_t plac_group_count = (uint32_t)map_group_placeables.size(); uint32_t tile_count = terrain ? (uint32_t)terrain->GetTiles().size() : 0; uint32_t quads_per_tile = terrain ? terrain->GetQuadsPerTile() : 0; float units_per_vertex = terrain ? terrain->GetUnitsPerVertex() : 0.0f; ss.write((const char*)&collide_vert_count, sizeof(uint32_t)); ss.write((const char*)&collide_ind_count, sizeof(uint32_t)); ss.write((const char*)&non_collide_vert_count, sizeof(uint32_t)); ss.write((const char*)&non_collide_ind_count, sizeof(uint32_t)); ss.write((const char*)&model_count, sizeof(uint32_t)); ss.write((const char*)&plac_count, sizeof(uint32_t)); ss.write((const char*)&plac_group_count, sizeof(uint32_t)); ss.write((const char*)&tile_count, sizeof(uint32_t)); ss.write((const char*)&quads_per_tile, sizeof(uint32_t)); ss.write((const char*)&units_per_vertex, sizeof(float)); for(uint32_t i = 0; i < collide_vert_count; ++i) { auto vert = collide_verts[i]; ss.write((const char*)&vert.x, sizeof(float)); ss.write((const char*)&vert.y, sizeof(float)); ss.write((const char*)&vert.z, sizeof(float)); } for (uint32_t i = 0; i < collide_ind_count; ++i) { uint32_t ind = collide_indices[i]; ss.write((const char*)&ind, sizeof(uint32_t)); } for(uint32_t i = 0; i < non_collide_vert_count; ++i) { auto vert = non_collide_verts[i]; ss.write((const char*)&vert.x, sizeof(float)); ss.write((const char*)&vert.y, sizeof(float)); ss.write((const char*)&vert.z, sizeof(float)); } for (uint32_t i = 0; i < non_collide_ind_count; ++i) { uint32_t ind = non_collide_indices[i]; ss.write((const char*)&ind, sizeof(uint32_t)); } auto model_iter = map_models.begin(); while(model_iter != map_models.end()) { uint8_t null = 0; ss.write(model_iter->second->GetName().c_str(), model_iter->second->GetName().length()); ss.write((const char*)&null, sizeof(uint8_t)); auto &verts = model_iter->second->GetVertices(); auto &polys = model_iter->second->GetPolygons(); uint32_t vert_count = (uint32_t)verts.size(); uint32_t poly_count = (uint32_t)polys.size(); ss.write((const char*)&vert_count, sizeof(uint32_t)); ss.write((const char*)&poly_count, sizeof(uint32_t)); for(uint32_t i = 0; i < vert_count; ++i) { auto &vert = verts[i]; float x = vert.pos.x; float y = vert.pos.y; float z = vert.pos.z; ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); ss.write((const char*)&z, sizeof(float)); } for (uint32_t i = 0; i < poly_count; ++i) { auto &poly = polys[i]; uint32_t v1 = poly.verts[0]; uint32_t v2 = poly.verts[1]; uint32_t v3 = poly.verts[2]; uint8_t vis = poly.flags == 0x10 ? 0 : 1; ss.write((const char*)&v1, sizeof(uint32_t)); ss.write((const char*)&v2, sizeof(uint32_t)); ss.write((const char*)&v3, sizeof(uint32_t)); ss.write((const char*)&vis, sizeof(uint8_t)); } ++model_iter; } auto eqg_model_iter = map_eqg_models.begin(); while (eqg_model_iter != map_eqg_models.end()) { uint8_t null = 0; ss.write(eqg_model_iter->second->GetName().c_str(), eqg_model_iter->second->GetName().length()); ss.write((const char*)&null, sizeof(uint8_t)); auto &verts = eqg_model_iter->second->GetVertices(); auto &polys = eqg_model_iter->second->GetPolygons(); uint32_t vert_count = (uint32_t)verts.size(); uint32_t poly_count = (uint32_t)polys.size(); ss.write((const char*)&vert_count, sizeof(uint32_t)); ss.write((const char*)&poly_count, sizeof(uint32_t)); for (uint32_t i = 0; i < vert_count; ++i) { auto &vert = verts[i]; float x = vert.pos.x; float y = vert.pos.y; float z = vert.pos.z; ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); ss.write((const char*)&z, sizeof(float)); } for (uint32_t i = 0; i < poly_count; ++i) { auto &poly = polys[i]; uint32_t v1 = poly.verts[0]; uint32_t v2 = poly.verts[1]; uint32_t v3 = poly.verts[2]; uint8_t vis = 1; if (poly.flags & 0x01) vis = 0; ss.write((const char*)&v1, sizeof(uint32_t)); ss.write((const char*)&v2, sizeof(uint32_t)); ss.write((const char*)&v3, sizeof(uint32_t)); ss.write((const char*)&vis, sizeof(uint8_t)); } ++eqg_model_iter; } for (uint32_t i = 0; i < plac_count; ++i) { auto &plac = map_placeables[i]; uint8_t null = 0; float x = plac->GetX(); float y = plac->GetY(); float z = plac->GetZ(); float x_rot = plac->GetRotateX(); float y_rot = plac->GetRotateY(); float z_rot = plac->GetRotateZ(); float x_scale = plac->GetScaleX(); float y_scale = plac->GetScaleY(); float z_scale = plac->GetScaleZ(); ss.write(plac->GetFileName().c_str(), plac->GetFileName().length()); ss.write((const char*)&null, sizeof(uint8_t)); ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); ss.write((const char*)&z, sizeof(float)); ss.write((const char*)&x_rot, sizeof(float)); ss.write((const char*)&y_rot, sizeof(float)); ss.write((const char*)&z_rot, sizeof(float)); ss.write((const char*)&x_scale, sizeof(float)); ss.write((const char*)&y_scale, sizeof(float)); ss.write((const char*)&z_scale, sizeof(float)); } for (uint32_t i = 0; i < plac_group_count; ++i) { auto &gp = map_group_placeables[i]; uint8_t null = 0; float x = gp->GetX(); float y = gp->GetY(); float z = gp->GetZ(); float x_rot = gp->GetRotationX(); float y_rot = gp->GetRotationY(); float z_rot = gp->GetRotationZ(); float x_scale = gp->GetScaleX(); float y_scale = gp->GetScaleY(); float z_scale = gp->GetScaleZ(); float x_tile = gp->GetTileX(); float y_tile = gp->GetTileY(); float z_tile = gp->GetTileZ(); ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); ss.write((const char*)&z, sizeof(float)); ss.write((const char*)&x_rot, sizeof(float)); ss.write((const char*)&y_rot, sizeof(float)); ss.write((const char*)&z_rot, sizeof(float)); ss.write((const char*)&x_scale, sizeof(float)); ss.write((const char*)&y_scale, sizeof(float)); ss.write((const char*)&z_scale, sizeof(float)); ss.write((const char*)&x_tile, sizeof(float)); ss.write((const char*)&y_tile, sizeof(float)); ss.write((const char*)&z_tile, sizeof(float)); auto &placs = gp->GetPlaceables(); uint32_t plac_count = (uint32_t)placs.size(); ss.write((const char*)&plac_count, sizeof(uint32_t)); for (uint32_t j = 0; j < plac_count; ++j) { auto &plac = placs[j]; float x = plac->GetX(); float y = plac->GetY(); float z = plac->GetZ(); float x_rot = plac->GetRotateX(); float y_rot = plac->GetRotateY(); float z_rot = plac->GetRotateZ(); float x_scale = plac->GetScaleX(); float y_scale = plac->GetScaleY(); float z_scale = plac->GetScaleZ(); ss.write(plac->GetFileName().c_str(), plac->GetFileName().length()); ss.write((const char*)&null, sizeof(uint8_t)); ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); ss.write((const char*)&z, sizeof(float)); ss.write((const char*)&x_rot, sizeof(float)); ss.write((const char*)&y_rot, sizeof(float)); ss.write((const char*)&z_rot, sizeof(float)); ss.write((const char*)&x_scale, sizeof(float)); ss.write((const char*)&y_scale, sizeof(float)); ss.write((const char*)&z_scale, sizeof(float)); } } if(terrain) { uint32_t quad_count = (quads_per_tile * quads_per_tile); uint32_t vert_count = ((quads_per_tile + 1) * (quads_per_tile + 1)); auto &tiles = terrain->GetTiles(); for (uint32_t i = 0; i < tile_count; ++i) { if(tiles[i]->IsFlat()) { bool flat = true; float x = tiles[i]->GetX(); float y = tiles[i]->GetY(); float z = tiles[i]->GetFloats()[0]; ss.write((const char*)&flat, sizeof(bool)); ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); ss.write((const char*)&z, sizeof(float)); } else { bool flat = false; float x = tiles[i]->GetX(); float y = tiles[i]->GetY(); ss.write((const char*)&flat, sizeof(bool)); ss.write((const char*)&x, sizeof(float)); ss.write((const char*)&y, sizeof(float)); auto &flags = tiles[i]->GetFlags(); for(uint32_t j = 0; j < quad_count; ++j) { uint8_t f = flags[j]; ss.write((const char*)&f, sizeof(uint8_t)); } auto &floats = tiles[i]->GetFloats(); for (uint32_t j = 0; j < vert_count; ++j) { float f = floats[j]; ss.write((const char*)&f, sizeof(float)); } } } } std::vector<char> buffer; uint32_t buffer_len = (uint32_t)(ss.str().length() + 128); buffer.resize(buffer_len); uint32_t out_size = EQEmu::DeflateData(ss.str().c_str(), (uint32_t)ss.str().length(), &buffer[0], buffer_len); if (fwrite(&out_size, sizeof(uint32_t), 1, f) != 1) { eqLogMessage(LogError, "Failed to write %s because the compressed size header could not be written.", filename.c_str()); fclose(f); return false; } uint32_t uncompressed_size = (uint32_t)ss.str().length(); if (fwrite(&uncompressed_size, sizeof(uint32_t), 1, f) != 1) { eqLogMessage(LogError, "Failed to write %s because the uncompressed size header could not be written.", filename.c_str()); fclose(f); return false; } if (fwrite(&buffer[0], out_size, 1, f) != 1) { eqLogMessage(LogError, "Failed to write %s because the compressed data could not be written.", filename.c_str()); fclose(f); return false; } fclose(f); return true; }
bool Map::CompileS3D( std::vector<EQEmu::S3D::WLDFragment> &zone_frags, std::vector<EQEmu::S3D::WLDFragment> &zone_object_frags, std::vector<EQEmu::S3D::WLDFragment> &object_frags ) { collide_verts.clear(); collide_indices.clear(); non_collide_verts.clear(); non_collide_indices.clear(); current_collide_index = 0; current_non_collide_index = 0; collide_vert_to_index.clear(); non_collide_vert_to_index.clear(); map_models.clear(); map_eqg_models.clear(); map_placeables.clear(); eqLogMessage(LogTrace, "Processing s3d zone geometry fragments."); for(uint32_t i = 0; i < zone_frags.size(); ++i) { if(zone_frags[i].type == 0x36) { EQEmu::S3D::WLDFragment36 &frag = reinterpret_cast<EQEmu::S3D::WLDFragment36&>(zone_frags[i]); auto model = frag.GetData(); auto &mod_polys = model->GetPolygons(); auto &mod_verts = model->GetVertices(); for (uint32_t j = 0; j < mod_polys.size(); ++j) { auto ¤t_poly = mod_polys[j]; auto v1 = mod_verts[current_poly.verts[0]]; auto v2 = mod_verts[current_poly.verts[1]]; auto v3 = mod_verts[current_poly.verts[2]]; float t = v1.pos.x; v1.pos.x = v1.pos.y; v1.pos.y = t; t = v2.pos.x; v2.pos.x = v2.pos.y; v2.pos.y = t; t = v3.pos.x; v3.pos.x = v3.pos.y; v3.pos.y = t; if(current_poly.flags == 0x10) AddFace(v1.pos, v2.pos, v3.pos, false); else AddFace(v1.pos, v2.pos, v3.pos, true); } } } eqLogMessage(LogTrace, "Processing zone placeable fragments."); std::vector<std::pair<std::shared_ptr<EQEmu::Placeable>, std::shared_ptr<EQEmu::S3D::Geometry>>> placables; std::vector<std::pair<std::shared_ptr<EQEmu::Placeable>, std::shared_ptr<EQEmu::S3D::SkeletonTrack>>> placables_skeleton; for (uint32_t i = 0; i < zone_object_frags.size(); ++i) { if (zone_object_frags[i].type == 0x15) { EQEmu::S3D::WLDFragment15 &frag = reinterpret_cast<EQEmu::S3D::WLDFragment15&>(zone_object_frags[i]); auto plac = frag.GetData(); if(!plac) { eqLogMessage(LogWarn, "Placeable entry was not found."); continue; } bool found = false; for (uint32_t o = 0; o < object_frags.size(); ++o) { if (object_frags[o].type == 0x14) { EQEmu::S3D::WLDFragment14 &obj_frag = reinterpret_cast<EQEmu::S3D::WLDFragment14&>(object_frags[o]); auto mod_ref = obj_frag.GetData(); if(mod_ref->GetName().compare(plac->GetName()) == 0) { found = true; auto &frag_refs = mod_ref->GetFrags(); for (uint32_t m = 0; m < frag_refs.size(); ++m) { if (object_frags[frag_refs[m] - 1].type == 0x2D) { EQEmu::S3D::WLDFragment2D &r_frag = reinterpret_cast<EQEmu::S3D::WLDFragment2D&>(object_frags[frag_refs[m] - 1]); auto m_ref = r_frag.GetData(); EQEmu::S3D::WLDFragment36 &mod_frag = reinterpret_cast<EQEmu::S3D::WLDFragment36&>(object_frags[m_ref]); auto mod = mod_frag.GetData(); placables.push_back(std::make_pair(plac, mod)); } else if (object_frags[frag_refs[m] - 1].type == 0x11) { EQEmu::S3D::WLDFragment11 &r_frag = reinterpret_cast<EQEmu::S3D::WLDFragment11&>(object_frags[frag_refs[m] - 1]); auto s_ref = r_frag.GetData(); EQEmu::S3D::WLDFragment10 &skeleton_frag = reinterpret_cast<EQEmu::S3D::WLDFragment10&>(object_frags[s_ref]); auto skele = skeleton_frag.GetData(); placables_skeleton.push_back(std::make_pair(plac, skele)); } } break; } } } if(!found) { eqLogMessage(LogWarn, "Could not find model for placeable %s", plac->GetName().c_str()); } } } eqLogMessage(LogTrace, "Processing s3d placeables."); size_t pl_sz = placables.size(); for(size_t i = 0; i < pl_sz; ++i) { auto plac = placables[i].first; auto model = placables[i].second; auto &mod_polys = model->GetPolygons(); auto &mod_verts = model->GetVertices(); float offset_x = plac->GetX(); float offset_y = plac->GetY(); float offset_z = plac->GetZ(); float rot_x = plac->GetRotateX() * 3.14159f / 180.0f; float rot_y = plac->GetRotateY() * 3.14159f / 180.0f; float rot_z = plac->GetRotateZ() * 3.14159f / 180.0f; float scale_x = plac->GetScaleX(); float scale_y = plac->GetScaleY(); float scale_z = plac->GetScaleZ(); if (map_models.count(model->GetName()) == 0) { map_models[model->GetName()] = model; } std::shared_ptr<EQEmu::Placeable> gen_plac(new EQEmu::Placeable()); gen_plac->SetFileName(model->GetName()); gen_plac->SetLocation(offset_x, offset_y, offset_z); //y rotation seems backwards on s3ds, probably cause of the weird coord system they used back then //x rotation might be too but there are literally 0 x rotated placeables in all the s3ds so who knows gen_plac->SetRotation(rot_x, -rot_y, rot_z); gen_plac->SetScale(scale_x, scale_y, scale_z); map_placeables.push_back(gen_plac); eqLogMessage(LogTrace, "Adding placeable %s at (%f, %f, %f)", model->GetName().c_str(), offset_x, offset_y, offset_z); } eqLogMessage(LogTrace, "Processing s3d animated placeables."); pl_sz = placables_skeleton.size(); for (size_t i = 0; i < pl_sz; ++i) { auto &plac = placables_skeleton[i].first; auto &bones = placables_skeleton[i].second->GetBones(); if(bones.size() > 0) { float offset_x = plac->GetX(); float offset_y = plac->GetY(); float offset_z = plac->GetZ(); float rot_x = plac->GetRotateX() * 3.14159f / 180.0f; float rot_y = plac->GetRotateY() * 3.14159f / 180.0f; float rot_z = plac->GetRotateZ() * 3.14159f / 180.0f; float scale_x = plac->GetScaleX(); float scale_y = plac->GetScaleY(); float scale_z = plac->GetScaleZ(); TraverseBone(bones[0], glm::vec3(offset_x, offset_y, offset_z), glm::vec3(rot_x, rot_y, rot_z), glm::vec3(scale_x, scale_y, scale_z)); } } return true; }
void Map::TraverseBone(std::shared_ptr<EQEmu::S3D::SkeletonTrack::Bone> bone, glm::vec3 parent_trans, glm::vec3 parent_rot, glm::vec3 parent_scale) { float offset_x = 0.0f; float offset_y = 0.0f; float offset_z = 0.0f; float rot_x = 0.0f; float rot_y = 0.0f; float rot_z = 0.0f; float scale_x = parent_scale.x; float scale_y = parent_scale.y; float scale_z = parent_scale.z; if(bone->orientation) { if (bone->orientation->shift_denom != 0) { offset_x = (float)bone->orientation->shift_x_num / (float)bone->orientation->shift_denom; offset_y = (float)bone->orientation->shift_y_num / (float)bone->orientation->shift_denom; offset_z = (float)bone->orientation->shift_z_num / (float)bone->orientation->shift_denom; } if(bone->orientation->rotate_denom != 0) { rot_x = (float)bone->orientation->rotate_x_num / (float)bone->orientation->rotate_denom; rot_y = (float)bone->orientation->rotate_y_num / (float)bone->orientation->rotate_denom; rot_z = (float)bone->orientation->rotate_z_num / (float)bone->orientation->rotate_denom; rot_x = rot_x * 3.14159f / 180.0f; rot_y = rot_y * 3.14159f / 180.0f; rot_z = rot_z * 3.14159f / 180.0f; } } glm::vec3 pos(offset_x, offset_y, offset_z); glm::vec3 rot(rot_x, rot_y, rot_z); RotateVertex(pos, parent_rot.x, parent_rot.y, parent_rot.z); pos += parent_trans; rot += parent_rot; if(bone->model) { auto &mod_polys = bone->model->GetPolygons(); auto &mod_verts = bone->model->GetVertices(); if (map_models.count(bone->model->GetName()) == 0) { map_models[bone->model->GetName()] = bone->model; } std::shared_ptr<EQEmu::Placeable> gen_plac(new EQEmu::Placeable()); gen_plac->SetFileName(bone->model->GetName()); gen_plac->SetLocation(pos.x, pos.y, pos.z); gen_plac->SetRotation(rot.x, rot.y, rot.z); gen_plac->SetScale(scale_x, scale_y, scale_z); map_placeables.push_back(gen_plac); eqLogMessage(LogTrace, "Adding placeable %s at (%f, %f, %f)",bone->model->GetName().c_str(), pos.x, pos.y, pos.z); } for(size_t i = 0; i < bone->children.size(); ++i) { TraverseBone(bone->children[i], pos, rot, parent_scale); } }
void MapGeometryLoader::LoadDoors() { // // Load the door data // std::string filename = m_meshPath + "\\MQ2Nav\\" + m_zoneName + "_doors.json"; boost::system::error_code ec; if (!boost::filesystem::is_regular_file(filename, ec)) return; std::stringstream ss; std::ifstream ifs; ifs.open(filename.c_str()); ss << ifs.rdbuf(); ifs.close(); rapidjson::Document document; if (document.Parse<0>(ss.str().c_str()).HasParseError()) return; if (!document.IsArray()) return; std::vector<DoorParams> doors; m_hasDynamicObjects = true; for (auto iter = document.Begin(); iter != document.End(); ++iter) { if (!iter->IsObject()) return; DoorParams params; params.id = (*iter)["ID"].GetInt(); params.name = (*iter)["Name"].GetString(); params.type = (*iter)["Type"].GetInt(); params.scale = (*iter)["Scale"].GetDouble(); // only add stationary objects if (!IsSwitchStationary(params.type)) continue; const auto& t = (*iter)["Transform"]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { params.transform[i][j] = t[i][j].GetDouble(); } } doors.push_back(params); } if (doors.empty()) { m_doorsLoaded = true; return; } // // Load the models for that door data // ZoneData zoneData(m_eqPath, m_zoneName); if (!zoneData.IsLoaded()) return; uint32_t counter = m_vertCount; auto AddTriangle = [&](const glm::mat4x4& matrix, const glm::vec3& v1_, const glm::vec3& v2_, const glm::vec3& v3_) { glm::vec4 v1 = matrix * glm::vec4(v1_.x, v1_.y, v1_.z, 1.0); glm::vec4 v2 = matrix * glm::vec4(v2_.x, v2_.y, v2_.z, 1.0); glm::vec4 v3 = matrix * glm::vec4(v3_.x, v3_.y, v3_.z, 1.0); addVertex(v1.y, v1.z, v1.x); addVertex(v2.y, v2.z, v2.x); addVertex(v3.y, v3.z, v3.x); addTriangle(counter, counter + 1, counter + 2); counter += 3; }; // generic lambda for both old and new model types auto addModel = [&](const glm::mat4x4& matrix, float scale, auto modelPtr) { auto verts = modelPtr->GetVertices(); auto polys = modelPtr->GetPolygons(); for (auto iter = polys.begin(); iter != polys.end(); ++iter) { if (iter->flags & 0x11) continue; auto& polygon = *iter; AddTriangle(matrix, scale * verts[polygon.verts[0]].pos, scale * verts[polygon.verts[1]].pos, scale * verts[polygon.verts[2]].pos); } ++m_dynamicObjects; }; for (auto iter = doors.begin(); iter != doors.end(); ++iter) { auto& params = *iter; if (std::shared_ptr<ModelInfo> mi = zoneData.GetModelInfo(params.name)) { glm::mat4x4 matrix = params.transform; if (mi->oldModel) { addModel(matrix, params.scale, mi->oldModel); } if (mi->newModel) { addModel(matrix, params.scale, mi->newModel); } } else { eqLogMessage(LogTrace, "Couldn't find model for %s.", params.name.c_str()); } } }
bool EQEmu::EQGLoader::ParseZon(EQEmu::PFS::Archive &archive, std::vector<char> &buffer, std::vector<std::shared_ptr<EQG::Geometry>> &models, std::vector<std::shared_ptr<Placeable>> &placeables, std::vector<std::shared_ptr<EQG::Region>> ®ions, std::vector<std::shared_ptr<Light>> &lights) { uint32_t idx = 0; SafeStructAllocParse(zon_header, header); if (header->magic[0] != 'E' || header->magic[1] != 'Q' || header->magic[2] != 'G' || header->magic[3] != 'Z') { return false; } idx += header->list_length; eqLogMessage(LogTrace, "Parsing zone models."); std::vector<std::string> model_names; for(uint32_t i = 0; i < header->model_count; ++i) { SafeVarAllocParse(uint32_t, model); std::string mod = &buffer[sizeof(zon_header) + model]; for(size_t j = 0; j < mod.length(); ++j) { if(mod[j] == ')') mod[j] = '_'; } model_names.push_back(mod); } //Need to load all the models eqLogMessage(LogTrace, "Loading zone models."); EQGModelLoader model_loader; for (size_t i = 0; i < model_names.size(); ++i) { std::string mod = model_names[i]; std::shared_ptr<EQG::Geometry> m(new EQG::Geometry()); m->SetName(mod); if(model_loader.Load(archive, mod, m)) { models.push_back(m); } else { m->GetMaterials().clear(); m->GetPolygons().clear(); m->GetVertices().clear(); models.push_back(m); } } //load placables eqLogMessage(LogTrace, "Parsing zone placeables."); float rot_change = 180.0f / 3.14159f; for (uint32_t i = 0; i < header->object_count; ++i) { SafeStructAllocParse(zon_placable, plac); std::shared_ptr<Placeable> p(new Placeable()); p->SetName(&buffer[sizeof(zon_header) + plac->loc]); if (plac->id >= 0 && plac->id < models.size()) { p->SetFileName(model_names[plac->id]); } p->SetLocation(plac->x, plac->y, plac->z); p->SetRotation(plac->rz * rot_change, plac->ry * rot_change, plac->rx * rot_change); p->SetScale(plac->scale, plac->scale, plac->scale); if(header->version > 1) { //don't know what this is but it relates to the underlying model SafeVarAllocParse(uint32_t, unk_size); idx += (unk_size) * sizeof(uint32_t); } placeables.push_back(p); } eqLogMessage(LogTrace, "Parsing zone regions."); for(uint32_t i = 0; i < header->region_count; ++i) { SafeStructAllocParse(zon_region, reg); std::shared_ptr<EQG::Region> region(new EQG::Region()); region->SetName(&buffer[sizeof(zon_header) + reg->loc]); region->SetLocation(reg->center_x, reg->center_y, reg->center_z); region->SetRotation(0.0f, 0.0f, reg->rotation / 512.0f * 360.0f); region->SetScale(1.0f, 1.0f, 1.0f); region->SetExtents(reg->extend_x, reg->extend_y, reg->extend_z); region->SetFlags(reg->flag_unknown020, reg->flag_unknown024); regions.push_back(region); } eqLogMessage(LogTrace, "Parsing zone lights."); for(uint32_t i = 0; i < header->light_count; ++i) { SafeStructAllocParse(zon_light, light); std::shared_ptr<Light> l(new Light()); l->SetName(&buffer[sizeof(zon_header) + light->loc]); l->SetLocation(light->x, light->y, light->z); l->SetColor(light->r, light->g, light->b); l->SetRadius(light->radius); lights.push_back(l); } return true; }