首页 > 编程语言 >3D小算法

3D小算法

时间:2024-02-22 14:33:20浏览次数:30  
标签:Normalize double Vector3 算法 arg var viewport 3D

向量投影

/// <summary>
/// 计算空间向量在平面上的投影
/// </summary>
/// <param name="o">原点</param>
/// <param name="end">终点</param>
/// <param name="unit">投影平面的法向量</param>
/// <returns></returns>
static Vector3 CreateProjection(Vector3 o, Vector3 end, Vector3 unit)
{
    unit = unit.Normalized();
    Vector3 v = end-o;
    var dotv = Vector3.Dot(v, unit);
    var b = dotv * unit;
    var retv = (v - b).Normalized();

    return retv;
}

两个向量角度

static double GetTowNormalAngle(Vector3 v1, Vector3 v2)
{
    v1.Normalize();
    v2.Normalize();
    var angle = v1.AngleBetween(v2) * 180 / Math.PI;    
    return angle;
}

两个向量投影角度

static double GetAngle(Vector3 v, Vector3 unitV, Vector3 unitN)
{
    v.Normalize();
    unitV.Normalize();
    unitN.Normalize();
    var dotv = Vector3.Dot(v, unitN);
    var b = Vector3D.Multiply(dotv, unitN.ToVector3D()).ToVector3();
    var retV = v - b;
    var angle = retV.AngleBetween(unitV) * 180 / Math.PI;
    return angle;
}

模型旋转移动

private void LeftMouse3DDown(object sender, RoutedEventArgs e)
{
    if (e is Mouse3DEventArgs arg)
    {
        viewport = arg.Viewport;
        Camera = viewport.Camera;
        startPoint = arg.Position;//roate
        startHitPoint = arg.HitTestResult.PointHit;//move
        isCaptured = true;
        arg.Handled = true;
        var model = sender as MeshGeometryModel3D;
        if (model != null && model.Material is DiffuseMaterial)
        {
            model.Material = DiffuseMaterials.Yellow;
        }
    }
}

private void LeftMouse3DUp(object sender, RoutedEventArgs e)
{
    var model = sender as MeshGeometryModel3D;
    if (isCaptured && e is Mouse3DEventArgs arg && model != null && model.Material is DiffuseMaterial)
    {
        model.Material = DiffuseMaterials.Red;
        arg.Handled = true;
    }
    isCaptured = false;
    viewport = null;
}


private void LeftMouse3DMove(object sender, RoutedEventArgs e)
{
    if (isCaptured && e is Mouse3DEventArgs arg && arg.Viewport == viewport)
    {
        var mouse = arg.OriginalInputEventArgs as MouseEventArgs;
        if (mouse == null)
            return;
        if (mouse.LeftButton == MouseButtonState.Pressed )
        {
            var newHit = viewport.UnProjectOnPlane(arg.Position, startHitPoint.ToPoint3D(), Camera.LookDirection);
            if (newHit.HasValue)
            {
                var newPos = newHit.Value.ToVector3();
                //newPos = new Vector3(newPos.X, startHitPoint.Y, newPos.Z); // trying to constraint elevation
                var offset = newPos - startHitPoint;
                startHitPoint = newPos;
                currentTranslation.TranslationVector += offset;
                UpdateTransform();
            }
        }
        else
        {
            RotateTrackball(startPoint, arg.Position, currentTranslation.TranslationVector);
            startPoint = arg.Position;
        }
        arg.Handled = true;
    }
}

private static Vector3 ProjectToTrackball(System.Windows.Point point, double w, double h)
{
    // Use the diagonal for scaling, making sure that the whole client area is inside the trackball
    double r = Math.Sqrt((w * w) + (h * h)) / 2;
    double x = (point.X - (w / 2)) / r;
    double y = ((h / 2) - point.Y) / r;
    double z2 = 1 - (x * x) - (y * y);
    double z = z2 > 0 ? Math.Sqrt(z2) : 0;

    return new Vector3((float)x, (float)y, (float)z);
}

private void RotateTrackball(System.Windows.Point p1, System.Windows.Point p2, Vector3 rotateAround)
{
    Vector3 v1, v2;
    if (ConstrainAxis.HasValue)
    {
        // preparing to compute the ratio to the screen
        var diag = Math.Sqrt(
            viewport.ActualWidth * viewport.ActualWidth +
            viewport.ActualHeight * viewport.ActualHeight
            );

        // can we project the constraintAxis onto the view?
        var t3 = Vector3.TransformCoordinate(ConstrainAxis.Value, Camera.CameraInternal.GetViewMatrix());
        var dir = new Vector2(t3.X, t3.Y); // axis of Constraint in view coordinates

        var pp1 = p1.ToVector2(); // computing distance perpendicular to axis in view coordinates
        var r1 = pp1 - (pp1 * dir);

        var pp2 = p2.ToVector2(); // computing distance perpendicular to axis in view coordinates
        var r2 = pp2 - (pp2 * dir);

        var angle = (r2.Length() - r1.Length()) / diag * 4;

        currentRotation *= Matrix.RotationAxis(Vector3.Normalize(ConstrainAxis.Value), (float)(angle * this.RotationSensitivity * 5));
        UpdateTransform();
    }
    else
    {
        v1 = ProjectToTrackball(p1, viewport.ActualWidth, viewport.ActualHeight);
        v2 = ProjectToTrackball(p2, viewport.ActualWidth, viewport.ActualHeight);

        // transform the trackball coordinates to view space
        var viewZ = Camera.CameraInternal.LookDirection;
        var viewX = Vector3.Cross(Camera.CameraInternal.UpDirection, viewZ);
        var viewY = Vector3.Cross(viewX, viewZ);
        viewX.Normalize();
        viewY.Normalize();
        viewZ.Normalize();
        var u1 = (viewZ * v1.Z) + (viewX * v1.X) + (viewY * v1.Y);
        var u2 = (viewZ * v2.Z) + (viewX * v2.X) + (viewY * v2.Y);

        var axis = Vector3.Cross(u1, u2);
        if (axis.LengthSquared() < 1e-8)
        {
            return;
        }

        var angle = u1.AngleBetween(u2);

        currentRotation *= Matrix.RotationAxis(Vector3.Normalize(axis), (float)(angle * this.RotationSensitivity * 5));
        UpdateTransform();
    }

}

private void UpdateTransform()
{
    totalTransform = currentRotation * currentTranslation;
    foreach (var item in GroupCameraModel)
    {
        item.Transform = CameraModelTransform = new MatrixTransform3D(totalTransform.ToMatrix3D());
    }
    UpdateLight();
    UpdateCameraData();
}

标签:Normalize,double,Vector3,算法,arg,var,viewport,3D
From: https://www.cnblogs.com/CloakBlowing/p/18027236

相关文章

  • day39 动态规划part2 代码随想录算法训练营 63. 不同路径 II
    题目:63.不同路径II我的感悟:题目不难,就是不知道哪个煞笔,把路拦截死了,并且入口就放石头,我真是吐了。理解难点:初始值的遇到障碍要Break其他我写的没错边界考虑:还有入口和出口有障碍物的话,要直接返回0.听课笔记:差不多,考虑的点就是:初始值后面为break开头和结尾有障......
  • 代码随想录算法训练营第二十五天 | 17.电话号码的字母组合 , 216.组合总和III
    216.组合总和III 已解答中等 相关标签相关企业 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:只使用数字1到9每个数字 最多使用一次返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回......
  • 区间操作优化算法
    1.树状数组一般为求区间的和并统计某个特定值的数量,同时可以进行快速的在线更新。不算特别重要,简略带过。看例题点击查看代码#include<bits/stdc++.h>usingnamespacestd;constintN=300000;intn,c[N],s[N];structlmy{ intx,y;}site[N];intlowbit(intx){ r......
  • 代码随想录算法训练营day 1 | 704 二分查找 27 删除元素
    704二分查找数组基础数组空间地址连续、随机访问时间复杂度O(1)、删除和移动时间复杂度O(n)vector和array区别:vector底层实现为array;array是栈上开辟空间、vector是堆上开辟空间;array不支持迭代器访问,支持指针和索引、vector还支持迭代器访问二分查找适用场景有序数组、数组......
  • 算法复习
    省选前最后一周了,对照大纲过一遍,每个算法稍微写一点自己的理解与板子记忆技巧。感觉很多东西还是之前听别人讲的时候学的似懂非懂......导致现在看起来好像啥都会一点实际上好像啥也不会,每次越临近考试就会感觉整个人很虚无啊......反正不是很好受。数论exgcd【7】用于解决......
  • m基于码率兼容打孔LDPC码nms最小和译码算法的LDPC编译码matlab误码率仿真
    1.算法仿真效果matlab2022a仿真结果如下: 2.算法涉及理论知识概要       码率兼容打孔LDPC码BP译码算法是一种改进的LDPC译码算法,能够在不同码率下实现更好的译码性能。该算法通过在LDPC码中引入打孔操作,使得码率可以灵活地调整,同时利用BP(BeliefPropagation)译码算法......
  • day38 动态规划part1 代码随想录算法训练营 746. 使用最小花费爬楼梯
    题目:746.使用最小花费爬楼梯我的感悟:哈哈,我居然自己独立写出来了,确实,只要定义定清楚了,哪怕定的含义只有自己能看懂,只要定义一致就可以求出解决来!!!我真是个大天才!!理解难点:听课笔记:代码示例:classSolution:defminCostClimbingStairs(self,cost:List[int])->int:......
  • # 代码随想录算法训练营day01 | leetcode 704. 二分查找、35.搜索插入位置、34.在排序
    题目链接:704.二分查找-简单题目描述:给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。示例1:输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在nums中并且下标为4示......
  • KMP 算法和 TIRE 树
    1.KMP算法KMP算法,是判断一个字符串是否在一个字符串中出现过,能够快速匹配字符串在文本串中的有无,位置,次数,我们在匹配字符串中可以找到失配点,就可以不用从\(1\)重新查找,从某个特定点进行查找,大大减小了时间复杂度。考虑一组样例:字符串:abcdf文本串:abcdabcdef我们来将他匹......
  • 2024牛客寒假算法基础集训营5
    A.总数-1的个数#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e5+10;#defineinf0x3f3f3f3fvoidsolve(){intn;cin>>n;intans=0;for(inti=1,x;i<=n;i++){cin>>x;if(x==1)c......