🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Help with custom portal occlusion script

Started by
0 comments, last by Tharrior 3 years, 1 month ago

I have custom portal occlusion culling working, but with some problems.

I'm making portal occlusion for that impossible space effect.

The test map was made in blender and the portals are part of the sector.

Portals are quads and the vertices go around clockwise.

There are problems with my script that I don't know exactly how to fix.

One problem is a sector turning off when a new portal that is visible and the sector is occluded from that portal.

Another problem is only one origin portal frustum can access a portal.

How do I make it work better or fix the problems?

This goes on the main camera.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class View : MonoBehaviour
{
    public Plane[] planes;

    public GameObject CurrentSector;

    public Transform[] Portals;

    // Start is called before the first frame update
    void Start()
    {
         
    }

    // Update is called once per frame
    void Update()
    {
        planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
        Portals = CurrentSector.GetComponentsInChildren<Transform>();
        for (int i = 0; i < Portals.Length; ++i)
        {
            Portals[i].GetComponentInChildren<Portal3>().CamTurnOnSector();
        }
    }
}

This goes on a portal quad.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Portal3 : MonoBehaviour
{
    public GameObject CamTargetSector;

    public Transform[] CamTargetPortals;

    public GameObject PortalTargetSector;

    public Transform[] PortalTargetPortals;

    public Plane[] Portalplanes;

    public Plane portalPlane;

    public GameObject[] OriginPortal;

    public GameObject NextSector;

    public int NextLayer;

    public float Distance = 0f;

    private GameObject Player;

    // Start is called before the first frame update
    void Start()
    {
        Portalplanes = new Plane[4];

        Player = GameObject.FindWithTag("Player");
        Mesh portalMesh = GetComponent<MeshFilter>().sharedMesh;
        Vector3[] normals = portalMesh.normals;

        for (int i = 0; i < normals.Length; ++i)
        {
            portalPlane.SetNormalAndPosition(transform.TransformDirection(normals[i]), transform.position);
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void CamTurnOnSector()
    {
        Mesh portalMesh = GetComponent<MeshFilter>().sharedMesh;
        Vector3[] corners = portalMesh.vertices;
        Vector3 Cam = Camera.main.transform.position;

        Vector3 corner0 = transform.TransformPoint(corners[0]);
        Vector3 corner1 = transform.TransformPoint(corners[1]);
        Vector3 corner2 = transform.TransformPoint(corners[2]);
        Vector3 corner3 = transform.TransformPoint(corners[3]);

        Portalplanes[0].Set3Points(Cam, corner3, corner2);
        Portalplanes[1].Set3Points(Cam, corner2, corner1);
        Portalplanes[2].Set3Points(Cam, corner1, corner0);
        Portalplanes[3].Set3Points(Cam, corner0, corner3);

        CamTargetPortals = CamTargetSector.GetComponentsInChildren<Transform>();

        Collider PortalCollider = GetComponent<Collider>();

        if (portalPlane.GetDistanceToPoint(Camera.main.transform.position) > Distance)
        {
            if (GeometryUtility.TestPlanesAABB(Camera.main.GetComponent<View>().planes, PortalCollider.bounds))
            {
                for (int i = 0; i < CamTargetPortals.Length; ++i)
                {
                    CamTargetPortals[i].GetComponentInChildren<Portal3>().PortalTurnOnSector();         
                }
                CamTargetSector.GetComponent<Renderer>().enabled = true;             
            }
            else
            {
                CamTargetSector.GetComponent<Renderer>().enabled = false;     
            }
        }
    }

    public void PortalTurnOnSector()
    {
        Mesh portalMesh = GetComponent<MeshFilter>().sharedMesh;
        Vector3[] corners = portalMesh.vertices;
        Vector3 Cam = Camera.main.transform.position;

        Vector3 corner0 = transform.TransformPoint(corners[0]);
        Vector3 corner1 = transform.TransformPoint(corners[1]);
        Vector3 corner2 = transform.TransformPoint(corners[2]);
        Vector3 corner3 = transform.TransformPoint(corners[3]);

        Portalplanes[0].Set3Points(Cam, corner3, corner2);
        Portalplanes[1].Set3Points(Cam, corner2, corner1);
        Portalplanes[2].Set3Points(Cam, corner1, corner0);
        Portalplanes[3].Set3Points(Cam, corner0, corner3);

        PortalTargetPortals = PortalTargetSector.GetComponentsInChildren<Transform>();

        Collider PortalCollider = GetComponent<Collider>();

        if (portalPlane.GetDistanceToPoint(Camera.main.transform.position) > Distance)
        {
            for (int i = 0; i < OriginPortal.Length; ++i)
            {
                if (GeometryUtility.TestPlanesAABB(OriginPortal[i].GetComponent<Portal3>().Portalplanes, PortalCollider.bounds) && GeometryUtility.TestPlanesAABB(Camera.main.GetComponent<View>().planes, PortalCollider.bounds))
                {
                    //for (int e = 0; e < PortalTargetPortals.Length; ++e)
                    //{
                    //PortalTargetPortals[e].GetComponentInChildren<Portal3>().PortalTurnOnSector();
                    //}

                    PortalTargetSector.GetComponent<Renderer>().enabled = true;
                }
                else
                {
                    PortalTargetSector.GetComponent<Renderer>().enabled = false;
                }
            }
        }
    }

    void OnTriggerStay(Collider other)
    {
        NextSector.GetComponent<Renderer>().enabled = true;
        if (portalPlane.GetDistanceToPoint(Camera.main.transform.position) < 0)
        {
            Camera.main.GetComponent<View>().CurrentSector = NextSector;
            Player.gameObject.layer = NextLayer;
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (portalPlane.GetDistanceToPoint(Camera.main.transform.position) < 0)
        {
            NextSector.GetComponent<Renderer>().enabled = true;
        }
        else
        {
            NextSector.GetComponent<Renderer>().enabled = false;
        }
    }
}

This topic is closed to new replies.

Advertisement