I need to draw a cube in processing without the use of built-in functions. All I could find was using the box() function then rotating the image to see it in 3D.
How can I achieve this?
An alternative is using createShape(BOX)
instead:
PShape cube;
void setup(){
size(600, 600, P3D);
strokeWeight(9);
cube = createShape(BOX, 150);
}
void draw(){
background(255);
lights();
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
shape(cube);
}
If this is for a homework/assignment it might not be enough (and you should state that in the question, and you should also post a code snippet of your attempt with a description of what didn't work). You'll need to draw the box from scratch. One easy way to think about is to draw the 8 cube vertices on pen and paper with 0,0,0 at the centre, then keeping in mind where -x/+x, -y/+y, -z/+z axes point, mark each vertex, for example:
( x, y, z)
(-1,-1,-1)
(+1,-1,-1)
(+1,+1,-1)
(-1,+1,-1)
should be the back face. Repeat the process for the rest of the faces.
In Processing you'd use beginShape(QUADS)
since you're drawing a cube and it's faces are quads, vertex(x, y, z)
to specify each point/vertex and finally endShape()
to complete the shape (and "join the dots"):
void setup(){
size(600, 600, P3D);
strokeWeight(9);
}
void draw(){
background(255);
lights();
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
cubeFaces(150);
}
void cubeFaces(float size){
// half size: keep the pivot at the center of the mesh
float s = size * 0.5;
beginShape(QUADS);
// back (-z)
vertex(-s, -s, -s);
vertex(+s, -s, -s);
vertex(+s, +s, -s);
vertex(-s, +s, -s);
// front (+z)
vertex(-s, -s, +s);
vertex(+s, -s, +s);
vertex(+s, +s, +s);
vertex(-s, +s, +s);
// top (-y)
vertex(-s, -s, +s);
vertex(-s, -s, -s);
vertex(+s, -s, -s);
vertex(+s, -s, +s);
// bottom (+y)
vertex(+s, +s, +s);
vertex(+s, +s, -s);
vertex(-s, +s, -s);
vertex(-s, +s, +s);
// left (-x)
vertex(-s, -s, +s);
vertex(-s, -s, -s);
vertex(-s, +s, -s);
vertex(-s, +s, +s);
// right (+x)
vertex(+s, -s, +s);
vertex(+s, -s, -s);
vertex(+s, +s, -s);
vertex(+s, +s, +s);
endShape();
}
PShape
is useful because you can cache the geometry using a very similar beginShape()
/ endShape()
, but rather than recreating the shape every frame you can simply render the predefined geometry:
PShape cube;
void setup(){
size(600, 600, P3D);
strokeWeight(9);
cube = getCube(150);
}
void draw(){
background(255);
lights();
translate(width * 0.5, height * 0.5, 0);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));
shape(cube);
}
void cubeFaces(float size){
// half size: keep the pivot at the center of the mesh
float s = size * 0.5;
beginShape(QUADS);
// back (-z)
vertex(-s, -s, -s);
vertex(+s, -s, -s);
vertex(+s, +s, -s);
vertex(-s, +s, -s);
// front (+z)
vertex(-s, -s, +s);
vertex(+s, -s, +s);
vertex(+s, +s, +s);
vertex(-s, +s, +s);
// top (-y)
vertex(-s, -s, +s);
vertex(-s, -s, -s);
vertex(+s, -s, -s);
vertex(+s, -s, +s);
// bottom (+y)
vertex(+s, +s, +s);
vertex(+s, +s, -s);
vertex(-s, +s, -s);
vertex(-s, +s, +s);
// left (-x)
vertex(-s, -s, +s);
vertex(-s, -s, -s);
vertex(-s, +s, -s);
vertex(-s, +s, +s);
// right (+x)
vertex(+s, -s, +s);
vertex(+s, -s, -s);
vertex(+s, +s, -s);
vertex(+s, +s, +s);
endShape();
}
PShape getCube(float size){
PShape cube = createShape();
// half size: keep the pivot at the center of the mesh
float s = size * 0.5;
cube.beginShape(QUADS);
// back (-z)
cube.vertex(-s, -s, -s);
cube.vertex(+s, -s, -s);
cube.vertex(+s, +s, -s);
cube.vertex(-s, +s, -s);
// front (+z)
cube.vertex(-s, -s, +s);
cube.vertex(+s, -s, +s);
cube.vertex(+s, +s, +s);
cube.vertex(-s, +s, +s);
// top (-y)
cube.vertex(-s, -s, +s);
cube.vertex(-s, -s, -s);
cube.vertex(+s, -s, -s);
cube.vertex(+s, -s, +s);
// bottom (+y)
cube.vertex(+s, +s, +s);
cube.vertex(+s, +s, -s);
cube.vertex(-s, +s, -s);
cube.vertex(-s, +s, +s);
// left (-x)
cube.vertex(-s, -s, +s);
cube.vertex(-s, -s, -s);
cube.vertex(-s, +s, -s);
cube.vertex(-s, +s, +s);
// right (+x)
cube.vertex(+s, -s, +s);
cube.vertex(+s, -s, -s);
cube.vertex(+s, +s, -s);
cube.vertex(+s, +s, +s);
cube.endShape();
return cube;
}
Bonus points, there's yet another way you can draw a cube: as a special case of a cylinder with 4 subdivions where the radius is half the height. Processing ships with an example you can tweak in Processing > Examples > Topics > Geometry > Vertices .
Here's a modified version of the example rendering a cube:
/**
* Vertices
* by Simon Greenwold.
*
* Draw a cylinder centered on the y-axis, going down
* from y=0 to y=height. The radius at the top can be
* different from the radius at the bottom, and the
* number of sides drawn is variable.
*/
void setup() {
size(640, 360, P3D);
}
void draw() {
background(0);
lights();
translate(width / 2, height / 2);
rotateY(map(mouseX, 0, width, 0, PI));
rotateZ(map(mouseY, 0, height, 0, -PI));
noStroke();
fill(255, 255, 255);
translate(0, -40, 0);
//drawCylinder(10, 180, 200, 16); // Draw a mix between a cylinder and a cone
//drawCylinder(70, 70, 120, 64); // Draw a cylinder
//drawCylinder(0, 180, 200, 4); // Draw a pyramid
// Draw a cube
drawCylinder(50, 50, 75, 4);
}
void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) {
float angle = 0;
float angleIncrement = TWO_PI / sides;
beginShape(QUAD_STRIP);
for (int i = 0; i < sides + 1; ++i) {
vertex(topRadius*cos(angle), 0, topRadius*sin(angle));
vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle));
angle += angleIncrement;
}
endShape();
// If it is not a cone, draw the circular top cap
if (topRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, 0, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(topRadius * cos(angle), 0, topRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
// If it is not a cone, draw the circular bottom cap
if (bottomRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, tall, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
}
(You can find my explanation of the polar to cartesian formula used above in this answer )
The above is very similar to the old school OpenGL immediate mode drawing. If this is for a more recent CS oriented course for OpenGL one, you might need to use PGL and a vertex array buffer, slightly different calls. The Cube OpenGL Tutorial cover that nicely. Even though it's c++, you'll recognize functions such as genBuffers()
, glBindBuffer()
, glBufferData()
in Processing's PGL
class ( Processing > Examples > Demos > Graphics > LowLevelGL * examples are great starting points and align nicely with the triangle OpenGL tutorial )
Update:
There's yet another example that can easily be tweaked to draw a cube: Processing > Examples > Demos > Graphics > Wiggling .
Here's a tweaked version that draws the cube without the wiggling nor the holes in the faces:
PShape cube;
float cubeSize = 320;
void setup() {
size(1024, 768, P3D);
createCube();
}
void draw() {
background(0);
translate(width/2, height/2);
rotateX(frameCount * 0.01f);
rotateY(frameCount * 0.01f);
shape(cube);
if (frameCount % 60 == 0) println(frameRate);
}
public void keyPressed() {
if (key == '1') {
cube.setStrokeWeight(1);
} else if (key == '2') {
cube.setStrokeWeight(5);
} else if (key == '3') {
cube.setStrokeWeight(10);
}
}
void createCube() {
cube = createShape(GROUP);
PShape face;
// Create all faces at front position
for (int i = 0; i < 6; i++) {
face = createShape();
createFace(face);
cube.addChild(face);
}
// Rotate all the faces to their positions
// Front face - already correct
face = cube.getChild(0);
// Back face
face = cube.getChild(1);
face.rotateY(radians(180));
// Right face
face = cube.getChild(2);
face.rotateY(radians(90));
// Left face
face = cube.getChild(3);
face.rotateY(radians(-90));
// Top face
face = cube.getChild(4);
face.rotateX(radians(90));
// Bottom face
face = cube.getChild(5);
face.rotateX(radians(-90));
}
void createFace(PShape face) {
face.beginShape(POLYGON);
face.stroke(255, 0, 0);
face.fill(255);
// Draw main shape Clockwise
face.vertex(-cubeSize/2, -cubeSize/2, +cubeSize/2);
face.vertex(+cubeSize/2, -cubeSize/2, +cubeSize/2);
face.vertex(+cubeSize/2, +cubeSize/2, +cubeSize/2);
face.vertex(-cubeSize / 2, +cubeSize / 2, +cubeSize / 2);
face.endShape(CLOSE);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.