diff --git a/README.md b/README.md index 91fe090..f920402 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,5 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0 # TODO -- Add popping-floating text of funny cow thoughts when in cow view -- Construct the required pdf with explanations and screenshots -- Properly comment the code :/ \ No newline at end of file +- Properly comment the code :/ +- Construct the required pdf with explanations and screenshots \ No newline at end of file diff --git a/cow.c b/cow.c index 8de0898..373837b 100644 --- a/cow.c +++ b/cow.c @@ -7,6 +7,7 @@ #include #include +// positional variables vec3 headRot = { 0.0, 0.0, 0.0 }; const vec3 headLimit = { 30.0, 30.0, 45.0 }; vec3 tailRot = { 0.0, 0.0, 0.0 }; @@ -22,20 +23,21 @@ enum COW_CONTROL control; float deg2rad(float deg) { return deg * 3.14 / 180.0; } - +/// Adds a rotation and wraps around(wraps around the +- 180 mark, so -190 turns to 170) float addAndWrapRot(float rot, float add) { rot += add; if(rot > 180.0) { rot -= 360.0; } else if(rot < -180.0) { rot += 360.0; } return rot; } +/// Adds a rotation and makes sure the result is within the limit float addAndLimitRot(float rot, float add, float limit) { rot += add; if(rot > limit) { rot = limit; } else if(rot < -limit) { rot = -limit; } return rot; } - +// controls the cow movement based on keyboard input void cowMove(char c) { // check for rotations cowRot = addAndWrapRot(cowRot, ((c == 'e') - (c == 'q')) * COW_ROT_SPEED); @@ -49,19 +51,20 @@ void cowMove(char c) { cowPos = vec3_add(cowPos, vec3_mult(r, COW_MOVE_SPEED)); glutPostRedisplay(); } - +// conrols cow head rotation(movement is a result of the offset of rotation) on keyboard input void cowHead(char c) { headRot.z = addAndLimitRot(headRot.z, ((c == 'e') - (c == 'q')) * COW_ROT_SPEED, headLimit.z); headRot.y = addAndLimitRot(headRot.y, ((c == 'a') - (c == 'd')) * COW_ROT_SPEED, headLimit.y); headRot.x = addAndLimitRot(headRot.x, ((c == 's') - (c == 'w')) * COW_ROT_SPEED, headLimit.x); glutPostRedisplay(); } +// controls cow tail rotaion on keyboard input void cowTail(char c) { tailRot.y = addAndLimitRot(tailRot.y, ((c == 'a') - (c == 'd')) * COW_ROT_SPEED, tailLimit.y); tailRot.x = addAndLimitRot(tailRot.x, ((c == 's') - (c == 'w')) * COW_ROT_SPEED, tailLimit.x); glutPostRedisplay(); } - +// Draws the cow... will skip drawing the head parts when in cow point of view void drawCow(char cowsPOV) { glMatrixMode(GL_MODELVIEW); glEnable(GL_COLOR_MATERIAL); @@ -76,47 +79,61 @@ void drawCow(char cowsPOV) { glScalef(1.2, 1.2, 2.3); glutSolidSphere(1.0, 16, 16); glPopMatrix(); // cow body scale - if(!cowsPOV) { + if(!cowsPOV) { // only draw head if we are not looking from within it // head - glPushMatrix(); // head center + glPushMatrix(); // head center - offset for the head rotation, allows for head movement relative to rotation easily glTranslatef(0.0, 1.0, 1.8); 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); + glPushMatrix(); // head sphere 1 glScalef(0.6, 0.4, 0.7); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // head sphere 1 + glPushMatrix(); // head sphere 2 glTranslatef(0.0, 0.3, -0.3); glScalef(0.6, 0.45, 0.75); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); + // eyes :) glColor3f(0.0,0.0,0.0); // Eyes black as night + glPushMatrix(); // eye 1 glTranslatef(-0.3, 0.5, 0.0); glScalef(0.17, 0.17, 0.17); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // eye 1 + glPushMatrix(); // eye 2 glTranslatef(0.3, 0.5, 0.0); glScalef(0.17, 0.17, 0.17); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // eye 2 + glColor3f(0.8,0.4,0.11); // go back to the normal cow color // EARS! they look like little pancakes to the side of the head + glPushMatrix(); // ear 1 glTranslatef(-0.7, 0.5, -0.4); glScalef(0.3, 0.18, 0.07); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // ear 1 + glPushMatrix(); // ear 2 glTranslatef(0.7, 0.5, -0.4); glScalef(0.3, 0.18, 0.07); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // ear 2 + // Add a little teapon earing :D glPushMatrix(); glColor3f(1.0, 1.0, 1.0); @@ -124,26 +141,34 @@ void drawCow(char cowsPOV) { glRotatef(146.0, 0.0, 1.0, 0.0); glRotatef(-90.0, 1.0, 0.0, 0.0); glRotatef(90.0, 0.0, 1.0, 0.0); - glCullFace(GL_FRONT); // for some reason, teapot normals are backwards to all other + glCullFace(GL_FRONT); // for some reason, teapot normals are backwards compared to other shapes, maybe a bug in freeglut 3.4.0-1(artix world repo) glutSolidTeapot(0.17); - glCullFace(GL_BACK); + glCullFace(GL_BACK); // reset face culling + glPopMatrix(); // teapot! + glPushMatrix(); // little nose glColor3f(0.9, 0.3, 0.4); glTranslatef(0.0, 0.1, 0.6); glScalef(0.3, 0.15, 0.14); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // little nose + glPopMatrix(); // head center } // tins glColor3f(0.9, 0.3, 0.4); + glPushMatrix(); // TINS! glTranslatef(0.0, -1.0, -0.58); glScalef(0.7, 0.4, 0.7); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // Thins! + glColor3f(0.8,0.4,0.11); // go back to the normal cow color + // looping over this array makes changes much easier as the legs should be mirrored in both x and z directions vec3 legs[] = { vec3_new(1.0, 0.0, 1.0), vec3_new(-1.0, 0.0, 1.0), vec3_new(1.0, 0.0, -1.0), vec3_new(-1.0, 0.0, -1.0) @@ -153,6 +178,7 @@ void drawCow(char cowsPOV) { glTranslatef(0.5 * legs[i].x, -1.2, 1.4 * legs[i].z); glScalef(0.4, 1.2, 0.4); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); } // now a tail @@ -163,7 +189,9 @@ void drawCow(char cowsPOV) { glTranslatef(0.0, -0.83, 0.0); glScalef(0.2, 1.0, 0.2); glutSolidSphere(1.0, 8, 8); + glPopMatrix(); // Tails(from sonic the hedgehog) + // Give the cow a little flashlight because its dark outside glPushMatrix(); // fl glTranslatef(0.5, -1.2, 1.4); @@ -184,12 +212,17 @@ void drawCow(char cowsPOV) { glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 30.0); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0); + glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005); + glPopMatrix(); // fl + glPopMatrix(); // cow pos + + // reset color material or else it will garbage all the colors next frame(for non color material enabled objects) glColor3f(1.0, 1.0, 1.0); glDisable(GL_COLOR_MATERIAL); } - +// controls which body part to move based on the `control` variable, called from the keyboard event callback of the main file void onCowKeyboardInput(char key) { switch(control) { case COW_CONTROL_MOVE: @@ -205,11 +238,11 @@ void onCowKeyboardInput(char key) { break; } } - +// updates the control mode, based on the right click submenu(the first one) void updateCowControl(enum COW_CONTROL c) { control = c; } - +// rotates the camera to the cow's perspective void setCameraToCowPOV() { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); diff --git a/grass_texture_color.h b/grass_texture_color.h index 5b7bfde..41cdea0 100644 --- a/grass_texture_color.h +++ b/grass_texture_color.h @@ -1,4 +1,4 @@ - +// grass texture taken from polyhaven, downscaled to 128x128 and transformed into a C array const unsigned char grass_color_128[] = { 0x56, 0x8b, 0x88, 0xff, 0x55, 0x87, 0x87, 0xff, 0x5d, 0x8a, 0x8d, 0xff, 0x5a, 0x81, 0x89, 0xff, 0x63, 0x87, 0x91, 0xff, 0x69, 0x8b, 0x98, 0xff, 0x5a, 0x7d, 0x8b, 0xff, 0x61, 0x86, 0x94, 0xff, 0x65, 0x8c, 0x9a, 0xff, 0x5b, 0x85, 0x92, 0xff, 0x5c, 0x86, 0x93, 0xff, 0x65, 0x8c, 0x9a, 0xff, 0x5c, 0x80, 0x90, 0xff, 0x76, 0x97, 0xa7, 0xff, 0x73, 0x8e, 0xa2, 0xff, 0x6f, 0x8a, 0x9e, 0xff, 0x68, 0x86, 0x99, 0xff, 0x6c, 0x8d, 0x9d, 0xff, 0x64, 0x86, 0x96, 0xff, 0x5d, 0x80, 0x8d, 0xff, 0x5f, 0x86, 0x8f, 0xff, 0x66, 0x8d, 0x95, 0xff, 0x5a, 0x7f, 0x87, 0xff, 0x71, 0x96, 0x9e, 0xff, 0x6a, 0x8a, 0x97, 0xff, 0x66, 0x86, 0x93, 0xff, 0x60, 0x7e, 0x8f, 0xff, 0x6b, 0x89, 0x9a, 0xff, 0x66, 0x87, 0x96, 0xff, 0x62, 0x85, 0x93, 0xff, 0x58, 0x7b, 0x88, 0xff, 0x56, 0x7f, 0x88, 0xff, 0x5a, 0x88, 0x8f, 0xff, 0x56, 0x86, 0x8a, 0xff, 0x5b, 0x8b, 0x8f, 0xff, 0x4f, 0x7f, 0x83, 0xff, 0x60, 0x8d, 0x90, 0xff, 0x66, 0x93, 0x96, 0xff, 0x5b, 0x85, 0x8a, 0xff, 0x4f, 0x79, 0x7e, 0xff, 0x51, 0x7b, 0x82, 0xff, 0x50, 0x7a, 0x81, 0xff, 0x5f, 0x88, 0x91, 0xff, 0x5e, 0x87, 0x90, 0xff, 0x56, 0x7d, 0x8b, 0xff, 0x57, 0x7e, 0x8c, 0xff, 0x56, 0x7f, 0x8e, 0xff, 0x61, 0x85, 0x95, 0xff, 0x6b, 0x86, 0x9a, 0xff, 0x60, 0x78, 0x8c, 0xff, 0x5b, 0x73, 0x89, 0xff, 0x71, 0x89, 0x9f, 0xff, 0x77, 0x92, 0xa7, 0xff, 0x75, 0x90, 0xa5, 0xff, 0x64, 0x7f, 0x93, 0xff, 0x68, 0x83, 0x97, 0xff, 0x64, 0x82, 0x95, 0xff, 0x63, 0x81, 0x92, 0xff, 0x60, 0x81, 0x91, 0xff, 0x55, 0x76, 0x85, 0xff, 0x64, 0x86, 0x93, 0xff, 0x60, 0x82, 0x8f, 0xff, 0x63, 0x86, 0x90, 0xff, 0x5f, 0x81, 0x8e, 0xff, 0x5e, 0x7b, 0x8a, 0xff, 0x50, 0x6f, 0x7e, 0xff, 0x51, 0x74, 0x81, 0xff, 0x5f, 0x89, 0x90, 0xff, 0x55, 0x85, 0x89, 0xff, 0x41, 0x74, 0x76, 0xff, 0x55, 0x85, 0x89, 0xff, 0x51, 0x7f, 0x86, 0xff, 0x57, 0x7e, 0x8c, 0xff, 0x67, 0x89, 0x99, 0xff, 0x73, 0x90, 0xa5, 0xff, 0x71, 0x8c, 0xa0, 0xff, 0x67, 0x82, 0x96, 0xff, 0x61, 0x7e, 0x8d, 0xff, 0x60, 0x7f, 0x8e, 0xff, 0x60, 0x82, 0x8f, 0xff, 0x67, 0x89, 0x99, 0xff, 0x64, 0x88, 0x98, 0xff, 0x60, 0x81, 0x94, 0xff, 0x65, 0x86, 0x99, 0xff, 0x6e, 0x8b, 0xa0, 0xff, 0x82, 0x9f, 0xb4, 0xff, 0x6b, 0x83, 0x9b, 0xff, 0x71, 0x89, 0xa1, 0xff, 0x78, 0x8c, 0xa5, 0xff, 0x73, 0x87, 0xa0, 0xff, 0x72, 0x86, 0x9f, 0xff, 0x71, 0x85, 0x9e, 0xff, 0x69, 0x7e, 0x94, 0xff, 0x7a, 0x8f, 0xa5, 0xff, 0x74, 0x89, 0x9e, 0xff, 0x68, 0x7d, 0x93, 0xff, 0x76, 0x87, 0xa1, 0xff, 0x62, 0x76, 0x8f, 0xff, 0x72, 0x8e, 0x9f, 0xff, 0x6a, 0x8d, 0x97, 0xff, 0x67, 0x91, 0x96, 0xff, 0x5c, 0x8d, 0x8b, 0xff, 0x57, 0x8c, 0x83, 0xff, 0x43, 0x7b, 0x70, 0xff, 0x4a, 0x7f, 0x72, 0xff, 0x58, 0x8a, 0x80, 0xff, 0x5c, 0x8a, 0x84, 0xff, 0x66, 0x8e, 0x8d, 0xff, 0x5c, 0x80, 0x88, 0xff, 0x75, 0x95, 0xa2, 0xff, 0x7c, 0x98, 0xa9, 0xff, 0x7b, 0x96, 0xaa, 0xff, 0x64, 0x81, 0x96, 0xff, 0x5e, 0x7b, 0x90, 0xff, 0x62, 0x80, 0x93, 0xff, 0x67, 0x85, 0x96, 0xff, 0x5c, 0x7d, 0x8d, 0xff, 0x5a, 0x7d, 0x8a, 0xff, 0x61, 0x87, 0x93, 0xff, 0x56, 0x81, 0x8a, 0xff, 0x54, 0x84, 0x8a, 0xff, 0x56, 0x8a, 0x90, 0xff, 0x45, 0x7c, 0x81, 0xff, 0x45, 0x7d, 0x82, 0xff, 0x51, 0x88, 0x8d, 0xff, 0x54, 0x8b, 0x90, 0xff, 0x55, 0x89, 0x8f, 0xff, 0x4b, 0x7f, 0x85, 0xff, 0x53, 0x84, 0x86, 0xff, 0x5d, 0x8d, 0x8f, 0xff, 0x61, 0x8b, 0x92, 0xff, 0x5c, 0x83, 0x8c, 0xff, 0x4c, 0x6e, 0x7b, 0xff, 0x63, 0x84, 0x93, 0xff, 0x63, 0x84, 0x94, 0xff, 0x6f, 0x91, 0xa1, 0xff, 0x64, 0x8b, 0x99, 0xff, 0x4b, 0x75, 0x82, 0xff, 0x50, 0x7a, 0x87, 0xff, 0x5e, 0x85, 0x93, 0xff, 0x60, 0x84, 0x94, 0xff, 0x64, 0x85, 0x95, 0xff, 0x62, 0x80, 0x93, 0xff, 0x64, 0x82, 0x95, 0xff, 0x60, 0x81, 0x91, 0xff, 0x74, 0x96, 0xa6, 0xff, 0x5d, 0x82, 0x90, 0xff, 0x59, 0x7f, 0x8b, 0xff, 0x59, 0x83, 0x8a, 0xff, 0x5e, 0x88, 0x8f, 0xff, 0x65, 0x8c, 0x94, 0xff, 0x68, 0x8d, 0x95, 0xff, 0x65, 0x88, 0x92, 0xff, 0x6e, 0x8e, 0x9b, 0xff, 0x72, 0x91, 0xa0, 0xff, 0x6a, 0x88, 0x99, 0xff, 0x6a, 0x89, 0x98, 0xff, 0x59, 0x7a, 0x89, 0xff, 0x58, 0x7b, 0x88, 0xff, 0x5e, 0x85, 0x8e, 0xff, 0x5d, 0x89, 0x90, 0xff, 0x5c, 0x8b, 0x8f, 0xff, 0x5f, 0x8e, 0x92, 0xff, 0x5f, 0x8e, 0x92, 0xff, 0x61, 0x8e, 0x92, 0xff, 0x64, 0x91, 0x95, 0xff, 0x5a, 0x84, 0x89, 0xff, 0x4f, 0x79, 0x7e, 0xff, 0x4b, 0x75, 0x7c, 0xff, 0x4c, 0x75, 0x7e, 0xff, 0x6b, 0x94, 0x9d, 0xff, 0x6a, 0x92, 0x9e, 0xff, 0x54, 0x7b, 0x89, 0xff, 0x65, 0x8c, 0x9a, 0xff, 0x69, 0x90, 0x9f, 0xff, 0x4e, 0x72, 0x82, 0xff, 0x69, 0x84, 0x98, 0xff, 0x70, 0x89, 0x9d, 0xff, 0x5c, 0x74, 0x8a, 0xff, 0x64, 0x7f, 0x94, 0xff, 0x6f, 0x8a, 0x9f, 0xff, 0x79, 0x94, 0xa9, 0xff, 0x7f, 0x9a, 0xae, 0xff, 0x69, 0x84, 0x98, 0xff, 0x70, 0x8e, 0xa1, 0xff, 0x61, 0x7f, 0x90, 0xff, 0x61, 0x82, 0x92, 0xff, 0x6d, 0x8e, 0x9d, 0xff, 0x59, 0x7b, 0x88, 0xff, 0x69, 0x8b, 0x98, 0xff, 0x65, 0x88, 0x92, 0xff, 0x65, 0x85, 0x92, 0xff, 0x5a, 0x79, 0x88, 0xff, 0x6e, 0x8d, 0x9c, 0xff, 0x62, 0x85, 0x92, 0xff, 0x59, 0x83, 0x8a, 0xff, 0x57, 0x87, 0x8b, 0xff, 0x59, 0x8c, 0x8e, 0xff, 0x57, 0x87, 0x8b, 0xff, 0x54, 0x82, 0x89, 0xff, 0x61, 0x88, 0x96, 0xff, 0x60, 0x82, 0x92, 0xff, 0x6d, 0x8b, 0x9e, 0xff, 0x7b, 0x96, 0xaa, 0xff, 0x69, 0x85, 0x96, 0xff, 0x6b, 0x88, 0x97, 0xff, 0x6c, 0x8b, 0x9a, 0xff, 0x63, 0x84, 0x93, 0xff, 0x61, 0x82, 0x92, 0xff, 0x62, 0x84, 0x94, 0xff, 0x6d, 0x8d, 0xa0, 0xff, 0x5f, 0x7f, 0x92, 0xff, 0x5d, 0x7a, 0x8f, 0xff, 0x67, 0x82, 0x97, 0xff, 0x6a, 0x82, 0x9a, 0xff, 0x79, 0x8f, 0xa8, 0xff, 0x7d, 0x93, 0xac, 0xff, 0x75, 0x89, 0xa2, 0xff, 0x7d, 0x91, 0xaa, 0xff, 0x67, 0x7b, 0x94, 0xff, 0x7e, 0x92, 0xab, 0xff, 0x6d, 0x84, 0x9a, 0xff, 0x70, 0x87, 0x9d, 0xff, 0x78, 0x8d, 0xa3, 0xff, 0x67, 0x7b, 0x94, 0xff, 0x6b, 0x81, 0x9a, 0xff, 0x6e, 0x8a, 0x9b, 0xff, 0x62, 0x84, 0x91, 0xff, 0x6a, 0x94, 0x99, 0xff, 0x5e, 0x8c, 0x8d, 0xff, 0x5a, 0x8e, 0x87, 0xff, 0x50, 0x85, 0x7c, 0xff, 0x51, 0x85, 0x7b, 0xff, 0x4e, 0x7f, 0x77, 0xff, 0x5c, 0x89, 0x86, 0xff, 0x5e, 0x85, 0x87, 0xff, 0x65, 0x89, 0x91, 0xff, 0x6a, 0x8a, 0x97, 0xff, 0x73, 0x8f, 0xa0, 0xff, 0x60, 0x7e, 0x91, 0xff, 0x6b, 0x88, 0x9d, 0xff, 0x62, 0x7f, 0x94, 0xff, 0x5a, 0x78, 0x8b, 0xff, 0x54, 0x75, 0x85, 0xff, 0x62, 0x83, 0x93, 0xff, 0x5d, 0x80, 0x8e, 0xff, 0x5b, 0x81, 0x8d, 0xff, 0x51, 0x7c, 0x85, 0xff, 0x45, 0x74, 0x7c, 0xff, 0x40, 0x72, 0x78, 0xff, 0x42, 0x79, 0x7e, 0xff, 0x44, 0x7b, 0x80, 0xff, 0x4d, 0x84, 0x89, 0xff, 0x47, 0x7b, 0x81, 0xff, 0x45, 0x79, 0x7f, 0xff, 0x4b, 0x7d, 0x83, 0xff, diff --git a/help.h b/help.h index f3b095e..be725b1 100644 --- a/help.h +++ b/help.h @@ -1,3 +1,4 @@ +// help text const unsigned char helpString[] = "World of Cow by Aviv Romem\n" "Left/Middle mouse to control camera rotation/Position.\n" diff --git a/mmn_17.c b/mmn_17.c index bb642a6..89a8b80 100644 --- a/mmn_17.c +++ b/mmn_17.c @@ -20,6 +20,7 @@ vec3 lightPos = { 0.0, 10, 25.0 }; float camRadius = 40.0; vec3 camCenter = { 0.0, 0.0, 0.0 }; vec3 camRot = { -PI * 0.25, PI, 0.0 }; +// some stuff to remember struct { unsigned char lockYMovement: 1; unsigned char showHelp: 1; @@ -34,15 +35,15 @@ struct { int cowControl; int filters; } menus; // to simply hold the menues in a labed manner - +// holding the lists, although only 1 was used struct { GLuint grass; } lists; // Ui stuff -int lastMouseButton = GLUT_LEFT_BUTTON; -int lastMouseX = 0, lastMouseY = 0; -ui_slider* draggedSlider = NULL; +int lastMouseButton = GLUT_LEFT_BUTTON; // for camera movement/rotation, also used with the sliders +int lastMouseX = 0, lastMouseY = 0; // for camera movement/rotation +ui_slider* draggedSlider = NULL; // helps when dragging a slider ui_slider sliders[] = { { // ambient red /* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -10.0, 0.0 } }, @@ -123,17 +124,19 @@ struct { sliders, sliders + 1, sliders + 2, sliders + 3, sliders + 4, sliders + 5, sliders + 6, sliders + 7, sliders + 8, sliders + 9, sliders + 10, sliders + 11 }; - +// generate a list for the grass, using a list makes it much faster +// and the correct way to make them wiggle a bit(wind) is using a vertex shader +// but that was not in the scope of the course void generateGrassVertexList() { lists.grass = glGenLists(1); glNewList(lists.grass, GL_COMPILE); - glDisable(GL_CULL_FACE); + glDisable(GL_CULL_FACE); // disable culling so we could see the grass from both directions for(float x = -50.0; x < 50.0; x += 1.0) { for(float z = -50.0; z < 50.0; z += 1.0) { - float tx = -0.03 * (rand() % 21), tz = -0.03 * (rand() % 21); + float tx = -0.03 * (rand() % 21), tz = -0.03 * (rand() % 21); // give the grass a bit of randomness in their looks glPushMatrix(); - glTranslatef(x, 0.0, z); - glRotatef(rand() % 360, 0.0, 1.0, 0.0); + glTranslatef(x, 0.0, z); // move the grass to the locaiton on grid + glRotatef(rand() % 360, 0.0, 1.0, 0.0); // rotate by a random amount glBegin(GL_TRIANGLES); glColor3f(0.0, 0.3, 0.0); glVertex3f(0.0, 0.0, 0.0); @@ -152,7 +155,7 @@ void generateGrassVertexList() { glEnable(GL_CULL_FACE); glEndList(); } - +// draws a tree based on the radius and the height in a location based on the matrix stack void drawTree(float rad, float height) { // Bark glEnable(GL_COLOR_MATERIAL); @@ -165,7 +168,7 @@ void drawTree(float rad, float height) { glColor3f(0.0, 1.0, 0.0); glPushMatrix(); glTranslatef(0.0, height, 0.0); - + // leaves, 5 green balls vec3 ts[] = { vec3_new(1.0, 0.0, 0.0), vec3_new(-1.0, 0.0, 0.0), vec3_new(0.0, 0.0, -1.0), vec3_new(0.0, 0.0, 1.0), @@ -175,14 +178,14 @@ void drawTree(float rad, float height) { vec3 t = ts[i]; glPushMatrix(); glTranslatef(t.x * rad, t.y * rad, t.z * rad); - glutSolidSphere(rad, 8, 8); + glutSolidSphere(rad * 1.5, 8, 8); glPopMatrix(); } glPopMatrix(); glColor3f(1.0, 1.0, 1.0); glDisable(GL_COLOR_MATERIAL); } - +// rotates a vector by the camera rotation vec3 rotateByCameraRotation(vec3 v) { vec3 r; // rotate along the x axis(yz plane) @@ -207,7 +210,7 @@ void drawUi(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, wWidth, 0.0, wHeight); - + // draw sliders for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { ui_slider_draw(s); } @@ -231,7 +234,7 @@ void drawUi(void) { glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, t2); glRasterPos2f(140.0, wHeight * 0.9 - 10.0); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, side); - + // show help if needed if(settings.showHelp) { glColor3f(0.3, 0.3, 0.3); glBegin(GL_QUADS); @@ -244,7 +247,7 @@ void drawUi(void) { glRasterPos2f(wWidth * 0.12, wHeight * 0.8); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, helpString); } - + // check for errors int err = glGetError(); if(err != 0) { printf("opengl error %d: %s\n", err, gluErrorString(err)); @@ -256,7 +259,6 @@ void drawWorld(void) { // set perspective camera GLdouble wWidth = (GLdouble) glutGet(GLUT_WINDOW_WIDTH); GLdouble wHeight = (GLdouble) glutGet(GLUT_WINDOW_HEIGHT); - // Calculate current camera position from rotation glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -264,6 +266,7 @@ void drawWorld(void) { setCameraToCowPOV(); } else { + // Calculate current camera position from rotation vec3 cp = vec3_new(0.0, 0.0, camRadius); cp = rotateByCameraRotation(cp); cp = vec3_add(cp, camCenter); @@ -305,7 +308,7 @@ void drawWorld(void) { glPopMatrix(); // World drawCow(settings.cowsPOV); - // Ground + // Ground - with a low res grass texture glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, settings.textureFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, settings.textureFilter); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, grass_color_128); @@ -319,6 +322,7 @@ void drawWorld(void) { glTexCoord2f(1.0, 0.0); glVertex3f(50.0, 0.0, -50.0); glEnd(); glDisable(GL_TEXTURE_2D); + // draw some trees glPushMatrix(); glTranslatef(25.0, 0.0, 25.0); drawTree(3.0, 20.0); @@ -362,10 +366,11 @@ void display(void) { } void mouseEvent(int button, int state, int x, int y) { + // save the last mouse position lastMouseX = x; lastMouseY = y; if(state == 0) lastMouseButton = button; if(state == 0 && button == GLUT_LEFT_BUTTON) { - + // check if a slider needs to be dragged for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { if(ui_slider_mouse_over(s, x, y)) { ui_slider_onclick(s, x, y); @@ -373,6 +378,7 @@ void mouseEvent(int button, int state, int x, int y) { } } } + // release the dragged slider(if there was one) else if(state == 1 && button == GLUT_LEFT_BUTTON) { draggedSlider = NULL; } @@ -381,7 +387,7 @@ void mouseEvent(int button, int state, int x, int y) { void mouseMotionEvent(int x, int y) { if(lastMouseButton == GLUT_LEFT_BUTTON) { - if(draggedSlider != NULL) { + if(draggedSlider != NULL) { // drag a slider if needed if(ui_slider_mouse_over(draggedSlider, x, y)) { ui_slider_onclick(draggedSlider, x, y); } @@ -398,6 +404,7 @@ void mouseMotionEvent(int x, int y) { } else if(lastMouseButton == GLUT_MIDDLE_BUTTON) { + // drag the camera vec3 moveX = rotateByCameraRotation(vec3_new(1.0, 0.0, 0.0)); vec3 moveY = rotateByCameraRotation(vec3_new(0.0, 1.0, 0.0)); @@ -414,6 +421,7 @@ void mouseMotionEvent(int x, int y) { } void mouseWheelEvent(int wheel, int dir, int x, int y) { + // slide a slider, if no sliders slided the zoom the camera char slided = 0; for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { if(ui_slider_mouse_over(s, x, y)) { @@ -430,7 +438,7 @@ void mouseWheelEvent(int wheel, int dir, int x, int y) { } void keyboardEvent(unsigned char c, int x, int y) { - if(c == '\e') { + if(c == '\e') { // exit help, or program if(settings.showHelp) { settings.showHelp = 0; glutPostRedisplay(); @@ -452,7 +460,7 @@ void keyboardEvent(unsigned char c, int x, int y) { glutPostRedisplay(); } } - +// main right click menu void onMenuItem(int item) { lastMouseButton = -1; // to prevent jumps in view position/rotation switch(item) { @@ -483,13 +491,13 @@ void onMenuItem(int item) { } } - +// cow control sub menu void onControlCowMenu(int item) { lastMouseButton = GLUT_RIGHT_BUTTON; settings.controlLight = 0; updateCowControl(item); } - +// filter sub menu void onFilterMenu(int item) { lastMouseButton = GLUT_RIGHT_BUTTON; GLenum filters[] = { GL_LINEAR, GL_NEAREST }; diff --git a/ui.c b/ui.c index 140e6b0..130f836 100644 --- a/ui.c +++ b/ui.c @@ -5,16 +5,16 @@ #include #include #include - +// originally i also had a ui button, but the right click menu made it much simpler, but that was to allow easily changing the colors for both buttons and sliders #define BACK_COLOR 0.3, 0.35, 0.35 void ui_slider_draw(ui_slider* s) { int wWidth = glutGet(GLUT_WINDOW_WIDTH); int wHeight = glutGet(GLUT_WINDOW_HEIGHT); - + // calculate position based on the different ui_pos items vec3 pos = vec3_add(s->position.absolute, vec3_new(s->position.relative.x * wWidth, s->position.relative.y * wHeight, 0.0)); vec3 ext = s->size; - + // center position vec3 slider = vec3_add(pos, vec3_new(ext.x * s->value, ext.y * 0.5, 0.0)); glBegin(GL_QUADS); // draw background line @@ -31,7 +31,7 @@ void ui_slider_draw(ui_slider* s) { glVertex3f(slider.x - ext.z, slider.y + ext.z, 0.0); glEnd(); } - +// checks if the mouse is hovering over the slider char ui_slider_mouse_over(ui_slider* s, int mouseX, int mouseY) { int wWidth = glutGet(GLUT_WINDOW_WIDTH); int wHeight = glutGet(GLUT_WINDOW_HEIGHT); diff --git a/vec.c b/vec.c index 93c40d1..31aa3a0 100644 --- a/vec.c +++ b/vec.c @@ -20,9 +20,6 @@ vec3 vec3_sub(vec3 a, vec3 b) { vec3 r = { a.x - b.x, a.y - b.y, a.z - b.z }; return r; } -float vec3_dot(vec3 a, vec3 b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -} vec3 vec3_mult(vec3 a, float s) { vec3 r = { a.x * s, a.y * s, a.z * s }; diff --git a/vec.h b/vec.h index 6e4162f..45d90b9 100644 --- a/vec.h +++ b/vec.h @@ -1,20 +1,27 @@ #ifndef _VEC #define _VEC +// Vectors and matrices are really useful when doing 2D/3D, esp in games +// sadly, i did not really need much more than that, and even the limited usage i had was not as fun as usual +// because the way C doesnt allow to define different operators for structs(that is, i cannot do vec3 + vec3) +// I know i could have chosen to use c++ or python but i oppose using c++ and decided to take the opportunity to work +// on my C programming skills(and i also dont like python) typedef struct _vec3 { float x; float y; float z; } vec3; - +// (x, y, z) vec3 vec3_new(float x, float y, float z); +// (f, f, f) vec3 vec3_splat(float f); +// a + b vec3 vec3_add(vec3 a, vec3 b); +// a - b vec3 vec3_sub(vec3 a, vec3 b); -float vec3_dot(vec3 a, vec3 b); vec3 vec3_mult(vec3 a, float s); -// Some opengl extensions to support these vectors +// Some opengl extensions to support these vectors - more could be defined, but the usage of the vec struct was annoying void glVertexVec(vec3 v); void glColorVec(vec3 v);