I'm experimenting with OpenGL 3.2+ and have starting loading Obj files/models in 3D and trying to interact with them.
(following tutorials from sources like this site)
I was wondering what the easiest way (if it's possible) to set up collision detection between two existing(loaded) Obj objects/Models without using third party physics engines etc?
The easiest possible algorithm that can meet your criteria detects collision between spheres, that concludes your meshes. Here you can see the implementation example.
Simplest collision model is to use bounding boxes for collision. The principle is simple: You surround your object by a box defined by two points, minimum and maximum. You then use these points to determine whether two boxes intersect.
In my engine the structure of bounding box and collision-detection method are set as this:
typedef struct BoundingBox
{
Vector3 min; //Contains lowest corner of the box
Vector3 max; //Contains highest corner of the box
} AABB;
//True if collision is detected, false otherwise
bool detectCollision( BoundingBox a, BoundingBox b )
{
return (a.min <= b.max && b.min <= a.max);
}
Other simple method is to use spheres. This method is useful for objects that are of similar size in all dimensions but it creates lots of false collisions if they are not. In this method, you surround your object by sphere with radius radius and center position position and when it comes to the collision, you simply check whether the distance between centers is smaller than sum of the radii and that case two spheres intersect.
Again, code snippet from my engine:
struct Sphere
{
Vector3 position; //Center of the sphere
float radius; //Radius of the sphere
};
bool inf::physics::detectCollision( Sphere a, Sphere b )
{
Vector3 tmp = a.position - b.position; //Distance between centers
return (Dot(tmp, tmp) <= pow((a.radius + b.radius), 2));
}
In code above Dot() computes the dot product of two vectors, if you dot vector with itself it gives you (by definition) the magnitude of the vector squared. Notice how I am actually not square-rooting to get the actual distances and I am comparing the squares instead to avoid extra computations.
You should also be aware that neither of these methods are perfect and will give you false collision detection (unless the objects are perfect boxes or spheres) from time to time but that is the trade-off of the simple implementation and computation complexity. Nevertheless it is good way to start detecting collisions.
Related
I have a Boost Polygon made like this :
Polygon2D create_polygon(Point2D const& p1, Point2D const& p2, Point2D const& p3, Point2D const& p4) {
return {{p1, p2, p3, p4, p1}};
}
int main() {
auto const& polygon = create_polygon({0., 0.}, {0., 4.}, {7., 4.}, {7., 0.});
return 0;
}
(not exactly my code but really similar and a lot more simple so i think it's better to understand).
And basically, i want to divide my polygon into regions and get a random coordinate (x & y) from each region (or just select specific regions).
Something like this :
Of course i know it's not going to be square, because a polygon is not everytime simple like this.
Do boost c++ have a specific "algorithm" or tool used to divide a Polygon into areas without impacting the whole Polygon ?
I have read that voronoi can do something similar to that, but when i'm looking to the example (https://www.boost.org/doc/libs/1_59_0/libs/polygon/doc/voronoi_main.htm) it's not really looking good for my problem.
Or maybe another "famous" algorithm can do something similar without the use of boost c++ ?
The requirement about regions are :
We don't need a specific numbers of regions. The polygon can change size and form so it's more simple without "limits".
If we can have regions with equal areas, it's better (but not mandatory, if an algorithm exists without a perfect equality, but a good repartition of areas, it's ok for me).
If you only want to use the subdivision to get the random points in your polygon, you can avoid that by combining the idea of marching squares with Monte Carlo:
Take the bounding box of your polygon and divide it into squares of equal size.
For each square, determine if it is wholly or partially inside the polygon.
Generate random points inside each square until you find one inside the polygon.
I have a working class that generates regular polygons given: polygon center and polygon radius and number of sides. Implementation details of the two private member functions here.
The class interface looks like this:
class RegularPolygon: public Closed_polyline{
public:
RegularPolygon(Point c, int r, int n)
: center(c), radius(r), sidesNumber(n)
{ generatePoly(); }
private:
Point center;
int radius;
int sidesNumber;
void generatePoly();
void rotateCoordinate(Point& axisOfRotation, Point& initial,
double angRads, int numberOfRotations);
};
Problem:
I am asked to implement a second way of generating regular polygons by using
a set of coordinates1. The constructor needs firstly to perform a validity check of the passed coordinates:
RegularPolygon(vector<Point>& vertices)
:center(), radius(), sideNumber()
{
// validity check of the elements of vertices
}
My initial thought is to:
Check if each pair of coordinates produces the same side length.
Check for each lines'(generated by a pair of coordinates) relative orientation. (they should be at an angle 360/polygon sides, from each other)
Question:
How could I check if all lines are properly oriented, i.e. their relative orientation? solved
Is there any standard algorithm that can determine if a set of coordinates are vertices of a regular polygon?
Note:
After checking [1] and all the question and answers regarding generating coordinates. I didn't found what I'm searching for.
1 In clockwise sequence, passed with the vector: vertices
All the additional files for compilation could be found: here. The FLTK could be found here.
Your task would be a lot simpler if you could find the center of your polygon. Then you would be able to check the distance from that center to each vertex to verify the placement of the vertices on the circle, and also to check the angles from the center to each individual vertex.
Fortunately, there is an easy formula for finding the center of a polygon: all you need to do is averaging the coordinates in both dimensions. With the center coordinates in hand, verify that
The distance from the center to each vertex is the same, and
The angle between consecutive vertices is the same, and that angle is equal to 2π/N radians
These two checks are sufficient to ensure that you have a regular polygon. You do not need to check the distances between consecutive vertices.
I have been working on Unigine and been trying to code a flight program for weeks, I need to find the direction between two dummy nodes so I can use this direction to rotate the wings of the aircraft. Any explanation would be appreciated.
First you have to calculate the length of the distance between P1 and P2.
distance = abs(P2(y) - P1(y))
Then you can use the angular functions to calculate the angle.
a = sin(distance / length(P12))
As already stated in the comments, the vector from P1 to P2 is given by P = P2 - P1.
The direction can be attained in two ways.
1. Directly compute angle = tan_inverse( P.y() / P.x() ).
In this method however, 1st quadrant and 3rd quadrant are treated in the same way as the signs cancel out.
2.You can normalize this vector to get a unit vector. This is the preferred way since it alleviates the quadrant issues.
P(normalized) = P / (mod(p))
Now you can get the projection of any vector in this direction by just calculating the dot-product by this unit vector.
I just randomly came across this question and therefore it might be useful for someone else to read some more useful information here, regardless of the fact that this question has been asked years ago.
Currently, there is no accepted answer, which could mean that it wasn't very clear what the OP was asking so I'll confront two problems here.
Finding the direction of a vector
I am not very fluent in C++ so I'll
go one abstraction below and write C. Consider the following function
double get_vector_direction (vector v)
{
return atan2(v.q.y - v.p.y, v.q.x - v.p.x); /* atan(ratio) */
}
As simple as this! Also, I like to define vectors this way:
typedef struct POINT { double x, y; } point;
typedef struct VECTOR { point p, q; } vector;
the atan family of functions returns the inverse tangent and this function returns the direction of a vector, which is the measure of the angle it makes with a horizontal line (in radians).
There is a diagram in the answers here that shows the horizontal line as the x component of a vector. It's a simplistic implementation of a Cartesian to Polar coordinates conversion.
Finding the distance between the initial and terminal point
You may also want to know the magnitude of the vector, which could be obtained using the distance formula: sqrt(pow(v.q.x-v.p.x, 2)+pow(v.q.y-v.p.y, 2));
The two functions make up direction() and distance() which are the two most essential functions when dealing with algebra during game development. I would also recommend vectoradd and maybe even vectorsub and of course, radtodeg to convert radians to degrees if the angle is to be showed to the player.
If under the direction you mean angle w.r.t. an arbitrary vector (let it be (p1,p3)), then you can calculate the angle using:
angle = arcos( (p1,p2) * (p1,p3) / (modulus((p1,p2)) * modulus((p1,p3)) ))
where * is the dot product. The angle will be in radians. To change it to degrees you can multiply it by 180/PI (PI=3.1415926...). Modulus is length of vector:
modulus((p1,p2))=square root((p1,p2) * (p1,p2)).
The answer is rather about math than C++ but the implementation of the simple formula is straightforward.
I'm currently working on a private project which depends on some operations on polygons using the Boost C++ Libraries.
I'm currently trying to work with the inner polygon/negative polygon concept.
What I need to do now is to join three polygons where two of them have a positive (counterclockwise) outer polygon and an negative (clockwise) inner polygon.
The third one is a negative polygon a new polygon object with a negative area - points in clockwise direction. And this is the point where I'm not fully sure how to handle the situation.
Here's a picture of those three polygons. The middle one which connects the left upper polygon with the right lower one is the negative one.
Now what I would like to do is to join all three polygons through the union function.
What I expect union to do is to cut away the positive parts of the polygons 1 and 3 (the positive polygons) and return the remaining two polygons of 1 and 3.
What I actually get are my polygons 1 and 3 untouched as there would be no negative polygon 2.
Any help will be appreciated.
Edit:
What I need to get is a vector not a bitmap or a picture or whatever.
These Picture are just used to better visualize what I have and what I need.
Those three Polygons are actually not more than an vector of x and y points.
Here's a picture of what I would expect to be the correct result of union of all three polygons:
Edit2: Corrected the result
How do you want unions to work? Usually a union of polygons 1 and 2 would result in polygon 3, but I suspect for your use case you want it to result in polygon 4. If that's the case, you can simply do a union of all the clockwise paths, then do a union of the counterclockwise paths, then take the difference of the former from the latter. If you want the union to result in polygon 3, then I don't think there's a consistent way to do what you want.
Good plan is to consider your polygons as a bitmap (of booleans):
Every polygon will be blit to a bitmap of type (R,R)->bool. Once it's in bitmap format, negative polygons are just andnot-operations on the booleans:
class Bitmap { virtual bool Map(float x, float y) const=0; };
class AndNot : public Bitmap {
public:
AndNot(Bitmap &bm1, Bitmap &bm2) : bm1(bm1), bm2(bm2) { }
bool Map(float x, float y) const {
return b1.Map(x,y) && !b2.Map(x,y);
}
private:
Bitmap &bm1, &bm2;
};
EDIT: I reformulate the question simply:
How do I generate in C++ or Python, random points (x,y) following: a circular distribution, a square distribution, and a triangular distribution.
This is a simple code for square for example:
def generateSquare(min, max, size):
data = []
for i in range(size):
x = randint(min, max)
y = randint(min, max)
data += [[x, y]]
return data
First of all, instead of storing your coordinates in a vector, you would be better off using std::pair or a custom class:
struct Point
{
int x;
int y;
};
Then you just need to have a way of generating random points, such as
Point randomPoint(Point const & min, Point const & max)
{
static std::mt19937 gen;
std::uniform_int_distribution<> distribX(min.x, max.x);
std::uniform_int_distribution<> distribY(min.y, max.y);
return Point{distribX(gen), distribY(gen)};
}
You can then use this generation function to fill your vector, for instance with generate_n:
unsigned int const nbPoints = 100;
std::vector<Point> points;
std::generate_n(back_inserter(points), nbPoints,
std::bind(randomPoint, Point{0, 0}, Point{1000, 1000}));
Note that this will generate random points, so you are not guaranteed to end up with a square, a triangle, etc. If you want to generate a could, you could either use a non-uniform distribution (if you know what distribution your coordinates follow) to generate your numbers, or use rejection sampling to discard points that are not in the area you want them to be.
Generating a triangle boils down to drawing three random points.
To generate a square, you can draw two points, corresponding to two opposite corners of the square.
And so on... I don't think there is a "universal" solution that would work for any shapes.
As supplement to Luc Touraille's post.
For a square find two random points and let these two points be the two furhest apart corners of the square.
For a triangle find three random points and let the triangle be triangle these three points make.
For a circle find a random point as a center for the circle and another random point, and let the distance between the two be the radius of the circle.
A more general approach could be to find the center point of the figures and let the parameters (scale, rotation, etc.) be found by further randomly generated numbers. (I guess a bit like Rook suggests).
Your problem is underspecified.
There is no such thing as a "circular distribution" or "triangular distribution".
You probably meant: a uniform distribution in the shape of a circle, rectangle, triangle.
There even is no uniquely specified triangle...
The key point is uniform.
E.g. a standard normal distribution in 2D may appear to be somewhat circular, but it is not exactly the shape of a circle.
There is no random generator that directly produces a circle with uniform density; at least not that I know of. The most common way is just to generate a square, and reject those points that you do not want to have.
E.g. generate (x,y) pairs on [0:1]x[0:1] and reject those with distance from .5,.5 larger than .5 - then you get the circle.
If you - as other users suggested - generate a radius and a distance, then the generated points will not be uniformly distributed on the circle.