Chrisir
September 9, 2022, 4:18pm
1
Hello all!
as we all know, we can use
beginShape curveVertex() endShape to make long complex curves.
See Reference / Processing.org
But it’s pretty much a black box.
How can I receive ALL points that are shown by curveVertex?
Apparently similar to curvePoint (with t / amt) but alas not quite
For a mcve see Easing equations with 'Influence' and 'In-/Outgoing Velocity' like in Adobe After Effects - #2 by Chrisir
Thank you all!
Chrisir
mnse
September 10, 2022, 9:28am
2
Hi @Chrisir ,
Not that easy as each implementation JAVA2D, P2D,etc handles it different. There is a native catmul-rom implementation in PGraphics which would store the vertices as float array, but it doesn’t seems to be used at all…
for OpenGL related (P2D/P3D) ones there is an internal class InGeometry used to store the vertices which are not accessable and for JAVA2D it uses the awt.geom stuff.
Here is a quick and evil hack for the latter…
Cheers
— mnse
import java.lang.reflect.*;
import java.awt.geom.*;
ArrayList<PVector> points = null;
void setup() {
size(300, 300);
}
void draw() {
background(0);
stroke(255);
noFill();
beginShape();
for (int x = 0; x < width; x+=width/8) {
curveVertex(x, x%2==0 ? height*0.25:height*0.75);
}
endShape();
if (points == null)
points = getVertices();
PVector current = points.get(int(millis()/100) % points.size());
noStroke();
fill(255, 0, 0);
ellipse(current.x, current.y, 8, 8);
}
Class findClass(Class c, String search) {
if (c.getName().endsWith(search))
return c;
else if (c.getSuperclass() != null)
return findClass(c.getSuperclass(), search);
return null;
}
ArrayList<PVector> getVertices() {
ArrayList<PVector> list = new ArrayList<PVector>();
try {
GeneralPath gpath = null;
Class pgclass = findClass(g.getClass(), "PGraphicsJava2D");
if (pgclass == null) {
throw new Exception("PGraphicsJava2D class not found");
}
Field[] fields = pgclass.getDeclaredFields();
for (Field f : fields) {
if ("gpath".equals(f.getName())) {
f.setAccessible(true);
gpath = (GeneralPath) f.get(g);
}
}
if (gpath == null) {
throw new Exception("class member gpath not found");
}
PathIterator i = gpath.getPathIterator(null, 1);
while (!i.isDone()) {
double[] coords = new double[6];
int segType = i.currentSegment(coords);
if (segType != PathIterator.SEG_CLOSE) {
list.add(new PVector((float)coords[0], (float)coords[1]));
}
i.next();
}
}
catch(Exception e) {
println("Error: " + e);
}
return list;
}
1 Like
glv
September 10, 2022, 1:10pm
3
Hello @mnse ,
Please provide some context to above with links to the source in GitHub.
I took a quick look already but you have done the groundwork and others would benefit from that journey.
:)
1 Like
mnse
September 12, 2022, 2:04pm
5
Hi,
Just to add a way for P2D mode …
Cheers
— mnse
PS: For demonstration purposes only … so still quick hack without following good coding conventions.
import java.lang.reflect.*;
import java.awt.geom.*;
ArrayList<PVector> points = null;
void setup() {
size(300, 300, P2D);
}
void draw() {
background(0);
stroke(255);
noFill();
beginShape();
for (int x = 0; x < width; x+=width/8) {
curveVertex(x, x%2==0 ? height*0.25:height*0.75);
}
endShape();
if (points == null) {
try {
points = getPoints();
if (points.isEmpty())
throw new Exception("no data found !?");
}
catch(Exception e) {
println("Error: " + e);
exit();
return;
}
}
PVector current = points.get(int(frameCount/5.) % points.size());
noStroke();
fill(255, 0, 0);
ellipse(current.x, current.y, 8, 8);
}
Class findClass(Class c, String search) {
if (c.getName().endsWith(search))
return c;
else if (c.getSuperclass() != null)
return findClass(c.getSuperclass(), search);
return null;
}
ArrayList<PVector> getPoints() throws Exception {
if (sketchRenderer().endsWith("PGraphics2D")) {
return getVerticesP2D();
} else if (sketchRenderer().endsWith("PGraphicsJava2D")) {
return getVerticesJAVA2D();
} else {
throw new Exception("unsupported renderer " + sketchRenderer() + " !?");
}
}
// JAVA2D Mode
ArrayList<PVector> getVerticesJAVA2D() throws Exception {
ArrayList<PVector> list = new ArrayList<PVector>();
GeneralPath gpath = null;
Class pgclass = findClass(g.getClass(), "PGraphicsJava2D");
if (pgclass == null) {
throw new Exception("PGraphicsJava2D class not found");
}
Field[] fields = pgclass.getDeclaredFields();
for (Field f : fields) {
if ("gpath".equals(f.getName())) {
f.setAccessible(true);
gpath = (GeneralPath) f.get(g);
break;
}
}
if (gpath == null) {
throw new Exception("class member gpath not found");
}
PathIterator i = gpath.getPathIterator(null, 1);
while (!i.isDone()) {
double[] coords = new double[6];
int segType = i.currentSegment(coords);
if (segType != PathIterator.SEG_CLOSE) {
list.add(new PVector((float)coords[0], (float)coords[1]));
}
i.next();
}
return list;
}
// P2D Mode
ArrayList<PVector> getVerticesP2D() throws Exception {
ArrayList<PVector> list = new ArrayList<PVector>();
float[] vertices = {};
int vertexCount = 0;
Class pgclass = findClass(g.getClass(), "PGraphicsOpenGL");
if (pgclass == null) {
throw new Exception("PGraphicsOpenGL class not found");
}
for (Field pgField : pgclass.getDeclaredFields()) {
if ("tessellator".equals(pgField.getName())) {
pgField.setAccessible(true);
Object tessellatorObj = pgField.get(g);
for (Field tessellatorField : tessellatorObj.getClass().getDeclaredFields()) {
if ("pathVertexCount".equals(tessellatorField.getName())) {
tessellatorField.setAccessible(true);
vertexCount = (int) tessellatorField.get(tessellatorObj);
}
else if ("pathVertices".equals(tessellatorField.getName())) {
tessellatorField.setAccessible(true);
vertices = (float[]) tessellatorField.get(tessellatorObj);
}
}
}
}
if (vertexCount == 0) {
throw new Exception("no Vertices found");
}
for (int i = 0; i < vertexCount*3; i+=3) {
list.add(new PVector(vertices[i], vertices[i+1]));
}
return list;
}
Github refs:
1 Like
mnse
September 12, 2022, 3:35pm
6
Hi,
finally, to be somehow complete, add version for P3D. Nearly the same as P2D just convert the 2D to 3D coords.
Cheers
— mnse
import java.lang.reflect.*;
import java.awt.geom.*;
ArrayList<PVector> points = null;
void setup() {
size(300, 300, P3D);
}
void draw() {
background(0);
stroke(255);
noFill();
beginShape();
for (int x = 0; x < width; x+=width/8) {
if (g.is3D())
curveVertex(x, x%2==0 ? height*0.25:height*0.75,x*-3.);
else
curveVertex(x, x%2==0 ? height*0.25:height*0.75);
}
endShape();
if (points == null) {
try {
points = getPoints();
if (points.isEmpty())
throw new Exception("no data found !?");
}
catch(Exception e) {
println("Error: " + e);
exit();
return;
}
}
PVector current = points.get(int(frameCount/5.) % points.size());
noStroke();
fill(255, 0, 0);
if (g.is3D())
translate(current.x,current.y,current.z);
else
translate(current.x,current.y);
ellipse(0,0,5,5);
}
Class findClass(Class c, String search) {
if (c.getName().endsWith(search))
return c;
else if (c.getSuperclass() != null)
return findClass(c.getSuperclass(), search);
return null;
}
ArrayList<PVector> getPoints() throws Exception {
if (sketchRenderer().equals(P2D)) {
return getVerticesP2D();
} else if (sketchRenderer().equals(P3D)) {
return getVerticesP3D();
} else if (sketchRenderer().equals(JAVA2D)) {
return getVerticesJAVA2D();
} else {
throw new Exception("unsupported renderer " + sketchRenderer() + " !?");
}
}
// JAVA2D Mode
ArrayList<PVector> getVerticesJAVA2D() throws Exception {
ArrayList<PVector> list = new ArrayList<PVector>();
GeneralPath gpath = null;
Class pgclass = findClass(g.getClass(), "PGraphicsJava2D");
if (pgclass == null) {
throw new Exception("PGraphicsJava2D class not found");
}
Field[] fields = pgclass.getDeclaredFields();
for (Field f : fields) {
if ("gpath".equals(f.getName())) {
f.setAccessible(true);
gpath = (GeneralPath) f.get(g);
break;
}
}
if (gpath == null) {
throw new Exception("class member gpath not found");
}
PathIterator i = gpath.getPathIterator(null, 1);
while (!i.isDone()) {
double[] coords = new double[6];
int segType = i.currentSegment(coords);
if (segType != PathIterator.SEG_CLOSE) {
list.add(new PVector((float)coords[0], (float)coords[1], 0));
}
i.next();
}
return list;
}
// P2D Mode
ArrayList<PVector> getVerticesP2D() throws Exception {
ArrayList<PVector> list = new ArrayList<PVector>();
float[] vertices = {};
int vertexCount = 0;
Class pgclass = findClass(g.getClass(), "PGraphicsOpenGL");
if (pgclass == null) {
throw new Exception("PGraphicsOpenGL class not found");
}
for (Field pgField : pgclass.getDeclaredFields()) {
if ("tessellator".equals(pgField.getName())) {
pgField.setAccessible(true);
Object tessellatorObj = pgField.get(g);
for (Field tessellatorField : tessellatorObj.getClass().getDeclaredFields()) {
if ("pathVertexCount".equals(tessellatorField.getName())) {
tessellatorField.setAccessible(true);
vertexCount = (int) tessellatorField.get(tessellatorObj);
}
if ("pathVertices".equals(tessellatorField.getName())) {
tessellatorField.setAccessible(true);
vertices = (float[]) tessellatorField.get(tessellatorObj);
}
}
}
}
if (vertexCount == 0) {
throw new Exception("no Vertices found");
}
for (int i = 0; i < vertexCount*3; i+=3) {
list.add(new PVector(vertices[i], vertices[i+1],0));
}
return list;
}
// P3D Mode
ArrayList<PVector> getVerticesP3D() throws Exception {
ArrayList<PVector> list = new ArrayList<PVector>();
float[] vertices = {};
int vertexCount = 0;
Class pgclass = findClass(g.getClass(), "PGraphicsOpenGL");
if (pgclass == null) {
throw new Exception("PGraphicsOpenGL class not found");
}
for (Field pgField : pgclass.getDeclaredFields()) {
if ("tessellator".equals(pgField.getName())) {
pgField.setAccessible(true);
Object tessellatorObj = pgField.get(g);
for (Field tessellatorField : tessellatorObj.getClass().getDeclaredFields()) {
if ("pathVertexCount".equals(tessellatorField.getName())) {
tessellatorField.setAccessible(true);
vertexCount = (int) tessellatorField.get(tessellatorObj);
}
if ("pathVertices".equals(tessellatorField.getName())) {
tessellatorField.setAccessible(true);
vertices = (float[]) tessellatorField.get(tessellatorObj);
}
}
}
}
if (vertexCount == 0) {
throw new Exception("no Vertices found");
}
for (int i = 0; i < vertexCount*3; i+=3) {
PVector m = new PVector(modelX(vertices[i],vertices[i+1],vertices[i+2])
,modelY(vertices[i],vertices[i+1],vertices[i+2])
,modelZ(vertices[i],vertices[i+1],vertices[i+2]));
list.add(new PVector(screenX(m.x,m.y,m.z)
,screenY(m.x,m.y,m.z)
,screenZ(m.x,m.y,m.z)));
}
return list;
}
3 Likes