Overlapping issue in P3D when rotating - processing

I'd like to rotate a cube in P3D and my code uses live sensor data to do that.
The problem is the previous orientations of the cube are always visible and overlap (as you can see in this image: http://i.stack.imgur.com/txXw6.jpg), which I don't want. I already tried the functions "hint(DISABLE_OPTIMIZED_STROKE)" and "hint(ENABLE_DEPTH_TEST)", which did nothing. Besides the hint functions I found nothing on a similar issue.
How can I render ONLY the current orientation?
import processing.serial.*;
import toxi.geom.*;
Serial myPort;
float qW;
float qX;
float qY;
float qZ;
float[] axis = new float[4];
Quaternion quat = new Quaternion(1, 0, 0, 0);
void setup()
{
size(600, 400, P3D);
myPort = new Serial(this, "COM3", 9600);
background(0);
lights();
}
void draw()
{
serialEvent();
quat.set(qW, qX, qY, qZ);
axis = quat.toAxisAngle();
pushMatrix();
translate(width/2, height/2, -100);
rotate(axis[0], axis[1], axis[2], axis[3]);
noFill();
stroke(255);
box(330, 200, 40);
popMatrix();
}
void serialEvent()
{
int newLine = 13; // new line character in ASCII
String message;
do
{
message = myPort.readStringUntil(newLine); // read from port until new line
if (message != null)
{
String[] list = split(trim(message), " ");
if (list.length >= 4)
{
qW = float(list[0]);
qX = float(list[1]);
qY = float(list[2]);
qZ = float(list[3]);
}
}
} while (message != null);
}

It looks like you're not clearing the frame buffer. Try adding background(0); as the first line in draw();:
void draw()
{
//clear background
background(0);
serialEvent();
quat.set(qW, qX, qY, qZ);
axis = quat.toAxisAngle();
pushMatrix();
translate(width/2, height/2, -100);
rotate(axis[0], axis[1], axis[2], axis[3]);
noFill();
stroke(255);
box(330, 200, 40);
popMatrix();
}
Off topic, it might worth checking out serialEvent().
You could do something like this in setup()
myPort = new Serial(this, "COM3", 9600);
myPort.bufferUntil('\n');
you shouldn't need to call serialEvent() in draw(), the serial library will do that, as it's buffering.
Then in serialEvent() hopefully you can get away with just:
String message = myPort.readString();
if(message !=null){
String[] list = split(trim(message), " ");
if (list.length >= 4)
{
qW = float(list[0]);
qX = float(list[1]);
qY = float(list[2]);
qZ = float(list[3]);
}
}

Related

I am trying to make an abstract kind of object i guess, referencing the book processing creative coding examples

Here is the code, i can get screenshots of everything if need be, but Im just getting one error - "syntax error you might be mixing active and static modes."
Im fairly new to this so any help would be great.
float boxSize = 40;
float margin = boxSize*2;
float depth = 400;
color boxFill;
void setup(){
size(500,500,P3D);
}
void draw(){
translate(width/2, height/2, -depth/2);
rotateY(frameCount*PI/60);
rotateX(frameCount*PI/60);
}
for (float i=-depth/2+margin; i<=depth/2-margin; i+=boxSize){
pushMatrix();
for (float j=-height/2+margin; j<=height/2-margin; j+=boxSize){
pushMatrix();
for (float k=-width/2+margin; k<=width/2-margin; k+=boxSize){
boxFill = color(abs(i), abs(j), abs(k), 50);
pushMatrix();
translate(k, j, i);
fill(boxFill);
box(boxSize, boxSize, boxSize);
popMatrix();
}
popMatrix();
}
popMatrix();
}
}
I recommend formatting your code first: Processing > Edit > Auto Format (CMD+T / Ctrl+T)
This will reveal this error right after the rotateX() call:
Missing left curly bracket "{"
What it actually means is that you have an extra } and it shouldn't be (as the for loop after should be part of the draw() function:
float boxSize = 40;
float margin = boxSize*2;
float depth = 400;
color boxFill;
void setup() {
size(500, 500, P3D);
}
void draw() {
translate(width/2, height/2, -depth/2);
rotateY(frameCount*PI/60);
rotateX(frameCount*PI/60);
for (float i=-depth/2+margin; i<=depth/2-margin; i+=boxSize) {
pushMatrix();
for (float j=-height/2+margin; j<=height/2-margin; j+=boxSize) {
pushMatrix();
for (float k=-width/2+margin; k<=width/2-margin; k+=boxSize) {
boxFill = color(abs(i), abs(j), abs(k), 50);
pushMatrix();
translate(k, j, i);
fill(boxFill);
box(boxSize, boxSize, boxSize);
popMatrix();
}
popMatrix();
}
popMatrix();
}
}

object releases another smaller object?

Can anyone help me?
So, I'm supposed to have a ball that is moving horizontally, such that every time I press the mouse, a ball would get shoot vertically, then slows down due to friction. The vertical ball would stay in the old position but the player would reset.
How do I go about doing that without using classes?
Here my code so far:
boolean circleupdatetostop = true;
float x = 100;
float yshot = 880;
float speedshot = random(4,10);
float speedx = 6;
void setup() {
size(1280,960);
}
void draw() {
background(255);
stroke(0);
fill(0);
circle(x,880,80);
if (x > width || x < 0 ) {
speedx = speedx * -1;
}
if (circleupdatetostop) {
x = x + speedx;
}
if (circleupdatetostop == false) {
float locationx = x;
stroke(0);
fill(255,0,255);
circle(locationx,yshot,30);
yshot = yshot - speedshot;
}
}
void mousePressed () {
circleupdatetostop = !circleupdatetostop;
}
I'm not entirely sure if this is what you meant, but you could achieve shooting multiple balls by using ArrayList as well as processing's PVector to better handle the x and y coordinate pairs. If you wanted to look at classes, see this post.
import java.util.*;
// Whether the ball is moving or not
boolean circleupdatetostop = true;
// Information about the main_ball
PVector position = new PVector(100, 880);
PVector speed = new PVector(6, 0);
float diameter = 80;
// Information about the sot balls
ArrayList<PVector> balls_loc = new ArrayList<PVector>();
ArrayList<PVector> balls_speed = new ArrayList<PVector>();
float diameter_shot = 30;
float friction = 0.994;
void setup() {
size(1280, 960);
}
void draw() {
background(255);
stroke(0);
fill(0);
circle(position.x, position.y, diameter);
// Remember to consider the radius of the ball when bouncing off the edges
if (position.x + diameter/2 > width || position.x - diameter/2 < 0 ) {
speed.mult(-1);
}
if (circleupdatetostop) {
position.add(speed);
}
// Cycle through the list updating their speed and draw each ball
for (int i = 0; i<balls_loc.size(); i++) {
balls_speed.get(i).mult(friction+random(-0.05, 0.05));
balls_loc.get(i).add(balls_speed.get(i));
stroke(0);
fill(255, 0, 255);
circle(balls_loc.get(i).x, balls_loc.get(i).y, diameter_shot);
}
}
void mousePressed(){
// Add a new ball to be drawn
if(circleupdatetostop){
balls_loc.add(new PVector(position.x, position.y));
balls_speed.add(new PVector(0, random(-4, -10)));
}
circleupdatetostop = !circleupdatetostop;
}

Trying to use multiple instances of Mouse pressed

I’m trying to add a feature where you can click on different parts of the sketch and have an image randomly generated. It worked for the first time, but when I add another if mouse pressed function, it triggers all the mouse pressed code and all of the sets of images go off at the same time. I’m not sure how to isolate it so that just one goes off if it’s in the right spot.
Here is my code for the last attempt, I tried to isolate the mouse pressed function with a push and pop Matrix, which didn’t work.
PImage stage;
PImage model;
PImage [] hat = new PImage [5];
PImage [] pants = new PImage [4];
PImage [] shirt = new PImage [5];
int choice = 0;
int page = 0;
void setup() {
size (800, 800);
stage = loadImage("background.png");
background(255);
image(stage, 0, 0);
hat[0] = loadImage ("hat1.png");
hat[1] = loadImage ("hat2.png");
hat[2] = loadImage ("hat3.png");
hat[3] = loadImage ("hat4.png");
pants[0] = loadImage ("pant1.png");
pants[1] = loadImage ("pant2.png");
pants[2] = loadImage ("pant3.png");
pants[3] = loadImage ("pant4.png");
}
void draw() {
println(mouseX, mouseY); //398, 237 for hats.
image(stage, 0, 0);
pushMatrix();
if (dist(398, 237, mouseX, mouseY) <90 && mousePressed) choice = floor(random(4));
image(hat[choice], 349, 98);
popMatrix();
pushMatrix();
if (dist(404, 363, mouseX, mouseY) <90 && mousePressed) choice = floor(random(4));
image(pants[choice], 228, 263);
popMatrix();
}
The issue is that you're using the same variable for all the clothing items. So when you click on the hat button, it sets choice to a random number (let's say 2). Then you display hat[choice] and then you also display pants[choice]. One way around this is to have multiple different choice variables, hatChoice and pantsChoice. When you click on the hat button, it randomizes hatChoice, and when you click on the pants button, it randomizes pantsChoice. Something like this:
if (dist(398, 237, mouseX, mouseY) <90 && mousePressed) hatChoice = floor(random(4));
image(hat[hatChoice], 349, 98);
if (dist(404, 363, mouseX, mouseY) <90 && mousePressed) pantsChoice = floor(random(4));
image(pants[pantsChoice], 228, 263);
I also second #rjw1428's recommendation of using mouseClicked() instead of if (mousePressed). You can do something like this:
//your global variables...
int hatChoice = 0;
int pantsChoice = 0;
void setup() {
//your setup stuff...
}
void draw() {
image(stage, 0, 0);
image(hat[hatChoice], 349, 98);
image(pants[pantsChoice], 228, 263);
}
void mouseClicked() {
if (dist(mouseX, mouseY, 398, 237) < 90) {
hatChoice = floor(random(4));
}
if (dist(mouseX, mouseY, 404, 363) < 90) {
pantsChoice = floor(random(4));
}
}
This isn't a perfect solution, but to implement what you're trying to do, i might do this
PImage stage;
PImage model;
PImage [] hat = new PImage [5];
PImage [] pants = new PImage [4];
PImage [] shirt = new PImage [5];
int selectedHat = -1;
int selectedPants = -1;
int selectedShirt = -1;
int choice = 0;
int page = 0;
void setup(){
size (800,800);
stage = loadImage("background.png");
background(255);
image(stage,0,0);
initializeImages()
}
void draw(){
println(mouseX, mouseY); //398, 237 for hats.
image(stage,0,0);
if (selectedHat > 0) {
image(hat[selectedHat], 349,98);
}
if (selectedPants > 0) {
image(pants[choice], 228,263);
}
}
void mouseClicked() {
if(dist(404,363, mouseX, mouseY) <90 && mousePressed) {
selectedPants = floor(random(4));
}
if(dist(398,237, mouseX, mouseY) <90 && mousePressed) {
selectedHat = floor(random(4));
}
}
void initializeImages() {
hat[0] = loadImage ("hat1.png");
hat[1] = loadImage ("hat2.png");
hat[2] = loadImage ("hat3.png");
hat[3] = loadImage ("hat4.png");
pants[0] = loadImage ("pant1.png");
pants[1] = loadImage ("pant2.png");
pants[2] = loadImage ("pant3.png");
pants[3] = loadImage ("pant4.png");
}
Then if you wanted to clear, have an IF check for the location (button) that you want to select to clear, and your function could return all the 'selected' values back to -1

Processing P3D Animation leaving artifacts behind

I am trying to make a spinning cube in Processing's P3D with this code:
int sizes = 500;
int rotation = 0;
void setup() {
size(500, 500, P3D);
}
void draw() {
lights();
translate(sizes/2, sizes/2, 0);
rotateY(rotation * (PI/180));
rotateX(rotation * (PI/180));
background(0);
box(sizes/2);
rotation = (rotation + 1);
}
When I run it the cube does spin as I wanted, but there are strange 'artifacts' (for lack of a better name) left behind its edges.
What causes this issue, and can it be solved?
I tried this and it worked. Maybe instead of using backround(0), set every pixel to black like the background function does manually.
int sizes = 500;
int rotation = 0;
void setup() {
size(500, 500, P3D);
}
void draw() {
fill(255);
lights();
translate(sizes/2, sizes/2, 0);
rotateY(rotation * (PI/180));
rotateX(rotation * (PI/180));
loadPixels();
for(int i = 0; i < pixels.length; i++) pixels[i] = color(0);
box(sizes/2);
rotation = (rotation + 1);
}

Stop background from refreshing?

I am trying to get my gif to do something similar to this gif.
I have been able to get the line to draw, and the 'planets' to orbit, but can't figure out how to keep the line connecting the two circles, like the gif does.
Here's the basic code:
int x = 500;
int y = 500;
int radius = y/2;
int cX = x/2;
int cY = y/2;
String text1;
int lg_xBall;
int lg_yBall;
int sm_xBall;
int sm_yBall;
void setup() {
size(x, y);
smooth();
colorMode(RGB);
}
void draw() {
background(0);
stroke(255);
float t = millis()/1000.0f;
drawSmBallOrbit(100);
drawLgBallOrbit(100);
moveSmBall(t);
moveLgBall(t);
sun();
// showMouse();
connectingLines();
}
void drawCircle() { // This will draw a simple circle
stroke(1);
// x1=a+r*cos t, y1=b+r*sin t
ellipse(x/2, y/2, x/2, y/2);
}
void drawLines() { // This will draw lines from the center of the circle.
stroke(1);
line(x/2, y/2, radius/2, radius); // line from 6 to center
line(x/2, y/2, x/2, y/4); // line from 12 to center
for (int i = 0; i <= 5; i+=2.5) {
float x1 = x/2+radius/2*cos(i);
float y1 = y/2+radius/2*sin(i);
line(x/2, y/2, x1, y1);
}
}
void moveSmBall(float ky) { // This will create, and move, a small 'planet'
pushStyle();
stroke(100);
sm_xBall = (int)(cX+radius*cos(ky));
sm_yBall = (int)(cY+radius*sin(ky));
fill(190, 0, 0);
// background(0);
ellipse(sm_xBall, sm_yBall, 10, 10);
popStyle();
}
void drawSmBallOrbit(float opacity) {
pushStyle();
stroke(255, opacity);
strokeWeight(1);
noFill();
ellipse(x/2, y/2, cX+radius, cY+radius);
popStyle();
}
void moveLgBall(float kx) {
kx = kx/.7;
pushStyle();
lg_xBall = (int)(cX+radius*cos(kx)*.6);
lg_yBall = (int)(cY+radius*sin(kx)*.6);
fill(0, 0, 230);
ellipse(lg_xBall, lg_yBall, 30, 30);
popStyle();
}
void drawLgBallOrbit(float opacity) {
pushStyle();
stroke(255, opacity);
strokeWeight(1);
noFill();
ellipse(x/2, y/2, (cX+radius)*.6, (cY+radius)*.6);
popStyle();
}
void sun() {
pushStyle();
fill(250, 250, 0);
ellipse(cX, cY, 40, 40);
popStyle();
}
void connectingLines() {
line(sm_xBall, sm_yBall, lg_xBall, lg_yBall);
}
void showMouse() {
text("X: " + mouseX, x/2, y/2-30);
text("Y: " + mouseY, x/2, y/2-50);
}
Thanks for any help/advice!
The problem is that you're calling background() during every frame, which will clear away anything you've already drawn.
So you either need to stop calling background(), or you need to redraw the old lines every frame.
If you simply move the call to background() out of your draw() function and into your setup() function, you're about 50% there already:
void setup() {
size(x, y);
smooth();
colorMode(RGB);
background(0);
}
void draw() {
// background(0);
stroke(255);
float t = millis()/1000.0f;
drawSmBallOrbit(100);
drawLgBallOrbit(100);
moveSmBall(t);
moveLgBall(t);
sun();
// showMouse();
connectingLines();
}
However, the original animation does not show the previous positions of the ellipses. So you need to clear away the previous frame by calling the background() function, and then redraw previous line positions. You'd do that by having an ArrayList that holds those previous positions.
Here's a simple example that uses an ArrayList to redraw anywhere the mouse has been:
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(500, 500);
}
void draw() {
background(0);
stroke(255);
points.add(new PVector(mouseX, mouseY));
for(PVector p : points){
ellipse(p.x, p.y, 10, 10);
}
}
You would need to do something very similar, but you'd have to keep track of two points at a time instead of one, since you're tracking two ellipses and not just the mouse position.

Resources