 # Beginning (3D) superprogrammer (57 years)

I have been a programmer for 57 years. Therefore, I find the introductory tutorials uninteresting. I have a very focused set of questions.

• I need to draw lines in 3D space. Just lines. No extrusions. Practically no surface rendering.

• I need to “walk around” my 3D line drawing. I want to use the mouse to rotate it in all three axes, alternatively, I want to be able to change the camera origin and axis. I do not want to deal with deep theory. I want to say, “Take the drawing I have just done and let me see it from various angles as determined by the mouse interaction”. I want 3D transformations without reading a thick book on quaternions (which I have).

• I will need to show an animation of lines being drawn, and when a surface is defined (a definite condition I know of) issue a set of calls that fill in the flat space, and even move it into a window of “known sides”, which may or may not have to be assembled into a solid.

• I will need to run this animation forwards and backwards, e.g., by using the scroll wheel. Or something. I have been writing GUIs for 30 years, and taught courses in GUI-based 2D graphics. I was doing 2D graphics long before I had GUI-based systems to run them on (no, you don’t want the long story of how to do 2D graphics on a character-based terminal).

• I will need to mark one end of the first line with a solid circle, and then draw the lines from point A to point B with an arrowhead at the end of the line

• A line is first drawn as a dotted line. Then, once its validity is established, it becomes a solid line. When two lines are successfully accepted, I want to create a transparent plane to show the plane on which the two lines lie, such that I can see other lines drawn behind the plane.

• This can be standalone, and I will be providing a text file that tells what to do, e.g., “line x0 y0 z0 x1 y1 z1” and have my program draw the line (note that parsing this command line to extract the data is something I could do while sleeping soundly, so don’t worry about how I get the values out of it).

• I will be using Java, and ideally this will later be incorporated into a Java app that already is generating the lines.

• I would like to go from zero to seeing the line drawing in 3D, with rotation, in less than a day.

I have been doing 2D graphics for something over 40 years, I can do 2D transformation matrices without slowing down, about as fast as I can type. I have taught courses in 2D graphics, and I have delivered 2D graphics products to my clients (I’m now retired, and doing this for fun). I do not want to have to learn a lot of boilerplate code to get this up and running. Assume that for the first day, I type in the calls that draw the lines. Assume that I could have my program that is creating the lines write the source code, in Java, to make the library calls to do the drawing, thus eliminating the parsing component entirely.

I need a simple example framework for doing this, because it is just a diversion in a much more complex project and I can’t afford too much of a diversion right now.

Once I have the framework, I can reverse-engineer it to figure out what I need to do to enhance it. That’s the easy part. Getting the framework, at the moment, is the hard part.

Programming does not intimidate me. Building a 3D framework from the ground up would not intimidate me if I had more time to give to the process, but I don’t. I need it now. OK, I realize this is “instant gratification”. But it is all I have time to give to it in the next week or two.

Also, for “free and open”, it seems to insist on a donation before I can download it. Perhaps I have misunderstood the word “free”. If it is useful, and solves my problem, I will happily make a donation. But I’m not going to donate if I can’t give it a free test drive to know if it is what I need.

So how do I get started? What’s the best “sample app” to start with?

2 Likes

Hey, and welcome to the processing forum!

Great to have you here!

• Also decide whether you go for processing p5.js (javascript I think), python processing or Java processing

code examples in Java processing

I just give you a few code examples to work from.

Parsing is easy too. (Strings don’t like `==`, so use `if(myString1.equals("Hello")) {....}` though, or use `switch()`)

Simple Sketch in 3D

Here is a simple Sketch in 3D.
It looks cool because of the `lights()` command.

``````PShape testShapeGroup;

void setup() {
// init
size(800, 600, P3D);

// Make a group PShape
testShapeGroup = createShape(GROUP);

// Make shapes (children)
PShape rectangle = createShape(BOX, 90, 7, 90); // #1
rectangle.translate(0, 44, 0);
rectangle.setFill(color(0, 0, 255));

PShape circle = createShape(SPHERE, 40 ); // #2
circle.setStroke(false);
circle.setFill(color(255, 0, 0));

} // func

void draw() {
// runs on and on
background(0);
lights();

translate(mouseX, mouseY);
shape(testShapeGroup);
} // func
//
``````

You can use the line() command. It comes as 2D AND 3D.

Or use this small line with a bit of surface:

``````void MyBox(float x1, float y1, float z1, float x2, float y2, float z2, float weight, color strokeColour)
// was called drawLine; programmed by James Carruthers
// see http://processing.org/discourse/yabb2/YaBB.pl?num=1262458611/0#9
{
PVector p1 = new PVector(x1, y1, z1);
PVector p2 = new PVector(x2, y2, z2);
PVector v1 = new PVector(x2-x1, y2-y1, z2-z1);
float rho = sqrt(pow(v1.x,2)+pow(v1.y,2)+pow(v1.z,2));
float phi = acos(v1.z/rho);
float the = atan2(v1.y,v1.x);
v1.mult(0.5);

pushMatrix();
translate(x1,y1,z1);
translate(v1.x, v1.y, v1.z);
rotateZ(the);
rotateY(phi);
noStroke();
fill(strokeColour);
// box(weight,weight,p1.dist(p2)*1.2);
box(weight,weight,p1.dist(p2)*1.0);
popMatrix();
}
``````

Yes, check out PeasyCam. It’s a library.

There is also QueasyCam like in a first person shooter.

Here is a PeasyCam example for zoom, pan, rotate:

``````

// Demo for PeasyCam

// http://mrfeinberg.com/peasycam/

import peasy.*;

PeasyCam pcam;

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

void setup() {
size(400, 400, P3D);
pcam = new PeasyCam(this, 1000);
//  hint(DISABLE_OPTIMIZED_STROKE);
}

void draw() {
background(255);
lights();
drawPyramid(150);

pcam.beginHUD();
noLights();
fill(0);
text("Use PeasyCam by dragging the mouse, pan etc. ", 12, 12);
pcam.endHUD();
}

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

void drawPyramid(int t) {

coor();

fill(255, 0, 255);
makeSphere(-t, t, -t);

strokeWeight(1);
stroke(0);

beginShape(TRIANGLES);

fill(255, 0, 0, 150); // Note that each polygon can have its own color.
vertex(-t, -t, -t);
vertex( t, -t, -t);
vertex( 0, 0, t);

fill(150, 150);
vertex( t, -t, -t);
vertex( t, t, -t);
vertex( 0, 0, t);

fill(255, 150);
vertex( t, t, -t);
vertex(-t, t, -t);
vertex( 0, 0, t);

fill(150, 150);
vertex(-t, t, -t);
vertex(-t, -t, -t);
vertex( 0, 0, t);

endShape();
}

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

void coor() {
//
// Draw axis X, Y, Z
strokeWeight(3);
stroke(255, 0, 0); // red
line(0, 0, 0, 400, 0, 0);
fill(255, 0, 0);
makeSphere(400, 0, 0);

stroke(0, 255, 0); //green
line(0, 0, 0, 0, 400, 0);
fill(0, 255, 0);
makeSphere(0, 400, 0);

stroke(0, 0, 255); // blue
line(0, 0, 0, 0, 0, 400);
fill(0, 0, 255); // blue
makeSphere(0, 0, 400);
}

void makeSphere(float x, float y, float z) {
pushMatrix();
translate(x, y, z);
noStroke();
sphere (10);
popMatrix();
}
//
``````

when you have an list of points use vertex to connect them:

``````// Make the shape
PShape myShape; // see https: // www.processing.org/tutorials/pshape/

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

fill(255, 0, 0);

myShape = createShape();
myShape.beginShape();

myShape.vertex(100, 100, -300);  // can be a for loop over an array of points (or `ArrayList`)
myShape.vertex(100, 200, -300);
myShape.vertex(100, 100, 0);

myShape.endShape();
}

void draw() {
background (0, 0, 0);
lights();

pushMatrix();
translate (width/2, height/2, 0);
rotateX (radians(map(mouseY, 0, width, 0, 360)));
rotateY (radians(map(mouseX, 0, width, 0, 360)));

shape(myShape, 0, 0);

popMatrix();
}
``````

``````
// arrow

float angle;

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

void setup() {
size(1600, 900, P3D);
}

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

// this is only to show with the mouse !!
translate(width/2, height/2);
rotateY(map(mouseX, 0, width, -TWO_PI, TWO_PI*2));
rotateX(map(mouseY, 0, height, -TWO_PI, TWO_PI*2));

// the line
myLine(new PVector(0, 0, 0),
new PVector(10, 210, -510));

// translate(200, 200, 0);
// rotateY(angle+=.122);
}

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

void myLine(PVector from, PVector to) {

// basic line
linePV(from, to);

// sphere
pushMatrix();
noStroke();
translate(from.x, from.y, from.z);
fill(0, 255, 0);
sphere(9);
popMatrix();
stroke(255, 0, 0);

PVector ortho = findOrtogonalPVectorLEFT(from, to);
PVector behind = PVector.lerp( ortho, from, 0.12 );
linePV(to, behind);

ortho = findOrtogonalPVectorRIGHT(from, to);
behind = PVector.lerp( ortho, from, 0.12 );
linePV(to, behind);
}

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

void linePV(PVector from, PVector to) {
stroke(255, 0, 0);
strokeWeight(5);

line(from.x, from.y, from.z,
to.x, to.y, to.z);
strokeWeight(1); // reset
}

PVector findOrtogonalPVectorLEFT (PVector a, PVector b) {
PVector dir = PVector.sub(b, a);
dir.setMag(47);
PVector c = b.copy();
c.x -= dir.y;
c.y += dir.x;

return c;
}

PVector findOrtogonalPVectorRIGHT (PVector a, PVector b) {
PVector dir = PVector.sub(b, a);
dir.setMag(47);
PVector c = b.copy();
c.x += dir.y;
c.y -= dir.x;

return c;
}

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

void arrow() {

// some color consts
final color RED = color(255, 0, 0);
final color GREEN = color(0, 255, 0);
final color BLUE = color(0, 0, 255);

final color LIGHTGRAY = color(111);

// points in 2D
final int[] x = {
-50, 0, 50, 25, 25, -25, -25, -50
};
final int[] y = {
0, -50, 0, 0, 50, 50, 0, 0
};

// how thick is the arrow (1/2)
final int halfOfTheThickness = 12;

pushMatrix();

// all no Stroke
noStroke();

// arrow Form - ceiling
fill(RED); // RED
beginShape();
for (int i = 0; i<8; i++) {
vertex(x[i], y[i], -halfOfTheThickness);
}
endShape(CLOSE);
//
// arrow Form - floor
fill(RED); // BLUE
beginShape();
for (int i = 0; i<8; i++) {
vertex(x[i], y[i], halfOfTheThickness);
}
endShape(CLOSE);
//
// walls of the arrow
fill(BLUE); //  GREEN
for (int i = 0; i<x.length; i++) {
vertex(x[i], y[i], -halfOfTheThickness);
vertex(x[i], y[i], halfOfTheThickness);
}
endShape(CLOSE);

popMatrix();
} // func
//
``````

I am not sure about the plane you mentioned.

Here is a dotted line though.

``````

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

void setup() {
size(1200, 400, P3D);
}

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

translate(width/2, 200, 0);
rotateY(map(mouseX, 0, width, 0, TWO_PI));
rotateX(map(mouseY, 0, height, 0, TWO_PI));

dottedLine(new PVector(0, 0, 0),
new PVector(10, 210, -510));
}

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

void dottedLine(PVector from, PVector to) {
stroke(255, 0, 0);
strokeWeight(2);

for (int i = 0; i < 100-5; i+=10) {

//   if (i%10==0) {
PVector step = PVector.lerp( from, to, i / 100.0 );
PVector step2 = PVector.lerp( from, to, (i+5) / 100.0 );

//point(step.x, step.y, step.z);
line(step.x, step.y, step.z,
step2.x, step2.y, step2.z);
// }
}
strokeWeight(1); // reset
}
//
``````

use `String[] txtFileAsArray = loadStrings("....");`, a for-loop and split(), then for-loop again

here is an example

text file content:

``````line 100 120 122 300 100 120
line 300 320 322 400 400 120
``````

Sketch to read and execute the lines:

``````
import peasy.*;

PeasyCam cam;

String[] list;
// ------------------------------------------------------------

void setup() {
size(1400, 900, P3D);
cam = new PeasyCam(this, 400);

}

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

for (String s1 : list) {
// for (int i = 0; i < 1; i++) {
String[] oneLine = s1.split(" ");
switch (oneLine) {
case "line":
PVector start = pvFromString(oneLine, oneLine, oneLine);
PVector stop  = pvFromString(oneLine, oneLine, oneLine);
dottedLine(start, stop);
pvSphere(start);
pvBox(stop);
break;

default:
println("Unknown command! " +s1);
break;
}//switch
}//for
}//func

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

void pvSphere (PVector pv) {
pushMatrix();
translate(pv.x, pv.y, pv.z);
noStroke();
sphere(13);
popMatrix();
}

void pvBox (PVector pv) {
pushMatrix();
translate(pv.x, pv.y, pv.z);
noStroke();
box(13);
popMatrix();
}

PVector pvFromString (String s0, String s1, String s2) {
PVector pv = new PVector (float(s0), float (s1), float (s2));
return pv;
}

void dottedLine(PVector from, PVector to) {

stroke(255, 0, 0);
strokeWeight(2);

for (int i = 0; i < 100-5; i+=10) {

PVector step = PVector.lerp( from, to, i / 100.0 );
PVector step2 = PVector.lerp( from, to, (i+5) / 100.0 );

line(step.x, step.y, step.z,
step2.x, step2.y, step2.z);
}
strokeWeight(1); // reset
}
//
``````

No.