To start I am taking an approach where I build up the geometry of the sponge in an unoptimized way using the "box" primitive. The locations of each cube element will be stored as a PVector in an ArrayList which we will then be able to iterate through when we render. To update the sponge I will iterate through the arraylist, and for each element determine the location for the 20 elements it will be replaced with.
So here is the Sponge class where all of this will happen:
class Sponge{ //This is a naive implementation of a Menger sponge, using a collection of //cubes to build up the geometry. float size; PVector center; ArrayList<PVector&rt; elements; int MAXLEVEL = 3; int level; Sponge(float size, PVector center){ this.size = size; this.center = center; elements = new ArrayList(); elements.add(center); level = 0; } void divide(){ if (level<MAXLEVEL){ level++; ArrayList<PVector&rt; newElements = new ArrayList(); float newSize = size/3; for(PVector e:elements){ for(int x=-1; x<2; x++){ for(int y=-1; y<2; y++){ for(int z=-1; z<2; z++){ if(!((x==0&&y==0&&z==0)|| (x==-1&&y==0&&z==0)|| (x==0&&y==0&&z==-1)|| (x==0&&y==0&&z==1)|| (x==0&&y==-1&&z==0)|| (x==0&&y==1&&z==0)|| (x==1&&y==0&&z==0))){ newElements.add( new PVector(e.x+x*newSize,e.y+y*newSize,e.z+z*newSize)); } } } } } elements = newElements; size = newSize; } } void draw(){ for(PVector e:elements){ pushMatrix(); noStroke(); fill(64,85,133); translate(e.x, e.y, e.z); box(size); popMatrix(); } } }This class is fairly simple, with only two methods, one divides the sponge so we get the next level of fractal, and the other renders the sponge. In the divide method a new arraylist is created where the locations of all of the new cubes will go. This is then populated by iterating through the current locations, and then for each of those iterating through the possible x, y, and z coordinates where we are subdividing the cube into a 3x3x3 set of cubes. Then the coordinates are checked against the locations we wish to exclude (center cube, and center of each face) and if appropriate add the location to the new arraylist.
One might notice that there is a check in the subdivide class for the maximum level for the sponge. The reason for this is that this is a very inefficient implementation to render. The division is not too bad, however rendering becomes a nightmare since we render 20^level different boxes. A natural optimization of this would be to not render the faces that are hidden from view; where two cubes are next to each other.
No comments:
Post a Comment