diff --git a/main.c b/main.c new file mode 100644 index 0000000..9e05d68 --- /dev/null +++ b/main.c @@ -0,0 +1,408 @@ +// +// main.c +// physics +// +// Created by Eric on 16/5/6. +// Copyright © 2016年 Bakantu Eric. All rights reserved. +// + +#include +#include +#include +#include +#include +#define E_G -9.8 +#define A_G 6.67259e-11 +#define o_MAX 16 +#define f_MAX 32 +#define X_WIN 400 +#define Y_WIN 400 +#define w_MAX 32 +#define Pi 3.1415926536 +#define CLEAN system("clear") +#define GL_SILENCE_DEPRECATION + +typedef struct{ + double x; + double y; + double mass; + int gravity; + int e_gravity; + double vx; + double vy; + double a_x; + double a_y; + int elasticity; +} obj; + +typedef struct { + double size; + double angle; + double time; + obj *p_obj; +} force; + +typedef struct { + double x0; + double y0; + double x1; + double y1; + int on; +} wall; + +int opengl_init(int argc, const char * argv[]); +int add_obj(obj *objs[o_MAX]); +int add_force(obj *objs[o_MAX], force *forces[f_MAX]); +int physics_engine(obj *objs[o_MAX],force *forces[f_MAX],wall *walls[w_MAX]); +int print(obj *objs[o_MAX], force *forces[f_MAX]); +int move_obj(obj *objs[o_MAX]); +int delete_obj(obj *objs[o_MAX]); +void o_display(void); +void key_down(unsigned char key, int x, int y); +void mouse_click(int button, int state, int x, int y); +void keep_physics_engine(void); +int set_wall(void); +void w_display(void); +int set_size(void); + +obj *i_objs[o_MAX]; +force *i_forces[f_MAX]; +wall *i_walls[w_MAX]; +int wall_point = 0; +int p_wall = 0; +int engine_on = 1; +int settings = 0; +double x_MAX = 1000, y_MAX = 1000; +double ENGINE_TIME = 0.01; + + +int main(int argc, const char * argv[]) { + for (int i = 0; i < o_MAX; i++) i_objs[i] = NULL; + for (int i = 0; i < f_MAX; i++) i_forces[i] = NULL; + for (int i = 0; i < f_MAX; i++) i_walls[i] = NULL; + + CLEAN; + opengl_init(argc, argv); + //physics_engine(i_objs, i_forces); + for (int i = 0; i < o_MAX; i++) { + if(i_objs[i] != NULL) free(i_objs[i]); + if(i_forces[i] != NULL) free(i_forces[i]); + if(i_walls[i] != NULL) free(i_walls[i]); + } + return 0; +} + + +int add_obj(obj *objs[o_MAX]){ + CLEAN; + int p_c = 0; + while (objs[p_c] != NULL) p_c++; + objs[p_c] = (obj *)malloc(sizeof(obj)); + printf("X: "); + scanf("%lf",&objs[p_c]->x); + printf("Y: "); + scanf("%lf",&objs[p_c]->y); + printf("MASS: "); + scanf("%lf",&objs[p_c]->mass); + printf("IF EARTH_GRAVITY: "); + scanf("%d",&objs[p_c]->e_gravity); + printf("IF GRAVITY: "); + scanf("%d",&objs[p_c]->gravity); + printf("VX: "); + scanf("%lf",&objs[p_c]->vx); + printf("VY: "); + scanf("%lf",&objs[p_c]->vy); + //printf("IF ELASTICITY: "); + //scanf("%d",&objs[p_c]->elasticity); + fflush(stdin); + return 0; +} + +int add_force(obj *objs[o_MAX], force *forces[f_MAX]){ + CLEAN; + int p_c = 0, i_obj; + while (forces[p_c] != NULL) p_c++; + forces[p_c] = (force *)malloc(sizeof(force)); + printf("SIZE: "); + scanf("%lf",&forces[p_c]->size); + printf("ANGLE: "); + scanf("%lf",&forces[p_c]->angle); + printf("TIME: "); + scanf("%lf",&forces[p_c]->time); + printf("OBJ: "); + scanf("%d",&i_obj); + if(objs[i_obj] != NULL) forces[p_c]->p_obj = objs[i_obj]; + else forces[p_c]->p_obj = NULL; + fflush(stdin); + return 0; +} + + +int physics_engine(obj *objs[o_MAX],force *forces[f_MAX],wall *walls[w_MAX]){ + for(int i = 0; i < o_MAX; i++){ + double a_x = 0.0, a_y = 0.0; + if (objs[i] == NULL) continue; + if(fabs(objs[i]->x) > x_MAX || fabs(objs[i]->y) > y_MAX){ + free(objs[i]); + objs[i] = NULL; + continue; + } + else{ + if(objs[i]->e_gravity){ + a_y += E_G * ENGINE_TIME; + } + if(objs[i]->gravity){ + for (int k = 0; k < o_MAX; k ++){ + if ((objs[k] == NULL)||(k == i)) continue; + else{ + double d_x = objs[k]->x - objs[i]->x; + double d_y = objs[k]->y - objs[i]->y; + double d_angle = atan(d_y / d_x); + if (d_y < 0 && d_x < 0) { + d_angle = -d_angle; + d_angle -= Pi/2; + } + else if (d_y > 0 && d_x < 0) { + d_angle = -d_angle; + if (d_x < 0) d_angle += Pi/2; + } + double dis = sqrt((d_x * d_x) + (d_y * d_y)); + double g_force =(A_G * objs[i]->mass * objs[k]->mass)/(dis * dis); + + a_x += (g_force * cos(d_angle)) / objs[i]->mass; + a_y += (g_force * sin(d_angle)) / objs[i]->mass; + } + } + } + } + for (int k = 0; k < f_MAX; k++){ + if (forces[k] == NULL)continue; + else if (forces[k]->p_obj == objs[i]){ + a_x += (forces[k]->size * cos(forces[k]->angle)) / objs[i]->mass *ENGINE_TIME; + a_y += (forces[k]->size * sin(forces[k]->angle)) / objs[i]->mass *ENGINE_TIME; + } + if(forces[k]->time > 0) forces[k]->time -= ENGINE_TIME; + if(forces[k]->time <= 0) { + free(forces[k]); + forces[k] = NULL; + } + } + objs[i]->a_x = a_x; + objs[i]->a_y = a_y; + } + usleep(1000000*ENGINE_TIME); + move_obj(objs); + return 0; +} + +int print(obj *objs[o_MAX], force *forces[f_MAX]){ + CLEAN; + printf("#OBJ:\n"); + for (int i = 0; i < o_MAX; i++){ + if (objs[i] != NULL){ + printf("OBJ[%d](%p): (%lf, %lf) \nMASS: %lf\n\n",i,objs[i],objs[i]->x,objs[i]->y,objs[i]->mass); + glVertex2f(objs[i]->x/x_MAX, objs[i]->y/y_MAX); + } + } + printf("\n#FORCE:\n"); + for (int i = 0; i < o_MAX; i++){ + if(forces[i] != NULL){ + printf("FORCE[%d]: SIZE:%.5lf ANGLE: %.5lf P_OBJ: %p\n, TIME: %.2lf",\ + i,forces[i]->size,forces[i]->angle,forces[i]->p_obj,forces[i]->time); + } + } + printf("\n"); + return 0; +} + +int move_obj(obj *objs[o_MAX]){ + for (int i = 0; i < o_MAX; i++){ + if (objs[i] == NULL) continue; + if (objs[i]->a_x != 0){ + double a_x = objs[i]->a_x; + objs[i]->x += objs[i]->vx + 0.5 * a_x * ENGINE_TIME * ENGINE_TIME; + objs[i]->vx += a_x; + } + if (objs[i]->a_y != 0){ + double a_y = objs[i]->a_y; + objs[i]->y += objs[i]->vy + 0.5 * a_y * ENGINE_TIME * ENGINE_TIME; + objs[i]->vy += a_y; + } + + } + return 0; +} +int delete_obj(obj *objs[o_MAX]){ + CLEAN; + int d_obj; + printf("DELETE OBJ: "); + scanf("%d",&d_obj); + if (objs[d_obj] != NULL){ + free(objs[d_obj]); + objs[d_obj] = NULL; + } + fflush(stdin); + return 0; + +} + +int opengl_init(int argc, const char * argv[]){ + glutInit(&argc, (char **)argv); + glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); + glutInitWindowPosition(X_WIN/2, Y_WIN/2); + glutInitWindowSize(X_WIN, Y_WIN); + glutCreateWindow("Physics"); + glutDisplayFunc(&o_display); + glutIdleFunc(&keep_physics_engine); + glutKeyboardFunc(&key_down); + glutMouseFunc(&mouse_click); + glutMainLoop(); + return 0; +} + +void o_display(void){ + glClearColor(1.0f,1.0f,1.0f,1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glPointSize(4.0f); + + glBegin(GL_POINTS); + glColor3f(0,255,0); + for (int i = 0; i < o_MAX; i++){ + if (i_objs[i] != NULL){ + glVertex2f(i_objs[i]->x/x_MAX, i_objs[i]->y/y_MAX); + } + } + glEnd(); + + glLineWidth(2); + glDisable(GL_LINE_STIPPLE); + glBegin(GL_LINES); + for (int i = 0; i < w_MAX; i++){ + if (i_walls[i] != NULL){ + if (i_walls[i]->on == 1){ + glVertex2f(i_walls[i]->x0/X_WIN*2,i_walls[i]->y0/Y_WIN*2); + glVertex2f(i_walls[i]->x1/X_WIN*2,i_walls[i]->y1/Y_WIN*2); + } + } + } + glEnd(); + glFlush(); +} + +void key_down(unsigned char key, int x, int y){ + if(key == 's'){ + CLEAN; + int ifnot = 1; + char input = '\0'; + while (ifnot){ + printf("DEALWHITH:\n"); + printf("1.ADD OBJ\n"); + printf("2.ADD FORCE\n"); + printf("3.EXIT PROGRAM\n"); + printf("4.DELETE OBJ\n"); + printf("5.SET WALL\n"); + printf("6.SET SIZE\n"); + printf("q.START ENGINE\n"); + fflush(stdin); + input = getchar(); + fflush(stdin); + switch (input) { + case '1': + add_obj(i_objs); + break; + case '2': + add_force(i_objs, i_forces); + break; + case '3': + exit(0); + break; + case '4': + delete_obj(i_objs); + break; + case '5': + engine_on = 0; + settings = 1; + wall_point = 0; + p_wall = 0; + while (i_walls[p_wall] != NULL) p_wall++; + i_walls[p_wall] = (wall *)malloc(sizeof(wall)); + i_walls[p_wall]->on = 0; + ifnot = 0; + break; + case '6': + set_size(); + break; + case 'q': + ifnot = 0; + break; + default: + break; + } + CLEAN; + } + } +} + +void keep_physics_engine(void){ + if (engine_on) { + physics_engine(i_objs, i_forces,i_walls); + print(i_objs,i_forces); + } + else{ + set_wall(); + } + o_display(); +} +int set_wall(void){ + if (wall_point == 2){ + engine_on = 1; + settings = 0; + wall_point = 0; + i_walls[p_wall]->on = 1; + } + return 0; +} + +void mouse_click(int button, int state, int x, int y){ + if (state == GLUT_DOWN){ + if (!engine_on && settings == 1 && button == GLUT_RIGHT_BUTTON){ + printf("%d,%d\n",x-X_WIN/2,-(y-Y_WIN/2)); + printf("x = %d y = %d\n",x,y); + if(wall_point < 2){ + if(wall_point == 0){ + i_walls[p_wall]->x0 = (x-X_WIN/2); + i_walls[p_wall]->y0 = -(y-Y_WIN/2); + } + else if(wall_point == 1){ + i_walls[p_wall]->x1 = (x-X_WIN/2); + i_walls[p_wall]->y1 = -(y-Y_WIN/2); + } + wall_point++; + } + } + } +} + +void w_display(void){ + glClear(GL_COLOR_BUFFER_BIT); + glPointSize(4.0f); + glBegin(GL_POINTS); + for (int i = 0; i < o_MAX; i++){ + if (i_objs[i] != NULL){ + glVertex2f(i_objs[i]->x/x_MAX, i_objs[i]->y/y_MAX); + } + } + glEnd(); + glFlush(); +} + +int set_size(void){ + CLEAN; + printf("XMAX: "); + scanf("%lf",&x_MAX); + printf("YMAX: "); + scanf("%lf",&y_MAX); + printf("ENGINE_TIME: "); + scanf("%lf",&ENGINE_TIME); + return 0; +}