Updated version of my tiled SPS ground with TextureAtlas.
The lower left corner is not broken, but intentional
Of course, we can also use an array of colors:
Playground w/ Colors
Code and Explaination.
// creation function, returns the SPS.
// @options
// tileSize: INT, The size of each tile, in BABYLON units. default 1.
// rows: INT, The number of rows of tiles, default 1.
// cols: INT, The number of columns of tiles, default 1.
// Options when using a material / textureAtlas
// material: BABYLON.Material, default Null.
// sheetHeight: INT, The number of ROWS of sprites/textures in the material texture/Atlas, default 1.
// sheetWidth: INT, The number of COLUMNS of sprites/textures in the material texture/Atlas, default 1.
// tileUvs: Array [ {u: 1, v: 1} ], An array indexing each tile's UV, starting from Array[0] being the first tile, default Null.
// Option when Not using a material / textureAtlas
// colors: Array[ BABYLON.COLOR3 ], An array, like tileUvs, but containing BABYLON.Color3's for each tile instead of uv data. default Null.
function createTiledGround(options){
if(!options) options = {};
let tileSize = options.tileSize || 1;
let rows = options.rows || 1;
let cols = options.cols || 1;
let sheetHeight = options.sheetHeight || 1;
let sheetWidth = options.sheetWidth || 1;
let material = options.material || null;
let tileUvs = options.tileUvs || null;
let colors = options.colors || null;
// SPS creation
var plane = BABYLON.MeshBuilder.CreateGround('plane', {width: tileSize, height: tileSize});
var SPS = new BABYLON.SolidParticleSystem('SPS', scene, {isPickable: true});
SPS.addShape(plane, rows * cols);
var mesh = SPS.buildMesh();
mesh.material = material ? material : null;
plane.dispose();
SPS.initParticles = function() {
var _this = this;
// just prepare everything
for (var _c = 0, xlen = cols; _c < xlen; _c++) {
for (var _r = 0, zlen = rows; _r < zlen; _r++) {
var particle = _this.particles[_r + (rows*_c)];
particle.indexNum = (_r + (rows*_c));
particle.position.x = (((_r - (rows/2))) + (tileSize/2)) * tileSize;
particle.position.z = (((_c - (cols/2))) + (tileSize/2)) * tileSize;
if(material && tileUvs){
particle.__uv = tileUvs[_r + (rows*_c)];
}
else if(colors){
particle.__color = colors[_r + (rows*_c)];
}
}
}
return SPS;
};
SPS.updateParticle = function(particle) {
if(particle.__uv){
let u = particle.__uv.u;
let v = particle.__uv.v;
particle.uvs.x = u/sheetWidth;
particle.uvs.z = (u+1) /sheetWidth;
particle.uvs.y = v/sheetHeight;
particle.uvs.w = (v+1) /sheetHeight;
}
else if(!particle.__hasColor) {
particle.__hasColor = true;
if(particle.__color){
particle.color = particle.__color;
}
else {
particle.color = new BABYLON.Color3((Math.random()), (Math.random()), (Math.random()));
}
}
return SPS;
};
// __processPicking - Optional.
// pickResult - The result from a scene.pick()
// callback - "onComplete" callback, returns the picked particle, if any.
SPS.__processPicking = function(pickResult, callback){
let _this = SPS;
if(!pickResult || pickResult.pickedMesh !== _this.mesh || pickResult.faceId === -1){
return;
}
if(typeof(callback) === "function"){
callback(_this.particles[_this.pickedParticles[pickResult.faceId].idx]);
}
// Update SPS
_this.setParticles();
};
return SPS;
}
.
Stressing the SPS.
10.000 tiles.
Colors
https://www.babylonjs-playground.com/#1ALQPZ#40
Material
https://www.babylonjs-playground.com/#1ALQPZ#41
.
101.124 tiles.
Colors
https://www.babylonjs-playground.com/#1ALQPZ#43
Material
https://www.babylonjs-playground.com/#1ALQPZ#44
250.000 tiles.
Colors
https://www.babylonjs-playground.com/#1ALQPZ#45
Material
https://www.babylonjs-playground.com/#1ALQPZ#46
501.264 tiles.
Colors
https://www.babylonjs-playground.com/#1ALQPZ#47
Material
https://www.babylonjs-playground.com/#1ALQPZ#48
1 Million tiles ? View at own risk. Will mostlikely crash on low-end devices ;-)