背景:
在三维模型深度处理的时候,有时候需要对模型进行区域划分.并赋予一定的材质,力学等属性,所以,需要对模型进行划分.
目前的模型体素化的方式基本分为cpu,gpu,都是投影射线法进行的, 在调研了一些已知的开源算法和项目,并测试后发现,大部分的开源项目也都是基于抽壳进行的计算,并不满足自己项目(岩土,GIS)等方面的要求,所以这里自己按照已有的理论,进行了修改,从而做了一个空间内部填充的全体素化,而且后续也方便进行不规则体素的操作.里面使用了bsvtree进行加速处理.
结果:
改两个参数:的效果.
计算时间加长了一点,不过很多细节保留了下来
换个模型试一下:
实现过程以及关键代码:
计算流程:
1.实现流程,求解模型的OBB盒子,按照其最大面积那个面,按照sizeX,sizeY进行拆分.
2.计算一系列等距射线,构建bsvTree进行模型结构化,进行快速求交,
3.获取交点后,处理交点为1和>1的多种情况,按照射线法向,进行距离迭代插值判定,依据奇偶规则进行区分内外盒子.到此,模型内外以及壳表面区分完成,进行体素绘制;
关键代码:
mDimStartZ = 0;int GetInterCheckFirst = 0;//我们获取当前的.double threoldValue = gridSizePerDim[2] / 2.0;//阈值./// <summary>/// 获取尺寸数据./// </summary>SigleT defalutData;defalutData.zL = 0;defalutData.isStatus = false;auto GetInterData = [&](int index)-> decltype(&interSectListL[0]) {if (index < interSectListL.size()){return &interSectListL[index];}else{return nullptr;}};SigleT*firstCheckData = nullptr;//获取第一个值.SigleT*secondChckData = nullptr;//全部体素,第三个循环bool isOpenAddStatus = false;while (mDimStartZ < ZLength){firstCheckData = GetInterData(GetInterCheckFirst);if (firstCheckData == nullptr){mDimStartZ += gridSizePerDim[2];continue;}CurP[0] = FaceStartPoint[0] + mDimStartX;CurP[1] = FaceStartPoint[1] + mDimStartY;CurP[2] = FaceStartPoint[2] + mDimStartZ;if (intersecCount == 1){CurP[2] = FaceStartPoint[2]+ firstCheckData->zL;AddVoxelDatas(CurP.GetData());//创建.break;}else{secondChckData = GetInterData(GetInterCheckFirst + 1);if (secondChckData == nullptr){mDimStartZ += gridSizePerDim[2];continue;}double firstDiffer = mDimStartZ - firstCheckData->zL;//取负数double secondDiffer = mDimStartZ - secondChckData->zL;double absValue = std::abs(firstDiffer);if (absValue < threoldValue)//横切边界.{AddVoxelDatas(CurP.GetData());isOpenAddStatus = true;//激活.}else //填充.{if (isOpenAddStatus == true){AddVoxelDatas(CurP.GetData());}}if (secondDiffer > 0)//奇偶变换.{GetInterCheckFirst++;isOpenAddStatus = false;//每次变换,关闭,直到下一次循环激活为止.}}mDimStartZ += gridSizePerDim[2];}
到此,任意模型体素化代码完成.