Hi @asymmetric,
You are here overwriting the values again from above…
Was quite busy with other work the last days. I’ll try to post a complete example for you tomorrow…
Cheers
---- mnse
Hi @asymmetric,
You are here overwriting the values again from above…
Was quite busy with other work the last days. I’ll try to post a complete example for you tomorrow…
Cheers
---- mnse
Hello @asymmetric ,
I will not provide you with the full code; I wrote that code so I could offer assistance.
This is an achievable exercise and worth the effort on your part to work through and understand.
I did this myself before providing you with some direction, a “snippet” of code and references.
I encourage you to work through this and try to understand it; this time invested will pay off in the long run.
The Processing Forum Guidelines are here:
Processing website:
I do not want to take the opportunity away from you!
If you have specific questions please ask.
:)
Hi @glv,
in principle I totally agree with you!
Learning to code is a long process that never ends and that only works if you work hard at it and learn from your mistakes, but also from other people.
However, regarding the latter, for many it is necessary to look at how others do it. First, to familiarize yourself with it, and second, to see if you understand the approach or not, and to question why someone implemented it the way they did. This also allows you, after you have studied it, to ask further questions and, in the best case, to develop your own and perhaps new approaches that will help you and, in turn, other people who learn from you.
However, since I also understand the purpose of the guildlines you carefully selected, I’m a little torn about posting my finished example solution here.
@asymmetric: Means, I think, I need some more time to came up with a final decission to post it or not … So, try first on your own to see if you get a result by @glv’s snippet and if you not came up with a solution for your own, let us know …
Cheers
— mnse
EDIT: removed example output from here as posted completely below …
Hi again,
Well, as the day is slowly coming to an end and I’ve had some thoughts about whether to post or not, I’ve come to the decision that I will post it after all.
There are many pros and cons that could be listed, but none of them weigh so heavily that there would be a right or wrong.
Reasons are …
My code is just one of many examples and is far from an all-encompassing implementation. There are many things that can be worked out in addition to this on the topic.
I’ve now added lots of comments to the code, to not offer this as a simple copy/paste solution, but rather that one can get an idea of what concrete was done here and most importantly why.
(took longer than to code it. )
If you disagree with my decision, you are free to flag the post.
// a class to representing a point on our grid.
// This should/would/could be done better by defining it as faces (of a triangle mesh).
// but would it keep as simple as possible
class GridPoint {
float x, y, v;
public GridPoint(float px, float py, float pv) {
x = px; // x-pos of the grid point
y = py; // y-pos of the grid point
v = pv; // height of the grid point
}
}
//helper variables
float halfWidth, halfHeight;
boolean mode = false;
// storage of out grid
int rows, cols;
GridPoint[][] grid;
// image used for texture and heightmap
PImage img;
void setup() {
size(800, 800, P3D);
halfWidth = width/2.;
halfHeight = height/2.;
initGrid(10.);
// use textureMode IMAGE as the grid is not normalized
textureMode(IMAGE);
}
void initGrid(float scl) {
// load the image, used for texture and heightmap.
// usually more than one picture will be used. One for heightmap, one for normalmap and one with the texture.
// for simplicity it has the same size than our grid to not make the code more math intensive.
// to get this work our image is somehow a bit blurred (like noise is), otherwise the mesh isn't smooth enough
img = loadImage("image.png");
img.loadPixels();
// initialize our gridpoints
rows = floor(height/scl);
cols = floor(width/scl);
grid= new GridPoint[rows][cols];
for (int y = 0; y < rows; y++) {
for (int x = 0; x < cols; x++) {
int sx = floor(x*scl);
int sy = floor(y*scl);
// set x and y coordinates (center origin) and the height of the current point.
// height is the normalized brightness value [0..1] of the pixel color from the image.
// Subtract 0.5 to align it to center [-0.5..0.5]
// scaling it by 50, so the range is [50.0*(-0.5)..50.0*(0.5)]
grid[y][x] = new GridPoint(-halfWidth+sx+scl/2, -halfHeight+sy+scl/2, 50.*(brightness(img.get(sx, sy))/255-0.5));
}
}
}
void draw() {
background(0);
// set the origin to the center of the screen, and move it 400px far away on z-axis
translate(halfWidth, halfHeight, -400);
// switch between mesh and texured mode
if (frameCount % int(TAU*100.) == 0) {
mode = !mode;
}
if (mode) {
// if textured mode no strokes and a light from viewpoint to object
noStroke();
directionalLight(255, 255, 255, 0, 0, -1);
} else {
// if mesh mode only show strokes
noFill();
stroke(128);
strokeWeight(0.5);
}
// apply the rotation after lighting, otherwhile the light gets also rotated, which we not want.
// tipping 30degree back on X-axis
rotateX(radians(30));
// tipping left/right a bit per frame from -PI/4 - +PI/4 on Y-axis
rotateY(sin(frameCount/100.)*QUARTER_PI);
// build the surface/terrain by triangle strips to display it
for (int y = 0; y < rows-1; y ++) {
beginShape(TRIANGLE_STRIP);
if (mode) {
// on textured mode set the texture
texture(img);
}
// common triangle strips
for (int x = 0; x < cols; x++) {
GridPoint ca = grid[y][x];
GridPoint cb = grid[y+1][x];
vertex(ca.x, ca.y, ca.v, ca.x+halfWidth, ca.y+halfHeight);
if (mode) {
// on textured mode we need to set the normal vector, so the light knows how to behave on hittng the surface
// usually there are better calculation than this cheap hack
// comment it out to see the difference if normals are messed up
PVector na = new PVector(ca.x-cb.x, ca.y-cb.y, 0).sub(new PVector(ca.x-cb.x, ca.y-cb.y, 1)).normalize();
normal(na.x, na.y, na.z);
}
vertex(cb.x, cb.y, cb.v, cb.x+halfWidth, cb.y+halfHeight);
if (mode) {
// on textured mode we need to set the normal vector, so the light knows how to behave on hittng the surface
// usually there are better calculation than this cheap hack
// comment it out to see the difference if normals are messed up
PVector nb = new PVector(cb.x-ca.x, cb.y-ca.y, 0).sub(new PVector(cb.x-ca.x, cb.y-ca.y, 1)).normalize();
normal(nb.x, nb.y, nb.z);
}
}
endShape();
}
}
Image used for code above [800x800]px
Result:
Cheers
— mnse
PImage img;
int cols, rows;
int scl = 26;
int w = 2800;
int h = 2600;
float ax, ay;
int videoScale =14;
int cols1, rows1;
//int sphereMy ;
void setup() {
size(1200, 1000, OPENGL);
// rectMode(CENTER);
String http = "http://";
//img = loadImage( http + "www.tfguy44.com/MyIcon1.PNG");
img = loadImage( "ee.jpeg");
cols = w / scl;
rows = h/ scl;
//cols1 = width/videoScale;
// rows1 = height/videoScale;
rows1 = 222/videoScale;
cols1 = 222/videoScale;
texture(img);
}
void draw() {
background(0);
lights();
translate(width/2, height/2, 0);
scale(1.5);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(-map(mouseY, 0, height, -PI, PI));
//point(455, 434, 122);
for (int u=0; u<1; u+=1) {
sphereMy(20-u, 10-u, 111-u);
}
// stroke(255, 0, 0);
// fill(255, 0, 0, 128);
// noStroke();
noFill();
stroke(255, 255, 255);
// fill(0, 0, 255, 128);
plane();
// stroke(0, 255, 0);
// fill(0, 255, 0, 128);
rotateX(HALF_PI);
//noStroke();
// noFill();
stroke(255, 255, 255);
//fill(0, 0, 255, 128);
plane();
// NoStrok();
// noStroke();
// noFill();
stroke(255, 255, 255);
//fill(255, 255, 255);
rotateY(HALF_PI);
plane();
}
void plane() {
//for (int f=-6; f<7; f++) {
// for (int c=-6; c<7; c++) {
// rect(10*c, 10*f, 10, 10);
for (int k = 0; k < cols1; k++) {
// Begin loop for rows
for (int j = 0; j < rows1; j++) {
// Scaling up to draw a rectangle at (x,y)
int g = k*videoScale;
int t = j*videoScale;
// fill(255);
//stroke(0);
// For every column and row, a rectangle is drawn at an (x,y) location scaled and sized by videoScale.
rect(g, t, videoScale, videoScale);
}
}
}
//void sphereMy(float s, float d, float w) {
void sphereMy(float l, float r, float e) {
lights();
background(4);
pushMatrix();
noStroke();
// fill(255, 111, 11);
translate(r, l, e);
sphere (2);
// translate(width/2, height/2);
// rotateY(map(mouseX, 0, width, -PI, PI));
//rotateX(map(mouseY, 0, width, -PI, PI));
scale(0.07);
translate(-w/12, -h/12);
for (int y = 0; y < rows-1; y++) {
beginShape(TRIANGLE_STRIP);
texture(img);
for (int x = 0; x < cols; x++) {
ax = map(x, 0, cols, 0, img.width);
ay = map(y, 0, rows, 0, img.height);
vertex(x*scl, y*scl, map(brightness(img.get(int(ax), int(ay))), 320, 255, 0, 200), ax, ay );
ax = map(x, 0, cols, 0, img.width);
ay = map(y+1, 0, rows, 0, img.height);
vertex(x*scl, (y+1)*scl, map(brightness(img.get(int(ax), int(ay))), 320, 255, 0, 200), ax, ay );
//rect(x*scl, y*scl, scl, scl);
}
endShape();
}
popMatrix();
}
Thank you, @mnse!! I really appreciate your help as well as the extra time you spent clarifying in the code comments. In the future, I would like to edit the actual grid into different shapes and varying geometric designs which will react in the same way to the underlying static image. With that being said, I will be studying the code that you sent me this week and trying to make sense of how you connected it all.
As a beginner, my first idea on how to connect the aesthetic of the Perlin noise grid to a static image was to combine the code of the tutorial with the example code: 2D image mapped to 3D. I am still having a disconnect between the two, but is it possible to also get similar results with the following code as well?
PImage img;
void setup(){
size(900, 900, P3D);
img = loadImage("Jan24.jpg");
img.resize(900,900);
}
void draw() {
background(#f1f1f1);
fill(0);
noStroke();
sphereDetail(3);
//ellipse(mouseX,mouseY,40,40);
float tiles = 100;
float tileSize = width/tiles;
push();
rotateY(radians(frameCount) );
translate(width/2,height/2);
for (int x = 0; x < tiles; x++) {
for (int y = 0; y < tiles; y++) {
color c = img.get(int(x*tileSize),int(y*tileSize));
float b = map(brightness(c),0,255,01,0);
float z = map(b,0,1,-100,100);
push();
translate(x*tileSize - width/2,y*tileSize- height/2, z);
sphere(tileSize*b);
pop();
}
}
}
Thank you again! Your code is very helpful for me to bounce off and learn!!
Hi @jafal! I tried compiling your code but it doesn’t work for some reason? I’m interested in seeing the way you did it as well and learning more! Thank you so much!
Hi
When I came to this forum my knowledge was less than zero about processing I read almost all entire forum and watched all processing videos all over internet now I have little experience to code what I want not that easy for me but I can hardly
Here you can meet very good experience people you can learn from them as I did
The sketch I provided isn’t mine I collected it from multi topics
Hi @asymmetric,
if you remove the first push and do the translate before the rotate you are getting this (took my image instead as not having yours)… (see vid below)
You can use the points (for which you’re currently adding spheres) also as gridpoints. If you afterwards connect it to a mesh it would do the same … so my answer would be, yes!
However, you can do whatever you want to do with that height information (There are so many possibilities to play around with it) depending on your imagination.
Cheers
— mnse
That’s so exciting!! Thank you again!!
If anyone is interested, I found the second code in this thread via Tim Rodenbröker!
@asymmetric
Hi
You can find the same here and much more stuff to learn in to easy explanation
Hi @jafal! Thank you, I’m going to check those tutorials out today!
Hi @mnse ! One more question… is it possible to create a height map/ grid that reacts to a 3D primitive? Like a sphere or a rectangle?
Hi @asymmetric,
Don’t know what you mean.
Do you mean to apply the height informations to a sphere surface, or s.th. like this ?
Rectangle is 2D not 3D… Guess you mean cube !?
Or something like ie. cloth simulation ?
Cheers
— mnse
Hi @jafal! Thank you, I will play around with the terrain code via github that you provided!
Hi @mnse! I meant is it possible to do essentially the same code but with a 3D object? To clarify, can I have an image interact with a mesh object such as a cube? Can I use the heightmap to sculpt the mesh surface of 3D geometry like the following image? Then 3D print the end product?