void InitCameraInfo() { if (m_TargetCamera != null) { var lookAt = m_TargetCamInfo.lookAt; m_IsCamOri = m_TargetCamera.orthographic; if (m_TargetCamera.orthographic) { m_TargetCamInfo = new PVSCameraInfo(); m_TargetCamInfo.far = m_TargetCamera.farClipPlane; m_TargetCamInfo.near = m_TargetCamera.nearClipPlane; m_TargetCamInfo.fieldOfView = m_TargetCamera.orthographicSize; } else { m_TargetCamInfo = new PVSCameraInfo(); m_TargetCamInfo.far = m_TargetCamera.farClipPlane; m_TargetCamInfo.near = m_TargetCamera.nearClipPlane; m_TargetCamInfo.fieldOfView = m_TargetCamera.fieldOfView; } m_TargetCamInfo.lookAt = lookAt; m_TargetCamInfo.aspect = m_TargetCamera.aspect; m_TargetCamInfo.position = m_TargetCamera.transform.position; m_TargetCamInfo.cullMatrix = m_TargetCamera.cullingMatrix; } }
public PVSBakerThread(Vector3[] cellArray, PVSCell[] results, PVSBounds[] bounds, int startIdx, int endIdx, PVSCameraInfo camInfo, bool isOriCam) { m_CellArray = cellArray; m_Results = results; m_Bounds = bounds; m_StartIdx = startIdx; m_EndIdx = endIdx; m_CamInfo = camInfo; m_IsOriCam = isOriCam; }
private void CellRays(int cellIdx, Vector3 cellPos, PVSBounds[] bounds, PVSCameraInfo camInfo, bool isOriCam) { var cell = m_Results[cellIdx]; cell.ResetVisible(); Vector3 right = camInfo.right; Vector3 up = camInfo.up; Vector3 lookAt = camInfo.lookAt; if (isOriCam) { // 正交攝影機 var width = camInfo.CameraWidth; var height = camInfo.CameraHeight; float perX = GetPerX(width); float perY = GetPerY(height); Vector3 halfV = (right * width / 2.0f + up * height / 2.0f); Vector3 minVec = cellPos - halfV; float stepY = 0; while (stepY <= height) { float stepX = 0; Vector3 yy = stepY * up; while (stepX <= width) { Vector3 startPt = minVec + stepX * right + yy + lookAt * camInfo.near; Ray ray = new Ray(startPt, lookAt); float tutDistance = 0; while (true) { int collisionIdx = PVSRayTrack.sdPVSCells(ref ray, bounds, ref tutDistance); if (collisionIdx >= 0) { var b = m_Bounds[collisionIdx]; cell.SetVisible(b.id, true); break; } if (tutDistance > (camInfo.far - camInfo.near)) { break; } } stepX += perX; } stepY += perY; } lock (cell) { cell.isEditorDone = true; } } else { // 透視攝影機 var width = camInfo.farWidth; var height = camInfo.farHeight; float perX = GetPerX(width); float perY = GetPerY(height); Vector3 halfV = (right * width / 2.0f + up * height / 2.0f); Vector3 minVec = cellPos - halfV; float d = camInfo.far; float stepY = 0; while (stepY < height) { float stepX = 0; Vector3 yy = stepY * up; while (stepX < width) { Vector3 endPt = minVec + stepX * right + yy + lookAt * d; Vector3 dir = (endPt - camInfo.position).normalized; Ray ray = new Ray(camInfo.position, dir); float tutDistance = 0; while (true) { int collisionIdx = PVSRayTrack.sdPVSCells(ref ray, bounds, ref tutDistance); if (collisionIdx >= 0) { var b = m_Bounds[collisionIdx]; cell.SetVisible(b.id, true); break; } if (tutDistance > camInfo.far) { break; } } stepX += perX; } stepY += perY; } lock (cell) { cell.isEditorDone = true; } } }
private void ProcessCurrentScene(bool isOnlyInit = false) { // 获得当前场景NavMesh if (isOnlyInit) { var tris = UnityEngine.AI.NavMesh.CalculateTriangulation(); if (tris.vertices == null || tris.indices == null || tris.indices.Length <= 0 || tris.vertices.Length <= 0) { Debug.LogError("当前场景没有NavMesh"); return; } m_PVSItemIDS = GameObject.FindObjectOfType <PVSItemIDS>(); if (m_PVSItemIDS == null) { GameObject obj = new GameObject("PVSItemIDS", typeof(PVSItemIDS)); m_PVSItemIDS = obj.GetComponent <PVSItemIDS>(); } Vector3 minVec = Vector3.zero; Vector3 maxVec = Vector3.zero; for (int i = 0; i < tris.vertices.Length; ++i) { var vec = tris.vertices [i]; if (i == 0) { minVec = vec; maxVec = vec; } else { minVec.x = Mathf.Min(minVec.x, vec.x); minVec.y = Mathf.Min(minVec.y, vec.y); minVec.z = Mathf.Min(minVec.z, vec.z); maxVec.x = Mathf.Max(maxVec.x, vec.x); maxVec.y = Mathf.Max(maxVec.y, vec.y); maxVec.z = Mathf.Max(maxVec.z, vec.z); } } float camY = this.CamHeight; // 处理区域 Vector3 center = (maxVec + minVec) / 2.0f; Vector3 size = (maxVec - minVec); size.x = Mathf.Abs(size.x); size.y = Mathf.Abs(size.y); size.z = Mathf.Abs(size.z); m_SearchBounds = new Bounds(center, size); int col = Mathf.CeilToInt(size.x / PVSCell.CellSize); int row = Mathf.CeilToInt(size.z / PVSCell.CellSize); Vector3 halfSize = new Vector3(PVSCell.CellSize, 0, PVSCell.CellSize) / 2.0f; Vector3[] arr = new Vector3[col * row]; for (int r = 0; r < row; ++r) { for (int c = 0; c < col; ++c) { int idx = c + r * col; Vector3 pt = new Vector3(c * PVSCell.CellSize + minVec.x, center.y, r * PVSCell.CellSize + minVec.z) + halfSize; UnityEngine.AI.NavMeshHit hit; if (UnityEngine.AI.NavMesh.SamplePosition(pt, out hit, PVSCell.CellSize, int.MaxValue)) { pt.y = hit.position.y + camY / 2.0f; } else { // 再搜索四个角,看是否有效,否则直接SIZE为0 Vector3 c1 = pt - halfSize; Vector3 c2 = pt - new Vector3(halfSize.x, 0, -halfSize.z); Vector3 c3 = pt + halfSize; Vector3 c4 = pt + new Vector3(halfSize.x, 0, -halfSize.z); if ((!UnityEngine.AI.NavMesh.SamplePosition(c1, out hit, PVSCell.CellSize, int.MaxValue)) && (!UnityEngine.AI.NavMesh.SamplePosition(c2, out hit, PVSCell.CellSize, int.MaxValue)) && (!UnityEngine.AI.NavMesh.SamplePosition(c3, out hit, PVSCell.CellSize, int.MaxValue)) && (!UnityEngine.AI.NavMesh.SamplePosition(c4, out hit, PVSCell.CellSize, int.MaxValue)) ) { pt = Vector3.zero; m_CellIngoreArray.Add(idx); } } arr [idx] = pt; } } m_CellArray = arr; return; } var size1 = m_SearchBounds.size; int col1 = Mathf.CeilToInt(size1.x / PVSCell.CellSize); int row1 = Mathf.CeilToInt(size1.z / PVSCell.CellSize); InitPVSMeshes(); InitCellResults(); ClearThreads(); if (m_CheckCellBuffer != null) { m_CheckCellBuffer.Dispose(); m_CheckCellBuffer = null; } if (m_CameraBuffer != null) { m_CameraBuffer.Dispose(); m_CameraBuffer = null; } if (m_BakerMode == PVSSceneBakerMode.CameraRTCpuMode || m_BakerMode == PVSSceneBakerMode.CameraRTComputeMode) { if (m_PVSCellShader == null) { Debug.LogError("PVS烘焙ComputeShader找不到"); return; } PVSCameraRtTrack camRtTrack = new PVSCameraRtTrack(); camRtTrack.Start(m_TargetCamera, m_CellsResult, m_PVSItemIDS, m_TargetCamInfo.lookAt, m_PVSCellShader, m_BakerMode == PVSSceneBakerMode.CameraRTComputeMode); OnCpuThreadDone(); return; } if (!SystemInfo.supportsComputeShaders || m_BakerMode == PVSSceneBakerMode.CpuThreadMode) { if (m_BakerMode == PVSSceneBakerMode.ComputeShaderMode) { Debug.LogError("设备不支持ComputeShader"); } // 开启线程模式 CreateThreadMode(); return; } m_CheckCellBuffer = new ComputeBuffer(m_CellArray.Length, Marshal.SizeOf(typeof(Vector3))); m_CheckCellBuffer.SetData(m_CellArray); m_CameraBuffer = new ComputeBuffer(1, Marshal.SizeOf(typeof(PVSCameraInfo))); PVSCameraInfo[] camArr = new PVSCameraInfo[1]; camArr[0] = m_TargetCamInfo; m_CameraBuffer.SetData(camArr); if (m_PVSCellShader != null) { int main = m_PVSCellShader.FindKernel("PVSBaker"); m_PVSCellShader.SetBuffer(main, "pvsBakerPosArray", m_CheckCellBuffer); m_PVSCellShader.SetBuffer(main, "camera", m_CameraBuffer); m_PVSCellShader.Dispatch(main, col1, row1, 1); } else { Debug.LogError("PVS烘焙ComputeShader找不到"); } }