// _prelude_ // _generic_ // _glut_ // _window_ // _shapes_ // _graphs_ // _editor_ // _compiler_ // _startup_ //#include "done.cc" // _prelude_ --------------------------------------------------------- #include #include #include #include #include #include int quit_frame = 0; int flush_every = 300; bool fullscreen = 0; using namespace std; namespace AMPS { typedef double Num; // _generic_ --------------------------------------------------------- typedef unsigned char uchar; // base object class - not needed? class Object { public: virtual ~Object() = 0; }; inline Object::~Object() {} // _glut_ ------------------------------------------------------------ class Window; vector windows; void glut_init(int argc, char *argv[]) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); } // _window_ ---------------------------------------------------------- class Window : Object { protected: int window; int width; int height; private: // This static member 'windows' does not work for some obscure reason. // static unordered_map windows; static void static_display() { int window = glutGetWindow(); windows[window]->display(); } static void static_reshape(int w, int h) { int window = glutGetWindow(); windows[window]->reshape(w, h); } static void static_mouse(int button, int state, int x, int y) { int window = glutGetWindow(); windows[window]->mouse(button, state, x, y); } static void static_motion(int x, int y) { int window = glutGetWindow(); windows[window]->motion(x, y); } static void static_keyboard(uchar key, int x, int y) { int window = glutGetWindow(); windows[window]->keyboard(key, x, y); } // static void static_timer(int window) { // windows[window]->timer(); // } public: Window(const char *title = "app", int width_ = 0, int height_ = 0, bool fullscreen = 0) : width(width_), height(height_) { if (width && height) { glutInitWindowSize(width, height); } window = glutCreateWindow(title); // TODO use growvec? if (window >= (int)windows.size()) windows.resize(window+1); windows[window] = this; if (fullscreen) glutFullScreen(); glutReshapeFunc(&static_reshape); glutDisplayFunc(&static_display); glutMouseFunc(static_mouse); glutMotionFunc(static_motion); glutKeyboardFunc(static_keyboard); } virtual ~Window() { cerr << "glutDestroyWindow" << endl; glutDestroyWindow(window); } virtual void display() { glClear(GL_COLOR_BUFFER_BIT); glutSwapBuffers(); } virtual void reshape(int w, int h) { w=w; h=h; } virtual void mouse(int button, int state, int x, int y) { button=button; state=state; x=x; y=y; } virtual void motion(int x, int y) { x=x; y=y; } virtual void keyboard(uchar key, int x, int y) { key=key; x=x; y=y; } void refresh() { glutPostWindowRedisplay(window); } }; // _shapes_ ---------------------------------------------------------- // max number of pixels error Num angle_per_radian = 180 / M_PI; Num arc_max_error = 0.25; Num a_pixel = 1; void draw_arc(Num x0, Num y0, Num x1, Num y1, Num angle) { angle /= angle_per_radian; // TODO simplify, use GL rotate / scale / translate Num dx, dy, d, hf, ox, oy, r, da, x, y, s, c, x_, y_, altx, alty, alt; Num bend = 1; angle = -angle; dx = (x1 - x0)/2; dy = (y1 - y0)/2; d = hypot(dx, dy); // calc origin hf = 1 / tan(angle / 2); ox = x0 + dx + dy*hf * bend; oy = y0 + dy - dx*hf * bend; // radius r = d / sin(fabs(angle)/2); // length // l = pi2*r * angle / 360 // delta angle // r * (1 - cos(da/2)) == arc_max_error // da = 0.2; // da = 1 / angle_per_radian; da = acos(1 - arc_max_error * a_pixel / r) * 2; // warn("da = %f old_da(3) = %f old_da(16) = %f", da, angle / l * 3 * a_pixel, angle / l * 16 * a_pixel) // da = angle / l * calc_arc_d * a_pixel altx = dy * hf; alty = -dx * hf; alt = hypot(altx, alty); altx /= alt; alty /= alt; // glVertex2d(x0, y0); int steps = fabs(angle) / da; for(int i=0; ir, fill->g, fill->b); glBegin(GL_POLYGON); vertices(); glEnd(); } if (outline) { glColor3ub(outline->r, outline->g, outline->b); glBegin(GL_LINE_LOOP); vertices(); glEnd(); } } void vertices() { Num lx = edges[0].x; Num ly = edges[0].y; for(int i=1; i of arcs? // TODO use Type instead of shape / colours, and shape in Type // Graph *sub; // char *name; // ... void draw() { RGB *fill = &RGB_blue; RGB *outline = &RGB_cyan; p.move(); shape->draw(fill, outline); p.back(); glRasterPos2d(0,0); glGetIntegerv(GL_CURRENT_RASTER_POSITION, view_p); printf("view_p %d %d\n", view_p[0], view_p[1]); } }; class Graph; class Arc { public: int from, to; Num bend; // TODO arcs that are normal to the edge at a port void draw(Graph *graph); }; class Graph { public: vector nodes; vector arcs; void draw(Pos *p) { p = p; // TODO remove int n = nodes.size(); for (int i=0; idraw(); // cope with glx bug on my laptop if (i % flush_every == 0) glFlush(); } glFlush(); } }; void Arc::draw(Graph *graph) { Node *n0 = graph->nodes[from]; Node *n1 = graph->nodes[to]; Num x0 = n0->p.x; Num y0 = n0->p.y; Num x1 = n1->p.x; Num y1 = n1->p.y; glVertex2d(x0, y0); if (!bend) { glVertex2d(x1, y1); } else { // TODO instead of calculating this each time, we can store it in an array, then just call // glDrawArrays (or glBegin .. glEnd). No need for math each time. draw_arc(x0, x0, x1, y1, bend); } } //class Port { //}; // _editor_ ---------------------------------------------------------- class Editor : Window { public: Graph *graph; Pos pos; Editor(Graph *graph) : Window("AMPS", glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT), fullscreen), graph(graph) { pos = { 0, 0, 0, 100, 0 }; // gluPerspective(30, (double)width / height, 0.1, 10); // glTranslated(0, 0, -2); // TODO if need other timers, a problem! use a map? // animate(); } virtual void display() { cerr << "display" << endl; glClear(GL_COLOR_BUFFER_BIT); pos.move(); graph->draw(&pos); pos.back(); glFlush(); glutSwapBuffers(); } virtual void reshape(int w, int h) { printf("editor reshape %d %d\n", w, h); width = w; height = h; glLoadIdentity(); gluOrtho2D(-width/2, width/2, -height/2, height/2); glViewport(0, 0, width, height); } void animate() { // frame_i++; // pos.x += 1; // pos.z *= 1.01; // pos.a += 1; refresh(); glutTimerFunc(1, static_timer_animate, window); } void mouse(int button, int state, int x, int y) { printf("mouse %d %d %d %d\n", button, state, x, y); } void motion(int x, int y) { printf("motion %d %d\n", x, y); } void keyboard(uchar key, int x, int y) { printf("keyboard %c %d %d\n", key, x, y); } private: static void static_timer_animate(int window) { Window *w = windows[window]; ((AMPS::Editor*)w)->animate(); } }; // _compiler_ -------------------------------------------------------- class Compiler { }; class Test { public: Test(int argc, char *argv[]) { glut_init(argc, argv); Graph graph; Node n; n.id = 1; n.p = { 2, 2, 0, 1, 0 }; n.shape = ˆ graph.nodes.push_back(&n); Editor e(&graph); // e.animate(); glutMainLoop(); } }; } // _startup_ --------------------------------------------------------- int main(int argc, char *argv[]) { AMPS::Test t(argc, argv); return 0; }