import processing.opengl.*; // my radial basis function class rbf g_rbf; // stuff processing wants PGraphics pg; PFont g_font; void setup() { size(800,500,OPENGL); g_rbf = new rbf(); pg = createGraphics(100, 100, P2D); g_font = createFont("FFScala", 15); textFont(g_font, 15); } // camera controls float g_ry, g_zoom = 1; float g_rx; void draw() { background(10); lights(); // simple camera controls; left mouse rotates and right mouse zooms if (mousePressed && mouseButton == LEFT && mouseX > 400) { g_rx -= (mouseX - pmouseX)*.01; g_ry -= (mouseY - pmouseY)*.01; if (g_ry > 1.5) g_ry = 1.5; if (g_ry < -1) g_ry = -1; } if (mousePressed && mouseButton == RIGHT && mouseX > 400) { //g_zoom -= (mouseX - lastMx)*.01; g_zoom += (mouseY - pmouseY)*.005; if (g_zoom < .25) g_zoom = .25; if (g_zoom > 2.5) g_zoom = 2.5; } // press a to add control points if (keyHit('a')) { g_rbf.add(mouseX, mouseY); } // press d to delete control points if (keyHit('d')) { g_rbf.removeUnderMouse(); } // press r to change the radial basis function used if (keyHit('r')) { g_rbf.rbfFn = (g_rbf.rbfFn + 1) % RBF_CNT; } // press t to change the extra polynomial terms if (keyHit('t')) { g_rbf.polyMode = (g_rbf.polyMode + 1) % POLY_COUNT; } // solve for the radial basis function weights using the current control points g_rbf.update(); // render a height field float sx = 1, sy = 1, sz = -2; // scale parameters // set up camera: pushMatrix(); translate(width/2+width/4, height/2); rotateX(45 + g_ry); rotateZ(g_rx); scale(g_zoom); // set offset in x,y so heightfield is centered at 0,0 float ox = -(pg.width*.5)*sx; float oy = -(pg.height*.5+25)*sy; noStroke(); fill(200, 200, 150); // render as a bunch of quad strips for (int y = 0; y < pg.height-1; y++) { beginShape(QUAD_STRIP); for (int x = 0; x < pg.width; x++) { vertex(x*sx+ox, y*sy+oy,g_rbf.eval(x*4,(y*4)+100)*sz); vertex(x*sx+ox, (y+1)*sy+oy, g_rbf.eval(x*4,(y+1)*4+100)*sz); } endShape(); } // render control points on top of 3d scene stroke(255,0,0); strokeWeight(4); beginShape(POINTS); for (int i = 0; i < g_rbf.draggables.size(); i++) { Draggable d = (Draggable)g_rbf.draggables.get(i); vertex((d.x/4)*sx+ox, ((d.y-100)/4)*sy+oy, d.z*sz); } endShape(); // un-set camera popMatrix(); // draw 2d top-down UI on left side of screen pg.beginDraw(); pg.loadPixels(); for (int y = 0; y < pg.height; y++) { for (int x = 0; x < pg.width; x++) { pg.pixels[x+y*pg.width] = color(0, 100.0 + 20.0*g_rbf.eval(x*4,y*4+100), 255); } } pg.updatePixels(); pg.endDraw(); image(pg, 0, 100, 400, 400); // display control points g_rbf.display(); // display instructions fill(255); stroke(255); text("'a' -- add control point", 10, 15); text("'d' -- delete control point", 10, 30); text("left click: change height. right click: change posn", 10, 45); text("current RBF is " + g_fnNames[g_rbf.rbfFn] + " (press r to cycle)", 10, 60); text("current polynomial term is " + g_polyNames[g_rbf.polyMode] + " (press t to cycle)", 10, 75); text("top down edit view: ", 10, 95); text("3D visualization (click/drag to rotate and zoom): ", 400, 95); }