优化Unity3D插件Ezy-Slice部分缺陷

 Unity3D中,如果制作者想开发一款类似《水果忍者》类型的游戏,需要利用到Mesh的切割技术,那我认为Ezy-Slice这款插件是必不可少的。本文着重讲解的是如何优化,代码的细节部分我不会过多讲解。有需要的可以自行去官网下载理解。

作者也是第一次写这类技术文章,作为刚入职工作的比较满意的成果,如果有地方写的不好请大家谅解~

插件网址GitHub - DavidArayan/ezy-slice: An open source mesh slicer framework for Unity3D Game Engine. Written in C#.

首先该插件使用的主要方法入口是SliceObject,需要提供一个被切割的物体GameObject,一个起始的坐标和法线方向,法线方向就是切割完法线朝着的那一侧为正侧,另一侧为反侧。

public SlicedHull SliceObject(GameObject obj, Vector3 StartPosition, Vector3 Normal, Material crossSectionMaterial = null)
    {
        // slice the provided object using the transforms of this object
        return obj.Slice(StartPosition, Normal, crossSectionMaterial);
    }

在Slicer类中有这么一个方法

public static SlicedHull Slice(Mesh sharedMesh, Plane pl, TextureRegion region, int crossIndex)

此处将所有的Mesh分为一个个三角面,让每个三角面和入口传入的这个‘片’进行判断是否在正面、侧面、还是相交。相对的,如果两个面有相交,则需要把交点求出。

此处就代码可以进行优化,在制作过程中,原作者并没有把刚刚好共线的线添加到相交的类型里面,导致如果我们切割的时候恰好是沿着这个模型某一条线段进行切割,就会导致缺少这个刚刚好平行的线段,也就是少点了,就无法补足侧面,所以我做了一下的更新。这样就可以把刚刚好是在平面上或者是相交的线段加入到所有相交的点数组中。

                    if (side == SideOfPlane.UP || side == SideOfPlane.ON)
                        {
                            mesh.upperHull.Add(newTri);

                            if (sa == SideOfPlane.ON && sa == sb)
                            //如果刚刚好在平面上,直接将线段当作交点加进去
                            {
                                result.AddIntersectionPoint(verts[i0]);
                                result.AddIntersectionPoint(verts[i1]);
                            }
                            else if (sa == SideOfPlane.ON && sa == sc)
                            {
                                result.AddIntersectionPoint(verts[i0]);
                                result.AddIntersectionPoint(verts[i2]);
                            }
                            else if (sb == SideOfPlane.ON && sb == sc)
                            {
                                result.AddIntersectionPoint(verts[i1]);
                                result.AddIntersectionPoint(verts[i2]);
                            }
                            int interHullCount = result.intersectionPointCount;
                            for (int i = 0; i < interHullCount; i++)
                            {
                                var n = result.intersectionPoints[i];
                                n.i = index + startIndex;
                                crossHull.Add(n);
                            }
                        }

好了,此处我们将所有相交的点已经加入,但是在Triangulator这个类中。原作者使用的是凸包算法,也就是在空间的游离点中,寻找所有最外围的点,把他们围成新的Mesh。但是如果我们的模型是具有凹字型结构,就无法适用这套算法,所以我们采用的是有向连通图的算法,通过线段和线段,最近点和点进行合并的算法。达成连接一个空间中游离点的最大环

while (testmapped.Count > 1)
            {
                Mapped2D mpnext = testmapped.Find(m => m.index == currentmp.index);
                newmapped.Add(mpnext);
                testmapped.Remove(mpnext);
                float minDistance = float.MaxValue;
                Mapped2D mpnear = testmapped[0];
                testmapped.ForEach(m =>
                {
                    float distance = Vector2.Distance(m.mappedValue, mpnext.mappedValue);
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                        mpnear = m;
                    }
                });
                testmapped.Remove(mpnear);
                currentmp = mpnear;
            }

这些点就自然而然的连起来了,再用上平面三角面的构造函数,构造出来侧面的Mesh,这样就大功告成了!

这是结果

 以后我还会分享一些在工作中遇到的困难和解决思路~希望各位大佬海涵

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
二维TE波ADI-FDTD方法是一种数值求解电磁波动方程的方法,紧差分格式是指在数值离散化时使用更加准确的差分方法,从而提高数值计算的精度。本文介绍如何用matlab实现二维TE波ADI-FDTD方法。 首先,我们需要定义一些物理参数和计算参数,如介电常数、磁导率、时间步长、空间步长等,具体值根据实际情况调整。 ```matlab % 物理参数 epsilon0 = 8.854187817e-12; % 真空介电常数 mu0 = pi * 4e-7; % 真空磁导率 epsilon = 4; % 介电常数 mu = 1; % 磁导率 % 计算参数 dx = 0.01; % 空间步长 dy = 0.01; dt = dx / (2e8 * sqrt(1 / (dx^2) + 1 / (dy^2))); % 时间步长 ``` 然后,我们需要初始化场变量,包括电场和磁场,以及在时间步进过程中需要用到的中间变量。这里我们使用矩阵来表示电场和磁场。 ```matlab % 初始化场变量 nx = 100; % x方向网格数 ny = 100; % y方向网格数 ez = zeros(nx, ny); % z方向电场 hx = zeros(nx, ny); % x方向磁场 hy = zeros(nx, ny); % y方向磁场 ezx = zeros(nx, ny); % x方向电场中间变量 ezy = zeros(nx, ny); % y方向电场中间变量 hxx = zeros(nx, ny); % x方向磁场中间变量 hyy = zeros(nx, ny); % y方向磁场中间变量 ``` 接下来,我们需要实现ADI-FDTD算法,这里使用两个循环来分别处理x方向和y方向的场变量更新。 ```matlab % ADI-FDTD算法 for n = 1:100 % 时间步数 % 更新x方向电场和磁场 for i = 2:nx-1 for j = 2:ny-1 ezx(i, j) = ezx(i, j) + (dt / epsilon) * (hy(i, j) - hy(i-1, j)) / dx; end end for i = 2:nx-1 for j = 2:ny-1 ezy(i, j) = ezy(i, j) + (dt / epsilon) * (hx(i, j-1) - hx(i, j)) / dy; ez(i, j) = ezx(i, j) + ezy(i, j); end end for i = 1:nx-1 for j = 1:ny-1 hxx(i, j) = hxx(i, j) + (dt / mu) * (ez(i, j) - ez(i, j+1)) / dy; end end for i = 1:nx-1 for j = 1:ny-1 hyy(i, j) = hyy(i, j) + (dt / mu) * (ez(i+1, j) - ez(i, j)) / dx; hx(i, j) = hxx(i, j); hy(i, j) = hyy(i, j); end end end ``` 最后,我们可以绘制电场和磁场的分布图。 ```matlab % 绘图 figure; subplot(2, 1, 1); imagesc(ez'); title('Electric Field (V/m)'); xlabel('X (m)'); ylabel('Y (m)'); colorbar; subplot(2, 1, 2); imagesc(sqrt(hx'.^2 + hy'.^2)); title('Magnetic Field (A/m)'); xlabel('X (m)'); ylabel('Y (m)'); colorbar; ``` 这样,我们就完成了二维TE波ADI-FDTD方法的matlab实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值