diff --git a/Makefile b/Makefile index c1df8ca..17c1fe6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -OBJ = ui.o vec.o +OBJ = ui.o vec.o cow.o CFLAGS = -g -Wall build: $(OBJ) diff --git a/README.md b/README.md index 405b00e..2a6f367 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0 - Add menu - partially done - Adjust ambient light - - help - - quit - Allow changing the move/rotation speed(or just a multiplier) - Create a cow - Head @@ -20,15 +18,17 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0 - Nose - Eyes - Allow user control of the cow - - Movement - turn and move + - Movement - turn and move - WIP - Head - Tail - Legs? (optional) - Change camera position to be cow point of view - Add popping-floating text of funny cow thoughts - Add multiple objects(that is not the cow) + - at least 3 + - on needs to be metalic - User controlled light source - Add light source - move the light - change intensity -- Add Textures and stuff :) \ No newline at end of file +- Add Textures and stuff :)(optional) \ No newline at end of file diff --git a/cow.c b/cow.c new file mode 100644 index 0000000..8c6d807 --- /dev/null +++ b/cow.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include "cow.h" +#include "vec.h" +#include +#include + +vec3 headRot; +const vec3 headLimit = { 90.0, 90.0 ,90.0 }; + +vec3 cowPos = { 0.0, 6.0, 0.0 }; +float cowRot = 0.0; // rotation along the Y axis +const float COW_ROT_SPEED = 5.0; +const float COW_MOVE_SPEED = 1.0; + +enum COW_CONTROL control; + +float deg2rad(float deg) { + return deg * 3.14 / 180.0; +} + +void cowMove(char c) { + // check for rotations + cowRot += ((c == 'e') - (c == 'q')) * COW_ROT_SPEED; + if(cowRot > 180.0) { cowRot -= 360.0; } + else if(cowRot < -180.0) { cowRot += 360.0; } + printf("rot: %f\n", cowRot); + // movement + vec3 dir = vec3_new((c == 'd') - (c == 'a'), 0.0, (c == 'w') - (c == 's')); + vec3 r = vec3_splat(0.0); + float rot = deg2rad(cowRot); + r.z = cosf(rot) * dir.z + sinf(rot) * dir.x; + r.x = -sinf(rot) * dir.z + cosf(rot) * dir.x; + + cowPos = vec3_add(cowPos, vec3_mult(r, COW_MOVE_SPEED)); + glutPostRedisplay(); +} + +void drawCow() { + glMatrixMode(GL_MODELVIEW); + glEnable(GL_COLOR_MATERIAL); + glPushMatrix(); + // Main cow position - as center of cow body + glTranslatef(cowPos.x, cowPos.y, cowPos.z); + glRotatef(cowRot, 0.0, 1.0, 0.0); + // Draw cow body + glPushMatrix(); + glColor3f(0.8,0.4,0.11); + glScalef(1.0, 1.0, 1.5); + glutSolidSphere(4.0, 16, 16); + glPopMatrix(); + // head + glPushMatrix(); + glTranslatef(0.0, 0.0, 5.0); + glRotatef(headRot.y, 0.0, 1.0, 0.0); + glRotatef(headRot.x, 1.0, 0.0, 0.0); + glTranslatef(0.0, 0.0, 1.0); + glRotatef(headRot.z, 0.0, 0.0 ,1.0); + glutSolidSphere(2.0, 16, 16); + glPopMatrix(); + + glPopMatrix(); + glDisable(GL_COLOR_MATERIAL); +} +void onCowKeyboardInput(char key) { + switch(control) { + case COW_CONTROL_MOVE: + cowMove(key); + break; + default: + break; + } +} + +void updateCowControl(enum COW_CONTROL c) { + control = c; +} \ No newline at end of file diff --git a/cow.h b/cow.h new file mode 100644 index 0000000..b2f2784 --- /dev/null +++ b/cow.h @@ -0,0 +1,18 @@ +#ifndef COWS_ARE_COOL +#define COWS_ARE_COOL + +/* + Helper file(with cow.c) to de-clutter mmn_17.c by taking all cow logic to another file +*/ +enum COW_CONTROL { + COW_CONTROL_MOVE, + COW_CONTROL_HEAD, + COW_CONTROL_TAIL, + COW_CONTROL_NONE +}; + +void drawCow(); +void onCowKeyboardInput(char key); +void updateCowControl(enum COW_CONTROL control); + +#endif \ No newline at end of file diff --git a/help.h b/help.h index 0edf616..f3b095e 100644 --- a/help.h +++ b/help.h @@ -3,7 +3,8 @@ const unsigned char helpString[] = "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" +"QE to rotate cow(when in control movement mode).\n" +"Different parts of the cow can be controlled by selecting\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 28d8f34..d3fb301 100644 --- a/mmn_17.c +++ b/mmn_17.c @@ -8,12 +8,12 @@ #include "ui.h" #include "grass_texture_color.h" #include "help.h" +#include "cow.h" // close enough #define PI 3.14 - // Camera rotation and stuff -float camRadius = 10.0; +float camRadius = 40.0; vec3 camCenter = { 0.0, 0.0, 0.0 }; vec3 camRot = { -PI * 0.125, 0.0, 0.0 }; struct { @@ -48,11 +48,22 @@ int lastMouseX = 0, lastMouseY = 0; ui_slider* draggedSlider = NULL; 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 } }, + { // ambient red + /* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -10.0, 0.0 } }, /* size */ { 100.0, 10.0, 10.0 }, - 0.1 + 0.0 + }, + { // ambient green + /* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -40.0, 0.0 } }, + /* size */ { 100.0, 10.0, 10.0 }, + 0.0 + }, + { // ambient blue + /* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -70.0, 0.0 } }, + /* size */ { 100.0, 10.0, 10.0 }, + 0.3 } + }; void drawUi(void) { @@ -75,6 +86,13 @@ void drawUi(void) { for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { ui_slider_draw(s); } + // sliders labels + glColor3f(1.0, 1.0, 1.0); + unsigned char t[] = "Ambient light"; + glRasterPos2f(wWidth * 0.9 - glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, t) * 0.5, wHeight * 0.90 + 20.0); + glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, t); + glRasterPos2f(wWidth * 0.9 - 75.0, wHeight * 0.9 - 10.0); + glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, (unsigned char*)"r\ng\nb"); if(settings.showHelp) { glColor3f(0.3, 0.3, 0.3); @@ -84,6 +102,9 @@ void drawUi(void) { glVertex3f(wWidth * 0.9, wHeight * 0.9, 0.0); glVertex3f(wWidth * 0.1, wHeight * 0.9, 0.0); glEnd(); + glColor3f(1.0,1.0,1.0); + glRasterPos2f(wWidth * 0.12, wHeight * 0.8); + glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, helpString); } int err = glGetError(); @@ -94,7 +115,6 @@ void drawUi(void) { void drawWorld(void) { glEnable(GL_DEPTH_TEST); - // set perspective camera GLdouble wWidth = (GLdouble) glutGet(GLUT_WINDOW_WIDTH); GLdouble wHeight = (GLdouble) glutGet(GLUT_WINDOW_HEIGHT); @@ -112,11 +132,19 @@ void drawWorld(void) { gluPerspective(90, wWidth / wHeight , 1.0, 500.0); // Lights glEnable(GL_LIGHTING); + // Ambient light + GLfloat ambient[] = { sliders[0].value, sliders[1].value, sliders[2].value, 1.0 }; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); glEnable(GL_LIGHT0); // Directional light - aka light GLfloat light1[] = { 0.0, 1.0, 0.0, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light1); + GLfloat lightColor[] = {0.5, 0.4, 0.1, 1.0}; + glLightfv(GL_LIGHT0, GL_AMBIENT, lightColor); + glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor); + glLightfv(GL_LIGHT0, GL_SPECULAR, lightColor); // World + drawCow(); // Ground glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, settings.textureFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, settings.textureFilter); @@ -131,14 +159,6 @@ void drawWorld(void) { glTexCoord2f(1.0, 0.0); glVertex3f(50.0, 0.0, -50.0); glEnd(); glDisable(GL_TEXTURE_2D); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glTranslatef(0.0, 5.0, 0.0); - glScalef(3.0, 3.0, 3.0); - glColor3f(1.0, 1.0, 1.0); - glutSolidDodecahedron(); - glPopMatrix(); } void display(void) { @@ -242,9 +262,7 @@ void keyboardEvent(unsigned char c, int x, int y) { exit(0); } } - if(c == 'a') { - glutPostRedisplay(); - } + onCowKeyboardInput(c); } void onMenuItem(int item) { @@ -258,13 +276,23 @@ void onMenuItem(int item) { settings.showHelp ^= 1; glutPostRedisplay(); break; + case 3: // reste view + camRadius = 40.0; + camCenter = vec3_new(0.0, 0.0, 0.0); + camRot = vec3_new(-PI * 0.125, 0.0, 0.0); + glutPostRedisplay(); + break; + case 4: // quit + glutLeaveMainLoop(); + exit(0); } } void onControlCowMenu(int item) { lastMouseButton = GLUT_RIGHT_BUTTON; - printf("Control cow: %d\n", item); + updateCowControl(item); } + void onFilterMenu(int item) { lastMouseButton = GLUT_RIGHT_BUTTON; GLenum filters[] = { GL_LINEAR, GL_NEAREST }; @@ -274,9 +302,9 @@ void onFilterMenu(int item) { void menuSetup() { // control cow sub-menu menus.cowControl = glutCreateMenu(onControlCowMenu); - glutAddMenuEntry("Movement", 0); - glutAddMenuEntry("Head", 1); - glutAddMenuEntry("Tail", 2); + glutAddMenuEntry("Movement", COW_CONTROL_MOVE); + glutAddMenuEntry("Head", COW_CONTROL_HEAD); + glutAddMenuEntry("Tail", COW_CONTROL_TAIL); // filters menus.filters = glutCreateMenu(onFilterMenu); glutAddMenuEntry("Linear", 0); @@ -287,7 +315,9 @@ void menuSetup() { glutAddSubMenu("Texture filters", menus.filters); glutAddMenuEntry("Lock Y position", 0); glutAddMenuEntry("Change to Cow POV", 1); + glutAddMenuEntry("Reset view", 3); glutAddMenuEntry("Help", 2); + glutAddMenuEntry("Quit", 4); glutAttachMenu(GLUT_RIGHT_BUTTON); } @@ -298,7 +328,7 @@ int main(int argc, char** argv) { glutInitWindowSize(800, 500); glutInitWindowPosition(450, 450); /* create window and set callbacks */ - glutCreateWindow("World of Cow"); + glutCreateWindow("World of Cow - Aviv Romem"); glutDisplayFunc(display); glutMouseFunc(mouseEvent); glutKeyboardFunc(keyboardEvent);