Finding verticies of a polygon given the number of sides? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to a function that will find all the vertices of a polygon given X number of sides and a radius r. My overall goal is to make a circle but since you can only draw straight lines I will have to make a polygon. So all of the polygons are going to be centred on the point (0,0). And I want to find all the coordinates for a polygon with 6 sides and radius that will iterate from .1 to 1.0. This should form a 10 circles inside of each other.
Here is what I have so far:
Here are my errors:
52:33: error: variable-sized object ‘vertices’ may not be initialized
57:17: error: request for member ‘insert’ in ‘vertices’, which is of non-class type ‘iPoint [(((long unsigned int)(((long int)nVertices) + -0x00000000000000001)) + 1)]’
My goal for the for loop is to get all the coordinates for a single polygon for the given radius and stick them in the verticies array as a 2 dimensional Point (x coordinate and a y coordinate).

I would take Point vertices[nVerticies] = {}; out of the loop (before the for). I would additionally correct verticies to vertices. Also, math functions sin and cos usually work in radians, not degrees. Finally, the angle increment can't be constant but depend (inversely) on nVertices.
Taking all together:
double radius = 0.1;
int nVertices = 6;
double angle = pi()*2/nVertices ;
while(radius <= 1.0)
{
iPoint vertices[nVertices];
for (int i = 0; i < nVertices; i++)
{
double x = 0 + radius * sin(i * angle);
double y = 0 + radius * cos(i * angle);
vertices[i]= iPoint(x,y) ;
}
radius = radius + 0.1;
}

Is there any advice?
The angular distance between two points on a regular flat 2D polygon is 2pi / N
Update due to comment
I'd write it slightly differently.
#include <math.h> // for M_PI
void circle_points(
double const radius,
int const n_points,
std::vector<Point<double>> &out_points )
{
out_points.resize(n_points);
double const angular_distance = M_PI / (double)n_points;
for( int i = 0; i < n_points; i++ ) {
double const x = radius * sin(i * angular_distance);
double const y = radius * cos(i * angular_distance);
out_points[i] = Point<double>(x,y);
}
}
void concentric_circles(
double const radius_start,
double const radius_end,
int const n_circles,
int const n_points_per_circle,
std::vector<std::vector<Point<double>> &out_circles )
{
out_circles.resize(n_circles);
double const radius_increment = (radius_end - radius_start) / n_circles;
for( int i = 0; i < n_circles; i++ ) {
circle_points(
radius_start + radius_increment*i,
n_points_per_circle,
out_circles[i] );
}
}
I'm passing the vectors by reference here to avoid deep copies when entering / leaving the function scopes.

If you would like vertices to be a static array and initialize it , declare 'nVertices' as a macro or const int.
const int nVertices = 6;

Related

perlin noise giving diffrent values for same point after player has moved [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 10 months ago.
Improve this question
I am using perlin noise to generate a map for my game. This is then being drawn using marching squares. The values That are being input for the perlin noise function are relative to a 0,0 coordinate and then this is converted to a position on screen that can then be drawn to.
The problem is that when the player moves the image that is drawn to the screen is slightly different at the edges of the mesh this causes a flickering effect when the player is moving.
asteroids_in_range(player.x-WIDTH/2,player.x+WIDTH/2,player.y-HEIGHT/2,player.y+HEIGHT/2,16);
int get_asteroid_case(float x, float y, float box_size)
{
/*get the case for the box with the bottom left corner
at location x,y and size of box_size*/
int count = 0;
if(perlin.GetValue(x, y, 0.1) > THRESHHOLD)
{
count += 8;
}
if(perlin.GetValue(x+box_size, y, 0.1) > THRESHHOLD)
{
count += 4;
}
if(perlin.GetValue(x+box_size, y+box_size, 0.1) > THRESHHOLD)
{
count += 2;
}
if(perlin.GetValue(x, y+box_size, 0.1) > THRESHHOLD)
{
count += 1;
}
return count;
}
void asteroids_in_range(float xmin, float xmax, float ymin, float ymax, float grid_size)
{
int num;
for(float x = xmin; x <= xmax; x+=grid_size)
{
for(float y = ymin; y <= ymax; y+=grid_size)
{
num = get_asteroid_case(x, y, grid_size);
if(num != 0 && num != 15)
render_asteroids(num,x,y, 1);
}
}
}
Images with the player one pixel apart as can be seen, there are subtle differences on the fringes of the generated meshes.
Your problem is you are getting different noise values because you are getting the noise at different points. Don't do that. Make it the same points - the ones on the grid.
Let's say grid_size is 10 (pixels) and WIDTH is 100 (pixels) and the player is at 0,0. You are getting the noise at -50,-50, and -40,-50, and -30,-50, and so on.
Now say the player moves 3 pixels right. You are getting the noise at -47,-50, and -37,-50, and -27,-50, and so on. Obviously you get different noise values, because you asked for different noise values!
Instead you should round the noise coordinates to the grid - to multiples of grid_size. Your code can easily be adapted by rounding xmin and xmax and ymin and ymax before the grid rendering - for example:
xmin = floor(xmin / grid_size) * grid_size;
xmax = ceil(xmax / grid_size) * grid_size;
// same for y
The min coordinate is rounded down, and the max coordinate is rounded up, to make sure the entire screen is still inside the rendered coordinates.

Perlin Noise getting wrong values in Y axis (C++)

Issue
I'm trying to implement the Perlin Noise algorithm in 2D with a single octave with a size of 16x16. I'm using this as heightmap data for a terrain, however it only seems to work in one axis. Whenever the sample point moves to a new Y section in the Perlin Noise grid, the gradient is very different from what I expect (for example, it often flips from 0.98 to -0.97, which is a very sudden change).
This image shows the staggered terrain in the z direction (which is the y axis in the 2D Perlin Noise grid)
Code
I've put the code that calculates which sample point to use at the end since it's quite long and I believe it's not where the issue is, but essentially I scale down the terrain to match the Perlin Noise grid (16x16) and then sample through all the points.
Gradient At Point
So the code that calculates out the gradient at a sample point is the following:
// Find the gradient at a certain sample point
float PerlinNoise::gradientAt(Vector2 point)
{
// Decimal part of float
float relativeX = point.x - (int)point.x;
float relativeY = point.y - (int)point.y;
Vector2 relativePoint = Vector2(relativeX, relativeY);
vector<float> weights(4);
// Find the weights of the 4 surrounding points
weights = surroundingWeights(point);
float fadeX = fadeFunction(relativePoint.x);
float fadeY = fadeFunction(relativePoint.y);
float lerpA = MathUtils::lerp(weights[0], weights[1], fadeX);
float lerpB = MathUtils::lerp(weights[2], weights[3], fadeX);
float lerpC = MathUtils::lerp(lerpA, lerpB, fadeY);
return lerpC;
}
Surrounding Weights of Point
I believe the issue is somewhere here, in the function that calculates the weights for the 4 surrounding points of a sample point, but I can't seem to figure out what is wrong since all the values seem sensible in the function when stepping through it.
// Find the surrounding weight of a point
vector<float> PerlinNoise::surroundingWeights(Vector2 point){
// Produces correct values
vector<Vector2> surroundingPoints = surroundingPointsOf(point);
vector<float> weights;
for (unsigned i = 0; i < surroundingPoints.size(); ++i) {
// The corner to the sample point
Vector2 cornerToPoint = surroundingPoints[i].toVector(point);
// Getting the seeded vector from the grid
float x = surroundingPoints[i].x;
float y = surroundingPoints[i].y;
Vector2 seededVector = baseGrid[x][y];
// Dot product between the seededVector and corner to the sample point vector
float dotProduct = cornerToPoint.dot(seededVector);
weights.push_back(dotProduct);
}
return weights;
}
OpenGL Setup and Sample Point
Setting up the heightmap and getting the sample point. Variables 'wrongA' and 'wrongA' is an example of when the gradient flips and changes suddenly.
void HeightMap::GenerateRandomTerrain() {
int perlinGridSize = 16;
PerlinNoise perlin_noise = PerlinNoise(perlinGridSize, perlinGridSize);
numVertices = RAW_WIDTH * RAW_HEIGHT;
numIndices = (RAW_WIDTH - 1) * (RAW_HEIGHT - 1) * 6;
vertices = new Vector3[numVertices];
textureCoords = new Vector2[numVertices];
indices = new GLuint[numIndices];
float perlinScale = RAW_HEIGHT/ (float) (perlinGridSize -1);
float height = 50;
float wrongA = perlin_noise.gradientAt(Vector2(0, 68.0f / perlinScale));
float wrongB = perlin_noise.gradientAt(Vector2(0, 69.0f / perlinScale));
for (int x = 0; x < RAW_WIDTH; ++x) {
for (int z = 0; z < RAW_HEIGHT; ++z) {
int offset = (x* RAW_WIDTH) + z;
float xVal = (float)x / perlinScale;
float yVal = (float)z / perlinScale;
float noise = perlin_noise.gradientAt(Vector2( xVal , yVal));
vertices[offset] = Vector3(x * HEIGHTMAP_X, noise * height, z * HEIGHTMAP_Z);
textureCoords[offset] = Vector2(x * HEIGHTMAP_TEX_X, z * HEIGHTMAP_TEX_Z);
}
}
numIndices = 0;
for (int x = 0; x < RAW_WIDTH - 1; ++x) {
for (int z = 0; z < RAW_HEIGHT - 1; ++z) {
int a = (x * (RAW_WIDTH)) + z;
int b = ((x + 1)* (RAW_WIDTH)) + z;
int c = ((x + 1)* (RAW_WIDTH)) + (z + 1);
int d = (x * (RAW_WIDTH)) + (z + 1);
indices[numIndices++] = c;
indices[numIndices++] = b;
indices[numIndices++] = a;
indices[numIndices++] = a;
indices[numIndices++] = d;
indices[numIndices++] = c;
}
}
BufferData();
}
Turned out the issue was in the interpolation stage:
float lerpA = MathUtils::lerp(weights[0], weights[1], fadeX);
float lerpB = MathUtils::lerp(weights[2], weights[3], fadeX);
float lerpC = MathUtils::lerp(lerpA, lerpB, fadeY);
I had the interpolation in the y axis the wrong way around, so it should have been:
lerp(lerpB, lerpA, fadeY)
Instead of:
lerp(lerpA, lerpB, fadeY)

How to aim the camera at the z-index of the cell in front of my character?

I've got a 3D terrain environment like so:
I'm trying to get the character (camera) to look up when climbing hills, and look down when descending, like climbing in real life.
This is what it's currently doing:
Right now the camera moves up and down the hills just fine, but I can't get the camera angle to work correctly. The only way I can think of aiming up or down depending on the terrain is getting the z-index of the cell my character is currently facing, and set that as the focus, but I really have no idea how to do that.
This is admittedly for an assignment, and we're intentionally not using objects so things are organized a little strangely.
Here's how I'm currently doing things:
const int M = 100; // width
const int N = 100; // height
double zHeights[M+1][N+1]; // 2D array containing the z-indexes of terrain cells
double gRX = 1.5; // x position of character
double gRY = 2.5; // y position of character
double gDirection = 45; // direction of character
double gRSpeed = 0.05; // move speed of character
double getZ(double x, double y) // returns the height of the current cell
{
double z = .5*sin(x*.25) + .4*sin(y*.15-.43);
z += sin(x*.45-.7) * cos(y*.315-.31)+.5;
z += sin(x*.15-.97) * sin(y*.35-8.31);
double amplitute = 5;
z *= amplitute;
return z;
}
void generateTerrain()
{
glBegin(GL_QUADS);
for (int i = 0; i <= M; i++)
{
for (int j = 0; j <= N; j++)
{
zHeights[i][j] = getZ(i,j);
}
}
}
void drawTerrain()
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
glColor3ub( (i*34525+j*5245)%256, (i*3456345+j*6757)%256, (i*98776+j*6554544)%256);
glVertex3d(i, j, getZ(i,j));
glVertex3d(i, j+1, getZ(i,j+1));
glVertex3d(i+1, j+1, getZ(i+1,j+1));
glVertex3d(i+1, j, getZ(i+1,j));
}
}
}
void display() // callback to glutDisplayFunc
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
double radians = gDirection /180.*3.141592654; // converts direction to radians
double z = getZ((int)gRX, (int)gRY); // casts as int to find z-index in zHeights[][]
double dx = cos(radians)*gRSpeed;
double dy = sin(radians)*gRSpeed;
double at_x = gRX + dx;
double at_y = gRY + dy;
double at_z = z; // source of problem, no idea what to do
gluLookAt(gRX, gRY, z + 2, // eye position
at_x, at_y, at_z + 2, // point to look at, also wrong
0, 0, 1); // up vector
drawTerrain();
glEnd();
}
void init()
{
generateTerrain();
}
Firstly, I don't see any reason to cast to int here:
double z = getZ((int)gRX, (int)gRY);
Just use the double values to get a smooth behavior.
Your basic approach is already pretty good. You take the current position (gRX, gRY), walk a bit in the viewing direction (dx, dy) and use that as the point to look at. There are just two small things that need adaptation:
double dx = cos(radians)*gRSpeed;
double dy = sin(radians)*gRSpeed;
Although multiplying by gRSpeed might be a good idea, in my opinion, this factor should not be related to the character's kinematics. Instead, this represents the smoothness of your view direction. Small values make the direction stick very closely to the terrain geometry, larger values smooth it out.
And finally, you need to evaluate the height at your look-at point:
double at_z = getZ(at_x, at_y);

Get point around rounded rectangle

I'm using this to get a point around a circle.
constexpr int quality = 20;
static Vertex_t verts[quality];
for ( int i = 0; i < quality; i++ ) {
float angle = ((float)i / -quality) * MATH_TAU;
verts[i].x = cir.pos.x + (cir.radius * sin( angle ));
verts[i].y = cir.pos.y + (cir.radius * cos( angle ));
}
now i need to get a point around a rounded rectangle given it's position, size and radius.
You'll have to split the code to 4 - one for each corner. As these are vertices you're dealing with, the straight lines will be filled automatically.

C++ How to scale a shape and create an if function to not print if too big after scale?

given a shapes orignal centroid + vertices .. i.e. if its a triangle, i know all three vertices coords. How could i then create a scaling function with a scaling factor as a parameter as below.. however my current code is with error and the result are huge shapes, much more than what im scaling by (only want scale factor of 2).
void Shape::scale(double factor)
{
int x, y, xx, xy;
int disx, disy;
for (itr = vertices.begin(); itr != vertices.end(); ++itr) {
//translate obj to origin (0,0)
x = itr->getX() - centroid.getX();
y = itr->getY() - centroid.getY();
//finds distance between centroid and vertex
disx = x + itr->getX();
disy = y + itr->getY();
xx = disx * factor;
xy = disy * factor;
//translate obj back
xx = xx + centroid.getX();
xy = xy + centroid.getY();
//set new coord
itr->setX(xx);
itr->setY(xy);
}
}
I know of using iterations to run through the vertices, my main point of confusion is how can i do the maths between the factor to scale my shapes size?
this is how i declare and itialise a vertex
// could i possible do (scale*x,scale*y)? or would that be problematic..
vertices.push_back(Vertex(x, y));
Also.. the grid is i.e. 100x100. if a scaled shape was to be too big to fit into that grid, i want an exit from the scale function so that the shape wont be enlarged, how can this be done effectively? so far i have a for look but that just loops on vertices, so it will only stop those that would be outside the grid, instead of cancelling the entire shape which would be ideal
if my question is too broad, please ask and i shall edit further to standard
First thing you need to do is find the center of mass of your set of points. That is the arithmetic mean of the coordinates of your points. Then, for each point calculate the line between the center of mass and that point. Now the only thing left is to put the point on that line, but in factor * current_distance away, where current_distance is the distance from the mass center to the given point before rescaling.
void Shape::scale(double factor)
{
Vertex mass_center = Vertex(0., 0.);
for(int i = 0; i < vertices.size(); i++)
{
mass_center.x += vertices[i].x;
mass_center.y += vertices[i].y;
}
mass_center.x /= vertices.size();
mass_center.y /= vertices.size();
for(int i = 0; i < vertices.size(); i++)
{
//this is a vector that leads from mass center to current vertex
Vertex vec = Vertex(vertices[i].x - mass_center.x, vertices[i].y - mass_center.y);
vertices[i].x = mass_center.x + factor * vec.x;
vertices[i].y = mass_center.y + factor * vec.y;
}
}
If you already know the centroid of a shape and the vertexes are the distance from that point then scaling in rectangular coordinates is just multiplying the x and y components of each vertex by the appropriate scaling factor (with a negative value flipping the shape around the axis.
void Shape::scale(double x_factor, double y_factor){
for(auto i=0; i < verticies.size();++i){
verticies[i].x *= x_scale;
verticies[i].y *= y_scale;
}
}
You could then just overload this function with one that takes a single parameter and calls this function with the same value for x and y.
void Shape::scale(double factor){
Shape::scale(factor, factor);
}
If you're vertex values are not centered at the origin then you will also have to multiply those values by your scaling factor.