| 325 | } |
| 326 | |
| 327 | void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) { |
| 328 | struct TerrainParticle* p; |
| 329 | TextureLoc loc; |
| 330 | int texIndex; |
| 331 | TextureRec baseRec, rec; |
| 332 | Vec3 origin, minBB, maxBB; |
| 333 | |
| 334 | /* texture UV variables */ |
| 335 | float uScale, vScale, maxU2, maxV2; |
| 336 | int minX, minZ, maxX, maxZ; |
| 337 | int minU, minV, maxU, maxV; |
| 338 | int maxUsedU, maxUsedV; |
| 339 | |
| 340 | /* per-particle variables */ |
| 341 | float cellX, cellY, cellZ; |
| 342 | Vec3 cell; |
| 343 | int x, y, z, type; |
| 344 | |
| 345 | if (now != BLOCK_AIR || Blocks.Draw[old] == DRAW_GAS) return; |
| 346 | IVec3_ToVec3(&origin, &coords); |
| 347 | loc = Block_Tex(old, FACE_XMIN); |
| 348 | |
| 349 | baseRec = Atlas1D_TexRec(loc, 1, &texIndex); |
| 350 | uScale = (1.0f/16.0f); vScale = (1.0f/16.0f) * Atlas1D.InvTileSize; |
| 351 | |
| 352 | minBB = Blocks.MinBB[old]; maxBB = Blocks.MaxBB[old]; |
| 353 | minX = (int)(minBB.x * 16); maxX = (int)(maxBB.x * 16); |
| 354 | minZ = (int)(minBB.z * 16); maxZ = (int)(maxBB.z * 16); |
| 355 | |
| 356 | minU = min(minX, minZ); minV = (int)(16 - maxBB.y * 16); |
| 357 | maxU = min(maxX, maxZ); maxV = (int)(16 - minBB.y * 16); |
| 358 | /* This way we can avoid creating particles which outside the bounds and need to be clamped */ |
| 359 | maxUsedU = maxU; maxUsedV = maxV; |
| 360 | if (minU < 12 && maxU > 12) maxUsedU = 12; |
| 361 | if (minV < 12 && maxV > 12) maxUsedV = 12; |
| 362 | |
| 363 | #define GRID_SIZE 4 |
| 364 | /* gridOffset gives the centre of the cell on a grid */ |
| 365 | #define CELL_CENTRE ((1.0f / GRID_SIZE) * 0.5f) |
| 366 | |
| 367 | maxU2 = baseRec.u1 + maxU * uScale; |
| 368 | maxV2 = baseRec.v1 + maxV * vScale; |
| 369 | for (x = 0; x < GRID_SIZE; x++) { |
| 370 | for (y = 0; y < GRID_SIZE; y++) { |
| 371 | for (z = 0; z < GRID_SIZE; z++) { |
| 372 | |
| 373 | cellX = (float)x / GRID_SIZE; cellY = (float)y / GRID_SIZE; cellZ = (float)z / GRID_SIZE; |
| 374 | cell = Vec3_Create3(CELL_CENTRE + cellX, CELL_CENTRE / 2 + cellY, CELL_CENTRE + cellZ); |
| 375 | if (cell.x < minBB.x || cell.x > maxBB.x || cell.y < minBB.y |
| 376 | || cell.y > maxBB.y || cell.z < minBB.z || cell.z > maxBB.z) continue; |
| 377 | |
| 378 | if (terrain_count == PARTICLES_MAX) Terrain_RemoveAt(0); |
| 379 | p = &terrain_particles[terrain_count++]; |
| 380 | |
| 381 | /* centre random offset around [-0.2, 0.2] */ |
| 382 | p->base.velocity.x = CELL_CENTRE + (cellX - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); |
| 383 | p->base.velocity.y = CELL_CENTRE + (cellY - 0.0f) + (Random_Float(&rnd) * 0.4f - 0.2f); |
| 384 | p->base.velocity.z = CELL_CENTRE + (cellZ - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f); |
no test coverage detected