()
| 230 | } |
| 231 | |
| 232 | func (r *BlockRender) updateMeshCache() { |
| 233 | block := NearBlock(game.camera.Pos()) |
| 234 | chunk := block.Chunkid() |
| 235 | x, z := chunk.X, chunk.Z |
| 236 | n := *renderRadius |
| 237 | needed := make(map[Vec3]bool) |
| 238 | |
| 239 | for dx := -n; dx < n; dx++ { |
| 240 | for dz := -n; dz < n; dz++ { |
| 241 | id := Vec3{x + dx, 0, z + dz} |
| 242 | if dx*dx+dz*dz > n*n { |
| 243 | continue |
| 244 | } |
| 245 | needed[id] = true |
| 246 | } |
| 247 | } |
| 248 | var added, removed []Vec3 |
| 249 | r.meshcache.Range(func(k, v interface{}) bool { |
| 250 | id := k.(Vec3) |
| 251 | if !needed[id] { |
| 252 | removed = append(removed, id) |
| 253 | return true |
| 254 | } |
| 255 | return true |
| 256 | }) |
| 257 | |
| 258 | for id := range needed { |
| 259 | mesh, ok := r.meshcache.Load(id) |
| 260 | // 不在cache里面的需要重新构建 |
| 261 | if !ok { |
| 262 | added = append(added, id) |
| 263 | } else { |
| 264 | if mesh.(*Mesh).Dirty { |
| 265 | log.Printf("update cache %v", id) |
| 266 | added = append(added, id) |
| 267 | removed = append(removed, id) |
| 268 | } |
| 269 | } |
| 270 | } |
| 271 | // 单次并发构造的chunk个数 |
| 272 | const batchBuildChunk = 4 |
| 273 | r.sortChunks(added) |
| 274 | if len(added) > 4 { |
| 275 | added = added[:batchBuildChunk] |
| 276 | } |
| 277 | |
| 278 | var removedMesh []*Mesh |
| 279 | for _, id := range removed { |
| 280 | log.Printf("remove cache %v", id) |
| 281 | mesh, _ := r.meshcache.Load(id) |
| 282 | r.meshcache.Delete(id) |
| 283 | removedMesh = append(removedMesh, mesh.(*Mesh)) |
| 284 | } |
| 285 | |
| 286 | newChunks := game.world.Chunks(added) |
| 287 | for _, c := range newChunks { |
| 288 | log.Printf("add cache %v", c.Id()) |
| 289 | r.meshcache.Store(c.Id(), r.makeChunkMesh(c, false)) |
no test coverage detected