class Asteroid{ boolean isDone = false; int noiseSeed; Perlin3D voxelField, textureNoise, terrainNoise, bumpNoise; int voxelComplexity, voxelResolution; float voxelThreshold, voxelScale, voxelNormalDetail, radius; color mareA, mareB, hillA, hillB, specularColor; float bumpScale, bumpDepth; float textureScale; float specularSize, specularMax; int textureComplexity; float terrainScale, terrainContrast, terrainBias; float ambient; // the vector of the infalling light float[] light = { -0.577,-0.577,-0.577}; float[] specular; //----------- Asteroid(){ noiseSeed = 3; voxelResolution = 5; voxelComplexity = 6; voxelThreshold = 0.4; voxelScale = 0.03; voxelNormalDetail = 0.5; radius = 100; textureComplexity = 8; terrainScale = 0.02; textureScale = 0.2; terrainContrast = 0.9; //terrainBias = 0.5; bumpScale = 0.1; bumpDepth = 0.1; specularSize = 0.2; specularMax = 0.5; ambient = 0.4; specularColor = color( #FFDDBB ); mareA = color( #446644 ); mareB = deviateColor( mareA, 16 ); hillA = color( #888888 ); hillB = deviateColor( hillA, 16 ); voxelField = new Perlin3D(voxelScale,voxelComplexity,noiseSeed); terrainNoise = new Perlin3D(terrainScale,textureComplexity,noiseSeed); textureNoise = new Perlin3D(textureScale,textureComplexity,noiseSeed); bumpNoise = new Perlin3D(bumpScale,textureComplexity,noiseSeed); noiseSeed(noiseSeed); calculateSpecular(); } //----------- Asteroid(int seed){ randomSeed(seed); noiseSeed = seed; voxelResolution = 1; voxelComplexity = (int) random(2,5); voxelThreshold = random(0.3,0.6); voxelScale = pow( 0.2, random(2,3) ); voxelNormalDetail = 2; radius = 100; textureComplexity = (int) random(4,8); terrainScale = random(0.01,0.1); textureScale = random(0.01,0.1); terrainContrast = random(0,0.5); //terrainBias = 0.5; bumpScale = pow( 0.1, random(1,2) ); bumpDepth = random(0,1); specularSize = random(0,0.02); specularMax = random(0,0.5); ambient = 0.3; specularColor = deviateColor( #FFFFFF, 32 ); mareA = color( #444444 ); mareB = deviateColor( mareA, 32 ); hillA = color( #999999 ); hillB = deviateColor( hillA, 32 ); voxelField = new Perlin3D(voxelScale,voxelComplexity,noiseSeed); terrainNoise = new Perlin3D(terrainScale,textureComplexity,noiseSeed); textureNoise = new Perlin3D(textureScale,textureComplexity,noiseSeed); bumpNoise = new Perlin3D(bumpScale,textureComplexity,noiseSeed); noiseSeed(noiseSeed); calculateSpecular(); light = normalizedVector(1,-1,-2); } //----------- float[] normalizedVector(float x, float y, float z){ float d = mag(x,y,z); return new float[]{ x/d, y/d, z/d }; } //----------- void calculateSpecular(){ specular = new float[3]; specular[0] = light[0]/2; specular[1] = light[1]/2; specular[2] = (light[2]+1)/2; float magnitude = mag(specular[0], specular[1], specular[2]); specular[0] = specular[0] / magnitude; specular[1] = specular[1] / magnitude; specular[2] = specular[2] / magnitude; } //----------- void render(int[] pixelArray, int w, int h, int supersample, color background){ float pixelWidth = 200.0/w; for( int i=0 ; i0){ for( int si=0 ; si=100 ) return background; else { color pixel; float[] n = surfaceNormal(x,y,z); pixel = terrainColor(x,y,z,n); pixel = addSpecular(x,y,z,n,pixel); return pixel; } } //----------- color randomColor(){ return color( random(255),random(255),random(255) ); } //----------- color deviateColor(color c,int deviation){ float r = constrain(red(c) + random(-deviation,deviation), 0, 255); float g = constrain(green(c) + random(-deviation,deviation), 0, 255); float b = constrain(blue(c) + random(-deviation,deviation), 0, 255); return color( r,g,b ); } //----------- float surfaceIntersect(float x, float y){ for( int z=-100 ; z<100 ; z+=4*voxelResolution ) if( voxel(x,y,z) > voxelThreshold ){ for( ; z>-100 ; z-=voxelResolution ) if( voxel(x,y,z) < voxelThreshold ) return z; return z; } return 100; } //----------- float[] surfaceNormal(float x, float y, float z){ //bump normal float bx,by,bz; if(bumpDepth > 0){ bx = bumpDepth*( bumpNoise.get(x ,y,z) - 0.5 ); by = bumpDepth*( bumpNoise.get(x+10,y,z) - 0.5 ); bz = bumpDepth*( bumpNoise.get(x+20,y,z) - 0.5 ); } else bx = by = bz = 0; //surface normal float h = voxelNormalDetail; float f = voxel(x,y,z); float dx = voxel(x+h,y,z) - f; float dy = voxel(x,y+h,z) - f; float dz = voxel(x,y,z+h) - f; float d = mag(dx,dy,dz); return new float[]{bx-dx/d,by-dy/d,bz-dz/d}; } //----------------------------- color addSpecular(float x, float y, float z, float[] normal, color background){ float specularValue = cosine( specular, normal ); if(specularValue<1-specularSize) return background; float specularBlend = (specularValue-(1-specularSize))/specularSize; return lerpColor( background, specularColor, specularMax*specularBlend ); } //----------------------------- color terrainColor(float x, float y, float z, float[] normal){ float shading = ambient + (1-ambient) * max(0,cosine( light, normal )); return lerpColor( color(0), texture(x,y,z), shading); } //----------------------------- color texture(float x, float y, float z){ noiseDetail( textureComplexity ,0.5); float terrainBlend = contrast( textureNoise.get(x+4711,y,z), terrainContrast ); float textureBlend = textureNoise.get(x,y,z); color c1 = lerpColor(mareA, mareB, textureBlend); color c2 = lerpColor(hillA, hillB, textureBlend); return lerpColor(c1, c2, terrainBlend); } //----------------------------- // Increases the contrast by cubic function float contrast(float x, float contrast){ for(float i=0 ; i0.5+c/2) return 1; else return (x-(0.5-c/2))/c; } //----------------------------- float perlin(float x, float y, float z, float s){ return noise(s*x+10,s*y+20,s*z+30); } //----------------------------- float voxel(float x, float y, float z){ float containmentField = 1 - pow( mag(x,y,z)/radius , 3 ); return containmentField * voxelField.get(x,y,z); } //----------------------------- float dotProduct(float[] a, float[] b){ return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } //----------------------------- float cosine(float[] a, float[] b){ float d = mag(a[0],a[1],a[2]) * mag(b[0],b[1],b[2]); return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) / d; } //----------------------------- float cosine(float[] v, float x, float y, float z){ float d = mag(v[0],v[1],v[2]) * mag(x,y,z); return (v[0]*x + v[1]*y + v[2]*z) / d; } //----------------------------- float[] vector(float x, float y, float z){ return new float[]{x,y,z}; } }