Compare commits
3 commits
60024859bf
...
a1292ce40f
Author | SHA1 | Date | |
---|---|---|---|
a1292ce40f | |||
790fee53b5 | |||
2fe1b677b7 |
5 changed files with 141 additions and 100 deletions
|
@ -6,9 +6,6 @@ Code here is published under the [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0
|
|||
|
||||
# TODO
|
||||
|
||||
- User controlled light source
|
||||
- Add light source
|
||||
- move the light
|
||||
- change intensity
|
||||
- Add popping-floating text of funny cow thoughts when in cow view
|
||||
- Add Textures and stuff :)(optional)
|
||||
- Construct the required pdf with explanations and screenshots
|
||||
- Properly comment the code :/
|
25
cow.c
25
cow.c
|
@ -1,3 +1,4 @@
|
|||
#include <GL/freeglut.h>
|
||||
#include <GL/freeglut_std.h>
|
||||
#include <GL/glut.h>
|
||||
#include <GL/gl.h>
|
||||
|
@ -163,10 +164,32 @@ void drawCow(char cowsPOV) {
|
|||
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);
|
||||
glColor3f(0.3, 0.3 ,0.3);
|
||||
glutSolidCylinder(0.3, 2.0, 8, 1);
|
||||
glTranslatef(0.0, 0.0, 2.0);
|
||||
glRotatef(180.0, 0.0, 1.0, 0.0);
|
||||
glutSolidCone(0.6, 0.6, 8, 2);
|
||||
glEnable(GL_LIGHT0);
|
||||
// Directional light - aka light
|
||||
GLfloat light1[] = { 0.0, 0.0, 0.0, 1.0 };
|
||||
GLfloat lightColor[] = {0.9, 0.9, 0.1, 1.0};
|
||||
GLfloat dir[] = { 0.0, 0.0, -1.0 };
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, light1);
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, lightColor);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, lightColor);
|
||||
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);
|
||||
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 30.0);
|
||||
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);
|
||||
glPopMatrix(); // fl
|
||||
glPopMatrix(); // cow pos
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
}
|
||||
|
||||
void onCowKeyboardInput(char key) {
|
||||
switch(control) {
|
||||
case COW_CONTROL_MOVE:
|
||||
|
@ -199,6 +222,6 @@ void setCameraToCowPOV() {
|
|||
glRotatef(-headRot.y, 0.0, 1.0, 0.0);
|
||||
glTranslatef(0.0, 0.0, -5.0);
|
||||
// body
|
||||
glTranslatef(-cowPos.x, -cowPos.y, -cowPos.z);
|
||||
glRotatef(-cowRot, 0.0, 1.0, 0.0);
|
||||
glTranslatef(-cowPos.x, -cowPos.y, -cowPos.z);
|
||||
}
|
148
mmn_17.c
148
mmn_17.c
|
@ -13,6 +13,9 @@
|
|||
// close enough
|
||||
#define PI 3.14
|
||||
|
||||
// user controlled light thing
|
||||
vec3 lightPos = { 0.0, 10, 25.0 };
|
||||
|
||||
// Camera rotation and stuff
|
||||
float camRadius = 40.0;
|
||||
vec3 camCenter = { 0.0, 0.0, 0.0 };
|
||||
|
@ -21,10 +24,10 @@ struct {
|
|||
unsigned char lockYMovement: 1;
|
||||
unsigned char showHelp: 1;
|
||||
unsigned char cowsPOV: 1;
|
||||
unsigned char controlLight: 1;
|
||||
GLenum textureFilter;
|
||||
|
||||
} settings = {
|
||||
0, 0, 0, GL_NEAREST,
|
||||
0, 0, 0, 0, GL_NEAREST,
|
||||
};
|
||||
struct {
|
||||
int main;
|
||||
|
@ -40,22 +43,21 @@ struct {
|
|||
int lastMouseButton = GLUT_LEFT_BUTTON;
|
||||
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[] = {
|
||||
{ // ambient red
|
||||
/* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -10.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.0
|
||||
0.1
|
||||
},
|
||||
{ // ambient green
|
||||
/* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -40.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.0
|
||||
0.1
|
||||
},
|
||||
{ // ambient blue
|
||||
/* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -70.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.3
|
||||
0.1
|
||||
},
|
||||
{ // drag speed
|
||||
/* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -120.0, 0.0 } },
|
||||
|
@ -66,7 +68,60 @@ ui_slider sliders[] = {
|
|||
/* pos */ { { 0.9, 0.9, 0.0 }, { -50.0, -170.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.3
|
||||
}
|
||||
},
|
||||
{ // user light - red
|
||||
/* pos */ { { 0., 0.9, 0.0 }, { 20.0, -10.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.0
|
||||
},
|
||||
{ // user light - green
|
||||
/* pos */ { { 0.0, 0.9, 0.0 }, { 20.0, -40.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.0
|
||||
},
|
||||
{ // user light - blue
|
||||
/* pos */ { { 0.0, 0.9, 0.0 }, { 20.0, -70.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
1.0
|
||||
},
|
||||
{ // user light - movement step
|
||||
/* pos */ { { 0.0, 0.9, 0.0 }, { 20.0, -100.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.2
|
||||
},
|
||||
{ // user light - constant attenuation
|
||||
/* pos */ { { 0.0, 0.9, 0.0 }, { 20.0, -130.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.0
|
||||
},
|
||||
{ // user light - linear attenuation
|
||||
/* pos */ { { 0.0, 0.9, 0.0 }, { 20.0, -160.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.0
|
||||
},
|
||||
{ // user light - cubic attenuation
|
||||
/* pos */ { { 0.0, 0.9, 0.0 }, { 20.0, -190.0, 0.0 } },
|
||||
/* size */ { 100.0, 10.0, 10.0 },
|
||||
0.5
|
||||
},
|
||||
};
|
||||
// sliders named, struct to give sliders a name, they are stored in an array to ease handling them
|
||||
struct {
|
||||
ui_slider* ambientRed;
|
||||
ui_slider* ambientGreen;
|
||||
ui_slider* ambientBlue;
|
||||
ui_slider* dragSpeed;
|
||||
ui_slider* rotSpeed;
|
||||
ui_slider* lightRed;
|
||||
ui_slider* lightGreen;
|
||||
ui_slider* lightBlue;
|
||||
ui_slider* lightMove;
|
||||
ui_slider* lightConAtten;
|
||||
ui_slider* lightLinAtten;
|
||||
ui_slider* lightQuadAtten;
|
||||
} slidersN = {
|
||||
sliders, sliders + 1, sliders + 2, sliders + 3, sliders + 4, sliders + 5, sliders + 6,
|
||||
sliders + 7, sliders + 8, sliders + 9, sliders + 10, sliders + 11
|
||||
};
|
||||
|
||||
void generateGrassVertexList() {
|
||||
|
@ -153,10 +208,6 @@ void drawUi(void) {
|
|||
glLoadIdentity();
|
||||
gluOrtho2D(0.0, wWidth, 0.0, wHeight);
|
||||
|
||||
// Draw buttons
|
||||
for(ui_button* b = buttons; b < buttons + sizeof buttons / sizeof(ui_button); b += 1) {
|
||||
ui_button_draw(b);
|
||||
}
|
||||
for(ui_slider* s = sliders; s < sliders + sizeof sliders / sizeof(ui_slider); s += 1) {
|
||||
ui_slider_draw(s);
|
||||
}
|
||||
|
@ -173,6 +224,13 @@ void drawUi(void) {
|
|||
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, td);
|
||||
glRasterPos2f(wWidth * 0.9 - glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, tr) * 0.5, wHeight * 0.9 - 150.0);
|
||||
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, tr);
|
||||
// light sliders
|
||||
unsigned char t2[] = "Light orb";
|
||||
unsigned char side[] = "r\ng\nb\nSpeed\nConstant Atten\nLinear Atten\nQuadraic Atten";
|
||||
glRasterPos2f(10.0, wHeight * 0.9 + 20.0);
|
||||
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, t2);
|
||||
glRasterPos2f(140.0, wHeight * 0.9 - 10.0);
|
||||
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, side);
|
||||
|
||||
if(settings.showHelp) {
|
||||
glColor3f(0.3, 0.3, 0.3);
|
||||
|
@ -219,16 +277,32 @@ void drawWorld(void) {
|
|||
glEnable(GL_LIGHTING);
|
||||
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
|
||||
// Ambient light
|
||||
GLfloat ambient[] = { sliders[0].value, sliders[1].value, sliders[2].value, 1.0 };
|
||||
GLfloat ambient[] = { slidersN.ambientRed->value, slidersN.ambientGreen->value, slidersN.ambientBlue->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);
|
||||
// GL_LIGHT0 is reserved for the cow's flashlight
|
||||
// user light
|
||||
glEnable(GL_LIGHT1);
|
||||
GLfloat ulPos[] = { lightPos.x, lightPos.y, lightPos.z, 1.0 };
|
||||
GLfloat ulColor[] = { slidersN.lightRed->value, slidersN.lightGreen->value, slidersN.lightBlue->value, 1.0 };
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, ulPos);
|
||||
glLightfv(GL_LIGHT1, GL_AMBIENT, ulColor);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, ulColor);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, ulColor);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, slidersN.lightConAtten->value * 5.0 + 0.01);
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, slidersN.lightLinAtten->value * 0.3);
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, slidersN.lightQuadAtten->value * 0.01);
|
||||
// draw a little glowing orb where it stands
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glTranslatef(lightPos.x, lightPos.y, lightPos.z);
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, ulColor);
|
||||
glutSolidSphere(1.0, 8, 8);
|
||||
GLfloat reset[] = { 0.0, 0.0, 0.0, 1.0 };
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, reset);
|
||||
glDisable(GL_COLOR_MATERIAL);
|
||||
glPopMatrix();
|
||||
// World
|
||||
drawCow(settings.cowsPOV);
|
||||
// Ground
|
||||
|
@ -291,11 +365,7 @@ void mouseEvent(int button, int state, int x, int y) {
|
|||
lastMouseX = x; lastMouseY = y;
|
||||
if(state == 0) lastMouseButton = button;
|
||||
if(state == 0 && button == GLUT_LEFT_BUTTON) {
|
||||
for(ui_button* b = buttons; b < buttons + sizeof buttons / sizeof(ui_button); b += 1) {
|
||||
if(ui_button_mouse_over(b, x, y) && b->onClick != NULL) {
|
||||
b->clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -305,12 +375,6 @@ void mouseEvent(int button, int state, int x, int y) {
|
|||
}
|
||||
else if(state == 1 && button == GLUT_LEFT_BUTTON) {
|
||||
draggedSlider = NULL;
|
||||
for(ui_button* b = buttons; b < buttons + sizeof buttons / sizeof(ui_button); b += 1) {
|
||||
b->clicked = 0;
|
||||
if(ui_button_mouse_over(b, x, y) && b->onClick != NULL) {
|
||||
b->onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
glutPostRedisplay();
|
||||
}
|
||||
|
@ -324,7 +388,7 @@ void mouseMotionEvent(int x, int y) {
|
|||
}
|
||||
else {
|
||||
// rotate the camera
|
||||
float speed = sliders[4].value * 0.095 + 0.005;
|
||||
float speed = slidersN.rotSpeed->value * 0.095 + 0.005;
|
||||
camRot.y -= (x - lastMouseX) * speed;
|
||||
if(camRot.y > 2 * PI) camRot.y -= 2 * PI;
|
||||
else if(camRot.y < 0.0) camRot.y += 2 * PI;
|
||||
|
@ -341,7 +405,7 @@ void mouseMotionEvent(int x, int y) {
|
|||
moveX.y = 0;
|
||||
moveY.y = 0;
|
||||
}
|
||||
float speed = sliders[3].value * 0.9 + 0.1;
|
||||
float speed = slidersN.dragSpeed->value * 0.9 + 0.1;
|
||||
camCenter = vec3_add(camCenter, vec3_mult(moveX, (lastMouseX - x) * speed));
|
||||
camCenter = vec3_add(camCenter, vec3_mult(moveY, (y - lastMouseY) * speed));
|
||||
}
|
||||
|
@ -377,6 +441,16 @@ void keyboardEvent(unsigned char c, int x, int y) {
|
|||
}
|
||||
}
|
||||
onCowKeyboardInput(c);
|
||||
// Move light source if applicable
|
||||
if(settings.controlLight) {
|
||||
// Controls: wasd - movement over xz plane, qe movement over y axle
|
||||
// color and such shall be controlled using the sliders
|
||||
float step = slidersN.lightMove->value * 9.0 + 1.0; // go from 1 to 10;
|
||||
lightPos.x += ((c == 'd') - (c == 'a')) * step;
|
||||
lightPos.y += ((c == 'q') - (c == 'e')) * step;
|
||||
lightPos.z += ((c == 'w') - (c == 's')) * step;
|
||||
glutPostRedisplay();
|
||||
}
|
||||
}
|
||||
|
||||
void onMenuItem(int item) {
|
||||
|
@ -403,11 +477,16 @@ void onMenuItem(int item) {
|
|||
case 4: // quit
|
||||
glutLeaveMainLoop();
|
||||
exit(0);
|
||||
case 5: // control light source
|
||||
updateCowControl(COW_CONTROL_NONE);
|
||||
settings.controlLight = 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void onControlCowMenu(int item) {
|
||||
lastMouseButton = GLUT_RIGHT_BUTTON;
|
||||
settings.controlLight = 0;
|
||||
updateCowControl(item);
|
||||
}
|
||||
|
||||
|
@ -434,6 +513,7 @@ void menuSetup() {
|
|||
glutAddMenuEntry("Lock Y position", 0);
|
||||
glutAddMenuEntry("Change to Cow POV", 1);
|
||||
glutAddMenuEntry("Reset view", 3);
|
||||
glutAddMenuEntry("Control point light", 5);
|
||||
glutAddMenuEntry("Help", 2);
|
||||
glutAddMenuEntry("Quit", 4);
|
||||
glutAttachMenu(GLUT_RIGHT_BUTTON);
|
||||
|
@ -443,7 +523,7 @@ int main(int argc, char** argv) {
|
|||
/* initialize glut and window */
|
||||
glutInit(&argc, argv);
|
||||
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
|
||||
glutInitWindowSize(800, 500);
|
||||
glutInitWindowSize(1280, 720);
|
||||
glutInitWindowPosition(450, 450);
|
||||
/* create window and set callbacks */
|
||||
glutCreateWindow("World of Cow - Aviv Romem");
|
||||
|
|
47
ui.c
47
ui.c
|
@ -7,53 +7,6 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#define BACK_COLOR 0.3, 0.35, 0.35
|
||||
#define BACK_CLICKED_COLOR 0.25, 0.3, 0.3
|
||||
|
||||
void ui_button_draw(ui_button* b) {
|
||||
int wWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||
int wHeight = glutGet(GLUT_WINDOW_HEIGHT);
|
||||
|
||||
vec3 pos = vec3_add(b->position.absolute, vec3_new(b->position.relative.x * wWidth, b->position.relative.y * wHeight, 0.0));
|
||||
vec3 ext = b->size;
|
||||
glColorVec(b->clicked ? vec3_new(BACK_CLICKED_COLOR) : vec3_new(BACK_COLOR));
|
||||
glBegin(GL_QUADS);
|
||||
glVertexVec(pos);
|
||||
glVertex3f(pos.x + ext.x, pos.y, pos.z);
|
||||
glVertexVec(vec3_add(pos, ext));
|
||||
glVertex3f(pos.x, pos.y + ext.y, pos.z);
|
||||
glEnd();
|
||||
glColor3f(0.7, 0.7, 0.8);
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertexVec(pos);
|
||||
glVertex3f(pos.x + ext.x, pos.y, pos.z);
|
||||
glVertexVec(vec3_add(pos, ext));
|
||||
glVertex3f(pos.x, pos.y + ext.y, pos.z);
|
||||
glEnd();
|
||||
// Draw text if needed
|
||||
if(b->text != NULL) {
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
// Get text size
|
||||
int textWidth = glutBitmapLength(GLUT_BITMAP_TIMES_ROMAN_24, (unsigned char*)b->text);
|
||||
int textHeight = glutBitmapHeight(GLUT_BITMAP_TIMES_ROMAN_24);
|
||||
// set raster position - not gonna take into account multiple line text buttons
|
||||
vec3 rPos = vec3_add(pos, vec3_mult(ext, 0.5));
|
||||
rPos.x -= textWidth * 0.5;
|
||||
rPos.y -= textHeight * 0.25;
|
||||
glRasterPos3f(rPos.x, rPos.y, rPos.z);
|
||||
glutBitmapString(GLUT_BITMAP_TIMES_ROMAN_24, (unsigned char*)b->text);
|
||||
}
|
||||
}
|
||||
|
||||
char ui_button_mouse_over(ui_button* b, int mouseX, int mouseY) {
|
||||
int wWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||
int wHeight = glutGet(GLUT_WINDOW_HEIGHT);
|
||||
|
||||
vec3 pos = vec3_add(b->position.absolute, vec3_new(b->position.relative.x * wWidth, b->position.relative.y * wHeight, 0.0));
|
||||
vec3 ext = b->size;
|
||||
vec3 m = vec3_sub(vec3_new(mouseX, wHeight - mouseY, 0.0), pos);
|
||||
return m.x > 0.0 && m.x < ext.x && m.y > 0.0 && m.y < ext.y;
|
||||
}
|
||||
|
||||
void ui_slider_draw(ui_slider* s) {
|
||||
int wWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||
|
|
12
ui.h
12
ui.h
|
@ -7,15 +7,6 @@ typedef struct _ui_position {
|
|||
vec3 absolute;
|
||||
} ui_pos;
|
||||
|
||||
typedef struct _ui_button {
|
||||
ui_pos position;
|
||||
/* x,y - width,height, z - unused */
|
||||
vec3 size; // size in pixels - if screen is too small i am not sure if it is a smart idea to make everything smaller
|
||||
void (*onClick)(); // instead of passing stuff in, im just gonna put every state variable in global scope to ensure everything lives...
|
||||
char* text;
|
||||
char clicked;
|
||||
} ui_button;
|
||||
|
||||
typedef struct _ui_slider {
|
||||
ui_pos position;
|
||||
/* x - width, y - height, z - middle circle radius */
|
||||
|
@ -23,9 +14,6 @@ typedef struct _ui_slider {
|
|||
float value; // Value will always range between 0 and 1
|
||||
} ui_slider;
|
||||
|
||||
void ui_button_draw(ui_button* b);
|
||||
char ui_button_mouse_over(ui_button* b, int mouseX, int mouseY);
|
||||
|
||||
void ui_slider_draw(ui_slider* s);
|
||||
char ui_slider_mouse_over(ui_slider* s, int mouseX, int mouseY);
|
||||
void ui_slider_onclick(ui_slider* s, int mouseX, int mouseY);
|
||||
|
|
Loading…
Reference in a new issue