How to use "vertex(float[] v)" ?

edited December 2014 in Questions about Code

Hello !

I 'm trying to use "vertex function" using a float array but it doesn't work... (I don't know how it works at least...)

I tryed with X Y U V values and X Y Z U V values but I get nothing on the screen. I have no error message, my demo is running but nothing is rendered.

Do someone know ?

My code is very simple

float[] datas;
PImage img;

void setup(){
  size(100,100,P3D);

  img = createImage(100,100,ARGB);
  img.loadPixels();
  int i,len = img.pixels.length;
  for(i=0;i<len;i++) img.pixels[i] = color(255,0,0);
  img.updatePixels();

  datas = new float[12];
  datas[0] = 0;
  datas[1] = 0;
  datas[2] = 0;
  datas[3] = 0;

  datas[4] = 100;
  datas[5] = 0;
  datas[6] = 100;
  datas[7] = 0;

  datas[8] = 0;
  datas[9] = 100;
  datas[10] = 0;
  datas[11] = 100;

}

void draw(){
  clear();

  beginShape();
  texture(img);
  vertex(datas);
  endShape();
}

I just observ that in Processing, the code create an "OutOfBoundException" - I have no error message in Eclipse -

Sounds like there is a bug here (?)

Answers

  • Answer ✓

    Not a bug but the documentation is not clear.

    In the source code PGraphics the method is

      /**
       * Used by renderer subclasses or PShape to efficiently pass in already
       * formatted vertex information.
       * @param v vertex parameters, as a float array of length VERTEX_FIELD_COUNT
       */
      public void vertex(float[] v) {
        vertexCheck();
        curveVertexCount = 0;
        float[] vertex = vertices[vertexCount];
        System.arraycopy(v, 0, vertex, 0, VERTEX_FIELD_COUNT);
        vertexCount++;
      }
    

    where VERTEX_FIELD_COUNT has the value 37 and you are only passing an array of 12 elements hence the exception.

    What is not clear is what constitutes formatted vertex information I suspect it includes x,y,z,,u,u,r,g,b,texture info but I don't know the correct format.

    There are several versions of the vertex method the important thing to know is that each call to vertex defines a SINGLE vertex and a shape must have a minimum of 3 vertices (i.e. a triangle)

  • edited November 2014

    Hello Quark

    I saw that VERTEX_FIELD_COUNT represents 37

    But I trully don't understand why 37 and not 42 or 42 000.

    At first, when I write the vertex call, I wrote it like that

    vertex(myArray, nbVertex);

    because it sounds to me obvious that I could define a custom length and that processing then should divide the length of the array by the number of vertex to get the number of data by vertex.

    But no... There is this length of 37 instead...

    I'm very disappointed...

    Thank you for you answer!

    EDIT : the code I posted was just an example, in my real code I have thousands of float in my array, that's why I didn't have any error message in eclipse.

  • Maybe I can do what I want with PShape but I don't understand exactly how it works...

    I found the method PShape.setPath but I don't understand the parameters http://www.processing.org/reference/javadoc/core/processing/core/PShape.html#setPath(int,%20float[][])

    Do someone know how it works ?

    Thanks !

  • Select File | Examples... from the menus then select Topics | Create Shapes. Try out the examples to see how its done.

  • edited November 2014

    I already did that...

    But I think the method I need could be PShape.setPath but there is no documentation (or example) about it.

    Thank you anyway

    EDIT : I really can't imagine that the only one way to send all the vertex in one time is using "PShape.loadShape" and a ".obj" file....

    I'm almost sure PShape.setShape do what I want but I still don't get it working... If someone know how to do, you're welcome ! :)

  • Here is my current code (no error message but nothing on the screen...)

    float[] datas;
    PImage img;
    PShape s;
    void setup(){
      size(1000,1000,P3D);
    
      img = createImage(100,100,ARGB);
      img.loadPixels();
      int i,len = img.pixels.length;
      for(i=0;i<len;i++) img.pixels[i] = color(255,0,0);
      img.updatePixels();
    
    
      s = new PShape(PATH);
    
      datas = new float[15];
      datas[0] = 0;
      datas[1] = 0;
      datas[2] = 0;
      datas[3] = 0;
      datas[4] = 0;
    
      datas[5] = 100;
      datas[6] = 0;
      datas[7] = 0;
      datas[8] = 100;
      datas[9] = 0;
    
      datas[10] = 0;
      datas[11] = 100;
      datas[12] = 0;
      datas[13] = 0;
      datas[14] = 100;
    
      float[][] pathDatas = new float[1][15];
      pathDatas[0] = datas;
    
      s.beginShape();
      s.texture(img);
      s.setPath(1,pathDatas);
      s.endShape(CLOSE);
    }
    void draw(){
      clear();
      background(255);
      shape(s);
    }
    
  • edited November 2014

    I think I understood how it works... But I don't know how to compute the normals...

    I understood why VERTEX_FIELD_COUNT == 37 and why a path is a float[][];

    actually, each path contains 37 float[] , each one of them match to a property.

    path[0] -> X positions;
    path[1] -> Y positions;
    path[2] -> Z positions;
    path[3] -> red values;
    path[4] -> green values;
    path[5] -> blue values;
    path[6] -> alpha values;
    

    etc....

    I filled these 7 first entry but it still doesn't work.... I think - but I'm not sure - it needs the normal (X/Y/Z) to works...

    It's much more complex than I though...

  • I'm still working on it.

    If someone is looking for the same thing, the wanted class is called "InGeometry" and it's described at the line 7132 of that class

    https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java

  • edited November 2014

    ....It looks impossible to access to the Object that I want from a class that exends PGraphicsOpenGL... (the console tell me "it's not visible" )

    I think the only one way is the update the code inside PGraphicsOpenGL...

    If I do that, in a context of the creation of a library, could it be possible to add my CustomPGraphicsOpenGL class without update the whole processing software ?

  • edited November 2014

    It looks impossible to access to the object that I want from a class that extends PGraphicsOpenGL

    Made a search in that PGraphicsOpenGL source and didn't find any private fields there!
    At most they're protected! Therefore, subclasses have access to all its fields! :D

    ... could it be possible to add my CustomPGraphicsOpenGL class...

    I've made a PGraphicsJava2D subclass called Layer.
    Perhaps you should take a look at it too: ;)

  • "Made a search in that PGraphicsOpenGL source and didn't find any private fields there! At most they're protected! Therefore, subclasses have access to all its fields! "

    I agree. I read the classes PGraphics & PGraphicsOpenGL maybe 10 times between today and yesterday.

    But please, get a simple try and see by yourself

    class CustomGraphics extends PGraphicsOpenGL {
    
      CustomGraphics(PApplet applet){
        super(); 
        setParent(applet);
        setPrimary(false);
        setSize(applet.width,applet.height);
    
        beginDraw();
        background(255,200,0);
        noStroke();
    
        beginShape(TRIANGLES); 
        fill(255,0,0);
        vertex(0,0,0);
        vertex(100,0,0);
        vertex(0,100,0);
        endShape();
        endDraw();
    
        println(inGeo.vertices);
    
      }
    
      class CustomGeom extends InGeometry {
    
        InGeometry(PGraphicsOpenGL pg, int mode){
         super(pg,mode);
        }
    
      }
    
    }
    
    CustomGraphics cg;
    void setup(){
      size(1000,1000,P3D);
      cg = new CustomGraphics();
    }
    
    void draw(){
      clear();
      image(cg,0,0);
    }
    

    I can't compile because it doesn't find "vertices" in "inGeo" (but there is a property "vertices" in the class InGeometry).

    If you put comments before the "println", you'll see that it's also impossible to extends the object InGeometry.

    My final goal is either the update the values contained in the properties of the class InGeometry, either to create a custom instance of InGeometry and replace the existed one.

    the class InGeometry is defined inside the class PGraphicsOpenGL, it is static and protected... To be honnest, I really don't know what does that mean... Never saw that kind of structure before...

  • Something is really weird with these classes... For example, PShape doesn't extends PGraphics but uses somes local constants (like X, Y or Z) only declared in PGraphics (and only usable in the context of PGraphics actually)

    I don't understand very well and the code is huge... Don't understand the dev who made it didn't divide the file in separate readable classes... More than 10 000 lines in PGraphicsOpenGL... It's crasy...

  • Really, if it's possible, I would prefer rebuild my own version of PGraphicsOpenGL... But if I do that, will my code still run with a "classic" version of Processing ? I'm not sure to understand exactly how works the compilation process...

    does it work if I put my CustomPGraphicsOpenGL in the "datas folder" , named "PGraphicsOpenGL.java" ? Does it replace the classic one ?

  • edited November 2014

    What I see in PGraphicsOpenGL is that it coulds be much much much more optimized. I didn't imagine Java was so powerfull...

    In AS3 you basicly can't write that kind of huge code, it will kill the CPU immediatly. Because AS3 is so slow, I think AS3-dev (not all of them unfortunately) use to deal with very-strongly-optimized structure and then it's very interesting for me to use Java & Processing after more than 10 years of creative-coding with Actionscript :)

    If I can adapt my JS-to-GLSL stuff for processing, it would be possible to create 1 shader for each scenario possible instead of using always generic shader. The problem with the Processing structure & shader is that when you want to draw some vertex with a simple fill, without texture, without stroke, without light, without nothing else. It's impossible for Processing to render only that.

    Right now, in the most optimized case, you have buffers for positions X,Y,Z,U,V,R,G,B,A,NX,NY,NZ,SR,SG,SB,SA

    (where NX,NY,NZ refeers to NormalX,NormalY,NormalZ ; and SR,SG,SB,SA refeers to StrokeRed,StrokeGreen,StrokeBlue,StrokeAlpha)

    It means that in the shader, even if you just want a fill without a stroke, the stroke will be drawn with an alpha = 0 and a transparent light

    It's really not the best optimization ever.

    Java is powerfull then it works... But on mobile, it certainly works less fine, and battery becomes an issue...

    And even if it works, wouldn't be cool if it woks even better ?

    EDIT : Really, I passed the last ten years to build rendering-lib and rendering-lib and renderind-lib,... I maybe made 100 a-bit-different rendering engine since I'm a coder and actually my goal is to obtain something like Processing... But Processing itself is not enought optimized for me.... I'm discouraged by the fact of doing "all-the-everything-else" but the rendering pipeline... I think I know the subject and it's a real surprise for me but I'm not affraid at all with the idea of rebuild the pipeline of Processing (it sounds to me like a very huge stuff 2 months ago) . I read the code a lot of time. I mainly understood it. What I didn't understood is the Java-grammar because I never saw class defined in a class until now - and that's why I would prefer rebuild my own version because I want to understand every aspect of what I'm doing -

    EDIT2 : "But Processing itself is not enought optimized for me..." Actually it is, or it was until the moment when I saw it could be better :)

  • I can't compile because it doesn't find vertices in "inGeo" (but there is a property vertices in the class InGeometry).

    It doesn't say it doesn't exist. Rather that it's invisible. Meaning you don't have permission to access that member!

    As mentioned, class PGraphicsOpenGL doesn't have private fields. However, that doesn't extend to other classes instantiated by it!

    Field vertices belongs to class InGeometry. And it got its own access permissions! [-X

  • What I didn't understood is the Java-grammar because I never saw class defined in a class.

    Actually by default in Processing, all our classes are nested to the "sketch" top-class! @-)
    If you hate nested classes, you're gonna hate JavaScript and similar languages even more, which even got functions inside other functions, remembering variables, snapshotting everything in something called closures! :-SS

  • Ok but then, what is the good way to put vertices in the vertices-array with arrayCopy instead of PGraphics.vertex ?

  • "If you hate nested classes, you're gonna hate JavaScript "

    You're right, I hate javascript exactly for that (but it's very usefull in some cases, but it's more like a hack for me to use Function as Objects

  • Actually... I just think again about how works

    vertex(float[] v)

    And it make perfect sense now :)

    I still want to update the buffer by myself but that function will finally allow me to do more with less.

    It's not as good as updating every datas in the array at the same time, but it allow to transfer a lot of data concerning a vertex in a single time.

    Then it's possible to transfer in a single call the XYZ RGBA UV SR SG SB SA NX NY NZ , and every other of the 37 vertex properties in one single call. It's better than nothing. The opposite would have been better because we usually have much more vertex than vertex-array, and ,in fine, the vertex array are updated then....

  • edited November 2014

    I still want to update the buffer by myself...

    Unfortunately, InGeometry doesn't have a public constructor. And hence can't be subclassed!
    Unless that subclass happens to be from the same package as PGraphicsOpenGL. :-@

    Only other option to grab vertices field is via Java's reflect library. More specifically the Field class:
    https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html
    https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredField-java.lang.String-

    Along w/ AccessibleObject's setAccessible() method:
    https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible-boolean-

  • edited November 2014

    Thank you a lot GoToLoop !

    I will look at it carefully :)

    I'm still crying with vertex(float[]) , I though I understood but I didn't...Still nothing on the screen... :-((

    EDIT "Unfortunately, InGeometry doesn't have a public constructor. And hence can't be subclassed! Unless that subclass happens to be from the same package as PGraphicsOpenGL. "

    I understand the problem, thank you.

    Sorry to ask again that question but if I do that, if I update the code of the class PGraphicsOpenGl, would it be possible to insert it directly inside the library of does it need to rebuild the processing software to be able to read it ?

    EDIT2 : I just looked at Field class. I think it's exactly what I was looking for all the day ! Thanks !

    EDIT3 : by "inside the library", I mean, the lib I'm working on, if I want to share it.

  • edited November 2014

    EDIT3 : by "inside the library", I mean, the lib I'm working on, if I want to share it.

    Like mentioned, if you "lie" that your library is package processing.opengl.PGraphicsOpenGL,
    you might be able to subclass PGraphicsOpenGL.InGeometry w/o any more "hacks"! :ar!

    Then you can add a new method to it like: =P~

    public float[] gimmeVertices() {
      return vertices;
    }
    
  • edited November 2014

    Concerning my original question "how to use vertex(float[] v) ? "

    I still don't get it X_X

    Here is my current code, maybe someone will see immediatly what's wrong in it...

    PImage img;
    float[] datas0 = new float[37];
    float[] datas1 = new float[37];
    float[] datas2 = new float[37];
    
    PGraphics g;
    
    void setup(){
      size(256,256,P3D);
    
      g = createGraphics(256,256,P3D);
      img = loadImage("color.png");
      for(int i=0;i<37;i++){
         datas0[i] = 0.0f;
         datas1[i] = 0.0f;
         datas2[i] = 0.0f;
       }
    
    
      //X
      datas0[0] = 0.0f;
      datas1[0] = 100f;
      datas2[0] = 0.0f;
    
      //Y
      datas0[1] = 0.0f;
      datas1[1] = 0.0f;
      datas2[1] = 100f;
    
      //Z
      datas0[2] = 0.0f;
      datas1[2] = 0.0;
      datas2[2] = 0.0f;
    
      //U
      datas0[3] = 0.0f;
      datas1[3] = 100.0f;
      datas2[3] = 0.0f;
    
      //V
      datas0[4] = 0.0f;
      datas1[4] = 0.0f;
      datas2[4] = 100.0f;
    
      //R
      datas0[5] = 255.0f;
      datas1[5] = 255.0f;
      datas2[5] = 255.0f;
    
      //G
      datas0[6] = 0.0f;
      datas1[6] = 0.0f;
      datas2[6] = 0.0f;
    
      //B
      datas0[7] = 0.0f;
      datas1[7] = 0.0f;
      datas2[7] = 0.0f;
    
      //A
      datas0[8] = 255.0f;
      datas1[8] = 255.0f;
      datas2[8] = 255.0f;
    
    
    }
    
    
    
    void draw(){
      clear();
      background(255);
    
      g.beginDraw();
      g.beginShape();
      g.background(0);
      g.texture(img);
    
      //g.vertex(0,0,0,0,0);
      //g.vertex(100,0,0,100,0);
      //g.vertex(0,100,0,0,100);
    
      g.vertex(datas0);
      g.vertex(datas1);
      g.vertex(datas2);
    
      g.endShape();
      g.endDraw();
      image(g,0,0);
    
    }
    

    "Like mentioned, if you "lie" that your library is package processing.opengl.PGraphicsOpenGL, you might be able to subclass PGraphicsOpenGL.InGeometry w/o any more "hacks"! "

    To be trully honnest, I don't understand what you mean by "lie"... I'm getting tired by this problem and I dont think about it as well as before having passed 30 hours on it.

  • edited November 2014

    A Java's protected member can be freely accessed by any class which belongs to its same package.
    When we create a ".java" file, we can specify which package it belongs to. That's the "lie"! >:)

    But it's preferable to simply get field vertices by force via reflection.
    You're gonna need class Class and its getDeclaredField() in order to get a Field object.
    And don't forget AccessibleObject's setAccessible() method! O:-)

  • edited January 2015

    Hello @tlecoz! I wonder whether you've finally accomplished your PGraphics's vertices[] hack already? :D
    Just decided to adapt my old Layer class, which extended PGraphicsJAVA2D, to use PGraphicsP3D instead now:
    http://forum.processing.org/two/discussion/6884/question-about-pgraphics

    After that, I've relied on reflection via Field in order to "steal" InGeometry's vertices[] from inGeo!
    It's split in 2 tabs: class HackedP3D's ".java" & sketch's ".pde" w/ custom subclass of HackedP3D called MyP3D: :ar!

    "HackedP3D.java":

    import processing.core.PApplet;
    import processing.opengl.PGraphics3D;
    import java.lang.reflect.Field;
    
    public class HackedP3D extends PGraphics3D {
      public HackedP3D() {
        super();
      }
    
      public HackedP3D(int w, int h) {
        super();
        final PApplet p = getEnclosingPApplet();
        initialize(w, h, p, p.dataPath(""));
        ignite();
      }
    
      public HackedP3D(int w, int h, PApplet p) {
        super();
        initialize(w, h, p, p.dataPath(""));
        ignite();
      }
    
      public HackedP3D(int w, int h, PApplet p, String s) {
        super();
        initialize(w, h, p, s);
        ignite();
      }
    
      public void initialize(int w, int h, PApplet p, String s) {
        setParent(p);
        setPrimary(false);
        setPath(s);
        setSize(w, h);
      }
    
      public void ignite() {
        beginDraw();
        smooth(8);
        fill(-1);
        stroke(0);
        endDraw();
      }
    
      protected PApplet getEnclosingPApplet() {
        try {
          return (PApplet) getClass()
            .getDeclaredField("this$0").get(this);
        }
        catch (ReflectiveOperationException cause) {
          throw new RuntimeException(cause);
        }
      }
    
      protected float getInGeometryArray(String s, InGeometry g)[] {
        final Field f;
    
        try {
          ( f = InGeometry.class.getDeclaredField(s) )
            .setAccessible(true);
        }
        catch (NoSuchFieldException cause) {
          throw new RuntimeException(cause);
        }
    
        try {
          return (float[]) f.get(g);
        }
        catch (IllegalAccessException cause) {
          throw new RuntimeException(cause);
        }
      }
    
      @ Override public void smooth() {
        super.smooth();
        lastSmoothCall = smoothCallCount = -0100;
      }
    
      @ Override public void noSmooth() {
        super.noSmooth();
        lastSmoothCall = smoothCallCount = -0100;
      }
    
      @ Override public String toString() {
        return "Width: " + width + "\t Height: " + height
          + "\nPath:  " + path;
      }
    }
    


    "P3D_Subclass.pde":

    /**
     * P3D Subclass (v1.1)
     * by GoToLoop (2014/Dec/04)
     *
     * forum.processing.org/two/discussion/8261/
     * how-to-use-vertexfloat-v-
     *
     * forum.processing.org/two/discussion/6884/
     * question-about-pgraphics
     */
    
    MyP3D pg;
    int w, h;
    
    void setup() {
      size(800, 600, P2D);
    
      frameRate(1);
      smooth(8);
      clear();
      imageMode(CORNER);
    
      println( pg = new MyP3D(width*3 >> 2, height*3 >> 2) );
      w = pg.width; 
      h = pg.height;
    
      pg.strokeWeight(3);
    }
    
    void draw() {
      final color c = (color) random(#000000);
    
      frame.setTitle("Frame: " + frameCount
        + "\t\tColor: #" + hex(c, 6));
    
      image(pg.script(c), width-w >> 1, height-h >> 1);
    }
    
    final class MyP3D extends HackedP3D {
      final float[] verts;
    
      MyP3D(int w, int h) {
        super(w, h);
        println( verts = getInGeometryArray("vertices", inGeo) );
      }
    
      MyP3D(int w, int h, PApplet p) {
        super(w, h, p);
        println( verts = getInGeometryArray("vertices", inGeo) );
      }
    
      MyP3D script(color c) {
        beginDraw();
        background(c);
    
        fill(~c | ALPHA_MASK);
        ellipse(width>>1, height>>1, random(width), random(height));
    
        fill(#FF0000);
        beginShape(TRIANGLES);
        vertex(0, 0, -50);
        vertex(100, 0, -50);
        vertex(0, 100, -50);
        endShape();
    
        endDraw();
        return this;
      }
    }
    
  • edited December 2014

    Oh my god !!! I didn't see that message !!!

    That's a very good news ! Thanks a lot ! I didn't do it yet, I had a lot of other stuff I could do before and I was tired of that problem. Big "Thank you" ! It's X-mas already ! :)

    Did you try to push some values in the vertices ? Does it work ?

  • Just by curiosity, in what project/lib/framework are you using a Layer class ?

  • edited December 2014

    ... in what project/lib/framework are you using a Layer class?

    None! Just made it as a reply solution to @karl_hungus, who never showed up again: b-(
    http://forum.processing.org/two/discussion/6884/question-about-pgraphics

    He wanted to know how to use PGraphics's methods w/o prepend an object reference w/ member accessor .!
    And this time I've adapted that code for PGraphics3D in order to "capture" that elusive field vertices[]! O:-)

    Did you try to push some values in the vertices? Does it work?

    Nope, not yet! Just used println() on it! But I'm pretty sure it's the big deal.
    It's a direct reference to InGeometry's vertices[], whose instance is held by PGraphicsOpenGL's inGeo field.
    As long vertices[] aren't assigned to another float[] array down the road, any modifications to its "captured" reference reflects directly on it! \m/

Sign In or Register to comment.