SuperMap iObjects .NET编写提取大纹理模型工具

首先解释下什么叫“大纹理模型”,一般来说我们建模会要求模型纹理尺寸应小于1024x1024,所以小编把存在子对象的纹理长或宽尺寸超过1024的模型称之为“大纹理模型”。其次,为何要把“大纹理模型”给提取出来?理由主要有如下两点:

(1)模型数据生成缓存时,会将模型的纹理长宽尺寸处理成一致,并且取其较大值,比如模型生成缓存前的纹理尺寸为256x1024,那么生成缓存后的尺寸则处理成1024x1024。由此可见,如果存在尺寸特别大的纹理,生成缓存后会导致缓存文件增大很多,影响性能,所以需要将这部分模型提取出来,单独做处理。

(2)模型生成缓存时,有一个限制纹理大小的选项,该选项功能是当模型纹理尺寸超过指定大小时,会将该纹理压缩到指定大小,生成缓存。很多用户为了性能,都会将纹理大小限制到1024,这样可能会造成一个问题,某些我们特别关注的地方,纹理被压缩后显示效果不好,比如某些广告墙。所以我们需要把这些我们特别关注的“大纹理模型”给挑出来,不去做纹理压缩。

一.开发思路

我们会逐个检查每个模型的所有子对象,获取子对象所有纹理的长和宽,当长或宽大于1024时,则在原来的数据集中删除掉这个模型,并且把该模型添加到新的数据集中。

二.数据结构图

工作空间(workspace)---->数据源(datasource)---->模型数据集(datasetvector)---->记录集(recordset)---->对象(geomodel3d)---->模型(model)---->子对象(Skeleton)---->材质(material3D)---->纹理(textureData)

需要特别说明的是,某些模型可能存在多级lod,如果存在多级lod,上述关系链需要调整为:模型(model)---->lod---->子对象(Skeleton),lod的索引是-1开始。
另外一般来说一个模型有一个或多个子对象,一个材质可能包含一重或多重纹理。

为了简便,本工具代码仅仅考虑模型只存在一级lod,材质只包含一重纹理。

三.代码实战

1.为了方便起见,我们直接在iDesktop中创建好一个新的模型数据集,代码中打开工作空间,获取到原模型数据集和新的模型数据集,并且获取到它们各自的记录集。

Workspace workspace = new Workspace();
WorkspaceConnectionInfo info = new WorkspaceConnectionInfo(@"C:\Users\hulinPC\Desktop\shandongjiaogui\Build1.smwu");//该路径为工作空间所在路径
workspace.Open(info);

DatasetVector dataset = workspace.Datasources[0].Datasets["model01"] as DatasetVector;//原数据集
DatasetVector datasetnew = workspace.Datasources[0].Datasets["New_Model"] as DatasetVector;//新数据集
recordset = dataset.GetRecordset(false, CursorType.Dynamic);//原记录集
recordsetnew = datasetnew.GetRecordset(false,CursorType.Dynamic);//新记录集

2.遍历记录集,逐个检查每个模型的所有子对象,获取子对象所有纹理的长和宽,当长或宽大于1024时,则在原来的数据集中删除掉这个模型,并且把该模型添加到新的数据集中。

 for (int i = 0; i < recordset.RecordCount; i++)
        {
            GeoModel3D geomodel3d = recordset.GetGeometry() as GeoModel3D;//获取对象
            Model model = geomodel3d.Model;//获取模型
            bool next = true;//设置一个游标指示,因为删除一条记录后,后一条记录的索引就会变成当前记录的索引,所以删除记录时,游标不必移动到下一条记录。
            int skeletoncount = model.GetSkeletonCount(-1);//数据只有一级lod,所以直接从-1索引即可
            for (int j = 0; j < skeletoncount; j++)//遍历对象的所有子对象
            {
                SkeletonID skeletonid = new SkeletonID(-1, j);//获取子对象ID,此处的-1也是lod的索引
                Skeleton skeleton = model.GetSkeleton(skeletonid);//根据ID获取到子对象

                Material3D material3D = skeleton.Material;//获取子对象的材质

                List<TextureData> textureDatas = material3D.Textures;获取子对象的纹理集合
                if (textureDatas[0].Height > 1024 || textureDatas[0].Width > 1024)//数据的材质都只有一重纹理,所以直接从0开始索引到纹理即可。
                {
                    recordsetnew.AddNew(geomodel3d);//向新数据集添加模型
                    recordsetnew.Update();//更新

                    recordset.Delete();//原数据集删除模型
                    recordset.Update();//更新
                    next = false;//游标指示设为false,也就是上面提到的,删除记录时,游标不需要移动到下一条记录
                    break;//只要存在一个长或宽超过1024的纹理,即跳出循环
                }


            }
            if (next == true)
            {
                recordset.MoveNext();//没有删除记录,游标移动到下一条记录
            }

           
        }

上面就是提取“大纹理模型”工具的开发思路和核心代码,后续小编会将相关代码整理成一个完整的范例上传到超图技术资源中心http://support.supermap.com.cn/,在里面搜索关键字后,点击超图代码即可查找范例。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值