C++ : How do I make this particle simulation faster? - c++

I have a simple 2D simulation which has particles travelling at given velocities and could collide with each other and the walls. But the fps drops when there are more than 500 particles. I want to simulate at least 5000 particles smoothly because I'll be adding more features to the program. Is there a different and efficient approach to this? Thanks!
gas.cpp:
#include<cstdlib>
#include<vector>
#include<glut.h>
#include "gas.h"
#include<time.h>
float t = 1; //time step
void gas::p(float pos_x, float pos_y, float vx, float vy, float mass)
{
srand(time(0));
m = mass;
x = pos_x;
y = pos_y;
velx = vx;
vely = vy;
size = 3;
}
void gas::draw()
{
glColor3f(1, 1, 1);
glVertex2f(x, y);
}
void gas::move(float t)
{
x += velx * t;
y += vely * t;
}
float temp;
//Function to be ran at every frame:
void run(std::vector <gas>& bn)
{
int it = 0;
for (gas& i : bn)
{
int jt = 0;
for (gas& j : bn)
{
if (it != jt)
{
//Handling collisions:
if (abs(i.y - (j.y + j.size)) < 1 && (abs(j.x - i.x) <= i.size + 1) && i.vely < 0)
{
temp = i.vely;
i.vely = j.vely;
j.vely = temp;
}
if (abs(j.y - (i.y + i.size)) < 1 && (abs(i.x - j.x) <= j.size + 1) && i.vely > 0)
{
temp = i.vely;
i.vely = j.vely;
j.vely = temp;
}
if (abs(j.x - (i.x + i.size)) < 1 && (abs(i.y - j.y) <= i.size + 1) && i.velx > 0)
{
temp = i.velx;
i.velx = j.velx;
j.velx = temp;
}
if (abs(i.x - (j.x + j.size)) < 1 && (abs(j.y - i.y) <= i.size + 1) && i.velx < 0)
{
temp = i.velx;
i.velx = j.velx;
j.velx = temp;
}
}
jt += 1;
}
//Boundary Collisions:
if (i.x > 600 - i.size) { i.x = 600 - i.size; i.velx = -i.velx; }
if (i.x < i.size) { i.x = i.size; i.velx = -i.velx; }
if (i.y > 600 - i.size) { i.y = 600 - i.size; i.vely = -i.vely; }
if (i.y < i.size) { i.y = i.size; i.vely = -i.vely; }
i.move(t);
it += 1;
}
}
gas.h:
#pragma once
class gas
{
public:
float m = 1;
float x = 0;
float y = 0;
float velx = 0;
float vely = 0;
float size = 3;
float density = 100;
float r = 1; float g = 1; float b = 1;
void p(float pos_x, float pos_y, float vx, float vy, float mass);
void draw();
void move(float t);
};
void run(std::vector<gas>& bn);
simulate.cpp (main file):
#include<cstdlib>
#include<glut.h>
#include<vector>
#include "gas.h"
#include<thread>
#include<time.h>
void display();
void reshape(int, int);
const int n = 600; //Number of particles
void init()
{
glClearColor(0, 0, 0, 1);
}
std::vector <gas> b(n);
void timer(int)
{
run(b);
glutPostRedisplay();
glutTimerFunc(1000 / 60, timer, 0);
}
void show(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowPosition(300, 60);
glutInitWindowSize(600, 600);
glutCreateWindow("Particles");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(1000, timer, 0); // Args: Time delay per frame in milliseconds, function to be called
init();
glutMainLoop();
}
int main(int argc, char** argv)
{
int it = 0;
for (gas& i : b)
{
srand(it);
i.p(rand() % 600, rand() % 600, (rand() % 10) * pow(-1, it + 1), (rand() % 10) * pow(-1, it), 1);
it += 1;
}
show(argc, argv);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glPointSize(3);
glBegin(GL_POINTS);
for (gas& i : b)
{
i.draw();
}
glEnd();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 600, 0, 600);
glMatrixMode(GL_MODELVIEW);
}

Related

Bresenham's algorithm in OpenGL

This is my fist time studying Computer Graphics and i was given the code below from my professor. I think i have understood how the algorithm is implemented in general, but what i fail to understand is in what way the incx,incy,inc1,inc2 lines work. I obviously know they are there to increase something but since i haven't fully understood the algorithm i'm kinda baffled. This is the full code:
#include <gl/glut.h>
#include <stdio.h>
int xstart, ystart, xend, yend;
void myInit() {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, 500, 0, 500);
}
void draw_pixel(int x, int y) {
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void draw_line(int xstart, int xend, int ystart, int yend) {
int dx, dy, i, e;
int incx, incy, inc1, inc2;
int x,y;
dx = xend-xstart;
dy = yend-ystart;
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
incx = 1;
if (xend < xstart) incx = -1;
incy = 1;
if (yend < ystart) incy = -1;
x = xstart;
y = ystart;
if (dx > dy) {
draw_pixel(x, y);
e = 2 * dy-dx;
inc1 = 2*(dy-dx);
inc2 = 2*dy;
for (i=0; i<dx; i++) {
if (e >= 0) {
y += incy;
e += inc1;
}
else
e += inc2;
x += incx;
draw_pixel(x, y);
}
} else {
draw_pixel(x, y);
e = 2*dx-dy;
inc1 = 2*(dx-dy);
inc2 = 2*dx;
for (i=0; i<dy; i++) {
if (e >= 0) {
x += incx;
e += inc1;
}
else
e += inc2;
y += incy;
draw_pixel(x, y);
}
}
}
void myDisplay() {
draw_line(xstart, xend, ystart, yend);
glFlush();
}
void main(int argc, char **argv) {
printf( "Enter (xstart, ystart, xend, yend)\n");
scanf("%d %d %d %d", &xstart, &ystart, &xend, &yend);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Bresenham's Line Algorithm Visualization");
myInit();
glutDisplayFunc(myDisplay);
glutMainLoop();
}

Bezier curve by control points is not working

I'm trying to make Bezier curve by control point.
I have some examples and followed it. But it did not work.
It shows the line is going to (0, 0) points during working.
I still don't get it why.
Here's the code in the C++ language, using OpenGL.
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <gl/glut.h>
#include <gl/GLU.h>
#include <gl/GL.h>
#include <math.h>
#define CTRL_COUNT 100
void display();
void init();
float getNextBezierPointX(float t);
float getNextBezierPointY(float t);
void drawline();
int ctrlPointsCount;
int ctrlPointsX[CTRL_COUNT], ctrlPointsY[CTRL_COUNT];
int X1[20] = { 10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105 };
int Y1[20] = { 50,60,40,70,40,60,35,80,45,55,30,60,40,60,40,55,35,70,40,50 };
void main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(500, 300);
glutCreateWindow("Bezier");
glutDisplayFunc(display);
init();
glutMainLoop();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
ctrlPointsCount = 20;
for (int i = 0; i < 20; i++) {
ctrlPointsX[i] = X1[i];
ctrlPointsY[i] = Y1[i];
}
drawline();
glFlush();
}
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glPointSize(8.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 128.0, 0.0, 96.0);
}
float getNextBezierPointX(float t) {
float x = 0.0;
int c;
for (int i = 0; i < ctrlPointsCount; i ++) {
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
c = ctrlPointsCount - 1;
x = x + c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsX[i];
}
return x;
}
float getNextBezierPointY(float t) {
float y = 0.0;
int c;
for (int i = 0; i < ctrlPointsCount; i ++) {
if (i == 0 || i == ctrlPointsCount - 1)
c = 1;
else
c = ctrlPointsCount - 1;
y = y + c * pow(t, i) * pow(1 - t, ctrlPointsCount - 1 - i) * ctrlPointsY[i];
}
return y;
}
void drawline() {
float x, y;
for (int i = 0; i < 20; i++) {
glBegin(GL_POINTS);
glVertex2i(ctrlPointsX[i], ctrlPointsY[i]);
glEnd();
glFlush();
}
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01) {
x = getNextBezierPointX(t);
y = getNextBezierPointY(t);
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f(x, y);
glEnd();
glFlush();
oldX = x;
oldY = y;
}
}
For a bezier curve like this you have to calculate Bernstein polynomials:
double factorial(int n)
{
double x = 1.0;
for (int i = 1; i <= n; i++)
x *= (double)i;
return x;
}
double Ni(int n, int i)
{
double a1 = factorial(n);
double a2 = factorial(i);
double a3 = factorial(n - i);
double ni = a1/ (a2 * a3);
return ni;
}
double Bernstein(int n, int i, double t)
{
double ti = (t == 0.0 && i == 0) ? 1.0 : pow(t, i); /* t^i */
double tni = (n == i && t == 1.0) ? 1.0 : pow((1 - t), (n - i)); /* (1 - t)^i */
double basis = Ni(n, i) * ti * tni; //Bernstein basis
return basis;
}
The code to create the curve may look like this:
struct vec2
{
double x, y;
};
vec2 getBezierPoint(float t, int n, int x[], int y[] )
{
vec2 pt{ 0.0, 0.0 };
for (int i = 0; i < n; i ++) {
double b = Bernstein( n - 1, i, t );
pt.x += b * x[i];
pt.y += b * y[i];
}
return pt;
}
float oldX = ctrlPointsX[0], oldY = ctrlPointsY[0];
for (double t = 0.0; t <= 1.0; t += 0.01)
{
vec2 pt = getBezierPoint( t, ctrlPointsCount, ctrlPointsX, ctrlPointsY );
glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINES);
glVertex2f(oldX, oldY);
glVertex2f((float)pt.x, (float)pt.y);
glEnd();
glFlush();
oldX = (float)pt.x; oldY = (float)pt.y;
}
An other solution is provided in the answer to the Stack Overflow question How do I implement a Bézier curve in C++?:
#include <vector>
vec2 getBezierPoint2( float t, int n, int x[], int y[] )
{
std::vector<double> tmpx( n ), tmpy( n );
for ( int i=0; i<n; ++ i )
{
tmpx[i] = x[i];
tmpy[i] = y[i];
}
int i = n - 1;
while (i > 0)
{
for (int k = 0; k < i; k++)
{
tmpx[k] = tmpx[k] + t * ( tmpx[k+1] - tmpx[k] );
tmpy[k] = tmpy[k] + t * ( tmpy[k+1] - tmpy[k] );
}
i--;
}
return { tmpx[0], tmpy[0] };
}
But may be the result is not what you expect it to be, because you create a Higher-order Bézier curve which results in a very flat curve:
Maybe you want to connect any number of points with square bezier curves: Quadratic Bézier Curve: Calculate Points

How to write an intersection function for any kind of shapes

I have to write a function, which detects intersection and returns true or false.
I have Shape.cpp file, and rectangle.cpp, circle.cpp files inherits of it. I tried to calculate it, but i failed. There is no error, but when my program starts, it crashes. MY Question is why it crashes? is my way wrongs? Here is circle.cpp file.
bool Circ::intersects(Shape* pshape)
{
Rect *p1 = dynamic_cast<Rect*>(pshape);
Circ *p2 = dynamic_cast<Circ*>(pshape);
if(p1)
{
float circleDistance_x = abs(p2->getPos().x - p1->getPos().x);
float circleDistance_y = abs(p2->getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + p2->getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + p2->getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= p2->getRad()^2);
}
return false;
}
This is not the code all i want to write. But when it fails, i stopped to write.
and my Shapes.h file
#ifndef _SHAPES_H
#define _SHAPES_H
struct Point2d
{
float x, y;
};
struct Point3d
{
float r, g, b;
};
class Shape
{
protected:
bool m_bMarked;
Point3d m_col;
Point2d m_veldir;
Point2d m_pos;
float m_vel;
public:
Shape(Point2d& pos, Point2d& veldir, float vel, Point3d& col)
:m_pos(pos),m_veldir(veldir),m_vel(vel),m_col(col)
{
m_bMarked = false;
}
virtual ~Shape() {}
virtual void draw() = 0;
virtual bool intersects(Shape*) = 0;
inline void move() { m_pos.x += m_veldir.x*m_vel; m_pos.y += m_veldir.y*m_vel; }
inline void invert_xdir() { m_veldir.x *= -1; }
inline void invert_ydir() { m_veldir.y *= -1; }
inline void MarkShape() { m_bMarked = true; }
inline void UnMarkShape() { m_bMarked = false; }
inline bool isMarked() { return m_bMarked; }
inline void increase_vel() { m_vel += 0.01f; }
inline void decrease_vel() { m_vel -= 0.01f; }
};
#endif
And finally my ShapesMain.cpp file
#include <time.h>
#include <GL/glut.h>
#include <cmath>
#include "Rectangle.h"
#include "Circle.h"
// YOU CAN CHANGE THE NUMBER OF SHAPES
#define SHAPE_COUNT 20
// YOU CAN MODIFY WINDOW SIZE BY CHANGING THESE
// YOU MAY ALSO VIEW WINDOW IN FULL SCREEN
#define WINDOWX 500
#define WINDOWY 500
// UNCOMMENT THE LINE BELOW TO STOP MOVING SHAPES
//#define NO_MOTION
// CHANGE THESE DIMENSIONS HOWEVER YOU LIKE
#define MAX_SHAPE_DIM 70
#define MIN_SHAPE_DIM 10
float g_windowWidth = WINDOWX;
float g_windowHeight = WINDOWY;
Shape* g_shapeList[SHAPE_COUNT];
int g_numShapes = 0;
bool g_bShowIntersection = true;
//------------------------------------
void Initialize()
{
srand ( time(NULL) );
// delete previous shapes, if there is any
if (g_numShapes > 0)
{
for (int i = 0; i < g_numShapes; i++)
delete g_shapeList[i];
}
// create a new shape repository
do {
g_numShapes = rand() % SHAPE_COUNT; // number of shapes are randomly determined
} while (g_numShapes < 5); // we dont want to have less than 5 shapes
int rect_count = g_numShapes * (rand() % 10 / 10.0f);
int circle_count = g_numShapes - rect_count;
int half_wind_x = 3* g_windowWidth / 4;
int half_wind_y = 3* g_windowHeight / 4;
int max_dim = MAX_SHAPE_DIM; // max dim. of any shape
int min_dim = MIN_SHAPE_DIM; // min dim. of any shape
int quad_wind = g_windowWidth / 4;
for (int i= 0; i<g_numShapes; i++)
{
float x, y;
float v1, v2;
// set positions
do {
x = rand() % half_wind_x;
} while (x <= quad_wind);
do {
y = rand() % half_wind_y;
} while (y <= quad_wind);
Point2d pos = { x,y };
// set velocity directions
do{
v1 = rand() % 10 / 10.0f;
v2 = rand() % 10 / 10.0f;
} while (v1 == 0 || v2 == 0);
v1 *= (rand() % 2) ? -1 : 1;
v2 *= (rand() % 2) ? -1 : 1;
float vnorm = sqrt(v1*v1 + v2*v2);
Point2d veldir = { v1 / vnorm, v2 / vnorm };
// set velocity
float vel;
do {
vel = rand() % 2 / 10.0f;
} while (vel == 0);
#ifdef NO_MOTION
vel = 0.0f;
#endif
//set color
float R = rand()%100/100.0f;
float G = rand()%100/100.0f;
float B = rand()%100/100.0f;
Point3d color = { R,G,B };
// construct objects
if (i < rect_count)
{
float wx;
float wy;
do {
wx = rand() % quad_wind;
} while (wx < min_dim || wx>max_dim);
do {
wy = rand() % quad_wind;
} while (wy < min_dim || wy>max_dim);
Point2d size = { wx, wy };
Rect* pRect = new Rect(pos, size, veldir, vel, color);
g_shapeList[i] = pRect;
}
else
{
float rad;
do {
rad = rand() % quad_wind;
} while (rad < min_dim || rad>max_dim);
Circ* pCirc = new Circ(pos, rad, veldir, vel, color);
g_shapeList[i] = pCirc;
}
}
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
//-------------------------------------
// This function handles the intersections of shapes.
// if the user is not interested in marking intersections
// s/he can set bMarkIntersections to false..in this case
// no intersection test is performed
void MarkObjects(bool bMarkIntersections)
{
if (bMarkIntersections == false)
{
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->UnMarkShape();
}
else
{
// reset the states of all shapes as unmarked
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->UnMarkShape();
for (int i = 0; i < g_numShapes; i++)
{
for (int j = i+1; j < g_numShapes; j++)
{
if (g_shapeList[i]->intersects(g_shapeList[j]))
{
g_shapeList[i]->MarkShape();
g_shapeList[j]->MarkShape();
}
}
}
}
}
//------------------------------------
void UpdateData()
{
// create viewport bounding rectangles to keep the shapes within the viewport
Point2d Winpos = { -1.0,0.0 };
Point2d Winsize = { 1.0 , g_windowHeight };
Point2d Winveldir = { 0,0 }; // dummy veldir
float Winvel = 0.0f; //not moving
Point3d Wincol = { 0,0,0 }; // dummy color
Rect WindowRectLeft(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = 0.0; Winpos.y = -1.0;
Winsize.x = g_windowWidth; Winsize.y = 1.0;
Rect WindowRectBottom(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = g_windowWidth; Winpos.y = 0.0;
Winsize.x = 1; Winsize.y = g_windowHeight;
Rect WindowRectRight(Winpos, Winsize, Winveldir, Winvel, Wincol);
Winpos.x = 0.0; Winpos.y = g_windowHeight;
Winsize.x = g_windowWidth; Winsize.y = 1.0f;
Rect WindowRectUp(Winpos, Winsize, Winveldir, Winvel, Wincol);
for (int i = 0; i < g_numShapes; i++)
{
// move the shape
g_shapeList[i]->move();
// if it bounces to the window walls, invert its veldir
if (g_shapeList[i]->intersects(&WindowRectLeft) ||
g_shapeList[i]->intersects(&WindowRectRight))
g_shapeList[i]->invert_xdir();
if (g_shapeList[i]->intersects(&WindowRectBottom) ||
g_shapeList[i]->intersects(&WindowRectUp))
g_shapeList[i]->invert_ydir();
}
}
//------------------------------------
void ChangeSize(GLsizei w, GLsizei h)
{
if(h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
g_windowHeight = h;
g_windowWidth = w;
glOrtho(0, g_windowWidth, 0, g_windowHeight , 1.0f, -1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//------------------------------------
void processNormalKeys(unsigned char key, int x, int y)
{
if (key == 'q') // PRESS 'q' to terminate the application
exit(0);
if(key=='r') // PRESS 'r' ket to reset the shapes
Initialize();
if (key == 's') // toggle between showing the intersections or not
g_bShowIntersection = g_bShowIntersection ? false: true;
}
//------------------------------------
void processSpecialKeys(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_LEFT :
break;
case GLUT_KEY_RIGHT :
break;
case GLUT_KEY_UP:
// PRESSING UP ARROW KEY INCREASES THE SHAPE VELOCITIES
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->increase_vel();
break;
case GLUT_KEY_DOWN:
// PRESSING DOWN ARROW KEY DECREASES THE SHAPE VELOCITIES
for (int i = 0; i < g_numShapes; i++)
g_shapeList[i]->decrease_vel();
break;
}
}
//-------------------------------------
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
UpdateData();
MarkObjects(g_bShowIntersection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int i= 0; i<g_numShapes; i++)
g_shapeList[i]->draw();
glutSwapBuffers();
}
//------------------------------------
int main(int argc, char* argv[])
{
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );
glutInitWindowPosition(100,100);
glutInitWindowSize(WINDOWX, WINDOWY);
glutCreateWindow("COM102B - PA4");
// Register callback handler for window re-paint
glutDisplayFunc(display);
glutReshapeFunc(ChangeSize);
glutIdleFunc(display);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(processSpecialKeys);
Initialize();
glutMainLoop(); // Enter infinitely event-processing loop
return 0;
}
Your problem is in these lines:
Rect *p1 = dynamic_cast<Rect*>(pshape);
Circ *p2 = dynamic_cast<Circ*>(pshape);
Unless you had inherited Rect from Circ or vice versa this is what makes your program crash, you can't cast your pShape to Circ if it is a Rect, so when you pass a Rect object to your function it will correctly cast to Rect* but it will fail with Circ* returning nullptr, so then when you try to access methods from p2 it will crash becouse you are accessing to invalid memory (0x00000000) :
if(p1)
{
float circleDistance_x = abs(p2->getPos().x - p1->getPos().x);
float circleDistance_y = abs(p2->getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + p2->getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + p2->getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= p2->getRad()^2);
}
So, you could simply just cast the first p1 pointer since the method is from circle, it's obvious that it was called from a Circ Object so there's no need for p2 pointer.
Rect *p1 = dynamic_cast<Rect*>(pshape);
if(p1)
{
float circleDistance_x = abs(getPos().x - p1->getPos().x);
float circleDistance_y = abs(getPos().y - p1->getPos().y);
if(circleDistance_x > (p1->getSize().x/2 + getRad()))
return false;
if(circleDistance_y > (p1->getSize().y/2 + getRad()))
return false;
if(circleDistance_x <= (p1->getSize().x/2))
return true;
if(circleDistance_y <= (p1->getSize().y/2))
return true;
float cornerDistance_sq = (circleDistance_x - (p1->getSize().x/2)) + (circleDistance_y - (p1->getSize().y/2))*(circleDistance_y - (p1->getSize().y/2));
return (cornerDistance_sq <= getRad()^2);
}
Also on the line:
return (cornerDistance_sq <= getRad()^2)
i think you are trying to get the radius square but this wont do it, what it is actually doing is
(cornerDistance_sq <= getRad()) ^ 2
becouse <= has greater precedence to ^, plus ^ is not a square operator it is a bitwise operator. So what you actually want is :
return cornerDistance_sq <= getRad() * getRad();

Expected a ';' before int main bracket [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
So I get an error for not putting a ';' before the bracket '{' right after int main and the annoying part is that I've tried anything I could so far (Warning: I am not an experienced coder at all) I even tried to put in new libraries but it wouldn't work. I noticed though that by taking a similar code with the same int main and copy/pasting it, that only the keyboard function was the one creating the problem.... I really cannot understand... Thank you in advance for any help given :)
#include <GL/glut.h>
#include <math.h>
class Boxes
{
public: float x;
public: float y;
public: float w;
public: float h;
public: float r;
public: float g;
public: float b;
public: float i;
public: float j;
public: bool ActiveBox;
public: bool Horizontal;
void Draw()
{
glColor3f(r, g, b);
glRectf(x, y, x + w, y + h);
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
glRectf(x, y, x + w, y + h);
glVertex2f(x, y);
glVertex2f(x, y + h);
glVertex2f(x + w, y + h);
glVertex2f(x + w, y);
glEnd();
}
void Outline(float r, float g, float b, float x, float y, float w, float h)
{
glColor3f(r, g, b);
glRectf(x, y, x + w, y + h);
glLineWidth(3);
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
glVertex2f(x, y);
glVertex2f(x, y + h);
glVertex2f(x + w, y + h);
glVertex2f(x + w, y);
glEnd();
}
Boxes() { x = 0; y = 0; w = 0; h = 0; r = 0; g = 0; b = 0; i = 0; j = 0; ActiveBox = false; Horizontal = false; }
~Boxes() { x = 0; y = 0; w = 0; h = 0; r = 0; g = 0; b = 0; i = 0; j = 0; ActiveBox = false; Horizontal = false; }
};
Boxes PuzzlePieces[10];
int grid[6][6];
int d = 1;
int highlight = 1;
void Grid(float i, float j)
{
for (int i = 1; i < 7; i++)
{
for (int j = 1; j < 7; j++)
{
grid[i][j];
}
}
grid[1][1] = 1;
grid[1][2] = 1;
grid[1][3] = 1;
grid[1][4] = 1;
grid[1][5] = 1;
grid[1][6] = 1;
grid[2][1] = 1;
grid[2][2] = 1;
grid[2][3] = 0;
grid[2][4] = 1;
grid[2][5] = 1;
grid[2][6] = 1;
grid[3][1] = 0;
grid[3][2] = 1;
grid[3][3] = 1;
grid[3][4] = 1;
grid[3][5] = 0;
grid[3][6] = 0;
grid[4][1] = 1;
grid[4][2] = 1;
grid[4][3] = 0;
grid[4][4] = 1;
grid[4][5] = 1;
grid[4][6] = 0;
grid[5][1] = 0;
grid[5][2] = 0;
grid[5][3] = 1;
grid[5][4] = 1;
grid[5][5] = 1;
grid[5][6] = 0;
grid[6][1] = 0;
grid[6][2] = 0;
grid[6][3] = 1;
grid[6][4] = 0;
grid[6][5] = 1;
grid[6][6] = 0;
PuzzlePieces[1].w = d;
PuzzlePieces[1].h = 2 * d;
PuzzlePieces[1].g = 1;
PuzzlePieces[2].x = 1;
PuzzlePieces[2].w = d;
PuzzlePieces[2].h = 2 * d;
PuzzlePieces[2].g = 1;
PuzzlePieces[3].x = 2;
PuzzlePieces[3].w = d;
PuzzlePieces[3].h = 2 * d;
PuzzlePieces[3].g = 1;
PuzzlePieces[4].x = 3;
PuzzlePieces[4].w = 2 * d;
PuzzlePieces[4].h = d;
PuzzlePieces[4].b = 1;
PuzzlePieces[4].Horizontal = true;
PuzzlePieces[5].x = 4;
PuzzlePieces[5].y = 1;
PuzzlePieces[5].w = 2 * d;
PuzzlePieces[5].h = d;
PuzzlePieces[5].b = 1;
PuzzlePieces[5].Horizontal = true;
PuzzlePieces[6].x = 1;
PuzzlePieces[6].y = 3;
PuzzlePieces[6].h = d;
PuzzlePieces[6].w = 2 * d;
PuzzlePieces[6].b = 1;
PuzzlePieces[6].Horizontal = true;
PuzzlePieces[7].x = 3;
PuzzlePieces[7].y = 2;
PuzzlePieces[7].w = d;
PuzzlePieces[7].h = 3 * d;
PuzzlePieces[7].g = 1;
PuzzlePieces[8].x = 1;
PuzzlePieces[8].y = 2;
PuzzlePieces[8].w = 2 * d;
PuzzlePieces[8].h = d;
PuzzlePieces[8].r = 1;
PuzzlePieces[8].Horizontal = true;
PuzzlePieces[9].x = 2;
PuzzlePieces[9].y = 4;
PuzzlePieces[9].w = d;
PuzzlePieces[9].h = 2 * d;
PuzzlePieces[9].g = 1;
PuzzlePieces[10].x = 4;
PuzzlePieces[10].y = 3;
PuzzlePieces[10].w = d;
PuzzlePieces[10].h = 2 * d;
PuzzlePieces[10].g = 1;
}
void display(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity;
glTranslatef(2.5, 2.5, 0);
glBegin(GL_POLYGON);
glVertex2f(0, 0);
glVertex2f(0, 6);
glVertex2f(6, 6);
glVertex2f(6, 0);
glEnd();
for (int i = 0; i < 11; i++)
{
PuzzlePieces[i].Draw();
if (PuzzlePieces[i].ActiveBox == true)
{
PuzzlePieces[i].Outline;
}
}
glColor3f(1, 1, 1);
glLineWidth(3);
glBegin(GL_LINE_LOOP);
glVertex2f(0, 0);
glVertex2f(0, 6);
glVertex2f(6, 6);
glVertex2f(6, 0);
glEnd();
for (int i = 0; i < 8; i++)
{
PuzzlePieces[i].Draw;
}
glFlush();
}
void reshape (int w, int h)
{
float dx=600, dy=600;
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glOrtho(0.0, dx, 0.0, dy, 0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27: exit(0); // escape ends the programm
case 'w':
if (highlight == 0)
{
PuzzlePieces[highlight].Outline = true;
}
if (highlight != 0)
{
PuzzlePieces[highlight].Outline = true;
PuzzlePieces[highlight - 1].Outline = false;
}
if (highlight == 8)
{
PuzzlePieces[0].Outline = true;
highlight = 0;
}
highlight++;
break;
glutPostRedisplay();
}
int main(int argc, char** argv)
**{**
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow ("DPSD - Graphics Arm Ex - 4");
Grid();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27: exit(0); // escape ends the programm
case 'w':
if (highlight == 0)
{
PuzzlePieces[highlight].Outline = true;
}
if (highlight != 0)
{
PuzzlePieces[highlight].Outline = true;
PuzzlePieces[highlight - 1].Outline = false;
}
if (highlight == 8)
{
PuzzlePieces[0].Outline = true;
highlight = 0;
}
highlight++;
break;
glutPostRedisplay();
}
} // <= This is what you need.
int main(int argc, char** argv)

Filling self intersecting polygon in OpenGL

I have a self intersecting polygon that I am trying to fill using the odd-even rule like so :
I use a scan line and when I detect an edge of the polygon I change the fill color. Here's my code so far :
Edited code :
#include<GL/glut.h>
#include<vector>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<limits>
using namespace std;
const int n = 7;
class Point{
public:
int x, y;
Point(){
};
Point(int a, int b){
x = a;
y = b;
};
void set(int a, int b){
x = a;
y = b;
};
};
Point P[n];
int min(int x, int y)
{
if (x <= y) return x;
else return y;
}
int max(int x, int y)
{
if (x >= y) return x;
else return y;
}
Point solve(Point A, Point B, Point C, Point D)
{ //returns the intersection point between line segments [AB] and [CD]
Point rez;
rez.x = -1;
rez.y = -1;
//[AB]
int A1 = B.y - A.y, B1 = A.x - B.x, C1 = (A1 * A.x) + (B1 * A.y);
//[CD]
int A2 = D.y - C.y, B2 = C.x - D.x, C2 = (A2 * C.x) + (B2 * C.y);
int det = A1*B2 - A2*B1;
if (det == 0){
return Point(-1, -1);
}
else
{
rez.x = (B2*C1 - B1*C2) / det;
rez.y = (A1*C2 - A2*C1) / det;
}
if (!(rez.x >= min(A.x, B.x) && rez.x <= max(A.x, B.x) && rez.x >= min(C.x, D.x) && rez.x <= max(C.x, D.x)))
{
rez.x = -1;
rez.y = -1;
}
return rez;
}
bool intComparison(int i, int j) { return (i < j); }
void scanfill()
{
int i, j, color = 1, k; //alb
vector<int> inter[501];
Point T;
for (j = 0; j < 500; j++) //go line by line
{
for (k = 0; k < n - 1; k++) //loop through all the line segments
{
T = solve(Point(0, j), Point(499, j), P[k], P[k + 1]);
if (!(T.x == -1 && T.y == -1))
{
inter[j].push_back(T.x); // save the x coord. of the intersection point between the line and the sweep line when y = j
}
}
T = solve(Point(0, j), Point(499, j), P[n - 1], P[0]);
if (!(T.x == -1 && T.y == -1))
{
inter[j].push_back(T.x);
}
}
for (j = 0; j < 500; j++)
{
sort(inter[j].begin(), inter[j].end(), intComparison);
}
for (j = 0; j < 500; j++)
{
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINES);
for (vector<int>::iterator it = inter[j].begin(); it != inter[j].end(); it++)
{
glVertex2i(*it, j); //draw the actual lines
}
glEnd();
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
P[0] = Point(100, 235);
P[1] = (Point(100, 100));
P[2] = (Point(230, 140));
P[3] = (Point(40, 200));
P[4] = (Point(20, 60));
P[5] = (Point(300, 150));
P[6] = (Point(150, 111));
glBegin(GL_LINE_LOOP);
for (int i = 0; i < n; i++)
{
glVertex2i(P[i].x, P[i].y);
}
glEnd();
scanfill();
glFlush();
}
void init()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 499.0, 0.0, 499.0);
}
void main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("scanline");
glutDisplayFunc(display);
init();
glutMainLoop();
}
It seems to detect more intersections between the sweep line and the actual lines than it should for some reason.
Result with the above code :
Desired Result :
I managed to solve the problem. Here's the code if anyone else is interested :
#include<GL/glut.h>
#include<vector>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<limits>
using namespace std;
const int n = 7;
class Point{
public:
int x, y;
Point(){
};
Point(int a, int b){
x = a;
y = b;
};
void set(int a, int b){
x = a;
y = b;
};
};
Point P[n];
int min(int x, int y)
{
if (x <= y) return x;
else return y;
}
int max(int x, int y)
{
if (x >= y) return x;
else return y;
}
double solve(int y, Point A, Point B)
{
if (y >= min(A.y, B.y) && y <= max(A.y, B.y))
{
return ((y * B.x) - (y * A.x) - (A.y * B.x) + (A.x * B.y)) / (B.y - A.y);
}
else return -1;
}
bool doubleComparison(double i, double j) { return (i < j); }
bool isVertex(int x, int y)
{
for (int i = 0; i < n; i++)
{
if (P[i].x == x && P[i].y == y) return 1;
}
return 0;
}
void scanfill()
{
int i, j, color = 1, k;
double x;
vector<double> inter[501];
for (j = 0; j < 500; j++)
{
for (k = 0; k < n - 1; k++)
{
x = solve(j, P[k], P[k + 1]);
if (x != -1 && !isVertex(x,j))
{
inter[j].push_back(x);
}
}
x = solve(j, P[n - 1], P[0]);
if (x != -1 && !isVertex(x, j))
{
inter[j].push_back(x);
}
}
for (j = 0; j < 500; j++)
{
sort(inter[j].begin(), inter[j].end(), doubleComparison);
}
for (j = 0; j < 500; j++)
{
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINES);
for (vector<double>::iterator it = inter[j].begin(); it != inter[j].end(); it++)
{
glVertex2d(*it, j);
}
glEnd();
}
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
P[0] = Point(100, 235);
P[1] = (Point(100, 100));
P[2] = (Point(230, 140));
P[3] = (Point(40, 200));
P[4] = (Point(20, 60));
P[5] = (Point(300, 150));
P[6] = (Point(150, 111));
glBegin(GL_LINE_LOOP);
for (int i = 0; i < n; i++)
{
glVertex2i(P[i].x, P[i].y);
}
glEnd();
scanfill();
glFlush();
}
void init()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 499.0, 0.0, 499.0);
}
void main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow("scanline");
glutDisplayFunc(display);
init();
glutMainLoop();
}