Cube with rounded edges

Hi there! I am working on a mobile quizapp based on rotating a cube. I am currently using this code for drawing a cube:

  beginShape(QUADS);
  texture(front);
  vertex(-1, -1,  1, 0, 0);
  vertex( 1, -1,  1, 1, 0);
  vertex( 1,  1,  1, 1, 1);
  vertex(-1,  1,  1, 0, 1);
  endShape();
  beginShape(QUADS);
  vertex( 1, -1, -1, 0, 0);
  vertex(-1, -1, -1, 1, 0);
  vertex(-1,  1, -1, 1, 1);
  vertex( 1,  1, -1, 0, 1);
  endShape();
  beginShape(QUADS);
  texture(any);
  vertex(-1,  1,  1, 0, 0);
  vertex( 1,  1,  1, 1, 0);
  vertex( 1,  1, -1, 1, 1);
  vertex(-1,  1, -1, 0, 1);
  endShape();
  beginShape(QUADS);
  texture(any);
  vertex(-1, -1, -1, 0, 0);
  vertex( 1, -1, -1, 1, 0);
  vertex( 1, -1,  1, 1, 1);
  vertex(-1, -1,  1, 0, 1);
  endShape();
  beginShape(QUADS);
  texture(any);
  vertex( 1, -1,  1, 0, 0);
  vertex( 1, -1, -1, 1, 0);
  vertex( 1,  1, -1, 1, 1);
  vertex( 1,  1,  1, 0, 1);
  endShape();
  beginShape(QUADS);
  texture(any);
  vertex(-1, -1, -1, 0, 0);
  vertex(-1, -1,  1, 1, 0);
  vertex(-1,  1,  1, 1, 1);
  vertex(-1,  1, -1, 0, 1);
  endShape();

Now I want the cube to look more dynamic. To achieve that, I am trying to round the cube’s edges like in this 3D Model: https://1drv.ms/u/s!AlgOmiL5mgw21lWz_pmcUoAcVRY0?e=blu6u0. Can anyone show me how I can do that? I am not really good with shapes.

Hello,

You could use Blender to create a cube and bevel the edges the way you want. Then you could export the cube with the .OBJ format and use the loadShape() function to import it into your project.

Thanks for the advise, but I already tried that without sucess. I can load the shape, but it behaves weird. It rotates around some weird axes and completely loses it’s form on rotation.

here is my way…

Unbenannt

first we take a sphere, then we cut out another smaller sphere from its center .

This leaves a hollow sphere.

Now we take the cube and minus the hollow sphere.

When all sizes are chosen correctly, the hollow sphere just cuts off the edges of the cube.

  // This is where the magic happens
  csgResult = roundedCube();

Chrisir


//https://stackoverflow.com/questions/56999816/is-it-possible-to-use-jcsg-library-with-processing
//https://discourse.processing.org/t/csg-constructive-solid-geometry/12693

// the PShape reference which will contain the converted CSG 
PShape csgResult;

void setup() {
  size(900, 900, P3D);
  // This is where the magic happens
  csgResult = roundedCube(); 
  println("Use mouse to rotate.");
}

void draw() {
  background(0);
  lights();
  translate(width * 0.5, height * 0.5, 0);
  rotateY(map(mouseX, 0, width, -PI, PI));
  rotateX(map(mouseY, 0, height, PI, -PI));

  shape(csgResult);
}

//-----------------------------------------------------------------------------

PShape roundedCube() {

  PShape csgResult;

  noStroke();

  // JCSG sample code:
  // we use cube and sphere as base geometries
  CSG cube = new Cube(2.78).toCSG();

  CSG sphere1 = new Sphere(3).toCSG();         // outer sphere 
  CSG sphere2 = new Sphere(2.0941, 39, 39).toCSG();    // inner sphere - the smaller this is, the more we cut off from the cube! 
  //CSG sphere2 = new Sphere(1.80941).toCSG(); // the smaller this is, the more we cut off from the cube! 

  // perform difference: this gives a hollow sphere  
  CSG sphere3 = sphere1.difference(sphere2);

  // perform difference again: this gives a cube with rounded edges 
  CSG cubeMinusSphere = cube.difference(sphere3);
  //  cubeMinusSphere = sphere.difference(cube);

  // Convert CSG to PShape -> Note: CSG units are small so we scale them up so the shapes are visible in Processing
  csgResult = CSGToPShape(cubeMinusSphere, 45);

  return csgResult;
} //func 

// re-usable function to convert a CSG mesh to a Processing PShape
PShape CSGToPShape(CSG mesh, float scale) {
  // allocate a PShape group
  PShape csgResult = createShape(GROUP);
  // for each CSG polygon (Note: these can have 3,4 or more vertices)
  for (Polygon p : mesh.getPolygons()) {
    // make a child PShape
    PShape polyShape = createShape();
    // begin setting vertices to it
    polyShape.beginShape();
    polyShape.fill(255, 0, 0); 
    // for each vertex in the polygon
    for (Vertex v : p.vertices) {
      // add each (scaled) polygon vertex 
      polyShape.vertex((float)v.pos.getX() * scale, (float)v.pos.getY() * scale, (float)v.pos.getZ() * scale);
    }
    // finish this polygon
    polyShape.endShape();
    //append the child PShape to the parent
    csgResult.addChild(polyShape);
  }
  return csgResult;
}
//

Thanks for the attempt, but fortunately I was able to get loading the 3d model working.

But there still is a big problem:


PShape cubeShape;
PShape secondaryShape;
PImage cubeImage;
PImage blank;
float rotationX;
float rotationY;
float sX, sY;
int childs;
PFont questionFont, optionFont;

void setup(){
  frameRate(60);
  orientation(PORTRAIT);
  fullScreen(P3D);
  shapeMode(CORNER);
  textAlign(CORNER);
  smooth(5);
  cubeShape = loadShape("Abc.obj");
  cubeShape.setFill(color(255));
  cubeShape.setTint(color(255));
  secondaryShape = loadShape("Abc.obj");
  secondaryShape.setFill(color(255));
  secondaryShape.setTint(color(255,255,255));
  cubeImage = loadImage("cubesite_front.PNG");
  childs = cubeShape.getChildCount();
  questionFont = createFont("cube.ttf",7); 
  optionFont = createFont("cube.ttf", 85);
  textureWrap(REPEAT);
  textureMode(IMAGE);
  secondaryShape.setTexture(loadImage("cubesite_any.png"));
  rotationX = 0.0f;
  rotationY = 0.0f;
  editSite(cubeImage, "Test", "Left", "Top", "Right", "Bottom");
  cubeImage = getMirror(cubeImage);
}

void draw(){
  cubeShape.setTexture(cubeImage);
  Runtime runtime = Runtime.getRuntime();
  float usedRam = 1.0f - (float) runtime.freeMemory() / (float) runtime.totalMemory();
  int usedRamPercent = (int) (usedRam*100.0f);
  background(255);
  lights();
  textSize(width/20);
  fill(0,125,255);
  text("Rotation X: " + String.valueOf(degrees(rotationX)).split("\\.")[0]+"°\n"+"Rotation Y: " + String.valueOf(degrees(rotationY)).split("\\.")[0]+"°",width/20,height/20);
  String rightBar = "Touch X: " + String.valueOf(sX) + "\nTouch Y: " + String.valueOf(sY) 
  + "\n\nRAM: " + usedRamPercent + "%"
  + "\nFPS: " + String.valueOf(frameRate).split("\\.")[0];
  text(rightBar,width-width/20-textWidth(rightBar),height/20); 
  textSize(width/20);
  fill(125,25,0);
  text("",width/2,height/7);
  if (rotationX>=TWO_PI||rotationX<=-TWO_PI) rotationX=0;
  if (rotationY>=TWO_PI||rotationY<=-TWO_PI) rotationY=0;
  for (int i = 0; i <childs; i++){
    PShape currentChild = cubeShape.getChild(i); 
    PShape secondaryChild = secondaryShape.getChild(i);
    boolean front = true;
    for (int j = 0; j < currentChild.getVertexCount(); j++){
      PVector currentVector = currentChild.getVertex(j);
      front = !(currentVector.z<0.95);
    }
    pushMatrix();
    translate(width/2,height/2,height/6);
    scale(height/7);
    rotateX(rotationX);
    rotateY(rotationY);
    shape(front ? currentChild : secondaryChild);
    popMatrix();
  }
}
 

PImage getMirror(PImage img) {
  PGraphics pg = createGraphics(img.width, img.height, JAVA2D);
  pg.beginDraw();
  pg.smooth(4);
  pg.scale(-1, 1);
  pg.image(img, -img.width, 0);
  pg.endDraw();
  return pg.get();
}

private void editSite(PImage background, String center, String left, String top, String right, String bottom){ 
  PGraphics siteGraphics = createGraphics(background.width,background.height); 
  imageMode(CORNER); 
  siteGraphics.beginDraw(); 
  siteGraphics.image(background,0,0); 
  siteGraphics.textSize(width/10); 
  fittedText(siteGraphics,center,questionFont,siteGraphics.width/2,siteGraphics.height/2,siteGraphics.width-siteGraphics.width/6,siteGraphics.height-siteGraphics.height/6); 
  siteGraphics.pushMatrix(); 
  siteGraphics.translate(0,0);
  siteGraphics.rotate(-HALF_PI); 
  siteGraphics.textAlign(CENTER, CENTER); 
  siteGraphics.textFont(optionFont); 
  siteGraphics.text(left,-siteGraphics.height/2,siteGraphics.width/6/2); 
  siteGraphics.rotate(PI); 
  siteGraphics.text(right,siteGraphics.height/2,-siteGraphics.width+siteGraphics.width/6/2); 
  siteGraphics.rotate(-HALF_PI); 
  siteGraphics.text(top,siteGraphics.width/2,siteGraphics.height/6/2); 
  siteGraphics.text(bottom,siteGraphics.width/2,siteGraphics.height-siteGraphics.height/6/2); siteGraphics.popMatrix(); 
  siteGraphics.endDraw(); 
  cubeImage = siteGraphics.get(); 
}


private final char NEWLINE = '\n'; private final String SPACE_SEPARATOR = " "; private final String SPLIT_REGEXP= "\\s+"; String breakLines(String input, int maxLineLength) { String[] tokens = input.split(SPLIT_REGEXP); StringBuilder output = new StringBuilder(input.length()); int lineLen = 0; for (int i = 0; i < tokens.length; i++) { String word = tokens[i]; if (lineLen + (SPACE_SEPARATOR + word).length() > maxLineLength) { if (i > 0) output.append(NEWLINE); lineLen = 0; } if (i < tokens.length - 1 && (lineLen + (word + SPACE_SEPARATOR).length() + tokens[i + 1].length() <=maxLineLength)) word += SPACE_SEPARATOR; output.append(word); lineLen += word.length(); } return output.toString();}
void fittedText(PGraphics graphics,String text, PFont font, float posX, float posY, float fitX, float fitY){ 
  text = breakLines(text, 15); 
  graphics.textFont(font); 
  graphics.textAlign(CENTER,CENTER); 
  graphics.textSize(min(font.getSize()*fitX/textWidth(text), fitY)); 
  graphics.textLeading(graphics.textSize*1.1); 
  graphics.text(text, posX, posY);
}


void mousePressed(){
  sX = mouseX;
  sY = mouseY;
}
void mouseDragged(){
  rotationX += (mouseY-sY)*(HALF_PI/(width));
  sY = mouseY;
  rotationY += (mouseX-sX)*(HALF_PI/(width));
  sX = mouseX;
}

The above demo code functions perfectly when run via APDE, but the texture is just one solid ugly color when build/run from a windows machine via PDE or Android Studio:

Do(es) you/anyone know(s) why this is happening and how I can fix it?

If needed I will upload the model as well if it is relevant!

I have no idea…

Chrisir

That’s a shame… I can’t understand why this is happening either. What is APDE doing differently?