BuildObjServiceImpl.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. package com.fdkankan.contro.mq.service.impl;
  2. import cn.hutool.core.exceptions.ExceptionUtil;
  3. import cn.hutool.core.collection.CollUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.JSONObject;
  7. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  8. import com.fdkankan.common.constant.*;
  9. import com.fdkankan.common.util.FileUtils;
  10. import com.fdkankan.contro.entity.ScenePlus;
  11. import com.fdkankan.contro.entity.ScenePlusExt;
  12. import com.fdkankan.contro.entity.ScenePro;
  13. import com.fdkankan.contro.entity.SceneProEdit;
  14. import com.fdkankan.contro.mq.service.IBuildSceneService;
  15. import com.fdkankan.contro.mq.service.ICommonService;
  16. import com.fdkankan.contro.service.*;
  17. import com.fdkankan.contro.service.impl.FdkkV4Service;
  18. import com.fdkankan.fyun.face.FYunFileServiceInterface;
  19. import com.fdkankan.model.constants.ConstantFileName;
  20. import com.fdkankan.model.constants.ConstantFilePath;
  21. import com.fdkankan.model.constants.SceneBuildProcessType;
  22. import com.fdkankan.model.constants.UploadFilePath;
  23. import com.fdkankan.model.utils.CreateObjUtil;
  24. import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
  25. import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
  26. import com.fdkankan.rabbitmq.util.RabbitMqProducer;
  27. import com.fdkankan.redis.constant.RedisKey;
  28. import com.fdkankan.redis.util.RedisUtil;
  29. import lombok.extern.slf4j.Slf4j;
  30. import org.springframework.beans.factory.annotation.Autowired;
  31. import org.springframework.beans.factory.annotation.Value;
  32. import org.springframework.stereotype.Service;
  33. import org.springframework.util.ObjectUtils;
  34. import java.io.File;
  35. import java.util.List;
  36. import java.util.Objects;
  37. /**
  38. * <p>
  39. * TODO
  40. * </p>
  41. *
  42. * @author dengsixing
  43. * @since 2022/3/1
  44. **/
  45. @Slf4j
  46. @Service
  47. public class BuildObjServiceImpl implements IBuildSceneService {
  48. @Value("${queue.modeling.modeling-call}")
  49. private String queueModelingCall;
  50. @Value("${queue.modeling.obj.modeling-post}")
  51. private String queueObjModelingPost;
  52. @Value("${queue.modeling.obj.modeling-pre}")
  53. private String queueObjModelingPre;
  54. @Value("${model.modelKind:3dtiles}")
  55. private String modelKind;
  56. @Value("#{'${model.3dtiles.sceneSource:}'.split(',')}")
  57. private List<Integer> sdTilesSceneSourceList;
  58. @Autowired
  59. private RabbitMqProducer mqProducer;
  60. @Autowired
  61. private FYunFileServiceInterface fYunFileService;
  62. @Autowired
  63. private ISceneProService sceneProService;
  64. @Autowired
  65. private IFdkkLaserService fdkkLaserService;
  66. @Autowired
  67. private FdkkV4Service fdkkV4Service;
  68. @Autowired
  69. private IBuildSceneDTService buildSceneDTService;
  70. @Autowired
  71. private ISceneProEditService sceneProEditService;
  72. @Autowired
  73. private IScenePlusService scenePlusService;
  74. @Autowired
  75. private ISceneBuildProcessLogService sceneBuildProcessLogService;
  76. @Autowired
  77. private ICommonService commonService;
  78. @Autowired
  79. private IScenePlusExtService scenePlusExtService;
  80. @Autowired
  81. private RedisUtil redisUtil;
  82. @Override
  83. public void buildScenePre(BuildSceneCallMessage message) throws Exception{
  84. boolean success = false;
  85. String num = message.getSceneNum();
  86. try {
  87. String path = message.getPath();
  88. String laserObjFilePath = path + "_laser_obj";
  89. //根据相机类型,组装资源路径
  90. log.info("开始准备生成OBJ场景资源,路径:{}", laserObjFilePath);
  91. FileUtils.delAllFile(laserObjFilePath);
  92. //获取解压后的资源的data.fdage中的数据
  93. File folderPath = new File(path);
  94. fYunFileService.downloadFile(ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage", laserObjFilePath + "/capture/data.fdage");
  95. JSONObject jsonObject = FileUtils.readJson(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage");
  96. if(ObjectUtils.isEmpty(jsonObject)){
  97. log.error("data.fdage文件不存在");
  98. return ;
  99. }
  100. if (!jsonObject.containsKey("exportMeshObj") || jsonObject.getIntValue("exportMeshObj") != 1) {
  101. // 写入data.fdage 防止重算
  102. jsonObject.put("exportMeshObj", 1);
  103. fYunFileService.uploadFile(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage",
  104. ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage");
  105. }
  106. // 重新构造datafdage文件,添加生成obt文件选项
  107. jsonObject.put("OnlyExportMeshObj",true);
  108. FileUtils.writeFile(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage", jsonObject.toJSONString());
  109. message.getBuildContext().put("previousPath",path);
  110. message.setCameraType("14");
  111. message.setResolution(jsonObject.getString("resolution"));
  112. message.setPath(laserObjFilePath);
  113. message.setResultReceiverMqName(queueObjModelingPost);
  114. //下载资源到本地
  115. this.downLoadSource(message, laserObjFilePath);
  116. //发送mq,就进行计算
  117. mqProducer.sendByWorkQueue(queueModelingCall, message);
  118. success = true;
  119. log.info("场景计算资源准备结束,场景码:{}", message.getSceneNum());
  120. }catch (Exception e){
  121. log.error("生成OBJ场景资源准备异常,num=" + num, e);
  122. buildSceneDTService.handBaseFail("生成OBJ场景资源准备异常", message.getPath(), message.getSceneNum(), "计算控制服务器");
  123. throw e;
  124. }
  125. }
  126. @Override
  127. public void downLoadSource(BuildSceneCallMessage message,String path) throws Exception{
  128. ScenePro scenePro = sceneProService.getByNum(message.getSceneNum());
  129. String version = "V4";
  130. if(Objects.nonNull(scenePro) && scenePro.getIsUpgrade() != CommonStatus.YES.code().intValue()){
  131. version = "V3";
  132. }
  133. if(SceneVersionType.V4.code().equals(version)){
  134. String ossResultPath = String.format(UploadFilePath.scene_result_data_path, message.getSceneNum());
  135. fYunFileService.downloadFile(ossResultPath + "caches/reconstruction/final.bin", path + "/caches/reconstruction/final.bin");
  136. fYunFileService.downloadFile(ossResultPath + "caches/reconstruction/chunk.json", path + "/caches/reconstruction/chunk.json");
  137. fYunFileService.downloadFile(ossResultPath + "caches/floor_group_fix.json", path + "/caches/floor_group_fix.json");
  138. fYunFileService.downloadFileByCommand(path + "/caches/images/", ossResultPath + "caches/images/");
  139. fYunFileService.downloadFileByCommand( path + "/caches/depthmap_csc/" , ossResultPath + "caches/depthmap_csc/");
  140. fYunFileService.downloadFileByCommand( path + "/caches/depthmap_vis/", ossResultPath + "caches/depthmap_vis/");
  141. fYunFileService.downloadFileByCommand( path + "/caches/depthmap/", ossResultPath + "caches/depthmap/");
  142. fYunFileService.downloadFile(ossResultPath + "caches/panorama.json", path + "/caches/panorama.json");
  143. fYunFileService.downloadFile(ossResultPath + "results/laserData/laser.ply", path + "/results/laserData/laser.ply");
  144. }else{
  145. String prevoisPath = message.getBuildContext().get("previousPath").toString();
  146. FileUtils.copyFile(prevoisPath + "/caches/reconstruction/final.bin", path + "/caches/reconstruction/final.bin", true);
  147. FileUtils.copyFile(prevoisPath + "/caches/reconstruction/chunk.json", path + "/caches/reconstruction/chunk.json", true);
  148. FileUtils.copyFile(prevoisPath + "/caches/floor_group_fix.json", path + "/caches/floor_group_fix.json", true);
  149. FileUtils.copyDirectiory(prevoisPath + "/caches/images", path + "/caches/images");
  150. FileUtils.copyDirectiory(prevoisPath + "/caches/depthmap_csc", path + "/caches/depthmap_csc");
  151. FileUtils.copyDirectiory(prevoisPath + "/caches/depthmap_vis", path + "/caches/depthmap_vis");
  152. FileUtils.copyDirectiory(prevoisPath + "/caches/depthmap", path + "/caches/depthmap");
  153. FileUtils.copyFile(prevoisPath + "/caches/panorama.json", path + "/caches/panorama.json", true);
  154. FileUtils.copyFile(prevoisPath + "/results/laserData/laser.ply", path + "/results/laserData/laser.ply", true);
  155. }
  156. }
  157. @Override
  158. public void buildScenePost(BuildSceneResultMqMessage message) throws Exception {
  159. String path = message.getPath();
  160. String projectNum = message.getBuildContext().get("sceneNum").toString();
  161. String laserObjFilePath = path;
  162. boolean success = false;
  163. try {
  164. //上传计算日志
  165. String buildLogPath = String.format(UploadFilePath.BUILD_LOG_PATH, projectNum);
  166. fYunFileService.uploadFile(path + File.separator + "console.log", buildLogPath + "console.log");
  167. if (!message.getBuildSuccess()) {
  168. log.error("生成OBJ场景计算失败!");
  169. // 发送钉钉消息,计算失败
  170. buildSceneDTService.handModelFail("生成OBJ场景计算失败!", message.getPath(), message.getBuildContext().get("sceneNum").toString(), message.getHostName());
  171. return;
  172. }
  173. ScenePro scenePro = sceneProService.getByNum(projectNum);
  174. String version = "v4";
  175. String ossImagePath = String.format(UploadFilePath.IMG_VIEW_PATH, projectNum);
  176. //如果是微服务上线之前的存量场景且未生成过obj(未升级过),需要上传到v3的目录,在函数最后调用升级接口进行文件拷贝
  177. if(Objects.nonNull(scenePro) && scenePro.getIsUpgrade() != CommonStatus.YES.code().intValue()){
  178. ossImagePath = String.format(ConstantFilePath.IMAGE_PATH_FORMAT, projectNum);
  179. version = "v3";
  180. }
  181. //上传obj
  182. String resultsPath = path + File.separator + "results" + File.separator;
  183. if(this.modelKind.equals(ModelKind.DAM.code())){
  184. CreateObjUtil.convertTxtToDam(path + File.separator + "results" + File.separator + "tex" + File.separator + "modeldata.txt", path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam");
  185. CreateObjUtil.convertDamToLzma(path + File.separator + "results/");
  186. CreateObjUtil.convertTxtToDam(path + File.separator + "results" + File.separator + "tex" + File.separator + "modeldata.txt", path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam");
  187. File file = new File(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam.lzma");
  188. while (!file.exists()) {
  189. Thread.sleep(60000);
  190. }
  191. fYunFileService.uploadFile(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam.lzma", ossImagePath + ConstantFileName.modelUUID + "_50k.dam.lzma");
  192. fYunFileService.uploadFile(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam", ossImagePath + ConstantFileName.modelUUID + "_50k.dam");
  193. }
  194. if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
  195. && CollUtil.isNotEmpty(sdTilesSceneSourceList)
  196. && sdTilesSceneSourceList.contains(SceneSource.JG.code())){
  197. String threedtilesPath = resultsPath + ModelKind.THREE_D_TILE.code();
  198. String oss3dtilesPath = ossImagePath + ModelKind.THREE_D_TILE.code();
  199. List<String> list = FileUtils.list(new File(threedtilesPath));
  200. if(CollUtil.isEmpty(list)){
  201. log.error("3dtiles目录异常,3dtiles地址:{}", new File(path + File.separator + "results" + File.separator + ModelKind.THREE_D_TILE.code()));
  202. throw new Exception("3dtiles目录异常");
  203. }
  204. //上传3dtiles文件
  205. fYunFileService.uploadFileByCommand(threedtilesPath, oss3dtilesPath);
  206. }
  207. String texPath = laserObjFilePath + File.separator + "results" + File.separator + "tex";
  208. File texFile = new File(texPath);
  209. if(texFile.exists()){
  210. for (File textureFile : texFile.listFiles()) {
  211. if(textureFile.getName().endsWith(".jpg")){
  212. fYunFileService.uploadFile(textureFile.getAbsolutePath(),
  213. ossImagePath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/"+textureFile.getName());
  214. }
  215. }
  216. }
  217. fYunFileService.uploadFile(laserObjFilePath + File.separator + "results" + File.separator + "tex/texture1.jpg",
  218. ossImagePath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/texture1.jpg");
  219. // 拷贝结果
  220. log.info("开始拷贝obj文件");
  221. FileUtils.copyFolderAllFiles(laserObjFilePath + "/results/mesh", laserObjFilePath + "/laserData/mesh/", true);
  222. //上传mesh文件
  223. fYunFileService.uploadFileByCommand(laserObjFilePath + "/results/mesh", String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "mesh");
  224. if(!ObjectUtils.isEmpty(scenePro)){
  225. LambdaUpdateWrapper<ScenePro> updateWrapper = new LambdaUpdateWrapper<ScenePro>()
  226. .set(ScenePro::getStatus, -2).eq(ScenePro::getNum, projectNum);
  227. sceneProService.update(updateWrapper);
  228. sceneProEditService.update(new LambdaUpdateWrapper<SceneProEdit>().set(SceneProEdit::getMapVisi,0)
  229. .eq(SceneProEdit::getProId,scenePro.getId()));
  230. }
  231. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(projectNum);
  232. if(!ObjectUtils.isEmpty(scenePlus)){
  233. LambdaUpdateWrapper<ScenePlus> plusUpdateWrapper = new LambdaUpdateWrapper<ScenePlus>()
  234. .set(ScenePlus::getSceneStatus, -2).eq(ScenePlus::getNum, projectNum);
  235. scenePlusService.update(plusUpdateWrapper);
  236. if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
  237. && CollUtil.isNotEmpty(sdTilesSceneSourceList)
  238. && sdTilesSceneSourceList.contains(SceneSource.JG.code())){
  239. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  240. scenePlusExt.setModelKind(ModelKind.THREE_D_TILE.code());
  241. scenePlusExtService.updateById(scenePlusExt);
  242. String sceneJsonStr = fYunFileService.getFileContent(String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "scene.json");
  243. if(StrUtil.isNotEmpty(sceneJsonStr)){
  244. JSONObject sceneJson = JSON.parseObject(sceneJsonStr);
  245. sceneJson.put("modelKind", ModelKind.THREE_D_TILE.code());
  246. fYunFileService.uploadFile(sceneJson.toJSONString().getBytes(), String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "scene.json");
  247. redisUtil.del(String.format(RedisKey.SCENE_JSON, projectNum));
  248. }
  249. }
  250. }
  251. // 如果未升级V4,则升级V4
  252. if("v3".equals(version)){
  253. fdkkV4Service.upgradeToV4(projectNum);
  254. }
  255. success = true;
  256. }catch (Exception e){
  257. log.error("生成OBJ场景计算结果处理异常,num=" + projectNum, e);
  258. buildSceneDTService.handBaseFail("生成OBJ场景计算结果处理异常", message.getPath(), projectNum, "计算控制服务器");
  259. throw e;
  260. }finally {
  261. fdkkLaserService.pushBuildStatusToLaserSystem(projectNum, laserObjFilePath + "/laserData/mesh", success ? CommonOperStatus.SUCCESS.code() : CommonOperStatus.FAILD.code());
  262. }
  263. }
  264. }