国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Unity 3D繩索】基于圖形渲染的3D繩索模擬

這篇具有很好參考價值的文章主要介紹了【Unity 3D繩索】基于圖形渲染的3D繩索模擬。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

? ? ? ? 前一段被要求模擬一根繩索,因為種種原因,筆者最后決定通過數(shù)學函數(shù)和Mesh模擬出一根繩索,具體的思路是首先利用Verlet函數(shù)模擬繩索的剛性,之后利用Mesh渲染圓柱體將繩索模擬出來。

????????player.instance.transform.position,圖形渲染,unity,游戲引擎

? ? ? ? 首先,利用Verlet進行邏輯上的繩索創(chuàng)建,具體思路參考了這篇文章:

在Unity使用Verlet積分實現(xiàn)逼真的繩索 - 知乎

? ? ? ? 不過這篇文章的作者是利用LineRenderer模擬的2D繩索,簡單來講就是將繩子看成許多節(jié),每個節(jié)點都包含兩個端點,端點會產(chǎn)生一個力來約束繩索,有了這些基礎就可以模擬繩子的物理特性了。

player.instance.transform.position,圖形渲染,unity,游戲引擎

/// <summary>
/// Verlet最小節(jié)點
/// </summary>
public class Particle
{
    public Vector3 position;
    public Vector3 oldPosition;
    public bool locked;
}

/// <summary>
/// 抓鉤段長
/// </summary>

public class Stick
{
    public Particle particleA;
    public Particle particleB;
    public float length;

    public Stick(Particle a, Particle b)
    {
        particleA = a;
        particleB = b;
        length = (a.position - b.position).magnitude;
    }
}

? ? ? ? 而因為需要建立在三維空間中,所以不采用LineRenderer,而是直接用一組Vector3來代表這些繩子的節(jié)點,在邏輯上將繩子模擬出來,以待后續(xù)的渲染。

public class Hook : MonoBehaviour
{
    [Header("節(jié)點數(shù)")]
    [Range(30, 100)]
    public float points = 80;
    [Header("半徑")]
    public float lineRadius = 0.02f;
    [Header("重力")]
    [SerializeField] public float gravity = 1f;
    [Header("作用力")]
    [SerializeField] public int stiffness = 200;

    [SerializeField] private bool startPointLock; //鎖定節(jié)點
    [SerializeField] private bool endPointLock;
    [SerializeField] private bool isfollow; //起始點隨父物體移動

    private Vector3 _startPosition; //開始位置
    private Vector3 _endPosition; //結束位置

    public Material _material;
    private List<Vector3> _vector3s = new List<Vector3>();     //抓鉤信息存儲列表
    private List<Particle> _particles = new List<Particle>();
    private List<Stick> _sticks = new List<Stick>();
    private Dictionary<int, UnityEngine.Mesh> _meshMap = new Dictionary<int, UnityEngine.Mesh>();

    private bool _isExist = false; //是否已存在抓鉤
    private int _index = 0; //抓鉤節(jié)點計數(shù)

    /// <summary>
    /// 初始化
    /// </summary>
    public void Init(Vector3 startV3, Vector3 endV3)
    {
        _startPosition = startV3;
        _endPosition = endV3;
        Initialization();
        SetParticlesLockSet();
        _isExist = true;
    }

    private void FixedUpdate()
    {
        Simulation();
    }

    /// <summary>
    /// 抓鉤節(jié)點設置
    /// </summary>
    private void Initialization()
    {
        _vector3s.Clear();
        _particles.Clear();
        _sticks.Clear();
        _meshMap.Clear();
        for (int i = 0; i <= points; i++)
        {
            float t = i / points;
            _vector3s.Add(Vector3.Lerp(_startPosition, _endPosition, t));
        }
        for (int i = 0; i < _vector3s.Count; i++)
        {
            _particles.Add(new Particle() { position = _vector3s[i], oldPosition = _vector3s[i] });
        }
        for (int i = 0; i < _particles.Count - 1; i++)
        {
            _sticks.Add(new Stick(_particles[i], _particles[i + 1]));
        }
    }

    /// <summary>
    /// 抓鉤節(jié)點鎖定設置
    /// </summary>
    private void SetParticlesLockSet()
    {
        if (startPointLock)
        {
            _particles[0].locked = true;
        }
        if (endPointLock)
        {
            _particles[_particles.Count - 1].locked = true;
        }
        if (isfollow)
        {
            _particles[0].locked = true;
        }
    }

    /// <summary>
    /// 抓鉤特性賦值
    /// </summary>
    private void Simulation()
    {
        //遍歷
        for (int i = 0; i < _particles.Count; i++)
        {
            Particle p = _particles[i];
            if (p.locked == false)
            {
                Vector3 temp = p.position;
                //Verlet積分
                p.position = p.position + (p.position - p.oldPosition) + Time.fixedDeltaTime * Time.fixedDeltaTime * new Vector3(0, -gravity, 0);
                p.oldPosition = temp;
            }
        }

        //迭代次數(shù),控制剛性
        for (int i = 0; i < stiffness; i++)
        {
            for (int j = 0; j < _sticks.Count; j++)
            {
                Stick stick = _sticks[j];

                Vector3 delta = stick.particleB.position - stick.particleA.position;
                float deltaLength = delta.magnitude;
                float diff = (deltaLength - stick.length) / deltaLength;
                if (stick.particleA.locked == false)
                    stick.particleA.position += 0.5f * diff * delta;
                if (stick.particleB.locked == false)
                    stick.particleB.position -= 0.5f * diff * delta;
            }
        }

        if (isfollow && _particles.Count > 0)
        {
            _particles[0].position = Player.instance.transform.position;
        }
    }
}

????????接下來便是考慮如何渲染3D的繩索了,最優(yōu)的方案如下,利用所得節(jié)點渲染不平行的柱體,這是以下這篇Unreal的繩索文檔思路,不過這個文章并沒有提供源碼,所有筆者準備改一種更簡單的方法。

https://docs.unrealengine.com/4.27/en-US/Basics/Components/CableComponent/

player.instance.transform.position,圖形渲染,unity,游戲引擎

? ? ? ??將兩個節(jié)點之間渲染成不平行圓柱體實現(xiàn)起來比較麻煩,而渲染成平行的就簡單很多了,但隨之面臨的問題是不平行的圓柱體之間會有縫隙在繩索彎曲的時候,但利用積分的思想,假設繩子上的節(jié)點越多,那么繩子間的縫隙影響就會越小,當節(jié)點夠多時 (目前嘗試的,其實50-80個的時候基本就看不到了,前提時繩子不要太粗),就看不到縫隙了。

player.instance.transform.position,圖形渲染,unity,游戲引擎

? ? ? ? 所以說,接下來只要對各個節(jié)點進行圓柱體繪制就行了:

    private void LateUpdate()
    {
        if (_isExist)
        {
            StartCoroutine(HookRendering(true));
        }
        Rendering();
    }
    
    /// <summary>
    /// 繪制抓鉤
    /// </summary>
    private void Rendering()
    {
        for (int i = 0; i < _index; i++)
        {
            DrawCylinder(_particles[i].position, _particles[i + 1].position);
        }
    }

    /// <summary>
    /// 繪制抓鉤攜程,true為延伸,false為收縮
    /// </summary>
    /// <param name="isExtend"></param>
    /// <returns></returns>
    IEnumerator HookRendering(bool isExtend)
    {
        endPointLock = isExtend;
        _isExist = false;
        if (isExtend)
        {
            while (_index < _particles.Count - 1)
            {
                _index++;
                yield return new WaitForSeconds(0.01f);
            }
            //Player.instance.MoveControl(_endPosition, true);
            //StartCoroutine(HookRendering(false));
        }
        else
        {
            while (_index > 0)
            {
                _index--;
                yield return new WaitForSeconds(0.01f);
            }
        }
    }    
    /// <summary>
    /// Mesh繪制
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    private void DrawCylinder(Vector3 a, Vector3 b)
    {
        if (isNaN(a) || isNaN(b)) { return; }

        float length = (a - b).magnitude;

        if ((a - b).magnitude > 0.001f)
        {
            Graphics.DrawMesh(GetCylinderMesh(length),
                              Matrix4x4.TRS(a,
                                            Quaternion.LookRotation(b - a),
                                            new Vector3(transform.lossyScale.x, transform.lossyScale.x, 1)),
                              _material,
                              gameObject.layer,
                              null, 0, null, true);
        }
    }

    /// <summary>
    /// Mesh獲取
    /// </summary>
    /// <param name="length"></param>
    /// <returns></returns>
    private UnityEngine.Mesh GetCylinderMesh(float length)
    {
        const float CYLINDER_MESH_RESOLUTION = 0.1f;
        int lengthKey = Mathf.RoundToInt(length * 100 / CYLINDER_MESH_RESOLUTION);

        UnityEngine.Mesh mesh;
        if (_meshMap.TryGetValue(lengthKey, out mesh))
        {
            return mesh;
        }

        mesh = new UnityEngine.Mesh();
        mesh.hideFlags = HideFlags.DontSave;

        List<Vector3> verts = new List<Vector3>();
        List<Color> colors = new List<Color>();
        List<int> tris = new List<int>();

        Vector3 p0 = Vector3.zero;
        Vector3 p1 = Vector3.forward * length;
        int _cylinderResolution = 12;
        float _cylinderRadius = lineRadius;
        for (int i = 0; i < _cylinderResolution; i++)
        {
            float angle = (Mathf.PI * 2.0f * i) / _cylinderResolution;
            float dx = _cylinderRadius * Mathf.Cos(angle);
            float dy = _cylinderRadius * Mathf.Sin(angle);

            Vector3 spoke = new Vector3(dx, dy, 0);

            verts.Add(p0 + spoke);
            verts.Add(p1 + spoke);

            colors.Add(Color.white);
            colors.Add(Color.white);

            int triStart = verts.Count;
            int triCap = _cylinderResolution * 2;

            tris.Add((triStart + 0) % triCap);
            tris.Add((triStart + 2) % triCap);
            tris.Add((triStart + 1) % triCap);

            tris.Add((triStart + 2) % triCap);
            tris.Add((triStart + 3) % triCap);
            tris.Add((triStart + 1) % triCap);
        }

        mesh.SetVertices(verts);
        mesh.SetIndices(tris.ToArray(), MeshTopology.Triangles, 0);
        mesh.RecalculateBounds();
        mesh.RecalculateNormals();
        mesh.UploadMeshData(true);

        _meshMap[lengthKey] = mesh;

        return mesh;
    }
    private bool isNaN(Vector3 v)
    {
        return float.IsNaN(v.x) || float.IsNaN(v.y) || float.IsNaN(v.z);
    }

最后,如果這篇文章幫助到你,麻煩點個贊吧。文章來源地址http://www.zghlxwxcb.cn/news/detail-861582.html

到了這里,關于【Unity 3D繩索】基于圖形渲染的3D繩索模擬的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Unity3D中實現(xiàn)Player的第一人稱視角

    Unity3D中實現(xiàn)Player的第一人稱視角

    效果,上面為Scene場景,下面為Game場景 0創(chuàng)建地形,當然可以先簡單的創(chuàng)建一個空白的Terrain。這里我已經(jīng)對地形進行了初步的編輯和渲染。 1.在Hierarchy視圖中右鍵創(chuàng)建一個膠囊體(Capsule)作為Player,添加好后重置膠囊體的位置,并且調(diào)整膠囊體在一個合適的位置。 ?2.將Main

    2023年04月08日
    瀏覽(30)
  • Unity3d_Rewired官方文檔翻譯:概念(一):InputManager、Players、Actions

    Unity3d_Rewired官方文檔翻譯:概念(一):InputManager、Players、Actions

    僅翻譯了官方文檔中的Essentials(要點)、Concepts(概念)兩部分,這是文檔中最重要的部分,理解了這兩部分的內(nèi)容應該足以讓你將Rewired運用到你的項目中,之后再去閱讀文檔的其他部分也能更容易理解。 斜體加下劃線部分為添加的注解,非官方文檔內(nèi)容。若你發(fā)現(xiàn)有翻譯

    2024年02月02日
    瀏覽(45)
  • 計算機視覺與圖形學-神經(jīng)渲染專題-pi-GAN and CIPS-3D

    計算機視覺與圖形學-神經(jīng)渲染專題-pi-GAN and CIPS-3D

    《pi-GAN: Periodic Implicit Generative Adversarial Networks for 3D-Aware Image Synthesis 》 摘要 我們見證了3D感知圖像合成的快速進展,利用了生成視覺模型和神經(jīng)渲染的最新進展。然而,現(xiàn)有的方法在兩方面存在不足:首先,它們可能缺乏底層的3D表示,或者依賴于視圖不一致的渲染,從而合

    2024年02月14日
    瀏覽(26)
  • Unity GPU Instancing合批_如何基于單個的實體修改材質(zhì)參數(shù)

    Unity GPU Instancing合批_如何基于單個的實體修改材質(zhì)參數(shù)

    最近在做DOTS的教程,由于DOTS(版本1.0.16)目前不支持角色的骨骼動畫,我們是將角色的所有動畫數(shù)據(jù)Baker到一個紋理里面,通過修改材質(zhì)中的參數(shù)AnimBegin,AnimEnd來決定動畫播放的起點和終點,材質(zhì)參數(shù)AnimTime記錄當前過去的動畫時間。但是在做大規(guī)模戰(zhàn)斗控制的時候,有10000+的小

    2024年01月21日
    瀏覽(24)
  • Unity繩子插件QuickRopes使用方法(讓你快速創(chuàng)建你想要的繩索效果)

    Unity繩子插件QuickRopes使用方法(讓你快速創(chuàng)建你想要的繩索效果)

    QuickRope插件介紹 從插件的名字就可以知道,QuickRope,使用此插件可以讓開發(fā)者快速創(chuàng)建繩子、鎖鏈等鏈條的工具,并可以模擬這些繩子的物理屬性,自動生成繩子,可以編輯繩子屬性,創(chuàng)建一條你想要的繩子。 插件demo演示說明 demo1:Edit Rope Renderer 點擊左側列表按鈕即可看到

    2023年04月08日
    瀏覽(32)
  • 【Unity3D】線段渲染器LineRenderer

    【Unity3D】線段渲染器LineRenderer

    1 LineRenderer 簡介 ????????LineRenderer 組件用于繪制線段,可以調(diào)整線段條數(shù)、端點坐標、顏色、寬度等屬性,其屬性面板如下: Materials :線段材質(zhì),最好設置為 Default-Line; Positions-Size :線段端點個數(shù); Positions-Element :線段端點值; Width :線段寬度,可以是不等寬的;

    2023年04月08日
    瀏覽(14)
  • Unity 之 Material (材質(zhì))渲染3D對象的重要組件

    Unity 之 Material (材質(zhì))渲染3D對象的重要組件

    在Unity中,Material(材質(zhì))是一種用于渲染3D對象的重要組件。Material定義了對象的外觀,包括其顏色、紋理、光照屬性和反射等。以下是關于Material的詳細介紹: 創(chuàng)建Material : 要創(chuàng)建一個Material,通常需要一個著色器(Shader)以及一個或多個紋理。您可以通過以下步驟來創(chuàng)建

    2024年02月08日
    瀏覽(19)
  • Unity3D學習記錄01:URP渲染管線以及3D游戲場景設置

    Unity3D學習記錄01:URP渲染管線以及3D游戲場景設置

    以下內(nèi)容所使用的版本均為Unity2022.3 先在 Window-Package Manager-Unity Registry 里面搜索添加Universal RP ? Unity中,創(chuàng)建渲染管線的方式為Asset文件夾下右鍵 Create-Readering-URP Asset(with Universal Asset) 會創(chuàng)建以下兩個Pipeline: ?接著在圖中的設置里添加這兩個渲染管線(Project Setting在Edit窗口下

    2024年02月08日
    瀏覽(102)
  • 計算機視覺與圖形學-神經(jīng)渲染專題-第一個基于NeRF的自動駕駛仿真平臺

    計算機視覺與圖形學-神經(jīng)渲染專題-第一個基于NeRF的自動駕駛仿真平臺

    如今,自動駕駛汽車可以在普通情況下平穩(wěn)行駛,人們普遍認識到,真實的 傳感器模擬將在通過模擬解決剩余的極端情況方面發(fā)揮關鍵作用 。為此,我們提出了一種基于神經(jīng)輻射場(NeRF)的自動駕駛模擬器。與現(xiàn)有作品相比,我們的作品具有三個顯著特點:(1) 實例感知

    2024年02月12日
    瀏覽(23)
  • 控制renderQueue解決NGUI與Unity3D物體渲染順序問題

    NGUI與Unity3D物體渲染順序問題,做過UI的各位應該都遇到過。主要指的是UI與Unity制作的特效、3D人物等一同顯示時的層次問題。 由于UI與特效等都是以transparent方式渲染,而Unity與NGUI在管理同是透明物體的render queue時實際上互相沒有感知,于是引出排序問題?,F(xiàn)在介紹以render

    2024年02月13日
    瀏覽(27)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包