Unity3d使用crossSection进行剖面视图

 

注:需要用到crossSection插件。

1.新建一个场景,创建一个空物体,名为Target。
2.在Target下创建要剖开的物体,这里创建一个圆柱体和一个球,位置错开一点,都在原点附件。
3.在Target上增加CrossSectionObjectSetup、Test组件(代码见后面)。
4.在Target上添加Box Collider组件,将子实体全部包入碰撞器内
5.创建滑条组件Slider,将Slider拖入Test组件的slider变量上。

代码一:滑动滑条就可以看到剖面视图了,也可以点击断面移动

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
 
[RequireComponent(typeof(CrossSectionObjectSetup))]
public class Test : MonoBehaviour
{
    CrossSectionObjectSetup cs_setup;
    public Slider slider;
 
    public enum ConstrainedAxis { X, Y, Z };
    public ConstrainedAxis selectedAxis = ConstrainedAxis.X;
 
    private GameObject rectGizmo;
    private Vector3 sectionplane = Vector3.up;
    private Vector3 zeroAlignmentVector = Vector3.zero;
 
    private float sectionX = 0;
    private float sectionY = 10;
    private float sectionZ = 0;
 
    void Awake()
    {
        cs_setup = gameObject.GetComponent<CrossSectionObjectSetup>();
    }
 
    void Start()
    {
        if (slider) slider.onValueChanged.AddListener(SliderListener);
        Shader.DisableKeyword("CLIP_TWO_PLANES");
        Shader.EnableKeyword("CLIP_PLANE");
 
        switch (selectedAxis)
        {
            case ConstrainedAxis.X:
                sectionplane = Vector3.right;
                break;
            case ConstrainedAxis.Y:
                sectionplane = Vector3.up;
                break;
            case ConstrainedAxis.Z:
                sectionplane = Vector3.forward;
                break;
            default:
                Debug.Log("case default");
                break;
        }
 
        Shader.SetGlobalVector("_SectionPlane", sectionplane);
 
        zeroAlignmentVector = new Vector3(0, 1, 0);
 
        InitGizmo();
        UpdateSection();
    }
 
    public void SliderListener(float value)
    {
        switch (selectedAxis)
        {
            case ConstrainedAxis.X:
                sectionX = value + zeroAlignmentVector.x;
                if (rectGizmo) rectGizmo.transform.position = new Vector3(sectionX, cs_setup.bounds.center.y, cs_setup.bounds.center.z);
                break;
            case ConstrainedAxis.Y:
                sectionY = value + zeroAlignmentVector.y;
                if (rectGizmo) rectGizmo.transform.position = new Vector3(cs_setup.bounds.center.x, sectionY, cs_setup.bounds.center.z);
                break;
            case ConstrainedAxis.Z:
                sectionZ = value + zeroAlignmentVector.z;
                if (rectGizmo) rectGizmo.transform.position = new Vector3(cs_setup.bounds.center.x, cs_setup.bounds.center.y, sectionZ);
                break;
        }
        Shader.SetGlobalVector("_SectionPoint", new Vector3(sectionX, sectionY, sectionZ));
    }
 
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (EventSystem.current.IsPointerOverGameObject()) return;
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            Collider coll = gameObject.GetComponent<Collider>();
            if (coll.Raycast(ray, out hit, 10000f))
            {
                StartCoroutine(dragGizmo());
            }
        }
    }
 
    IEnumerator dragGizmo()
    {
        //基本思路:将鼠标在屏幕上的移动距离换算为空间距离,再分别投影到X\Y\Z轴
 
        //空间距离
        float cameraDistance = Vector3.Distance(cs_setup.bounds.center, Camera.main.transform.position);
 
        //记录初始化位置
        Vector3 startPoint = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, cameraDistance));
        Vector3 startPos = rectGizmo.transform.position;
 
        Vector3 translation = Vector3.zero;
        //Camera.main.GetComponent<maxCamera>().enabled = false;
 
        if (slider) slider.onValueChanged.RemoveListener(SliderListener);
 
        while (Input.GetMouseButton(0))
        {
            //换算移动距离
            translation = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, cameraDistance)) - startPoint;
 
            //分别投影到X\Y\Z轴
            Vector3 projectedTranslation = Vector3.Project(translation, sectionplane);
 
            Vector3 newPoint = startPos + projectedTranslation;
            switch (selectedAxis)
            {
                case ConstrainedAxis.X:
                    if (newPoint.x > cs_setup.bounds.max.x) sectionX = cs_setup.bounds.max.x;
                    else if (newPoint.x < cs_setup.bounds.min.x) sectionX = cs_setup.bounds.min.x;
                    else sectionX = newPoint.x;
                    break;
                case ConstrainedAxis.Y:
                    if (newPoint.y > cs_setup.bounds.max.y) sectionY = cs_setup.bounds.max.y;
                    else if (newPoint.y < cs_setup.bounds.min.y) sectionY = cs_setup.bounds.min.y;
                    else sectionY = newPoint.y;
                    break;
                case ConstrainedAxis.Z:
                    if (newPoint.z > cs_setup.bounds.max.z) sectionZ = cs_setup.bounds.max.z;
                    else if (newPoint.z < cs_setup.bounds.min.z) sectionZ = cs_setup.bounds.min.z;
                    else sectionZ = newPoint.z;
                    break;
            }
            UpdateSection();
            yield return null;
        }
        //Camera.main.GetComponent<maxCamera>().enabled = true;
        if (slider)
            slider.onValueChanged.AddListener(SliderListener);
    }
 
    //刷新断面位置
    void UpdateSection()
    {
        Vector3 sectionpoint = new Vector3(sectionX, sectionY, sectionZ);
 
        Shader.SetGlobalVector("_SectionPoint", sectionpoint);
        if (rectGizmo)
            rectGizmo.transform.position = new Vector3(cs_setup.bounds.center.x, sectionY, cs_setup.bounds.center.z);
 
        //更新进度条
        switch (selectedAxis)
        {
            case ConstrainedAxis.X:
                slider.value = sectionX;
                break;
            case ConstrainedAxis.Y:
                slider.value = sectionY;
                break;
            case ConstrainedAxis.Z:
                slider.value = sectionZ;
                break;
            default:
                Debug.Log("case default");
                break;
        }
        
    }
 
    //初始化示意框
    void InitGizmo()
    {        
        rectGizmo = Resources.Load("rectGizmo") as GameObject;
        rectGizmo = Instantiate(rectGizmo, cs_setup.bounds.center + (-cs_setup.bounds.extents.y + (slider ? slider.value : 0) + zeroAlignmentVector.y) * transform.up, Quaternion.identity) as GameObject;
        RectGizmo rg = rectGizmo.GetComponent<RectGizmo>();
        rg.SetSizedGizmo(cs_setup.bounds.size, selectedAxis);
    }
}
代码二:只能滑动滑条查看剖面视图

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.EventSystems;
 
public class Planar_xyzClippingSection : MonoBehaviour
{
    public Slider slider;    
    public enum ConstrainedAxis { X, Y, Z };
 
    void Awake()
    {
        Shader.EnableKeyword("CLIP_PLANE");
    }
 
    void Start () {    
        if (slider)
            slider.onValueChanged.AddListener(SliderListener);
    }
 
    public void SliderListener(float value)
    {        
        Shader.SetGlobalVector("_SectionPoint", new Vector3(value, 0, 0));
        Shader.SetGlobalVector("_SectionPlane", Vector3.right);
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值