如何使用 Processing 在 P3D 中卷起 2D 网格
How to roll up a 2D Grid in P3D with Processing
我已经构建了一个带有嵌套循环的二维矩形网格。现在我想在三维 space 中“卷起”这个网格,或者换句话说“形成一个圆柱体”或“列”。随着我鼠标指针的移动。在“汇总”之前,我根据需要对所有内容进行了编程 - 但随后我的数学失败了。
float size;
float pixel = 75;
void setup() {
size(1920, 1080, P3D);
frameRate(30);
size = width/pixel;
rectMode(CENTER);
noStroke();
}
void draw() {
background(0);
rotateX(radians(45));
translate(pixel*size/2, -pixel*size, -pixel*size);
translate(-pixel*size/2, -pixel*size/2, -pixel*size/4);
pushMatrix();
for (int x = 0; x < pixel; x++) {
for (int y = 0; y < pixel; y++) {
pushMatrix();
float sin = sin(radians(x * 10)) * mouseX;
float cos = cos(radians(x * 10)) * mouseX;
translate(x*size, y*size);
rotate(radians(45));
fill(255);
rect(sin, cos, size/5, size/5);
popMatrix();
}
}
popMatrix();
}
网格不是卷起,而是扭曲了两次....我想我可以通过连接 sin(); 来实现“卷起”;和余弦(); - 类似于这个例子:
float sin, cos;
void setup() {
size(900, 900);
background(0);
}
void draw() {
translate(width/2, height/2);
for (int i = 0; i < 200; i++) {
sin = sin(radians(frameCount + i *10)) * 400;
cos = cos(radians(frameCount + i *10)) * 400;
ellipse(sin, cos, 10, 10);
}
}
实现此汇总的最佳方法是什么?
您使用极坐标系到笛卡尔坐标系的转换公式是正确的。
有多种方法可以解决这个问题。
这是一个想法,首先从 2D 开始:将圆展开成一条线。
我不知道这样做在数学上是 100% 正确的方法,我希望其他人 post 这样做。然而,我可以 post 使用这些“成分”进行足够令人信服的估算:
- 圆(周长)的长度为2πR
- Processing 的
lerp()
在两个值(函数的前两个参数)之间按百分比(表示 0.0 和 1.0 之间的值(称为归一化值))进行线性插值 -> 0 = 0% = 起始值, 0.5 = 50% = half-way 在标准值和最终值之间,1.0 = 100% = 在最终值)
- Processing 提供了一个
PVector
class 既可以方便地封装 2D/3D 点属性 (.x, .y, .z
),又提供了一个 lerp()
方法,它是一个很好 [=79=] 避免手动 lerping 3 次(每个维度 (x, y, z) 一次)
这里有一个基本的注释草图来说明上面的内容:
// total number of points
int numPoints = 24;
// circle radius
float radius = 50;
// circle length (circumference) = 2πR
float circleLength = TWO_PI * radius;
// spacing between each point for the length of the circle
float lengthIncrement = circleLength / numPoints;
// how many radians should each point on a circle increment by
float angleIncrement = TWO_PI / numPoints;
// cache for points on a the circle
PVector[] pointsCircle = new PVector[numPoints];
// cache for points on a line the lenght of the circle
PVector[] pointsLine = new PVector[numPoints];
void setup(){
size(300, 300);
noStroke();
// cache: pre-compute start(circle) and end(line) points
for(int i = 0 ; i < numPoints; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
float angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = new PVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = new PVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
void draw(){
background(0);
translate(width * 0.5, height * 0.5);
// map interpolation amount to mouse X position
float interpolationAmount = (float)mouseX / width;
// for each point
for(int i = 0 ; i < numPoints; i++){
// compute the interpolated position
PVector pointAnimated = PVector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// optional: visualise the first point as the darkest and last point as the brightest
fill(map(i, 0, numPoints -1, 64, 255));
// render the point as a circle
circle(pointAnimated.x, pointAnimated.y, 9);
}
}
可以在 3D 中应用相同的逻辑,使用额外的循环来重复 circles/lines 以显示为 cylinder/grid:
// total number of points
int numPointsX = 24;
// circle radius
float radius = 50;
// circle length (circumference) = 2πR
float circleLength = TWO_PI * radius;
// spacing between each point for the length of the circle
float lengthIncrement = circleLength / numPointsX;
// how many radians should each point on a circle increment by
float angleIncrement = TWO_PI / numPointsX;
// cache for points on a the circle
PVector[] pointsCircle = new PVector[numPointsX];
// cache for points on a line the lenght of the circle
PVector[] pointsLine = new PVector[numPointsX];
// number of points on Z axis
int numPointsZ = 24;
void setup(){
size(300, 300, P3D);
// render circles as thick points
noFill();
strokeWeight(9);
// cache: pre-compute start(circle) and end(line) points
for(int i = 0 ; i < numPointsX; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
float angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = new PVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = new PVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
void draw(){
background(0);
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
float interpolationAmount = (float)mouseX / width;
// render the grid (circular or rectangular)
beginShape(POINTS);
for(int j = 0 ; j < numPointsZ; j++){
// offset by half the size to pivot from center
float z = (circleLength * 0.5) - (lengthIncrement * j);
for(int i = 0 ; i < numPointsX; i++){
// compute the interpolated position
PVector pointAnimated = PVector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// render point
stroke(map(i, 0, numPointsX -1, 64, 255));
vertex(pointAnimated.x, pointAnimated.y, z);
}
}
endShape();
}
以上代码在没有 PVector
的情况下也能正常工作,但会更冗长。
另一件要记住的事情是,静态 PVector.lerp()
方法将在每次调用时生成一个新的 PVector 实例:这对于像这样的小型演示是可以的,但是将一堆 PVector
缓存到 lerp()
应该会浪费更少的内存。
为了完整起见,这里是交互式版本,您可以 运行 就在这里通过 p5.js:
// total number of points
let numPoints = 24;
// circle radius
let radius = 50;
// circle length (circumference) = 2πR
let circleLength;
// spacing between each point for the length of the circle
let lengthIncrement;
// how many radians should each point on a circle increment by
let angleIncrement;
// cache for points on a the circle
let pointsCircle = new Array(numPoints);
// cache for points on a line the lenght of the circle
let pointsLine = new Array(numPoints);
function setup(){
createCanvas(300, 300);
noStroke();
// ensure TWO_PI is defined before assignment
circleLength = TWO_PI * radius;
lengthIncrement = circleLength / numPoints;
angleIncrement = TWO_PI / numPoints;
// cache: pre-compute start(circle) and end(line) points
for(let i = 0 ; i < numPoints; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
let angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = createVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = createVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
function draw(){
background(0);
translate(width * 0.5, height * 0.5);
// map interpolation amount to mouse X position
let interpolationAmount = constrain(mouseX, 0, width) / width;
// for each point
for(let i = 0 ; i < numPoints; i++){
// compute the interpolated position
let pointAnimated = p5.Vector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// optional: visualise the first point as the darkest and last point as the brightest
fill(map(i, 0, numPoints -1, 64, 255));
// render the point as a circle
circle(pointAnimated.x, pointAnimated.y, 9);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
// total number of points
let numPointsX = 24;
// circle radius
let radius = 50;
// circle length (circumference) = 2πR
let circleLength;
// spacing between each point for the length of the circle
let lengthIncrement;
// how many radians should each point on a circle increment by
let angleIncrement;
// cache for points on a the circle
let pointsCircle = new Array(numPointsX);
// cache for points on a line the lenght of the circle
let pointsLine = new Array(numPointsX);
// number of points on Z axis
let numPointsZ = 24;
function setup(){
createCanvas(600, 600, WEBGL);
// ensure TWO_PI is defined before assignment
circleLength = TWO_PI * radius;
lengthIncrement = circleLength / numPointsX;
angleIncrement = TWO_PI / numPointsX;
// render circles as thick points
noFill();
strokeWeight(9);
stroke(255);
// cache: pre-compute start(circle) and end(line) points
for(let i = 0 ; i < numPointsX; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
let angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = createVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = createVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
function draw(){
background(0);
orbitControl();
rotateX(HALF_PI);
let interpolationAmount = constrain(mouseX, 0, width) / width;
// render the grid (circular or rectangular)
beginShape(POINTS);
for(let j = 0 ; j < numPointsZ; j++){
// offset by half the size to pivot from center
let z = (circleLength * 0.5) - (lengthIncrement * j);
for(let i = 0 ; i < numPointsX; i++){
// compute the interpolated position
let pointAnimated = p5.Vector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// render point
vertex(pointAnimated.x, pointAnimated.y, z);
}
}
endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
更新
如前所述,在这种简单的情况下,您可以在没有 PVector 的情况下工作:
// total number of points
int numPointsX = 24;
// circle radius
float radius = 50;
// circle length (circumference) = 2πR
float circleLength = TWO_PI * radius;
// spacing between each point for the length of the circle
float lengthIncrement = circleLength / numPointsX;
// how many radians should each point on a circle increment by
float angleIncrement = TWO_PI / numPointsX;
// cache for points on a the circle
float[][] pointsCircle = new float[numPointsX][2];
// cache for points on a line the lenght of the circle
float[][] pointsLine = new float[numPointsX][2];
// number of points on Z axis
int numPointsZ = 24;
void setup(){
size(300, 300, P3D);
// render circles as thick points
noFill();
strokeWeight(9);
// cache: pre-compute start(circle) and end(line) points
for(int i = 0 ; i < numPointsX; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
float angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = new float[]{cos(angle) * radius, sin(angle) * radius};
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = new float[]{lengthIncrement * i - (circleLength * 0.5), 0};
}
}
void draw(){
background(0);
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
float interpolationAmount = (float)mouseX / width;
// render the grid (circular or rectangular)
beginShape(POINTS);
for(int j = 0 ; j < numPointsZ; j++){
// offset by half the size to pivot from center
float z = (circleLength * 0.5) - (lengthIncrement * j);
for(int i = 0 ; i < numPointsX; i++){
// compute the interpolated position
float pointAnimatedX = lerp(pointsCircle[i][0], pointsLine[i][0], interpolationAmount);
float pointAnimatedY = lerp(pointsCircle[i][1], pointsLine[i][1], interpolationAmount);
// render point
stroke(map(i, 0, numPointsX -1, 64, 255));
vertex(pointAnimatedX, pointAnimatedY, z);
}
}
endShape();
}
就我个人而言,我觉得 PVector 版本的可读性稍微好一些。
我已经构建了一个带有嵌套循环的二维矩形网格。现在我想在三维 space 中“卷起”这个网格,或者换句话说“形成一个圆柱体”或“列”。随着我鼠标指针的移动。在“汇总”之前,我根据需要对所有内容进行了编程 - 但随后我的数学失败了。
float size;
float pixel = 75;
void setup() {
size(1920, 1080, P3D);
frameRate(30);
size = width/pixel;
rectMode(CENTER);
noStroke();
}
void draw() {
background(0);
rotateX(radians(45));
translate(pixel*size/2, -pixel*size, -pixel*size);
translate(-pixel*size/2, -pixel*size/2, -pixel*size/4);
pushMatrix();
for (int x = 0; x < pixel; x++) {
for (int y = 0; y < pixel; y++) {
pushMatrix();
float sin = sin(radians(x * 10)) * mouseX;
float cos = cos(radians(x * 10)) * mouseX;
translate(x*size, y*size);
rotate(radians(45));
fill(255);
rect(sin, cos, size/5, size/5);
popMatrix();
}
}
popMatrix();
}
网格不是卷起,而是扭曲了两次....我想我可以通过连接 sin(); 来实现“卷起”;和余弦(); - 类似于这个例子:
float sin, cos;
void setup() {
size(900, 900);
background(0);
}
void draw() {
translate(width/2, height/2);
for (int i = 0; i < 200; i++) {
sin = sin(radians(frameCount + i *10)) * 400;
cos = cos(radians(frameCount + i *10)) * 400;
ellipse(sin, cos, 10, 10);
}
}
实现此汇总的最佳方法是什么?
您使用极坐标系到笛卡尔坐标系的转换公式是正确的。
有多种方法可以解决这个问题。 这是一个想法,首先从 2D 开始:将圆展开成一条线。 我不知道这样做在数学上是 100% 正确的方法,我希望其他人 post 这样做。然而,我可以 post 使用这些“成分”进行足够令人信服的估算:
- 圆(周长)的长度为2πR
- Processing 的
lerp()
在两个值(函数的前两个参数)之间按百分比(表示 0.0 和 1.0 之间的值(称为归一化值))进行线性插值 -> 0 = 0% = 起始值, 0.5 = 50% = half-way 在标准值和最终值之间,1.0 = 100% = 在最终值) - Processing 提供了一个
PVector
class 既可以方便地封装 2D/3D 点属性 (.x, .y, .z
),又提供了一个lerp()
方法,它是一个很好 [=79=] 避免手动 lerping 3 次(每个维度 (x, y, z) 一次)
这里有一个基本的注释草图来说明上面的内容:
// total number of points
int numPoints = 24;
// circle radius
float radius = 50;
// circle length (circumference) = 2πR
float circleLength = TWO_PI * radius;
// spacing between each point for the length of the circle
float lengthIncrement = circleLength / numPoints;
// how many radians should each point on a circle increment by
float angleIncrement = TWO_PI / numPoints;
// cache for points on a the circle
PVector[] pointsCircle = new PVector[numPoints];
// cache for points on a line the lenght of the circle
PVector[] pointsLine = new PVector[numPoints];
void setup(){
size(300, 300);
noStroke();
// cache: pre-compute start(circle) and end(line) points
for(int i = 0 ; i < numPoints; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
float angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = new PVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = new PVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
void draw(){
background(0);
translate(width * 0.5, height * 0.5);
// map interpolation amount to mouse X position
float interpolationAmount = (float)mouseX / width;
// for each point
for(int i = 0 ; i < numPoints; i++){
// compute the interpolated position
PVector pointAnimated = PVector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// optional: visualise the first point as the darkest and last point as the brightest
fill(map(i, 0, numPoints -1, 64, 255));
// render the point as a circle
circle(pointAnimated.x, pointAnimated.y, 9);
}
}
可以在 3D 中应用相同的逻辑,使用额外的循环来重复 circles/lines 以显示为 cylinder/grid:
// total number of points
int numPointsX = 24;
// circle radius
float radius = 50;
// circle length (circumference) = 2πR
float circleLength = TWO_PI * radius;
// spacing between each point for the length of the circle
float lengthIncrement = circleLength / numPointsX;
// how many radians should each point on a circle increment by
float angleIncrement = TWO_PI / numPointsX;
// cache for points on a the circle
PVector[] pointsCircle = new PVector[numPointsX];
// cache for points on a line the lenght of the circle
PVector[] pointsLine = new PVector[numPointsX];
// number of points on Z axis
int numPointsZ = 24;
void setup(){
size(300, 300, P3D);
// render circles as thick points
noFill();
strokeWeight(9);
// cache: pre-compute start(circle) and end(line) points
for(int i = 0 ; i < numPointsX; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
float angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = new PVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = new PVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
void draw(){
background(0);
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
float interpolationAmount = (float)mouseX / width;
// render the grid (circular or rectangular)
beginShape(POINTS);
for(int j = 0 ; j < numPointsZ; j++){
// offset by half the size to pivot from center
float z = (circleLength * 0.5) - (lengthIncrement * j);
for(int i = 0 ; i < numPointsX; i++){
// compute the interpolated position
PVector pointAnimated = PVector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// render point
stroke(map(i, 0, numPointsX -1, 64, 255));
vertex(pointAnimated.x, pointAnimated.y, z);
}
}
endShape();
}
以上代码在没有 PVector
的情况下也能正常工作,但会更冗长。
另一件要记住的事情是,静态 PVector.lerp()
方法将在每次调用时生成一个新的 PVector 实例:这对于像这样的小型演示是可以的,但是将一堆 PVector
缓存到 lerp()
应该会浪费更少的内存。
为了完整起见,这里是交互式版本,您可以 运行 就在这里通过 p5.js:
// total number of points
let numPoints = 24;
// circle radius
let radius = 50;
// circle length (circumference) = 2πR
let circleLength;
// spacing between each point for the length of the circle
let lengthIncrement;
// how many radians should each point on a circle increment by
let angleIncrement;
// cache for points on a the circle
let pointsCircle = new Array(numPoints);
// cache for points on a line the lenght of the circle
let pointsLine = new Array(numPoints);
function setup(){
createCanvas(300, 300);
noStroke();
// ensure TWO_PI is defined before assignment
circleLength = TWO_PI * radius;
lengthIncrement = circleLength / numPoints;
angleIncrement = TWO_PI / numPoints;
// cache: pre-compute start(circle) and end(line) points
for(let i = 0 ; i < numPoints; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
let angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = createVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = createVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
function draw(){
background(0);
translate(width * 0.5, height * 0.5);
// map interpolation amount to mouse X position
let interpolationAmount = constrain(mouseX, 0, width) / width;
// for each point
for(let i = 0 ; i < numPoints; i++){
// compute the interpolated position
let pointAnimated = p5.Vector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// optional: visualise the first point as the darkest and last point as the brightest
fill(map(i, 0, numPoints -1, 64, 255));
// render the point as a circle
circle(pointAnimated.x, pointAnimated.y, 9);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
// total number of points
let numPointsX = 24;
// circle radius
let radius = 50;
// circle length (circumference) = 2πR
let circleLength;
// spacing between each point for the length of the circle
let lengthIncrement;
// how many radians should each point on a circle increment by
let angleIncrement;
// cache for points on a the circle
let pointsCircle = new Array(numPointsX);
// cache for points on a line the lenght of the circle
let pointsLine = new Array(numPointsX);
// number of points on Z axis
let numPointsZ = 24;
function setup(){
createCanvas(600, 600, WEBGL);
// ensure TWO_PI is defined before assignment
circleLength = TWO_PI * radius;
lengthIncrement = circleLength / numPointsX;
angleIncrement = TWO_PI / numPointsX;
// render circles as thick points
noFill();
strokeWeight(9);
stroke(255);
// cache: pre-compute start(circle) and end(line) points
for(let i = 0 ; i < numPointsX; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
let angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = createVector(cos(angle) * radius, sin(angle) * radius);
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = createVector(lengthIncrement * i - (circleLength * 0.5), 0);
}
}
function draw(){
background(0);
orbitControl();
rotateX(HALF_PI);
let interpolationAmount = constrain(mouseX, 0, width) / width;
// render the grid (circular or rectangular)
beginShape(POINTS);
for(let j = 0 ; j < numPointsZ; j++){
// offset by half the size to pivot from center
let z = (circleLength * 0.5) - (lengthIncrement * j);
for(let i = 0 ; i < numPointsX; i++){
// compute the interpolated position
let pointAnimated = p5.Vector.lerp(pointsCircle[i], pointsLine[i], interpolationAmount);
// render point
vertex(pointAnimated.x, pointAnimated.y, z);
}
}
endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
更新
如前所述,在这种简单的情况下,您可以在没有 PVector 的情况下工作:
// total number of points
int numPointsX = 24;
// circle radius
float radius = 50;
// circle length (circumference) = 2πR
float circleLength = TWO_PI * radius;
// spacing between each point for the length of the circle
float lengthIncrement = circleLength / numPointsX;
// how many radians should each point on a circle increment by
float angleIncrement = TWO_PI / numPointsX;
// cache for points on a the circle
float[][] pointsCircle = new float[numPointsX][2];
// cache for points on a line the lenght of the circle
float[][] pointsLine = new float[numPointsX][2];
// number of points on Z axis
int numPointsZ = 24;
void setup(){
size(300, 300, P3D);
// render circles as thick points
noFill();
strokeWeight(9);
// cache: pre-compute start(circle) and end(line) points
for(int i = 0 ; i < numPointsX; i++){
// compute the angle using the increment but also offset by 90 degrees so 1st point is at bottom
float angle = (angleIncrement * i) + HALF_PI;
pointsCircle[i] = new float[]{cos(angle) * radius, sin(angle) * radius};
// compute positions on a line, offsetting by half: avoids most self-intersections when animating
pointsLine[i] = new float[]{lengthIncrement * i - (circleLength * 0.5), 0};
}
}
void draw(){
background(0);
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
float interpolationAmount = (float)mouseX / width;
// render the grid (circular or rectangular)
beginShape(POINTS);
for(int j = 0 ; j < numPointsZ; j++){
// offset by half the size to pivot from center
float z = (circleLength * 0.5) - (lengthIncrement * j);
for(int i = 0 ; i < numPointsX; i++){
// compute the interpolated position
float pointAnimatedX = lerp(pointsCircle[i][0], pointsLine[i][0], interpolationAmount);
float pointAnimatedY = lerp(pointsCircle[i][1], pointsLine[i][1], interpolationAmount);
// render point
stroke(map(i, 0, numPointsX -1, 64, 255));
vertex(pointAnimatedX, pointAnimatedY, z);
}
}
endShape();
}
就我个人而言,我觉得 PVector 版本的可读性稍微好一些。