In my processing application I want to translate a shape and scale it.
The coordinate, scale, and translate-values are saved in objects.
In each cycle I use the same translate-value per object and a bigger scale-value.
The problem is the 'scale' is somehow cumulated with the 'translate'- the scale does not happen in the middle of the object...
How can I setup the objects so the scaling happens at their center?
for (int i = 1; i < formen.size(); i++) {
Form f = formen.get(i);
pushMatrix();
f.sx = f.sx * 2;
f.sy = f.sy * 2;
scale(f.sx, f.sy);
translate(f.tx, f.ty);
noStroke();
createShape();
beginShape();
vertex(f.ax, f.ay);
bezierVertex(f.ax + f.kabx, f.ay, f.bx, f.by - f.kaby, f.bx, f.by);
bezierVertex(f.bx, f.by + f.kbcy, f.cx + f.kbcx, f.cy, f.cx, f.cy);
bezierVertex(f.cx - f.kcdx, f.cy, f.dx, f.dy + f.kcdy, f.dx, f.dy);
bezierVertex(f.dx, f.dy - f.kday, f.ax - f.kdax, f.ay, f.ax, f.ay);
endShape();
popMatrix();
delay(5);
}
Related
I am working QCustomPlot with Qt and need to change the color of a particular vertical grid line within the graph please let us know how we can change that I attached the image of my requirement.
The bleo code solve the issue
GraphTesting(QCustomPlot * customPlot)
{
// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i = 0; i < 101; ++i)
{
x[i] = i; //i / 50.0 - 1; // x goes from -1 to 1
y[i] = x[i]/2; // let's plot a quadratic function
}
// create graph and assign data to it:
customPlot->addGraph();
customPlot->graph(0)->setData(x, y);
// give the axes some labels:
customPlot->xAxis->setLabel("x");
customPlot->yAxis->setLabel("y");
customPlot->rescaleAxes();
QCPItemLine *step = new QCPItemLine(customPlot);
step->setPen(QPen(QColor(140, 0, 0)));
double begin = 25;
double first = customPlot->yAxis->range().lower;
double end = customPlot->yAxis->range().upper; //example values
step->start->setCoords(begin, first);
step->end->setCoords(begin, end);
customPlot->replot();
}
I am trying to get my arduino code for gemma, with neopixels, which has 5310 bytes of memory smaller so I can get more things into the program.
Currently I am trying to remove floats / reduce the size of the code snippet below:
void gradient(Color c1, Color c2, float time) {
for (float i = 0; i < time; i += 0.001) {
Color result(0, 0, 0);
result.Red = c1.Red * (1 - (i / time)) + c2.Red * (i / time);
result.Green = c1.Green * (1 - (i / time)) + c2.Green * (i / time);
result.Blue = c1.Blue * (1 - (i / time)) + c2.Blue * (i / time);
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
delay(1);
}
}
I managed to reduce it by 30 bytes to:
void gradient(Color c1, Color c2, float time) {
float stepsize = 0.01; // Stepsize in seconds
float lambda;
int maxiter = (int) (time/ stepsize);
Color result(0, 0, 0);
for (int i = 0; i <= maxiter; i++) {
lambda = (float) i / maxiter;
result.Red = c1.Red * (1 - lambda) + c2.Red * (lambda);
result.Green = c1.Green * (1 - lambda) + c2.Green * (lambda);
result.Blue = c1.Blue * (1 - lambda) + c2.Blue * (lambda);
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
delay(stepsize * 1000); // delay in milliseconds
}
}
But am trying still to make it smaller.
For those wondering the Color object is just an object with 3 ints called Red, Green and Blue. An example usage of this code would be:
gradient(Color(255, 0, 0), Color(0, 255, 0), 2);
Which would be a gradient from Red to Green over 2 seconds.
Thanks in advance!
If you can pull "delay()" out of all your code, it seems to avoid including a 100 byte size library? idk tbh, but here is my suggested modification, which in my testing saves 100 bytes of memory:
void gradient(Color c1, Color c2, float time) {
float stepsize = 0.01; // Stepsize in seconds
float lambda;
int maxiter = (int) (time/ stepsize);
Color result(0, 0, 0);
for (int i = 0; i <= maxiter; i++) {
lambda = (float) i / maxiter;
result.Red = c1.Red * (1 - lambda) + c2.Red * (lambda);
result.Green = c1.Green * (1 - lambda) + c2.Green * (lambda);
result.Blue = c1.Blue * (1 - lambda) + c2.Blue * (lambda);
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
//delay(stepsize * 1000); // delay in milliseconds
long lastTime=millis();
long delayTime = stepsize * 1000;
while(millis()-lastTime<delayTime){}
}
}
-First off, your color object should take 3 unsigned chars (0-255) there is no reason to put ints in there. (byte type in arduino)
-Second, I am not sure how you are implementing time, but generally in arduino you are working in milliseconds. Furthermore, without seeing your other implementation, I am guessing that time is a segment of time and based on your delay, I am going to guess that you could send time as a short (up multiply x1000 if necessary) (This would hold up to 32 seconds, in milliseconds)
void gradient(Color c1, Color c2, short time) {
short maxiter = (short) (time/ 10);
Color result(0, 0, 0);
for (int i = 0; i <= maxiter; i++) {
result.Red = (c1.Red * (maxiter-i) + c2.Red * i)/maxiter;
result.Green = (c1.Green* (maxiter-i) + c2.Green* i)/maxiter;
result.Blue = (c1.Blue* (maxiter-i) + c2.Blue* i)/maxiter;
for (uint8_t x = 0; x < 20; x++)pixels.setPixelColor(x, result.Red, result.Green, result.Blue);
pixels.show();
delay(10); // delay in milliseconds
}
}
I wrote a very simple sketch to simulate the interference of two planar waves, very easy.
The problem seems to be a little to much intensive for the cpu (moreover processing uses only one core) and I get only 1 o 2 fps.
Any idea how to improve this sketch?
float x0;
float y0;
float x1;
float y1;
float x2;
float y2;
int t = 0;
void setup() {
//noLoop();
frameRate(30);
size(400, 400, P2D);
x0 = width/2;
y0 = height/2;
x1 = width/4;
y1 = height/2;
x2 = width * 3/4;
y2 = height / 2;
}
void draw() {
background(0);
for (int x = 0; x <= width; x++) {
for (int y = 0; y <= height; y++) {
float d1 = dist(x1, y1, x, y);
float d2 = dist(x2, y2, x, y);
float factorA = 20;
float factorB = 80;
float wave1 = (1 + (sin(TWO_PI * d1/factorA + t)))/2 * exp(-d1/factorB);
float wave2 = (1 + (sin(TWO_PI * d2/factorA + t)))/2 * exp(-d2/factorB);
stroke( (wave1 + wave2) *255);
point(x, y);
}
}
t--; //Wave propagation
//saveFrame("wave-##.png");
}
As Kevin suggested, using point() isn't the most efficient method since it calls beginShape();vertex() and endShape();. You might be off better using pixels.
Additionally, the nested loops can be written as a single loop and dist() which uses square root behind the scenes can be avoided (you can uses squared distance with higher values).
Here's a version using these:
float x1;
float y1;
float x2;
float y2;
int t = 0;
//using larger factors to use squared distance bellow instead of dist(),sqrt()
float factorA = 20*200;
float factorB = 80*200;
void setup() {
//noLoop();
frameRate(30);
size(400, 400);
x1 = width/4;
y1 = height/2;
x2 = width * 3/4;
y2 = height / 2;
//use pixels, not points()
loadPixels();
}
void draw() {
for (int i = 0; i < pixels.length; i++) {
int x = i % width;
int y = i / height;
float dx1 = x1-x;
float dy1 = y1-y;
float dx2 = x2-x;
float dy2 = y2-y;
//squared distance
float d1 = dx1*dx1+dy1*dy1;//dist(x1, y1, x, y);
float d2 = dx2*dx2+dy2*dy2;//dist(x2, y2, x, y);
float wave1 = (1 + (sin(TWO_PI * d1/factorA + t))) * 0.5 * exp(-d1/factorB);
float wave2 = (1 + (sin(TWO_PI * d2/factorA + t))) * 0.5 * exp(-d2/factorB);
pixels[i] = color((wave1 + wave2) *255);
}
updatePixels();
text((int)frameRate+"fps",10,15);
// endShape();
t--; //Wave propagation
//saveFrame("wave-##.png");
}
This can be sped up further using lookup tables for the more time consuming functions such as sin() and exp().
You can see a rough (numbers need to be tweaked) preview running even in javascript:
var x1;
var y1;
var x2;
var y2;
var t = 0;
var factorA = 20*200;
var factorB = 80*200;
var numPixels;
var scaledWidth;
function setup() {
createCanvas(400, 400);
fill(255);
frameRate(30);
x1 = width /4;
y1 = height /2;
x2 = width * 3/4;
y2 = height / 2;
loadPixels();
numPixels = (width * height) * pixelDensity();
scaledWidth = width * pixelDensity();
}
function draw() {
for (var i = 0, j = 0; i < numPixels; i++, j += 4) {
var x = i % scaledWidth;
var y = floor(i / scaledWidth);
var dx1 = x1 - x;
var dy1 = y1 - y;
var dx2 = x2 - x;
var dy2 = y2 - y;
var d1 = (dx1 * dx1) + (dy1 * dy1);//dist(x1, y1, x, y);
var d2 = (dx2 * dx2) + (dy2 * dy2);//dist(x2, y2, x, y);
var wave1 = (1 + (sin(TWO_PI * d1 / factorA + t))) * 0.5 * exp(-d1 / factorB);
var wave2 = (1 + (sin(TWO_PI * d2 / factorA + t))) * 0.5 * exp(-d2 / factorB);
var gray = (wave1 + wave2) * 255;
pixels[j] = pixels[j+1] = pixels[j+2] = gray;
pixels[j+3] = 255;
}
updatePixels();
text(frameRate().toFixed(2)+"fps",10,15);
t--; //Wave propagation
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
Because you're using math to synthesise the image, it may make more sense to write this as a GLSL Shader. Be sure sure to checkout the PShader tutorial for more info.
Update:
Here's a GLSL version: code is less hacky and a lot more readable:
float t = 0;
float factorA = 0.20;
float factorB = 0.80;
PShader waves;
void setup() {
size(400, 400, P2D);
noStroke();
waves = loadShader("waves.glsl");
waves.set("resolution", float(width), float(height));
waves.set("factorA",factorA);
waves.set("factorB",factorB);
waves.set("pt1",-0.5,0.0);
waves.set("pt2",0.75,0.0);
}
void draw() {
t++;
waves.set("t",t);
shader(waves);
rect(0, 0, width, height);
}
void mouseDragged(){
float x = map(mouseX,0,width,-1.0,1.0);
float y = map(mouseY,0,height,1.0,-1.0);
println(x,y);
if(keyPressed) waves.set("pt2",x,y);
else waves.set("pt1",x,y);
}
void keyPressed(){
float amount = 0.05;
if(keyCode == UP) factorA += amount;
if(keyCode == DOWN) factorA -= amount;
if(keyCode == LEFT) factorB -= amount;
if(keyCode == RIGHT) factorB += amount;
waves.set("factorA",factorA);
waves.set("factorB",factorB);
println(factorA,factorB);
}
And the waves.glsl:
#define PROCESSING_COLOR_SHADER
uniform vec2 pt1;
uniform vec2 pt2;
uniform float t;
uniform float factorA;
uniform float factorB;
const float TWO_PI = 6.283185307179586;
uniform vec2 resolution;
uniform float time;
void main(void) {
vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
float d1 = distance(pt1,p);
float d2 = distance(pt2,p);
float wave1 = (1.0 + (sin(TWO_PI * d1/factorA + t))) * 0.5 * exp(-d1/factorB);
float wave2 = (1.0 + (sin(TWO_PI * d2/factorA + t))) * 0.5 * exp(-d2/factorB);
float gray = wave1 + wave2;
gl_FragColor=vec4(gray,gray,gray,1.0);
}
You can use drag for first point and hold a key and drag for the second point.
Additionally, use UP/DOWN, LEFT/RIGHT keys to change factorA and factorB. Results look interesting:
Also, you can grab a bit of code from this answer to save frames using Threads (I recommend saving uncompressed).
Option 1: Pre-render your sketch.
This seems to be a static repeating pattern, so you can pre-render it by running the animation ahead of time and saving each frame to an image. I see that you already had a call to saveFrame() in there. Once you have the images saved, you can then load them into a new sketch and play them one frame at a time. It shouldn't require very many images, since it seems to repeat itself pretty quickly. Think of an animated gif that loops forever.
Option 2: Decrease the resolution of your sketch.
Do you really need pixel-perfect 400x400 resolution? Can you maybe draw to an image that's 100x100 and scale up?
Or you could decrease the resolution of your for loops by incrementing by more than 1:
for (int x = 0; x <= width; x+=2) {
for (int y = 0; y <= height; y+=2) {
You could play with how much you increase and then use the strokeWeight() or rect() function to draw larger pixels.
Option 3: Decrease the time resolution of your sketch.
Instead of moving by 1 pixel every 1 frame, what if you move by 5 pixels every 5 frames? Speed your animation up, but only move it every X frames, that way the overall speed appears to be the same. You can use the modulo operator along with the frameCount variable to only do something every X frames. Note that you'd still want to keep the overall framerate of your sketch to 30 or 60, but you'd only change the animation every X frames.
Option 4: Simplify your animation.
Do you really need to calculate every single pixels? If all you want to show is a series of circles that increase in size, there are much easier ways to do that. Calling the ellipse() function is much faster than calling the point() function a bunch of times. You can use other functions to create the blurry effect without calling point() half a million times every second (which is how often you're trying to call it).
Option 5: Refactor your code.
If all else fails, then you're going to have to refactor your code. Most of your program's time is being spent in the point() function- you can prove this by drawing an ellipse at mouseX, mouseY at the end of the draw() function and comparing the performance of that when you comment out the call to point() inside your nested for loops.
Computers aren't magic, so calling the point() function half a million times every second isn't free. You're going to have to decrease that number somehow, either by taking one (or more than one) of the above options, or by refactoring your code in some other way.
How you do that really depends on your actual goals, which you haven't stated. If you're just trying to render this animation, then pre-rendering it will work fine. If you need to have user interaction with it, then maybe something like decreasing the resolution will work. You're going to have to sacrifice something, and it's really up to you what that is.
QPainter graduation(this);
pen.setWidth(2);
pen.setColor(Qt::white);
graduation.setPen(pen);
graduation.setRenderHint(QPainter::HighQualityAntialiasing);
graduation.translate(center.x(), center.y());
double newRadius = (width() - 50) / 2;
//qreal angleStep = 270 / m_stepsize;
for (int i = 0; i <= m_stepsize; i++)
{
graduation.save();
graduation.rotate(i * angleStep + 135);
graduation.drawLine(newRadius - 8, 0, newRadius, 0);
graduation.drawText(newRadius - 30, 0, "100");
graduation.restore();
}
I used code above to draw numbers on clock. Here is what i get
But i want to draw numbers to look like the image below. It must not be upside down.
Can anyone help me. I understand about rotate function that's is the reason its happen to the numbers, but i can not figure it out how to fix it.
You can calculate the position manually and draw the text unrotated:
for (int i = 0; i <= m_stepsize; i++)
{
graduation.save();
graduation.rotate(i * angleStep + 135);
graduation.drawLine(newRadius - 8, 0, newRadius, 0);
graduation.restore();
double xpos=(newRadius - 30)*cos((i * angleStep + 135.)/360.*2.*3.14159);
double ypos=(newRadius - 30)*sin((i * angleStep + 135.)/360.*2.*3.14159);
graduation.drawText(xpos, ypos, "100");
}
so this is my first post ever on asking a question about programming, so please be patient :)
For a little project in school I made a little physics class, handling collision. Although it worked out fine I still have a bug I couldn't figure out after some hours of searching and I still don't really know where the problem lies in.
For the implementation we used the on Java based language Processing which is used for an introduction to programming and prototyping.
With the a left mouseclick I can spawn some balls which collide pixel-wise with a certain color on the screen. When colliding with a 90 degree corner they just fall through the obstacle. Sadly I can't post a screenshot because of my lack in reputation.
So my question is about what the problem is. Someone I asked said it could be a problem with the dot product I use for calculating the new mirrored velocity, but I couldn't find anything in that direction. I suspect the error lies somewhere in the part where the new velocity is calculated, in the update method of the PhysicsEntity class.
So thanks to everyone who is answering, I am grateful for every useful hint :)
Here is my code, it consists of three classes. I am going to post everything so you can run the code yourself. If you don't have processing you'll need to download it from http://processing.org/ in order to run the code sample below.
Main.pde NOTE: This part is only an example for using my physics class.
ArrayList<PhysicsEntity> entities = new ArrayList<PhysicsEntity>();
boolean mouseClicked = false;
boolean paused = false;
void setup()
{
size(800, 600);
background(0);
frameRate(60);
}
void draw()
{
if (!paused)
{
clear();
float gameTime = 1 / frameRate;
loadPixels();
for (int x = 0; x < width; ++x)
{
for (int y = height - 100; y < height; ++y)
{
pixels[x + y * width] = color(0, 200, 0, 128);
}
}
for (int x = 0; x < width; ++x)
{
for (int y = 0; y < 20; ++y)
{
pixels[x + y * width] = color(0, 200, 0, 128);
}
}
for (int x = 0; x < 100; ++x)
{
for (int y = 0; y < height; ++y)
{
pixels[x + y * width] = color(0, 200, 0, 128);
}
}
for (int x = width - 100; x < width; ++x)
{
for (int y = 0; y < height; ++y)
{
pixels[x + y * width] = color(0, 200, 0, 128);
}
}
updatePixels();
if (mousePressed)
{
entities.add(new PhysicsEntity(new Vector2(width / 2, height / 2), new Vector2(random(-100, 100), random(-100, 100)), new Vector2(0.0f, 250.0f)));
}
for (int i = 0; i < entities.size(); ++i)
{
entities.get(i).update(gameTime);
entities.get(i).show();
}
}
}
Vector2.pde NOTE: This class is just necessary for calculting things in the physics class.
class Vector2
{
float a;
float b;
Vector2()
{
a = 0.0f;
b = 0.0f;
}
Vector2(float _a, float _b)
{
a = _a;
b = _b;
}
/* Return exact copy of the vector */
Vector2 Copy()
{
return new Vector2(a, b);
}
Vector2 Add(Vector2 vecB)
{
return new Vector2(a + vecB.a, b + vecB.b);
}
Vector2 Substract(Vector2 vecB)
{
return new Vector2(a - vecB.a, b - vecB.b);
}
/* Scale the vector by a scalar x */
Vector2 Scale(float x)
{
return new Vector2(a * x, b * x);
}
Vector2 Divide(float x)
{
return new Vector2(a / x, b / x);
}
float Dot(Vector2 vecB)
{
return (a * vecB.a + b * vecB.b);
}
float SqrLength()
{
return (pow(a, 2) + pow(b, 2));
}
float Length()
{
return sqrt(SqrLength());
}
boolean Equals(Vector2 vecB)
{
return (a != vecB.a || b != vecB.b) ? false : true;
}
}
Vector2 ZeroVector()
{
return new Vector2(0.0f, 0.0f);
}
PhysicsEntity.pde NOTE: That's the class where actually failed.
class PhysicsEntity
{
Vector2 m_Pos;
Vector2 m_PrevPos;
Vector2 m_Vel;
Vector2 m_Acc;
/* bouncyness in case of collision; gets multiplied with the velocity */
float m_fBouncyness = 1.0f;
color collisionKey = color(0, 200, 0, 128);
public PhysicsEntity(Vector2 _pos, Vector2 _vel, Vector2 _acc)
{
if (_vel == null)
_vel = new Vector2(0.0f, 0.0f);
m_Pos = new Vector2(_pos.a, _pos.b);
m_PrevPos = m_Pos;
m_Vel = _vel;
m_Acc = _acc;
}
public void update(float dt)
{
/* Euler Integration more accurate Version */
/* x = x + vt + 0.5*at^2 */
m_Pos = m_Pos.Add(m_Vel.Scale(dt)).Add(m_Acc.Scale(pow(dt, 2)).Scale(0.5));
/* v = v + at */
m_Vel = m_Vel.Add(m_Acc.Scale(dt));
/* Collision based on color key */
if (isCollidable(m_Pos.a, m_Pos.b, collisionKey))
{
float speed = m_Vel.Length();
if (speed > 0.0f)
{
/* normalized vector of velocity */
Vector2 velNorm = m_Vel.Divide(speed);
/* getting the floor normal */
Vector2 floorNorm = interp(m_Pos, m_PrevPos);
if (!floorNorm.Equals(ZeroVector()))
{
/* mirror velocity on floor normal vector */
/* C = A - (2 * B * (A dot B)) where A is original vector, B the mirror, C result. */
Vector2 mirVel = velNorm.Substract(floorNorm.Scale(2.0f).Scale(velNorm.Dot(floorNorm)));
/* caculate new velocity */
m_Vel = mirVel.Scale(speed).Scale(m_fBouncyness);
/* add to position to move out of collision */
m_Pos = m_Pos.Add(m_Vel.Scale(dt));
}
}
}
m_PrevPos = m_Pos;
}
public void show()
{
ellipse(m_Pos.a, m_Pos.b, 10, 10);
}
public Vector2 interp(Vector2 pos, Vector2 PrevPos)
{
/* Vector from previous position to current position */
Vector2 line = pos.Substract(PrevPos);
float iLength = line.Length();
Vector2 lineFraction = ZeroVector();
/* checks if there the is vectorlength greater zero that connects the current and the previous position */
if (iLength > 0.0f)
lineFraction = line.Divide(iLength);
/* loop from through positions between previous position and current position */
for (int i = 0; i <= iLength; ++i)
{
Vector2 normVec = getNormal(PrevPos.Add(lineFraction.Scale(i)), collisionKey);
if (!normVec.Equals(ZeroVector()))
return normVec;
}
return ZeroVector();
}
}
/* returns normal vector of a 2d landscape in a certain area */
public Vector2 getNormal(Vector2 pos, color col)
{
int area = 10;
/* prevent coordinates from being out of the window */
if (pos.a <= area || pos.a >= width - area || pos.b <= area || pos.b >= height - area)
return ZeroVector();
Vector2 avg = new Vector2();
float loops = 0;
/* loop through an area of pixels */
for (int x = -area; x <= area; ++x)
{
for (int y = -area; y <= area; ++y)
{
if (x*x + y*y <= area*area)
{
float sumX = pos.a + float(x);
float sumY = pos.b + float(y);
/* count collidable pixels in area */
if (isCollidable(sumX, sumY, col))
{
/* add up positions of these pixels */
avg.a += sumX;
avg.b += sumY;
++loops;
}
}
}
}
if (loops == 0)
return ZeroVector();
/* calculate average position */
avg = avg.Divide(loops);
/* calculate length of the vector from initial position to average position */
float avgLength = dist(avg.a, avg.b, pos.a, pos.b);
/* check if avgLenth is zero or in other words: if avg is equals to pos */
if (avgLength == 0.0f)
return ZeroVector();
/* calculate vector(connection vector) from initial position to average position */
Vector2 conVec = pos.Substract(avg);
/* return normalized connection vector */
return conVec.Divide(avgLength);
}
/* method to check if pixel on a certain position is collidable */
public boolean isCollidable(float pixelX, float pixelY, color col)
{
if (pixelX >= width || pixelX < 0 || pixelY >= height || pixelY < 0)
return false;
return pixels[int(pixelX) + int(pixelY) * width] == col;
}
Edit1:
So thanks to the friendly first replay I stripped my code by a few lines :) If there is still a problem with my post let me know!
I cant analyze correctness of your whole physic calculation but in my opinion problem is with calculation of new velocity and :
/* caculate new velocity */
m_Vel = mirVel.Scale(speed).Scale(m_fBouncyness);
/* add to position to move out of collision */
m_Pos = m_Pos.Add(m_Vel.Scale(dt));
Because if you change m_fBouncyness to real value simulating some gravitation (0.8f or less) your problem will never occur but if you change it to some unreal value like 2.0f you will lose all your balls after few bounces.
This indicate problem in algorithm. Your approach consist (in simple) of this steps in loop:
update position of ball
calculate new position
correct position depending on bounce
draw ball
Here can be problem because you calculate new position of ball - this position is out of black box so you calculate average position then new velocity and correct new position. Then draw ball and repeat but what if this new position is also out of the black box? This ball will bounce out of border ... this happens in corner because of calculation of average position (in corner you got far away from black box then at classic border (when you set m_fBouncyness to some bigger value this will happen even on normal border not only in corner!))
Hope this could help you to find your problem.
So finally I've got a solution.
It appears that the answer of Majlik was very helpful. According to his answer I did a few changes which I will explain now.
First of all I put the if-statement if (speed > 0.0f) way up, over the whole movement code so nothing happens anymore if the speed is too low. Of course you can define a certain treshold which works for you.
In addition to that I introduced an else-case, for the if(colliding) statement, in which the movement code is handled, so if the ball is currently colliding it doesn't move at all apart from the collision handling code.
Finally I thought of a new way to move the ball out of the collision. The suggestion of Maljik proved to be right. My previous method didn't move the ball out of the collision at all.
For that I made a while loop which loops as long as the ball is still in collision. In every runthrough the ball gets moved by a normalized vector with the same direction as my mirrored velocity vector. For safety reasons I still got an iterator incrementing every time, so it doesn't end in an infinite loop.
After all the solution was very obvious. But thanks to those who answered.
Below the new changed code:
public void update(float dt)
{
float speed = m_Vel.Length();
if (speed > 0.0f)
{
/* Collision based on color key */
if (isCollidable(m_Pos.a, m_Pos.b, collisionKey))
{
/* normalized vector of velocity */
Vector2 velNorm = m_Vel.Divide(speed);
/* getting the floor normal */
Vector2 floorNorm = interp(m_Pos, m_PrevPos);
if (!floorNorm.Equals(ZeroVector()))
{
/* mirror velocity on floor normal vector */
/* C = A - (2 * B * (A dot B)) where A is original vector, B the mirror, C result. */
Vector2 mirVel = velNorm.Substract(floorNorm.Scale(2.0f).Scale(velNorm.Dot(floorNorm)));
/* caculate new velocity */
m_Vel = mirVel.Scale(speed).Scale(m_fBouncyness);
int it = 0;
Vector2 normMirVel = mirVel.Divide(mirVel.Length());
while (isCollidable(m_Pos.a, m_Pos.b, collisionKey) && it < 100)
{
/* add to position to move out of collision */
m_Pos = m_Pos.Add(normMirVel);
++it;
}
}
}
else
{
/* Euler Integration more accurate Version */
/* x = x + vt + 0.5*at^2 */
m_Pos = m_Pos.Add(m_Vel.Scale(dt)).Add(m_Acc.Scale(pow(dt, 2)).Scale(0.5));
/* v = v + at */
m_Vel = m_Vel.Add(m_Acc.Scale(dt));
}
}
m_PrevPos = m_Pos;
}
Edit: I might that this is not an ideal soluation since the ball gets moved further than it should in this frame. Maybe you should only calculate the necessary distance to move out of collision and add the actual velocity step by step. Also you could compare the current velocity direction to the direction where it should go. If it's already moving in the right direction there is no interference needed.