OpenGL-How do I draw randomly non-overlapping circle - c++

I've already draw few random placed circle, but I want different numbers of circles every time I run the program. So the question really is how do I call a function in random times?
I also need them to have convex and concave effects but unable to arrange them to random circles.
Finally, I need circles not to overlap, how do I do that?
Below is my partial code so far.
void circle(){
double r=50;
int dx, dy;
dx=rand()%350;
dy=rand()%250;
glLineWidth(1);
glEnable(GL_LINE_SMOOTH);
glBegin(GL_LINES);
double i=1.0;
double j=0.0;
for (double y=r; y>=-r; y=y-1) {
i=i-0.01;
j=j+0.01;
//glColor3f(i, i, i);
glColor3f(j, j, j);
glVertex2f(-sqrt(r*r-y*y)+dx, y+dy);
glVertex2f(sqrt(r*r-y*y)+dx, y+dy);
}
glEnd();
}
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
srand((unsigned)time(0));
circle();
circle();
circle();
glEnd();
glFlush();
}

The simple approach
It is enough to pick a random number and iterate. This can cause the circles to overlap.
int min_circles = 10;
int max_circles = 100;
int amount = min_circles + rand()%(max_circles-min_circles+1);
for (int i = 0; i < amount; i++)
circle();
Non overlapping
This is not a trivial matter and has been an interesting research topic. You can have several approaches to this problem for example:
Naïve Generation
Store all previously added circle positions and if you try to add a new one just do a check with the previous for overlapping. If it overlaps choose another position. If it fails several times in a row then stop.
Easing
You can also consider treating all circles as a system of points connected with springs and iterate a few times so that the springs will repel the circles from each other thus conforming to the non-overlapping rule.
Poisson Disk Sampling
You can read up on implementing Poisson Disk Sampling on the internet. The algorithm generates a uniform random distribution of points on a plane so that they are at certain distance from each other. Then just use these points as centers of circles.

how do I call a function in random times?
that one way of doing it:
if (rand() % someNumber == 0)
callFunc();
I also need them to have convex and concave effects but unable to arrange them to random circles.
i didnt understand what you mean.
Finally, I need circles not to overlap, how do I do that?
first you need to creaye circles in a structure, and store them in a collection. assume you the structure like that:
struct Circle {
float x, y, raduis;
}
and a collection like that:
std::vector<Circle> circles;
then the creation may look like that:
Circle c;
do {
bool canExit = true;
c.x = rand()*350;
c.y = rand()*250;
c.radius = 50;
for (int i = 0; i < circles.size(); i++) {
float dx = (circles[i].x - c.x);
float dy = (circles[i].y - c.y);
floar radii = circles[i].radius + c.radius;
if (dx*dx + dy*dy < (radii*radii) ) {
canExit = false;
break;
}
}
while(canExit == false);
circles.push_back(c);
of cours thats only may way, hope it works for you, and good luck.

Related

cocos2dx detect intersection with polygon sprite

I am using cocos2d-x 3.8.
I try to create two polygon sprites with the following code.
I know we can detect intersect with BoundingBox but is too rough.
Also, I know we can use Cocos2d-x C++ Physics engine to detect collisions but doesn't it waste a lot of resource of the mobile device? The game I am developing does not need physics engine.
is there a way to detect the intersect of polygon sprites?
Thank you.
auto pinfoTree = AutoPolygon::generatePolygon("Tree.png");
auto treeSprite= Sprite::create(pinfoTree);
treeSprite-> setPosition(width / 4 * 3 - 30 , height / 2 - 200);
this->addChild(treeSprite);
auto pinfoBird = AutoPolygon::generatePolygon("Bird.png");
auto Bird= Sprite::create(pinfoTree);
Bird->setPosition(width / 4 * 3, height / 2);
this->addChild(Bird)
This is a bit more complicated: AutoPolygon gives you a bunch of triangles - the PhysicsBody::createPolygon requires a convex polygon with clockwise winding… so these are 2 different things. The vertex count might even be limited. I think Box2d’s maximum count for 1 polygon is 8.
If you want to try this you’ll have to merge the triangles to form polygons. An option would be to start with one triangle and add more as long as the whole thing stays convex. If you can’t add any more triangles start a new polygon. Add all the polygons as PhysicsShapes to your physics body to form a compound object.
I would propose that you don’t follow this path because
Autopolygon is optimized for rendering - not for best fitting
physics - that is a difference. A polygon traced with Autopolygon will always be bigger than the original sprite - Otherwise you would see rendering artifacts.
You have close to no control over the generated polygons
Tracing the shape in the app will increase your startup time
Triangle meshes and physics outlines are 2 different things
I would try some different approach: Generate the collision shapes offline. This gives you a bunch of advantages:
You can generate and tweak the polygons in a visual editor e.g. by
using PhysicsEditor
Loading the prepares polygons is way faster
You can set additional parameters like mass etc
The solution is battle proven and works out of the box
But if you want to know how polygon intersect work. You can look at this code.
// Calculate the projection of a polygon on an axis
// and returns it as a [min, max] interval
public void ProjectPolygon(Vector axis, Polygon polygon, ref float min, ref float max) {
// To project a point on an axis use the dot product
float dotProduct = axis.DotProduct(polygon.Points[0]);
min = dotProduct;
max = dotProduct;
for (int i = 0; i < polygon.Points.Count; i++) {
flaot d = polygon.Points[i].DotProduct(axis);
if (d < min) {
min = dotProduct;
} else {
if (dotProduct> max) {
max = dotProduct;
}
}
}
}
// Calculate the distance between [minA, maxA] and [minB, maxB]
// The distance will be negative if the intervals overlap
public float IntervalDistance(float minA, float maxA, float minB, float maxB) {
if (minA < minB) {
return minB - maxA;
} else {
return minA - maxB;
}
}
// Check if polygon A is going to collide with polygon B.
public boolean PolygonCollision(Polygon polygonA, Polygon polygonB) {
boolean result = true;
int edgeCountA = polygonA.Edges.Count;
int edgeCountB = polygonB.Edges.Count;
float minIntervalDistance = float.PositiveInfinity;
Vector edge;
// Loop through all the edges of both polygons
for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) {
if (edgeIndex < edgeCountA) {
edge = polygonA.Edges[edgeIndex];
} else {
edge = polygonB.Edges[edgeIndex - edgeCountA];
}
// ===== Find if the polygons are currently intersecting =====
// Find the axis perpendicular to the current edge
Vector axis = new Vector(-edge.Y, edge.X);
axis.Normalize();
// Find the projection of the polygon on the current axis
float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
ProjectPolygon(axis, polygonA, ref minA, ref maxA);
ProjectPolygon(axis, polygonB, ref minB, ref maxB);
// Check if the polygon projections are currentlty intersecting
if (IntervalDistance(minA, maxA, minB, maxB) > 0)
result = false;
return result;
}
}
The function can be used this way
boolean result = PolygonCollision(polygonA, polygonB);
I once had to program a collision detection algorithm where a ball was to collide with a rotating polygon obstacle. In my case the obstacles where arcs with certain thickness. and where moving around an origin. Basically it was rotating in an orbit. The ball was also rotating around an orbit about the same origin. It can move between orbits. To check the collision I had to just check if the balls angle with respect to the origin was between the lower and upper bound angles of the arc obstacle and check if the ball and the obstacle where in the same orbit.
In other words I used the various constrains and properties of the objects involved in the collision to make it more efficient. So use properties of your objects to cause the collision. Try using a similar approach depending on your objects

Closed Bezier curve

I implemented a Bezier curve drawing function like this:
Vector Bezier(float t)
{
Vector rt(0,0);
int n = length-1;
for(int i=0;i<length;i++)
{
float Bi = 1;
for(int j = 1;j<=i;j++)
{
Bi *= (float) (n-j+1)/j;
}
Bi *= pow(t,i) * pow(1-t, n-i);
rt = rt + (Cpoints[i] * Bi);
}
return rt;
}
void drawBezier()
{
int segments = 100;
glBegin( GL_LINE_STRIP );
for(int i=0;i<segments;i++)
{
float t = (float) i / segments;
Vector p = Bezier(t);
glVertex2f(p.x, p.y);
}
glEnd( );
}
CPoints is an array containing the coordinates of the Control Points, length is the number of Control Points. The question is, how do I make it a closed Bezier curve, like this:
Simply use an additional segment that connects the last endpoint to the first (ex: duplicating the first control point).
A single bezier spline segment, whether it's cubic or quadratic or quartic, can't represent that kind of closed shape. Yet multiple segments can.
So you typically don't want to modify your multi-segment curve drawing function, per se, but rather the control points you feed into it. Although you could modify the drawing function to accept a flag to draw a closing segment, it's probably easier is to just think of it as a problem associated with the control points/curve segments you provide as input.

Marching Cubes Issues

I've been trying to implement the marching cubes algorithm with C++ and Qt. Anyway, so far all the steps have been written, but I'm getting a really bad result. I'm looking for orientation or advices about what can be going wrong. I suspect one of the problems may be with the voxel conception, specifically about which vertex goes in which corner (0, 1, ..., 7). Also, I'm not a 100% sure about how to interpret the input for the algorithm (I'm using datasets). Should I read it in the ZYX order and move the marching cube in the same way or it doesn't matter at all? (Leaving aside the fact that no every dimension has to have the same size).
Here is what I'm getting against what it should look like...
http://i57.tinypic.com/2nb7g46.jpg
http://en.wikipedia.org/wiki/Marching_cubes
http://en.wikipedia.org/wiki/Marching_cubes#External_links
Paul Bourke. "Overview and source code".
http://paulbourke.net/geometry/polygonise/
Qt_MARCHING_CUBES.zip: Qt/OpenGL example courtesy Dr. Klaus Miltenberger.
http://paulbourke.net/geometry/polygonise/Qt_MARCHING_CUBES.zip
The example requires boost, but looks like it probably should work.
In his example, it has in marchingcubes.cpp, a few different methods for calculating the marching cubes: vMarchCube1 and vMarchCube2.
In the comments it says vMarchCube2 performs the Marching Tetrahedrons algorithm on a single cube by making six calls to vMarchTetrahedron.
Below is the source for the first one vMarchCube1:
//vMarchCube1 performs the Marching Cubes algorithm on a single cube
GLvoid GL_Widget::vMarchCube1(const GLfloat &fX, const GLfloat &fY, const GLfloat &fZ, const GLfloat &fScale, const GLfloat &fTv)
{
GLint iCorner, iVertex, iVertexTest, iEdge, iTriangle, iFlagIndex, iEdgeFlags;
GLfloat fOffset;
GLvector sColor;
GLfloat afCubeValue[8];
GLvector asEdgeVertex[12];
GLvector asEdgeNorm[12];
//Make a local copy of the values at the cube's corners
for(iVertex = 0; iVertex < 8; iVertex++)
{
afCubeValue[iVertex] = (this->*fSample)(fX + a2fVertexOffset[iVertex][0]*fScale,fY + a2fVertexOffset[iVertex][1]*fScale,fZ + a2fVertexOffset[iVertex][2]*fScale);
}
//Find which vertices are inside of the surface and which are outside
iFlagIndex = 0;
for(iVertexTest = 0; iVertexTest < 8; iVertexTest++)
{
if(afCubeValue[iVertexTest] <= fTv) iFlagIndex |= 1<<iVertexTest;
}
//Find which edges are intersected by the surface
iEdgeFlags = aiCubeEdgeFlags[iFlagIndex];
//If the cube is entirely inside or outside of the surface, then there will be no intersections
if(iEdgeFlags == 0)
{
return;
}
//Find the point of intersection of the surface with each edge
//Then find the normal to the surface at those points
for(iEdge = 0; iEdge < 12; iEdge++)
{
//if there is an intersection on this edge
if(iEdgeFlags & (1<<iEdge))
{
fOffset = fGetOffset(afCubeValue[ a2iEdgeConnection[iEdge][0] ],afCubeValue[ a2iEdgeConnection[iEdge][1] ], fTv);
asEdgeVertex[iEdge].fX = fX + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][0] + fOffset * a2fEdgeDirection[iEdge][0]) * fScale;
asEdgeVertex[iEdge].fY = fY + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][1] + fOffset * a2fEdgeDirection[iEdge][1]) * fScale;
asEdgeVertex[iEdge].fZ = fZ + (a2fVertexOffset[ a2iEdgeConnection[iEdge][0] ][2] + fOffset * a2fEdgeDirection[iEdge][2]) * fScale;
vGetNormal(asEdgeNorm[iEdge], asEdgeVertex[iEdge].fX, asEdgeVertex[iEdge].fY, asEdgeVertex[iEdge].fZ);
}
}
//Draw the triangles that were found. There can be up to five per cube
for(iTriangle = 0; iTriangle < 5; iTriangle++)
{
if(a2iTriangleConnectionTable[iFlagIndex][3*iTriangle] < 0) break;
for(iCorner = 0; iCorner < 3; iCorner++)
{
iVertex = a2iTriangleConnectionTable[iFlagIndex][3*iTriangle+iCorner];
vGetColor(sColor, asEdgeVertex[iVertex], asEdgeNorm[iVertex]);
glColor4f(sColor.fX, sColor.fY, sColor.fZ, 0.6);
glNormal3f(asEdgeNorm[iVertex].fX, asEdgeNorm[iVertex].fY, asEdgeNorm[iVertex].fZ);
glVertex3f(asEdgeVertex[iVertex].fX, asEdgeVertex[iVertex].fY, asEdgeVertex[iVertex].fZ);
}
}
}
UPDATE: Github working example, tested
https://github.com/peteristhegreat/qt-marching-cubes
Hope that helps.
Finally, I found what was wrong.
I use a VBO indexer class to reduce the ammount of duplicated vertices and make the render faster. This class is implemented with a std::map to find and discard already existing vertices, using a tuple of < vec3, unsigned short >. As you may imagine, a marching cubes algorithm generates structures with thousands if not millions of vertices. The highest number a common unsigned short can hold is 65536, or 2^16. So, when the output geometry had more than that, the map index started to overflow and the result was a mess, since it started to overwrite vertices with the new ones. I just changed my implementation to draw with common VBO and not indexed while I fix my class to support millions of vertices.
The result, with some minor vertex normal issues, speaks for itself:
http://i61.tinypic.com/fep2t3.jpg

Circular collision rebound not working properly

I'm writing a little physics simulation in C++ that basically moves circles across the screen and when two circles collide, they should ricochet in the same manner as billiard balls would. When the circles do collide with each other, most of the time they will practically slow down infinitely/they appear to stick to each other and become static. Sometimes only one ball will rebound in the collision and the other will retain it's trajectory. This is just a simple 2D simulation.
So here's what I have for the detection/ricochet logic:
bool Ball::BallCollision(Ball &b2)
{
if (sqrt(pow(b2.x - x, 2) + pow(b2.y - y, 2)) <= b2.radius + radius) // Test for collision
{
normal[0] = (x - (x + b2.x) / 2) / radius; // Finds normal vector from point of collision to radius
normal[1] = (y - (y + b2.y) / 2) / radius;
xvel = xvel - 2 * (xvel * normal[0]) * normal[0]; // Sets the velocity vector to the reflection vector
yvel = yvel - 2 * (yvel * normal[1]) * normal[1];
////x = xprev; // These just move the circle back a 'frame' so the collision
////y = yprev; // detection doesn't detect collision more than once.
// Not sure if working?
}
}
I can't figure out what is wrong with my function. Thanks for any help in advance!
Edit:
Every variable is declared as a float
The functions:
void Ball::Move()
{
xprev = x;
yprev = y;
x += xvel;
y += yvel;
}
void Ball::DrawCircle()
{
glColor3ub(100, 230, 150);
glBegin(GL_POLYGON);
for (int i = 0; i < 10; i++)
{
angle = i * (2*3.1415/10);
newx = x + r*cos(angle);
newy = y + r*sin(angle);
glVertex2f(newx, newy);
}
glEnd();
}
The loop:
run_prev.clear(); // A vector, cleared every loop, that holds the Ball objects that collided
for (int i = 0; i < num_balls; i++)
{
b[i].Move();
}
for (int i = 0; i < num_balls; i++)
{
b[i].WallCollision(); // Just wall collision detecting, that is working just fine
}
//The loop that checks for collisions... Am I executing this properly?
for (int i = 0; i < num_balls; i++)
{
for (int j = 0; j < num_balls; j++)
{
if (i == j) continue;
if (b[i].BallCollision(b[j]) == true)
{
run_prev.push_back(b[i]);
}
}
}
for (int i = 0; i < num_balls; i++)
{
b[i].DrawCircle();
}
//xprev and yprev are the x and y values of the frame before for each circle
for (int i = 0; i < run_prev.size(); i++)
{
run_prev[i].x = run_prev[i].xprev;
run_prev[i].y = run_prev[i].yprev;
}
Makes balls collide (reflect movement vector) only if they're moving towards each other. Do not process collision if they're moving away from each other. Break this rule, and they'll be glued together.
When processing collision, update both balls at once. Do not update one ball at a time.
Your move vector adjustment is incorrect. Balls don't reflect against each other, because they can be moving at different speeds.
Correct movement adjustment (assuming balls have equal mass) should look something like that:
pos1 and pos2 = positions;
v1 and v2 are movement vector (speed);
n is collision normal == normalize(pos1 - pos2);
collisionSpeed = dot((v2-v1), n);
collisionSpeed *= elasticy; (0.0..1.0);
v1 = v1 - dot(v1, n);
v2 = v2 - dot(v2, n);
v1 -= scale(n, collisionSpeed * 0.5);
v2 += scale(n, collisionSpeed * 0.5);
To understand the formula, check newtons law (impulses in particular). Or check Chris Hecker's papers on game physics.
It's not clear how you're calling this function, but I think I see the problem.
Say you have Ball ballA and Ball ballB, which are colliding in the current frame, and then you run ballA.BallCollision(ballB).
This will update the member variables of ballA, and move it back a frame. But it doesn't update the position or trajectory of ballB.
Even if you call the converse as well (ballB.BallCollision(ballA)), it won't detect the collision because when you called ballA.BallCollision(ballB), it moved ballA back a frame.
I haven't looked at your code in detail, but it doesn't take into consideration that this type of collision can only work in center of momentum frames. Now, I assume your balls are of equal masses. What you do is take the average of the two momentums (or velocities since they have the same masses) and subtract that average from the velocities. Perform your calculations, and add the average back. Here is the question I asked that may relate to this.
I know this question is quite old, but it's still relevant, especially to students. Something that wasn't mentioned in the answers made me want to contribute.
One thing that I ran into when solving a similar problem was overlap. That is, if the moving balls overlap by any amount at all, the collision detection will trigger continuously, giving the sticking behavior the OP referred to.
There was an attempt here to prevent this by moving the balls to the previous frame, but that can occasionally fail if the movement was enough that the balls enmeshed more than a single frame can account for, or if the movement velocity is just right so that the frame before doesn't trigger collision but the frame after is too far overlapped.
Since the original check was for center distance less than or equal to the sum of the radii, the detection triggers on both collision AND overlap.
One way to fix this is to separate the test into checking for collision (equals only) or overlap (less than only). For the collision, proceed as normal. But for the overlap condition, you can physically move one ball or the other (or both by half) the amount of overlap. This positions them at correct "collision" position, which allows for the correct behavior of the bounce function.
An overlap function that only moves one ball at a time might look something like this(not real code):
if (distanceBetweenBallCenters < sumOfRadii){
currentPosition = oldPosition - (distanceBetweenBallCenters - sumOfRadii) * (unitVectorFromSecondBallToFirstBall);
}
One could easily move both balls by half, but I found that moving one at a time gave satisfactory results for my uses, and allowed me to keep the parameter as a const.
I hope this helps future students! (I am also a student, and new to this, so take my advice with the proverbial grain of salt)
Your way of calculating the normal is wrong. (x + b2.x)/2 doesn't have to be the point of collision, if the radii of the balls aren't equal.

Polygon to Polygon Collision Detection Issue

I have been having a few issues implementing my narrow phase collision detection. Broadphase is working perfectly.
I have a group of polygons, that have a stl::vector array of points for their vertices in clockwise order. Every cycle, I check to see whether they're colliding.
I have borrowed the following Point in Polygon test from here and changed it using my Point data structures:
int InsidePolygon(std::vector <Point> poly, Point p) {
int i, j, c = 0;
int nvert = poly.size();
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ((poly[i].y> p.y) != (poly[j].y> p.y)) && (p.x < (poly[j].x-poly[i].x) * (p.y-poly[i].y) / (poly[j].y-poly[i].y) + poly[i].x) )
c = !c;
}
return c;
}
I have extended that to include a PolygonPolygon function, which check all the points of 1 polygon against another and then reverse it to check the other way around.
int PolygonPolygon(std::vector <Point> polygon1, std::vector <Point> polygon2) {
for(int i=0; i<polygon1.size();i++) {
if(InsidePolygon(polygon2, polygon1[i])) {
return 1;
}
}
for(int j=0; j<polygon2.size();j++) {
if(InsidePolygon(polygon1, polygon2[j])) {
return 1;
}
}
return 0;
}
The strange thing is that my PolygonPolygon function is always returning 1. So I have a few questions:
Have I screwed up the logic somewhere? Should I write my PolygonPolygon function differently?
Are there any better methods for a PolygonPolygon test, the polygons themselves are not guaranteed to be convex, which is why I went for the point in polygon method. I also hope to determine which point is colliding eventually, if I can get past this bit.
Should I be presenting my points in a particular order for the InsidePolygon test?
You may want to consider trying to draw a line between polygons as an alternative collision detection method.
[edit] Oops, I missed the fact that you have non-convex polys in there too. Maybe "Determining if a point lies on the interior of a polygon" would be better? Either that or you could break your non-convex polygons up into convex polygons first.
Also, there's at least one similar question here on StackOverflow.
Thanks for your help guys! But i've managed to sort it out on my own.
The importance of translating your vertices to world space and rotating them should not be overlooked, especially if you're colliding them.