问题
I was wondering how to achieve a similar effect like the shape of the letter "A" coming out of a horizontal line grid (see picture attached). Does somebody know how to find a tutorial? How is this technique called? Can you do it with Processing? Or do you need a 3D program?
Any hint is very welcome!
回答1:
Imagine extruding a blurred white A shape on a black background, a height map if you will.
In Processing you'd loop through each pixel in the image and map the brightness of each pixel to the z axis (as you already have the x,y coordinate).
In short:
- load or create an image of the A shape with a black background and smooth/blur the image to get smooth curves when mapping brightness to elevation
- loop through pixels and map each pixel's brightness to a z position
Here's a commented sketch to illustrate the idea:
PGraphics buffer;
PShape lines;
void setup(){
size(400,400,P3D);
smooth(8);
//create a PGraphics buffer to draw an "A" into and then blur it -> could use a loaded PImage
buffer = createGraphics(400,400);
buffer.beginDraw();
buffer.background(0);
buffer.textSize(270);
buffer.text("A",110,270);
buffer.endDraw();
//add blur (smooth edges = smooth elevation when moving to 3D)
buffer.filter(BLUR,8);
//setup PShape
int hSpacing = 1; //horizontal spacing
int vSpacing = 9; //vertical spacing
float maxHeight = 30; //maximum height (when brightness is mapped to elevation)
int lineStroke = color(255);
float hw = buffer.width * 0.5; //half width
float hh = buffer.height * 0.5; //half height
lines = createShape(GROUP);
//scan image on Y axis (skipping based on vertical spacing)
for(int y = 0 ; y < buffer.height; y += vSpacing){
//create a a shape made of lines
PShape line = createShape();
line.beginShape(LINES);
line.stroke(lineStroke);
line.strokeWeight(3);
//scan image on X axis
for(int x = 0; x < buffer.width; x += hSpacing){
//if we're not at the last pixel
if(x < buffer.width - 1){
//calculate the next x position
int nextX = x+1;
//calculate the brightness for the current and next pixel
float currentPixelBrightness = brightness(buffer.get(x,y));
float nextPixelBrightness = brightness(buffer.get(nextX,y));
//map brightness levels to elevation
float currentZ = map(currentPixelBrightness,0.0,255.0,0,maxHeight);
float nextZ = map(nextPixelBrightness,0.0,255.0,0,maxHeight);
//add a line between the current and next pixel using the calculated elevations, but offseting by half the image's with so the PShape pivot is at the centre
line.vertex(x - hw,y - hh,currentZ);
line.vertex(nextX - hw,y - hh,nextZ);
}
}
//finish the lines shape and add it to the main PShape
line.endShape();
lines.addChild(line);
}
}
void draw(){
background(0);
//debug mode - if mouse is pressed just render the 2D image
if(mousePressed){
image(buffer,0,0);
return;
}
//otherwise render the 3D image, rotating on X axis based on mouse X position
translate(width * 0.5,height * 0.5,0);
rotateX(map(mouseX,0,width,-PI,PI));
shape(lines,0,0);
}
There are multiple ways to implement this. This is just one option. Bare in mind the code isn't optimised for speed, instead left more verbose so it's easier to understand and tweak.
Feel free to play with the available variables and values (e.g. text size, blur amount, max. height, horizontal and vertical spacing, etc.), practice playing with createShape()(e.g. expand the horizontal lines, etc.)...overall, have fun!
This proves you don't really need to use a 3D program unless you really want to.
If you wanted to use one, Photoshop Extended has a 3D depth map option and most 3D editor allow you to create a mesh from a height map, to which you could apply a stripped texture.
来源:https://stackoverflow.com/questions/44861020/how-to-form-a-shape-out-of-horizontal-line-grid-with-processing