fusenapi/server/websocket/internal/logic/ws_render_image.go
2023-09-05 14:58:37 +08:00

585 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package logic
//处理websocket云渲染任务数据
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/service/repositories"
"fusenapi/utils/curl"
"fusenapi/utils/hash"
"fusenapi/utils/websocket_data"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
"strconv"
"time"
)
// 渲染处理器
type renderProcessor struct {
}
// 云渲染属性
type extendRenderProperty struct {
renderImageTask map[string]*renderTask //需要渲染的图片任务 key是taskId val 是renderId
renderImageTaskCtlChan chan renderImageControlChanItem //渲染任务新增/回调结果移除任务/更新渲染耗时属性的控制通道由于任务map无法读写并发
renderChan chan []byte //渲染消息入口的缓冲队列
}
// 渲染任务新增移除的控制通道的数据
type renderImageControlChanItem struct {
option int // 0删除 1添加 2修改耗时属性
taskId string //map的key(必须传)
renderId string // map的val(增加任务时候传)
renderNotifyImageUrl string //渲染回调数据(删除任务时候传)
taskProperty renderTask //渲染任务的属性
}
// 渲染任务属性
type renderTask struct {
renderId string //渲染id(新增任务传)
unityRenderBeginTime int64 //发送给unity时间
unityRenderEndTime int64 //unity回调结果时间
uploadUnityRenderImageTakesTime int64 //上传unity渲染结果图时间
}
// 处理分发到这里的数据
func (r *renderProcessor) allocationMessage(w *wsConnectItem, data []byte) {
logx.Info("收到渲染任务消息:", string(data))
select {
case <-w.closeChan: //已经关闭
return
case w.extendRenderProperty.renderChan <- data: //发入到缓冲队列
return
case <-time.After(time.Second * 3): //三秒没进入缓冲队列就丢弃
return
}
}
// 消费渲染缓冲队列数据
func (w *wsConnectItem) consumeRenderImageData() {
defer func() {
if err := recover(); err != nil {
logx.Error("func renderImage err:", err)
}
}()
for {
select {
case <-w.closeChan: //已关闭
return
case data := <-w.extendRenderProperty.renderChan:
w.renderImage(data)
}
}
}
// 执行渲染任务
func (w *wsConnectItem) renderImage(data []byte) {
logx.Info("消费渲染数据:", string(data))
var renderImageData websocket_data.RenderImageReqMsg
if err := json.Unmarshal(data, &renderImageData); err != nil {
w.incomeDataFormatErrResponse("invalid format of render data:" + string(data))
logx.Error("invalid format of websocket render image message", err)
return
}
//获取上传最近的logo
userMaterial, err := w.logic.svcCtx.AllModels.FsUserMaterial.FindLatestOne(w.logic.ctx, w.userId, w.guestId)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取用户上传logo素材失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
logx.Error("failed to get user logo")
return
}
//使用默认logo(id=0)
userMaterialDefault, err := w.logic.svcCtx.AllModels.FsUserMaterial.FindOneById(w.logic.ctx, 0)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "默认logo不存在", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取默认logo失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
logx.Error("default logo is not exists")
return
}
renderImageData.RenderData.Logo = *userMaterialDefault.ResourceUrl
} else {
renderImageData.RenderData.Logo = *userMaterial.ResourceUrl
}
//用户id赋值
renderImageData.RenderData.UserId = w.userId
renderImageData.RenderData.GuestId = w.guestId
var (
model3dInfo *gmodel.FsProductModel3d
productTemplate *gmodel.FsProductTemplateV2
productSize *gmodel.FsProductSize
)
//指定尺寸
if renderImageData.RenderData.ProductSizeId > 0 {
productSize, productTemplate, model3dInfo, err = w.getProductRelateionInfoWithSizeId(renderImageData)
} else { //未指定尺寸反查,先寻找模板
productSize, productTemplate, model3dInfo, err = w.getProductRelateionInfoWithNoSizeId(renderImageData)
}
if err != nil {
return
}
//获取渲染设置信息
element, err := w.logic.svcCtx.AllModels.FsProductTemplateElement.FindOneByModelId(w.logic.ctx, *productTemplate.ElementModelId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "云渲染设置不存在", renderImageData.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
logx.Error("element info is not found,element_model_id = ", 0)
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取云渲染设置失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
logx.Error("failed to get element ,", err)
return
}
//获取刀版图
combineReq := repositories.LogoCombineReq{
UserId: renderImageData.RenderData.UserId,
GuestId: renderImageData.RenderData.GuestId,
TemplateId: productTemplate.Id,
TemplateTag: renderImageData.RenderData.TemplateTag,
Website: renderImageData.RenderData.Website,
Slogan: renderImageData.RenderData.Slogan,
Address: renderImageData.RenderData.Address,
Phone: renderImageData.RenderData.Phone,
Qrcode: renderImageData.RenderData.Qrcode,
LogoUrl: renderImageData.RenderData.Logo,
}
res, err := w.logic.svcCtx.Repositories.ImageHandle.LogoCombine(w.logic.ctx, &combineReq)
if err != nil {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "合成刀版图失败:"+err.Error(), renderImageData.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
logx.Error("合成刀版图失败,合成请求数据:", combineReq, "错误信息:", err)
return
}
combineImage := "" //刀版图
if res != nil && res.ResourceUrl != nil {
combineImage = *res.ResourceUrl
} else {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "合成的刀版图是空的地址", renderImageData.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
logx.Error("合成刀版图失败,合成的刀版图是空指针:", err)
return
}
//发送合图完毕阶段消息
w.sendCombineImageStepResponseMessage(renderImageData.RenderId, combineImage, res.DiffTimeLogoCombine, res.DiffTimeUploadFile)
//如果指定指定只返回刀版图
if renderImageData.OnlyReturnCombineImage {
logx.Info("云渲染传入size id则不走unity云渲染,只返回刀版图render_id:", renderImageData.RenderId)
return
}
//获取唯一id
taskId := w.genRenderTaskId(renderImageData, model3dInfo, productTemplate, element)
//查询有没有缓存的资源,有就返回######################
resource, err := w.logic.svcCtx.AllModels.FsResource.FindOneById(w.logic.ctx, taskId)
if err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, taskId, "获取unity云渲染缓存失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
logx.Error("failed to find render resource:", err)
return
}
} else {
//返回给客户端
w.sendRenderResultData(websocket_data.RenderImageRspMsg{
RenderId: renderImageData.RenderId,
Image: *resource.ResourceUrl,
RenderProcessTime: websocket_data.RenderProcessTime{
UnityRenderTakesTime: "cache",
UploadUnityRenderImageTakesTime: "cache",
},
})
return
}
//###########################################
//把需要渲染的图片任务加进去
w.createRenderTask(taskId, renderImageData.RenderId)
//组装数据
if err = w.assembleRenderDataToUnity(taskId, combineImage, renderImageData, productTemplate, model3dInfo, element, productSize); err != nil {
logx.Error("组装数据失败:", err)
return
}
}
// 获取模板相关信息(指定尺寸)
func (w *wsConnectItem) getProductRelateionInfoWithSizeId(renderImageData websocket_data.RenderImageReqMsg) (productSize *gmodel.FsProductSize, productTemplate *gmodel.FsProductTemplateV2, model3d *gmodel.FsProductModel3d, err error) {
productSize, err = w.logic.svcCtx.AllModels.FsProductSize.FindOneByIdProductId(w.logic.ctx, renderImageData.RenderData.ProductSizeId, renderImageData.RenderData.ProductId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "找不到产品的指定尺寸", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, renderImageData.RenderData.ProductSizeId, 0)
logx.Error("product size is not found")
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取产品的指定尺寸失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, renderImageData.RenderData.ProductSizeId, 0)
logx.Error("failed to get product size:", err)
return
}
//获取模型
model3d, err = w.logic.svcCtx.AllModels.FsProductModel3d.GetOneBySizeIdTag(w.logic.ctx, productSize.Id, constants.TAG_MODEL)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "产品指定尺寸对应的模型不存在", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, productSize.Id, 0)
logx.Error("product model is not found")
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取产品指定尺寸对应的模型失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, productSize.Id, 0)
logx.Error("failed to get product model:", err)
return
}
//获取模板
productTemplate, err = w.logic.svcCtx.AllModels.FsProductTemplateV2.FindOneCloudRenderByProductIdModelIdTemplateTag(w.logic.ctx, renderImageData.RenderData.ProductId, model3d.Id, renderImageData.RenderData.TemplateTag)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "找不到对应开启云渲染的模板", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, model3d.Id, productSize.Id, 0)
logx.Error("template info is not found")
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取对应开启云渲染模板失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, model3d.Id, productSize.Id, 0)
logx.Error("failed to get template info:", err)
return
}
return
}
// 获取模板相关信息(未指定尺寸)
func (w *wsConnectItem) getProductRelateionInfoWithNoSizeId(renderImageData websocket_data.RenderImageReqMsg) (productSize *gmodel.FsProductSize, productTemplate *gmodel.FsProductTemplateV2, model3d *gmodel.FsProductModel3d, err error) {
//获取模板
productTemplate, err = w.logic.svcCtx.AllModels.FsProductTemplateV2.FindOneCloudRenderByProductIdTemplateTag(w.logic.ctx, renderImageData.RenderData.ProductId, renderImageData.RenderData.TemplateTag)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "找不到对应开启云渲染的模板", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
logx.Error("template info is not found")
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取对应开启云渲染模板失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
logx.Error("failed to get template info:", err)
return
}
//获取模型
model3d, err = w.logic.svcCtx.AllModels.FsProductModel3d.FindOne(w.logic.ctx, *productTemplate.ModelId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "产品指定尺寸对应的模型不存在", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
logx.Error("product model is not found")
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取产品指定尺寸对应的模型失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, 0, 0, 0)
logx.Error("failed to get product model:", err)
return
}
productSize, err = w.logic.svcCtx.AllModels.FsProductSize.FindOne(w.logic.ctx, *model3d.SizeId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "找不到产品的指定尺寸", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, model3d.Id, renderImageData.RenderData.ProductSizeId, 0)
logx.Error("product size is not found")
return
}
w.renderErrResponse(renderImageData.RenderId, renderImageData.RenderData.TemplateTag, "", "获取产品的指定尺寸失败", renderImageData.RenderData.ProductId, w.userId, w.guestId, 0, model3d.Id, renderImageData.RenderData.ProductSizeId, 0)
logx.Error("failed to get product size:", err)
return
}
return
}
// 组装数据发送给unity
func (w *wsConnectItem) assembleRenderDataToUnity(taskId string, combineImage string, info websocket_data.RenderImageReqMsg, productTemplate *gmodel.FsProductTemplateV2, model3dInfo *gmodel.FsProductModel3d, element *gmodel.FsProductTemplateElement, productSize *gmodel.FsProductSize) (err error) {
//组装数据
refletion := -1
if element.Refletion != nil && *element.Refletion != "" {
refletion, err = strconv.Atoi(*element.Refletion)
if err != nil {
logx.Error("err refletion:set default -1")
w.renderErrResponse(info.RenderId, info.RenderData.TemplateTag, taskId, "解析云渲染设置把Refletion字段值从字符串转数字失败", info.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
return err
}
}
//组装data数据
var mode map[string]interface{}
if element.Mode != nil && *element.Mode != "" {
if err = json.Unmarshal([]byte(*element.Mode), &mode); err != nil {
logx.Error("faile to parse element mode json:", err)
w.renderErrResponse(info.RenderId, info.RenderData.TemplateTag, taskId, "解析云渲染设置字段 mode 为map对象失败", info.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
return err
}
}
tempData := make([]map[string]interface{}, 0, 3)
if element.Base != nil && *element.Base != "" {
tempData = append(tempData, map[string]interface{}{
"name": "model",
"data": "0," + combineImage + "," + *element.Base,
"type": "other",
"layer": "0",
"is_update": 1,
"mode": mode["model"],
})
}
if element.Shadow != nil && *element.Shadow != "" {
tempData = append(tempData, map[string]interface{}{
"name": "shadow",
"data": *element.Shadow,
"type": "other",
"layer": "0",
"is_update": 0,
"mode": mode["shadow"],
})
}
if element.ModelP != nil && *element.ModelP != "" {
tempData = append(tempData, map[string]interface{}{
"name": "model_P",
"data": "0," + *element.ModelP,
"type": "other",
"layer": "0",
"is_update": 0,
"mode": mode["model_P"],
})
}
result := []interface{}{
map[string]interface{}{
"light": *element.Light,
"refletion": refletion,
"scale": *element.Scale,
"sku_id": info.RenderData.ProductId,
"tid": *element.Title,
"rotation": *element.Rotation,
"filePath": "", //todo 文件路径,针对千人千面
"data": tempData,
},
}
//发送运行阶段消息(组装数据)
w.sendAssembleRenderDataStepResponseMessage(info.RenderId)
sendData := map[string]interface{}{
"id": taskId + " " + w.uniqueId, //空格分开
"order_id": 0,
"user_id": info.RenderData.UserId,
"guest_id": info.RenderData.GuestId,
"sku_ids": []int64{info.RenderData.ProductId},
"tids": []string{*element.Title},
"data": result,
"is_thousand_face": 0,
"folder": "", //todo 千人千面需要使用
}
//请求unity接口
url := w.logic.svcCtx.Config.Unity.Host + "/api/render/queue/push"
header := make(map[string]string)
header["content-type"] = "application/json"
postData := map[string]interface{}{
"group": "unity3d",
"source": "home page",
"priority": 1,
"create_at": time.Now().UTC(),
"render_data": sendData,
}
postDataBytes, _ := json.Marshal(postData)
unityRenderBeginTime := time.Now().UTC().UnixMilli()
_, err = curl.ApiCall(url, "POST", header, bytes.NewReader(postDataBytes), time.Second*10)
if err != nil {
w.renderErrResponse(info.RenderId, info.RenderData.TemplateTag, taskId, "请求unity接口失败", info.RenderData.ProductId, w.userId, w.guestId, productTemplate.Id, model3dInfo.Id, productSize.Id, *productTemplate.ElementModelId)
logx.Error("failed to send data to unity")
return err
}
//记录发送到unity时间
w.modifyRenderTaskProperty(taskId, renderTask{unityRenderBeginTime: unityRenderBeginTime})
//发送运行阶段消息
w.sendRenderDataToUnityStepResponseMessage(info.RenderId)
logx.Info("发送到unity成功,刀版图:", combineImage, " 请求unity的数据:", string(postDataBytes))
return nil
}
// 发送合图完毕阶段通知消息
func (w *wsConnectItem) sendCombineImageStepResponseMessage(renderId, combineImage string, combineTime, uploadTime int64) {
combineTakesTime := "cache"
uploadCombineImageTakesTime := "cache"
if combineTime > 0 {
combineTakesTime = fmt.Sprintf("%dms", combineTime)
}
if uploadTime > 0 {
uploadCombineImageTakesTime = fmt.Sprintf("%dms", uploadTime)
}
w.sendToOutChan(w.respondDataFormat(constants.WEBSOCKET_COMBINE_IMAGE, websocket_data.CombineImageRspMsg{
RenderId: renderId,
CombineImage: combineImage,
CombineProcessTime: websocket_data.CombineProcessTime{
CombineTakesTime: combineTakesTime,
UploadCombineImageTakesTime: uploadCombineImageTakesTime,
},
}))
}
// 发送组装unity渲染数据完毕阶段通知消息
func (w *wsConnectItem) sendAssembleRenderDataStepResponseMessage(renderId string) {
w.sendToOutChan(w.respondDataFormat(constants.WEBSOCKET_ASSEMBLE_RENDER_DATA, websocket_data.ToUnityRspMsg{RenderId: renderId}))
}
// 发送组装unity渲染数据完毕阶段通知消息
func (w *wsConnectItem) sendRenderDataToUnityStepResponseMessage(renderId string) {
w.sendToOutChan(w.respondDataFormat(constants.WEBSOCKET_SEND_DATA_TO_UNITY, websocket_data.AssembleRenderDataRspMsg{RenderId: renderId}))
}
// 发送渲染最终结果数据到前端
func (w *wsConnectItem) sendRenderResultData(data websocket_data.RenderImageRspMsg) {
w.sendToOutChan(w.respondDataFormat(constants.WEBSOCKET_RENDER_IMAGE, data))
}
// 增加渲染任务
func (w *wsConnectItem) createRenderTask(taskId, renderId string) {
if taskId == "" {
logx.Error("task_id不能为空")
return
}
if renderId == "" {
logx.Error("render_id不能为空")
return
}
data := renderImageControlChanItem{
option: 1,
taskId: taskId,
renderId: renderId,
}
select {
case <-w.closeChan: //关闭
return
case w.extendRenderProperty.renderImageTaskCtlChan <- data:
return
case <-time.After(time.Second * 3):
return
}
}
// 渲染回调处理并删除渲染任务
func (w *wsConnectItem) deleteRenderTask(taskId, renderNotifyImageUrl string) {
if taskId == "" {
logx.Error("task_id不能为空")
return
}
data := renderImageControlChanItem{
option: 0,
taskId: taskId,
renderNotifyImageUrl: renderNotifyImageUrl,
}
select {
case <-w.closeChan: //关闭
return
case w.extendRenderProperty.renderImageTaskCtlChan <- data:
return
case <-time.After(time.Second * 3):
return
}
}
// 修改任务属性(只有耗时属性可以更新)
func (w *wsConnectItem) modifyRenderTaskProperty(taskId string, property renderTask) {
if taskId == "" {
logx.Error("task_id不能为空")
return
}
//强制设为修改任务属性
data := renderImageControlChanItem{
option: 2,
taskId: taskId,
taskProperty: property,
}
select {
case <-w.closeChan: //关闭
return
case w.extendRenderProperty.renderImageTaskCtlChan <- data:
return
case <-time.After(time.Second * 3):
return
}
}
// 组装渲染任务id
func (w *wsConnectItem) genRenderTaskId(renderImageData websocket_data.RenderImageReqMsg, model3dInfo *gmodel.FsProductModel3d, productTemplate *gmodel.FsProductTemplateV2, element *gmodel.FsProductTemplateElement) string {
//生成任务id(需要把user_id,guest_id设为0)
incomeHashParam := renderImageData.RenderData
incomeHashParam.UserId = 0 //设为0(渲染跟用户id无关)
incomeHashParam.GuestId = 0 //设为0(渲染跟用户id无关)
incomeHashBytes, _ := json.Marshal(incomeHashParam)
modelHashStr := ""
templateHashStr := ""
if model3dInfo.ModelInfo != nil {
modelHashStr = *model3dInfo.ModelInfo
}
if productTemplate.TemplateInfo != nil {
templateHashStr = *productTemplate.TemplateInfo
}
elementHashBytes, _ := json.Marshal(element)
hashMap := map[string]interface{}{
"income_param": incomeHashBytes,
"model_info": modelHashStr,
"template_info": templateHashStr,
"material_image": *productTemplate.MaterialImg,
"render_element": elementHashBytes,
}
return hash.JsonHashKey(hashMap)
}
// 处理渲染任务的增加/删除/修改耗时属性任务map不能读写并发所以放在chan里面串行执行
func (w *wsConnectItem) operationRenderTask() {
defer func() {
if err := recover(); err != nil {
logx.Error("operation render task panic:", err)
}
}()
for {
select {
case <-w.closeChan:
return
case data := <-w.extendRenderProperty.renderImageTaskCtlChan:
switch data.option {
case 0: //渲染结果回调,删除任务
taskData, ok := w.extendRenderProperty.renderImageTask[data.taskId]
if !ok {
continue
}
//存在任务,则发送渲染结果给前端
UnityRenderTakesTime := "cache"
uploadUnityRenderImageTakesTime := "cache"
//unity渲染时间
if taskData.unityRenderBeginTime > 0 && taskData.unityRenderEndTime > 0 {
UnityRenderTakesTime = fmt.Sprintf("%dms", taskData.unityRenderEndTime-taskData.unityRenderBeginTime)
}
//上传unity渲染图耗时
if taskData.uploadUnityRenderImageTakesTime > 0 {
uploadUnityRenderImageTakesTime = fmt.Sprintf("%dms", taskData.uploadUnityRenderImageTakesTime)
}
//发送到出口
w.sendRenderResultData(websocket_data.RenderImageRspMsg{
RenderId: taskData.renderId,
Image: data.renderNotifyImageUrl,
RenderProcessTime: websocket_data.RenderProcessTime{
UnityRenderTakesTime: UnityRenderTakesTime,
UploadUnityRenderImageTakesTime: uploadUnityRenderImageTakesTime,
},
})
//删除任务
delete(w.extendRenderProperty.renderImageTask, data.taskId)
case 1: //新增任务
w.extendRenderProperty.renderImageTask[data.taskId] = &renderTask{
renderId: data.renderId,
}
case 2: //修改任务属性
taskData, ok := w.extendRenderProperty.renderImageTask[data.taskId]
if !ok {
continue
}
//上传渲染结果图耗时
if data.taskProperty.uploadUnityRenderImageTakesTime != 0 {
taskData.uploadUnityRenderImageTakesTime = data.taskProperty.uploadUnityRenderImageTakesTime
}
//发送unity时间
if data.taskProperty.unityRenderBeginTime != 0 {
taskData.unityRenderBeginTime = data.taskProperty.unityRenderBeginTime
}
//收到unity返回的时间
if data.taskProperty.unityRenderEndTime != 0 {
taskData.unityRenderEndTime = data.taskProperty.unityRenderEndTime
}
}
}
}
}