Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I'm looking at an example from Nature of Code.
The particular example has a ball accelerate towards the cursor. However, it does not stop when it reaches it, actually it has maximum momentum, and starts to decelerate once it passes it, accelerate towards the cursor, and overshoot it again.
My question is, how to have the ball accelerate, then start decelerating BEFORE it touches the cursor using a transition such as ease out, so it stops before it touches the cursor?
The ProcessingJS code:
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// A Mover object
Mover mover;
void setup() {
size(640,360);
mover = new Mover();
}
void draw() {
background(255);
// Update the position
mover.update();
// Display the Mover
mover.display();
}
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
class Mover {
// The Mover tracks position, velocity, and acceleration
PVector position;
PVector velocity;
PVector acceleration;
// The Mover's maximum speed
float topspeed;
Mover() {
// Start in the center
position = new PVector(width/2,height/2);
velocity = new PVector(0,0);
topspeed = 5;
}
void update() {
// Compute a vector that points from position to mouse
PVector mouse = new PVector(mouseX,mouseY);
PVector acceleration = PVector.sub(mouse,position);
// Set magnitude of acceleration
acceleration.setMag(0.2);
// Velocity changes according to acceleration
velocity.add(acceleration);
// Limit the velocity by topspeed
velocity.limit(topspeed);
// position changes by velocity
position.add(velocity);
}
void display() {
stroke(0);
strokeWeight(2);
fill(127);
ellipse(position.x,position.y,48,48);
}
}
The Nature of Code is an awesome book and I'm often coming back to read it, especially when it comes to autonomous agents.
About your specific question, Shiffman deals with this exact problem just a little bit further in the same chapter. Take a look at example 6.2 on this page and you'll get the approximative comportment you just described. It's a little bit too long to post the whole thing, but here's an excerpt just in case the site goes down in the future and someone reads this question:
void arrive(PVector target) {
PVector desired = PVector.sub(target,location);
// The distance is the magnitude of
// the vector pointing from
// location to target.
float d = desired.mag();
desired.normalize();
// If we are closer than 100 pixels...
if (d < 100) {
//[full] ...set the magnitude
// according to how close we are.
float m = map(d,0,100,0,maxspeed);
desired.mult(m);
//[end]
} else {
// Otherwise, proceed at maximum speed.
desired.mult(maxspeed);
}
// The usual steering = desired - velocity
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce);
applyForce(steer);
}
I can take no credit for the code, as it's Shiffman's writing. I'm just the messenger. Have fun and thanks for the glory points!
Related
I tried to make a jump look realistic, while I watched through the Videos:
The Natur of Code - The Coding Train
I got into PVectors. I strongly recomend watching him. But to get to my question, everything seems to work, exept that it draws the rectangle (my PVector) the way I want.
void keyPressed() {
if (keyCode == UP) {
for (int i = 0; i < 16; i++) {
location.sub(velocity);
velocity.sub(acceleration);
h.display();
background(0);
}
velocity.set(0, 15);
}
}
That's the Code, I expect it to "jump", but nothing realy happens. You can see that the rectangle get's drawn again (on the same spot), but there's no movement. It's definitly an issue with the drawing of the background or something, I don't know what exaclty though.
The nature of your question is unclear. You mentioned issues regarding the background interfering with your rectangle after the UP arrow key is pressed. This is likely because background(0) is called immediately after h.display(). I would remove background(0) from your loop if it's a display issue.
Other than that, there seem to be other issues with the loop itself. When the UP key is pressed, h is affected by acceleration only for 16 frames. To make your object more realistic, gravity (or whatever acceleration you choose) should constantly be acting upon the object.
With that in mind, here's a solution for you.
void keyPressed() {
if (keyCode == UP) {
// Make the character 'jump' upwards when the UP arrow is pressed.
// Setting the velocity should be the only thing happening when the key is pressed.
velocity.set(0, -2);
}
}
void draw() {
// Reset the background each frame so rectangles don't overlap.
background(255);
// Always draw the rectangle AFTER resetting the canvas.
h.display();
// Change the object's location by it's velocity.
location.add(velocity);
// And chance the object's velocity by it's acceleration.
// Since acceleration is the acting force of gravity in this situation, acceleration need not be changed.
velocity.add(acceleration);
// Prevent the rectangle from falling through the bottom of the canvas.
if(location.y > height - 5) location.y = height - 5;
}
// You negleteced to define your variables in your code snippet. Here they are.
PVector location = new PVector(0, 0);
PVector velocity = new PVector(0, 0);
PVector acceleration = new PVector(0, 0.1); // Notice that acceleration's y-value is 0.01. This is so you can see the effect of gravity.
// Define your rectangle object.
Object h = new Object();
class Object {
Object() {} // Constructor.
void display() {
// Draw the rectangle at the x- and y-positions of the location vector.
// The '+ width/2' places it at the center of the screen.
rectMode(CENTER);
rect(location.x + width/2, location.y, 10, 10);
}
}
I am creating a model of a solar system in processing, and after removing the background I noticed the planets were leaving a trail of their image behind them. The program runs fine when the background is back in, but I want to add a lot more and I am sure this is inefficient and will bog things down.
I am very new to processing, and I am really not sure how to solve this. Maybe delete previous images after a delay to create a shortened trail?
These are just the parts I think are important cherry picked from the code, this is just the example of one planet. Sorry if the code is clunky, any suggestions are happily accepted.
Planet p1;
void setup() {
mercury = loadImage("mercury.png")
p1 = new Planet(40, random(TWO_PI), 0.05);
}
void draw() {
//background(0)
translate(width / 2, height / 2);
p1.display1();
p1.orbit();
}
class Planet {
float radius;
float angle;
float distance;
float orbitSpeed;
Planet(float r, float d, float o) {
radius = r;
distance = d;
orbitSpeed = o;
angle = random(TWO_PI);
}
void orbit() {
angle = angle + orbitSpeed;
}
void display1() {
pushMatrix();
rotate(angle);
translate(distance, 0);
imageMode(CENTER);
image(mercury, radius, radius, 10, 10);
popMatrix();
}
}
I realized that this would probably happen, and I am not sure how to stop it.
The behavior you describe is simply the nature of computer graphics; it's how games, operating systems, and hardware displays all work – they clear and redraw everything every frame.
In Processing, graphic objects that are pushed to a buffer remain there indefinitely until the buffer is cleared or something is pushed on top of them (this is why the planets are leaving a trail without calling background() – previous frames remain in the buffer).
You are worried about the background() being inefficient. Don't be, as it's one of the fastest operations (simply sets the value of each pixel, as given by the user).
Processing does provide a clear() function, but this is equivalent to background(0).
If you're are still concerned about efficiency and speed, one way to speed up Processing is to use the FX2D renderer rather than default AWT renderer. Another way is cache drawn objects into PGraphics objects to prevent successive rasterization (since your planets are image files and not drawn with processing, you needn't worry about this).
Your code is simple enough that it doesn't need optimisations at this stage.
As micycle mentions, you are are drawing an image at a translated position, pretty similar to blitting.
In terms of the trails, one common trick you could use is not clear the screen completely, but draw a transparent rectangle as the background. The more transparency, the longer the trails.
Here's a tweaked version of your code:
// planet object
Planet p1;
// planet texture
PImage mercury;
void setup() {
size(300, 300);
// draw image from center
imageMode(CENTER);
// clear to black one
background(0);
// remove strokes (we'll use rect() later)
noStroke();
// set the fill to black but with 9/255 transparency (~3.5% transparent)
fill(0,9);
// init texture
mercury = loadImage("mercury.png");
// init planet
p1 = new Planet(40, random(TWO_PI), 0.05);
}
void draw() {
// draw a transparent rectangle instead of completely clearing the screen
rect(0,0,width,height);
// render planet
translate(width / 2, height / 2);
p1.display1();
p1.orbit();
}
class Planet {
float radius;
float angle;
float distance;
float orbitSpeed;
Planet(float r, float d, float o) {
radius = r;
distance = d;
orbitSpeed = o;
angle = random(TWO_PI);
}
void orbit() {
angle = angle + orbitSpeed;
}
void display1() {
pushMatrix();
rotate(angle);
translate(distance, 0);
image(mercury, radius, radius, 10, 10);
popMatrix();
}
}
It's an efficient quick'n'dirty hack as you won't need to store previous position and redraw multiple times, however it has it limitations in terms of the flexibility of the trails. Hopefully tweaking the fill() alpha parameter will get you the desired effect.
Later on if you're drawing many many many planets it things start running slow have a peak at VisualVM. Profile the CPU and see the methods that take the longest to complete and focus on those. Don't need to optimise everything, just the slowest calls. Remember that Processing have multiple renderers: JAVA2D is the default one, but there's also FX2D and P2D/P3D and they will behave differently. I strongly recommend optimising at the last moment (otherwise code might be less flexible and readable and will slow down development/iteration).
Hi How do I make bullets to collide with the objects in Processing ?
Bullets are fired and being translated and rotated
but whenever i try to use function dist() it always gives me 0 as the position of the vector
How do i get the correct vector position if i want the bullet to collide with objects using distance and make the the other object disappear ?
Here's the code
void move(){
passed = passed + time;
if (passed > bulletLife) {
alive = false;
}
forward.x = sin(theta);
forward.y = -cos(theta);
float speed = 15.0f;
velocity = PVector.mult(forward, speed);
side.add(forward);
void display(){
pushMatrix();
translate(side.x, side.y);
rotate(theta);
stroke(255);
ellipse(side.x, side.y, 30, 30);
popMatrix();
Thanks
You're getting 0 from dist() because translate() moves the coordinate system! I think, more than your question, you need to reconsider your code overall. You translate to side.x, side.y (which will then be 0,0 until you call popMatrix()) but then you draw the ellipse at side.x, side.y which is offset from its actual position.
In other words: if the position is 100,200, you're actually drawing the object at 200,400!
If you skip the translate() part, you can use this to draw your object:
void display() {
stroke(255);
ellipse(side.x, side.y, 30,30);
}
And this to check collision:
if (dist(side.x, side.y, bullet.x, bullet.y) == 0) {
collision = true;
}
else {
collision = false;
}
You can also see my collision-detection functions for Processing, which have lots of examples that might help.
So I’m trying to give an obj some physics, and have work with the example of the bouncing ball that processing comes with, and I have make it instead of a ball to be a cylinder, but I can’t find the way to make the obj to have the physics.
I’m importing the obj with the library saito.objloader. I have this code, which is the invocation of the obj
import processing.opengl.*;
import saito.objloader.*;
OBJModel modelCan;
PVector location; // Location of shape
PVector velocity; // Velocity of shape
PVector gravity; // Gravity acts at the shape's acceleration
float rotX, rotY;
void setup() {
size(1028, 768, OPENGL);
frameRate(30);
modelCan = new OBJModel(this, "can.obj", "absolute", TRIANGLES);
modelCan.scale(50);
modelCan.translateToCenter();
modelCan.enableTexture();
location = new PVector(100,100,100);
velocity = new PVector(1.5,2.1,3);
gravity = new PVector(0,0.2,0);
}
void draw() {
background(129);
lights();
// Add velocity to the location.
location.add(velocity);
// Add gravity to velocity
velocity.add(gravity);
// Bounce off edges
if ((location.x > width) || (location.x < 0)) {
velocity.x = velocity.x * -1;
}
if (location.y > height) {
// We're reducing velocity ever so slightly
// when it hits the bottom of the window
velocity.y = velocity.y * -0.95;
location.y = height;
}
if (location.z < -height || location.z > 0) { //note that Zaxis goes 'into' the screen
velocity.z = velocity.z * -0.95;
//location.z = height;
}
println("location x: "+location.x);
println("location y: "+location.y);
println("location z: "+location.z);
println("velocidad x: "+velocity.x);
println("velocidad y: "+velocity.y);
println("velocidad z: "+velocity.z);
pushMatrix();
translate(width/2, height/2, 0);
modelCan.draw();
popMatrix();
}
I hope you guys can help me! Thanks!
The bouncing ball example is a very simple example, and I guess you can't apply it to a cylinder in an easy way.
You might want to have a look at these sites :
http://www.wildbunny.co.uk/blog/2011/04/20/collision-detection-for-dummies/
http://shiffman.net/ (his book is essential )
https://github.com/shiffman/Box2D-for-Processing (again : Daniel Shiffman)
Collision detection is made in computer time : it means that it's correlated with the frequency of your program execution. For instance, the velocity of an object can be so big that between two render cycles your first object is passing through your second object: collision detection won't happen. They didn't collide during the previous cycle, and don't collide during the current cycle.
That's why some physics "engine" like Box2D try to anticipate the collision, computing the bounding box of each object.
If you want to make accurate collision detection in 3D, you can look at the Bullet library, used in many games and movies : http://bulletphysics.org/wordpress/ but the learning curve might be large.
In your program, you can try to give a threshold to your collision detection (and add the dimensions of your object to its position, if you want the whole body to collide, not only its center !): if your object's position is between your limit and (your limit +/- a threshold) consider it's colliding, but you won't totally avoid tunnelling.
Im working on a project where i want to generate a 3D mesh to represent a certain amount of data.
To create this mesh i want to use transformation Matrixes, so i created a class based upon the mathematical algorithms found on a couple of websites.
Everything seems to work, scale/translation but as soon as im rotating a mesh on its x-axis its starts to deform after 2 to 3 complete rotations. It feels like my scale values are increasing which transforms my mesh. I'm struggling with this problem for a couple of days but i can't figure out what's going wrong.
To make things more clear you can download my complete setup here.
I defined the coordinates of a box and put them through the transformation matrix before writing them to the screen
This is the formula for rotating my object
void appendRotation(float inXAngle, float inYAngle, float inZAngle, PVector inPivot ) {
boolean setPivot = false;
if (inPivot.x != 0 || inPivot.y != 0 || inPivot.z != 0) {
setPivot = true;
}
// If a setPivot = true, translate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,inPivot.z); }
}
// Create a rotationmatrix
Matrix3D rotationMatrix = new Matrix3D();
// xsin en xcos
float xSinCal = sin(radians(inXAngle));
float xCosCal = cos(radians(inXAngle));
// ysin en ycos
float ySinCal = sin(radians(inYAngle));
float yCosCal = cos(radians(inYAngle));
// zsin en zcos
float zSinCal = sin(radians(inZAngle));
float zCosCal = cos(radians(inZAngle));
// Rotate around x
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[1][1] = xCosCal;
rotationMatrix.matrix[1][2] = xSinCal;
rotationMatrix.matrix[2][1] = -xSinCal;
rotationMatrix.matrix[2][2] = xCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around y
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = yCosCal;
rotationMatrix.matrix[0][2] = -ySinCal;
rotationMatrix.matrix[2][0] = ySinCal;
rotationMatrix.matrix[2][2] = yCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Rotate around z
rotationMatrix.setIdentity();
// --
rotationMatrix.matrix[0][0] = zCosCal;
rotationMatrix.matrix[0][1] = zSinCal;
rotationMatrix.matrix[1][0] = -zSinCal;
rotationMatrix.matrix[1][1] = zCosCal;
// Add rotation to the basis matrix
this.multiplyWith(rotationMatrix);
// Untranslate the position
if (setPivot) {
// Translations for the different axises need to be set different
if (inPivot.x != 0) { this.appendTranslation(-inPivot.x,0,0); }
if (inPivot.y != 0) { this.appendTranslation(0,-inPivot.y,0); }
if (inPivot.z != 0) { this.appendTranslation(0,0,-inPivot.z); }
}
}
Does anyone have a clue?
You never want to cumulatively transform matrices. This will introduce error into your matrices and cause problems such as scaling or skewing the orthographic components.
The correct method would be to keep track of the cumulative pitch, yaw, roll angles. Then reconstruct the transformation matrix from those angles every update.
If there is any chance: avoid multiplying rotation matrices. Keep track of the cumulative rotation and compute a new rotation matrix at each step.
If it is impossible to avoid multiplying the rotation matrices then renormalize them (starts on page 16). It works for me just fine for more than 10 thousand multiplications.
However, I suspect that it will not help you, numerical errors usually requires more than 2 steps to manifest themselves. It seems to me the reason for your problem is somewhere else.
Yaw, pitch and roll are not good for arbitrary rotations. Euler angles suffer from singularities and instability. Look at 38:25 (presentation of David Sachs)
http://www.youtube.com/watch?v=C7JQ7Rpwn2k
Good luck!
As #don mentions, try to avoid cumulative transformations, as you can run into all sort of problems. Rotating by one axis at a time might lead you to Gimbal Lock issues. Try to do all rotations in one go.
Also, bare in mind that Processing comes with it's own Matrix3D class called PMatrix3D which has a rotate() method which takes an angle(in radians) and x,y,z values for the rotation axis.
Here is an example function that would rotate a bunch of PVectors:
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){
int vl = verts.length;
PVector[] clone = new PVector[vl];
for(int i = 0; i<vl;i++) clone[i] = verts[i].get();
//rotate using a matrix
PMatrix3D rMat = new PMatrix3D();
rMat.rotate(angle,axis.x,axis.y,axis.z);
PVector[] dst = new PVector[vl];
for(int i = 0; i<vl;i++) {
dst[i] = new PVector();
rMat.mult(clone[i],dst[i]);
}
return dst;
}
and here is an example using it.
HTH
A shot in the dark: I don't know the rules or the name of the programming language you are using, but this procedure looks suspicious:
void setIdentity() {
this.matrix = identityMatrix;
}
Are you sure your are taking a copy of identityMatrix? If it is just a reference you are copying, then identityMatrix will be modified by later operations, and soon nothing makes sense.
Though the matrix renormalization suggested probably works fine in practice, it is a bit ad-hoc from a mathematical point of view. A better way of doing it is to represent the cumulative rotations using quaternions, which are only converted to a rotation matrix upon application. The quaternions will also drift slowly from orthogonality (though slower), but the important thing is that they have a well-defined renormalization.
Good starting information for implementing this can be:
http://www.cprogramming.com/tutorial/3d/quaternions.html
http://www.scheib.net/school/library/quaternions.pdf
A useful academic reference can be:
K. Shoemake, “Animating rotation with quaternion curves,” ACM
SIGGRAPH Comput. Graph., vol. 19, no. 3, pp. 245–254, 1985. DOI:10.1145/325165.325242