[PShapes] child SVG elements misplaced in P3D

edited October 2016 in Questions about Code

hi guys

i'm having an issue with an SVG file with a few childs. it works absolutely fine with normal render, but it gets all misplaced in 3D, and i need 3D to send processing to modul8 via syphon.

it's a cockroach, so i'm animating the legs and the antennas. i'm quite sure the bug(no pun intended) is within the svg file. i started it using illustrator, but illustrator cc2015 sucks producing svgcode, so i used inkscape.

here is the SVG http://eduzal.com/downloads/barata.svg

the svg file is long and the forum didn't allow me to publish it here.

Tagged:

Answers

  • @eduzal when you say it "gets misplaced in 3D," what is happening? Can you share brief sketch (MCVE) to demonstrate the problem when you load this svg?

  • edited October 2016

    hi @jeremydouglass

    i have this roach. i created different layers for each part(body, two antennas, six legs). each one is a child. when i load it with P2D the positions are fine, when loading in P3D, the body is alright and but the legs and the antennas are misplaced. each appendix is a group that has the vertex in itself and an placeholder object for pivoting.

    below goes the roach object, with the appendices animation

    class Barata {
      PShape barata;
      PShape b, aD, aE;
      PShape RFL, RML, RBL, LFL, LML, LBL;
      float roff=0.0;
      float rinc=0.01;
      float scFactor=.5;
      PVector pos;
      PVector velocity;
      PVector acceleration;
    
      Barata(PVector _pos) {
        acceleration=new PVector(0, -0.1);
        velocity=new PVector(random(-2, 2), random(-2, 0));
        pos=_pos.get();
        lifespan=200;
        init();
      }
    
      void init() {
    
        barata=loadShape("barata.svg");
        barata.disableStyle();
        barata.scale(scFactor);
        b=barata.getChild("body");
        aE=barata.getChild("antennaE");
        aD=barata.getChild("antennaD");
        RFL=barata.getChild("rightFrontLeg");
        RML=barata.getChild("rightMidLeg");
        RBL=barata.getChild("rightBackLeg");
        LFL=barata.getChild("leftFrontLeg");
        LML=barata.getChild("leftMidLeg");
        LBL=barata.getChild("leftBackLeg");
    
        b.scale(scFactor);
        aE.scale(scFactor);
        aD.scale(scFactor);
        RFL.scale(scFactor);
        RML.scale(scFactor);
        RBL.scale(scFactor);
        LFL.scale(scFactor);
        LML.scale(scFactor);
        LBL.scale(scFactor);
      }
    
      void run() {
        update();
        animate();
        display();
      }
    
      void update() {
        velocity.add(acceleration);
        pos.add(velocity);
        acceleration.mult(0);
      }
    
      void animate() {
        float nAD=random(-1,1);
        float nAE=random(-1,1);
        //float nAD=noise(roff)*5;
        //float nAE=noise(roff)*5;
        nAE=constrain(nAE, -25, 25);
        nAD=constrain(nAE, -25, 25);
        //float n=noise(roff)*10;
        float n=20;
        float rRight=sin(frameCount)*n;
        float rLeft=cos(frameCount)*n;
        println(rRight,rLeft);
        childMove(aD, "pivotAD", nAD);
        childMove(aE, "pivotAE", nAE);
        childMove(RFL, "pivotRFL", rRight);
        childMove(RML, "pivotRML", rRight);
        childMove(RBL, "pivotRBL", rRight);
        childMove(LFL, "pivotLFL", rLeft);
        childMove(LML, "pivotLML", rLeft);
        childMove(LBL, "pivotLBL", rLeft);
        roff-=rinc;
      }
    
      void childMove(PShape s, String pivot, float a) {
        float[] p=s.getChild(pivot).getParams();
        float px=p[0];
        float py=p[1];
        float pw=p[2];
        float ph=p[3];
    
        s.translate(px, py);
        s.rotate(radians(a));
        s.translate(-px, -py);
      }
    
    
      void intersects(ArrayList<Barata> baratas) {
        for (Barata other : baratas) {
          if (other != this) {
            PVector dir = PVector.sub(pos, other.pos);
            if (dir.mag() < barata.width/4) {
              dir.setMag(0.5); 
              applyForce(dir);
            }
          }
        }
      }
    
      void applyForce(PVector f) {
        acceleration.add(f);
      }
    
      void display() {
        noStroke();
        fill(200);
        pushMatrix();
        translate(pos.x, pos.y);
        shape(b, 0, 0);
        shape(aE, 0, 0);
        shape(aD, 0, 0);
        shape(RFL, 0, 0);
        shape(RML, 0, 0);
        shape(RBL, 0, 0);
        shape(LFL, 0, 0);
        shape(LML, 0, 0);
        shape(LBL, 0, 0);
        popMatrix();
      }
    
      boolean isDead() {
        if (pos.x<0 || pos.x>width+barata.width/2 || pos.y<0) {
          return true;
        } else {
          return false;
        }
      }
    }
    
  • edited October 2016

    @jeremydouglass P2D P3D

  • edited October 2016

    @eduzal -- Your error appears to be in some complex movement code -- if I had to guess, my first guess would be cumulative translations that shouldn't be cumulative.

    Your class works just fine in the default, P2D, and P3D renderers with a minimal example -- see below, and try any of the example size commands.

    Barata b;
    int lifespan;
    
    void setup(){
      size(400,400);
      // size(400,400,P2D);
      // size(400,400,P3D);
      b = new Barata(new PVector(width/2, height/2));
    }
    void draw(){
      background(0);
      b.display();
    }
    

    The roach looks just fine in all 3 renderers.

    Rather than sharing screenshots, try breaking your problem down to a minimum complete example that demonstrates the problem in sketch in a way that others can run. Then, if you can't debug it yourself, share that example here and ask for help!

    Also -- it might be helpful to explain why are you trying to use the P3D renderer for these flat SVG components at all -- what is the goal?

  • edited October 2016

    @jeremydouglass

    i put the roaches within a particle system.

    ParticleSystem ps;
    
    void setup() {
      size(1024, 768);
      shapeMode(CENTER);
    
      PVector p=new PVector(width/2, height/2);
      ps=new ParticleSystem(p);
    }
    
    void draw() {
    
    background(10); 
      if (frameCount%10==0) { 
        ps.addBarata();
      }
      ps.intersection();
      ps.run();
    }
    
    class ParticleSystem {
      ArrayList<Barata> baratas;
      PVector origin;
    
      ParticleSystem(PVector location) {
        origin=location;
        baratas=new ArrayList<Barata>();
      }
    
      void addBarata() {
        int x=int(random(width));
        PVector p=new PVector(x, height+100);
        baratas.add(new Barata(p));
      }
    
      void intersection() {
        for (Barata b : baratas) {
          b.intersects(baratas);
        }
      }
    
      void applyForce(PVector f) {
        for (Barata b : baratas) {
          b.applyForce(f);
        }
      }
    
      void run() {
        for (int i=baratas.size ()-1; i>=0; i--) {
          Barata b=baratas.get(i);
          b.run();
          if (b.isDead()) {
            baratas.remove(i);
          }
        }
      }
    }
    
  • like i said, i need to use it with P3D to send it through syphon to modul8. this is just one of a lot of video pieces that will be on a play.

  • and yes, the issue lies in two possible places, in the pivot point of the animation or int the code of the svg.

  • edited October 2016

    @edzul -- your error / bug appears in the call to Barata.animate(), and probably has to do with cumulative translation in Barata.childMove(). The error does not happen in the default JAVA2D renderer but does happen in both P2D and in P3D.

    It might be an error in your code, and /or it could be an error in Processing having inconsistent ways in which PShape accumulates translations across children. Perhaps s.applyMatrix() or s.resetMatrix() might help.

    Don't debug your class with a particle system. Debug a simple, minimal sketch that uses your class, like this:

    Barata b;
    int lifespan;
    void setup(){
      // size(400,400); //// works
      size(400,400,P2D); //// broken
      // size(400,400,P3D); //// broken
      b = new Barata(new PVector(width/2, height/2));
      frameRate(6);
    }
    void draw(){
      background(0);
      b.animate();
      b.display();
    }
    
  • edited October 2016

    exactly the point @jeremydouglass.

    the bug lies in the render engine. it misplaces the pivot/insertion points of each svg child and makes a mess where there should be none. the question is how to make it work. i'm not that intimate with these methods applyMatrix() and resetMatrix().

    checking to see what these methods are about. they are not that well documented.

  • edited October 2016

    Yep, cumulative translation error.

    Try commenting out all childMove() calls in animate() except "aD" -- the antenna stays anchored correctly.

    childMove(aD, "pivotAD", nAD);
    

    Now leave in two childMove() calls -- aD and AE. The antenna both begin to drift together along their x=y axis.

    childMove(aD, "pivotAD", nAD);
    childMove(aE, "pivotAE", nAE);
    

    This does look like it is probably a bug in Processing to me, with JAVA2D having the correct behavior (child matrix transforms are independent) and P2D / P3D having the wrong behavior (dependent).

    Your "s.translate" effects are passed on to subsequent children rather than being reset. There is no PShape.pushMatrix() / PShape.popMatrix(), but one workaround might be to refactor your childMove to call its own display with a displayChild function rather than doing one batch display at the end -- so childMove(), displayChild(), resetMatrix(), next childMove(), displayChild(), resetMatrix()....

  • for some exoteric reason these renderers displace the insertion points and the matrixes transformations. still trying to figure out some non brute force answer to this issue. i'm still massaging the variables within childMove() to figure out what is going on.

  • I experienced a similar issue with PShape transformations:

    https://github.com/processing/processing/issues/4662

  • @eduzal I wonder if the getVertexCount() workaround described in the @T_D mentioned would work for you.

  • hi @ jeremydouglass i'm figuring out how to try that solution with all my children

  • Of historical interest: there was a fix for issue 4662 above released in more recent versions of Processing: pre-apply PShape transformation, fixes #4662.

Sign In or Register to comment.