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
- 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 <stdio.h>
// 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();

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[] = {
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,

1
help.h
View File

@ -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"

View File

@ -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 };

8
ui.c
View File

@ -5,16 +5,16 @@
#include <GL/glut.h>
#include <GL/gl.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
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);

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 };
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 };

13
vec.h
View File

@ -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);