├── Learning shaders ├── WIP_shader_32bit_textures │ ├── WIP_shader_32bit_textures.pde │ └── data │ │ ├── frag.glsl │ │ └── vert.glsl ├── s00_test_texture_to_frag │ ├── data │ │ ├── frag.glsl │ │ └── texture.jpg │ └── s00_test_texture_to_frag.pde ├── s01_shader_to_fbo │ ├── data │ │ └── gradient.glsl │ └── s01_shader_to_fbo.pde ├── s02_shader_to_fbo_to_texture │ ├── data │ │ └── gradient.glsl │ └── s02_shader_to_fbo_to_texture.pde ├── s03_shader_fbo_displace │ ├── data │ │ ├── displaceFrag.glsl │ │ ├── displaceVert.glsl │ │ └── gradient.glsl │ └── s03_shader_fbo_displace.pde ├── s04_shader_fbo_noise_displace │ ├── data │ │ ├── displaceFrag.glsl │ │ ├── displaceVert.glsl │ │ └── noise.glsl │ └── s04_shader_fbo_noise_displace.pde ├── s05a_shader_fbo_noise_displace_packing │ ├── data │ │ ├── displaceFrag.glsl │ │ ├── displaceNoise.glsl │ │ ├── displaceVert.glsl │ │ └── noise.glsl │ └── s05a_shader_fbo_noise_displace_packing.pde ├── s05b_shader_fbo_noise_displace_native │ ├── data │ │ ├── displaceFrag.glsl │ │ ├── displaceVert.glsl │ │ └── noise.glsl │ └── s05b_shader_fbo_noise_displace_native.pde ├── s06_shader_standard_particles │ └── s06_shader_standard_particles.pde ├── s07_shader_custom_particles │ ├── data │ │ ├── frag.glsl │ │ └── vert.glsl │ └── s07_shader_custom_particles.pde ├── s08_shader_many_particles │ ├── data │ │ ├── frag.glsl │ │ └── vert.glsl │ └── s08_shader_many_particles.pde └── s09_shader_many_pointcloud │ ├── data │ ├── frag.glsl │ └── vert.glsl │ └── s09_shader_many_pointcloud.pde ├── aa_AutonomousAgents ├── Agent.pde ├── AutonomousAgents.pde └── FlowField.pde ├── aa_AutonomousAgents3D ├── Agent.pde ├── AutonomousAgents3D.pde └── FlowField.pde ├── aa_ImageBrightness ├── Agent.pde ├── FlowField.pde └── aa_ImageBrightness.pde ├── aa_ImageBrightness_and_backgrondSubstraction ├── Agent.pde ├── FlowField.pde └── aa_ImageBrightness_and_backgrondSubstraction.pde ├── aa_OpticalFlow ├── Agent.pde ├── FlowField.pde └── aa_OpticalFlow.pde ├── basic_3d_rotation └── basic_3d_rotation.pde ├── complexity_gridDemo ├── Grid.pde ├── Particle.pde ├── Quadtree.pde └── complexity_gridDemo.pde ├── complexity_gridOptimization ├── Grid.pde ├── Particle.pde ├── Quadtree.pde ├── background.jpg ├── background1.jpg ├── background2.jpg ├── background3.jpg ├── build-tmp │ ├── repelQuadTreeGravityDebugMode$Particle.class │ ├── repelQuadTreeGravityDebugMode$Quadtree.class │ ├── repelQuadTreeGravityDebugMode.class │ └── source │ │ └── repelQuadTreeGravityDebugMode.java ├── complexity_gridOptimization.pde └── sprite.png ├── complexity_quadTree ├── Grid.pde ├── Particle.pde ├── Quadtree.pde └── complexity_quadTree.pde ├── curves_and_probability └── curves_and_probability.pde ├── delaunay_portraits ├── delaunay_portraits.pde ├── source0.jpg ├── source1.jpg ├── source2.jpg ├── source3.jpg ├── source4.jpg ├── source5.jpg └── source6.jpg ├── particles_attraction_repulsion ├── Particle.pde └── particles_attraction_repulsion.pde ├── particles_magneticFlowField ├── Attractor.pde ├── Field.pde ├── Particle.pde └── particles_magneticFlowField.pde ├── rda_shader ├── data │ ├── grayscott.glsl │ └── render.glsl └── rda_shader.pde ├── readme.md ├── stigmergy ├── Agent.pde ├── Field.pde └── stigmergy.pde ├── stigmergyagents ├── Agent.pde ├── Field.pde ├── palette.jpg └── stigmergyagents.pde ├── verlet_growingRope_mesh ├── build-tmp │ └── source │ │ └── growingRope.java └── verlet_growingRope_mesh.pde └── verlet_sticky_threads ├── Particle.pde ├── Spring.pde ├── StickyString.pde └── verlet_sticky_threads.pde /Learning shaders/WIP_shader_32bit_textures/WIP_shader_32bit_textures.pde: -------------------------------------------------------------------------------- 1 | import java.nio.ByteBuffer; 2 | import java.nio.ByteOrder; 3 | import java.nio.FloatBuffer; 4 | import java.nio.IntBuffer; 5 | 6 | import com.jogamp.opengl.GL; 7 | import com.jogamp.opengl.GL3; 8 | import com.jogamp.opengl.GL2ES2; 9 | 10 | import peasy.*; 11 | 12 | PeasyCam cam; 13 | PShader shader; 14 | 15 | PJOGL pgl; 16 | GL2ES2 gl; 17 | 18 | float[] data; 19 | FloatBuffer dataBuffer; 20 | int[] textId; 21 | 22 | float[] positions; 23 | float[] colors; 24 | float[] uvs; 25 | int[] indices; 26 | 27 | FloatBuffer posBuffer; 28 | FloatBuffer uvsBuffer; 29 | FloatBuffer colorBuffer; 30 | IntBuffer indexBuffer; 31 | 32 | int posVboId; 33 | int colorVboId; 34 | int uvsVboId; 35 | int indexVboId; 36 | 37 | int posLoc; 38 | int colorLoc; 39 | int uvsLoc; 40 | int textLoc; 41 | 42 | void setup(){ 43 | size(800,600,P3D); 44 | cam = new PeasyCam(this, 100); 45 | 46 | 47 | pgl = (PJOGL) beginPGL(); 48 | gl = pgl.gl.getGL2ES2(); 49 | shader = loadShader("frag.glsl","vert.glsl"); 50 | 51 | positions = new float[4*4]; 52 | colors = new float[4*4]; 53 | uvs = new float[4*2]; 54 | indices = new int[4+2]; 55 | 56 | 57 | 58 | posBuffer = allocateDirectFloatBuffer(4*4); 59 | colorBuffer = allocateDirectFloatBuffer(4*4); 60 | uvsBuffer = allocateDirectFloatBuffer(4*2); 61 | indexBuffer = allocateDirectIntBuffer(4+2); 62 | 63 | generateGeometry(); 64 | 65 | // Get GL ids for all the buffers 66 | IntBuffer intBuffer = IntBuffer.allocate(4); 67 | gl.glGenBuffers(4, intBuffer); 68 | posVboId = intBuffer.get(0); 69 | colorVboId = intBuffer.get(1); 70 | uvsVboId = intBuffer.get(2); 71 | indexVboId = intBuffer.get(3); 72 | 73 | 74 | data = new float[512*512*4]; 75 | int i = 0; 76 | for (int x = 0; x<512;x++){ 77 | for (int y = 0; y<512;y++){ 78 | data[i] = x/512.0;; 79 | data[i+1] = y/512.0; 80 | data[i+2] = 3.130; 81 | data[i+3] = 1.0; 82 | i+=4; 83 | } 84 | } 85 | 86 | dataBuffer = allocateDirectFloatBuffer(512*512*4); 87 | dataBuffer.put(data); 88 | dataBuffer.rewind(); 89 | 90 | textId = new int[1]; 91 | gl.glActiveTexture(GL.GL_TEXTURE0); 92 | //gl.glEnable(GL.GL_TEXTURE_2D); 93 | shader.bind(); 94 | 95 | 96 | gl.glGenTextures(1, textId,0); 97 | gl.glBindTexture(GL.GL_TEXTURE_2D, textId[0]); 98 | gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA32F, 512, 512, 0, GL.GL_RGBA, GL.GL_FLOAT, dataBuffer); 99 | 100 | posLoc = gl.glGetAttribLocation(shader.glProgram, "position"); 101 | colorLoc = gl.glGetAttribLocation(shader.glProgram, "color"); 102 | uvsLoc = gl.glGetAttribLocation(shader.glProgram, "uvs"); 103 | textLoc = gl.glGetUniformLocation(shader.glProgram, "texture"); 104 | 105 | 106 | shader.unbind(); 107 | 108 | endPGL(); 109 | 110 | } 111 | 112 | void draw(){ 113 | background(100); 114 | pgl = (PJOGL) beginPGL(); 115 | gl = pgl.gl.getGL2ES2(); 116 | 117 | shader.bind(); 118 | //gl.glEnable(GL.GL_TEXTURE_2D); 119 | gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); 120 | 121 | gl.glBindTexture(GL.GL_TEXTURE_2D,textId[0]); 122 | 123 | gl.glEnableVertexAttribArray(posLoc); 124 | gl.glEnableVertexAttribArray(colorLoc); 125 | gl.glEnableVertexAttribArray(uvsLoc); 126 | gl.glUniform1i(textLoc,0); 127 | 128 | // Copy vertex data to VBOs 129 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, posVboId); 130 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * positions.length, posBuffer, GL.GL_DYNAMIC_DRAW); 131 | gl.glVertexAttribPointer(posLoc, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0); 132 | 133 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colorVboId); 134 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * colors.length, colorBuffer, GL.GL_DYNAMIC_DRAW); 135 | gl.glVertexAttribPointer(colorLoc, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0); 136 | 137 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, uvsVboId); 138 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * uvs.length, uvsBuffer, GL.GL_DYNAMIC_DRAW); 139 | gl.glVertexAttribPointer(uvsLoc, 2, GL.GL_FLOAT, false, 2 * Float.BYTES, 0); 140 | 141 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); 142 | 143 | gl.glBindBuffer(PGL.ELEMENT_ARRAY_BUFFER, indexVboId); 144 | pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, Integer.BYTES * indices.length, indexBuffer, GL.GL_DYNAMIC_DRAW); 145 | gl.glDrawElements(PGL.TRIANGLES, indices.length, GL.GL_UNSIGNED_INT, 0); 146 | gl.glBindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); 147 | 148 | gl.glDisableVertexAttribArray(posLoc); 149 | gl.glDisableVertexAttribArray(colorLoc); 150 | gl.glDisableVertexAttribArray(uvsLoc); 151 | 152 | shader.unbind(); 153 | 154 | endPGL(); 155 | } 156 | 157 | void generateGeometry(){ 158 | // Vertex 1 159 | positions[0] = -200; 160 | positions[1] = -200; 161 | positions[2] = 0; 162 | positions[3] = 1; 163 | 164 | colors[0] = 1.0f; 165 | colors[1] = 1.0f; 166 | colors[2] = 1.0f; 167 | colors[3] = 1.0f; 168 | 169 | // Vertex 2 170 | positions[4] = +200; 171 | positions[5] = -200; 172 | positions[6] = 0; 173 | positions[7] = 1; 174 | 175 | colors[4] = 1.0f; 176 | colors[5] = 1.0f; 177 | colors[6] = 1.0f; 178 | colors[7] = 1.0f; 179 | 180 | // Vertex 3 181 | positions[8] = +200; 182 | positions[9] = +200; 183 | positions[10] = 0; 184 | positions[11] = 1; 185 | 186 | colors[8] = 1.0f; 187 | colors[9] = 1.0f; 188 | colors[10] = 1.0f; 189 | colors[11] = 1.0f; 190 | 191 | // Vertex 4 192 | positions[12] = -200; 193 | positions[13] = +200; 194 | positions[14] = 0; 195 | positions[15] = 1; 196 | 197 | colors[12] = 1.0f; 198 | colors[13] = 1.0f; 199 | colors[14] = 1.0f; 200 | colors[15] = 1.0f; 201 | 202 | //UVS 203 | uvs[0] = 0.0f; 204 | uvs[1] = 0.0f; 205 | 206 | uvs[2] = 1.0f; 207 | uvs[3] = 0.0f; 208 | 209 | uvs[4] = 1.0f; 210 | uvs[5] = 1.0f; 211 | 212 | uvs[6] = 0.0f; 213 | uvs[7] = 1.0f; 214 | 215 | // Triangle 1 216 | indices[0] = 0; 217 | indices[1] = 1; 218 | indices[2] = 2; 219 | 220 | // Triangle 2 221 | indices[3] = 2; 222 | indices[4] = 0; 223 | indices[5] = 3; 224 | 225 | posBuffer.rewind(); 226 | posBuffer.put(positions); 227 | posBuffer.rewind(); 228 | 229 | colorBuffer.rewind(); 230 | colorBuffer.put(colors); 231 | colorBuffer.rewind(); 232 | 233 | uvsBuffer.rewind(); 234 | uvsBuffer.put(uvs); 235 | uvsBuffer.rewind(); 236 | 237 | indexBuffer.rewind(); 238 | indexBuffer.put(indices); 239 | indexBuffer.rewind(); 240 | } 241 | 242 | FloatBuffer allocateDirectFloatBuffer(int n) { 243 | return ByteBuffer.allocateDirect(n * Float.BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 244 | } 245 | 246 | 247 | IntBuffer allocateDirectIntBuffer(int n) { 248 | return ByteBuffer.allocateDirect(n * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer(); 249 | } -------------------------------------------------------------------------------- /Learning shaders/WIP_shader_32bit_textures/data/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform sampler2D texture; 6 | varying vec4 vertColor; 7 | varying vec2 txtCoords; 8 | 9 | void main(void) 10 | 11 | { 12 | 13 | gl_FragColor = texture(texture,txtCoords)*vertColor; 14 | 15 | } -------------------------------------------------------------------------------- /Learning shaders/WIP_shader_32bit_textures/data/vert.glsl: -------------------------------------------------------------------------------- 1 | // vert.glsl 2 | 3 | uniform mat4 transform; 4 | uniform sampler2D texture; 5 | 6 | in vec4 position; 7 | in vec4 color; 8 | in vec2 uvs; 9 | 10 | out vec4 vertColor; 11 | out vec2 txtCoords; 12 | 13 | void main() { 14 | gl_Position = transform * position; 15 | vertColor = color; 16 | txtCoords = uvs; 17 | } -------------------------------------------------------------------------------- /Learning shaders/s00_test_texture_to_frag/data/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform vec2 resolution; 6 | uniform sampler2D texture1; 7 | 8 | void main(void) 9 | 10 | { 11 | 12 | vec2 xy = vec2(gl_FragCoord.x / resolution.x, 1.0-gl_FragCoord.y / resolution.y); 13 | gl_FragColor = texture2D(texture1,xy);; 14 | 15 | } -------------------------------------------------------------------------------- /Learning shaders/s00_test_texture_to_frag/data/texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lignazio/Learning-Processing/ad31aa427ec598c6d983ce09aedbd44ac9bfd59b/Learning shaders/s00_test_texture_to_frag/data/texture.jpg -------------------------------------------------------------------------------- /Learning shaders/s00_test_texture_to_frag/s00_test_texture_to_frag.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Sketch to test the fragment coordinates. 3 | In the fragment shader the upper left corner of the screen isn't (0,0) but (0,1); 4 | so it has to be flipped (see shader code); 5 | 6 | f. shader processing 7 | 0,1--------1,1 0,0--------1,0 8 | | | | | 9 | | | | | 10 | 0,0--------1,0 0,1--------1,1 11 | 12 | Notice: I cannot use the word texture as uniform name, so I used texture1, 13 | maybe the word texture is reserved? 14 | */ 15 | 16 | PImage image; 17 | PShader shader; 18 | 19 | void setup(){ 20 | size(800,600,P3D); 21 | 22 | shader = loadShader("frag.glsl"); 23 | image = loadImage("texture.jpg"); 24 | 25 | shader.set("texture1",image); 26 | shader.set("resolution",float(width),float(height)); 27 | } 28 | 29 | void draw(){ 30 | background(0); 31 | shader(shader); 32 | rect(0,0,width,height); 33 | } -------------------------------------------------------------------------------- /Learning shaders/s01_shader_to_fbo/data/gradient.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform float time; 6 | uniform vec2 resolution; 7 | 8 | 9 | vec4 f = vec4(1.,1.,1.,1.); 10 | 11 | void main(void) 12 | 13 | { 14 | 15 | vec2 c = vec2 (-1.0 + 2.0 * gl_FragCoord.x / resolution.x, 1.0 - 2.0 * gl_FragCoord.y / resolution.y) ; 16 | 17 | float t = time; 18 | f = vec4(c.x*abs(sin(t)), c.y* abs(cos(t)), abs(sin(t/2)), 1.0); 19 | 20 | gl_FragColor = f; 21 | 22 | } -------------------------------------------------------------------------------- /Learning shaders/s01_shader_to_fbo/s01_shader_to_fbo.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Create an fbo object (PShape) and run a shader to render inside the fbo 3 | */ 4 | 5 | PShader shader; 6 | PGraphics fbo; 7 | 8 | void setup(){ 9 | size(800,600,P3D); 10 | 11 | shader=loadShader("gradient.glsl"); 12 | shader.set("resolution",float(512),float(512)); 13 | 14 | fbo = createGraphics(512,512,P2D); 15 | } 16 | 17 | void draw(){ 18 | fbo.beginDraw(); 19 | shader(shader); 20 | shader.set("time",millis()/1000.0); 21 | 22 | rect(0,0,width,height); 23 | resetShader(); 24 | fbo.endDraw(); 25 | 26 | //Show fbo to debug; 27 | image(fbo,0,0); 28 | } -------------------------------------------------------------------------------- /Learning shaders/s02_shader_to_fbo_to_texture/data/gradient.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform float time; 6 | uniform vec2 resolution; 7 | 8 | void main(void) 9 | 10 | { 11 | 12 | vec2 c = vec2 (-1.0 + 2.0 * gl_FragCoord.x / resolution.x, 1.0 - 2.0 * gl_FragCoord.y / resolution.y); 13 | 14 | gl_FragColor = vec4(c.x*abs(sin(time)), c.y* abs(cos(time)), abs(sin(time/2)), 1.0); 15 | 16 | } -------------------------------------------------------------------------------- /Learning shaders/s02_shader_to_fbo_to_texture/s02_shader_to_fbo_to_texture.pde: -------------------------------------------------------------------------------- 1 | /* 2 | How to render a fragment shader inside a fbo object 3 | and then use that fbo as a texture for a 3D plane 4 | 5 | Use the mouse to rotate the view; 6 | */ 7 | 8 | import peasy.*; 9 | 10 | PeasyCam cam; 11 | 12 | PShader shader; 13 | PShape plane; 14 | PGraphics fbo; 15 | 16 | void setup(){ 17 | size(800,600,P3D); 18 | cam = new PeasyCam(this, 200); 19 | 20 | shader=loadShader("gradient.glsl"); 21 | shader.set("resolution",1024.0,1024.0); 22 | 23 | fbo = createGraphics(1024,1024,P2D); 24 | plane = createPlane(); 25 | } 26 | 27 | void draw(){ 28 | background(0); 29 | 30 | shader.set("time",millis()/1000.0); 31 | 32 | //Update the fbo 33 | fbo.beginDraw(); 34 | fbo.shader(shader); 35 | fbo.rect(0,0,fbo.width,fbo.height); 36 | fbo.resetShader(); 37 | fbo.endDraw(); 38 | 39 | //Draw my plane 40 | shape(plane); 41 | } 42 | 43 | PShape createPlane(){ 44 | //use normalized texture coordinates 45 | textureMode(NORMAL); 46 | 47 | //create a plane 48 | PShape mesh = createShape(); 49 | mesh.beginShape(QUADS); 50 | mesh.noStroke(); 51 | mesh.texture(fbo); 52 | 53 | mesh.vertex(-100,-100,0,0,0); //add vertices (X,Y,Z,U,V); 54 | mesh.vertex(100,-100,0,1,0); 55 | mesh.vertex(100,100,0,1,1); 56 | mesh.vertex(-100,100,0,0,1); 57 | mesh.endShape(); 58 | 59 | return mesh; 60 | } -------------------------------------------------------------------------------- /Learning shaders/s03_shader_fbo_displace/data/displaceFrag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | precision mediump int; 4 | #endif 5 | 6 | uniform sampler2D texture; 7 | 8 | varying vec4 vertColor; 9 | varying vec4 vertTexCoord; 10 | 11 | void main() { 12 | gl_FragColor = texture2D(texture, vertTexCoord.st) * vertColor; 13 | } -------------------------------------------------------------------------------- /Learning shaders/s03_shader_fbo_displace/data/displaceVert.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | uniform mat4 transform; 4 | uniform mat4 texMatrix; 5 | 6 | attribute vec4 vertex; 7 | attribute vec4 color; 8 | attribute vec3 normal; 9 | attribute vec2 texCoord; 10 | 11 | varying vec4 vertColor; 12 | varying vec4 vertTexCoord; 13 | 14 | uniform sampler2D texture; 15 | float scale = 200.0; 16 | 17 | void main() { 18 | 19 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 20 | 21 | vec4 dv = texture2D( texture, vertTexCoord.st ); //Get the pixel on the texture; 22 | 23 | //render the vertices with an offset to the center and a scale; 24 | vec4 newVertexPos = vec4((dv.x-0.5)*scale,(dv.y-0.5)*scale,(dv.z-0.5)*scale,1.0); 25 | 26 | gl_Position = transform * newVertexPos; 27 | 28 | vertColor = color; 29 | vertTexCoord = vertTexCoord; 30 | } -------------------------------------------------------------------------------- /Learning shaders/s03_shader_fbo_displace/data/gradient.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | #define M_PI 3.1415926535897932384626433832795 5 | 6 | uniform float time; 7 | uniform vec2 resolution; 8 | 9 | void main(void) 10 | 11 | { 12 | 13 | vec2 st = gl_FragCoord.xy/resolution.xy; 14 | 15 | gl_FragColor = vec4(st.x,st.y,0.5*abs(cos(st.x*M_PI+time)*sin(st.y*M_PI+time)),1.0); 16 | 17 | } -------------------------------------------------------------------------------- /Learning shaders/s03_shader_fbo_displace/s03_shader_fbo_displace.pde: -------------------------------------------------------------------------------- 1 | /* 2 | How to render a shader into an fbo and then use that fbo as a texture 3 | for a second shader. 4 | The second shader takes the values from the texture and apply a displace 5 | to each vertices according to the colors of the texture. 6 | */ 7 | 8 | import peasy.*; 9 | 10 | PeasyCam cam; 11 | 12 | PShader shader; 13 | PShader displace; 14 | PShape plane; 15 | PGraphics fbo; 16 | 17 | 18 | 19 | void setup(){ 20 | size(800,600,P3D); 21 | cam = new PeasyCam(this, 200); 22 | 23 | shader=loadShader("gradient.glsl"); 24 | displace=loadShader("displaceFrag.glsl","displaceVert.glsl"); 25 | 26 | shader.set("resolution",512.0,512.0); 27 | 28 | fbo = createGraphics(512,512,P2D); 29 | plane = createPlane(64,64,200); //x segments,y segments, size 30 | } 31 | 32 | void draw(){ 33 | background(0); 34 | 35 | shader.set("time",millis()/1000.0); 36 | 37 | 38 | //Update the fbo 39 | fbo.beginDraw(); 40 | fbo.shader(shader); 41 | fbo.rect(0,0,fbo.width,fbo.height); 42 | fbo.resetShader(); 43 | fbo.endDraw(); 44 | 45 | //Draw my plane 46 | shader(displace); 47 | shape(plane); 48 | } 49 | 50 | 51 | 52 | //Function to create a plane of quads; 53 | PShape createPlane(int rows,int cols, float size){ 54 | //Arraylists to store positions and uv coordinates of each vertex; 55 | ArrayList positions = new ArrayList(); 56 | ArrayList uvs = new ArrayList(); 57 | float u,v; 58 | float uSize = 1/(float)rows; 59 | float vSize = 1/(float)cols; 60 | 61 | //Put data inside the arraylists 62 | for (int x=0; x 1D wrapping 50 | float n = dot(i, step); 51 | 52 | vec3 u = f * f * (3.0 - 2.0 * f); 53 | return mix(mix(mix( hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x), 54 | mix( hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y), 55 | mix(mix( hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x), 56 | mix( hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); 57 | } 58 | 59 | float fbm(float x) { 60 | float v = 0.0; 61 | float a = 0.5; 62 | float shift = float(100); 63 | for (int i = 0; i < NUM_OCTAVES; ++i) { 64 | v += a * noise(x); 65 | x = x * 2.0 + shift; 66 | a *= 0.5; 67 | } 68 | return v; 69 | } 70 | 71 | 72 | float fbm(vec2 x) { 73 | float v = 0.0; 74 | float a = 0.5; 75 | vec2 shift = vec2(100); 76 | // Rotate to reduce axial bias 77 | mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50)); 78 | for (int i = 0; i < NUM_OCTAVES; ++i) { 79 | v += a * noise(x); 80 | x = rot * x * 2.0 + shift; 81 | a *= 0.5; 82 | } 83 | return v; 84 | } 85 | 86 | 87 | float fbm(vec3 x) { 88 | float v = 0.0; 89 | float a = 0.5; 90 | vec3 shift = vec3(100); 91 | for (int i = 0; i < NUM_OCTAVES; ++i) { 92 | v += a * noise(x); 93 | x = x * 2.0 + shift; 94 | a *= 0.5; 95 | } 96 | return v; 97 | } 98 | void main(void) 99 | 100 | { 101 | 102 | vec2 st = gl_FragCoord.xy/resolution.xy; 103 | float cx = fbm(vec3(st,time/10.0)); 104 | float cy = fbm(vec3(st,100+time/10.0)); 105 | float cz = fbm(vec3(st,200+time/10.0)); 106 | //float c = POWER*fbm( SCALE*p ) + BIAS; 107 | gl_FragColor = vec4(cx,cy,cz,1.0); 108 | 109 | } -------------------------------------------------------------------------------- /Learning shaders/s04_shader_fbo_noise_displace/s04_shader_fbo_noise_displace.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Same concept as before but uses a more complex shader to compute a fractal noise 3 | into the fbo. 4 | */ 5 | 6 | import peasy.*; 7 | 8 | PeasyCam cam; 9 | 10 | PShader shader; 11 | PShader displace; 12 | PShape plane; 13 | PGraphics fbo; 14 | 15 | float planeSize = 200.0; 16 | 17 | void setup(){ 18 | size(800,600,P3D); 19 | cam = new PeasyCam(this, 200); 20 | 21 | shader=loadShader("noise.glsl"); 22 | displace=loadShader("displaceFrag.glsl","displaceVert.glsl"); 23 | 24 | shader.set("resolution",512.0,512.0); 25 | displace.set("pscale",planeSize); 26 | fbo = createGraphics(512,512,P2D); 27 | plane = createPlane(64,64,200.0);//try 512*512 = 262144 points 28 | } 29 | 30 | void draw(){ 31 | background(0); 32 | 33 | shader.set("time",millis()/1000.0); 34 | 35 | //Update the fbo 36 | fbo.beginDraw(); 37 | fbo.shader(shader); 38 | fbo.rect(0,0,fbo.width,fbo.height); 39 | fbo.resetShader(); 40 | fbo.endDraw(); 41 | //Show fbo for debug 42 | //image(fbo,0,0); 43 | 44 | //Draw my plane 45 | shader(displace); 46 | shape(plane); 47 | } 48 | 49 | PShape createPlane(int rows,int cols, float size){ 50 | ArrayList positions = new ArrayList(); 51 | ArrayList uvs = new ArrayList(); 52 | float u,v; 53 | float uSize = 1/(float)rows; 54 | float vSize = 1/(float)cols; 55 | 56 | for (int x=0; x 1D wrapping 51 | float n = dot(i, step); 52 | 53 | vec3 u = f * f * (3.0 - 2.0 * f); 54 | return mix(mix(mix( hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x), 55 | mix( hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y), 56 | mix(mix( hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x), 57 | mix( hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); 58 | } 59 | 60 | float fbm(float x) { 61 | float v = 0.0; 62 | float a = 0.5; 63 | float shift = float(100); 64 | for (int i = 0; i < NUM_OCTAVES; ++i) { 65 | v += a * noise(x); 66 | x = x * 2.0 + shift; 67 | a *= 0.5; 68 | } 69 | return v; 70 | } 71 | 72 | 73 | float fbm(vec2 x) { 74 | float v = 0.0; 75 | float a = 0.5; 76 | vec2 shift = vec2(100); 77 | // Rotate to reduce axial bias 78 | mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50)); 79 | for (int i = 0; i < NUM_OCTAVES; ++i) { 80 | v += a * noise(x); 81 | x = rot * x * 2.0 + shift; 82 | a *= 0.5; 83 | } 84 | return v; 85 | } 86 | 87 | 88 | float fbm(vec3 x) { 89 | float v = 0.0; 90 | float a = 0.5; 91 | vec3 shift = vec3(100); 92 | for (int i = 0; i < NUM_OCTAVES; ++i) { 93 | v += a * noise(x); 94 | x = x * 2.0 + shift; 95 | a *= 0.5; 96 | } 97 | return v; 98 | } 99 | 100 | 101 | 102 | //Functions to encode and decode values 103 | // 32bit float <----> rgba 104 | 105 | vec3 encodeFloatToVec3( const in float f ) { 106 | vec3 color; 107 | color.b = floor(f / 255.0 / 255.0); 108 | color.g = floor( (f - (color.b * 255.0 * 255.0) ) / 255.0 ); 109 | color.r = floor( f - (color.b * 255.0 * 255.0) - (color.g * 255.0) ); 110 | 111 | 112 | // color.rgb are in range 0:255, but GLSL 113 | // buffer needs values in 0:1 range. 114 | // Divide through by 255. 115 | return (color/255.0); 116 | } 117 | 118 | 119 | // This function has an extra *255 for RGB compared 120 | // to the processing sketch because GLSL operates RGB 121 | // in the 0:1 range, processing in 0:255 122 | float decodeVec3ToFloat( vec3 color) { 123 | float result; 124 | result = float(color.r * 255.0); 125 | result += float(color.g * 255.0 * 255.0 ); 126 | result += float(color.b * 255.0 * 255.0 * 255.0); 127 | return result; 128 | } 129 | void main(void) 130 | 131 | { 132 | 133 | vec2 st = gl_FragCoord.xy/resolution.xy; 134 | float c = fbm(vec3(st+offset,time/10.0))*16777216.0; 135 | 136 | //float c = POWER*fbm( SCALE*p ) + BIAS; 137 | gl_FragColor = vec4(encodeFloatToVec3(c),1.0); 138 | 139 | } -------------------------------------------------------------------------------- /Learning shaders/s05a_shader_fbo_noise_displace_packing/data/displaceVert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision highp float; 3 | #endif 4 | 5 | uniform mat4 transform; 6 | uniform mat4 texMatrix; 7 | 8 | attribute vec4 vertex; 9 | attribute vec4 color; 10 | attribute vec3 normal; 11 | attribute vec2 texCoord; 12 | 13 | varying vec4 vertColor; 14 | varying vec4 vertTexCoord; 15 | 16 | uniform sampler2D texture; 17 | uniform sampler2D texturex; 18 | uniform sampler2D texturey; 19 | uniform sampler2D texturez; 20 | uniform float pscale; 21 | 22 | 23 | //Functions to encode and decode values 24 | // 32bit float <----> rgba 25 | 26 | vec3 encodeFloatToVec3( const in float f ) { 27 | vec3 color; 28 | color.b = floor(f / 255.0 / 255.0); 29 | color.g = floor( (f - (color.b * 255.0 * 255.0) ) / 255.0 ); 30 | color.r = floor( f - (color.b * 255.0 * 255.0) - (color.g * 255.0) ); 31 | 32 | 33 | // color.rgb are in range 0:255, but GLSL 34 | // buffer needs values in 0:1 range. 35 | // Divide through by 255. 36 | return (color/255.0); 37 | } 38 | 39 | 40 | // This function has an extra *255 for RGB compared 41 | // to the processing sketch because GLSL operates RGB 42 | // in the 0:1 range, processing in 0:255 43 | float decodeVec3ToFloat( vec3 color) { 44 | float result; 45 | result = float(color.r * 255.0); 46 | result += float(color.g * 255.0 * 255.0 ); 47 | result += float(color.b * 255.0 * 255.0 * 255.0); 48 | return result; 49 | } 50 | 51 | 52 | void main() { 53 | 54 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 55 | 56 | vec4 dv = texture2D( texture, vertTexCoord.st ); 57 | vec4 dvx = texture2D( texturex, vertTexCoord.st ); 58 | vec4 dvy = texture2D( texturey, vertTexCoord.st ); 59 | vec4 dvz = texture2D( texturez, vertTexCoord.st ); 60 | 61 | float valuex = decodeVec3ToFloat(dvx.xyz)/16777216.0; 62 | float valuey = decodeVec3ToFloat(dvy.xyz)/16777216.0; 63 | float valuez = decodeVec3ToFloat(dvz.xyz)/16777216.0; 64 | 65 | vec4 newVertexPos = vec4((valuex-0.5)*pscale,(valuey-0.5)*pscale,(valuez-0.5)*pscale,1.0); 66 | //vec4 newVertexPos = vec4(vertex.x,vertex.y,(valuez-0.5)*pscale,1.0); 67 | 68 | gl_Position = transform * newVertexPos; 69 | vertColor = color; 70 | 71 | } -------------------------------------------------------------------------------- /Learning shaders/s05a_shader_fbo_noise_displace_packing/data/noise.glsl: -------------------------------------------------------------------------------- 1 | //Based on this code: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | #define NUM_OCTAVES 4 6 | 7 | uniform float time; 8 | 9 | uniform vec2 resolution; 10 | 11 | float hash(float n) { return fract(sin(n) * 1e4); } 12 | float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } 13 | 14 | float noise(float x) { 15 | float i = floor(x); 16 | float f = fract(x); 17 | float u = f * f * (3.0 - 2.0 * f); 18 | return mix(hash(i), hash(i + 1.0), u); 19 | } 20 | 21 | float noise(vec2 x) { 22 | vec2 i = floor(x); 23 | vec2 f = fract(x); 24 | 25 | // Four corners in 2D of a tile 26 | float a = hash(i); 27 | float b = hash(i + vec2(1.0, 0.0)); 28 | float c = hash(i + vec2(0.0, 1.0)); 29 | float d = hash(i + vec2(1.0, 1.0)); 30 | 31 | // Simple 2D lerp using smoothstep envelope between the values. 32 | // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), 33 | // mix(c, d, smoothstep(0.0, 1.0, f.x)), 34 | // smoothstep(0.0, 1.0, f.y))); 35 | 36 | // Same code, with the clamps in smoothstep and common subexpressions 37 | // optimized away. 38 | vec2 u = f * f * (3.0 - 2.0 * f); 39 | return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; 40 | } 41 | 42 | // This one has non-ideal tiling properties that I'm still tuning 43 | float noise(vec3 x) { 44 | const vec3 step = vec3(110, 241, 171); 45 | 46 | vec3 i = floor(x); 47 | vec3 f = fract(x); 48 | 49 | // For performance, compute the base input to a 1D hash from the integer part of the argument and the 50 | // incremental change to the 1D based on the 3D -> 1D wrapping 51 | float n = dot(i, step); 52 | 53 | vec3 u = f * f * (3.0 - 2.0 * f); 54 | return mix(mix(mix( hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x), 55 | mix( hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y), 56 | mix(mix( hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x), 57 | mix( hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); 58 | } 59 | 60 | float fbm(float x) { 61 | float v = 0.0; 62 | float a = 0.5; 63 | float shift = float(100); 64 | for (int i = 0; i < NUM_OCTAVES; ++i) { 65 | v += a * noise(x); 66 | x = x * 2.0 + shift; 67 | a *= 0.5; 68 | } 69 | return v; 70 | } 71 | 72 | 73 | float fbm(vec2 x) { 74 | float v = 0.0; 75 | float a = 0.5; 76 | vec2 shift = vec2(100); 77 | // Rotate to reduce axial bias 78 | mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50)); 79 | for (int i = 0; i < NUM_OCTAVES; ++i) { 80 | v += a * noise(x); 81 | x = rot * x * 2.0 + shift; 82 | a *= 0.5; 83 | } 84 | return v; 85 | } 86 | 87 | 88 | float fbm(vec3 x) { 89 | float v = 0.0; 90 | float a = 0.5; 91 | vec3 shift = vec3(100); 92 | for (int i = 0; i < NUM_OCTAVES; ++i) { 93 | v += a * noise(x); 94 | x = x * 2.0 + shift; 95 | a *= 0.5; 96 | } 97 | return v; 98 | } 99 | 100 | 101 | 102 | 103 | 104 | void main(void) 105 | 106 | { 107 | 108 | vec2 st = gl_FragCoord.xy/resolution.xy; 109 | float cx = fbm(vec3(st+0,time/10.0)); 110 | float cy = fbm(vec3(st+100.0,time/10.0)); 111 | float cz = fbm(vec3(st+200.0,time/10.0)); 112 | //float c = POWER*fbm( SCALE*p ) + BIAS; 113 | gl_FragColor = vec4(cx,cy,cz,1.0); 114 | 115 | } -------------------------------------------------------------------------------- /Learning shaders/s05a_shader_fbo_noise_displace_packing/s05a_shader_fbo_noise_displace_packing.pde: -------------------------------------------------------------------------------- 1 | /* 2 | The shaders now encode and decode a float value to RGBA. 3 | This technique allows to keep precision. 4 | In order to achieve that I used 3 more textures 5 | Each texture takes care of one axis 6 | */ 7 | 8 | import peasy.*; 9 | 10 | PeasyCam cam; 11 | 12 | PShader shader,dispx,dispy,dispz; 13 | PShader displace; 14 | PShape plane; 15 | PGraphics fbo,fbox,fboy,fboz; 16 | 17 | float planeSize = 200.0; 18 | 19 | void setup(){ 20 | size(800,600,P3D); 21 | cam = new PeasyCam(this, 200); 22 | shader=loadShader("noise.glsl"); 23 | dispx=loadShader("displaceNoise.glsl"); 24 | dispy=loadShader("displaceNoise.glsl"); 25 | dispz=loadShader("displaceNoise.glsl"); 26 | displace=loadShader("displaceFrag.glsl","displaceVert.glsl"); 27 | 28 | shader.set("resolution",512.0,512.0); 29 | dispx.set("resolution",512.0,512.0); 30 | dispx.set("offset",0.0); 31 | dispy.set("resolution",512.0,512.0); 32 | dispy.set("offset",100.0); 33 | dispz.set("resolution",512.0,512.0); 34 | dispz.set("offset",200.0); 35 | 36 | displace.set("pscale",planeSize); 37 | fbo = createGraphics(512,512,P2D); 38 | fbox = createGraphics(512,512,P2D); 39 | fboy = createGraphics(512,512,P2D); 40 | fboz = createGraphics(512,512,P2D); 41 | plane = createPlane(512,512,200.0);//try 512*512 = 262144 points 42 | 43 | ((PGraphicsOpenGL)g).textureSampling(2); 44 | } 45 | 46 | void draw(){ 47 | background(50); 48 | 49 | shader.set("time",millis()/1000.0); 50 | dispx.set("time",millis()/1000.0); 51 | dispy.set("time",millis()/1000.0); 52 | dispz.set("time",millis()/1000.0); 53 | 54 | //Update the fbos 55 | fbo.beginDraw(); 56 | fbo.shader(shader); 57 | fbo.rect(0,0,fbo.width,fbo.height); 58 | fbo.resetShader(); 59 | fbo.endDraw(); 60 | 61 | fbox.beginDraw(); 62 | fbox.shader(dispx); 63 | fbox.rect(0,0,fbox.width,fbox.height); 64 | fbox.resetShader(); 65 | fbox.endDraw(); 66 | 67 | fboy.beginDraw(); 68 | fboy.shader(dispy); 69 | fboy.rect(0,0,fboy.width,fboz.height); 70 | fboy.resetShader(); 71 | fboy.endDraw(); 72 | 73 | fboz.beginDraw(); 74 | fboz.shader(dispz); 75 | fboz.rect(0,0,fboz.width,fboz.height); 76 | fboz.resetShader(); 77 | fboz.endDraw(); 78 | //Show fbo for debug 79 | //image(fboy,0,0); 80 | 81 | displace.set("texturex",fbox); 82 | displace.set("texturey",fboy); 83 | displace.set("texturez",fboz); 84 | //Draw my plane 85 | shader(displace); 86 | shape(plane); 87 | } 88 | 89 | PShape createPlane(int rows,int cols, float size){ 90 | ArrayList positions = new ArrayList(); 91 | ArrayList uvs = new ArrayList(); 92 | float u,v; 93 | float uSize = 1/(float)rows; 94 | float vSize = 1/(float)cols; 95 | 96 | for (int x=0; x 1D wrapping 62 | float n = dot(i, step); 63 | 64 | vec3 u = f * f * (3.0 - 2.0 * f); 65 | return mix(mix(mix( hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x), 66 | mix( hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y), 67 | mix(mix( hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x), 68 | mix( hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); 69 | } 70 | 71 | float fbm(float x) { 72 | float v = 0.0; 73 | float a = 0.5; 74 | float shift = float(100); 75 | for (int i = 0; i < NUM_OCTAVES; ++i) { 76 | v += a * noise(x); 77 | x = x * 2.0 + shift; 78 | a *= 0.5; 79 | } 80 | return v; 81 | } 82 | 83 | 84 | float fbm(vec2 x) { 85 | float v = 0.0; 86 | float a = 0.5; 87 | vec2 shift = vec2(100); 88 | // Rotate to reduce axial bias 89 | mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50)); 90 | for (int i = 0; i < NUM_OCTAVES; ++i) { 91 | v += a * noise(x); 92 | x = rot * x * 2.0 + shift; 93 | a *= 0.5; 94 | } 95 | return v; 96 | } 97 | 98 | 99 | float fbm(vec3 x) { 100 | float v = 0.0; 101 | float a = 0.5; 102 | vec3 shift = vec3(100); 103 | for (int i = 0; i < NUM_OCTAVES; ++i) { 104 | v += a * noise(x); 105 | x = x * 2.0 + shift; 106 | a *= 0.5; 107 | } 108 | return v; 109 | } 110 | 111 | 112 | 113 | 114 | void main() { 115 | 116 | vertTexCoord = texMatrix * vec4(texCoord, 1.0, 1.0); 117 | 118 | vec4 dv = texture2D( texture, vertTexCoord.st ); 119 | float valuex = fbm(vec3(vertTexCoord.st+0,time/10.0)); 120 | float valuey = fbm(vec3(vertTexCoord.st+100.0,time/10.0)); 121 | float valuez = fbm(vec3(vertTexCoord.st+200.0,time/10.0)); 122 | 123 | vec4 newVertexPos = vec4((valuex-0.5)*pscale,(valuey-0.5)*pscale,(valuez-0.5)*pscale,1.0); 124 | 125 | gl_Position = transform * newVertexPos; 126 | 127 | vertColor = color; 128 | } -------------------------------------------------------------------------------- /Learning shaders/s05b_shader_fbo_noise_displace_native/data/noise.glsl: -------------------------------------------------------------------------------- 1 | //Based on this code: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | #define NUM_OCTAVES 4 6 | 7 | uniform float time; 8 | 9 | uniform vec2 resolution; 10 | 11 | float hash(float n) { return fract(sin(n) * 1e4); } 12 | float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } 13 | 14 | float noise(float x) { 15 | float i = floor(x); 16 | float f = fract(x); 17 | float u = f * f * (3.0 - 2.0 * f); 18 | return mix(hash(i), hash(i + 1.0), u); 19 | } 20 | 21 | float noise(vec2 x) { 22 | vec2 i = floor(x); 23 | vec2 f = fract(x); 24 | 25 | // Four corners in 2D of a tile 26 | float a = hash(i); 27 | float b = hash(i + vec2(1.0, 0.0)); 28 | float c = hash(i + vec2(0.0, 1.0)); 29 | float d = hash(i + vec2(1.0, 1.0)); 30 | 31 | // Simple 2D lerp using smoothstep envelope between the values. 32 | // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), 33 | // mix(c, d, smoothstep(0.0, 1.0, f.x)), 34 | // smoothstep(0.0, 1.0, f.y))); 35 | 36 | // Same code, with the clamps in smoothstep and common subexpressions 37 | // optimized away. 38 | vec2 u = f * f * (3.0 - 2.0 * f); 39 | return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; 40 | } 41 | 42 | // This one has non-ideal tiling properties that I'm still tuning 43 | float noise(vec3 x) { 44 | const vec3 step = vec3(110, 241, 171); 45 | 46 | vec3 i = floor(x); 47 | vec3 f = fract(x); 48 | 49 | // For performance, compute the base input to a 1D hash from the integer part of the argument and the 50 | // incremental change to the 1D based on the 3D -> 1D wrapping 51 | float n = dot(i, step); 52 | 53 | vec3 u = f * f * (3.0 - 2.0 * f); 54 | return mix(mix(mix( hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x), 55 | mix( hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y), 56 | mix(mix( hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x), 57 | mix( hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); 58 | } 59 | 60 | float fbm(float x) { 61 | float v = 0.0; 62 | float a = 0.5; 63 | float shift = float(100); 64 | for (int i = 0; i < NUM_OCTAVES; ++i) { 65 | v += a * noise(x); 66 | x = x * 2.0 + shift; 67 | a *= 0.5; 68 | } 69 | return v; 70 | } 71 | 72 | 73 | float fbm(vec2 x) { 74 | float v = 0.0; 75 | float a = 0.5; 76 | vec2 shift = vec2(100); 77 | // Rotate to reduce axial bias 78 | mat2 rot = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.50)); 79 | for (int i = 0; i < NUM_OCTAVES; ++i) { 80 | v += a * noise(x); 81 | x = rot * x * 2.0 + shift; 82 | a *= 0.5; 83 | } 84 | return v; 85 | } 86 | 87 | 88 | float fbm(vec3 x) { 89 | float v = 0.0; 90 | float a = 0.5; 91 | vec3 shift = vec3(100); 92 | for (int i = 0; i < NUM_OCTAVES; ++i) { 93 | v += a * noise(x); 94 | x = x * 2.0 + shift; 95 | a *= 0.5; 96 | } 97 | return v; 98 | } 99 | 100 | 101 | 102 | 103 | 104 | void main(void) 105 | 106 | { 107 | 108 | vec2 st = gl_FragCoord.xy/resolution.xy; 109 | float cx = fbm(vec3(st+0,time/10.0)); 110 | float cy = fbm(vec3(st+100.0,time/10.0)); 111 | float cz = fbm(vec3(st+200.0,time/10.0)); 112 | //float c = POWER*fbm( SCALE*p ) + BIAS; 113 | gl_FragColor = vec4(cx,cy,cz,1.0); 114 | 115 | } -------------------------------------------------------------------------------- /Learning shaders/s05b_shader_fbo_noise_displace_native/s05b_shader_fbo_noise_displace_native.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Debug sketch to make a comparison between 3 | native 32bit values of this sketch 4 | and the packing technique of previous example 5 | */ 6 | 7 | import peasy.*; 8 | 9 | PeasyCam cam; 10 | 11 | PShader shader; 12 | PShader displace; 13 | PShape plane; 14 | PGraphics fbo; 15 | 16 | float planeSize = 200.0; 17 | 18 | void setup(){ 19 | size(800,600,P3D); 20 | cam = new PeasyCam(this, 200); 21 | 22 | shader=loadShader("noise.glsl"); 23 | displace=loadShader("displaceFrag.glsl","displaceVert.glsl"); 24 | 25 | shader.set("resolution",512.0,512.0); 26 | 27 | 28 | displace.set("pscale",planeSize); 29 | fbo = createGraphics(512,512,P2D); 30 | plane = createPlane(512,512,200.0);//try 512*512 = 262144 points 31 | } 32 | 33 | void draw(){ 34 | background(50); 35 | 36 | shader.set("time",millis()/1000.0); 37 | displace.set("time",millis()/1000.0); 38 | //Update the fbos 39 | fbo.beginDraw(); 40 | fbo.shader(shader); 41 | fbo.rect(0,0,fbo.width,fbo.height); 42 | fbo.resetShader(); 43 | fbo.endDraw(); 44 | 45 | 46 | //Show fbo for debug 47 | //image(fbo,0,0); 48 | 49 | //Draw my plane 50 | shader(displace); 51 | shape(plane); 52 | } 53 | 54 | PShape createPlane(int rows,int cols, float size){ 55 | ArrayList positions = new ArrayList(); 56 | ArrayList uvs = new ArrayList(); 57 | float u,v; 58 | float uSize = 1/(float)rows; 59 | float vSize = 1/(float)cols; 60 | 61 | for (int x=0; x 0.5) { 12 | discard; 13 | } 14 | fragColor = vertColor; 15 | } -------------------------------------------------------------------------------- /Learning shaders/s08_shader_many_particles/data/vert.glsl: -------------------------------------------------------------------------------- 1 | // vert.glsl 2 | #version 330 3 | 4 | uniform mat4 transform; 5 | 6 | in vec4 position; 7 | in vec4 color; 8 | in float size; 9 | 10 | out vec4 vertColor; 11 | 12 | void main() { 13 | 14 | gl_Position = transform * position; 15 | gl_PointSize = 100.0*size / gl_Position.w; 16 | vertColor = color; 17 | } -------------------------------------------------------------------------------- /Learning shaders/s08_shader_many_particles/s08_shader_many_particles.pde: -------------------------------------------------------------------------------- 1 | /* 2 | This sketch uses native jogl calls and a custom shader 3 | to render one million particles. 4 | 5 | This runs much faster than native point shader because 6 | the custom shader uses only one vertex for each particles 7 | 8 | The code is based on: https://github.com/processing/processing/wiki/Advanced-OpenGL 9 | */ 10 | 11 | //Import java libraries 12 | import java.nio.ByteBuffer; 13 | import java.nio.ByteOrder; 14 | import java.nio.FloatBuffer; 15 | import java.nio.IntBuffer; 16 | 17 | import com.jogamp.opengl.GL; 18 | import com.jogamp.opengl.GL3; 19 | import com.jogamp.opengl.GL2ES2; 20 | 21 | //import peasycam to interact with the scene 22 | import peasy.*; 23 | 24 | PeasyCam cam; 25 | 26 | PShader shader; 27 | float a; 28 | 29 | // declare processing gl and standard gl objects 30 | PJOGL pgl; 31 | GL2ES2 gl; 32 | 33 | int nop = 1000000; //set the number of particles 34 | 35 | //declare arrays to store position,color, size and index of each particles 36 | float[] positions; 37 | float[] colors; 38 | float[] sizes; 39 | int[] indices; 40 | 41 | //declare buffers to contain each of the data; 42 | FloatBuffer posBuffer; 43 | FloatBuffer colorBuffer; 44 | FloatBuffer sizeBuffer; 45 | IntBuffer indexBuffer; 46 | 47 | //Integers to store and id for each buffer 48 | int posVboId; 49 | int colorVboId; 50 | int sizeVboId; 51 | int indexVboId; 52 | //Integers to store each attribute 53 | int posLoc; 54 | int colorLoc; 55 | int sizeLoc; 56 | 57 | PVector randomPos; 58 | float x, y, z; 59 | float noiseScale = 50; 60 | 61 | void setup() { 62 | size(800, 600, P3D); 63 | pixelDensity(2); 64 | cam = new PeasyCam(this, 100); 65 | shader = loadShader("frag.glsl", "vert.glsl"); 66 | 67 | //create arrays 68 | //note: positions and colors contain 4 values for each particles 69 | //positions: x,y,z,w 70 | //colors: r,g,b,a, 71 | positions = new float[nop*4]; 72 | colors = new float[nop*4]; 73 | sizes = new float[nop]; 74 | indices = new int[nop]; 75 | 76 | //function to generate particles and store each attribute inside the arrays 77 | generateParticles(); 78 | 79 | //allocate space for the buffers to be passed on the opengl call 80 | posBuffer = allocateDirectFloatBuffer(nop*4); 81 | colorBuffer = allocateDirectFloatBuffer(nop*4); 82 | sizeBuffer = allocateDirectFloatBuffer(nop); 83 | indexBuffer = allocateDirectIntBuffer(nop); 84 | 85 | //fill each buffer with data 86 | posBuffer.put(positions); 87 | posBuffer.rewind(); 88 | 89 | colorBuffer.put(colors); 90 | colorBuffer.rewind(); 91 | 92 | sizeBuffer.put(sizes); 93 | sizeBuffer.rewind(); 94 | 95 | indexBuffer.put(indices); 96 | indexBuffer.rewind(); 97 | 98 | pgl = (PJOGL) beginPGL(); 99 | gl = pgl.gl.getGL2ES2(); 100 | 101 | // Get GL ids for all the buffers 102 | IntBuffer intBuffer = IntBuffer.allocate(4); 103 | gl.glGenBuffers(4, intBuffer); 104 | posVboId = intBuffer.get(0); 105 | colorVboId = intBuffer.get(1); 106 | sizeVboId = intBuffer.get(2); 107 | indexVboId = intBuffer.get(3); 108 | 109 | // get an unique id for each attribute 110 | shader.bind(); 111 | posLoc = gl.glGetAttribLocation(shader.glProgram, "position"); 112 | colorLoc = gl.glGetAttribLocation(shader.glProgram, "color"); 113 | sizeLoc = gl.glGetAttribLocation(shader.glProgram, "size"); 114 | shader.unbind(); 115 | 116 | endPGL(); 117 | } 118 | 119 | void draw() { 120 | background(10); 121 | pgl = (PJOGL) beginPGL(); 122 | gl = pgl.gl.getGL2ES2(); 123 | 124 | shader.bind(); 125 | 126 | // enable attributes 127 | gl.glEnableVertexAttribArray(posLoc); 128 | gl.glEnableVertexAttribArray(colorLoc); 129 | gl.glEnableVertexAttribArray(sizeLoc); 130 | 131 | // Copy vertex data to VBOs 132 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, posVboId); 133 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * positions.length, posBuffer, GL.GL_DYNAMIC_DRAW); 134 | gl.glVertexAttribPointer(posLoc, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0); 135 | 136 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colorVboId); 137 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * colors.length, colorBuffer, GL.GL_DYNAMIC_DRAW); 138 | gl.glVertexAttribPointer(colorLoc, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0); 139 | 140 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, sizeVboId); 141 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * sizes.length, sizeBuffer, GL.GL_DYNAMIC_DRAW); 142 | gl.glVertexAttribPointer(sizeLoc, 1, GL.GL_FLOAT, false, 1 * Float.BYTES, 0); 143 | 144 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); 145 | 146 | 147 | gl.glEnable(GL3.GL_PROGRAM_POINT_SIZE); 148 | 149 | // Draw the vertices 150 | gl.glBindBuffer(PGL.ELEMENT_ARRAY_BUFFER, indexVboId); 151 | pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, Integer.BYTES * indices.length, indexBuffer, GL.GL_DYNAMIC_DRAW); 152 | gl.glDrawElements(GL.GL_POINTS, nop, GL.GL_UNSIGNED_INT, 0); 153 | 154 | gl.glBindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); 155 | 156 | // disable attributes 157 | gl.glDisableVertexAttribArray(posLoc); 158 | gl.glDisableVertexAttribArray(colorLoc); 159 | gl.glDisableVertexAttribArray(sizeLoc); 160 | shader.unbind(); 161 | endPGL(); 162 | } 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | void generateParticles() { 172 | float size = 200.0; 173 | int index = 0; 174 | for (int i = 0; i 0.5) { 12 | discard; 13 | } 14 | fragColor = vertColor; 15 | } -------------------------------------------------------------------------------- /Learning shaders/s09_shader_many_pointcloud/data/vert.glsl: -------------------------------------------------------------------------------- 1 | // vert.glsl 2 | #version 330 3 | 4 | uniform mat4 transform; 5 | 6 | in vec4 position; 7 | in vec4 color; 8 | in float size; 9 | 10 | out vec4 vertColor; 11 | 12 | void main() { 13 | 14 | gl_Position = transform * position; 15 | gl_PointSize = 100.0*size / gl_Position.w; 16 | vertColor = color; 17 | } -------------------------------------------------------------------------------- /Learning shaders/s09_shader_many_pointcloud/s09_shader_many_pointcloud.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Same as before with a slightly more appealing cloud 3 | */ 4 | 5 | import java.nio.ByteBuffer; 6 | import java.nio.ByteOrder; 7 | import java.nio.FloatBuffer; 8 | import java.nio.IntBuffer; 9 | 10 | import com.jogamp.opengl.GL; 11 | import com.jogamp.opengl.GL3; 12 | import com.jogamp.opengl.GL2ES2; 13 | 14 | import peasy.*; 15 | 16 | PeasyCam cam; 17 | 18 | PShader shader; 19 | PGraphics gradient; 20 | color[] palette; 21 | float a; 22 | 23 | PJOGL pgl; 24 | GL2ES2 gl; 25 | 26 | int nop = 1000000; 27 | 28 | float[] positions; 29 | float[] colors; 30 | float[] sizes; 31 | int[] indices; 32 | 33 | FloatBuffer posBuffer; 34 | FloatBuffer colorBuffer; 35 | FloatBuffer sizeBuffer; 36 | IntBuffer indexBuffer; 37 | 38 | int posVboId; 39 | int colorVboId; 40 | int sizeVboId; 41 | int indexVboId; 42 | 43 | int posLoc; 44 | int colorLoc; 45 | int sizeLoc; 46 | 47 | PVector randomPos,pv; 48 | float x, y, z; 49 | float noiseScale = 100; 50 | 51 | void setup() { 52 | size(800, 600, P3D); 53 | pixelDensity(2); 54 | cam = new PeasyCam(this, 100); 55 | shader = loadShader("frag.glsl", "vert.glsl"); 56 | 57 | positions = new float[nop*4]; 58 | colors = new float[nop*4]; 59 | sizes = new float[nop]; 60 | indices = new int[nop]; 61 | 62 | createPalette(); 63 | generateParticles(); 64 | 65 | posBuffer = allocateDirectFloatBuffer(nop*4); 66 | colorBuffer = allocateDirectFloatBuffer(nop*4); 67 | sizeBuffer = allocateDirectFloatBuffer(nop); 68 | indexBuffer = allocateDirectIntBuffer(nop); 69 | 70 | posBuffer.put(positions); 71 | posBuffer.rewind(); 72 | 73 | colorBuffer.put(colors); 74 | colorBuffer.rewind(); 75 | 76 | sizeBuffer.put(sizes); 77 | sizeBuffer.rewind(); 78 | 79 | indexBuffer.put(indices); 80 | indexBuffer.rewind(); 81 | 82 | pgl = (PJOGL) beginPGL(); 83 | gl = pgl.gl.getGL2ES2(); 84 | 85 | // Get GL ids for all the buffers 86 | IntBuffer intBuffer = IntBuffer.allocate(4); 87 | gl.glGenBuffers(4, intBuffer); 88 | posVboId = intBuffer.get(0); 89 | colorVboId = intBuffer.get(1); 90 | sizeVboId = intBuffer.get(2); 91 | indexVboId = intBuffer.get(3); 92 | 93 | shader.bind(); 94 | posLoc = gl.glGetAttribLocation(shader.glProgram, "position"); 95 | colorLoc = gl.glGetAttribLocation(shader.glProgram, "color"); 96 | sizeLoc = gl.glGetAttribLocation(shader.glProgram, "size"); 97 | shader.unbind(); 98 | 99 | endPGL(); 100 | } 101 | 102 | void draw() { 103 | background(100); 104 | pgl = (PJOGL) beginPGL(); 105 | gl = pgl.gl.getGL2ES2(); 106 | 107 | shader.bind(); 108 | 109 | gl.glEnableVertexAttribArray(posLoc); 110 | gl.glEnableVertexAttribArray(colorLoc); 111 | gl.glEnableVertexAttribArray(sizeLoc); 112 | 113 | // Copy vertex data to VBOs 114 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, posVboId); 115 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * positions.length, posBuffer, GL.GL_DYNAMIC_DRAW); 116 | gl.glVertexAttribPointer(posLoc, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0); 117 | 118 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, colorVboId); 119 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * colors.length, colorBuffer, GL.GL_DYNAMIC_DRAW); 120 | gl.glVertexAttribPointer(colorLoc, 4, GL.GL_FLOAT, false, 4 * Float.BYTES, 0); 121 | 122 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, sizeVboId); 123 | gl.glBufferData(GL.GL_ARRAY_BUFFER, Float.BYTES * sizes.length, sizeBuffer, GL.GL_DYNAMIC_DRAW); 124 | gl.glVertexAttribPointer(sizeLoc, 1, GL.GL_FLOAT, false, 1 * Float.BYTES, 0); 125 | 126 | gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); 127 | 128 | 129 | gl.glEnable(GL3.GL_PROGRAM_POINT_SIZE); 130 | 131 | // Draw the triangle elements 132 | gl.glBindBuffer(PGL.ELEMENT_ARRAY_BUFFER, indexVboId); 133 | pgl.bufferData(PGL.ELEMENT_ARRAY_BUFFER, Integer.BYTES * indices.length, indexBuffer, GL.GL_DYNAMIC_DRAW); 134 | gl.glDrawElements(GL.GL_POINTS, nop, GL.GL_UNSIGNED_INT, 0); 135 | 136 | gl.glBindBuffer(PGL.ELEMENT_ARRAY_BUFFER, 0); 137 | 138 | gl.glDisableVertexAttribArray(posLoc); 139 | gl.glDisableVertexAttribArray(colorLoc); 140 | gl.glDisableVertexAttribArray(sizeLoc); 141 | shader.unbind(); 142 | endPGL(); 143 | } 144 | 145 | 146 | void generateParticles() { 147 | 148 | int index = 0; 149 | for (int i = 0; i> 16 & 0xFF)/255.0; 160 | colors[index+1] = (c >> 8 & 0xFF)/255.0; 161 | colors[index+2] = (c & 0xFF)/255.0; 162 | colors[index+3] = 1.0; 163 | 164 | index+=4; 165 | } 166 | } 167 | 168 | PVector getRandomPos(float size) { 169 | float a = 0; 170 | float trying = 0; 171 | while (a<0.5 || trying < 10) { 172 | pv = PVector.random3D(); 173 | pv.mult(random(size)); 174 | pv.add(new PVector(size*0.5,size*0.5,size*0.5)); 175 | a = noise(pv.x/noiseScale, pv.y/noiseScale, pv.z/noiseScale); 176 | trying++; 177 | } 178 | return pv; 179 | } 180 | 181 | 182 | 183 | FloatBuffer allocateDirectFloatBuffer(int n) { 184 | return ByteBuffer.allocateDirect(n * Float.BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 185 | } 186 | 187 | IntBuffer allocateDirectIntBuffer(int n) { 188 | return ByteBuffer.allocateDirect(n * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer(); 189 | } 190 | 191 | 192 | //utility function to create a custom gradient; 193 | void createPalette(){ 194 | gradient = createGraphics(100,100,P3D); 195 | gradient.beginDraw(); 196 | gradient.beginShape(); 197 | gradient.strokeWeight(100); 198 | gradient.stroke(26,81,115); 199 | gradient.vertex(0,50); 200 | gradient.stroke(26,81,115); 201 | gradient.vertex(20,50); 202 | gradient.stroke(231,137,166); 203 | gradient.vertex(30,50); 204 | gradient.stroke(253,255,237); 205 | gradient.vertex(50,50); 206 | gradient.stroke(253,255,237); 207 | gradient.vertex(100,50); 208 | gradient.endShape(); 209 | gradient.endDraw(); 210 | 211 | palette = new color[100]; 212 | for (int i = 0; i<100;i++){ 213 | palette[i] = gradient.get(i,20); 214 | } 215 | 216 | } -------------------------------------------------------------------------------- /aa_AutonomousAgents/Agent.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Autonomous Agents Behaviours 3 | see: http://www.red3d.com/cwr/steer/ 4 | */ 5 | 6 | class Agent{ 7 | 8 | PVector position, velocity, acceleration; 9 | 10 | float maxSpeed, maxForce; 11 | 12 | PVector pastTarget, futPosition; 13 | 14 | float r = 5.0; 15 | color c; 16 | float dist = 50; 17 | float fov = radians(90); 18 | 19 | float desiredSeparation = r*3; 20 | 21 | public Agent(PVector p, float ms, float mf){ 22 | pastTarget = new PVector(0,0); 23 | 24 | r=5.0; 25 | c = 255; 26 | position = p.copy(); 27 | maxSpeed = ms; 28 | maxForce = mf; 29 | velocity = new PVector(0,0); 30 | acceleration = new PVector(0,0); 31 | } 32 | 33 | void run(){ 34 | update(); 35 | borders(); 36 | //boundaries(); 37 | display(); 38 | } 39 | 40 | void applyForce(PVector force) { 41 | // We could add mass here if we want A = F / M 42 | acceleration.add(force); 43 | } 44 | 45 | 46 | 47 | void update() { 48 | // Update velocity 49 | velocity.add(acceleration); 50 | // Limit speed 51 | velocity.limit(maxSpeed); 52 | position.add(velocity); 53 | // Reset accelertion to 0 each cycle 54 | acceleration.mult(0); 55 | } 56 | 57 | /* 58 | Autonomous Agents behaviours 59 | see: http://www.red3d.com/cwr/steer/ 60 | */ 61 | 62 | /* 63 | Steer Formula by Reynolds 64 | */ 65 | 66 | PVector steer(PVector desired){ 67 | PVector steer = PVector.sub(desired,velocity); 68 | steer.limit(maxForce); 69 | return steer; 70 | } 71 | 72 | /* 73 | Seek 74 | */ 75 | PVector seek(PVector target){ 76 | PVector desired = PVector.sub(target,position); 77 | desired.normalize(); 78 | 79 | desired.mult(maxSpeed); 80 | return steer(desired); 81 | 82 | } 83 | 84 | /* 85 | Flee 86 | */ 87 | 88 | PVector flee(PVector target){ 89 | PVector desired = PVector.sub(target,position); 90 | desired.normalize(); 91 | 92 | desired.mult(-maxSpeed); 93 | 94 | return steer(desired); 95 | } 96 | 97 | 98 | /* 99 | Flee and arrive 100 | */ 101 | 102 | 103 | PVector fleeStop(PVector target){ 104 | PVector desired = PVector.sub(target,position); 105 | 106 | float d = desired.mag(); 107 | desired.normalize(); 108 | 109 | if (d > 400){ 110 | float m = map(d,400,500,-maxSpeed,0); 111 | desired.mult(m); 112 | }else{ 113 | desired.mult(-maxSpeed); 114 | } 115 | 116 | return steer(desired); 117 | } 118 | 119 | 120 | /* 121 | Seek and arrive 122 | */ 123 | 124 | PVector arrive(PVector target){ 125 | PVector desired = PVector.sub(target,position); 126 | float d = desired.mag(); 127 | desired.normalize(); 128 | if (d < 100){ 129 | float m = map(d,0,100,0,maxSpeed); 130 | desired.mult(m); 131 | }else{ 132 | desired.mult(maxSpeed); 133 | } 134 | return steer(desired); 135 | } 136 | 137 | /* 138 | Pursuit 139 | */ 140 | 141 | PVector pursuit(PVector target){ 142 | PVector targetVel = PVector.sub(target,pastTarget); 143 | PVector distance = PVector.sub(target,position); 144 | targetVel.normalize(); 145 | targetVel.mult(distance.mag()*0.5); 146 | targetVel.add(target); 147 | 148 | PVector force = arrive(targetVel); 149 | pastTarget = target.copy(); 150 | return force; 151 | } 152 | 153 | /* 154 | Evasion 155 | */ 156 | 157 | PVector evasion(PVector target){ 158 | PVector targetVel = PVector.sub(target,pastTarget); 159 | PVector distance = PVector.sub(target,position); 160 | targetVel.normalize(); 161 | targetVel.mult(distance.mag()*0.5); 162 | targetVel.add(target); 163 | 164 | PVector force = fleeStop(targetVel); 165 | pastTarget = target.copy(); 166 | 167 | return force; 168 | } 169 | 170 | 171 | /* 172 | Follow flowfield on future position 173 | */ 174 | 175 | PVector followForward(FlowField field){ 176 | futPosition = velocity.copy(); 177 | futPosition.normalize(); 178 | futPosition.mult(r*4); 179 | futPosition.add(position); 180 | PVector desired = field.lookup(futPosition); 181 | desired.mult(maxSpeed); 182 | 183 | return steer(desired); 184 | } 185 | 186 | /* 187 | Follow flowfield on current position 188 | */ 189 | 190 | PVector follow(FlowField field){ 191 | PVector desired = field.lookup(position); 192 | desired.mult(maxSpeed); 193 | 194 | return steer(desired); 195 | } 196 | 197 | /* 198 | Group Behaviours: Separate 199 | It includes a Field of view limitation 200 | */ 201 | 202 | PVector separate(ArrayList others){ 203 | PVector sum = new PVector(); 204 | int count = 0; 205 | 206 | for (Agent other : others){ 207 | 208 | float d = PVector.dist(position, other.position); 209 | PVector dif = PVector.sub(other.position,position); 210 | boolean isInView = false; 211 | if (d>0 ){ 212 | 213 | float a = velocity.heading2D(); 214 | float da = dif.heading2D(); 215 | 216 | isInView = (abs(a-da) < fov/2); 217 | 218 | 219 | } 220 | if (isInView && d < 200){ 221 | //other.c = color(255,0,0); 222 | } 223 | 224 | if (d > 0 && d < desiredSeparation && isInView){ 225 | PVector diff = PVector.sub(position,other.position); 226 | 227 | diff.normalize(); 228 | sum.add(diff); 229 | count++; 230 | } 231 | } 232 | 233 | if (count > 0){ 234 | sum.div(count); 235 | sum.setMag(maxSpeed); 236 | return steer(sum); 237 | } 238 | return new PVector(0,0); 239 | } 240 | 241 | 242 | /* 243 | Group Behaviours: Align 244 | */ 245 | 246 | PVector align(ArrayList agents){ 247 | float neighbordist = 50; 248 | PVector sum = new PVector(0,0); 249 | int count = 0; 250 | 251 | for (Agent other : agents){ 252 | float d = PVector.dist(position,other.position); 253 | if ((d > 0) && (d < neighbordist)){ 254 | sum.add(other.velocity); 255 | count++; 256 | } 257 | } 258 | 259 | if (count > 0){ 260 | sum.div(count); 261 | sum.normalize(); 262 | sum.mult(maxSpeed); 263 | return steer(sum); 264 | }else{ 265 | return new PVector(0,0); 266 | } 267 | } 268 | 269 | /* 270 | Group Behaviours: Cohesion 271 | */ 272 | 273 | PVector cohesion(ArrayList agents){ 274 | float neighbordist = 50; 275 | PVector sum = new PVector(0,0); 276 | int count = 0; 277 | 278 | for (Agent other : agents){ 279 | float d = PVector.dist(position,other.position); 280 | if ((d > 0) && (d < neighbordist)){ 281 | sum.add(other.position); 282 | count++; 283 | } 284 | } 285 | 286 | if (count > 0){ 287 | sum.div(count); 288 | 289 | return arrive(sum); 290 | }else{ 291 | return new PVector(0,0); 292 | } 293 | } 294 | 295 | /* 296 | Group Behaviours: flock 297 | It unites and weight each behaviours 298 | */ 299 | 300 | void flock(ArrayList agents){ 301 | PVector sep = separate(agents); 302 | PVector ali = align(agents); 303 | PVector coh = cohesion(agents); 304 | 305 | sep.mult(1.5); 306 | ali.mult(0.6); 307 | coh.mult(0.5); 308 | applyForce(sep); 309 | applyForce(ali); 310 | applyForce(coh); 311 | } 312 | 313 | 314 | 315 | void displayTarget(){ 316 | fill(c); 317 | noStroke(); 318 | ellipse(futPosition.x,futPosition.y,6,6); 319 | } 320 | 321 | 322 | 323 | void display() { 324 | // Draw a triangle rotated in the direction of velocity 325 | float theta = velocity.heading2D() + radians(90); 326 | fill(c); 327 | noStroke(); 328 | pushMatrix(); 329 | translate(position.x,position.y); 330 | rotate(theta); 331 | beginShape(TRIANGLES); 332 | vertex(0, -r*2); 333 | vertex(-r, r*2); 334 | vertex(r, r*2); 335 | endShape(); 336 | popMatrix(); 337 | } 338 | 339 | // Wraparound 340 | void borders() { 341 | if (position.x < -r) position.x = width+r; 342 | if (position.y < -r) position.y = height+r; 343 | if (position.x > width+r) position.x = -r; 344 | if (position.y > height+r) position.y = -r; 345 | } 346 | 347 | void boundaries() { 348 | 349 | PVector desired = null; 350 | 351 | if (position.x < dist) { 352 | desired = new PVector(maxSpeed, velocity.y); 353 | } 354 | else if (position.x > width - dist) { 355 | desired = new PVector(-maxSpeed, velocity.y); 356 | } 357 | 358 | if (position.y < dist) { 359 | desired = new PVector(velocity.x, maxSpeed); 360 | } 361 | else if (position.y > height-dist) { 362 | desired = new PVector(velocity.x, -maxSpeed); 363 | } 364 | 365 | if (desired != null) { 366 | desired.normalize(); 367 | desired.mult(maxSpeed); 368 | PVector steer = PVector.sub(desired, velocity); 369 | steer.limit(maxForce); 370 | applyForce(steer); 371 | } 372 | } 373 | } -------------------------------------------------------------------------------- /aa_AutonomousAgents/AutonomousAgents.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Autonomous Agents Behaviours 3 | see: http://www.red3d.com/cwr/steer/ 4 | */ 5 | ArrayList agents; 6 | 7 | Agent a,b,c,d,e,f; 8 | 9 | FlowField field; 10 | 11 | boolean debug ; 12 | 13 | void setup(){ 14 | size(1280,720,P2D); 15 | agents = new ArrayList(); 16 | field = new FlowField(16); 17 | 18 | 19 | a = new Agent(new PVector(width/2,height/2),4,4); 20 | 21 | b = new Agent(new PVector(width/2,height/2),4,4); 22 | b.c = color(255,0,0); 23 | 24 | c = new Agent(new PVector(width/2,height/2),4,4); 25 | c.c = color(0,255,0); 26 | 27 | d = new Agent(new PVector(width/2,height/2),4,4); 28 | d.c = color(0,0,255); 29 | 30 | e = new Agent(new PVector(width/2,height/2),4,0.5); 31 | e.c = color(255,0,255); 32 | 33 | f = new Agent(new PVector(width/2,height/2),4,0.5); 34 | f.c = color(0,255,255); 35 | 36 | for (int i = 0; i < 200; i++){ 37 | Agent g = new Agent(new PVector(random(width),random(height)),4,0.5); 38 | g.c = color(255,255,0); 39 | g.r = 2; 40 | 41 | agents.add(g); 42 | } 43 | } 44 | 45 | 46 | void draw(){ 47 | background(0,0,30); 48 | PVector mouseTarget = new PVector(mouseX,mouseY); 49 | 50 | a.applyForce(a.arrive(mouseTarget)); 51 | a.run(); 52 | 53 | b.applyForce(b.pursuit(mouseTarget)); 54 | b.run(); 55 | 56 | c.applyForce(c.fleeStop(mouseTarget)); 57 | c.run(); 58 | 59 | d.applyForce(d.evasion(mouseTarget)); 60 | d.run(); 61 | 62 | 63 | field.update(); 64 | if (debug) field.display(); 65 | 66 | e.applyForce(e.followForward(field)); 67 | //if (debug) e.displayTarget(); 68 | e.run(); 69 | 70 | f.applyForce(f.follow(field)); 71 | f.run(); 72 | 73 | for (Agent g : agents){ 74 | PVector seek = g.arrive(mouseTarget); 75 | PVector follow = g.follow(field); 76 | g.flock(agents); 77 | seek.mult(0.7); 78 | follow.mult(0.5); 79 | //g.applyForce(seek); 80 | g.applyForce(follow); 81 | g.run(); 82 | } 83 | 84 | } 85 | 86 | 87 | 88 | void keyPressed(){ 89 | if (key=='d'){ 90 | debug = !debug; 91 | } 92 | } -------------------------------------------------------------------------------- /aa_AutonomousAgents/FlowField.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | 3 | PVector[][] field; 4 | 5 | int cols,rows; 6 | int resolution; 7 | 8 | float step = 0.05; 9 | float dt = 0; 10 | 11 | public FlowField(int _r){ 12 | resolution = _r; 13 | 14 | cols = width/resolution; 15 | rows = height/resolution; 16 | 17 | field = new PVector[cols][rows]; 18 | 19 | initField(); 20 | } 21 | 22 | void initField(){ 23 | float xoff = 0; 24 | for (int x = 0; x < cols; x++){ 25 | float yoff = 0; 26 | for (int y = 0; y < rows; y++){ 27 | 28 | float angle = map(noise(xoff,yoff,dt),0,1,0,TWO_PI); 29 | field[x][y] = new PVector(cos(angle),sin(angle)); 30 | 31 | yoff += step; 32 | 33 | } 34 | xoff += step; 35 | } 36 | dt+=step/10; 37 | } 38 | 39 | void update(){ 40 | initField(); 41 | } 42 | 43 | void display(){ 44 | stroke(100); 45 | 46 | for (int x = 0; x < cols; x++){ 47 | for (int y = 0; y < rows; y++){ 48 | drawVector(field[x][y],x*resolution,y*resolution,resolution-2); 49 | } 50 | 51 | } 52 | 53 | } 54 | 55 | void drawVector(PVector v, float x, float y, float scayl) { 56 | pushMatrix(); 57 | //float arrowsize = 4; 58 | // Translate to location to render vector 59 | translate(x,y); 60 | //stroke(0,100); 61 | // Call vector heading function to get direction (note that pointing to the right is a heading of 0) and rotate 62 | rotate(v.heading2D()); 63 | // Calculate length of vector & scale it to be bigger or smaller if necessary 64 | float len = v.mag()*scayl; 65 | // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) 66 | line(0,0,len,0); 67 | //line(len,0,len-arrowsize,+arrowsize/2); 68 | //line(len,0,len-arrowsize,-arrowsize/2); 69 | popMatrix(); 70 | } 71 | 72 | PVector lookup(PVector lookup){ 73 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 74 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 75 | return field[column][row].copy(); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /aa_AutonomousAgents3D/AutonomousAgents3D.pde: -------------------------------------------------------------------------------- 1 | /* 2 | 3D Implementation of a flock 3 | */ 4 | 5 | import peasy.*; 6 | 7 | ArrayList agents; 8 | Agent a,b,c,d,e,f; 9 | FlowField field; 10 | 11 | PVector x,y,z; 12 | float scale = 0.01; 13 | float dt = 0; 14 | boolean debug ; 15 | PeasyCam cam; 16 | 17 | void setup(){ 18 | size(1280,720,P3D); 19 | agents = new ArrayList(); 20 | //agents.add(new Agent(new PVector(width/2,height/2),4,4)); 21 | field = new FlowField(16); 22 | cam = new PeasyCam(this,100); 23 | 24 | x = new PVector(1,0,0); 25 | y = new PVector(0,1,0); 26 | z = new PVector(0,0,1); 27 | 28 | a = new Agent(new PVector(width/2,height/2),4,4); 29 | 30 | b = new Agent(new PVector(width/2,height/2),4,4); 31 | b.c = color(255,0,0); 32 | 33 | c = new Agent(new PVector(width/2,height/2),4,4); 34 | c.c = color(0,255,0); 35 | 36 | d = new Agent(new PVector(width/2,height/2),4,4); 37 | d.c = color(0,0,255); 38 | 39 | e = new Agent(new PVector(width/2,height/2),4,0.5); 40 | e.c = color(255,0,255); 41 | 42 | f = new Agent(new PVector(width/2,height/2),4,0.5); 43 | f.c = color(0,255,255); 44 | 45 | for (int i = 0; i < 400; i++){ 46 | Agent g = new Agent(new PVector(random(width),random(height),random(width)),4,0.5); 47 | g.c = color(255,255,0); 48 | g.r = 2; 49 | 50 | agents.add(g); 51 | } 52 | } 53 | 54 | 55 | void draw(){ 56 | background(0,0,30); 57 | stroke(255); 58 | noFill(); 59 | pushMatrix(); 60 | //translate(-500,-500,-500); 61 | box(1000, 1000, 1000); 62 | popMatrix(); 63 | PVector target = new PVector(mouseX,mouseY); 64 | 65 | a.arrive(target); 66 | a.run(); 67 | 68 | b.pursuit(target); 69 | b.run(); 70 | 71 | c.fleeStop(target); 72 | c.run(); 73 | 74 | d.evasion(target); 75 | d.run(); 76 | 77 | 78 | field.update(); 79 | 80 | if (debug) field.display(); 81 | 82 | e.followForward(field); 83 | if (debug) e.displayTarget(); 84 | e.run(); 85 | 86 | f.follow(field); 87 | f.run(); 88 | 89 | for (Agent a : agents){ 90 | //a.separate(agents); 91 | a.flock(agents); 92 | //a.followForward(field); 93 | float dx =map(noise(a.position.x*scale, a.position.y*scale,a.position.z*scale+1.352+dt),0,1,-1,1); 94 | float dy =map(noise(a.position.x*scale, a.position.y*scale,a.position.z*scale+12.814+dt),0,1,-1,1); 95 | float dz =map(noise(a.position.x*scale, a.position.y*scale,a.position.z*scale+42.814+dt),0,1,-1,1); 96 | 97 | PVector force = new PVector(dx,dy,dz); 98 | a.applyForce(force); 99 | a.run(); 100 | } 101 | dt+=0.01; 102 | } 103 | 104 | 105 | 106 | void keyPressed(){ 107 | if (key=='d'){ 108 | debug = !debug; 109 | } 110 | } -------------------------------------------------------------------------------- /aa_AutonomousAgents3D/FlowField.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | 3 | PVector[][] field; 4 | PVector[] v; 5 | int cols,rows; 6 | int resolution; 7 | 8 | float step = 0.05; 9 | float dt = 0; 10 | 11 | public FlowField(int _r){ 12 | resolution = _r; 13 | v = new PVector[5]; 14 | cols = width/resolution; 15 | rows = height/resolution; 16 | 17 | field = new PVector[cols][rows]; 18 | 19 | initField(); 20 | } 21 | 22 | void initField(){ 23 | float xoff = 0; 24 | for (int x = 0; x < cols; x++){ 25 | float yoff = 0; 26 | for (int y = 0; y < rows; y++){ 27 | 28 | float angle = map(noise(xoff,yoff,dt),0,1,0,TWO_PI); 29 | field[x][y] = new PVector(cos(angle),sin(angle)); 30 | 31 | yoff += step; 32 | 33 | } 34 | xoff += step; 35 | } 36 | dt+=step/10; 37 | } 38 | 39 | void update(){ 40 | initField(); 41 | } 42 | 43 | void display(){ 44 | stroke(100); 45 | 46 | for (int x = 0; x < cols; x++){ 47 | for (int y = 0; y < rows; y++){ 48 | drawVector(field[x][y],x*resolution,y*resolution,resolution-2); 49 | } 50 | 51 | } 52 | 53 | } 54 | 55 | void drawVector(PVector v, float x, float y, float scayl) { 56 | pushMatrix(); 57 | //float arrowsize = 4; 58 | // Translate to location to render vector 59 | translate(x,y); 60 | //stroke(0,100); 61 | // Call vector heading function to get direction (note that pointing to the right is a heading of 0) and rotate 62 | rotate(v.heading2D()); 63 | // Calculate length of vector & scale it to be bigger or smaller if necessary 64 | float len = v.mag()*scayl; 65 | // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) 66 | line(0,0,len,0); 67 | //line(len,0,len-arrowsize,+arrowsize/2); 68 | //line(len,0,len-arrowsize,-arrowsize/2); 69 | popMatrix(); 70 | } 71 | 72 | PVector lookup(PVector lookup){ 73 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 74 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 75 | return field[column][row].copy(); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /aa_ImageBrightness/Agent.pde: -------------------------------------------------------------------------------- 1 | class Agent{ 2 | 3 | PVector position, velocity, acceleration; 4 | 5 | float maxSpeed, maxForce; 6 | 7 | PVector pastTarget, futPosition; 8 | 9 | float r; 10 | color c; 11 | float dist = 50; 12 | 13 | public Agent(PVector p, float ms, float mf){ 14 | pastTarget = new PVector(0,0); 15 | 16 | r=5.0; 17 | c = 255; 18 | position = p.copy(); 19 | maxSpeed = ms; 20 | maxForce = mf; 21 | velocity = new PVector(0,0); 22 | acceleration = new PVector(0,0); 23 | } 24 | 25 | void run(){ 26 | update(); 27 | borders(); 28 | //boundaries(); 29 | display(); 30 | } 31 | 32 | void applyForce(PVector force) { 33 | // We could add mass here if we want A = F / M 34 | acceleration.add(force); 35 | } 36 | 37 | 38 | 39 | void update() { 40 | // Update velocity 41 | velocity.add(acceleration); 42 | // Limit speed 43 | velocity.limit(maxSpeed); 44 | position.add(velocity); 45 | // Reset accelertion to 0 each cycle 46 | acceleration.mult(0); 47 | } 48 | 49 | /* 50 | Autonomous Agents behaviours 51 | see: http://www.red3d.com/cwr/steer/ 52 | */ 53 | 54 | /* 55 | SEEK behaviour 56 | */ 57 | void seek(PVector target){ 58 | PVector desired = PVector.sub(target,position); 59 | desired.normalize(); 60 | 61 | desired.mult(maxSpeed); 62 | 63 | PVector steer = PVector.sub(desired,velocity); 64 | steer.limit(maxForce); 65 | applyForce(steer); 66 | } 67 | 68 | 69 | /* 70 | Flee behaviour 71 | */ 72 | 73 | void flee(PVector target){ 74 | PVector desired = PVector.sub(target,position); 75 | desired.normalize(); 76 | 77 | desired.mult(-maxSpeed); 78 | 79 | PVector steer = PVector.sub(desired,velocity); 80 | steer.limit(maxForce); 81 | applyForce(steer); 82 | } 83 | 84 | 85 | 86 | /* 87 | Flee with arrive behaviour 88 | */ 89 | 90 | void fleeStop(PVector target){ 91 | PVector desired = PVector.sub(target,position); 92 | 93 | float d = desired.mag(); 94 | desired.normalize(); 95 | 96 | if (d > 400){ 97 | float m = map(d,400,500,-maxSpeed,0); 98 | desired.mult(m); 99 | }else{ 100 | desired.mult(-maxSpeed); 101 | } 102 | 103 | PVector steer = PVector.sub(desired,velocity); 104 | steer.limit(maxForce); 105 | applyForce(steer); 106 | } 107 | 108 | 109 | /* 110 | Seek with arrive behaviour 111 | */ 112 | 113 | void arrive(PVector target){ 114 | PVector desired = PVector.sub(target,position); 115 | float d = desired.mag(); 116 | desired.normalize(); 117 | if (d < 100){ 118 | float m = map(d,0,100,0,maxSpeed); 119 | desired.mult(m); 120 | }else{ 121 | desired.mult(maxSpeed); 122 | } 123 | PVector steer = PVector.sub(desired,velocity); 124 | steer.limit(maxForce); 125 | applyForce(steer); 126 | } 127 | 128 | 129 | 130 | /* 131 | Pursuit behaviour 132 | */ 133 | 134 | void pursuit(PVector target){ 135 | PVector targetVel = PVector.sub(target,pastTarget); 136 | PVector distance = PVector.sub(target,position); 137 | targetVel.normalize(); 138 | targetVel.mult(distance.mag()*0.5); 139 | targetVel.add(target); 140 | 141 | arrive(targetVel); 142 | pastTarget = target.copy(); 143 | } 144 | 145 | 146 | 147 | 148 | /* 149 | Evasion behaviour 150 | */ 151 | 152 | void evasion(PVector target){ 153 | PVector targetVel = PVector.sub(target,pastTarget); 154 | PVector distance = PVector.sub(target,position); 155 | targetVel.normalize(); 156 | targetVel.mult(distance.mag()*0.5); 157 | targetVel.add(target); 158 | 159 | fleeStop(targetVel); 160 | pastTarget = target.copy(); 161 | } 162 | 163 | 164 | /* 165 | FlowField follow behaviour 166 | */ 167 | 168 | void follow(FlowField field){ 169 | futPosition = velocity.copy(); 170 | futPosition.normalize(); 171 | futPosition.mult(r*4); 172 | futPosition.add(position); 173 | PVector desired = field.lookup(futPosition); 174 | desired.mult(maxSpeed); 175 | 176 | PVector steer = PVector.sub(desired,velocity); 177 | steer.limit(maxForce); 178 | applyForce(steer); 179 | } 180 | 181 | 182 | 183 | 184 | void displayTarget(){ 185 | fill(c); 186 | noStroke(); 187 | ellipse(futPosition.x,futPosition.y,6,6); 188 | } 189 | 190 | 191 | 192 | void display() { 193 | // Draw a triangle rotated in the direction of velocity 194 | float theta = velocity.heading2D() + radians(90); 195 | fill(c); 196 | noStroke(); 197 | pushMatrix(); 198 | translate(position.x,position.y); 199 | rotate(theta); 200 | beginShape(TRIANGLES); 201 | vertex(0, -r*2); 202 | vertex(-r, r*2); 203 | vertex(r, r*2); 204 | endShape(); 205 | popMatrix(); 206 | } 207 | 208 | // Wraparound 209 | void borders() { 210 | if (position.x < -r) position.x = width+r; 211 | if (position.y < -r) position.y = height+r; 212 | if (position.x > width+r) position.x = -r; 213 | if (position.y > height+r) position.y = -r; 214 | } 215 | 216 | void boundaries() { 217 | 218 | PVector desired = null; 219 | 220 | if (position.x < dist) { 221 | desired = new PVector(maxSpeed, velocity.y); 222 | } 223 | else if (position.x > width - dist) { 224 | desired = new PVector(-maxSpeed, velocity.y); 225 | } 226 | 227 | if (position.y < dist) { 228 | desired = new PVector(velocity.x, maxSpeed); 229 | } 230 | else if (position.y > height-dist) { 231 | desired = new PVector(velocity.x, -maxSpeed); 232 | } 233 | 234 | if (desired != null) { 235 | desired.normalize(); 236 | desired.mult(maxSpeed); 237 | PVector steer = PVector.sub(desired, velocity); 238 | steer.limit(maxForce); 239 | applyForce(steer); 240 | } 241 | } 242 | } -------------------------------------------------------------------------------- /aa_ImageBrightness/FlowField.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | 3 | PVector[][] field; 4 | 5 | int cols,rows; 6 | int resolution; 7 | 8 | float step = 0.1; 9 | float dt = 0; 10 | 11 | public FlowField(int _r){ 12 | resolution = _r; 13 | 14 | cols = width/resolution; 15 | rows = height/resolution; 16 | 17 | field = new PVector[cols][rows]; 18 | 19 | initField(); 20 | } 21 | 22 | void initField(){ 23 | float xoff = 0; 24 | for (int x = 0; x < cols; x++){ 25 | float yoff = 0; 26 | for (int y = 0; y < rows; y++){ 27 | 28 | float angle = map(noise(xoff,yoff,dt),0,1,0,TWO_PI); 29 | field[x][y] = new PVector(cos(angle),sin(angle)); 30 | 31 | yoff += step; 32 | 33 | } 34 | xoff += step; 35 | } 36 | dt+=step/10; 37 | } 38 | 39 | void update(){ 40 | initField(); 41 | } 42 | 43 | void display(){ 44 | stroke(100); 45 | 46 | for (int x = 0; x < cols; x++){ 47 | for (int y = 0; y < rows; y++){ 48 | drawVector(field[x][y],x*resolution,y*resolution,resolution-2); 49 | } 50 | } 51 | 52 | } 53 | 54 | void drawVector(PVector v, float x, float y, float scayl) { 55 | pushMatrix(); 56 | //float arrowsize = 4; 57 | // Translate to location to render vector 58 | translate(x,y); 59 | //stroke(0,100); 60 | // Call vector heading function to get direction (note that pointing to the right is a heading of 0) and rotate 61 | rotate(v.heading2D()); 62 | // Calculate length of vector & scale it to be bigger or smaller if necessary 63 | float len = v.mag()*scayl; 64 | // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) 65 | line(0,0,len,0); 66 | //line(len,0,len-arrowsize,+arrowsize/2); 67 | //line(len,0,len-arrowsize,-arrowsize/2); 68 | popMatrix(); 69 | } 70 | 71 | PVector lookup(PVector lookup){ 72 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 73 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 74 | return field[column][row].copy(); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /aa_ImageBrightness/aa_ImageBrightness.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Autonomous Agent on flowfield 3 | The flowfield vectors orientation is based 4 | on the brightness of the webcam capture 5 | */ 6 | 7 | import gab.opencv.*; 8 | import processing.video.*; 9 | 10 | Capture video; 11 | 12 | ArrayList agents; 13 | 14 | FlowField field; 15 | int totAgents = 1000; 16 | 17 | boolean debug ; 18 | 19 | void setup(){ 20 | size(1280,720,P2D); 21 | //there is a bug with the camera and the P2D render 22 | //if it doesn't work, remove P2D 23 | 24 | video = new Capture(this,160,90); 25 | video.start(); 26 | 27 | agents = new ArrayList(); 28 | for (int i = 0; i < totAgents; i++){ 29 | agents.add(new Agent(new PVector(random(width),random(height)),random(3,5),random(0.1,0.5))); 30 | } 31 | 32 | field = new FlowField(8); 33 | } 34 | 35 | 36 | void draw(){ 37 | if (video.available()){ 38 | background(0,0,30); 39 | video.read(); 40 | 41 | if (debug){ 42 | pushMatrix(); 43 | scale(-1,1); 44 | image(video, -width, 0,width,height); 45 | popMatrix(); 46 | video.loadPixels(); 47 | } 48 | 49 | 50 | for (int x = 0; x < field.cols; x++){ 51 | for (int y = 0; y < field.rows; y++){ 52 | int loc = (video.width - x - 1) + y*video.width; 53 | color c = video.pixels[loc]; 54 | float angle = map(brightness(c),0,255,-PI,PI); 55 | field.field[x][y] = new PVector(cos(angle),sin(angle)); 56 | 57 | } 58 | } 59 | 60 | 61 | //field.update(); 62 | if (debug) field.display(); 63 | 64 | for (Agent e : agents){ 65 | 66 | e.follow(field); 67 | if (debug) e.displayTarget(); 68 | e.run(); 69 | } 70 | } 71 | } 72 | 73 | void keyPressed(){ 74 | if (key=='d'){ 75 | debug = !debug; 76 | } 77 | } -------------------------------------------------------------------------------- /aa_ImageBrightness_and_backgrondSubstraction/Agent.pde: -------------------------------------------------------------------------------- 1 | class Agent{ 2 | 3 | PVector position, velocity, acceleration; 4 | 5 | float maxSpeed, maxForce; 6 | 7 | PVector pastTarget, futPosition; 8 | 9 | float r; 10 | color c; 11 | float dist = 50; 12 | 13 | public Agent(PVector p, float ms, float mf){ 14 | pastTarget = new PVector(0,0); 15 | 16 | r=5.0; 17 | c = 255; 18 | position = p.copy(); 19 | maxSpeed = ms; 20 | maxForce = mf; 21 | velocity = new PVector(0,0); 22 | acceleration = new PVector(0,0); 23 | } 24 | 25 | void run(){ 26 | update(); 27 | borders(); 28 | //boundaries(); 29 | display(); 30 | } 31 | 32 | void applyForce(PVector force) { 33 | // We could add mass here if we want A = F / M 34 | acceleration.add(force); 35 | } 36 | 37 | 38 | 39 | void update() { 40 | // Update velocity 41 | velocity.add(acceleration); 42 | // Limit speed 43 | velocity.limit(maxSpeed); 44 | position.add(velocity); 45 | // Reset accelertion to 0 each cycle 46 | acceleration.mult(0); 47 | } 48 | 49 | 50 | 51 | 52 | void seek(PVector target){ 53 | PVector desired = PVector.sub(target,position); 54 | desired.normalize(); 55 | 56 | desired.mult(maxSpeed); 57 | 58 | PVector steer = PVector.sub(desired,velocity); 59 | steer.limit(maxForce); 60 | applyForce(steer); 61 | } 62 | 63 | 64 | 65 | 66 | void flee(PVector target){ 67 | PVector desired = PVector.sub(target,position); 68 | desired.normalize(); 69 | 70 | desired.mult(-maxSpeed); 71 | 72 | PVector steer = PVector.sub(desired,velocity); 73 | steer.limit(maxForce); 74 | applyForce(steer); 75 | } 76 | 77 | 78 | 79 | 80 | 81 | void fleeStop(PVector target){ 82 | PVector desired = PVector.sub(target,position); 83 | 84 | float d = desired.mag(); 85 | desired.normalize(); 86 | 87 | if (d > 400){ 88 | float m = map(d,400,500,-maxSpeed,0); 89 | desired.mult(m); 90 | }else{ 91 | desired.mult(-maxSpeed); 92 | } 93 | 94 | PVector steer = PVector.sub(desired,velocity); 95 | steer.limit(maxForce); 96 | applyForce(steer); 97 | } 98 | 99 | 100 | 101 | 102 | void arrive(PVector target){ 103 | PVector desired = PVector.sub(target,position); 104 | float d = desired.mag(); 105 | desired.normalize(); 106 | if (d < 100){ 107 | float m = map(d,0,100,0,maxSpeed); 108 | desired.mult(m); 109 | }else{ 110 | desired.mult(maxSpeed); 111 | } 112 | PVector steer = PVector.sub(desired,velocity); 113 | steer.limit(maxForce); 114 | applyForce(steer); 115 | } 116 | 117 | 118 | 119 | 120 | 121 | void pursuit(PVector target){ 122 | PVector targetVel = PVector.sub(target,pastTarget); 123 | PVector distance = PVector.sub(target,position); 124 | targetVel.normalize(); 125 | targetVel.mult(distance.mag()*0.5); 126 | targetVel.add(target); 127 | 128 | arrive(targetVel); 129 | pastTarget = target.copy(); 130 | } 131 | 132 | 133 | 134 | 135 | 136 | 137 | void evasion(PVector target){ 138 | PVector targetVel = PVector.sub(target,pastTarget); 139 | PVector distance = PVector.sub(target,position); 140 | targetVel.normalize(); 141 | targetVel.mult(distance.mag()*0.5); 142 | targetVel.add(target); 143 | 144 | fleeStop(targetVel); 145 | pastTarget = target.copy(); 146 | } 147 | 148 | 149 | 150 | 151 | void follow(FlowField field){ 152 | futPosition = velocity.copy(); 153 | futPosition.normalize(); 154 | futPosition.mult(r*4); 155 | futPosition.add(position); 156 | PVector desired = field.lookup(futPosition); 157 | desired.mult(maxSpeed); 158 | 159 | PVector steer = PVector.sub(desired,velocity); 160 | steer.limit(maxForce); 161 | applyForce(steer); 162 | } 163 | 164 | 165 | 166 | 167 | void displayTarget(){ 168 | fill(c); 169 | noStroke(); 170 | ellipse(futPosition.x,futPosition.y,6,6); 171 | } 172 | 173 | 174 | 175 | void display() { 176 | // Draw a triangle rotated in the direction of velocity 177 | float theta = velocity.heading2D() + radians(90); 178 | fill(c); 179 | noStroke(); 180 | pushMatrix(); 181 | translate(position.x,position.y); 182 | rotate(theta); 183 | beginShape(TRIANGLES); 184 | vertex(0, -r*2); 185 | vertex(-r, r*2); 186 | vertex(r, r*2); 187 | endShape(); 188 | popMatrix(); 189 | } 190 | 191 | // Wraparound 192 | void borders() { 193 | if (position.x < -r) position.x = width+r; 194 | if (position.y < -r) position.y = height+r; 195 | if (position.x > width+r) position.x = -r; 196 | if (position.y > height+r) position.y = -r; 197 | } 198 | 199 | void boundaries() { 200 | 201 | PVector desired = null; 202 | 203 | if (position.x < dist) { 204 | desired = new PVector(maxSpeed, velocity.y); 205 | } 206 | else if (position.x > width - dist) { 207 | desired = new PVector(-maxSpeed, velocity.y); 208 | } 209 | 210 | if (position.y < dist) { 211 | desired = new PVector(velocity.x, maxSpeed); 212 | } 213 | else if (position.y > height-dist) { 214 | desired = new PVector(velocity.x, -maxSpeed); 215 | } 216 | 217 | if (desired != null) { 218 | desired.normalize(); 219 | desired.mult(maxSpeed); 220 | PVector steer = PVector.sub(desired, velocity); 221 | steer.limit(maxForce); 222 | applyForce(steer); 223 | } 224 | } 225 | } -------------------------------------------------------------------------------- /aa_ImageBrightness_and_backgrondSubstraction/FlowField.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | 3 | PVector[][] field; 4 | 5 | int cols,rows; 6 | int resolution; 7 | 8 | float step = 0.1; 9 | float dt = 0; 10 | 11 | public FlowField(int _r){ 12 | resolution = _r; 13 | 14 | cols = width/resolution; 15 | rows = height/resolution; 16 | 17 | field = new PVector[cols][rows]; 18 | 19 | initField(); 20 | } 21 | 22 | void initField(){ 23 | float xoff = 0; 24 | for (int x = 0; x < cols; x++){ 25 | float yoff = 0; 26 | for (int y = 0; y < rows; y++){ 27 | 28 | float angle = map(noise(xoff,yoff,dt),0,1,0,TWO_PI); 29 | field[x][y] = new PVector(cos(angle),sin(angle)); 30 | 31 | yoff += step; 32 | 33 | } 34 | xoff += step; 35 | } 36 | dt+=step/10; 37 | } 38 | 39 | void update(){ 40 | initField(); 41 | } 42 | 43 | void display(){ 44 | stroke(100); 45 | 46 | for (int x = 0; x < cols; x++){ 47 | for (int y = 0; y < rows; y++){ 48 | drawVector(field[x][y],x*resolution,y*resolution,resolution-2); 49 | } 50 | } 51 | 52 | } 53 | 54 | void drawVector(PVector v, float x, float y, float scayl) { 55 | pushMatrix(); 56 | //float arrowsize = 4; 57 | // Translate to location to render vector 58 | translate(x,y); 59 | //stroke(0,100); 60 | // Call vector heading function to get direction (note that pointing to the right is a heading of 0) and rotate 61 | rotate(v.heading2D()); 62 | // Calculate length of vector & scale it to be bigger or smaller if necessary 63 | float len = v.mag()*scayl; 64 | // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) 65 | line(0,0,len,0); 66 | //line(len,0,len-arrowsize,+arrowsize/2); 67 | //line(len,0,len-arrowsize,-arrowsize/2); 68 | popMatrix(); 69 | } 70 | 71 | PVector lookup(PVector lookup){ 72 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 73 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 74 | return field[column][row].copy(); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /aa_ImageBrightness_and_backgrondSubstraction/aa_ImageBrightness_and_backgrondSubstraction.pde: -------------------------------------------------------------------------------- 1 | import gab.opencv.*; 2 | import processing.video.*; 3 | 4 | Capture video; 5 | ArrayList agents; 6 | 7 | FlowField field; 8 | 9 | int totAgents = 1000; 10 | 11 | int numPixels; 12 | int[] backgroundPixels; 13 | 14 | boolean debug ; 15 | 16 | void setup(){ 17 | size(1280,720); 18 | video = new Capture(this,160,90); 19 | video.start(); 20 | 21 | agents = new ArrayList(); 22 | for (int i = 0; i < totAgents; i++){ 23 | agents.add(new Agent(new PVector(random(width),random(height)),random(3,5),random(0.1,0.5))); 24 | } 25 | 26 | field = new FlowField(8); 27 | 28 | numPixels = video.width * video.height; 29 | backgroundPixels = new int[numPixels]; 30 | } 31 | 32 | 33 | void draw(){ 34 | if (video.available()){ 35 | background(0,0,30); 36 | video.read(); 37 | 38 | video.loadPixels(); 39 | 40 | int presenceSum = 0; 41 | for (int x = 0; x < field.cols; x++){ 42 | for (int y = 0; y < field.rows; y++){ 43 | int loc = (video.width - x - 1) + y*video.width; 44 | 45 | color currColor = video.pixels[loc]; 46 | color bkgdColor = backgroundPixels[loc]; 47 | 48 | // Extract the red, green, and blue components of the current pixel's color 49 | int currR = (currColor >> 16) & 0xFF; 50 | int currG = (currColor >> 8) & 0xFF; 51 | int currB = currColor & 0xFF; 52 | // Extract the red, green, and blue components of the background pixel's color 53 | int bkgdR = (bkgdColor >> 16) & 0xFF; 54 | int bkgdG = (bkgdColor >> 8) & 0xFF; 55 | int bkgdB = bkgdColor & 0xFF; 56 | // Compute the difference of the red, green, and blue values 57 | int diffR = abs(currR - bkgdR); 58 | int diffG = abs(currG - bkgdG); 59 | int diffB = abs(currB - bkgdB); 60 | 61 | presenceSum = diffR + diffG + diffB; 62 | 63 | if (presenceSum < 20){ 64 | video.pixels[loc] = 0; 65 | } 66 | 67 | 68 | color c = video.pixels[loc]; 69 | float angle = map(brightness(c),0,255,-PI,PI); 70 | field.field[x][y] = new PVector(cos(angle),sin(angle)); 71 | 72 | } 73 | } 74 | video.updatePixels(); 75 | pushMatrix(); 76 | scale(-1,1); 77 | image(video, -width, 0,width,height); 78 | popMatrix(); 79 | 80 | //field.update(); 81 | if (debug) field.display(); 82 | 83 | for (Agent e : agents){ 84 | 85 | e.follow(field); 86 | if (debug) e.displayTarget(); 87 | e.run(); 88 | 89 | } 90 | 91 | } 92 | } 93 | 94 | 95 | 96 | void keyPressed(){ 97 | if (key=='d'){ 98 | debug = !debug; 99 | }else{ 100 | 101 | video.loadPixels(); 102 | arraycopy(video.pixels, backgroundPixels); 103 | } 104 | } -------------------------------------------------------------------------------- /aa_OpticalFlow/Agent.pde: -------------------------------------------------------------------------------- 1 | class Agent{ 2 | 3 | PVector position, velocity, acceleration; 4 | 5 | float maxSpeed, maxForce; 6 | 7 | PVector pastTarget, futPosition; 8 | 9 | float r = 5.0; 10 | color c; 11 | float dist = 50; 12 | 13 | float desiredSeparation = 50; 14 | 15 | public Agent(PVector p, float ms, float mf){ 16 | pastTarget = new PVector(0,0); 17 | 18 | r=5.0; 19 | c = 255; 20 | position = p.copy(); 21 | maxSpeed = ms; 22 | maxForce = mf; 23 | velocity = new PVector(0,0); 24 | acceleration = new PVector(0,0); 25 | } 26 | 27 | void run(){ 28 | update(); 29 | borders(); 30 | //boundaries(); 31 | display(); 32 | } 33 | 34 | void applyForce(PVector force) { 35 | // We could add mass here if we want A = F / M 36 | acceleration.add(force); 37 | } 38 | 39 | 40 | 41 | void update() { 42 | // Update velocity 43 | velocity.add(acceleration); 44 | // Limit speed 45 | velocity.limit(maxSpeed); 46 | position.add(velocity); 47 | // Reset accelertion to 0 each cycle 48 | acceleration.mult(0); 49 | } 50 | 51 | void steer(PVector desired){ 52 | PVector steer = PVector.sub(desired,velocity); 53 | steer.limit(maxForce); 54 | applyForce(steer); 55 | } 56 | 57 | 58 | void seek(PVector target){ 59 | PVector desired = PVector.sub(target,position); 60 | desired.normalize(); 61 | 62 | desired.mult(maxSpeed); 63 | steer(desired); 64 | 65 | } 66 | 67 | 68 | 69 | 70 | void flee(PVector target){ 71 | PVector desired = PVector.sub(target,position); 72 | desired.normalize(); 73 | 74 | desired.mult(-maxSpeed); 75 | 76 | steer(desired); 77 | } 78 | 79 | 80 | 81 | 82 | 83 | void fleeStop(PVector target){ 84 | PVector desired = PVector.sub(target,position); 85 | 86 | float d = desired.mag(); 87 | desired.normalize(); 88 | 89 | if (d > 400){ 90 | float m = map(d,400,500,-maxSpeed,0); 91 | desired.mult(m); 92 | }else{ 93 | desired.mult(-maxSpeed); 94 | } 95 | 96 | steer(desired); 97 | } 98 | 99 | 100 | 101 | 102 | void arrive(PVector target){ 103 | PVector desired = PVector.sub(target,position); 104 | float d = desired.mag(); 105 | desired.normalize(); 106 | if (d < 100){ 107 | float m = map(d,0,100,0,maxSpeed); 108 | desired.mult(m); 109 | }else{ 110 | desired.mult(maxSpeed); 111 | } 112 | steer(desired); 113 | } 114 | 115 | 116 | 117 | 118 | 119 | void pursuit(PVector target){ 120 | PVector targetVel = PVector.sub(target,pastTarget); 121 | PVector distance = PVector.sub(target,position); 122 | targetVel.normalize(); 123 | targetVel.mult(distance.mag()*0.5); 124 | targetVel.add(target); 125 | 126 | arrive(targetVel); 127 | pastTarget = target.copy(); 128 | } 129 | 130 | 131 | 132 | 133 | 134 | 135 | void evasion(PVector target){ 136 | PVector targetVel = PVector.sub(target,pastTarget); 137 | PVector distance = PVector.sub(target,position); 138 | targetVel.normalize(); 139 | targetVel.mult(distance.mag()*0.5); 140 | targetVel.add(target); 141 | 142 | fleeStop(targetVel); 143 | pastTarget = target.copy(); 144 | } 145 | 146 | 147 | 148 | 149 | void followForward(FlowField field){ 150 | futPosition = velocity.copy(); 151 | futPosition.normalize(); 152 | futPosition.mult(r*4); 153 | futPosition.add(position); 154 | PVector desired = field.lookup(futPosition); 155 | desired.mult(maxSpeed); 156 | 157 | steer(desired); 158 | } 159 | 160 | void follow(FlowField field){ 161 | PVector desired = field.lookup(position); 162 | desired.mult(maxSpeed); 163 | 164 | steer(desired); 165 | } 166 | 167 | 168 | 169 | 170 | 171 | void separate(ArrayList others){ 172 | PVector sum = new PVector(); 173 | int count = 0; 174 | 175 | for (Agent other : others){ 176 | float d = PVector.dist(position, other.position); 177 | if (d > 0 && d < desiredSeparation){ 178 | PVector diff = PVector.sub(position,other.position); 179 | diff.normalize(); 180 | sum.add(diff); 181 | count++; 182 | } 183 | } 184 | 185 | if (count > 0){ 186 | sum.div(count); 187 | sum.setMag(maxSpeed); 188 | steer(sum); 189 | } 190 | } 191 | 192 | 193 | 194 | void displayTarget(){ 195 | fill(c); 196 | noStroke(); 197 | ellipse(futPosition.x,futPosition.y,6,6); 198 | } 199 | 200 | 201 | 202 | void display() { 203 | // Draw a triangle rotated in the direction of velocity 204 | float theta = velocity.heading2D() + radians(90); 205 | fill(c); 206 | noStroke(); 207 | pushMatrix(); 208 | translate(position.x,position.y); 209 | rotate(theta); 210 | beginShape(TRIANGLES); 211 | vertex(0, -r*2); 212 | vertex(-r, r*2); 213 | vertex(r, r*2); 214 | endShape(); 215 | popMatrix(); 216 | } 217 | 218 | // Wraparound 219 | void borders() { 220 | if (position.x < -r) position.x = width+r; 221 | if (position.y < -r) position.y = height+r; 222 | if (position.x > width+r) position.x = -r; 223 | if (position.y > height+r) position.y = -r; 224 | } 225 | 226 | void boundaries() { 227 | 228 | PVector desired = null; 229 | 230 | if (position.x < dist) { 231 | desired = new PVector(maxSpeed, velocity.y); 232 | } 233 | else if (position.x > width - dist) { 234 | desired = new PVector(-maxSpeed, velocity.y); 235 | } 236 | 237 | if (position.y < dist) { 238 | desired = new PVector(velocity.x, maxSpeed); 239 | } 240 | else if (position.y > height-dist) { 241 | desired = new PVector(velocity.x, -maxSpeed); 242 | } 243 | 244 | if (desired != null) { 245 | desired.normalize(); 246 | desired.mult(maxSpeed); 247 | PVector steer = PVector.sub(desired, velocity); 248 | steer.limit(maxForce); 249 | applyForce(steer); 250 | } 251 | } 252 | } -------------------------------------------------------------------------------- /aa_OpticalFlow/FlowField.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | 3 | PVector[][] field; 4 | 5 | int cols,rows; 6 | int resolution; 7 | 8 | float step = 0.1; 9 | float dt = 0; 10 | 11 | public FlowField(int _r){ 12 | resolution = _r; 13 | 14 | cols = width/resolution; 15 | rows = height/resolution; 16 | 17 | field = new PVector[cols][rows]; 18 | 19 | initField(); 20 | } 21 | 22 | void initField(){ 23 | float xoff = 0; 24 | for (int x = 0; x < cols; x++){ 25 | float yoff = 0; 26 | for (int y = 0; y < rows; y++){ 27 | 28 | float angle = map(noise(xoff,yoff,dt),0,1,0,TWO_PI); 29 | field[x][y] = new PVector(cos(angle),sin(angle)); 30 | 31 | yoff += step; 32 | 33 | } 34 | xoff += step; 35 | } 36 | dt+=step/10; 37 | } 38 | 39 | void update(){ 40 | initField(); 41 | } 42 | 43 | void display(){ 44 | stroke(100); 45 | 46 | for (int x = 0; x < cols; x++){ 47 | for (int y = 0; y < rows; y++){ 48 | drawVector(field[x][y],x*resolution,y*resolution,resolution-2); 49 | } 50 | } 51 | 52 | } 53 | 54 | void drawVector(PVector v, float x, float y, float scayl) { 55 | pushMatrix(); 56 | //float arrowsize = 4; 57 | // Translate to location to render vector 58 | translate(x,y); 59 | //stroke(0,100); 60 | // Call vector heading function to get direction (note that pointing to the right is a heading of 0) and rotate 61 | rotate(v.heading2D()); 62 | // Calculate length of vector & scale it to be bigger or smaller if necessary 63 | float len = v.mag()*scayl; 64 | // Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction) 65 | line(0,0,len,0); 66 | //line(len,0,len-arrowsize,+arrowsize/2); 67 | //line(len,0,len-arrowsize,-arrowsize/2); 68 | popMatrix(); 69 | } 70 | 71 | PVector lookup(PVector lookup){ 72 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 73 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 74 | return field[column][row].copy(); 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /aa_OpticalFlow/aa_OpticalFlow.pde: -------------------------------------------------------------------------------- 1 | import gab.opencv.*; 2 | import processing.video.*; 3 | 4 | OpenCV opencv; 5 | Capture video; 6 | 7 | ArrayList agents; 8 | 9 | Agent a,b,c,d,e; 10 | 11 | FlowField field; 12 | 13 | int totAgents = 200; 14 | 15 | boolean debug ; 16 | 17 | void setup(){ 18 | size(1280,720,P2D); 19 | video = new Capture(this,160,90); 20 | opencv = new OpenCV(this,160,90); 21 | video.start(); 22 | 23 | agents = new ArrayList(); 24 | for (int i = 0; i < totAgents; i++){ 25 | agents.add(new Agent(new PVector(random(width),random(height)),random(3,5),random(0.1,0.5))); 26 | } 27 | 28 | field = new FlowField(8); 29 | } 30 | 31 | 32 | void draw(){ 33 | //background(0,0,30); 34 | fill(0,10); 35 | rect(0,0,width,height); 36 | if (video.available()){ 37 | 38 | video.read(); 39 | opencv.loadImage(video); 40 | opencv.calculateOpticalFlow(); 41 | 42 | for (int x = 0; x < field.cols; x++){ 43 | for (int y = 0; y < field.rows; y++){ 44 | PVector flow = opencv.getFlowAt(160-x-1,y); 45 | if (field.field[x][y].mag() < flow.mag()){ 46 | flow.x *= -1; 47 | field.field[x][y] = flow; 48 | } 49 | field.field[x][y].mult(0.98); 50 | } 51 | } 52 | 53 | } 54 | 55 | 56 | //field.update(); 57 | if (debug) field.display(); 58 | 59 | for (Agent e : agents){ 60 | 61 | e.follow(field); 62 | e.separate(agents); 63 | //if (debug) e.displayTarget(); 64 | e.run(); 65 | 66 | } 67 | 68 | } 69 | 70 | 71 | 72 | void keyPressed(){ 73 | if (key=='d'){ 74 | debug = !debug; 75 | } 76 | } -------------------------------------------------------------------------------- /basic_3d_rotation/basic_3d_rotation.pde: -------------------------------------------------------------------------------- 1 | import peasy.*; 2 | PeasyCam cam; 3 | PVector[] v; 4 | PVector linea; 5 | float r=5; 6 | 7 | PVector x,y,z; 8 | 9 | void setup(){ 10 | size(1280,720,P3D); 11 | cam = new PeasyCam(this,100); 12 | 13 | linea = new PVector(.3,.2,.5); 14 | linea.normalize(); 15 | 16 | v = new PVector[5]; 17 | v[0] = new PVector(0, -r*2, 0); // top of the pyramid 18 | v[1] = new PVector(r*cos(HALF_PI), r*2, r*sin(HALF_PI)); // base point 1 19 | v[2] = new PVector(r*cos(PI), r*2, r*sin(PI)); // base point 2 20 | v[3] = new PVector(r*cos(1.5*PI), r*2, r*sin(1.5*PI)); // base point 3 21 | v[4] = new PVector(r*cos(TWO_PI), r*2, r*sin(TWO_PI)); // base point 4 22 | 23 | x = new PVector(1,0,0); 24 | y = new PVector(0,1,0); 25 | z = new PVector(0,0,1); 26 | } 27 | 28 | void draw(){ 29 | background(255); 30 | stroke(255,0,0); 31 | line(0,0,0,20,0,0); 32 | stroke(0,255,0); 33 | line(0,0,0,0,20,0); 34 | stroke(0,0,255); 35 | line(0,0,0,0,0,20); 36 | stroke(0); 37 | linea.mult(20); 38 | line(0,0,0,linea.x,linea.y,linea.z); 39 | linea.normalize(); 40 | 41 | 42 | 43 | pushMatrix(); 44 | translate(0,0,0); 45 | float rx = asin(-linea.y)-HALF_PI; 46 | float ry = atan2(linea.x, linea.z); 47 | rotateY(ry); 48 | rotateX(rx); 49 | beginShape(TRIANGLE_FAN); 50 | for (int i=0; i<5; i++) { 51 | vertex(v[i].x, v[i].y, v[i].z); // set the vertices based on the object coordinates defined in the createShape() method 52 | } 53 | vertex(v[1].x, v[1].y, v[1].z); 54 | endShape(); 55 | popMatrix(); 56 | } -------------------------------------------------------------------------------- /complexity_gridDemo/Grid.pde: -------------------------------------------------------------------------------- 1 | class Grid{ 2 | ArrayList[] grid; 3 | int cellWidth; 4 | int cellHeight; 5 | 6 | int rows,cols; 7 | 8 | public Grid(int _cols, int _rows){ 9 | grid = new ArrayList[_rows*_cols]; 10 | 11 | rows = _rows; 12 | cols = _cols; 13 | 14 | cellWidth = width/cols; 15 | cellHeight = height/rows; 16 | } 17 | 18 | void clear(){ 19 | for (int i = 0; i(); 36 | } 37 | grid[index].add(p); 38 | } 39 | 40 | ArrayList getCell(Particle p){ 41 | int index = getParticlePosition(p); 42 | return grid[index]; 43 | } 44 | 45 | ArrayList getNear(Particle p){ 46 | ArrayList objects = new ArrayList(); 47 | 48 | int xpos = floor(p.location.x/cellWidth); 49 | int ypos = floor(p.location.y/cellHeight); 50 | 51 | int xstart = constrain(xpos-1,0,cols); 52 | int ystart = constrain(ypos-1,0,rows); 53 | int xend = constrain(xpos+2,0,cols); 54 | int yend = constrain(ypos+2,0,rows); 55 | 56 | for (int x = xstart; x objects = getNear(p); 68 | for (int i = objects.size()-1; i>=0; i--){ 69 | Particle tempP = objects.get(i); 70 | PVector dist = PVector.sub(p.location,tempP.location); 71 | if (dist.magSq() > radius*radius){ 72 | objects.remove(i); 73 | } 74 | } 75 | 76 | return objects; 77 | } 78 | 79 | void drawGrid(){ 80 | for (int i = 0; i < cols; i++){ 81 | line (cellWidth*i,0,cellWidth*i,height); 82 | } 83 | for (int i = 0; i < rows; i++){ 84 | line (0,i*cellHeight,width,i*cellHeight); 85 | 86 | } 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /complexity_gridDemo/Particle.pde: -------------------------------------------------------------------------------- 1 | // The Nature of Code 2 | // Daniel Shiffman 3 | // http://natureofcode.com 4 | 5 | class Particle { 6 | 7 | PVector location; 8 | PVector velocity; 9 | PVector acceleration; 10 | PVector force,friction; 11 | float mass,r,distance,loc; 12 | float maxForce, maxSpeed,strength; 13 | int id,val; 14 | color c; 15 | float k = 0.001; 16 | int age = 0; 17 | int spawnAge = (int)random(80,120); 18 | float minr = 1.0; 19 | float maxr = 5.0; 20 | boolean spawned = false; 21 | 22 | Particle(float x, float y,int _id) { 23 | mass = 2; 24 | id = _id; 25 | r = 2; 26 | maxSpeed = 1; 27 | maxForce = 2; 28 | location = new PVector(x, y); 29 | velocity = new PVector(0, 0); 30 | acceleration = new PVector(0, 0); 31 | } 32 | 33 | void applyForce(PVector force) { 34 | //PVector f = PVector.div(force, mass); 35 | acceleration.add(force); 36 | } 37 | 38 | void update() { 39 | velocity.add(acceleration); 40 | velocity.limit(maxSpeed); 41 | location.add(velocity); 42 | acceleration.mult(0); 43 | //friction(); 44 | borders(); 45 | age+=1; 46 | } 47 | 48 | void friction(){ 49 | friction = velocity.copy(); 50 | friction.mult(-1); 51 | friction.normalize(); 52 | friction.mult(k); 53 | 54 | applyForce(friction); 55 | } 56 | 57 | void display() { 58 | 59 | ellipse(location.x,location.y,r*2,r*2); 60 | } 61 | 62 | PVector attract(Particle p) { 63 | force = PVector.sub(p.location,location); // Calculate direction of force 64 | distance = force.magSq(); 65 | 66 | distance = constrain(distance, 1.0, 5000.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects 67 | force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction 68 | 69 | strength = (g) / (distance*4*PI); // Calculate gravitional force magnitude 70 | force.mult(strength); // Get force vector --> magnitude * direction 71 | return force; 72 | 73 | 74 | } 75 | 76 | void setRadius (PImage img){ 77 | 78 | loc = (int)location.x + (int)location.y*img.width; 79 | //c= img.get((int)location.x,(int)location.y); 80 | //c = img.pixels[int(loc)]; 81 | val = img.pixels[int(loc)] & 0xFF; 82 | r= lerp(r,map(val,0.0,255.0,minr,maxr),0.01); 83 | 84 | } 85 | 86 | void borders() { 87 | if ( location.x < r || location.x > width-r){ 88 | velocity.x = -velocity.x; 89 | } 90 | if ( location.y < r || location.y > height-r){ 91 | velocity.y = -velocity.y; 92 | } 93 | 94 | if (location.x> width-r) location.x = width-r; 95 | if (location.x< r) location.x = r; 96 | if (location.y> height-r) location.y = height-r; 97 | if (location.y< r) location.y = r; 98 | 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /complexity_gridDemo/Quadtree.pde: -------------------------------------------------------------------------------- 1 | class Quadtree { 2 | private int maxObjects = 10; 3 | private int maxLevels = 5; 4 | 5 | private int level; 6 | private ArrayList objects; 7 | private Rectangle bounds; 8 | private Quadtree[] nodes; 9 | 10 | public Quadtree(int pLevel, Rectangle pBounds){ 11 | level = pLevel; 12 | objects = new ArrayList(); 13 | bounds = pBounds; 14 | nodes = new Quadtree[4]; 15 | } 16 | 17 | void clear() { 18 | if (objects.size() > 0){ 19 | objects.clear(); 20 | } 21 | for (int i = 0; i < nodes.length; i++) { 22 | if (nodes[i] != null) { 23 | nodes[i].clear(); 24 | nodes[i] = null; 25 | } 26 | } 27 | } 28 | 29 | void split() { 30 | int subWidth = (int)(bounds.getWidth() / 2); 31 | int subHeight = (int)(bounds.getHeight() / 2); 32 | int x = (int)bounds.getX(); 33 | int y = (int)bounds.getY(); 34 | 35 | nodes[0] = new Quadtree(level+1, new Rectangle(x + subWidth, y, subWidth, subHeight)); 36 | nodes[1] = new Quadtree(level+1, new Rectangle(x, y, subWidth, subHeight)); 37 | nodes[2] = new Quadtree(level+1, new Rectangle(x, y + subHeight, subWidth, subHeight)); 38 | nodes[3] = new Quadtree(level+1, new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight)); 39 | } 40 | 41 | 42 | 43 | private int getIndex(Particle pParticle) { 44 | int index = -1; 45 | double verticalMidpoint = bounds.getX() + (bounds.getWidth() / 2); 46 | double horizontalMidpoint = bounds.getY() + (bounds.getHeight() / 2); 47 | 48 | // Object can completely fit within the top quadrants 49 | boolean topQuadrant = (pParticle.location.y < horizontalMidpoint); 50 | // Object can completely fit within the bottom quadrants 51 | boolean bottomQuadrant = (pParticle.location.y >= horizontalMidpoint); 52 | 53 | // Object can completely fit within the left quadrants 54 | if (pParticle.location.x < verticalMidpoint) { 55 | if (topQuadrant) { 56 | index = 1; 57 | } 58 | else if (bottomQuadrant) { 59 | index = 2; 60 | } 61 | } 62 | // Object can completely fit within the right quadrants 63 | else if (pParticle.location.x >= verticalMidpoint) { 64 | if (topQuadrant) { 65 | index = 0; 66 | } 67 | else if (bottomQuadrant) { 68 | index = 3; 69 | } 70 | } 71 | 72 | return index; 73 | } 74 | 75 | /* 76 | * Insert the object into the quadtree. If the node 77 | * exceeds the capacity, it will split and add all 78 | * objects to their corresponding nodes. 79 | */ 80 | void insert(Particle pParticle) { 81 | if (nodes[0] != null) { 82 | int index = getIndex(pParticle); 83 | 84 | if (index != -1) { 85 | nodes[index].insert(pParticle); 86 | 87 | return; 88 | } 89 | } 90 | 91 | objects.add(pParticle); 92 | 93 | if (objects.size() > maxObjects && level < maxLevels) { 94 | if (nodes[0] == null) { 95 | split(); 96 | } 97 | 98 | int i = 0; 99 | while (i < objects.size()) { 100 | int index = getIndex((Particle)objects.get(i)); 101 | if (index != -1) { 102 | nodes[index].insert((Particle)objects.remove(i)); 103 | } 104 | else { 105 | i++; 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | public List retrieve(List returnObjects, Particle p) { 113 | int index = getIndex(p); 114 | if (index != -1 && nodes[0] != null) { 115 | nodes[index].retrieve(returnObjects, p); 116 | } 117 | 118 | returnObjects.addAll(objects); 119 | 120 | return returnObjects; 121 | } 122 | } -------------------------------------------------------------------------------- /complexity_gridDemo/complexity_gridDemo.pde: -------------------------------------------------------------------------------- 1 | /* 2 | Complexity, grid structure allow calculations to be made 3 | in the neighbourood only. 4 | */ 5 | 6 | import java.util.*; 7 | import java.awt.Rectangle; 8 | 9 | Grid grid; 10 | ArrayList particles; 11 | ArrayList check; 12 | Particle p; 13 | 14 | float g = 1; 15 | 16 | 17 | boolean debugMode; 18 | int debugId = 0; 19 | 20 | void setup(){ 21 | size(800,600); 22 | grid = new Grid(8,6); 23 | particles = new ArrayList(); 24 | check = new ArrayList(); 25 | for (int i = 0; i < 1000; i++){ 26 | particles.add(new Particle(random(width),random(height),i)); 27 | } 28 | } 29 | 30 | void draw(){ 31 | background(0); 32 | fill(255); 33 | noStroke(); 34 | grid.clear(); 35 | for (int i = 0; i < particles.size(); i++) { 36 | grid.insert(particles.get(i)); 37 | } 38 | 39 | for (int i = 0; i < particles.size(); i++) { 40 | p = particles.get(i); 41 | 42 | check.clear(); 43 | check = grid.getInsideCircle(p,100); 44 | 45 | for (int j = 0; j < check.size(); j++){ 46 | if (p.id != check.get(j).id){ 47 | p.applyForce(check.get(j).attract(p)); 48 | } 49 | } 50 | p.update(); 51 | p.display(); 52 | } 53 | 54 | if (debugMode){ 55 | p = particles.get(debugId); 56 | fill(255,0,0); 57 | p.display(); 58 | fill(0,255,0); 59 | check.clear(); 60 | check = grid.getInsideCircle(p,100); 61 | for (int j = 0; j < check.size(); j++){ 62 | if (p.id != check.get(j).id){ 63 | check.get(j).display(); 64 | } 65 | } 66 | stroke(50); 67 | grid.drawGrid(); 68 | 69 | } 70 | 71 | } 72 | 73 | 74 | void keyPressed(){ 75 | if (key=='d'){ 76 | debugMode = !debugMode; 77 | println(particles.get(debugId).id); 78 | } 79 | } -------------------------------------------------------------------------------- /complexity_gridOptimization/Grid.pde: -------------------------------------------------------------------------------- 1 | class Grid{ 2 | ArrayList[] grid; 3 | int cellWidth; 4 | int cellHeight; 5 | 6 | int rows,cols; 7 | 8 | public Grid(int _cols, int _rows){ 9 | grid = new ArrayList[_rows*_cols]; 10 | 11 | rows = _rows; 12 | cols = _cols; 13 | 14 | cellWidth = width/cols; 15 | cellHeight = height/rows; 16 | } 17 | 18 | void clear(){ 19 | for (int i = 0; i(); 36 | } 37 | grid[index].add(p); 38 | } 39 | 40 | ArrayList getCell(Particle p){ 41 | int index = getParticlePosition(p); 42 | return grid[index]; 43 | } 44 | 45 | ArrayList getNear(Particle p){ 46 | ArrayList objects = new ArrayList(); 47 | 48 | int xpos = floor(p.location.x/cellWidth); 49 | int ypos = floor(p.location.y/cellHeight); 50 | 51 | int xstart = constrain(xpos-1,0,cols); 52 | int ystart = constrain(ypos-1,0,rows); 53 | int xend = constrain(xpos+2,0,cols); 54 | int yend = constrain(ypos+2,0,rows); 55 | 56 | for (int x = xstart; x objects = getNear(p); 68 | for (int i = objects.size()-1; i>=0; i--){ 69 | Particle tempP = objects.get(i); 70 | PVector dist = PVector.sub(p.location,tempP.location); 71 | if (dist.magSq() > radius*radius){ 72 | objects.remove(i); 73 | } 74 | } 75 | 76 | return objects; 77 | } 78 | 79 | void drawGrid(){ 80 | for (int i = 0; i < cols; i++){ 81 | line (cellWidth*i,0,cellWidth*i,height); 82 | } 83 | for (int i = 0; i < rows; i++){ 84 | line (0,i*cellHeight,width,i*cellHeight); 85 | 86 | } 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /complexity_gridOptimization/Particle.pde: -------------------------------------------------------------------------------- 1 | // The Nature of Code 2 | // Daniel Shiffman 3 | // http://natureofcode.com 4 | 5 | class Particle { 6 | 7 | PVector location; 8 | PVector velocity; 9 | PVector acceleration; 10 | PVector force,friction; 11 | float mass,r,distance,loc; 12 | float maxForce, maxSpeed,strength; 13 | int id,val; 14 | color c; 15 | float k = 0.02; 16 | int age = 0; 17 | int spawnAge = (int)random(80,120); 18 | float minr = 0; 19 | float maxr = 5.0; 20 | boolean spawned = false; 21 | 22 | Particle(float x, float y,int _id) { 23 | mass = 2; 24 | id = _id; 25 | r = 2; 26 | maxSpeed = 0.1; 27 | maxForce = 50; 28 | location = new PVector(constrain(x,r,width-r), constrain(y,r,height-r)); 29 | velocity = new PVector(0, 0); 30 | acceleration = new PVector(0, 0); 31 | } 32 | 33 | void applyForce(PVector force) { 34 | //PVector f = PVector.div(force, mass); 35 | acceleration.add(force); 36 | } 37 | 38 | void update() { 39 | velocity.add(acceleration); 40 | velocity.limit(maxSpeed); 41 | location.add(velocity); 42 | acceleration.mult(0); 43 | friction(); 44 | borders(); 45 | age+=1; 46 | } 47 | 48 | void friction(){ 49 | friction = velocity.copy(); 50 | friction.mult(-1); 51 | friction.normalize(); 52 | friction.mult(k); 53 | 54 | applyForce(friction); 55 | } 56 | 57 | void display() { 58 | 59 | ellipse(location.x,location.y,r*2,r*2); 60 | } 61 | 62 | PVector attract(Particle p) { 63 | force = PVector.sub(p.location,location); // Calculate direction of force 64 | distance = force.magSq(); 65 | 66 | distance = constrain(distance, 1.0, 5000.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects 67 | force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction 68 | 69 | strength = (g) / (distance*4*PI); // Calculate gravitional force magnitude 70 | force.mult(strength); // Get force vector --> magnitude * direction 71 | return force; 72 | 73 | 74 | } 75 | 76 | void setRadius (PImage img){ 77 | 78 | loc = (int)location.x + (int)location.y*img.width; 79 | //c= img.get((int)location.x,(int)location.y); 80 | //c = img.pixels[int(loc)]; 81 | val = img.pixels[int(loc)] & 0xFF; 82 | r= lerp(r,map(val,0.0,255.0,minr,maxr),0.01); 83 | 84 | } 85 | 86 | void borders() { 87 | if ( location.x < r || location.x > width-r){ 88 | velocity.x = -velocity.x; 89 | } 90 | if ( location.y < r || location.y > height-r){ 91 | velocity.y = -velocity.y; 92 | } 93 | 94 | if (location.x> width-r) location.x = width-r; 95 | if (location.x< r) location.x = r; 96 | if (location.y> height-r) location.y = height-r; 97 | if (location.y< r) location.y = r; 98 | 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /complexity_gridOptimization/Quadtree.pde: -------------------------------------------------------------------------------- 1 | class Quadtree { 2 | private int maxObjects = 10; 3 | private int maxLevels = 5; 4 | 5 | private int level; 6 | private ArrayList objects; 7 | private Rectangle bounds; 8 | private Quadtree[] nodes; 9 | 10 | public Quadtree(int pLevel, Rectangle pBounds){ 11 | level = pLevel; 12 | objects = new ArrayList(); 13 | bounds = pBounds; 14 | nodes = new Quadtree[4]; 15 | } 16 | 17 | void clear() { 18 | if (objects.size() > 0){ 19 | objects.clear(); 20 | } 21 | for (int i = 0; i < nodes.length; i++) { 22 | if (nodes[i] != null) { 23 | nodes[i].clear(); 24 | nodes[i] = null; 25 | } 26 | } 27 | } 28 | 29 | void split() { 30 | int subWidth = (int)(bounds.getWidth() / 2); 31 | int subHeight = (int)(bounds.getHeight() / 2); 32 | int x = (int)bounds.getX(); 33 | int y = (int)bounds.getY(); 34 | 35 | nodes[0] = new Quadtree(level+1, new Rectangle(x + subWidth, y, subWidth, subHeight)); 36 | nodes[1] = new Quadtree(level+1, new Rectangle(x, y, subWidth, subHeight)); 37 | nodes[2] = new Quadtree(level+1, new Rectangle(x, y + subHeight, subWidth, subHeight)); 38 | nodes[3] = new Quadtree(level+1, new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight)); 39 | } 40 | 41 | 42 | 43 | private int getIndex(Particle pParticle) { 44 | int index = -1; 45 | double verticalMidpoint = bounds.getX() + (bounds.getWidth() / 2); 46 | double horizontalMidpoint = bounds.getY() + (bounds.getHeight() / 2); 47 | 48 | // Object can completely fit within the top quadrants 49 | boolean topQuadrant = (pParticle.location.y + pParticle.r < horizontalMidpoint); 50 | // Object can completely fit within the bottom quadrants 51 | boolean bottomQuadrant = (pParticle.location.y - pParticle.r > horizontalMidpoint); 52 | 53 | // Object can completely fit within the left quadrants 54 | if (pParticle.location.x + pParticle.r < verticalMidpoint) { 55 | if (topQuadrant) { 56 | index = 1; 57 | } 58 | else if (bottomQuadrant) { 59 | index = 2; 60 | } 61 | } 62 | // Object can completely fit within the right quadrants 63 | else if (pParticle.location.x - pParticle.r > verticalMidpoint) { 64 | if (topQuadrant) { 65 | index = 0; 66 | } 67 | else if (bottomQuadrant) { 68 | index = 3; 69 | } 70 | } 71 | 72 | return index; 73 | } 74 | 75 | /* 76 | * Insert the object into the quadtree. If the node 77 | * exceeds the capacity, it will split and add all 78 | * objects to their corresponding nodes. 79 | */ 80 | void insert(Particle pParticle) { 81 | if (nodes[0] != null) { 82 | int index = getIndex(pParticle); 83 | 84 | if (index != -1) { 85 | nodes[index].insert(pParticle); 86 | 87 | return; 88 | } 89 | } 90 | 91 | objects.add(pParticle); 92 | 93 | if (objects.size() > maxObjects && level < maxLevels) { 94 | if (nodes[0] == null) { 95 | split(); 96 | } 97 | 98 | int i = 0; 99 | while (i < objects.size()) { 100 | int index = getIndex((Particle)objects.get(i)); 101 | if (index != -1) { 102 | nodes[index].insert((Particle)objects.remove(i)); 103 | } 104 | else { 105 | i++; 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | List retrieve(List returnObjects, Particle pParticle) { 113 | int index = getIndex(pParticle); 114 | if (nodes[0] != null){ 115 | if (index != -1) { 116 | nodes[index].retrieve(returnObjects, pParticle); 117 | returnObjects.addAll(objects); 118 | }else{ 119 | for (int i = 0; i particles; 8 | ArrayList check; 9 | Particle newp; 10 | Grid qt; 11 | PGraphics circle; 12 | 13 | int nParticles = 15000; 14 | int count = 0; 15 | PImage img; 16 | float rythm = 0; 17 | float growRatio = 0.8; 18 | Particle p; 19 | float g = 50.0; 20 | boolean debugMode = false; 21 | int debugId = 0; 22 | float distance = 2; 23 | float angle = random(TWO_PI); 24 | 25 | void setup(){ 26 | size(1200, 700,OPENGL); 27 | pixelDensity(2); 28 | 29 | img = loadImage("background3.jpg"); 30 | img.loadPixels(); 31 | 32 | sprite = loadImage("sprite.png"); 33 | 34 | 35 | qt = new Grid(48,28); 36 | particles = new ArrayList(); 37 | check = new ArrayList(); 38 | for (int i=0; i<1; i++){ 39 | particles.add(new Particle(width/2+1,height/2,count)); 40 | count++; 41 | } 42 | noStroke(); 43 | fill(255); 44 | hint(DISABLE_DEPTH_MASK); 45 | hint(DISABLE_DEPTH_TEST); 46 | //hint(ENABLE_ACCURATE_2D); 47 | } 48 | 49 | void draw(){ 50 | 51 | background(0); 52 | fill(255); 53 | 54 | qt.clear(); 55 | 56 | for (int i = 0; i < particles.size(); i++) { 57 | qt.insert(particles.get(i)); 58 | 59 | } 60 | for (int i = particles.size()-1; i >= 0; i--) { 61 | p = particles.get(i); 62 | check = qt.getInsideCircle(p,30); 63 | for (int j = 0; j < check.size(); j++){ 64 | if (p.id != check.get(j).id){ 65 | p.applyForce(check.get(j).attract(p)); 66 | } 67 | } 68 | 69 | p.setRadius(img); 70 | p.update(); 71 | drawParticle(p); 72 | //p.display(); 73 | 74 | if (p.age > p.spawnAge && p.velocity.magSq() < 1 && !p.spawned && count(); 36 | } 37 | grid[index].add(p); 38 | } 39 | 40 | ArrayList getCell(Particle p){ 41 | int index = getParticlePosition(p); 42 | return grid[index]; 43 | } 44 | 45 | ArrayList getNear(Particle p){ 46 | ArrayList objects = new ArrayList(); 47 | 48 | int index = getParticlePosition(p); 49 | objects.addAll(grid[index]); 50 | 51 | if (grid[index-1] != null) objects.addAll(grid[index-1]); 52 | if (grid[index+1] != null) objects.addAll(grid[index+1]); 53 | 54 | if (grid[index-rows] != null) objects.addAll(grid[index-rows]); 55 | if (grid[index-rows-1] != null) objects.addAll(grid[index-rows-1]); 56 | if (grid[index-rows+1] != null) objects.addAll(grid[index-rows+1]); 57 | 58 | if (grid[index+rows] != null) objects.addAll(grid[index+rows]); 59 | if (grid[index+rows-1] != null) objects.addAll(grid[index+rows-1]); 60 | if (grid[index+rows+1] != null) objects.addAll(grid[index+rows+1]); 61 | 62 | return objects; 63 | } 64 | 65 | ArrayList getInsideCircle(Particle p, float radius){ 66 | ArrayList objects = getNear(p); 67 | for (int i = objects.size()-1; i>=0; i--){ 68 | Particle tempP = objects.get(i); 69 | PVector dist = PVector.sub(p.location,tempP.location); 70 | if (dist.magSq() > radius*radius){ 71 | objects.remove(i); 72 | } 73 | } 74 | 75 | return objects; 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /complexity_quadTree/Particle.pde: -------------------------------------------------------------------------------- 1 | // The Nature of Code 2 | // Daniel Shiffman 3 | // http://natureofcode.com 4 | 5 | class Particle { 6 | 7 | PVector location; 8 | PVector velocity; 9 | PVector acceleration; 10 | PVector force,friction; 11 | float mass,r,distance,loc; 12 | float maxForce, maxSpeed,strength; 13 | int id,val; 14 | color c; 15 | float k = 0.001; 16 | int age = 0; 17 | int spawnAge = (int)random(80,120); 18 | float minr = 1.0; 19 | float maxr = 5.0; 20 | boolean spawned = false; 21 | 22 | Particle(float x, float y,int _id) { 23 | mass = 2; 24 | id = _id; 25 | r = 2; 26 | maxSpeed = 0.1; 27 | maxForce = 2; 28 | location = new PVector(x, y); 29 | velocity = new PVector(0, 0); 30 | acceleration = new PVector(0, 0); 31 | } 32 | 33 | void applyForce(PVector force) { 34 | //PVector f = PVector.div(force, mass); 35 | acceleration.add(force); 36 | } 37 | 38 | void update() { 39 | velocity.add(acceleration); 40 | velocity.limit(maxSpeed); 41 | location.add(velocity); 42 | acceleration.mult(0); 43 | //friction(); 44 | borders(); 45 | age+=1; 46 | } 47 | 48 | void friction(){ 49 | friction = velocity.copy(); 50 | friction.mult(-1); 51 | friction.normalize(); 52 | friction.mult(k); 53 | 54 | applyForce(friction); 55 | } 56 | 57 | void display() { 58 | 59 | ellipse(location.x,location.y,r*2,r*2); 60 | } 61 | 62 | PVector attract(Particle p) { 63 | force = PVector.sub(p.location,location); // Calculate direction of force 64 | distance = force.magSq(); 65 | 66 | distance = constrain(distance, 1.0, 5000.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects 67 | force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction 68 | 69 | strength = (g) / (distance*4*PI); // Calculate gravitional force magnitude 70 | force.mult(strength); // Get force vector --> magnitude * direction 71 | return force; 72 | 73 | 74 | } 75 | 76 | void setRadius (PImage img){ 77 | 78 | loc = (int)location.x + (int)location.y*img.width; 79 | //c= img.get((int)location.x,(int)location.y); 80 | //c = img.pixels[int(loc)]; 81 | val = img.pixels[int(loc)] & 0xFF; 82 | r= lerp(r,map(val,0.0,255.0,minr,maxr),0.01); 83 | 84 | } 85 | 86 | void borders() { 87 | if ( location.x < r || location.x > width-r){ 88 | velocity.x = -velocity.x; 89 | } 90 | if ( location.y < r || location.y > height-r){ 91 | velocity.y = -velocity.y; 92 | } 93 | 94 | if (location.x> width-r) location.x = width-r; 95 | if (location.x< r) location.x = r; 96 | if (location.y> height-r) location.y = height-r; 97 | if (location.y< r) location.y = r; 98 | 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /complexity_quadTree/Quadtree.pde: -------------------------------------------------------------------------------- 1 | class Quadtree { 2 | private int maxObjects = 10; 3 | private int maxLevels = 5; 4 | 5 | private int level; 6 | private ArrayList objects; 7 | private Rectangle bounds; 8 | private Quadtree[] nodes; 9 | 10 | public Quadtree(int pLevel, Rectangle pBounds){ 11 | level = pLevel; 12 | objects = new ArrayList(); 13 | bounds = pBounds; 14 | nodes = new Quadtree[4]; 15 | } 16 | 17 | void clear() { 18 | if (objects.size() > 0){ 19 | objects.clear(); 20 | } 21 | for (int i = 0; i < nodes.length; i++) { 22 | if (nodes[i] != null) { 23 | nodes[i].clear(); 24 | nodes[i] = null; 25 | } 26 | } 27 | } 28 | 29 | void split() { 30 | int subWidth = (int)(bounds.getWidth() / 2); 31 | int subHeight = (int)(bounds.getHeight() / 2); 32 | int x = (int)bounds.getX(); 33 | int y = (int)bounds.getY(); 34 | 35 | nodes[0] = new Quadtree(level+1, new Rectangle(x + subWidth, y, subWidth, subHeight)); 36 | nodes[1] = new Quadtree(level+1, new Rectangle(x, y, subWidth, subHeight)); 37 | nodes[2] = new Quadtree(level+1, new Rectangle(x, y + subHeight, subWidth, subHeight)); 38 | nodes[3] = new Quadtree(level+1, new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight)); 39 | } 40 | 41 | 42 | 43 | private int getIndex(Particle pParticle) { 44 | int index = -1; 45 | double verticalMidpoint = bounds.getX() + (bounds.getWidth() / 2); 46 | double horizontalMidpoint = bounds.getY() + (bounds.getHeight() / 2); 47 | 48 | // Object can completely fit within the top quadrants 49 | boolean topQuadrant = (pParticle.location.y < horizontalMidpoint); 50 | // Object can completely fit within the bottom quadrants 51 | boolean bottomQuadrant = (pParticle.location.y >= horizontalMidpoint); 52 | 53 | // Object can completely fit within the left quadrants 54 | if (pParticle.location.x < verticalMidpoint) { 55 | if (topQuadrant) { 56 | index = 1; 57 | } 58 | else if (bottomQuadrant) { 59 | index = 2; 60 | } 61 | } 62 | // Object can completely fit within the right quadrants 63 | else if (pParticle.location.x >= verticalMidpoint) { 64 | if (topQuadrant) { 65 | index = 0; 66 | } 67 | else if (bottomQuadrant) { 68 | index = 3; 69 | } 70 | } 71 | 72 | return index; 73 | } 74 | 75 | /* 76 | * Insert the object into the quadtree. If the node 77 | * exceeds the capacity, it will split and add all 78 | * objects to their corresponding nodes. 79 | */ 80 | void insert(Particle pParticle) { 81 | if (nodes[0] != null) { 82 | int index = getIndex(pParticle); 83 | 84 | if (index != -1) { 85 | nodes[index].insert(pParticle); 86 | 87 | return; 88 | } 89 | } 90 | 91 | objects.add(pParticle); 92 | 93 | if (objects.size() > maxObjects && level < maxLevels) { 94 | if (nodes[0] == null) { 95 | split(); 96 | } 97 | 98 | int i = 0; 99 | while (i < objects.size()) { 100 | int index = getIndex((Particle)objects.get(i)); 101 | if (index != -1) { 102 | nodes[index].insert((Particle)objects.remove(i)); 103 | } 104 | else { 105 | i++; 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | public List retrieve(List returnObjects, Particle p) { 113 | int index = getIndex(p); 114 | if (index != -1 && nodes[0] != null) { 115 | nodes[index].retrieve(returnObjects, p); 116 | } 117 | 118 | returnObjects.addAll(objects); 119 | 120 | return returnObjects; 121 | } 122 | } -------------------------------------------------------------------------------- /complexity_quadTree/complexity_quadTree.pde: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.awt.Rectangle; 3 | 4 | Quadtree qt; 5 | ArrayList particles; 6 | ArrayList check; 7 | Particle p; 8 | 9 | float g = 0.3; 10 | 11 | 12 | boolean debugMode; 13 | int debugId = 0; 14 | 15 | void setup(){ 16 | size(600,600); 17 | qt = new Quadtree(0, new Rectangle(0,0,600,600)); 18 | particles = new ArrayList(); 19 | check = new ArrayList(); 20 | for (int i = 0; i < 1000; i++){ 21 | particles.add(new Particle(random(width),random(height),i)); 22 | } 23 | } 24 | 25 | void draw(){ 26 | background(0); 27 | fill(255); 28 | qt.clear(); 29 | for (int i = 0; i < particles.size(); i++) { 30 | qt.insert(particles.get(i)); 31 | } 32 | 33 | for (int i = 0; i < particles.size(); i++) { 34 | p = particles.get(i); 35 | 36 | check.clear(); 37 | qt.retrieve(check, p); 38 | 39 | for (int j = 0; j < check.size(); j++){ 40 | if (p.id != check.get(j).id){ 41 | p.applyForce(check.get(j).attract(p)); 42 | } 43 | } 44 | p.update(); 45 | p.display(); 46 | } 47 | 48 | if (debugMode){ 49 | p = particles.get(debugId); 50 | fill(255,0,0); 51 | p.display(); 52 | fill(0,255,0); 53 | check.clear(); 54 | qt.retrieve(check, p); 55 | println(check.size()); 56 | for (int j = 0; j < check.size(); j++){ 57 | if (p.id != check.get(j).id){ 58 | check.get(j).display(); 59 | } 60 | } 61 | } 62 | 63 | } 64 | 65 | 66 | void keyPressed(){ 67 | if (key=='d'){ 68 | debugMode = !debugMode; 69 | println(particles.get(debugId).id); 70 | } 71 | } -------------------------------------------------------------------------------- /curves_and_probability/curves_and_probability.pde: -------------------------------------------------------------------------------- 1 | size(1650, 1100); 2 | float p = 0.00; 3 | 4 | for (int i = 0; i<100; i++) { 5 | float h = pow( 1-p, 4); 6 | //float h = pow( p, 4); 7 | rect(25+i*5, 180, 3, -h*100); 8 | p+= 0.01; 9 | } 10 | 11 | p = 0.00; 12 | for (int i = 0; i<100; i++) { 13 | float h = pow( p, 4); 14 | //float h = pow( p, 4); 15 | rect(25+i*5, 380, 3, -h*100); 16 | p+= 0.01; 17 | } 18 | float[] rects = new float[100]; 19 | for (int i = 0; i< 5000; i++) { 20 | float xloc = randomGaussian(); 21 | 22 | float sd = 10; // Define a standard deviation 23 | float mean = 50; // Define a mean value (middle of the screen along the x-axis) 24 | xloc = (( xloc * sd ) + mean); 25 | //print(xloc,","); 26 | if (xloc >0 && xloc < 100){ 27 | rects[(int)xloc]+= 0.005; 28 | } 29 | } 30 | for (int i = 0; i<100; i++) { 31 | rect(25+i*5, 580, 3, -rects[i]*100); 32 | 33 | } 34 | 35 | float a = PI; 36 | 37 | 38 | for (int i = 0; i<100; i++) { 39 | float s = pow(sin(i*a/100),5); 40 | rect(25+i*5, 780, 3, -s*100); 41 | 42 | } 43 | 44 | for (int i = 0; i<100; i++) { 45 | float s = pow(1-sin(i*a/100),2); 46 | rect(25+i*5, 980, 3, -s*100); 47 | 48 | } 49 | 50 | 51 | p = 0; 52 | for (int i = 0; i<100; i++) { 53 | float x = i*a/100; 54 | float s = pow(sin(x),2)*pow(p,4); 55 | //print(x,","); 56 | rect(575+i*5, 180, 3, -s*100); 57 | p+= 0.015; 58 | } 59 | 60 | p = 0; 61 | for (int i = 0; i<100; i++) { 62 | float x = i*a/100; 63 | float s = pow(sin(x),2)*pow(1-p,4); 64 | rect(575+i*5, 380, 3, -s*600); 65 | p+= 0.01; 66 | } 67 | 68 | p = 0; 69 | for (int i = 0; i<100; i++) { 70 | float x = noise(p); 71 | rect(575+i*5, 580, 3, -x*100); 72 | p+= 0.05; 73 | } 74 | 75 | for (int i = 0; i<100; i++) { 76 | float x = random(1); 77 | rect(575+i*5, 780, 3, -x*100); 78 | } 79 | 80 | for (int i = 0; i<100; i++) { 81 | float x = 0; 82 | while(true){ 83 | p = random(1); 84 | x = random(1); 85 | if (p < x){ 86 | break; 87 | } 88 | } 89 | rect(575+i*5, 980, 3, -x*100); 90 | } 91 | 92 | p = 0.00; 93 | for (int i = 0; i<100; i++) { 94 | float h = log(p); 95 | 96 | //float h = pow( p, 4); 97 | rect(1125+i*5, 180, 3, h*25); 98 | p+= 0.01; 99 | } 100 | 101 | fill(0); 102 | noStroke(); 103 | text("(1-x)^n", 25, 200); 104 | text("x^n", 25, 400); 105 | text("gaussian 1000 samples", 25, 600); 106 | text("(sin(x))^n", 25, 800); 107 | text("(1-sin(x))^n", 25, 1000); 108 | text("(sin(x))^n * x^n", 575, 200); 109 | text("(sin(x))^n * (1-x)^n", 575, 400); 110 | text("perlin noise", 575, 600); 111 | text("random", 575, 800); 112 | text("montecarlo", 575, 1000); -------------------------------------------------------------------------------- /delaunay_portraits/delaunay_portraits.pde: -------------------------------------------------------------------------------- 1 | import megamu.mesh.*; 2 | import controlP5.*; 3 | 4 | ControlP5 cp5; 5 | controlP5.Toggle c,d,e; 6 | PImage[] images; 7 | PImage image; 8 | int seed,x,y,p; 9 | int particles = 10000; 10 | float power,mvalue,ratio,posx,posy,deltaX,deltaY,tStep; 11 | float startX,startY,endX,endY; 12 | float[][] points; 13 | Delaunay myDelaunay; 14 | float[][] myEdges; 15 | color c1,c2; 16 | boolean re, colorMode,drawDelaunay,lightMode,showGui = true; 17 | 18 | 19 | void setup(){ 20 | size(1280,720,P2D); 21 | pixelDensity(2); 22 | //noLoop(); 23 | power = 1; 24 | particles = 10000; 25 | cp5 = new ControlP5(this); 26 | cp5.addSlider("source") 27 | .setPosition(50,20) 28 | .setSize(50,10) 29 | .setRange(0,6) 30 | .setNumberOfTickMarks(7) 31 | ; 32 | cp5.addSlider("particles").setPosition(50,50).setRange(0,20000); 33 | cp5.addSlider("power").setPosition(50,80).setRange(0.5,8.0); 34 | c= cp5.addToggle("toggle") 35 | .setPosition(50,110) 36 | .setSize(50,10) 37 | .setValue(true) 38 | .setMode(ControlP5.SWITCH); 39 | 40 | d= cp5.addToggle("toggle2") 41 | .setPosition(50,140) 42 | .setSize(50,10) 43 | .setValue(true) 44 | .setMode(ControlP5.SWITCH); 45 | 46 | e= cp5.addToggle("toggle3") 47 | .setPosition(50,170) 48 | .setSize(50,10) 49 | .setValue(true) 50 | .setMode(ControlP5.SWITCH); 51 | 52 | c.setLabel("Color"); 53 | d.setLabel("Draw Delaunay"); 54 | e.setLabel("Light or Dark"); 55 | images = new PImage[7]; 56 | for (int i=0; i< images.length;i++){ 57 | images[i] = loadImage("source"+i+".jpg"); 58 | images[i].loadPixels(); 59 | } 60 | image = images[0]; 61 | } 62 | 63 | 64 | void draw(){ 65 | // println(re); 66 | 67 | if (re == true){ 68 | re = false; 69 | println(colorMode); 70 | particles = (int)cp5.getController("particles").getValue(); 71 | power = cp5.getController("power").getValue(); 72 | ratio = min(float(width-50)/(float)image.width,float(height-50)/ (float)image.height); 73 | posx = (width-image.width*ratio)/2; 74 | posy = (height-image.height*ratio)/2; 75 | 76 | background(0); 77 | noFill(); 78 | noStroke(); 79 | if(colorMode){ 80 | background(image.get(0,0)); 81 | } 82 | 83 | points = new float[particles][2]; 84 | println(image.width,image.height); 85 | while (particles > 0){ 86 | x = (int)random(image.width); 87 | y = (int)random(image.height); 88 | p = x+y*image.width; 89 | mvalue = map(brightness(image.pixels[p]),0,255,1,0); 90 | // println(mvalue,value); 91 | 92 | 93 | if(!drawDelaunay){ 94 | fill(255); 95 | } 96 | boolean condition; 97 | if (lightMode){ 98 | condition = random(1.0) < pow(mvalue,power); 99 | }else{ 100 | condition = random(1.0) < pow(1 - mvalue,power); 101 | } 102 | 103 | 104 | if(condition){ 105 | particles--; 106 | points[particles][0] = x; 107 | points[particles][1] = y; 108 | 109 | if(!drawDelaunay){ 110 | if (colorMode){ 111 | fill(image.get(x,y)); 112 | } 113 | ellipse(posx+x*ratio,posy+y*ratio,2,2); 114 | } 115 | } 116 | } 117 | 118 | if (drawDelaunay){ 119 | myDelaunay = new Delaunay( points ); 120 | myEdges = myDelaunay.getEdges(); 121 | //stroke(0); 122 | for(int i=0; i particles) { 36 | PVector separateForce = separate(particles); 37 | PVector seekForce = seek(new PVector(width/2,height/2)); 38 | separateForce.mult(1.5); 39 | seekForce.mult(1); 40 | applyForce(separateForce); 41 | applyForce(seekForce); 42 | //collide(particles); 43 | } 44 | 45 | PVector seek(PVector target){ 46 | PVector desired = PVector.sub(target,location); 47 | desired.normalize(); 48 | desired.mult(maxSpeed); 49 | 50 | PVector steer = PVector.sub(desired,velocity); 51 | steer.limit(maxForce); 52 | return steer; 53 | } 54 | void collide(ArrayList particles){ 55 | 56 | for (Particle other : particles){ 57 | collideEqualMass(other); 58 | } 59 | } 60 | 61 | PVector cohesion(ArrayList particles){ 62 | float desiredSep = 1000; 63 | PVector sum = new PVector(); 64 | int count = 0; 65 | for (Particle other : particles){ 66 | float d = PVector.dist(location, other.location); 67 | if ((d > 0) && (d < desiredSep)){ 68 | sum.add(other.location); 69 | count++; 70 | } 71 | } 72 | if (count > 0){ 73 | return seek(sum); 74 | }else{ 75 | return new PVector(0,0); 76 | } 77 | } 78 | 79 | void collideEqualMass(Particle other) { 80 | float d = PVector.dist(location,other.location); 81 | float sumR = r + other.r; 82 | // Are they colliding? 83 | if (!colliding && d < sumR) { 84 | // Yes, make new velocities! 85 | colliding = true; 86 | println("colliding"); 87 | // Direction of one object another 88 | PVector n = PVector.sub(other.location,location); 89 | n.normalize(); 90 | 91 | // Difference of velocities so that we think of one object as stationary 92 | PVector u = PVector.sub(velocity,other.velocity); 93 | 94 | // Separate out components -- one in direction of normal 95 | PVector un = componentVector(u,n); 96 | // Other component 97 | u.sub(un); 98 | // These are the new velocities plus the velocity of the object we consider as stastionary 99 | velocity = PVector.add(u,other.velocity); 100 | other.velocity = PVector.add(un,other.velocity); 101 | } 102 | else if (d > sumR) { 103 | colliding = false; 104 | } 105 | } 106 | 107 | PVector separate(ArrayList particles){ 108 | PVector sum = new PVector(); 109 | int count = 0; 110 | for (Particle other : particles){ 111 | 112 | float d = PVector.dist(location, other.location); 113 | 114 | if ((d > 0) && (d < (r+other.r))){ 115 | PVector diff = PVector.sub (location,other.location); 116 | diff.normalize(); 117 | diff.div(d); 118 | sum.add(diff); 119 | stroke(250); 120 | line (location.x,location.y,other.location.x,other.location.y); 121 | noStroke(); 122 | count++; 123 | } 124 | } 125 | if (count > 0){ 126 | sum.div(count); 127 | sum.normalize(); 128 | sum.setMag(maxSpeed); 129 | sum.sub(velocity); 130 | sum.limit(maxForce); 131 | } 132 | return sum; 133 | } 134 | 135 | 136 | 137 | void display(){ 138 | stroke(c,50,50,150); 139 | noFill(); 140 | pushMatrix(); 141 | translate(location.x,location.y); 142 | ellipse(0,0,r*2,r*2); 143 | popMatrix(); 144 | } 145 | 146 | void borders() { 147 | if (location.x < -r) location.x = width+r; 148 | if (location.y < -r) location.y = height+r; 149 | if (location.x > width+r) location.x = -r; 150 | if (location.y > height+r) location.y = -r; 151 | } 152 | } 153 | 154 | PVector componentVector (PVector vector, PVector directionVector) { 155 | //--! ARGUMENTS: vector, directionVector (2D vectors) 156 | //--! RETURNS: the component vector of vector in the direction directionVector 157 | //-- normalize directionVector 158 | directionVector.normalize(); 159 | directionVector.mult(vector.dot(directionVector)); 160 | return directionVector; 161 | } -------------------------------------------------------------------------------- /particles_attraction_repulsion/particles_attraction_repulsion.pde: -------------------------------------------------------------------------------- 1 | ArrayList particles; 2 | 3 | void setup(){ 4 | size(1280,720); 5 | particles = new ArrayList(); 6 | } 7 | 8 | void draw(){ 9 | background(20,10,50); 10 | for (Particle p : particles){ 11 | p.applyBehaviors(particles); 12 | p.update(); 13 | p.display(); 14 | } 15 | } 16 | 17 | void mousePressed(){ 18 | particles.add(new Particle(mouseX,mouseY)); 19 | } -------------------------------------------------------------------------------- /particles_magneticFlowField/Attractor.pde: -------------------------------------------------------------------------------- 1 | class Attractor{ 2 | PVector position; 3 | float strength; 4 | float distance; 5 | float mass = 1; 6 | 7 | public Attractor(PVector pos, float s){ 8 | position = pos.copy(); 9 | strength = s; 10 | } 11 | 12 | void display(){ 13 | 14 | if (strength > 0){ 15 | //stroke(255); 16 | fill(30); 17 | }else{ 18 | noStroke(); 19 | fill(255); 20 | } 21 | ellipse(position.x,position.y,10,10); 22 | noStroke(); 23 | } 24 | 25 | 26 | PVector attract(Particle p) { 27 | PVector force = PVector.sub(position ,p.position); // Calculate direction of force 28 | float d = force.mag(); // Distance between objects 29 | d = constrain(d,1.0,10.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects 30 | force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction) 31 | float str = (strength * mass * p.mass) / (d * d * 4 * PI); // Calculate gravitional force magnitude 32 | force.mult(str); // Get force vector --> magnitude * direction 33 | return force; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /particles_magneticFlowField/Field.pde: -------------------------------------------------------------------------------- 1 | class Field{ 2 | PVector[][] field; 3 | ArrayList attractors; 4 | int cols, rows; 5 | int resolution; 6 | boolean noised,rotation = false; 7 | 8 | float distance = 50.0; 9 | float angle = 0; 10 | float t = 0; 11 | 12 | public Field (int r){ 13 | resolution = r; 14 | cols = width/resolution; 15 | rows = height/resolution; 16 | field = new PVector[cols][rows]; 17 | 18 | initField(); 19 | } 20 | 21 | void initField(){ 22 | for (int x = 0; x < cols; ++x){ 23 | for (int y = 0; y < rows; ++y){ 24 | PVector v = new PVector(0,0); 25 | field[x][y] = v; 26 | } 27 | } 28 | } 29 | 30 | void update(){ 31 | float weight = 0; 32 | t += 0.01; 33 | float offx = 0; 34 | float offy = 0; 35 | initField(); 36 | 37 | if (attractors.size() > 0){ 38 | for (Attractor a : attractors){ 39 | PVector pos = a.position; 40 | for (int x = 0; x < cols; ++x){ 41 | offy = 0; 42 | for (int y = 0; y < rows; ++y){ 43 | PVector force = PVector.sub(pos,new PVector(x*resolution,y*resolution)); 44 | float d = force.mag(); 45 | d = constrain(d,1.0,distance); 46 | float str = (a.strength*50) / (d * d * PI * 4 ); 47 | angle = force.heading(); 48 | if (rotation) angle += HALF_PI; 49 | if (noised)angle += map(noise(offx,offy,t),0,1,-PI/4,PI/4); 50 | //if (a.strength<0) angle+=PI; 51 | PVector v = new PVector(cos(angle),sin(angle)); 52 | v.normalize(); 53 | v.mult(str); 54 | field[x][y].add(v); 55 | offy+=0.05; 56 | } 57 | offx+=0.05; 58 | } 59 | } 60 | } 61 | 62 | 63 | 64 | } 65 | 66 | void display(){ 67 | //background(0); 68 | stroke(255,0,0,100); 69 | for (int x = 0; x < cols; ++x){ 70 | for (int y = 0; y < rows; ++y){ 71 | drawVector(field[x][y], x*resolution, y*resolution, resolution -2); 72 | } 73 | } 74 | noStroke(); 75 | } 76 | 77 | 78 | void drawVector(PVector v, float x, float y, float scale){ 79 | PVector vec =v.copy(); 80 | vec.normalize(); 81 | float len = vec.mag()*scale; 82 | 83 | pushMatrix(); 84 | translate(x,y); 85 | rotate(v.heading()); 86 | line(0, 0, len, 0); 87 | popMatrix(); 88 | } 89 | 90 | PVector lookup(PVector lookup){ 91 | 92 | int column = int(constrain(lookup.x/resolution+1,0,cols-1)); 93 | int row = int(constrain(lookup.y/resolution+1,0,rows-1)); 94 | 95 | int left =constrain(column-1,0,cols); 96 | int down = constrain(row-1,0,rows); 97 | 98 | PVector v = field[column][row].copy(); 99 | v.add(field[left][row].copy()); 100 | v.add(field[column][down].copy()); 101 | v.add(field[left][row].copy()); 102 | v.div(4); 103 | return v; 104 | } 105 | 106 | } -------------------------------------------------------------------------------- /particles_magneticFlowField/Particle.pde: -------------------------------------------------------------------------------- 1 | class Particle{ 2 | PVector position, velocity, acceleration; 3 | float maxSpeed, maxForce; 4 | 5 | float radius, mass,angle; 6 | int lifeSpan = floor(random(50,100)); 7 | 8 | public Particle(PVector pos, float maxspeed, float maxforce){ 9 | position = new PVector (pos.x,pos.y); 10 | velocity = new PVector(0,0); 11 | acceleration = new PVector(0,0); 12 | 13 | maxSpeed = maxspeed; 14 | maxForce = maxforce; 15 | 16 | mass = 1.0; 17 | radius = 1.0; 18 | } 19 | 20 | void update(){ 21 | velocity.add(acceleration); 22 | position.add(velocity); 23 | velocity.limit(maxSpeed); 24 | acceleration.mult(0); 25 | angle = velocity.heading(); 26 | lifeSpan--; 27 | } 28 | 29 | void display(PGraphics l){ 30 | 31 | l.pushMatrix(); 32 | l.translate(position.x,position.y); 33 | l.rotate(angle); 34 | l.line(0,0,velocity.mag()*2,0); 35 | 36 | l.popMatrix(); 37 | } 38 | 39 | void applyForce(PVector force){ 40 | PVector f = force.copy(); 41 | f.div(mass); 42 | acceleration.add(f); 43 | } 44 | 45 | void follow(Field field){ 46 | PVector desired = field.lookup(position); 47 | desired.mult(maxSpeed); 48 | 49 | PVector steer = PVector.sub(desired,velocity); 50 | steer.limit(maxForce); 51 | applyForce(steer); 52 | } 53 | 54 | void run(PGraphics l){ 55 | update(); 56 | //borders(); 57 | display(l); 58 | } 59 | 60 | boolean isDead(){ 61 | if (lifeSpan < 0) { 62 | return true; 63 | } else { 64 | return false; 65 | } 66 | } 67 | 68 | // Wraparound 69 | void borders() { 70 | if (position.x < - radius) position.x = width + radius; 71 | if (position.y < - radius) position.y = height + radius; 72 | if (position.x > width + radius) position.x = - radius; 73 | if (position.y > height + radius) position.y = - radius; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /particles_magneticFlowField/particles_magneticFlowField.pde: -------------------------------------------------------------------------------- 1 | import controlP5.*; 2 | 3 | Field f; 4 | int totParticles = 10000; 5 | Particle[] particles; 6 | ArrayList attractors; 7 | boolean displayField, isDragging = false; 8 | int selected =-1; 9 | int strength = 300; 10 | 11 | float distance = 50.0; 12 | PGraphics particlesLayer; 13 | ControlP5 cp5; 14 | 15 | void setup(){ 16 | size(1280,720,P2D); 17 | pixelDensity(2); 18 | particlesLayer = createGraphics(1280, 720,P2D); 19 | particlesLayer.pixelDensity = 2; 20 | particlesLayer.beginDraw(); 21 | particlesLayer.background(0); 22 | particlesLayer.endDraw(); 23 | 24 | cp5 = new ControlP5(this); 25 | 26 | cp5.setColorForeground(0xffcccccc); 27 | cp5.setColorBackground(0xff111111); 28 | cp5.setColorActive(0xff666666); 29 | 30 | 31 | 32 | 33 | cp5.begin(100,50); 34 | cp5.addSlider("strength",0,1000).linebreak(); 35 | cp5.addSlider("distance",0,500).linebreak(); 36 | 37 | cp5.addToggle("toggle") 38 | .setSize(50,10) 39 | .setValue(true) 40 | .setCaptionLabel("rotation"); 41 | cp5.end(); 42 | 43 | f = new Field(8); 44 | attractors = new ArrayList(); 45 | f.attractors = attractors; 46 | 47 | particles = new Particle[totParticles]; 48 | for (int i = 0; i < totParticles; ++i){ 49 | particles[i] = new Particle(new PVector(random(width),random(height)), 4, 1); 50 | } 51 | 52 | } 53 | 54 | void draw(){ 55 | f.distance = distance; 56 | 57 | background(0); 58 | image(particlesLayer,0,0); 59 | noStroke(); 60 | 61 | f.update(); 62 | if (displayField) f.display(); 63 | 64 | //attractorsLayer.beginDraw(); 65 | //attractorsLayer.background(0,0); 66 | 67 | for (Attractor a : attractors){ 68 | a.display(); 69 | } 70 | //attractorsLayer.endDraw(); 71 | 72 | 73 | particlesLayer.beginDraw(); 74 | 75 | particlesLayer.blendMode(BLEND); 76 | particlesLayer.fill(0,10); 77 | particlesLayer.rect(0,0,width,height); 78 | //particlesLayer.stroke(255,30); 79 | particlesLayer.blendMode(ADD); 80 | for (int i = 0; i < particles.length; ++i){ 81 | 82 | Particle p = particles[i]; 83 | particlesLayer.stroke(255,map(p.velocity.mag(),0,p.maxSpeed,5,50)); 84 | //PVector force = new PVector(0,0); 85 | for (Attractor a : attractors){ 86 | //force.add(a.attract(p)); 87 | PVector dir = PVector.sub(a.position,p.position); 88 | if (dir.magSq() < 100){ 89 | p.lifeSpan = 0; 90 | }; 91 | 92 | 93 | //p.applyForce(force); 94 | } 95 | if (p.isDead()){ 96 | particles[i] = new Particle(new PVector(random(width),random(height)),10,0.5); 97 | } 98 | p.follow(f); 99 | p.run(particlesLayer); 100 | } 101 | particlesLayer.endDraw(); 102 | 103 | //image(attractorsLayer,0,0); 104 | //image(particlesLayer,0,0); 105 | } 106 | 107 | void keyPressed(){ 108 | if (key == 'd'){ 109 | displayField = !displayField; 110 | }else if ( key == 'n'){ 111 | f.noised = !f.noised; 112 | }else if (key == 'h'){ 113 | cp5.setVisible(!cp5.isVisible()); 114 | } 115 | } 116 | 117 | void mousePressed(){ 118 | if (cp5.getWindow().getMouseOverList().size() == 0){ 119 | for (int i=0;i tail; 20 | int tLength = 20; 21 | int tStep = 2; 22 | int tCount = 0; 23 | 24 | 25 | public Agent(PVector pos, float ms, float mf){ 26 | location = new PVector(pos.x, pos.y); 27 | velocity = new PVector(0,0); 28 | acceleration = new PVector(0,0); 29 | tail = new ArrayList(); 30 | 31 | mass = 1; 32 | r = 4.0; 33 | maxspeed = ms; 34 | maxforce = mf; 35 | angle = 0; 36 | } 37 | 38 | void update(){ 39 | prevLoc = location.copy(); 40 | velocity.add(acceleration); 41 | location.add(velocity); 42 | velocity.limit(maxspeed); 43 | acceleration.mult(0); 44 | angle = velocity.heading(); 45 | } 46 | 47 | void display(){ 48 | stroke(map(maxspeed,1,6,0,250)); 49 | //pushMatrix(); 50 | //translate(location.x, location.y); 51 | //rotate(angle); 52 | //rectMode(CENTER); 53 | if (prevLoc.dist(location) < 30) line(prevLoc.x,prevLoc.y,location.x,location.y); 54 | //popMatrix(); 55 | } 56 | 57 | void applyForce(PVector force){ 58 | PVector f = force.get(); 59 | f.div(mass); 60 | acceleration.add(f); 61 | } 62 | 63 | 64 | void futureLocation() { 65 | 66 | futVec = velocity.copy(); 67 | futVec.normalize(); 68 | futVec.mult(2.0); 69 | futLoc = futVec.add(location); 70 | 71 | } 72 | 73 | void follow(FlowField flow){ 74 | PVector desired = flow.lookup(futLoc); 75 | //desired.normalize(); 76 | desired.mult(maxspeed); 77 | 78 | PVector steer = PVector.sub(desired,velocity); 79 | steer.limit(maxforce); 80 | applyForce(steer); 81 | 82 | } 83 | 84 | void run() { 85 | update(); 86 | borders(); 87 | display(); 88 | // drawTail(); 89 | } 90 | 91 | void seek(PVector target){ 92 | PVector desired = PVector.sub(target,location); 93 | desired.normalize(); 94 | desired.mult(maxspeed); 95 | 96 | PVector steer = PVector.sub(desired,velocity); 97 | steer.limit(maxforce); 98 | applyForce(steer); 99 | } 100 | 101 | void turn(PVector target){ 102 | PVector desired = PVector.sub(target,location); 103 | desired.normalize(); 104 | 105 | 106 | PVector steer = PVector.sub(desired,velocity); 107 | steer.limit(maxforce); 108 | applyForce(steer); 109 | } 110 | 111 | void deposit(FlowField flow){ 112 | flow.depositPher(location, velocity); 113 | } 114 | 115 | void wander(){ 116 | dt += 0.2; 117 | PVector futurePos = velocity.copy(); 118 | futurePos.add(location); 119 | 120 | 121 | float angleWander = velocity.heading() + map(noise(dt),0,1,-0.4,0.4); 122 | PVector wanderPos = new PVector(futurePos.x + cos(angleWander)*wanderRadius, futurePos.y + sin(angleWander)*wanderRadius); 123 | 124 | seek(wanderPos); 125 | /* 126 | noFill(); 127 | stroke(100); 128 | ellipse(futurePos.x,futurePos.y,wanderRadius*2,wanderRadius*2); 129 | noStroke(); 130 | fill(255,0,0); 131 | ellipse(wanderPos.x,wanderPos.y,4,4); 132 | */ 133 | } 134 | 135 | void drawTail(){ 136 | tCount++; 137 | 138 | if (tCount > tStep){ 139 | tail.add(location.copy()); 140 | tCount = 0; 141 | } 142 | 143 | if (tail.size() > tLength){ 144 | tail.remove(0); 145 | } 146 | 147 | for (int i = 1; i < tail.size(); i++){ 148 | PVector a = tail.get(i-1); 149 | PVector b = tail.get(i); 150 | 151 | if (a.dist(b) < 30){ 152 | stroke(255,map(i, 0, tail.size(),0, 200)); 153 | line(a.x,a.y,b.x,b.y); 154 | } 155 | } 156 | } 157 | 158 | // Wraparound 159 | void borders() { 160 | if (location.x < -r) location.x = width+r; 161 | if (location.y < -r) location.y = height+r; 162 | if (location.x > width+r) location.x = -r; 163 | if (location.y > height+r) location.y = -r; 164 | } 165 | } -------------------------------------------------------------------------------- /stigmergy/Field.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | PVector[][] field; 3 | int cols, rows; 4 | 5 | int resolution; 6 | PImage img; 7 | float angle = 0; 8 | float t; 9 | 10 | public FlowField(int r){ 11 | resolution = r; 12 | cols = width/resolution; 13 | rows = height/resolution; 14 | field = new PVector[cols][rows]; 15 | 16 | //INIT 17 | t = 0; 18 | init(); 19 | } 20 | void init(){ 21 | t+=0.01; 22 | float offx = 0; 23 | for (int i = 0; i < cols; ++i) { 24 | float offy = 0; 25 | for (int j = 0; j < rows; ++j) { 26 | float angle = map(noise(offx,offy,t),0,1,0,TWO_PI); 27 | //float angle = map(img.get(int(i*w/cols),int(j*h/rows)),0,255,0,TWO_PI); 28 | //field[i][j] = new PVector(cos(angle),sin(angle)); 29 | field[i][j] = PVector.random2D(); 30 | offy +=0.1; 31 | } 32 | offx +=0.1; 33 | } 34 | 35 | } 36 | 37 | 38 | void depositPher(PVector loc, PVector pheromone){ 39 | int column = int(constrain(loc.x/resolution, 0, cols-1)); 40 | int row = int(constrain(loc.y/resolution, 0, rows-1)); 41 | field[column][row] = pheromone.copy().normalize(); 42 | } 43 | 44 | void update(){ 45 | 46 | } 47 | void display(){ 48 | 49 | 50 | 51 | 52 | //tint(255, 100); 53 | //image(img, 0, 0, width, height); 54 | 55 | stroke(255, 50); 56 | 57 | 58 | for (int i = 0; i < cols; ++i) { 59 | //line(i*resolution,0,i*resolution,height); 60 | for (int j = 0; j < rows; ++j) { 61 | //line(i*resolution,j*resolution,(i+1)*resolution,j*resolution); 62 | drawVector(field[i][j],i*resolution,j*resolution,resolution-2); 63 | } 64 | } 65 | } 66 | 67 | void drawVector(PVector v,float x, float y, float scayl){ 68 | pushMatrix(); 69 | translate(x, y); 70 | rotate(v.heading2D()); 71 | float len = v.mag()*scayl; 72 | 73 | line(0,0,len,0); 74 | popMatrix(); 75 | } 76 | 77 | PVector lookup(PVector lookup){ 78 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 79 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 80 | return field[column][row].get(); 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /stigmergy/stigmergy.pde: -------------------------------------------------------------------------------- 1 | FlowField f; 2 | ArrayList agents; 3 | 4 | int totAgents = 35000; 5 | 6 | void setup(){ 7 | size(1280,720,P2D); 8 | f = new FlowField(4); 9 | agents = new ArrayList(); 10 | 11 | 12 | 13 | for (int i = 0; i < totAgents; i++) { 14 | agents.add(new Agent(new PVector(random(width), random(height)), random(2, 5), random(.5, 6))); 15 | } 16 | 17 | background(0); 18 | 19 | } 20 | 21 | void draw(){ 22 | 23 | fill(0,80); 24 | rect(0,0,width,height); 25 | //f.update(); 26 | //f.display(); 27 | noStroke(); 28 | blendMode(ADD); 29 | for (Agent v : agents) { 30 | v.futureLocation(); 31 | v.follow(f); 32 | //v.futureLocation(); 33 | v.deposit(f); 34 | v.wander(); 35 | v.run(); 36 | } 37 | blendMode(NORMAL); 38 | filter(BLUR); 39 | saveFrame("particlesFEW-######.png"); 40 | } -------------------------------------------------------------------------------- /stigmergyagents/Agent.pde: -------------------------------------------------------------------------------- 1 | class Agent{ 2 | PVector location; 3 | PVector velocity; 4 | PVector acceleration; 5 | 6 | PVector futVec,futLoc,prevLoc; 7 | 8 | float maxspeed; 9 | float maxforce; 10 | 11 | float mass; 12 | float angle; 13 | float r; 14 | 15 | float wanderRadius = 20.0; 16 | float dt = 0+random(500); 17 | 18 | 19 | ArrayList tail; 20 | int tLength = 5; 21 | int tStep = 1; 22 | int tCount = 0; 23 | float rndValue = random(1.0); 24 | color col = 255; 25 | 26 | public Agent(PVector pos, float ms, float mf){ 27 | location = new PVector(pos.x, pos.y); 28 | velocity = new PVector(0,0); 29 | acceleration = new PVector(0,0); 30 | tail = new ArrayList(); 31 | 32 | mass = 1; 33 | r = 4.0; 34 | maxspeed = ms; 35 | maxforce = mf; 36 | angle = 0; 37 | } 38 | public Agent(PVector pos){ 39 | location = new PVector(pos.x, pos.y); 40 | velocity = new PVector(0,0); 41 | acceleration = new PVector(0,0); 42 | tail = new ArrayList(); 43 | 44 | mass = 1; 45 | r = 4.0; 46 | maxspeed = minSpeed + rndValue*(maxSpeed-minSpeed); 47 | maxforce = minForce + rndValue*(maxForce-minForce); 48 | angle = 0; 49 | } 50 | 51 | void updateData(){ 52 | maxspeed = minSpeed + rndValue*(maxSpeed-minSpeed); 53 | maxforce = minForce + rndValue*(maxForce-minForce); 54 | } 55 | 56 | void update(){ 57 | prevLoc = location.copy(); 58 | velocity.add(acceleration); 59 | location.add(velocity); 60 | velocity.limit(maxspeed); 61 | acceleration.mult(0); 62 | angle = velocity.heading(); 63 | } 64 | 65 | void display(){ 66 | stroke(col,pOpacity); 67 | //pushMatrix(); 68 | //translate(location.x, location.y); 69 | //rotate(angle); 70 | //rectMode(CENTER); 71 | if (prevLoc.dist(location) < 30) line(prevLoc.x,prevLoc.y,location.x,location.y); 72 | //popMatrix(); 73 | } 74 | 75 | void applyForce(PVector force){ 76 | PVector f = force.get(); 77 | f.div(mass); 78 | acceleration.add(f); 79 | } 80 | 81 | 82 | void futureLocation() { 83 | 84 | futVec = velocity.copy(); 85 | futVec.normalize(); 86 | futVec.mult(2.0); 87 | futLoc = futVec.add(location); 88 | 89 | } 90 | 91 | void follow(FlowField flow){ 92 | PVector desired = flow.lookup(futLoc); 93 | //desired.normalize(); 94 | desired.mult(maxspeed); 95 | 96 | PVector steer = PVector.sub(desired,velocity); 97 | steer.limit(maxforce); 98 | applyForce(steer); 99 | 100 | } 101 | 102 | void run() { 103 | update(); 104 | borders(); 105 | display(); 106 | //drawTail(); 107 | } 108 | 109 | void seek(PVector target){ 110 | PVector desired = PVector.sub(target,location); 111 | desired.normalize(); 112 | desired.mult(maxspeed); 113 | 114 | PVector steer = PVector.sub(desired,velocity); 115 | steer.limit(maxforce); 116 | applyForce(steer); 117 | } 118 | 119 | void turn(PVector target){ 120 | PVector desired = PVector.sub(target,location); 121 | desired.normalize(); 122 | 123 | 124 | PVector steer = PVector.sub(desired,velocity); 125 | steer.limit(maxforce); 126 | applyForce(steer); 127 | } 128 | 129 | void deposit(FlowField flow){ 130 | flow.depositPher(location, velocity); 131 | } 132 | 133 | void wander(){ 134 | dt += 0.2; 135 | PVector futurePos = velocity.copy(); 136 | futurePos.add(location); 137 | 138 | 139 | float angleWander = velocity.heading() + map(noise(dt),0,1,-0.4,0.4); 140 | PVector wanderPos = new PVector(futurePos.x + cos(angleWander)*wanderRadius, futurePos.y + sin(angleWander)*wanderRadius); 141 | 142 | seek(wanderPos); 143 | /* 144 | noFill(); 145 | stroke(100); 146 | ellipse(futurePos.x,futurePos.y,wanderRadius*2,wanderRadius*2); 147 | noStroke(); 148 | fill(255,0,0); 149 | ellipse(wanderPos.x,wanderPos.y,4,4); 150 | */ 151 | } 152 | 153 | void drawTail(){ 154 | tCount++; 155 | 156 | if (tCount > tStep){ 157 | tail.add(location.copy()); 158 | tCount = 0; 159 | } 160 | 161 | if (tail.size() > tLength){ 162 | tail.remove(0); 163 | } 164 | 165 | for (int i = 1; i < tail.size(); i++){ 166 | PVector a = tail.get(i-1); 167 | PVector b = tail.get(i); 168 | 169 | if (a.dist(b) < 30){ 170 | stroke(col,map(i, 0, tail.size(),0, 200)); 171 | line(a.x,a.y,b.x,b.y); 172 | } 173 | } 174 | } 175 | 176 | // Wraparound 177 | void borders() { 178 | if (location.x < -r) location.x = width+r; 179 | if (location.y < -r) location.y = height+r; 180 | if (location.x > width+r) location.x = -r; 181 | if (location.y > height+r) location.y = -r; 182 | } 183 | } -------------------------------------------------------------------------------- /stigmergyagents/Field.pde: -------------------------------------------------------------------------------- 1 | class FlowField{ 2 | PVector[][] field; 3 | int cols, rows; 4 | 5 | int resolution; 6 | PImage img; 7 | float angle = 0; 8 | float t; 9 | 10 | public FlowField(int r){ 11 | resolution = r; 12 | cols = width/resolution; 13 | rows = height/resolution; 14 | field = new PVector[cols][rows]; 15 | 16 | //INIT 17 | t = 0; 18 | init(); 19 | } 20 | void init(){ 21 | t+=0.01; 22 | float offx = 0; 23 | for (int i = 0; i < cols; ++i) { 24 | float offy = 0; 25 | for (int j = 0; j < rows; ++j) { 26 | float angle = noise(offx/noiseScale,offy/noiseScale)*noiseStrength; 27 | //float angle = map(noise(offx,offy,t),0,1,0,TWO_PI); 28 | //float angle = map(img.get(int(i*w/cols),int(j*h/rows)),0,255,0,TWO_PI); 29 | //field[i][j] = new PVector(cos(angle),sin(angle)); 30 | field[i][j] = PVector.random2D(); 31 | offy +=0.1; 32 | } 33 | offx +=0.1; 34 | } 35 | 36 | } 37 | 38 | 39 | void depositPher(PVector loc, PVector pheromone){ 40 | int column = int(constrain(loc.x/resolution, 0, cols-1)); 41 | int row = int(constrain(loc.y/resolution, 0, rows-1)); 42 | field[column][row] = pheromone.copy().normalize(); 43 | } 44 | 45 | void update(){ 46 | 47 | } 48 | void display(){ 49 | 50 | 51 | 52 | 53 | //tint(255, 100); 54 | //image(img, 0, 0, width, height); 55 | 56 | stroke(255, 50); 57 | 58 | 59 | for (int i = 0; i < cols; ++i) { 60 | //line(i*resolution,0,i*resolution,height); 61 | for (int j = 0; j < rows; ++j) { 62 | //line(i*resolution,j*resolution,(i+1)*resolution,j*resolution); 63 | drawVector(field[i][j],i*resolution,j*resolution,resolution-2); 64 | } 65 | } 66 | } 67 | 68 | void drawVector(PVector v,float x, float y, float scayl){ 69 | pushMatrix(); 70 | translate(x, y); 71 | rotate(v.heading2D()); 72 | float len = v.mag()*scayl; 73 | 74 | line(0,0,len,0); 75 | popMatrix(); 76 | } 77 | 78 | PVector lookup(PVector lookup){ 79 | int column = int(constrain(lookup.x/resolution,0,cols-1)); 80 | int row = int(constrain(lookup.y/resolution,0,rows-1)); 81 | return field[column][row].get(); 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /stigmergyagents/palette.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lignazio/Learning-Processing/ad31aa427ec598c6d983ce09aedbd44ac9bfd59b/stigmergyagents/palette.jpg -------------------------------------------------------------------------------- /stigmergyagents/stigmergyagents.pde: -------------------------------------------------------------------------------- 1 | import controlP5.*; 2 | 3 | ControlP5 cp5; 4 | CallbackListener cb; 5 | FlowField f; 6 | ArrayList agents; 7 | float noiseScale = 1; 8 | float noiseStrength = TWO_PI; 9 | int totAgents = 45000; 10 | PImage palette; 11 | float minSpeed = 2; 12 | float maxSpeed = 5; 13 | float minForce = 0.5; 14 | float maxForce = 5; 15 | float bgOpacity = 10; 16 | float pOpacity = 50; 17 | 18 | boolean drawGui = false; 19 | 20 | void setup(){ 21 | size(1280,720,P2D); 22 | pixelDensity(2); 23 | f = new FlowField(2); 24 | agents = new ArrayList(); 25 | 26 | palette = loadImage("palette.jpg"); 27 | palette.loadPixels(); 28 | 29 | cb = new CallbackListener() { 30 | public void controlEvent(CallbackEvent theEvent) { 31 | switch(theEvent.getAction()) { 32 | case(ControlP5.RELEASED): 33 | for (Agent a : agents) { 34 | a.updateData(); 35 | } 36 | break; 37 | 38 | } 39 | } 40 | }; 41 | 42 | for (int i = 0; i < totAgents; i++) { 43 | PVector pos = new PVector (random(width),random(height)); 44 | Agent a = new Agent(pos); 45 | a.col = palette.get(int(pos.x),int(pos.y)); 46 | agents.add(a); 47 | } 48 | 49 | background(0); 50 | cp5 = new ControlP5(this); 51 | 52 | cp5.setColorForeground(0xffcccccc); 53 | cp5.setColorBackground(0xff111111); 54 | cp5.setColorActive(0xff666666); 55 | 56 | 57 | 58 | 59 | cp5.begin(100,50); 60 | //cp5.addSlider("noiseStrength",1,100).linebreak(); 61 | //cp5.addSlider("noiseScale",1,1000).linebreak(); 62 | cp5.addSlider("minSpeed",0,5).linebreak(); 63 | cp5.addSlider("maxSpeed",1,10).linebreak(); 64 | cp5.addSlider("minForce",0,5).linebreak(); 65 | cp5.addSlider("maxForce",1,10).linebreak(); 66 | cp5.addSlider("bgOpacity",0,255).linebreak(); 67 | cp5.addSlider("pOpacity",0,255).linebreak(); 68 | cp5.addBang("toggle") 69 | .setSize(50,10) 70 | .setCaptionLabel("reset field"); 71 | cp5.end(); 72 | 73 | // add the above callback to controlP5 74 | cp5.addCallback(cb); 75 | cp5.setAutoDraw(false); 76 | //blendMode(SCREEN); 77 | } 78 | 79 | void draw(){ 80 | //background(0); 81 | noStroke(); 82 | fill(0,bgOpacity); 83 | rect(0,0,width,height); 84 | //f.update(); 85 | //f.display(); 86 | //blendMode(SCREEN); 87 | for (Agent v : agents) { 88 | v.futureLocation(); 89 | v.follow(f); 90 | //v.futureLocation(); 91 | v.deposit(f); 92 | //v.wander(); 93 | v.run(); 94 | } 95 | 96 | blendMode(NORMAL); 97 | if (drawGui) cp5.draw(); 98 | } 99 | 100 | void toggle(){ 101 | f.init(); 102 | } 103 | 104 | 105 | void keyPressed(){ 106 | if (key == 'g') drawGui = !drawGui; 107 | } 108 | 109 | -------------------------------------------------------------------------------- /verlet_growingRope_mesh/build-tmp/source/growingRope.java: -------------------------------------------------------------------------------- 1 | import processing.core.*; 2 | import processing.data.*; 3 | import processing.event.*; 4 | import processing.opengl.*; 5 | 6 | import toxi.physics.*; 7 | import toxi.physics.behaviors.*; 8 | import toxi.physics.constraints.*; 9 | import toxi.physics2d.*; 10 | import toxi.physics2d.behaviors.*; 11 | import toxi.physics2d.constraints.*; 12 | 13 | import java.util.HashMap; 14 | import java.util.ArrayList; 15 | import java.io.File; 16 | import java.io.BufferedReader; 17 | import java.io.PrintWriter; 18 | import java.io.InputStream; 19 | import java.io.OutputStream; 20 | import java.io.IOException; 21 | 22 | public class growingRope extends PApplet { 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | int numParticles = 100; 32 | float restLength = 10.0f; 33 | 34 | VerletPhysics2D physics; 35 | VerletParticle2D head,tail; 36 | 37 | Iterator it; 38 | 39 | public void setup(){ 40 | 41 | 42 | physics = new VerletPhysics2D(); 43 | Vec2D stepDir = new Vec2D(1,0).normalizeTo(REST_LENGTH); 44 | ParticleString2D s = new ParticleString2D(physics, new Vec2D(), stepDir, NUM_PARTICLES, 1, 0.1f); 45 | head = s.getHead(); 46 | tail = s.getTail(); 47 | 48 | noFill(); 49 | stroke(255); 50 | } 51 | 52 | public void draw(){ 53 | background(0); 54 | physics.update(); 55 | it = physics.particles.iterator(); 56 | beginShape(); 57 | 58 | while(it.hasNext()){ 59 | VerletParticle2D p = (VerletParticle2D)it.next(); 60 | vertex(p.x,p.y); 61 | } 62 | endShape(); 63 | } 64 | public void settings() { size(1280,720,P2D); } 65 | static public void main(String[] passedArgs) { 66 | String[] appletArgs = new String[] { "growingRope" }; 67 | if (passedArgs != null) { 68 | PApplet.main(concat(appletArgs, passedArgs)); 69 | } else { 70 | PApplet.main(appletArgs); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /verlet_growingRope_mesh/verlet_growingRope_mesh.pde: -------------------------------------------------------------------------------- 1 | 2 | import toxi.physics2d.constraints.*; 3 | import toxi.physics2d.*; 4 | import toxi.physics2d.behaviors.*; 5 | 6 | import java.util.*; 7 | import toxi.geom.*; 8 | import toxi.math.*; 9 | 10 | import wblut.math.*; 11 | import wblut.processing.*; 12 | import wblut.core.*; 13 | import wblut.hemesh.*; 14 | import wblut.geom.*; 15 | 16 | WB_Render render; 17 | WB_BSpline C; 18 | WB_Point[] points; 19 | HE_Mesh mesh; 20 | 21 | 22 | int numParticles = 50; 23 | float restLength = 10.0; 24 | float ropeRadius = 8; 25 | boolean cCircle,cSquare,meshCreated = false; 26 | float diameter = 720; 27 | Vec2D center; 28 | 29 | VerletPhysics2D physics; 30 | VerletParticle2D head,tail; 31 | 32 | Iterator it; 33 | 34 | void setup(){ 35 | size(1280,800,P3D); 36 | pixelDensity(2); 37 | 38 | center = new Vec2D(width/2,height/2); 39 | 40 | physics = new VerletPhysics2D(); 41 | physics.setDrag(0.05f); 42 | physics.setWorldBounds(new Rect(ropeRadius, ropeRadius, width-ropeRadius*2, height-ropeRadius*2)); 43 | drawRope(); 44 | 45 | strokeWeight(ropeRadius); 46 | strokeCap(ROUND); 47 | } 48 | VerletParticle2D addParticle(Vec2D pos){ 49 | VerletParticle2D p = new VerletParticle2D(pos); 50 | physics.addParticle(p); 51 | physics.addBehavior(new AttractionBehavior(p, 40, -0.6f, 0.01f)); 52 | return p; 53 | } 54 | 55 | void draw(){ 56 | background(0,0,255); 57 | noFill(); 58 | stroke(255); 59 | 60 | if (cCircle){ 61 | ellipse(center.x,center.y,diameter+ropeRadius*4,diameter+ropeRadius*4); 62 | } 63 | if (cSquare){ 64 | rect(center.x-diameter/2,center.y-diameter/2,diameter,diameter); 65 | physics.setWorldBounds(new Rect(center.x-diameter/2+ropeRadius,center.y-diameter/2+ropeRadius,diameter-ropeRadius*2,diameter-ropeRadius*2)); 66 | }else{ 67 | physics.setWorldBounds(new Rect(ropeRadius, ropeRadius, width-ropeRadius*2, height-ropeRadius*2)); 68 | } 69 | 70 | 71 | 72 | it = physics.particles.iterator(); 73 | beginShape(); 74 | while(it.hasNext()){ 75 | VerletParticle2D p = it.next(); 76 | if (cCircle){ 77 | if ((dist(p.x, p.y, center.x, center.y) > diameter/2)){ 78 | float a = PVector.sub(new PVector(p.x,p.y),new PVector(center.x,center.y)).heading(); 79 | p.x = center.x + diameter/2 * cos (a); 80 | p.y = center.y + diameter/2 * sin (a); 81 | 82 | } 83 | } 84 | curveVertex(p.x,p.y); 85 | } 86 | endShape(); 87 | 88 | 89 | 90 | if (meshCreated){ 91 | directionalLight(255, 255, 255, 1, 1, -1); 92 | noStroke(); 93 | fill(200); 94 | render.drawFaces(mesh); 95 | } 96 | 97 | physics.update(); 98 | } 99 | void removeEverything(){ 100 | for (int i = physics.particles.size() - 1; i >= 0; i--) { 101 | physics.particles.remove(i); 102 | } 103 | 104 | for (int i = physics.behaviors.size() - 1; i >= 0; i--) { 105 | physics.behaviors.remove(i); 106 | } 107 | 108 | for (int i = physics.springs.size() - 1; i >= 0; i--) { 109 | physics.springs.remove(i); 110 | } 111 | } 112 | 113 | void doubleSize(){ 114 | ArrayList particles = new ArrayList(physics.particles); 115 | removeEverything(); 116 | 117 | 118 | VerletParticle2D p0 = addParticle(particles.get(0)); 119 | 120 | for (int i=1; i particles; 9 | 10 | Particle first,last; 11 | 12 | public StickyString(float l, int n, float s){ 13 | particles = new ArrayList(); 14 | 15 | totalLength = l; 16 | numPoints = n; 17 | strength = s; 18 | 19 | float len = totalLength / numPoints; 20 | 21 | for (int i=0; i < numPoints; i++){ 22 | 23 | Particle particle = new Particle(width/2,i*len,0); 24 | 25 | world.addParticle(particle); 26 | particles.add(particle); 27 | 28 | if (i != 0){ 29 | Particle previous = particles.get(i-1); 30 | VerletSpring spring = new VerletSpring(particle,previous,len,strength); 31 | world.addSpring(spring); 32 | } 33 | } 34 | 35 | first = particles.get(0); 36 | first.lock(); 37 | 38 | last = particles.get(numPoints-1); 39 | } 40 | 41 | void setFirst(Vec3D loc){ 42 | first.lock(); 43 | first.set(loc); 44 | } 45 | 46 | void setLast(Vec3D loc){ 47 | last.lock(); 48 | last.set(loc); 49 | } 50 | 51 | 52 | void display(){ 53 | stroke(c); 54 | noFill(); 55 | 56 | beginShape(); 57 | for (Particle p : particles){ 58 | vertex (p.x,p.y,p.z); 59 | } 60 | endShape(); 61 | 62 | first.display(); 63 | last.display(); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /verlet_sticky_threads/verlet_sticky_threads.pde: -------------------------------------------------------------------------------- 1 | import toxi.physics.*; 2 | import toxi.physics.behaviors.*; 3 | import toxi.physics.constraints.*; 4 | import toxi.geom.*; 5 | import peasy.*; 6 | 7 | PeasyCam cam; 8 | 9 | VerletPhysics world; 10 | 11 | int numStrings = 60; 12 | int resolution = 40; 13 | int stickyDist = 0; 14 | StickyString[] strings; 15 | ArrayList springs; 16 | boolean[][] connections; 17 | 18 | void setup(){ 19 | size(1280,720,P3D); 20 | pixelDensity(2); 21 | cam = new PeasyCam(this, 1000); 22 | cam.setMinimumDistance(1000); 23 | cam.setMaximumDistance(2000); 24 | cam.pan(width/2,height/2); 25 | 26 | world = new VerletPhysics(); 27 | world.addBehavior(new GravityBehavior(new Vec3D(0,0.1,0))); 28 | 29 | strings = new StickyString[numStrings]; 30 | springs = new ArrayList(); 31 | connections = new boolean[numStrings*resolution][numStrings*resolution]; 32 | 33 | for (int i = 0; i < numStrings; i++){ 34 | Vec3D a = new Vec3D(0,sin(random(TWO_PI))*200,cos(random(TWO_PI))*200); 35 | Vec3D b = new Vec3D(1280,sin(random(TWO_PI))*200,cos(random(TWO_PI))*200); 36 | float len = a.distanceTo(b); 37 | StickyString s = new StickyString(len, resolution, 0.5); 38 | s.setFirst(a); 39 | s.setLast(b); 40 | strings[i] = s; 41 | 42 | } 43 | 44 | blendMode(ADD); 45 | 46 | } 47 | 48 | void draw(){ 49 | world.update(); 50 | 51 | background (0,0,50); 52 | 53 | for (int i = 0; i < numStrings; i++){ 54 | strings[i].display(); 55 | } 56 | 57 | 58 | 59 | for (Spring sp : springs){ 60 | sp.display(); 61 | } 62 | 63 | cam.beginHUD(); 64 | fill(255); 65 | text ("sticky length: "+stickyDist,50,650); 66 | text ("n. of connections: "+springs.size(),50,670); 67 | cam.endHUD(); 68 | } 69 | 70 | 71 | void checkSticky(){ 72 | for (int i = 0; i < numStrings; i++){ 73 | int pa = 0; 74 | for (Particle p : strings[i].particles){ 75 | 76 | 77 | for (int j = 0; j < numStrings; j++){ 78 | int pb = 0; 79 | if (j != i){ 80 | for (Particle b : strings[j].particles){ 81 | 82 | 83 | if (p.distanceTo(b) < stickyDist && !connections[i*resolution+pa][j*resolution+pb] && (!p.connected || !b.connected) ){ 84 | connections[i*resolution+pa][j*resolution+pb] = true; 85 | p.connected = b.connected = true; 86 | Spring sp = new Spring(p,b,stickyDist/5,.5); 87 | sp.setColor(color(255,150)); 88 | springs.add(sp); 89 | world.addSpring(sp); 90 | } 91 | pb+=1; 92 | }//particelle interno 93 | }//if 94 | 95 | }//stringhe interno 96 | pa+=1; 97 | }//particelle1 98 | } //stringhe 99 | }//funzione 100 | 101 | void keyPressed(){ 102 | if (key == CODED) { 103 | if (keyCode == UP) { 104 | ++stickyDist; 105 | 106 | } else if (keyCode == DOWN) { 107 | if (stickyDist > 0) --stickyDist; 108 | } 109 | } 110 | checkSticky(); 111 | println("sticky distance:",stickyDist); 112 | println("springs:",springs.size()); 113 | } --------------------------------------------------------------------------------