/// <summary> /// 划分格子的Lod级别 /// </summary> private void UpdateLodLevel() { var cam = Camera.main; float CL = 0.6f; Vector3 pos = hero.position; for (int i = 0; i < PieceNum; i++) { for (int j = 0; j < PieceNum; j++) { LodPiece ps = m_piecees[j, i]; Vector2 center = ps.box.position + ps.box.size / 2; float distence = Vector2.Distance(center, new Vector2(pos.x, pos.z)); ps.LodLevel = Mathf.FloorToInt((distence / ps.box.width) * CL); if (ps.LodLevel > LOD_LEVEL_MAX) { ps.LodLevel = LOD_LEVEL_MAX; } } } for (int i = 0; i < PieceNum; i++) { for (int j = 0; j < PieceNum; j++) { LodPiece ps = m_piecees[j, i]; CheckSideLodLevel(j, i, ps); } } }
/// <summary> /// 检查所有的片的LOD级别是否符合规范 /// </summary> public void CheckSidesLodLevel() { for (int i = 0; i < m_mesh_piece_num; i++) { for (int j = 0; j < m_mesh_piece_num; j++) { LodPiece ps = m_piecees[j, i]; CheckSideLodLevel(j, i, ps); } } }
/// <summary> /// 初始化片的数据 /// </summary> private void InitPiece() { if (m_piecees == null) { m_piecees = new LodPiece[m_mesh_piece_num, m_mesh_piece_num]; } Vector2 piecesize = m_mesh_segment_size * m_mesh_piece_segment; for (int i = 0; i < m_mesh_piece_num; i++) { for (int j = 0; j < m_mesh_piece_num; j++) { LodPiece piece = m_piecees[j, i]; if (piece == null) { piece = new LodPiece(); m_piecees[j, i] = piece; } int offset_x = j * m_mesh_piece_segment; int offset_y = i * m_mesh_piece_segment; piece.offset_x = offset_x; piece.offset_y = offset_y; piece.LodLevel = ChunkManager.LOD_LEVEL_MAX; piece.box = new Rect(offset_x * m_mesh_segment_size.x + box.x, offset_y * m_mesh_segment_size.y + box.y, piecesize.x, piecesize.y); } } var cache_v3 = ChunkManager.Instence.cache_v3; var cache_v2 = ChunkManager.Instence.cache_v2; var cache_int = ChunkManager.Instence.cache_int; for (int i = 0; i < m_mesh_piece_num; i++) {//需要分2次循环执行,否则LookUpSideLodLevel会出错 for (int j = 0; j < m_mesh_piece_num; j++) { bool[] isLevelBiger = new bool[] { false, false, false, false }; LodPiece piece = m_piecees[j, i]; int each_offset = 1 << piece.LodLevel; int segment = m_mesh_piece_segment / each_offset; int ver_num = (segment + 1) * (segment + 1); Vector3[] vers = cache_v3.GetOneArray(ver_num); Vector3[] nors = cache_v3.GetOneArray(ver_num); Vector2[] uvs = cache_v2.GetOneArray(ver_num); int[] indexes = cache_int.GetOneArray(segment * segment * 6); LookUpSideLodLevel(j, i, piece.LodLevel, isLevelBiger); UpdatePieceLod(vers, nors, uvs, indexes, segment, piece, isLevelBiger); piece.vers = vers; piece.nors = nors; piece.uvs = uvs; piece.indexes = indexes; piece.last_lod_level = piece.LodLevel; piece.last_is_biger_level = isLevelBiger; } } }
/// <summary> /// 创建所有的片 /// </summary> private void CreatePieces() { GameObject piece_root = new GameObject("chunk_" + id_x + "_" + id_y); obj = piece_root; for (int i = 0; i < m_mesh_piece_num; i++) { for (int j = 0; j < m_mesh_piece_num; j++) { LodPiece piece = m_piecees[j, i]; GameObject obj = MeshCreator.DrawMesh(piece.vers, piece.nors, piece.uvs, piece.indexes, m_chunk_mat, "piece_" + j + "_" + i); piece.mesh = obj.GetComponent <MeshFilter>().mesh; obj.AddComponent <MeshCollider>(); obj.transform.SetParent(piece_root.transform); } } piece_root.transform.SetParent(ChunkManager.Instence.transform); }
/// <summary> /// 检查周围4个格子的Lod级别是否符合:Lod级别不超过此格子的级别+1。否则,直接强制划分Lod级别,并递归划分 /// </summary> /// <param name="j"></param> /// <param name="i"></param> /// <param name="ps"></param> private void CheckSideLodLevel(int j, int i, LodPiece ps) { if (j > 0 && m_piecees[j - 1, i].LodLevel - ps.LodLevel > 1) { m_piecees[j - 1, i].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j - 1, i, m_piecees[j - 1, i]); } if (j < m_mesh_piece_num - 1 && m_piecees[j + 1, i].LodLevel - ps.LodLevel > 1) { m_piecees[j + 1, i].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j + 1, i, m_piecees[j + 1, i]); } if (i > 0 && m_piecees[j, i - 1].LodLevel - ps.LodLevel > 1) { m_piecees[j, i - 1].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j, i - 1, m_piecees[j, i - 1]); } if (i < m_mesh_piece_num - 1 && m_piecees[j, i + 1].LodLevel - ps.LodLevel > 1) { m_piecees[j, i + 1].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j, i + 1, m_piecees[j, i + 1]); } if (j == 0 && Left != null && Left.m_piecees[m_mesh_piece_num - 1, i].LodLevel - ps.LodLevel > 1) { Left.m_piecees[m_mesh_piece_num - 1, i].LodLevel = ps.LodLevel + 1; Left.CheckSideLodLevel(m_mesh_piece_num - 1, i, Left.m_piecees[m_mesh_piece_num - 1, i]); } if (j == m_mesh_piece_num - 1 && Right != null && Right.m_piecees[0, i].LodLevel - ps.LodLevel > 1) { Right.m_piecees[0, i].LodLevel = ps.LodLevel + 1; Right.CheckSideLodLevel(0, i, Right.m_piecees[0, i]); } if (i == 0 && Down != null && Down.m_piecees[j, m_mesh_piece_num - 1].LodLevel - ps.LodLevel > 1) { Down.m_piecees[j, m_mesh_piece_num - 1].LodLevel = ps.LodLevel + 1; Down.CheckSideLodLevel(j, m_mesh_piece_num - 1, Down.m_piecees[j, m_mesh_piece_num - 1]); } if (i == m_mesh_piece_num - 1 && Up != null && Up.m_piecees[j, 0].LodLevel - ps.LodLevel > 1) { Up.m_piecees[j, 0].LodLevel = ps.LodLevel + 1; Up.CheckSideLodLevel(j, 0, Up.m_piecees[j, 0]); } }
/// <summary> /// 划分格子的Lod级别 /// </summary> public void UpdateLodLevel(Vector3 pos) { var cl = ChunkManager.Instence.CL; for (int i = 0; i < m_mesh_piece_num; i++) { for (int j = 0; j < m_mesh_piece_num; j++) { LodPiece ps = m_piecees[j, i]; Vector2 center = ps.box.position + ps.box.size / 2; float distence = Vector2.Distance(center, new Vector2(pos.x, pos.z)); ps.LodLevel = Mathf.FloorToInt((distence / ps.box.width) * cl); if (ps.LodLevel > ChunkManager.LOD_LEVEL_MAX) { ps.LodLevel = ChunkManager.LOD_LEVEL_MAX; } } } }
private bool isNormalUpdated = false; //是否更新过法线 /// <summary> /// 销毁根GameObject和材质 /// </summary> public void DestroyGameObject() { if (m_piecees != null) { var cache_v3 = ChunkManager.Instence.cache_v3; var cache_V2 = ChunkManager.Instence.cache_v2; var cache_int = ChunkManager.Instence.cache_int; for (int i = 0; i < m_mesh_piece_num; i++) { for (int j = 0; j < m_mesh_piece_num; j++) { LodPiece ps = m_piecees[j, i]; cache_v3.GiveBack(ps.vers); cache_v3.GiveBack(ps.nors); cache_V2.GiveBack(ps.uvs); cache_int.GiveBack(ps.indexes); ps.vers = null; ps.nors = null; ps.uvs = null; ps.indexes = null; ps.mesh = null; } } } if (obj != null) { GameObject.Destroy(obj); obj = null; } if (m_chunk_mat != null) { Object.Destroy(m_chunk_mat); m_chunk_mat = null; } if (mask != null) { Object.Destroy(mask); mask = null; maskcolor = null; } }
/// <summary> /// 检查周围4个格子的Lod级别是否符合:Lod级别不超过此格子的级别+1,这个条件。否则,直接强制划分Lod级别,并递归划分 /// </summary> /// <param name="j"></param> /// <param name="i"></param> /// <param name="ps"></param> private void CheckSideLodLevel(int j, int i, LodPiece ps) { if (j > 0 && m_piecees[j - 1, i].LodLevel - ps.LodLevel > 1) { m_piecees[j - 1, i].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j - 1, i, m_piecees[j - 1, i]); } if (j < PieceNum - 1 && m_piecees[j + 1, i].LodLevel - ps.LodLevel > 1) { m_piecees[j + 1, i].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j + 1, i, m_piecees[j + 1, i]); } if (i > 0 && m_piecees[j, i - 1].LodLevel - ps.LodLevel > 1) { m_piecees[j, i - 1].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j, i - 1, m_piecees[j, i - 1]); } if (i < PieceNum - 1 && m_piecees[j, i + 1].LodLevel - ps.LodLevel > 1) { m_piecees[j, i + 1].LodLevel = ps.LodLevel + 1; CheckSideLodLevel(j, i + 1, m_piecees[j, i + 1]); } }
/// <summary> /// 更新所有片的网格 /// </summary> public void UpdateLod() { var m_cache_v3 = ChunkManager.Instence.cache_v3; var m_cache_v2 = ChunkManager.Instence.cache_v2; var m_cache_int = ChunkManager.Instence.cache_int; bool[] isLevelBiger = new bool[4]; for (int i = 0; i < m_mesh_piece_num; i++) { for (int j = 0; j < m_mesh_piece_num; j++) { LodPiece piece = m_piecees[j, i]; LookUpSideLodLevel(j, i, piece.LodLevel, isLevelBiger); if (isNormalUpdated || piece.CheckNeedUpdate(isLevelBiger)) { piece.SetLastBigLevel(isLevelBiger); int each_offset = 1 << piece.LodLevel; int segment = m_mesh_piece_segment / each_offset; int ver_num = (segment + 1) * (segment + 1); if (ver_num != piece.vers.Length) { m_cache_v3.GiveBack(piece.vers); piece.vers = m_cache_v3.GetOneArray(ver_num); m_cache_v3.GiveBack(piece.nors); piece.nors = m_cache_v3.GetOneArray(ver_num); m_cache_v2.GiveBack(piece.uvs); piece.uvs = m_cache_v2.GetOneArray(ver_num); m_cache_int.GiveBack(piece.indexes); piece.indexes = m_cache_int.GetOneArray(segment * segment * 6); } UpdatePieceLod(piece.vers, piece.nors, piece.uvs, piece.indexes, segment, piece, isLevelBiger); piece.UpdateMeshData(); } } } isNormalUpdated = false; }
private void UpdateLod() { bool[] isLevelBiger = new bool[4]; for (int i = 0; i < PieceNum; i++) { for (int j = 0; j < PieceNum; j++) { LodPiece piece = m_piecees[j, i]; LookUpSideLodLevel(j, i, piece.LodLevel, isLevelBiger); if (piece.CheckNeedUpdate(isLevelBiger)) { int each_offset = 1 << piece.LodLevel; int segment = PieceMechSegment / each_offset; int ver_num = (segment + 1) * (segment + 1); if (ver_num != piece.vers.Length) { m_cache_v3.GiveBack(piece.vers); piece.vers = m_cache_v3.GetOneArray(ver_num); m_cache_v3.GiveBack(piece.nors); piece.nors = m_cache_v3.GetOneArray(ver_num); m_cache_v2.GiveBack(piece.uvs); piece.uvs = m_cache_v2.GetOneArray(ver_num); m_cache_int.GiveBack(piece.indexes); piece.indexes = m_cache_int.GetOneArray(segment * segment * 6); } UpdatePieceLod(piece.vers, piece.nors, piece.uvs, piece.indexes, segment, piece, isLevelBiger); var mesh = piece.mesh; mesh.Clear(); mesh.vertices = piece.vers; mesh.uv = piece.uvs; mesh.triangles = piece.indexes; mesh.normals = piece.nors; } } } }
private GameObject CreatePiece(LodPiece piece, string name) { int each_offset = 1 << piece.LodLevel; int segment = PieceMechSegment / each_offset; int ver_num = (segment + 1) * (segment + 1); bool[] isLevelBiger = new bool[] { false, false, false, false }; Vector3[] vers = new Vector3[ver_num]; Vector3[] nors = new Vector3[ver_num]; Vector2[] uvs = new Vector2[ver_num]; int[] indexes = new int[segment * segment * 6]; UpdatePieceLod(vers, nors, uvs, indexes, segment, piece, isLevelBiger); GameObject obj = MeshCreator.DrawMesh(vers, nors, uvs, indexes, PieceMat, name); piece.mesh = obj.GetComponent <MeshFilter>().mesh; piece.vers = vers; piece.nors = nors; piece.uvs = uvs; piece.indexes = indexes; piece.last_lod_level = piece.LodLevel; piece.last_is_biger_level = isLevelBiger; obj.AddComponent <MeshCollider>(); return(obj); }
private void InitPiece() {//test GameObject piece_root = new GameObject("piece_root"); m_piecees = new LodPiece[PieceNum, PieceNum]; for (int i = 0; i < PieceNum; i++) { for (int j = 0; j < PieceNum; j++) { int offset_x = j * PieceMechSegment; int offset_y = i * PieceMechSegment; LodPiece piece = new LodPiece() { offset_x = offset_x, offset_y = offset_y, LodLevel = LOD_LEVEL_MAX, box = new Rect(offset_x * m_mesh_segment_size.x, offset_y * m_mesh_segment_size.y, PieceMechSegment * m_mesh_segment_size.x, PieceMechSegment * m_mesh_segment_size.y) }; m_piecees[j, i] = piece; GameObject obj = CreatePiece(piece, "piece_" + j + "_" + i); obj.transform.SetParent(piece_root.transform); } } }
private void UpdatePieceLod(Vector3[] vers, Vector3[] nors, Vector2[] uvs, int[] indexes, int segment, LodPiece piece, bool[] isLevelBiger) { int each_offset = 1 << piece.LodLevel; for (int i = 0; i < segment + 1; i++) { for (int j = 0; j < segment + 1; j++) { int index_x = piece.offset_x + each_offset * j; int index_y = piece.offset_y + each_offset * i; int index = i * (segment + 1) + j; vers[index] = m_mesh_vers[index_x, index_y]; nors[index] = m_mesh_normals[index_x, index_y]; uvs[index] = m_mesh_uvs[index_x, index_y]; } } InitPieceIndexes(segment, indexes, isLevelBiger); }