comments!

This commit is contained in:
Rusty Striker 2023-08-09 18:27:55 +03:00
parent a1292ce40f
commit e2d8466e93
Signed by: RustyStriker
GPG key ID: 87E4D691632DFF15
8 changed files with 95 additions and 50 deletions

View file

@ -6,6 +6,5 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0
# TODO # 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 :/ - Properly comment the code :/
- Construct the required pdf with explanations and screenshots

57
cow.c
View file

@ -7,6 +7,7 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
// positional variables
vec3 headRot = { 0.0, 0.0, 0.0 }; vec3 headRot = { 0.0, 0.0, 0.0 };
const vec3 headLimit = { 30.0, 30.0, 45.0 }; const vec3 headLimit = { 30.0, 30.0, 45.0 };
vec3 tailRot = { 0.0, 0.0, 0.0 }; vec3 tailRot = { 0.0, 0.0, 0.0 };
@ -22,20 +23,21 @@ enum COW_CONTROL control;
float deg2rad(float deg) { float deg2rad(float deg) {
return deg * 3.14 / 180.0; 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) { float addAndWrapRot(float rot, float add) {
rot += add; rot += add;
if(rot > 180.0) { rot -= 360.0; } if(rot > 180.0) { rot -= 360.0; }
else if(rot < -180.0) { rot += 360.0; } else if(rot < -180.0) { rot += 360.0; }
return rot; return rot;
} }
/// Adds a rotation and makes sure the result is within the limit
float addAndLimitRot(float rot, float add, float limit) { float addAndLimitRot(float rot, float add, float limit) {
rot += add; rot += add;
if(rot > limit) { rot = limit; } if(rot > limit) { rot = limit; }
else if(rot < -limit) { rot = -limit; } else if(rot < -limit) { rot = -limit; }
return rot; return rot;
} }
// controls the cow movement based on keyboard input
void cowMove(char c) { void cowMove(char c) {
// check for rotations // check for rotations
cowRot = addAndWrapRot(cowRot, ((c == 'e') - (c == 'q')) * COW_ROT_SPEED); 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)); cowPos = vec3_add(cowPos, vec3_mult(r, COW_MOVE_SPEED));
glutPostRedisplay(); glutPostRedisplay();
} }
// conrols cow head rotation(movement is a result of the offset of rotation) on keyboard input
void cowHead(char c) { void cowHead(char c) {
headRot.z = addAndLimitRot(headRot.z, ((c == 'e') - (c == 'q')) * COW_ROT_SPEED, headLimit.z); 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.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); headRot.x = addAndLimitRot(headRot.x, ((c == 's') - (c == 'w')) * COW_ROT_SPEED, headLimit.x);
glutPostRedisplay(); glutPostRedisplay();
} }
// controls cow tail rotaion on keyboard input
void cowTail(char c) { void cowTail(char c) {
tailRot.y = addAndLimitRot(tailRot.y, ((c == 'a') - (c == 'd')) * COW_ROT_SPEED, tailLimit.y); 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); tailRot.x = addAndLimitRot(tailRot.x, ((c == 's') - (c == 'w')) * COW_ROT_SPEED, tailLimit.x);
glutPostRedisplay(); glutPostRedisplay();
} }
// Draws the cow... will skip drawing the head parts when in cow point of view
void drawCow(char cowsPOV) { void drawCow(char cowsPOV) {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
@ -76,47 +79,61 @@ void drawCow(char cowsPOV) {
glScalef(1.2, 1.2, 2.3); glScalef(1.2, 1.2, 2.3);
glutSolidSphere(1.0, 16, 16); glutSolidSphere(1.0, 16, 16);
glPopMatrix(); // cow body scale glPopMatrix(); // cow body scale
if(!cowsPOV) { if(!cowsPOV) { // only draw head if we are not looking from within it
// head // 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); glTranslatef(0.0, 1.0, 1.8);
glRotatef(headRot.y, 0.0, 1.0, 0.0); glRotatef(headRot.y, 0.0, 1.0, 0.0);
glRotatef(headRot.x, 1.0, 0.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); glRotatef(headRot.z, 0.0, 0.0 ,1.0);
glPushMatrix(); // head sphere 1 glPushMatrix(); // head sphere 1
glScalef(0.6, 0.4, 0.7); glScalef(0.6, 0.4, 0.7);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // head sphere 1 glPopMatrix(); // head sphere 1
glPushMatrix(); // head sphere 2 glPushMatrix(); // head sphere 2
glTranslatef(0.0, 0.3, -0.3); glTranslatef(0.0, 0.3, -0.3);
glScalef(0.6, 0.45, 0.75); glScalef(0.6, 0.45, 0.75);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); glPopMatrix();
// eyes :) // eyes :)
glColor3f(0.0,0.0,0.0); // Eyes black as night glColor3f(0.0,0.0,0.0); // Eyes black as night
glPushMatrix(); // eye 1 glPushMatrix(); // eye 1
glTranslatef(-0.3, 0.5, 0.0); glTranslatef(-0.3, 0.5, 0.0);
glScalef(0.17, 0.17, 0.17); glScalef(0.17, 0.17, 0.17);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // eye 1 glPopMatrix(); // eye 1
glPushMatrix(); // eye 2 glPushMatrix(); // eye 2
glTranslatef(0.3, 0.5, 0.0); glTranslatef(0.3, 0.5, 0.0);
glScalef(0.17, 0.17, 0.17); glScalef(0.17, 0.17, 0.17);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // eye 2 glPopMatrix(); // eye 2
glColor3f(0.8,0.4,0.11); // go back to the normal cow color 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 // EARS! they look like little pancakes to the side of the head
glPushMatrix(); // ear 1 glPushMatrix(); // ear 1
glTranslatef(-0.7, 0.5, -0.4); glTranslatef(-0.7, 0.5, -0.4);
glScalef(0.3, 0.18, 0.07); glScalef(0.3, 0.18, 0.07);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // ear 1 glPopMatrix(); // ear 1
glPushMatrix(); // ear 2 glPushMatrix(); // ear 2
glTranslatef(0.7, 0.5, -0.4); glTranslatef(0.7, 0.5, -0.4);
glScalef(0.3, 0.18, 0.07); glScalef(0.3, 0.18, 0.07);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // ear 2 glPopMatrix(); // ear 2
// Add a little teapon earing :D // Add a little teapon earing :D
glPushMatrix(); glPushMatrix();
glColor3f(1.0, 1.0, 1.0); 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(146.0, 0.0, 1.0, 0.0);
glRotatef(-90.0, 1.0, 0.0, 0.0); glRotatef(-90.0, 1.0, 0.0, 0.0);
glRotatef(90.0, 0.0, 1.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); glutSolidTeapot(0.17);
glCullFace(GL_BACK); glCullFace(GL_BACK); // reset face culling
glPopMatrix(); // teapot! glPopMatrix(); // teapot!
glPushMatrix(); // little nose glPushMatrix(); // little nose
glColor3f(0.9, 0.3, 0.4); glColor3f(0.9, 0.3, 0.4);
glTranslatef(0.0, 0.1, 0.6); glTranslatef(0.0, 0.1, 0.6);
glScalef(0.3, 0.15, 0.14); glScalef(0.3, 0.15, 0.14);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // little nose glPopMatrix(); // little nose
glPopMatrix(); // head center glPopMatrix(); // head center
} }
// tins // tins
glColor3f(0.9, 0.3, 0.4); glColor3f(0.9, 0.3, 0.4);
glPushMatrix(); // TINS! glPushMatrix(); // TINS!
glTranslatef(0.0, -1.0, -0.58); glTranslatef(0.0, -1.0, -0.58);
glScalef(0.7, 0.4, 0.7); glScalef(0.7, 0.4, 0.7);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // Thins! glPopMatrix(); // Thins!
glColor3f(0.8,0.4,0.11); // go back to the normal cow color 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 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),
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); glTranslatef(0.5 * legs[i].x, -1.2, 1.4 * legs[i].z);
glScalef(0.4, 1.2, 0.4); glScalef(0.4, 1.2, 0.4);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); glPopMatrix();
} }
// now a tail // now a tail
@ -163,7 +189,9 @@ void drawCow(char cowsPOV) {
glTranslatef(0.0, -0.83, 0.0); glTranslatef(0.0, -0.83, 0.0);
glScalef(0.2, 1.0, 0.2); glScalef(0.2, 1.0, 0.2);
glutSolidSphere(1.0, 8, 8); glutSolidSphere(1.0, 8, 8);
glPopMatrix(); // Tails(from sonic the hedgehog) glPopMatrix(); // Tails(from sonic the hedgehog)
// Give the cow a little flashlight because its dark outside // Give the cow a little flashlight because its dark outside
glPushMatrix(); // fl glPushMatrix(); // fl
glTranslatef(0.5, -1.2, 1.4); glTranslatef(0.5, -1.2, 1.4);
@ -184,12 +212,17 @@ void drawCow(char cowsPOV) {
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 30.0); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 30.0);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005);
glPopMatrix(); // fl glPopMatrix(); // fl
glPopMatrix(); // cow pos 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); glColor3f(1.0, 1.0, 1.0);
glDisable(GL_COLOR_MATERIAL); 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) { void onCowKeyboardInput(char key) {
switch(control) { switch(control) {
case COW_CONTROL_MOVE: case COW_CONTROL_MOVE:
@ -205,11 +238,11 @@ void onCowKeyboardInput(char key) {
break; break;
} }
} }
// updates the control mode, based on the right click submenu(the first one)
void updateCowControl(enum COW_CONTROL c) { void updateCowControl(enum COW_CONTROL c) {
control = c; control = c;
} }
// rotates the camera to the cow's perspective
void setCameraToCowPOV() { void setCameraToCowPOV() {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();

View file

@ -1,4 +1,4 @@
// grass texture taken from polyhaven, downscaled to 128x128 and transformed into a C array
const unsigned char grass_color_128[] = { 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, 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, 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,

1
help.h
View file

@ -1,3 +1,4 @@
// help text
const unsigned char helpString[] = const unsigned char helpString[] =
"World of Cow by Aviv Romem\n" "World of Cow by Aviv Romem\n"
"Left/Middle mouse to control camera rotation/Position.\n" "Left/Middle mouse to control camera rotation/Position.\n"

View file

@ -20,6 +20,7 @@ vec3 lightPos = { 0.0, 10, 25.0 };
float camRadius = 40.0; float camRadius = 40.0;
vec3 camCenter = { 0.0, 0.0, 0.0 }; vec3 camCenter = { 0.0, 0.0, 0.0 };
vec3 camRot = { -PI * 0.25, PI, 0.0 }; vec3 camRot = { -PI * 0.25, PI, 0.0 };
// some stuff to remember
struct { struct {
unsigned char lockYMovement: 1; unsigned char lockYMovement: 1;
unsigned char showHelp: 1; unsigned char showHelp: 1;
@ -34,15 +35,15 @@ struct {
int cowControl; int cowControl;
int filters; int filters;
} menus; // to simply hold the menues in a labed manner } menus; // to simply hold the menues in a labed manner
// holding the lists, although only 1 was used
struct { struct {
GLuint grass; GLuint grass;
} lists; } lists;
// Ui stuff // Ui stuff
int lastMouseButton = GLUT_LEFT_BUTTON; int lastMouseButton = GLUT_LEFT_BUTTON; // for camera movement/rotation, also used with the sliders
int lastMouseX = 0, lastMouseY = 0; int lastMouseX = 0, lastMouseY = 0; // for camera movement/rotation
ui_slider* draggedSlider = NULL; ui_slider* draggedSlider = NULL; // helps when dragging a slider
ui_slider sliders[] = { ui_slider sliders[] = {
{ // ambient red { // ambient red
/* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -10.0, 0.0 } }, /* 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, sliders + 1, sliders + 2, sliders + 3, sliders + 4, sliders + 5, sliders + 6,
sliders + 7, sliders + 8, sliders + 9, sliders + 10, sliders + 11 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() { void generateGrassVertexList() {
lists.grass = glGenLists(1); lists.grass = glGenLists(1);
glNewList(lists.grass, GL_COMPILE); 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 x = -50.0; x < 50.0; x += 1.0) {
for(float z = -50.0; z < 50.0; z += 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(); glPushMatrix();
glTranslatef(x, 0.0, z); glTranslatef(x, 0.0, z); // move the grass to the locaiton on grid
glRotatef(rand() % 360, 0.0, 1.0, 0.0); glRotatef(rand() % 360, 0.0, 1.0, 0.0); // rotate by a random amount
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);
glColor3f(0.0, 0.3, 0.0); glColor3f(0.0, 0.3, 0.0);
glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 0.0);
@ -152,7 +155,7 @@ void generateGrassVertexList() {
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glEndList(); 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) { void drawTree(float rad, float height) {
// Bark // Bark
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
@ -165,7 +168,7 @@ void drawTree(float rad, float height) {
glColor3f(0.0, 1.0, 0.0); glColor3f(0.0, 1.0, 0.0);
glPushMatrix(); glPushMatrix();
glTranslatef(0.0, height, 0.0); glTranslatef(0.0, height, 0.0);
// leaves, 5 green balls
vec3 ts[] = { vec3 ts[] = {
vec3_new(1.0, 0.0, 0.0), vec3_new(-1.0, 0.0, 0.0), 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), 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]; vec3 t = ts[i];
glPushMatrix(); glPushMatrix();
glTranslatef(t.x * rad, t.y * rad, t.z * rad); glTranslatef(t.x * rad, t.y * rad, t.z * rad);
glutSolidSphere(rad, 8, 8); glutSolidSphere(rad * 1.5, 8, 8);
glPopMatrix(); glPopMatrix();
} }
glPopMatrix(); glPopMatrix();
glColor3f(1.0, 1.0, 1.0); glColor3f(1.0, 1.0, 1.0);
glDisable(GL_COLOR_MATERIAL); glDisable(GL_COLOR_MATERIAL);
} }
// rotates a vector by the camera rotation
vec3 rotateByCameraRotation(vec3 v) { vec3 rotateByCameraRotation(vec3 v) {
vec3 r; vec3 r;
// rotate along the x axis(yz plane) // rotate along the x axis(yz plane)
@ -207,7 +210,7 @@ void drawUi(void) {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
gluOrtho2D(0.0, wWidth, 0.0, wHeight); gluOrtho2D(0.0, wWidth, 0.0, wHeight);
// draw sliders
for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) {
ui_slider_draw(s); ui_slider_draw(s);
} }
@ -231,7 +234,7 @@ void drawUi(void) {
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, t2); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, t2);
glRasterPos2f(140.0, wHeight * 0.9 - 10.0); glRasterPos2f(140.0, wHeight * 0.9 - 10.0);
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, side); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, side);
// show help if needed
if(settings.showHelp) { if(settings.showHelp) {
glColor3f(0.3, 0.3, 0.3); glColor3f(0.3, 0.3, 0.3);
glBegin(GL_QUADS); glBegin(GL_QUADS);
@ -244,7 +247,7 @@ void drawUi(void) {
glRasterPos2f(wWidth * 0.12, wHeight * 0.8); glRasterPos2f(wWidth * 0.12, wHeight * 0.8);
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, helpString); glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, helpString);
} }
// check for errors
int err = glGetError(); int err = glGetError();
if(err != 0) { if(err != 0) {
printf("opengl error %d: %s\n", err, gluErrorString(err)); printf("opengl error %d: %s\n", err, gluErrorString(err));
@ -256,7 +259,6 @@ void drawWorld(void) {
// set perspective camera // set perspective camera
GLdouble wWidth = (GLdouble) glutGet(GLUT_WINDOW_WIDTH); GLdouble wWidth = (GLdouble) glutGet(GLUT_WINDOW_WIDTH);
GLdouble wHeight = (GLdouble) glutGet(GLUT_WINDOW_HEIGHT); GLdouble wHeight = (GLdouble) glutGet(GLUT_WINDOW_HEIGHT);
// Calculate current camera position from rotation
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
@ -264,6 +266,7 @@ void drawWorld(void) {
setCameraToCowPOV(); setCameraToCowPOV();
} }
else { else {
// Calculate current camera position from rotation
vec3 cp = vec3_new(0.0, 0.0, camRadius); vec3 cp = vec3_new(0.0, 0.0, camRadius);
cp = rotateByCameraRotation(cp); cp = rotateByCameraRotation(cp);
cp = vec3_add(cp, camCenter); cp = vec3_add(cp, camCenter);
@ -305,7 +308,7 @@ void drawWorld(void) {
glPopMatrix(); glPopMatrix();
// World // World
drawCow(settings.cowsPOV); 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_MAG_FILTER, settings.textureFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); 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); glTexCoord2f(1.0, 0.0); glVertex3f(50.0, 0.0, -50.0);
glEnd(); glEnd();
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
// draw some trees
glPushMatrix(); glPushMatrix();
glTranslatef(25.0, 0.0, 25.0); glTranslatef(25.0, 0.0, 25.0);
drawTree(3.0, 20.0); drawTree(3.0, 20.0);
@ -362,10 +366,11 @@ void display(void) {
} }
void mouseEvent(int button, int state, int x, int y) { void mouseEvent(int button, int state, int x, int y) {
// save the last mouse position
lastMouseX = x; lastMouseY = y; lastMouseX = x; lastMouseY = y;
if(state == 0) lastMouseButton = button; if(state == 0) lastMouseButton = button;
if(state == 0 && button == GLUT_LEFT_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) { for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) {
if(ui_slider_mouse_over(s, x, y)) { if(ui_slider_mouse_over(s, x, y)) {
ui_slider_onclick(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) { else if(state == 1 && button == GLUT_LEFT_BUTTON) {
draggedSlider = NULL; draggedSlider = NULL;
} }
@ -381,7 +387,7 @@ void mouseEvent(int button, int state, int x, int y) {
void mouseMotionEvent(int x, int y) { void mouseMotionEvent(int x, int y) {
if(lastMouseButton == GLUT_LEFT_BUTTON) { if(lastMouseButton == GLUT_LEFT_BUTTON) {
if(draggedSlider != NULL) { if(draggedSlider != NULL) { // drag a slider if needed
if(ui_slider_mouse_over(draggedSlider, x, y)) { if(ui_slider_mouse_over(draggedSlider, x, y)) {
ui_slider_onclick(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) { else if(lastMouseButton == GLUT_MIDDLE_BUTTON) {
// drag the camera
vec3 moveX = rotateByCameraRotation(vec3_new(1.0, 0.0, 0.0)); vec3 moveX = rotateByCameraRotation(vec3_new(1.0, 0.0, 0.0));
vec3 moveY = rotateByCameraRotation(vec3_new(0.0, 1.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) { void mouseWheelEvent(int wheel, int dir, int x, int y) {
// slide a slider, if no sliders slided the zoom the camera
char slided = 0; char slided = 0;
for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) { for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) {
if(ui_slider_mouse_over(s, x, y)) { 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) { void keyboardEvent(unsigned char c, int x, int y) {
if(c == '\e') { if(c == '\e') { // exit help, or program
if(settings.showHelp) { if(settings.showHelp) {
settings.showHelp = 0; settings.showHelp = 0;
glutPostRedisplay(); glutPostRedisplay();
@ -452,7 +460,7 @@ void keyboardEvent(unsigned char c, int x, int y) {
glutPostRedisplay(); glutPostRedisplay();
} }
} }
// main right click menu
void onMenuItem(int item) { void onMenuItem(int item) {
lastMouseButton = -1; // to prevent jumps in view position/rotation lastMouseButton = -1; // to prevent jumps in view position/rotation
switch(item) { switch(item) {
@ -483,13 +491,13 @@ void onMenuItem(int item) {
} }
} }
// cow control sub menu
void onControlCowMenu(int item) { void onControlCowMenu(int item) {
lastMouseButton = GLUT_RIGHT_BUTTON; lastMouseButton = GLUT_RIGHT_BUTTON;
settings.controlLight = 0; settings.controlLight = 0;
updateCowControl(item); updateCowControl(item);
} }
// filter sub menu
void onFilterMenu(int item) { void onFilterMenu(int item) {
lastMouseButton = GLUT_RIGHT_BUTTON; lastMouseButton = GLUT_RIGHT_BUTTON;
GLenum filters[] = { GL_LINEAR, GL_NEAREST }; GLenum filters[] = { GL_LINEAR, GL_NEAREST };

8
ui.c
View file

@ -5,16 +5,16 @@
#include <GL/glut.h> #include <GL/glut.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <stdio.h> #include <stdio.h>
// 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 #define BACK_COLOR 0.3, 0.35, 0.35
void ui_slider_draw(ui_slider* s) { void ui_slider_draw(ui_slider* s) {
int wWidth = glutGet(GLUT_WINDOW_WIDTH); int wWidth = glutGet(GLUT_WINDOW_WIDTH);
int wHeight = glutGet(GLUT_WINDOW_HEIGHT); 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 pos = vec3_add(s->position.absolute, vec3_new(s->position.relative.x * wWidth, s->position.relative.y * wHeight, 0.0));
vec3 ext = s->size; vec3 ext = s->size;
// center position
vec3 slider = vec3_add(pos, vec3_new(ext.x * s->value, ext.y * 0.5, 0.0)); vec3 slider = vec3_add(pos, vec3_new(ext.x * s->value, ext.y * 0.5, 0.0));
glBegin(GL_QUADS); glBegin(GL_QUADS);
// draw background line // 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); glVertex3f(slider.x - ext.z, slider.y + ext.z, 0.0);
glEnd(); glEnd();
} }
// checks if the mouse is hovering over the slider
char ui_slider_mouse_over(ui_slider* s, int mouseX, int mouseY) { char ui_slider_mouse_over(ui_slider* s, int mouseX, int mouseY) {
int wWidth = glutGet(GLUT_WINDOW_WIDTH); int wWidth = glutGet(GLUT_WINDOW_WIDTH);
int wHeight = glutGet(GLUT_WINDOW_HEIGHT); int wHeight = glutGet(GLUT_WINDOW_HEIGHT);

3
vec.c
View file

@ -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 }; vec3 r = { a.x - b.x, a.y - b.y, a.z - b.z };
return r; 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 vec3_mult(vec3 a, float s) {
vec3 r = { a.x * s, a.y * s, a.z * s }; vec3 r = { a.x * s, a.y * s, a.z * s };

13
vec.h
View file

@ -1,20 +1,27 @@
#ifndef _VEC #ifndef _VEC
#define _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 { typedef struct _vec3 {
float x; float x;
float y; float y;
float z; float z;
} vec3; } vec3;
// (x, y, z)
vec3 vec3_new(float x, float y, float z); vec3 vec3_new(float x, float y, float z);
// (f, f, f)
vec3 vec3_splat(float f); vec3 vec3_splat(float f);
// a + b
vec3 vec3_add(vec3 a, vec3 b); vec3 vec3_add(vec3 a, vec3 b);
// a - b
vec3 vec3_sub(vec3 a, vec3 b); vec3 vec3_sub(vec3 a, vec3 b);
float vec3_dot(vec3 a, vec3 b);
vec3 vec3_mult(vec3 a, float s); 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 glVertexVec(vec3 v);
void glColorVec(vec3 v); void glColorVec(vec3 v);