Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PShape doesn't allow attibutes of int type anymore #344

Closed
processing-bot opened this issue Jan 15, 2022 · 5 comments
Closed

PShape doesn't allow attibutes of int type anymore #344

processing-bot opened this issue Jan 15, 2022 · 5 comments
Labels

Comments

@processing-bot
Copy link
Collaborator

Created by: cacheflowe

As of Processing 4.0.b3, it seems that vertex attributes have changed a bit. And getTessellation() behavior has changed slightly.

One potential bug I'm seeing is an immediate crash if I've assigned an int value to an attrib and try to draw the shape. This crash is relieved if I cast the attribute value to a float like shape.attrib("x", (float) x);. It seems that int values should be allowed?

Full example to crash is here:

PShape shape;

void setup(){
  size(512, 512, P3D);
  shape = createShape(BOX, 100, 100, 100);
  shape.attrib("x", 1); // <- int attrib crashes when shape() is called!
}

void draw() {
  background(255,0,0);
  translate(256, 256);
  shape(shape);
}

Here's what the stack trace looks like in my local Eclipse setup:

java.lang.ClassCastException: class java.nio.DirectFloatBufferU cannot be cast to class java.nio.IntBuffer (java.nio.DirectFloatBufferU and java.nio.IntBuffer are in module java.base of loader 'bootstrap')
	at processing.opengl.PGraphicsOpenGL$TessGeometry.updateAttribBuffer(PGraphicsOpenGL.java:10486)
	at processing.opengl.PGraphicsOpenGL$TessGeometry.updateAttribBuffer(PGraphicsOpenGL.java:10475)
	at processing.opengl.PGraphicsOpenGL$TessGeometry.initPolyAttribsBuffer(PGraphicsOpenGL.java:9924)
	at processing.opengl.PShapeOpenGL.initPolyBuffers(PShapeOpenGL.java:4662)
	at processing.opengl.PShapeOpenGL.initBuffers(PShapeOpenGL.java:4601)
	at processing.opengl.PShapeOpenGL.updateGeometry(PShapeOpenGL.java:4764)
	at processing.opengl.PShapeOpenGL.draw(PShapeOpenGL.java:5252)
	at processing.core.PGraphics.shape(PGraphics.java:4134)
	at processing.core.PApplet.shape(PApplet.java:12344)
	at com.myapp.draw(Demo_PShapeAttribs.java:235)

Your Environment

  • Processing version: 4.0.b3
  • Operating System and OS version: Windows 11, JDK (Adoptium) 17.0.1.12-hotspot
  • Other information:

Possible Causes / Solutions

I see some of the code around tessellation and attributes has changed. As a side note, I don't seem to be able to run PShape.getTessellation() on an svg/obj PShape and then add attributes anymore. I used to call getTessellation() and then use shape.setAttrib("key", vertIndex, value);, but setAttrib() has been removed. This had previously seemed like the only way I could assign vertex attributes to svg/obj meshes. As of this new update I don't know if this is possible anymore - when I try to use shape.attrib() on an svg/obj PShape, I get the following error, which seems to have something to do with inGeo being null. It does look like the latest core updates have changed some code in this area:

java.lang.NullPointerException: Cannot invoke "processing.opengl.PGraphicsOpenGL$InGeometry.initAttrib(processing.opengl.PGraphicsOpenGL$VertexAttribute)" because "this.inGeo" is null
	at processing.opengl.PShapeOpenGL.attribImpl(PShapeOpenGL.java:1187)
	at processing.opengl.PShapeOpenGL.attrib(PShapeOpenGL.java:1159)
	at com.myapp.draw(Demo_PShapeAttribs.java:167)

I hardly know anything about the inner workings here, but it would be cool to be able to add attributes to geometry that was loaded from an svg/obj again :-D

As another clue as to what's happening here, I can add attributes to a PShape just fine if it was created like so: createShape(BOX, 100, 100, 100);. However, an additional potentially new behavior there is an error if I try to call getTessellation() on that type of shape:

java.lang.ArrayIndexOutOfBoundsException: Index -2 out of bounds for length 48
	at processing.opengl.PShapeOpenGL.scaleTextureUV(PShapeOpenGL.java:843)
	at processing.opengl.PShapeOpenGL.setTextureImpl(PShapeOpenGL.java:807)
	at processing.opengl.PShapeOpenGL.setTexture(PShapeOpenGL.java:786)
	at com.haxademic.demo.draw.shapes.shader.Demo_VertexShader_GPUParticlesMoveShapes.firstFrame(Demo_VertexShader_GPUParticlesMoveShapes.java:156)

Thank you core contributors for your work here. Obviously Ben and Andres have made heroic updates in recent weeks/months 🙏

@processing-bot
Copy link
Collaborator Author

Created by: benfry

Thanks for the thorough report—I've tagged Andrés so he can weigh in as well.

@processing-bot
Copy link
Collaborator Author

Created by: codeanticode

Thanks for tagging me on this issue, most likely a regression after the updates in the PShape code, I will look at it asap.

@processing-bot
Copy link
Collaborator Author

Created by: codeanticode

@cacheflowe The cast error is fixed with this PR

About why the setAttrib() methods are no longer accessible, the reason is discussed in the thread of issue #235. As part of the API updates you mentioned, I implemented the rest of all the setAttrib*() methods. However, we decided to keep all of this new API out of PShape, so you need to cast the result of getTessellation() as PShapeOpenGL in order to access all the setAttrib*() methods.

Another important change to be noted is that getTessellation() now returns the stroked geometry (points and lines) as separate child shapes, if present in the original shape. So, if the original shape does not contain strokes, the returned PShape is a GEOMETRY PShapeOpenGL that you can manipulate directly. If lines or points are present in the original shape, then the returned PShape is a GROUP, with the first child the actually fill geometry, the second is the lines, and the third, the points. The following code demonstrates this:

PShape shape;
PShapeOpenGL tess = null;

void setup() {
  size(512, 512, P3D);
  shape = createShape(BOX, 100, 100, 100);
  shape.attrib("x", 1);
}

void draw() {
  background(180);
  lights();

  translate(width/2, height/2);
  rotateX(frameCount * 0.01f);
  rotateY(frameCount * 0.02f);

  if (tess == null) {
    shape(shape);
  } else {
    PShapeOpenGL fillGeo = (PShapeOpenGL)tess.getChild(0);
    for (int i = 0; i < fillGeo.getVertexCount(); i++) {
      fillGeo.setAttrib("x", i, random(1));
    }
    shape(fillGeo);

    PShapeOpenGL lineGeo = (PShapeOpenGL)tess.getChild(1);
    shape(lineGeo);
  }
}

void keyPressed() {
  tess = (PShapeOpenGL)shape.getTessellation();
  println(tess.getVertexCount());
}

I think the next step is to properly document the advanced PShape API :-)

@processing-bot
Copy link
Collaborator Author

Created by: benfry

#363 now incorporated for 4.0 beta 4.

@processing-bot
Copy link
Collaborator Author

Created by: github-actions[bot]

This issue has been automatically locked. To avoid confusion with reports that have already been resolved, closed issues are automatically locked 30 days after the last comment. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

1 participant