Last active
September 25, 2020 15:34
-
-
Save JakubNei/b4b8b4a4b11ef5549a40 to your computer and use it in GitHub Desktop.
Lame Implementation of Area and Portal Occlusion Culling based on DOOM 3 BFG http://www.iddevnet.com/doom3/visportals.php https://github.com/id-Software/DOOM-3-BFG
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Occlusion.ConvexPolygon CreatePolygonFor(VoxelDungeon.Corridor corridor, VoxelDungeon.Corridor.PositionNode pathNode) | |
{ | |
Vector3 pos = new Vector3(pathNode.position.x, mapData.config.groundPlaneHeight, pathNode.position.y) - Vector3.one; | |
float h = corridor.height+2; | |
int width = corridor.width; | |
int wStart = width / 2; | |
int wEnd = width - wStart; | |
Quaternion rot; | |
if(MapData.IsHorizontalFromTop(pathNode.direction)) rot=Quaternion.LookRotation(new Vector3(1,0,0), Vector3.up); | |
else rot=Quaternion.LookRotation(new Vector3(0,0,1), Vector3.up); | |
var polygon = new Occlusion.ConvexPolygon(); | |
polygon.points.Add(rot * new Vector3(-wStart, h, 0) + pos); | |
polygon.points.Add(rot * new Vector3(wEnd, h, 0) + pos); | |
polygon.points.Add(rot * new Vector3(wEnd, 0, 0) + pos); | |
polygon.points.Add(rot * new Vector3(-wStart, 0, 0) + pos); | |
return polygon; | |
} | |
void Update() | |
{ | |
if (!isGenerated) return; | |
Camera cam = manager.camera.current; | |
Vector3 poi = cam.transform.position;// manager.actor.player.position; | |
Int3 poii = WorldToLocal(poi); | |
VoxelDungeon.OwnerNode owner = null; | |
for (int i = 0; i < 8 && owner == null; i++) | |
{ | |
owner = mapData.GetOwnerAt( | |
poii.x + tilesOffsets[i, 0], | |
poii.y + tilesOffsets[i, 1], | |
poii.z + tilesOffsets[i, 2] | |
); | |
} | |
if (owner == null) return; | |
NodeData node; | |
if (!voxelMapNodeToContainer.TryGetValue(owner, out node)) return; | |
node.occlusionArea.StartPropagate(cam); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using Extensions; | |
namespace Occlusion | |
{ | |
public class Area : MonoBehaviour | |
{ | |
public float turnInvisibleInSec = 10; | |
public Dictionary<Area,Portal> portals = new Dictionary<Area,Portal>(); | |
void LateUpdate() | |
{ | |
if (turnInvisibleInSec>0) | |
{ | |
turnInvisibleInSec-=Time.deltaTime; | |
if (turnInvisibleInSec<=0) | |
this.gameObject.SetActive(false); | |
} | |
} | |
public void TurnVisible() | |
{ | |
turnInvisibleInSec = 10; | |
this.gameObject.SetActive(true); | |
} | |
public void StartPropagate(Camera cam) | |
{ | |
Vector3 origin = cam.transform.position; | |
var planes = GeometryUtility.CalculateFrustumPlanes(cam); | |
var toUsePlanes = new List<Plane>(); | |
var excludeNormal = cam.transform.forward; | |
foreach (var plane in planes) | |
{ | |
var d = plane.normal.Dot(excludeNormal); | |
if (d < 0.9f && d > -0.9f) toUsePlanes.Add(plane); | |
} | |
this.Propagate_r(null, origin, toUsePlanes.ToArray()); | |
} | |
void Propagate_r(Portal parentPortal, Vector3 origin, Plane[] planes) | |
{ | |
TurnVisible(); | |
foreach (var kvp in portals) | |
{ | |
var portal = kvp.Value; | |
if (parentPortal == portal) continue; | |
var area = kvp.Key; | |
var polygon = portal.polygon.Clone(); | |
bool isVisible = true; | |
foreach (var plane in planes) | |
{ | |
isVisible &= polygon.Clip(plane); | |
} | |
if (isVisible) | |
{ | |
portal.polygon.DebugDrawLines(Color.blue); | |
polygon.DebugDrawLines(Color.red); | |
} | |
else | |
{ | |
portal.polygon.DebugDrawLines(Color.yellow); | |
continue; | |
} | |
var points = polygon.points; | |
int numPoints = points.Count; | |
Plane[] portalPlanes = new Plane[numPoints]; | |
for (int i = 0; i < numPoints; i++) | |
{ | |
portalPlanes[i] = new Plane(points[i], points[(i + 1) % numPoints], origin); | |
} | |
area.Propagate_r(portal, origin, portalPlanes); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections.Generic; | |
using Extensions; | |
namespace Occlusion | |
{ | |
// based on idWinding class from Doom 3 BFG source by ID | |
public class ConvexPolygon | |
{ | |
//public Plane plane; | |
public List<Vector3> points = new List<Vector3>(); | |
public ConvexPolygon Clone() | |
{ | |
return new ConvexPolygon() { points = new List<Vector3>(this.points) }; | |
} | |
public void DebugOnTick() | |
{ | |
DebugDrawLines(Color.blue); | |
var oldPoints = this.points.ToArray(); | |
var planes = GeometryUtility.CalculateFrustumPlanes(Camera.main); | |
var excludeNormal = Camera.main.transform.forward; | |
foreach (var plane in planes) | |
{ | |
var d = plane.normal.Dot(excludeNormal); | |
if (d < 0.9f && d > -0.9f) Clip(plane); | |
} | |
DebugDrawLines(Color.red); | |
points = new List<Vector3>(oldPoints); | |
} | |
public void DebugDrawLines(Color color = default(Color)) | |
{ | |
int numPoints = points.Count; | |
for (int i = 0; i < numPoints; i++) | |
{ | |
Debug.DrawLine(points[i], points[(i + 1) % numPoints], color); | |
} | |
} | |
public bool Clip(Plane plane, float epsilon = 0.0f) | |
{ | |
const int SIDE_BEHIND = 0; | |
const int SIDE_FRONT = 1; | |
const int SIDE_ON = 2; | |
List<Vector3> newPoints = new List<Vector3>(); | |
int numPoints = points.Count; | |
float dist = 0; | |
int[] sides = new int[numPoints]; | |
float[] dists = new float[numPoints]; | |
int[] counts = new int[3]; | |
for (int i = 0; i < numPoints; i++) | |
{ | |
dists[i] = dist = plane.GetDistanceToPoint(points[i]); | |
if (dist > epsilon) sides[i] = SIDE_FRONT; | |
else if (dist < -epsilon) sides[i] = SIDE_BEHIND; | |
else sides[i] = SIDE_ON; | |
counts[sides[i]]++; | |
} | |
// no point is clipped | |
if (counts[SIDE_BEHIND] == 0) return true; | |
if (counts[SIDE_FRONT] + counts[SIDE_ON] == 0) return false; | |
for (int i = 0; i < numPoints; i++) | |
{ | |
if (sides[i] == SIDE_BEHIND) | |
{ | |
continue; | |
} | |
if (sides[i] == SIDE_FRONT || sides[i] == SIDE_ON) | |
{ | |
newPoints.Add(points[i]); | |
} | |
int otherI; | |
bool insertAtEnd = true; | |
if (sides[otherI = (i + 1) % numPoints] == SIDE_BEHIND) insertAtEnd = true; | |
else if (sides[otherI = (numPoints + i - 1) % numPoints] == SIDE_BEHIND) insertAtEnd = false; | |
else continue; | |
float t = dists[i] / (dists[i] - dists[otherI]); | |
newPoints.Insert( | |
insertAtEnd ? newPoints.Count : newPoints.Count - 1, | |
points[i] * (1 - t) + points[otherI] * (t) | |
); | |
} | |
points = newPoints; | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is meant just as a general idea on how to do it. It is tightly integrated into 1gb project, You ought to understand it and modify it to suit your needs. I pretty much only converted the DOOM code into C#.