Skip to content

Commit ded0d37

Browse files
committed
Luxo with filtering; pde examples updated. constrainFrame example is missed. @sechaparroc API can now be taken as the basis for p5.tree
1 parent e56348b commit ded0d37

5 files changed

Lines changed: 218 additions & 55 deletions

File tree

‎examples/basics/Luxo/Luxo.pde‎

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
import nub.primitives.*;
1414
import nub.core.*;
15-
import nub.core.constraint.*;
1615
import nub.processing.*;
1716

1817
Scene scene;
@@ -22,32 +21,17 @@ void setup() {
2221
size(1000, 700, P3D);
2322
scene = new Scene(this);
2423
scene.enableHint(Scene.BACKGROUND);
25-
//scene.setShape(this::floor);
2624
scene.fit(1);
27-
// Constraints
28-
WorldConstraint baseConstraint = new WorldConstraint();
29-
baseConstraint.setTranslationConstraint(AxisPlaneConstraint.Type.PLANE, Vector.plusK);
30-
baseConstraint.setRotationConstraint(AxisPlaneConstraint.Type.AXIS, Vector.plusK);
31-
LocalConstraint tipConstraint = new LocalConstraint();
32-
tipConstraint.setTranslationConstraint(AxisPlaneConstraint.Type.FORBIDDEN, Vector.zero);
33-
tipConstraint.setRotationConstraint(AxisPlaneConstraint.Type.AXIS, Vector.plusI);
34-
LocalConstraint shadeConstraint = new LocalConstraint();
35-
shadeConstraint.setTranslationConstraint(AxisPlaneConstraint.Type.FORBIDDEN, Vector.zero);
36-
// Nodes
3725
base = new Node(this::base);
38-
base.setConstraint(baseConstraint);
3926
arm = new Node(base, this::limb);
4027
arm.setPosition(0, 0, 8);
4128
arm.setOrientation(Quaternion.from(Vector.plusI, 0.6));
42-
arm.setConstraint(tipConstraint);
4329
forarm = new Node(arm, this::limb);
4430
forarm.setPosition(0, 0, 50);
4531
forarm.setOrientation(Quaternion.from(Vector.plusI, -2));
46-
forarm.setConstraint(tipConstraint);
4732
shade = new Node(forarm, this::shade);
4833
shade.setPosition(0, 0, 50);
4934
shade.setOrientation(Quaternion.from(new Vector(1, -0.3, 0), -1.7));
50-
shade.setConstraint(shadeConstraint);
5135
// for the lights to work the floor node should be the last to be added
5236
floor = new Node(this::floor);
5337
floor.tagging = false;
@@ -119,20 +103,30 @@ void draw() {
119103
}
120104

121105
void mouseMoved() {
122-
scene.mouseTag();
106+
scene.mouseTag("piece");
123107
}
124108

125109
void mouseDragged() {
126-
// no inertia for the nodes, but for the eye
127-
if (mouseButton == LEFT) {
128-
scene.mouseSpin(scene.node() != null ? 0 : 0.85);
129-
} else if (mouseButton == RIGHT) {
130-
scene.mouseShift(scene.node() != null ? 0 : 0.85);
110+
Node piece = scene.node("piece");
111+
if (piece == base) {
112+
Vector translateFromMouse = scene.displacement(new Vector(scene.mouseDX(), scene.mouseDY(), 0), piece);
113+
Vector axis = piece.displacement(Vector.plusK);
114+
piece.translate(translateFromMouse, Node.vectorPlaneFilter, new Object[] { axis });
115+
} else if (piece == arm || piece == forarm) {
116+
piece.rotate(Quaternion.from(scene.mouseRADX(), 0, 0));
117+
} else if (piece == shade) {
118+
scene.mouseSpin(piece);
131119
} else {
132-
scene.zoom(mouseX - pmouseX, scene.node() != null ? 0 : 0.85);
120+
if (mouseButton == LEFT) {
121+
scene.mouseSpin();
122+
} else if (mouseButton == RIGHT) {
123+
scene.mouseShift();
124+
} else {
125+
scene.zoom(mouseX - pmouseX);
126+
}
133127
}
134128
}
135129

136130
void mouseWheel(MouseEvent event) {
137131
scene.moveForward(event.getCount() * 20);
138-
}
132+
}

‎examples/demos/CustomNodeInteraction/CustomNodeInteraction.pde‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,17 @@ void keyPressed() {
6565
}
6666

6767
void mouseDragged() {
68-
if (mouseButton == LEFT)
69-
scene.mouseSpin("key");
70-
else if (mouseButton == CENTER)
71-
scene.zoom("key", scene.mouseDX());
72-
else
73-
scene.mouseShift("key");
68+
if (scene.node("key") != null) {
69+
if (mouseButton == LEFT)
70+
scene.mouseSpin("key");
71+
else if (mouseButton == CENTER)
72+
scene.zoom("key", scene.mouseDX());
73+
else
74+
scene.mouseShift("key");
75+
}
76+
else {
77+
scene.mouseSpin();
78+
}
7479
}
7580

7681
void mouseWheel(MouseEvent event) {
@@ -82,4 +87,4 @@ void mouseClicked(MouseEvent event) {
8287
scene.interact("key");
8388
if (event.getCount() == 2)
8489
scene.mouseTag("key");
85-
}
90+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
class Boid {
2+
// Node
3+
Node node;
4+
// timing task
5+
TimingTask task;
6+
// fields
7+
Vector position, velocity, acceleration, alignment, cohesion, separation; // position, velocity, and acceleration in
8+
// a vector datatype
9+
float neighborhoodRadius; // radius in which it looks for fellow boids
10+
float maxSpeed = 4; // maximum magnitude for the velocity vector
11+
float maxSteerForce = 0.1; // maximum magnitude of the steering vector
12+
float sc = 3; // scale factor for the render of the boid
13+
float flap = 0;
14+
float t = 0;
15+
16+
Boid(Vector inPos) {
17+
node = new Node(this::display);
18+
position = new Vector();
19+
position.set(inPos);
20+
node.setPosition(new Vector(position.x(), position.y(), position.z()));
21+
velocity = Vector.random();
22+
acceleration = new Vector();
23+
neighborhoodRadius = 100;
24+
task = new TimingTask(this::behavior);
25+
task.run();
26+
}
27+
28+
public void display(PGraphics pg) {
29+
pg.pushStyle();
30+
// uncomment to draw boid axes
31+
//Scene.drawAxes(pg, 10);
32+
pg.strokeWeight(2);
33+
pg.stroke(color(40, 255, 40));
34+
pg.fill(color(0, 255, 0, 125));
35+
// highlight boids under the mouse
36+
if (scene.node("mouseMoved") == node) {
37+
pg.stroke(color(0, 0, 255));
38+
pg.fill(color(0, 0, 255));
39+
}
40+
// highlight avatar
41+
if (node == avatar) {
42+
pg.stroke(color(255, 0, 0));
43+
pg.fill(color(255, 0, 0));
44+
}
45+
//draw boid
46+
pg.beginShape(TRIANGLES);
47+
pg.vertex(3 * sc, 0, 0);
48+
pg.vertex(-3 * sc, 2 * sc, 0);
49+
pg.vertex(-3 * sc, -2 * sc, 0);
50+
pg.vertex(3 * sc, 0, 0);
51+
pg.vertex(-3 * sc, 2 * sc, 0);
52+
pg.vertex(-3 * sc, 0, 2 * sc);
53+
pg.vertex(3 * sc, 0, 0);
54+
pg.vertex(-3 * sc, 0, 2 * sc);
55+
pg.vertex(-3 * sc, -2 * sc, 0);
56+
pg.vertex(-3 * sc, 0, 2 * sc);
57+
pg.vertex(-3 * sc, 2 * sc, 0);
58+
pg.vertex(-3 * sc, -2 * sc, 0);
59+
pg.endShape();
60+
pg.popStyle();
61+
}
62+
63+
Vector avoid(Vector target) {
64+
Vector steer = new Vector(); // creates vector for steering
65+
steer.set(Vector.subtract(position, target)); // steering vector points away from
66+
steer.multiply(1 / sq(Vector.distance(position, target)));
67+
return steer;
68+
}
69+
70+
//-----------behaviors---------------
71+
72+
void behavior() {
73+
t += 0.1;
74+
flap = 10 * sin(t);
75+
// acceleration.add(steer(new Vector(mouseX,mouseY,300),true));
76+
// acceleration.add(new Vector(0,.05,0));
77+
if (avoidWalls) {
78+
acceleration.add(Vector.multiply(avoid(new Vector(position.x(), flockHeight, position.z())), 5));
79+
acceleration.add(Vector.multiply(avoid(new Vector(position.x(), 0, position.z())), 5));
80+
acceleration.add(Vector.multiply(avoid(new Vector(flockWidth, position.y(), position.z())), 5));
81+
acceleration.add(Vector.multiply(avoid(new Vector(0, position.y(), position.z())), 5));
82+
acceleration.add(Vector.multiply(avoid(new Vector(position.x(), position.y(), 0)), 5));
83+
acceleration.add(Vector.multiply(avoid(new Vector(position.x(), position.y(), flockDepth)), 5));
84+
}
85+
//alignment
86+
alignment = new Vector();
87+
int alignmentCount = 0;
88+
//cohesion
89+
Vector posSum = new Vector();
90+
int cohesionCount = 0;
91+
//separation
92+
separation = new Vector();
93+
Vector repulse;
94+
for (int i = 0; i < flock.size(); i++) {
95+
Boid boid = flock.get(i);
96+
//alignment
97+
float distance = Vector.distance(position, boid.position);
98+
if (distance > 0 && distance <= neighborhoodRadius) {
99+
alignment.add(boid.velocity);
100+
alignmentCount++;
101+
}
102+
//cohesion
103+
float dist = dist(position.x(), position.y(), boid.position.x(), boid.position.y());
104+
if (dist > 0 && dist <= neighborhoodRadius) {
105+
posSum.add(boid.position);
106+
cohesionCount++;
107+
}
108+
//separation
109+
if (distance > 0 && distance <= neighborhoodRadius) {
110+
repulse = Vector.subtract(position, boid.position);
111+
repulse.normalize();
112+
repulse.divide(distance);
113+
separation.add(repulse);
114+
}
115+
}
116+
//alignment
117+
if (alignmentCount > 0) {
118+
alignment.divide((float) alignmentCount);
119+
alignment.limit(maxSteerForce);
120+
}
121+
//cohesion
122+
if (cohesionCount > 0)
123+
posSum.divide((float) cohesionCount);
124+
cohesion = Vector.subtract(posSum, position);
125+
cohesion.limit(maxSteerForce);
126+
acceleration.add(Vector.multiply(alignment, 1));
127+
acceleration.add(Vector.multiply(cohesion, 3));
128+
acceleration.add(Vector.multiply(separation, 1));
129+
move();
130+
checkBounds();
131+
}
132+
133+
void move() {
134+
velocity.add(acceleration); // add acceleration to velocity
135+
velocity.limit(maxSpeed); // make sure the velocity vector magnitude does not
136+
// exceed maxSpeed
137+
position.add(velocity); // add velocity to position
138+
node.setPosition(position);
139+
node.setOrientation(Quaternion.multiply(Quaternion.from(Vector.plusJ, atan2(-velocity.z(), velocity.x())),
140+
Quaternion.from(Vector.plusK, asin(velocity.y() / velocity.magnitude()))));
141+
acceleration.multiply(0); // reset acceleration
142+
}
143+
144+
void checkBounds() {
145+
if (position.x() > flockWidth)
146+
position.setX(0);
147+
if (position.x() < 0)
148+
position.setX(flockWidth);
149+
if (position.y() > flockHeight)
150+
position.setY(0);
151+
if (position.y() < 0)
152+
position.setY(flockHeight);
153+
if (position.z() > flockDepth)
154+
position.setZ(0);
155+
if (position.z() < 0)
156+
position.setZ(flockDepth);
157+
}
158+
}

‎src/nub/processing/Scene.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,6 +3087,15 @@ public void mouseSpin(String tag, float inertia) {
30873087
mouseSpin(node(tag), inertia);
30883088
}
30893089

3090+
/**
3091+
* Same as {@code mouseSpin(node, Graph.inertia)}.
3092+
*
3093+
* @see #mouseSpin(Node, float)
3094+
*/
3095+
public void mouseSpin(Node node) {
3096+
mouseSpin(node, Graph.inertia);
3097+
}
3098+
30903099
/**
30913100
* Same as {@code super.spinNode(node, pmouseX(), pmouseY(), mouseX(), mouseY(), inertia)}.
30923101
*

‎testing/src/intellij/Luxo.java‎

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,16 @@ public void setup() {
2121
scene.enableHint(Scene.BACKGROUND);
2222
//scene.setShape(this::floor);
2323
scene.fit(1);
24-
// Constraints
25-
/*
26-
WorldConstraint baseConstraint = new WorldConstraint();
27-
baseConstraint.setTranslationConstraint(AxisPlaneConstraint.Type.PLANE, Vector.plusK);
28-
baseConstraint.setRotationConstraint(AxisPlaneConstraint.Type.AXIS, Vector.plusK);
29-
LocalConstraint tipConstraint = new LocalConstraint();
30-
tipConstraint.setTranslationConstraint(AxisPlaneConstraint.Type.FORBIDDEN, Vector.zero);
31-
tipConstraint.setRotationConstraint(AxisPlaneConstraint.Type.AXIS, Vector.plusI);
32-
LocalConstraint shadeConstraint = new LocalConstraint();
33-
shadeConstraint.setTranslationConstraint(AxisPlaneConstraint.Type.FORBIDDEN, Vector.zero);
34-
// */
35-
// Nodes
3624
base = new Node(this::base);
37-
//base.setConstraint(baseConstraint);
3825
arm = new Node(base, this::limb);
3926
arm.setPosition(0, 0, 8);
4027
arm.setOrientation(Quaternion.from(Vector.plusI, 0.6));
41-
//arm.setConstraint(tipConstraint);
4228
forarm = new Node(arm, this::limb);
4329
forarm.setPosition(0, 0, 50);
4430
forarm.setOrientation(Quaternion.from(Vector.plusI, -2));
45-
//forarm.setConstraint(tipConstraint);
4631
shade = new Node(forarm, this::shade);
4732
shade.setPosition(0, 0, 50);
4833
shade.setOrientation(Quaternion.from(new Vector(1, -0.3f, 0), -1.7));
49-
//shade.setConstraint(shadeConstraint);
5034
// for the lights to work the floor node should be the last to be added
5135
floor = new Node(this::floor);
5236
floor.tagging = false;
@@ -118,17 +102,30 @@ public void draw() {
118102
}
119103

120104
public void mouseMoved() {
121-
scene.mouseTag();
105+
scene.mouseTag("piece");
122106
}
123107

124108
public void mouseDragged() {
125-
// no inertia for the nodes, but for the eye
126-
if (mouseButton == LEFT) {
127-
scene.mouseSpin(scene.node() != null ? 0 : 0.85f);
128-
} else if (mouseButton == RIGHT) {
129-
scene.mouseShift(scene.node() != null ? 0 : 0.85f);
130-
} else {
131-
scene.zoom(mouseX - pmouseX, scene.node() != null ? 0 : 0.85f);
109+
Node piece = scene.node("piece");
110+
if (piece == base) {
111+
Vector translateFromMouse = scene.displacement(new Vector(scene.mouseDX(), scene.mouseDY(), 0), piece);
112+
Vector axis = piece.displacement(Vector.plusK);
113+
piece.translate(translateFromMouse, Node.vectorPlaneFilter, new Object[] { axis });
114+
}
115+
else if (piece == arm || piece == forarm) {
116+
piece.rotate(Quaternion.from(scene.mouseRADX(), 0, 0));
117+
}
118+
else if (piece == shade) {
119+
scene.mouseSpin(piece);
120+
}
121+
else {
122+
if (mouseButton == LEFT) {
123+
scene.mouseSpin();
124+
} else if (mouseButton == RIGHT) {
125+
scene.mouseShift();
126+
} else {
127+
scene.zoom(mouseX - pmouseX);
128+
}
132129
}
133130
}
134131

0 commit comments

Comments
 (0)