CreateManager.cs 12.7 KB
using System.Collections;
using System;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class CreateManager : MonoBehaviour
{

    public ARRaycastManager raycastMgr;
    public ARPlane _ARPlane;
    public GameObject[] placeObject;
    public GameObject tempObject;
    GameObject spawnObject;
    private List<ARRaycastHit> hits = new List<ARRaycastHit>();
    public static bool isSetted = false;
    bool isActivated = false;

    public bool gameoverTimerActivate;

    /// <summary>
    /// Game Over Script here
    /// </summary>

    private float deadTime;
    public GameObject gOverPanel;


    [SerializeField]
    [Tooltip("The ARCameraManager which will produce frame events.")]
    ARCameraManager m_CameraManager;

    /// <summary>
    /// Get or set the <c>ARCameraManager</c>.
    /// </summary>
    public ARCameraManager cameraManager
    {
        get => m_CameraManager;
        set => m_CameraManager = value;
    }

    [SerializeField]
    RawImage m_RawCameraImage;

    /// <summary>
    /// The UI RawImage used to display the image on screen.
    /// </summary>
    public RawImage rawCameraImage
    {
        get => m_RawCameraImage;
        set => m_RawCameraImage = value;
    }

    [SerializeField]
    [Tooltip("The AROcclusionManager which will produce human depth and stencil textures.")]
    AROcclusionManager m_OcclusionManager;

    public AROcclusionManager occlusionManager
    {
        get => m_OcclusionManager;
        set => m_OcclusionManager = value;
    }

    [SerializeField]
    RawImage m_RawHumanDepthImage;

    /// <summary>
    /// The UI RawImage used to display the image on screen.
    /// </summary>
    public RawImage rawHumanDepthImage
    {
        get => m_RawHumanDepthImage;
        set => m_RawHumanDepthImage = value;
    }

    [SerializeField]
    RawImage m_RawHumanStencilImage;

    /// <summary>
    /// The UI RawImage used to display the image on screen.
    /// </summary>
    public RawImage rawHumanStencilImage
    {
        get => m_RawHumanStencilImage;
        set => m_RawHumanStencilImage = value;
    }

    [SerializeField]
    RawImage m_RawEnvironmentDepthImage;

    /// <summary>
    /// The UI RawImage used to display the image on screen.
    /// </summary>
    public RawImage rawEnvironmentDepthImage
    {
        get => m_RawEnvironmentDepthImage;
        set => m_RawEnvironmentDepthImage = value;
    }

    [SerializeField]
    RawImage m_RawEnvironmentDepthConfidenceImage;

    /// <summary>
    /// The UI RawImage used to display the image on screen.
    /// </summary>
    public RawImage rawEnvironmentDepthConfidenceImage
    {
        get => m_RawEnvironmentDepthConfidenceImage;
        set => m_RawEnvironmentDepthConfidenceImage = value;
    }

    [SerializeField]
    Text m_ImageInfo;
    public Text m_ImageInfo2;
    public Text m_ImageInfo3;

    /// <summary>
    /// The UI Text used to display information about the image on screen.
    /// </summary>
    public Text imageInfo
    {
        get => m_ImageInfo;
        set => m_ImageInfo = value;
    }

    public Text imageInfo2
    {
        get => m_ImageInfo2;
        set => m_ImageInfo2 = value;
    }

    void OnEnable()
    {
        if (m_CameraManager != null)
        {
            m_CameraManager.frameReceived += OnCameraFrameReceived;
        }
    }

    void OnDisable()
    {
        if (m_CameraManager != null)
        {
            m_CameraManager.frameReceived -= OnCameraFrameReceived;
        }
    }

    unsafe void UpdateCameraImage()
    {
        // Attempt to get the latest camera image. If this method succeeds,
        // it acquires a native resource that must be disposed (see below).
        if (!cameraManager.TryAcquireLatestCpuImage(out XRCpuImage image))
        {
            return;
        }

        // Display some information about the camera image
        Vector3 screenCenter2 = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
        m_ImageInfo.text = string.Format(
            "Image info:\n\twidth: {0}\n\theight: {1}\n\tplaneCount: {2}\n\ttimestamp: {3}\n\tformat: {4} \n\tcenterPosx: {5} \n\tcenterPosx: {6}",
            image.width, image.height, image.planeCount, image.timestamp, image.format, screenCenter2.x, screenCenter2.y);

        // Once we have a valid XRCpuImage, we can access the individual image "planes"
        // (the separate channels in the image). XRCpuImage.GetPlane provides
        // low-overhead access to this data. This could then be passed to a
        // computer vision algorithm. Here, we will convert the camera image
        // to an RGBA texture and draw it on the screen.

        // Choose an RGBA format.
        // See XRCpuImage.FormatSupported for a complete list of supported formats.
        var format = TextureFormat.RGBA32;

        if (m_CameraTexture == null || m_CameraTexture.width != image.width || m_CameraTexture.height != image.height)
        {
            m_CameraTexture = new Texture2D(image.width, image.height, format, false);
        }

        // Convert the image to format, flipping the image across the Y axis.
        // We can also get a sub rectangle, but we'll get the full image here.
        var conversionParams = new XRCpuImage.ConversionParams(image, format, XRCpuImage.Transformation.MirrorY);

        // Texture2D allows us write directly to the raw texture data
        // This allows us to do the conversion in-place without making any copies.
        var rawTextureData = m_CameraTexture.GetRawTextureData<byte>();
        try
        {
            image.Convert(conversionParams, new IntPtr(rawTextureData.GetUnsafePtr()), rawTextureData.Length);
        }
        finally
        {
            // We must dispose of the XRCpuImage after we're finished
            // with it to avoid leaking native resources.
            image.Dispose();
        }

        // Apply the updated texture data to our texture
        m_CameraTexture.Apply();
        m_ImageInfo2.text = string.Format(
    "Image 2:\n\twidth: {0}\n\theight: {1}\n\thideFlags: {2} \n\tred: {3}\n\tgreen: {4}\n\tblue: {5}\n\tIntensity: {6}\n\tisSetted: {7}",
    m_CameraTexture.width, m_CameraTexture.height, m_CameraTexture.hideFlags, m_CameraTexture.GetPixel(m_CameraTexture.width / 2, m_CameraTexture.height / 2)[0], m_CameraTexture.GetPixel(m_CameraTexture.width / 2, m_CameraTexture.height / 2)[1],
    m_CameraTexture.GetPixel(m_CameraTexture.width / 2, m_CameraTexture.height / 2)[2], (m_CameraTexture.GetPixel(m_CameraTexture.width / 2, m_CameraTexture.height / 2)[0] + m_CameraTexture.GetPixel(m_CameraTexture.width / 2, m_CameraTexture.height / 2)[1] + m_CameraTexture.GetPixel(m_CameraTexture.width / 2, m_CameraTexture.height / 2)[2]) / 3, isSetted);

        // Set the RawImage's texture so we can visualize it.
        m_RawCameraImage.texture = m_CameraTexture;
    }




    void OnCameraFrameReceived(ARCameraFrameEventArgs eventArgs)
    {
        UpdateCameraImage();
    }

    Texture2D m_CameraTexture;







    // Start is called before the first frame update
    void Start()
    {
        tempObject.SetActive(false);
        deadTime = 0;
        isSetted = false;
        gOverPanel.SetActive(false);

    }

    // Update is called once per frame
    void Update()
    {
        if(!isSetted)
        {
            UpdateCenterObject();
        }
        if (isSetted) // 활성화 상태면
        {
            deadTime += Time.deltaTime; // 1초씩 타임 재기
        }

        CheckDead();

    }

    void UpdateCenterObject()
    {
        


        Vector3 screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
        raycastMgr.Raycast(screenCenter, hits, TrackableType.PlaneWithinPolygon);




        if (hits.Count > 0) // Raycast가 평면에 hit하면
        {
            Pose placementPose = hits[0].pose;
            float[,] p_array = new float[9, 2] { { 1 / 6, 1 / 6 }, { 1 / 2, 1 / 6 }, { 5 / 6, 1 / 6 }, { 1 / 6, 1 / 2 }, { 1 / 2, 1 / 2 }, { 5 / 6, 1 / 2 }, { 1 / 6, 5 / 6 }, { 1 / 2, 5 / 6 }, { 5 / 6, 5 / 6 } };
            Color[] colorarray = new Color[9];
            for (int i = 0; i < 9; i++)
            {
                colorarray[i] = m_CameraTexture.GetPixel((int)(m_CameraTexture.width * p_array[i, 0]), (int)(m_CameraTexture.height * p_array[i, 1]));
            }

            float[] avg = new float[9] { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // 각 위치 밝기 배열 초기화
            for (int k = 0; k < 9; k++) // 밝기 배열 배정 // 반경 픽셀 측정하면 렉걸림..
            {
                Color tempcolor = m_CameraTexture.GetPixel((int)(m_CameraTexture.width * p_array[k, 0]), (int)(m_CameraTexture.height * p_array[k, 1]));
                avg[k] += (tempcolor[0] + tempcolor[1] + tempcolor[2]) / 3;
            } // 배열 줄이고 코드 단순화함


            float min = avg[0];
            int idx = 0;
            for (int i = 0; i < 9; i++) // 밝기 최솟값 찾기
            {
                if (min > avg[i])
                {
                    min = avg[i];
                    idx = i;
                }
            } // 최솟값 인덱스 idx 구함



            Vector3 pos = Camera.current.ViewportToScreenPoint(new Vector3(0.166f, 0.166f));
            switch (idx) // 최솟값이 어느 부분인지 확인하고, 그 방향으로 raycast를 한다
            {
                case 0:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.166f, 0.166f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 1:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.166f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 2:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.83f, 0.166f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 3:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.166f, 0.5f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 4:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 5:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.83f, 0.5f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 6:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.166f, 0.83f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 7:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.83f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
                case 8:
                    pos = Camera.current.ViewportToScreenPoint(new Vector3(0.83f, 0.83f));
                    raycastMgr.Raycast(pos, hits, TrackableType.Planes);
                    break;
            }

            Pose placementPose2 = hits[1].pose;
            

            // 출현 위치 = (x,y(9분면 위의 한 중심점),placementPose2.position.z)

            if(min < 0.3) // 최솟값이 0.2 이하면
            {
                m_ImageInfo3.GetComponent<Text>().text = placementPose2.position.x + ", " + placementPose2.position.y + ", " + placementPose2.position.z + ", " + +min + ", " + isSetted;
                if (!spawnObject)
                {
                    int ran = UnityEngine.Random.Range(0, 3);
                    placeObject[ran].SetActive(true);
                    spawnObject = Instantiate(placeObject[ran], placementPose2.position, placementPose2.rotation); // 그 장소에 스폰
                    isSetted = true;
                }
                else
                {
                    spawnObject.transform.position = placementPose2.position;
                    spawnObject.transform.rotation = placementPose2.rotation; //이미 있다면 위치 변경
                }
                //tempObject.SetActive(true);
                /*
                 * Instantiate(tempObject)
                 */

                //tempObject.transform.SetPositionAndRotation(placementPose2.position, placementPose2.rotation); //Position을 어떻게?
                //isSetted = true;
            }
        }

    }

    void CheckDead()
    {
        if(deadTime >= 30)
        {
            gOverPanel.SetActive(true);
        }
    }




}