diff --git a/README.md b/README.md index a435bca..405b00e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,11 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0 # TODO +- Add menu - partially done + - Adjust ambient light + - help + - quit +- Allow changing the move/rotation speed(or just a multiplier) - Create a cow - Head - Tail @@ -21,10 +26,6 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0 - Legs? (optional) - Change camera position to be cow point of view - Add popping-floating text of funny cow thoughts -- Add menu - - Adjust ambient light - - help - - quit - Add multiple objects(that is not the cow) - User controlled light source - Add light source diff --git a/help.h b/help.h new file mode 100644 index 0000000..0edf616 --- /dev/null +++ b/help.h @@ -0,0 +1,9 @@ +const unsigned char helpString[] = +"World of Cow by Aviv Romem\n" +"Left/Middle mouse to control camera rotation/Position.\n" +"Scroll wheel to control camera zoom.\n" +"WASD keys to control the cow.\n" +"Different parts of the cow can be controlled by select\n a different part in the right click menu(under 'Control Cow').\n" +"Left click/scroll wheel on a slider to change its value.\n" +"ESC to close this popup, ESC again to exit the program.\n" +; \ No newline at end of file diff --git a/mmn_17.c b/mmn_17.c index 8e0fdeb..28d8f34 100644 --- a/mmn_17.c +++ b/mmn_17.c @@ -7,6 +7,7 @@ #include #include "ui.h" #include "grass_texture_color.h" +#include "help.h" // close enough #define PI 3.14 @@ -17,10 +18,17 @@ vec3 camCenter = { 0.0, 0.0, 0.0 }; vec3 camRot = { -PI * 0.125, 0.0, 0.0 }; struct { unsigned char lockYMovement: 1; + unsigned char showHelp: 1; GLenum textureFilter; } settings = { - 0, GL_NEAREST, + 0, 0, GL_NEAREST, }; +struct { + int main; + int cowControl; + int filters; +} menus; // to simply hold the menues in a labed manner + vec3 rotateByCameraRotation(vec3 v) { vec3 r; @@ -38,23 +46,7 @@ vec3 rotateByCameraRotation(vec3 v) { int lastMouseButton = GLUT_LEFT_BUTTON; int lastMouseX = 0, lastMouseY = 0; ui_slider* draggedSlider = NULL; -void changeFilterButton(); -void lockYButton(); -ui_button buttons[] = { - { - /* pos */ { { 0.9, 0.5, 0.0 }, { -65.0, -20.0, 0.0 } }, - /* size */ { 130.0, 40.0, 0.0 }, - /* onclick */ changeFilterButton, - /* text */ "Cycle filter", - 0 - }, - { - { { 0.9, 0.5, 0.0 }, { -50.0, 25.0, 0.0 } }, - { 100.0, 40.0, 0.0 }, - lockYButton, - "Lock Y" - } -}; +ui_button buttons[] = {}; // TODO: maybe delete? the menu thing is easier to work with ui_slider sliders[] = { { /* pos */ { { 0.9, 0.7, 0.0 }, { -50.0, -5.0, 0.0 } }, @@ -63,18 +55,6 @@ ui_slider sliders[] = { } }; -void changeFilterButton() { - static int current = 0; - GLenum filters[] = { GL_NEAREST, GL_LINEAR }; - current = (current + 1) % (sizeof(filters) / sizeof(GLenum)); - settings.textureFilter = filters[current]; - glutPostRedisplay(); -} -void lockYButton() { - settings.lockYMovement ^= 1; - buttons[1].text = settings.lockYMovement ? "Unlock Y" : "Lock Y"; -} - void drawUi(void) { glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); @@ -96,6 +76,16 @@ void drawUi(void) { ui_slider_draw(s); } + if(settings.showHelp) { + glColor3f(0.3, 0.3, 0.3); + glBegin(GL_QUADS); + glVertex3f(wWidth * 0.1, wHeight * 0.1, 0.0); + glVertex3f(wWidth * 0.9, wHeight * 0.1, 0.0); + glVertex3f(wWidth * 0.9, wHeight * 0.9, 0.0); + glVertex3f(wWidth * 0.1, wHeight * 0.9, 0.0); + glEnd(); + } + int err = glGetError(); if(err != 0) { printf("opengl error %d: %s\n", err, gluErrorString(err)); @@ -199,6 +189,15 @@ void mouseMotionEvent(int x, int y) { ui_slider_onclick(draggedSlider, x, y); } } + else { + // rotate the camera + camRot.y -= (x - lastMouseX) * PI * 0.01; + if(camRot.y > 2 * PI) camRot.y -= 2 * PI; + else if(camRot.y < 0.0) camRot.y += 2 * PI; + + camRot.x = fmin(PI * 0.5, fmax(-PI * 0.5, camRot.x - (y - lastMouseY) * 0.01 * PI)); + } + } else if(lastMouseButton == GLUT_MIDDLE_BUTTON) { vec3 moveX = rotateByCameraRotation(vec3_new(1.0, 0.0, 0.0)); @@ -212,14 +211,6 @@ void mouseMotionEvent(int x, int y) { camCenter = vec3_add(camCenter, vec3_mult(moveX, (lastMouseX - x))); camCenter = vec3_add(camCenter, vec3_mult(moveY, (y - lastMouseY))); } - else if(lastMouseButton == GLUT_RIGHT_BUTTON) { - // rotate the camera - camRot.y -= (x - lastMouseX) * PI * 0.01; - if(camRot.y > 2 * PI) camRot.y -= 2 * PI; - else if(camRot.y < 0.0) camRot.y += 2 * PI; - - camRot.x = fmin(PI * 0.5, fmax(-PI * 0.5, camRot.x - (y - lastMouseY) * 0.01 * PI)); - } lastMouseX = x; lastMouseY = y; glutPostRedisplay(); } @@ -242,14 +233,64 @@ void mouseWheelEvent(int wheel, int dir, int x, int y) { void keyboardEvent(unsigned char c, int x, int y) { if(c == '\e') { - glutLeaveMainLoop(); - exit(0); + if(settings.showHelp) { + settings.showHelp = 0; + glutPostRedisplay(); + } + else { + glutLeaveMainLoop(); + exit(0); + } } if(c == 'a') { glutPostRedisplay(); } } +void onMenuItem(int item) { + lastMouseButton = -1; // to prevent jumps in view position/rotation + switch(item) { + case 0: // Lock y + settings.lockYMovement ^= 1; + glutChangeToMenuEntry(3, settings.lockYMovement ? "Unlock Y position" : "Lock Y position", 0); + break; + case 2: // Show help + settings.showHelp ^= 1; + glutPostRedisplay(); + break; + } +} + +void onControlCowMenu(int item) { + lastMouseButton = GLUT_RIGHT_BUTTON; + printf("Control cow: %d\n", item); +} +void onFilterMenu(int item) { + lastMouseButton = GLUT_RIGHT_BUTTON; + GLenum filters[] = { GL_LINEAR, GL_NEAREST }; + settings.textureFilter = filters[item]; +} + +void menuSetup() { + // control cow sub-menu + menus.cowControl = glutCreateMenu(onControlCowMenu); + glutAddMenuEntry("Movement", 0); + glutAddMenuEntry("Head", 1); + glutAddMenuEntry("Tail", 2); + // filters + menus.filters = glutCreateMenu(onFilterMenu); + glutAddMenuEntry("Linear", 0); + glutAddMenuEntry("Nearest", 1); + + menus.main = glutCreateMenu(onMenuItem); + glutAddSubMenu("Control Cow", menus.cowControl); + glutAddSubMenu("Texture filters", menus.filters); + glutAddMenuEntry("Lock Y position", 0); + glutAddMenuEntry("Change to Cow POV", 1); + glutAddMenuEntry("Help", 2); + glutAttachMenu(GLUT_RIGHT_BUTTON); +} + int main(int argc, char** argv) { /* initialize glut and window */ glutInit(&argc, argv); @@ -263,6 +304,7 @@ int main(int argc, char** argv) { glutKeyboardFunc(keyboardEvent); glutMouseWheelFunc(mouseWheelEvent); glutMotionFunc(mouseMotionEvent); + menuSetup(); // set up some rendering related stuff glEnable(GL_CULL_FACE); glCullFace(GL_BACK);