Hi @asymmetric,
Here is an example how to link grid points to an image, and how you can move
- type r to switch random on and off
- type space to reset
- if random mode off you can capture the points and move them by mouse in a predefined range
You can play around with it a bit to get a better understanding… hope that helps…
Cheers
— mnse
PS: to make it easier I striped down to 2D. If you’ve understand this, it would be easy for you to add the z axis as heightmap …
//helper variables
float scl = 50.;
int rows, cols;
boolean doRandomMove = false;
boolean mode = true;
GridPoint[][] grid;
// image used for texture and heightmap
PImage img;
class GridPoint {
float ox, oy, ou, ov;
float x, y, u, v;
float sz=10;
boolean locked;
boolean dragged;
float angle;
public GridPoint(float px, float py, float pu, float pv, boolean plocked) {
ox=x=px;
oy=y=py;
ou=u=pu; // u-pos of the image
ov=v=pv; // v-pos of the image
locked = plocked;
dragged=false;
angle = random(TWO_PI);
}
public void reset() {
x=ox;
y=oy;
u=ou;
v=ov;
}
// automover
public void move() {
if (!locked) {
PVector r=PVector.random2D();
x=ox+0.2*scl*cos(angle);
y=oy+0.2*scl*sin(angle);
angle+=random(0.05, 0.1);
}
}
// manual mouse movement below
public void capture(float mx, float my) {
if (dist(mx, my, x, y) < sz) {
dragged=true;
} else
dragged=false;
}
public void move(float mx, float my) {
if (dragged) {
// remove check to not bound to surrounding box
if (dist(mx, my, ox, oy) < scl) {
x=mx;
y=my;
// uncomment move point but keep image
//u=x/((cols-1)*scl);
//v=y/((rows-1)*scl);
}
}
}
public void release() {
dragged=false;
}
public void render() {
pushStyle();
noStroke();
if (locked)
fill(255, 0, 0);
else if (dragged)
fill(255, 128, 64);
else
fill(0, 255, 0);
ellipse(x, y, sz, sz);
popStyle();
}
}
void setup() {
size(1000, 1000, P2D);
// smooth(10);
// using normal to be independent to img size
textureMode(NORMAL);
// initialize our gridpoints
rows = floor(height/scl)+1;
cols = floor(width/scl)+1;
grid= new GridPoint[rows][cols];
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
float sx = x*scl;
float sy = y*scl;
// u,v can also be written by x/(cols-1), y/(rows-1) casted to floats
grid[y][x] = new GridPoint(sx, sy, sx/((cols-1)*scl), sy/((rows-1)*scl), (x==0|y==0|x==cols-1||y==rows-1));
}
}
img = loadImage("aimage.jpg");
}
void mousePressed() {
if (!doRandomMove) {
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
grid[y][x].capture(mouseX, mouseY);
}
}
}
}
void mouseDragged() {
if (!doRandomMove) {
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
grid[y][x].move(mouseX, mouseY);
}
}
}
}
void mouseReleased() {
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
grid[y][x].release();
}
}
}
void keyPressed() {
if (key == ' ') {
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
grid[y][x].reset();
}
}
} else if (key == 'r') {
doRandomMove=!doRandomMove;
}
}
void updateRandom() {
for (int y = 0; y < rows; y ++) {
for (int x = 0; x < cols; x++) {
grid[y][x].move();
}
}
}
void draw() {
background(0);
if (doRandomMove) {
updateRandom();
}
// draw grid ... set noStroke to remove lines
stroke(0, 255, 0);
// build the surface/terrain by triangle strips to display it
for (int y = 0; y < rows-1; y ++) {
beginShape (QUAD_STRIP); // or (TRIANGLE_STRIP),(QUAD_STRIP),
texture(img); // on textured mode set the texture
// common triangle strips
for (int x = 0; x < cols; x++) {
GridPoint ca = grid[y][x];
vertex(ca.x, ca.y, ca.u, ca.v);
GridPoint cb = grid[y+1][x];
vertex(cb.x, cb.y, cb.u, cb.v);
}
endShape();
}
// draw grid points.
for (int y = 0; y < rows; y ++) {
for (int x = 0; x < cols; x++) {
grid[y][x].render();
}
}
}