/* Public domain */ #include #include #include #include M_Real x0 = -2.0, u0 = -2.0; M_Real x1 = 2.0, u1 = 2.0; M_Real xInc = 0.02, uInc = 0.05; M_Real spinX = 0.0, spinY = -0.0, spinZ = 0.0; M_Real urMin = -2.0; int init = 1; int plotMode = 1; SG_NodeClass CatastropheClass; static void CatastropheDraw(void *pNode, SG_View *sgv) { SG_Node *node = pNode; M_Color color; M_Vector3 v; M_Real x, u; GLenum mode = GL_POINTS; int i; switch (plotMode) { case 0: mode = GL_POINTS; break; case 1: mode = GL_LINE_STRIP; break; case 2: mode = GL_LINES; break; } GL_Begin(GL_LINES); GL_Vertex3(-1.0, 0.0, 0.0); GL_Vertex3(+1.0, 0.0, 0.0); GL_Vertex3( 0.0, -1.0, 0.0); GL_Vertex3( 0.0, +1.0, 0.0); GL_Vertex3( 0.0, 0.0, -1.0); GL_Vertex3( 0.0, 0.0, +1.0); GL_End(); for (x = x0; x < x1; x += xInc) { GL_Begin(mode); for (u = u0; u < u1; u += uInc) { v.x = x; v.y = Cbrt(-u/3.0) + u*Sqrt(-x/2.0); v.z = u; M_VecScale3v(&v, 30.0); color.r = 1.0; color.g = 1.0 - 1.0/Fabs(u*100.0); color.b = 1.0 - 1.0/Fabs(u*100.0); GL_Color3v(&color); GL_Vertex3v(&v); } GL_End(); } for (x = x0; x < x1; x += xInc) { GL_Begin(mode); for (u = u0; u < u1; u += uInc) { v.x = x; v.y = Cbrt(-u/3.0) - u*Sqrt(-x/2.0); v.z = u; M_VecScale3v(&v, 30.0); color.g = 1.0; color.r = 1.0 - 1.0/Fabs(x*3.0); color.b = 1.0 - 1.0/Fabs(x*3.0); GL_Color3v(&color); GL_Vertex3v(&v); } GL_End(); } SG_RotateI(node, spinX); SG_RotateJ(node, spinY); SG_RotateK(node, spinZ); if (init) { if (u0 > urMin) { u0 -= 0.06; } else { init = 0; spinY = -0.006; } } } AG_Window * CreateParametersWindow(void) { AG_Window *win; AG_Numerical *num; const char *modes[] = { "Points", "Lines", "Segments", NULL }; win = AG_WindowNew(0); AG_WindowSetCaptionS(win, "Parameters"); AG_WindowSetPosition(win, AG_WINDOW_MIDDLE_LEFT, 0); AG_RadioNewInt(win, AG_RADIO_EXPAND, modes, &plotMode); num = M_NumericalNewReal(win, 0, NULL, "x0: ", &x0); AG_NumericalSetIncrement(num, 0.1); num = M_NumericalNewReal(win, 0, NULL, "xInc: ", &xInc); AG_NumericalSetIncrement(num, 0.001); num = M_NumericalNewReal(win, 0, NULL, "x1: ", &x1); AG_NumericalSetIncrement(num, 0.1); num = M_NumericalNewReal(win, 0, NULL, "u0: ", &u0); AG_NumericalSetIncrement(num, 0.1); num = M_NumericalNewReal(win, 0, NULL, "uInc: ", &uInc); AG_NumericalSetIncrement(num, 0.001); num = M_NumericalNewReal(win, 0, NULL, "u1: ", &u1); AG_NumericalSetIncrement(num, 0.1); num = M_NumericalNewReal(win, 0, "deg", "Pitch: ", &spinX); AG_NumericalSetIncrement(num, 0.0001); num = M_NumericalNewReal(win, 0, "deg", "Yaw: ", &spinY); AG_NumericalSetIncrement(num, 0.0001); num = M_NumericalNewReal(win, 0, "deg", "Roll: ", &spinZ); AG_NumericalSetIncrement(num, 0.0001); AG_WindowShow(win); } int main(int argc, char *argv[]) { int c, i, fps = -1; AG_Window *win; SG_View *sv; SG *sg; SG_Node *cat; char *s; char *driverSpec = ""; char *optArg; if (AG_InitCore("catastrophe-demo", 0) == -1) { fprintf(stderr, "%s\n", AG_GetError()); return (1); } while ((c = AG_Getopt(argc, argv, "?d:", &optArg, NULL)) != -1) { switch (c) { case 'd': driverSpec = optArg; break; default: printf("Usage: %s [-d driverspec]\n", agProgName); exit(0); } } if (AG_InitGraphics(driverSpec) == -1) { fprintf(stderr, "%s\n", AG_GetError()); return (-1); } SG_InitSubsystem(); AG_SetRefreshRate(fps); AG_BindGlobalKey(AG_KEY_ESCAPE, AG_KEYMOD_ANY, AG_Quit); AG_BindGlobalKey(AG_KEY_F8, AG_KEYMOD_ANY, AG_ViewCapture); agColors[WINDOW_BG_COLOR] = AG_ColorRGB(0,0,0); /* Create the scene. */ sg = SG_New(NULL, "MyScene", 0); /* Create an instance of our plot object. */ AG_RegisterClass(&CatastropheClass); cat = Malloc(sizeof(SG_Node)); AG_ObjectInit(cat, &CatastropheClass); AG_ObjectSetName(cat, "MyCatastrophe"); AG_ObjectAttach(sg->root, cat); SG_Rotatevd(cat, 30.0, M_VecJ3()); /* Create the user interface. */ CreateParametersWindow(); win = AG_WindowNew(0); AG_WindowSetCaptionS(win, "Catastrophe"); sv = SG_ViewNew(win, sg, SG_VIEW_EXPAND|SG_VIEW_NO_LIGHTING); SG_Translate(sv->cam, 10.0, 0.0, -100.0); SG_Rotatevd(sv->cam, 180.0, M_VecI3()); AG_WindowSetGeometryAlignedPct(win, AG_WINDOW_MC, 60, 40); AG_WindowShow(win); AG_EventLoop(); AG_Destroy(); return (0); fail: AG_Destroy(); return (1); } /* Define a new node class for our plot. */ SG_NodeClass CatastropheClass = { { "SG_Node:Catastrophe", sizeof(SG_Node), { 0,0 }, NULL, /* init */ NULL, /* destroy */ NULL, /* load */ NULL, /* save */ NULL, /* edit */ }, NULL, /* menuInstance */ NULL, /* menuClass */ CatastropheDraw, NULL /* edit */ };