Commit 270d3cbb authored by Taddeüs Kroes's avatar Taddeüs Kroes

Graphics: Added assignment 5.

parent ed3f4107
CC=gcc
WARNING_FLAGS=-Wall -Wextra -Werror-implicit-function-declaration -Wshadow -Wstrict-prototypes -pedantic-errors
CFLAGS=-g -O2 -std=c99 $(WARNING_FLAGS)
LDFLAGS=-g -lGL -lglut -lGLU
.c.o:
$(CC) -c $(CFLAGS) $<
all: main
main: vectors.o intersect.o main.o polys.o
$(CC) $(LDFLAGS) -o main vectors.o intersect.o main.o polys.o
clean:
rm -f *.o
rm -f main
polys.o : polys.h
intersect.o : intersect.h polys.h vectors.h intersect.c
intersect.o : vectors.h polys.h intersect.h
main.o : intersect.h polys.h main.c
polys.o : polys.h polys.c
vectors.o : vectors.h vectors.c
/*
* Computer Graphics, Assignment, Intersections
* Filename ........ intersect.c
* Description ..... Line-polygon intersection algorithm
* Date ............ 20.08.2008
*
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Date ............ 10.10.2010
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glut.h>
#include "intersect.h"
#include "polys.h"
#include "vectors.h"
#define CUBE_SIZE .1
#define MAX(x, y, z) (x > y ? (x > z ? x : z) : (y > z ? y : z))
#define ABS(x) (x < 0 ? -x : x)
/*
* Draw a cube around a point p, with simensions CUBE_SIZE
*/
void
drawCube(point p)
{
glPushMatrix();
glTranslatef(p.x, p.y, p.z);
glutSolidCube(CUBE_SIZE);
glPopMatrix();
}
/*
* Project a point from 3D to 2D by omitting one of the vectors
*/
void
project(point p, GLdouble *x, GLdouble *y, GLint omit)
{
switch( omit )
{
case 0: *x = p.y; *y = p.z; break;
case 1: *x = p.x; *y = p.z; break;
default: *x = p.x; *y = p.y; break;
}
}
void
intersectPoly(poly p, point line_start, point line_end)
{
// 1. Calculate plane equation
point n;
GLdouble D;
// Use the first 3 points of the polygon to determine the plane by
// creating 2 directional vectors. Then, normalize the cross product
// of those vectors to calculate the normal.
p.pnormal = n = normalizeVector(crossProduct(
subtractVectors(p.pts[1], p.pts[0]),
subtractVectors(p.pts[2], p.pts[0])
));
// n.P = D, P is a point on the plane (we'l use a corner of the polygon)
D = dotProduct(n, p.pts[0]);
// 2. Calculate intersection of line with plane
GLdouble t, denom;
point plane_intersect;
denom = dotProduct(n, subtractVectors(line_end, line_start));
// If the line is parallel to the plane, there is no intersection
if( !denom )
return;
t = (D - dotProduct(n, line_start)) / denom;
// If t is not in the interval [0,1], the intersection of the line is not
// on the given line segment.
if( t < 0 || t > 1 )
return;
plane_intersect = addVectors(
line_start,
scalarMultiply( subtractVectors(line_end, line_start), t )
);
// 3. Project 3D to 2D by omitting the largest dimension.
// Check if plane intersection is in polygon using the 2D projection.
GLint i, omit, edges = 0;
GLdouble k, y, Px, Py, Ax, Ay, Bx, By;
// Omit the axis with the largest value in the polygon's normal vector
if( ABS(n.x) > ABS(n.y) )
omit = ABS(n.x) > ABS(n.z) ? 0 : 2;
else
omit = ABS(n.y) > ABS(n.z) ? 1 : 2;
// Convert P to 2D
project(plane_intersect, &Px, &Py, omit);
// Draw a line from the projected P in a positive x direction and count the
// intersections with the edges of the polygon.
for( i = 0; i < p.points; i++ )
{
// Next edge
project(p.pts[i], &Ax, &Ay, omit);
project(p.pts[(i+1) % p.points], &Bx, &By, omit);
// Check if P is vertically between A and B
if( Py <= fmax(Ay, By) && Py > fmin(Ay, By) )
{
// Check if P is left of AB. If so, there's an intersection.
if( Ax == Bx )
{
// Corner case: k = 0
if( Px <= Ax )
edges++;
}
else if( Ay != By )
{
// Normal case, compare AB's line equation to P
k = (By - Ay) / (Bx - Ax);
y = k * (Px - Ax) + Ay;
if( k > 0 ? y <= Py : y >= Py )
edges++;
}
}
}
// If there's an odd number of edge intersections, P is inside the polygon.
if( edges % 2 )
drawCube(plane_intersect);
}
void
intersect(polys* list, point line_start, point line_end)
{
int p;
for (p = 0; p < list->length; p++)
intersectPoly(list->items[p], line_start, line_end);
}
/* Computer Graphics, Assignment, Intersections
* Filename ........ intersect.h
* Description ..... Line-polygon intersection algorithm
* Date ............ 20.08.2008
*/
#ifndef INTERSECT_H
#define INTERSECT_H
#include "polys.h"
void intersect(polys* list, point line_start, point line_end);
#endif
/* Computer Graphics, Assignment, Intersections
*
* Filename ........ main.c
* Description ..... Creates OpenGL window and draws the scene.
* Date ............ 20.08.2008
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include "polys.h"
#include "intersect.h"
#ifndef M_PI
#define M_PI 3.141592653589793238462643350279
#endif
polys *polylist = NULL;
float camDistance = 12.5;
float camRotZ = 215.0, camAzimuth = 20.0;
float saved_camRotZ, saved_camAzimuth, saved_camDistance;
int mouse_mode = 0;
int mx, my;
point line_start = { 0, -3, 0 };
point line_end = { -3, 3.5, 0 };
#define color_roof {1.0,0.2,0.0,0.0}
#define color_wall {0.7,0.7,0.7,0.0}
#define color_wall2 {0.8,0.8,0.8,0.0}
#define color_garden {0.1,1.0,0.0,0.0}
#define base_NW {-1.5, 0.0, 1.0}
#define base_NE { 1.5, 0.0, 1.0}
#define base_SW {-1.5, 0.0,-1.0}
#define base_SE { 1.5, 0.0,-1.0}
#define roof_NW {-1.5, 1.5, 1.0}
#define roof_NE { 1.5, 1.5, 1.0}
#define roof_SW {-1.5, 1.5,-1.0}
#define roof_SE { 1.5, 1.5,-1.0}
#define roof_W {-1.5, 2.5, 0.0}
#define roof_E { 1.5, 2.5, 0.0}
#define garden_E {-4.5, 0.0, 0.0}
#define garden_NE {-3.5, 0.0, 3.5}
#define garden_NW { 3.5, 0.0, 3.5}
#define garden_W { 4.5, 0.0, 0.0}
#define garden_SW { 3.5, 0.0,-3.5}
#define garden_SE {-3.5, 0.0,-3.5}
#define n { 0.0, 0.0, 0.0}
#define nn { n, n, n, n, n, n}
#define z { 0, 0, 0 }
poly garden = {6, {garden_E,garden_NE,garden_NW,garden_W,garden_SW,garden_SE}, nn, n, z, color_garden};
poly wall_E = {5, {base_NE,base_SE,roof_SE,roof_E,roof_NE}, nn, n, z, color_wall};
poly wall_W = {5, {base_NW,base_SW,roof_SW,roof_W,roof_NW}, nn, n, z, color_wall};
poly wall_N = {4, {base_NW,base_NE,roof_NE,roof_NW}, nn, n, z, color_wall2};
poly wall_S = {4, {base_SW,base_SE,roof_SE,roof_SW}, nn, n, z, color_wall2};
poly roof_N = {4, {roof_NE,roof_NW,roof_W,roof_E}, nn, n, z, color_roof};
poly roof_S = {4, {roof_SE,roof_SW,roof_W,roof_E}, nn, n, z, color_roof};
#undef n
#undef nn
#undef z
void
InitializePolygonlist(void)
{
polylist = CreatePolylist(10);
AddPolyToPolylist(polylist, garden);
AddPolyToPolylist(polylist, wall_E);
AddPolyToPolylist(polylist, wall_W);
AddPolyToPolylist(polylist, wall_S);
AddPolyToPolylist(polylist, wall_N);
AddPolyToPolylist(polylist, roof_S);
AddPolyToPolylist(polylist, roof_N);
printf("%d polygons\n", polylist->length);
}
void
InitGL(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void
ReSizeGLScene(int Width, int Height)
{
if (Height == 0)
Height = 1;
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)Width/(GLfloat)Height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
void
SetupCamera(void)
{
float cx, cy, cz;
float t;
float beta, gamma;
glLoadIdentity();
// degrees -> radians
beta = camAzimuth / 180.0 * M_PI;
gamma = camRotZ / 180.0 * M_PI;
cx = camDistance;
cy = cz = 0.0;
// Rotate around Z
t = cx;
cx = cx * cos(beta) + cy * sin(beta);
cy = t * sin(beta) + cy * cos(beta);
// Rotate around Y
t = cx;
cx = cx * cos(gamma) - cz * sin(gamma);
cz = t * sin(gamma) + cz * cos(gamma);
gluLookAt (cx, cy, cz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void
DrawGLScene(void)
{
int i,j;
poly p;
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
SetupCamera();
// Draw the polygons
for (i = 0; i < polylist->length; i++)
{
p = polylist->items[i];
glColor3f(p.color[0], p.color[1], p.color[2]);
glBegin(GL_POLYGON);
for (j = 0; j < p.points; j++)
glVertex3f(p.pts[j].x, p.pts[j].y, p.pts[j].z);
glEnd();
}
// Draw the intersecting line
glColor3f(0, 0, 1);
glBegin(GL_LINES);
glVertex3f(line_start.x, line_start.y, line_start.z);
glVertex3f(line_end.x, line_end.y, line_end.z);
glEnd();
// Intersect the line with the polygons, intersect() will
// draw an intersect point marker
intersect(polylist, line_start, line_end);
glutSwapBuffers();
}
void
keyPressed(unsigned char key, int x, int y)
{
switch(key)
{
case 'q':
exit(-1);
break;
}
}
void
specialKeyPressed(int key, int x, int y)
{
switch(key)
{
case GLUT_KEY_LEFT:
line_end.x += 0.1;
break;
case GLUT_KEY_RIGHT:
line_end.x -= 0.1;
break;
case GLUT_KEY_UP:
line_end.z += 0.1;
break;
case GLUT_KEY_DOWN:
line_end.z -= 0.1;
break;
case GLUT_KEY_PAGE_UP:
line_end.y += 0.1;
break;
case GLUT_KEY_PAGE_DOWN:
line_end.y -= 0.1;
break;
}
glutPostRedisplay();
}
static void
mouseFunc(int button, int state, int x, int y)
{
// guard against both left and right buttons being pressed at the same time,
// by only responding when a mouse button is pressed while another one
// hasn't been pressed yet
if (state == GLUT_DOWN && mouse_mode == 0)
{
if (button == GLUT_LEFT_BUTTON)
{
mouse_mode = GLUT_LEFT_BUTTON;
saved_camRotZ = camRotZ;
saved_camAzimuth = camAzimuth;
mx = x;
my = y;
}
else if (button == GLUT_RIGHT_BUTTON)
{
mouse_mode = GLUT_RIGHT_BUTTON;
saved_camDistance = camDistance;
my = y;
}
}
else if (state == GLUT_UP && button == mouse_mode)
{
// pressed button released
mouse_mode = 0;
}
}
static void
motionFunc(int x, int y)
{
int dx, dy;
if (mouse_mode == GLUT_LEFT_BUTTON)
{
dx = mx - x;
dy = my - y;
camRotZ = saved_camRotZ - dx * 0.25;
camAzimuth = saved_camAzimuth - dy * 0.25;
if (camAzimuth > 89.99)
camAzimuth = 89.99;
else if (camAzimuth < -89.99)
camAzimuth = -89.99;
}
else if (mouse_mode == GLUT_RIGHT_BUTTON)
{
dy = my - y;
camDistance = saved_camDistance - dy * 0.5;
if (camDistance < 0.5)
camDistance = 0.5;
else if (camDistance > 100.0)
camDistance = 100.0;
}
}
int
main(int argc, char **argv)
{
InitializePolygonlist();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutInitWindowPosition(0, 0);
glutCreateWindow("Intersection");
glutDisplayFunc(&DrawGLScene);
glutIdleFunc(&DrawGLScene);
glutReshapeFunc(&ReSizeGLScene);
glutSpecialFunc(&specialKeyPressed);
glutKeyboardFunc(&keyPressed);
glutMotionFunc(&motionFunc);
glutMouseFunc(&mouseFunc);
InitGL();
glutMainLoop();
return 1;
}
/* Computer Graphics
*
* Filename ........ polys.c
* Description ..... Functions to manage lists of polygons
* Date ............ 19.08.2008
* Created by ...... Jurgen Sturm
* Cleaned up by ... Paul Melis
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "polys.h"
/* Create a list of polys, and reserve space for `n' polys */
polys*
CreatePolylist(int n)
{
polys *l;
l = (polys*) malloc(sizeof(polys));
if (l == NULL)
{
printf("CreatePolylist(): could not allocate memory (l): %s\n",
strerror(errno));
exit(-1);
}
if (n > 0)
{
l->items = (poly*) malloc(n * sizeof(poly));
if (l->items == NULL)
{
printf("CreatePolylist(): could not allocate memory (data): %s\n",
strerror(errno));
exit(-1);
}
l->capacity = n;
l->length = 0;
}
else
{
l->capacity = 0;
l->length = 0;
l->items = NULL;
}
return l;
}
/* Free the memory used by the given poly list */
void
DestroyPolylist(polys *list)
{
if (list == NULL)
return;
list->capacity = 0;
list->length = 0;
free(list->items);
list = NULL;
}
/* Enlarge the capacity of the given polylist by "delta" items *
* exit()'s if not enough memory is available.
* Returns 0 if poly* is NULL, 1 otherwise */
int
GrowPolylist(polys *list, int delta)
{
poly *newdata;
if (list == NULL)
return 0;
newdata = (poly*) realloc(list->items, (list->capacity + delta)*sizeof(poly));
if (newdata == NULL)
{
printf("GrowPolylist(): could not allocate memory: %s\n",
strerror(errno));
exit(-1);
}
list->capacity += delta;
list->items = newdata;
return 1;
}
/* Decrease the capacity of the given polylist by "delta" items.
* exit()'s if no memory available, returns 0 if poly* is NULL, 1 otherwise.
* Decreasing the data segment can, and will, destroy polygons if the new
* segment cannot contain all current data.
* The data segment cannot be reduced to a size less than 0 (size is clamped
* to zero).
* The new data segment will be a NULL pointer if the new size is 0. */
int
ShrinkPolylist(polys *list, int delta)
{
int n;
poly *newdata;
if (list == NULL)
return 0;
n = list->capacity - delta;
if (n < 1)
{
free(list->items);
list->items = NULL;
list->capacity = 0;
list->length = 0;
return 1;
}
newdata = (poly*)realloc(list->items, (list->capacity + delta)*sizeof(poly));
if (newdata == NULL)
{
printf("ShrinkPolylist(): could not allocate memory: %s\n",
strerror(errno));
exit(-1);
}
list->capacity -= delta;
list->items = newdata;
/* update list->length if neccesary */
if (list->length > list->capacity)
list->length = list->capacity;
return 1;
}
/* Add polygon p to the list.
* Note: the list will be enlarged if needed to accomodate p */
void
AddPolyToPolylist(polys *list, poly p)
{
int i;
if (list == NULL)
return;
for (i = 0; i < p.points; i++)
{
p.normal[i].x = 0;
p.normal[i].y = 0;
p.normal[i].z = 0;
}
/* polylist is full, so first add some space */
if (list->length == list->capacity)
{
/* grow arbitrary amount */
if (GrowPolylist(list, 8) != 1)
{
printf("AddPolyToList(): failed");
exit(-1);
}
}
list->items[list->length] = p;
list->length++;
}
/* Make a copy of the given list */
polys*
CopyPolylist(polys* list)
{
int i;
polys *copy;
if (list == NULL)
return NULL;
copy = CreatePolylist(list->capacity);
/* not the most efficient, but certainly easiest & least error-prone */
for (i = 0; i < list->length; i++)
AddPolyToPolylist(copy, list->items[i]);
return copy;
}
/* Computer Graphics
*
* Filename ........ polys.h
* Description ..... Functions to manage lists of polygons (header file)
* Date ............ 19.08.2008
* Created by ...... Jurgen Sturm
* Cleaned up by ... Paul Melis
*
*/
#ifndef POLYS_H
#define POLYS_H
#include <GL/gl.h>
#define MAX_VERTICES 6
typedef struct point
{
GLdouble x;
GLdouble y;
GLdouble z;
}
point;
typedef struct poly
{
int points;
point pts[MAX_VERTICES];
point normal[MAX_VERTICES]; // Vertex normals
point pnormal; // Overall polygon normal
point inside;
GLfloat color[4];
}
poly;
typedef struct polys
{
/* size of the poly array "items" below */
int capacity;
/* number of poly's stored, also index of the first free position
* in the "items" array. If this number is equal to "capacity" above,
* then this list is full */
int length;
/* poly pointer to array of size "capacity" */
poly *items;
}
polys;
/* Create a list of polys, and immediately reserve space for `n' polys */
polys* CreatePolylist(int numpolys);
/* Destroy a list of polygons */
void DestroyPolylist(polys *list);
/* exit() if no memory available, returns 0 if poly* is NULL, 1 otherwise */
int IncreasePolylist(polys *list, int delta);
/* exit() if no memory available, returns 0 if poly* is NULL, 1 otherwise.
* Decreasing the data segment can, and will, destroy polygons if the new
* segment cannot contain all current data.
* The data segment cannot be reduced to a size less than 0 (size is clamped
* to zero).
* The new data segment will be a NULL pointer if the new size is 0. */
int DecreasePolylist(polys *list, int delta);
/* poly's are structs of (point) arrays, so they are passed by value instead
* of by reference (as do arrays)
* Silently fails if `list' is a NULL pointer.
* exit()'s if we need more memory but cannot allocate it. */
void AddPolyToPolylist(polys *list, poly p);
/* Copies the list of polys `list', calls AddPolytoPolylist() for each poly
* in the given list.
* exit()'s if it cannot allocate memory. */
polys* CopyPolylist(polys *list);
#endif
/*
* Filename ........ vectors.c
* Description ..... Some functions to calculate with vectors.
*
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Date ............ 09.10.2010
*/
#include "vectors.h"
point createPoint(GLdouble x, GLdouble y, GLdouble z)
{
point p = {x, y, z};
return p;
}
point normalizeVector(point p)
{
return scalarMultiply(p, 1 / VECTOR_LENGTH(p));
}
point addVectors(point p1, point p2)
{
return createPoint(p1.x + p2.x, p1.y + p2.y, p1.z + p2.z);
}
point subtractVectors(point p1, point p2)
{
return createPoint(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z);
}
point scalarMultiply(point p, GLdouble scalar)
{
return createPoint(p.x * scalar, p.y * scalar, p.z * scalar);
}
GLdouble dotProduct(point p1, point p2)
{
return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
}
point crossProduct(point p1, point p2)
{
return createPoint( p1.y * p2.z - p1.z * p2.y,
p1.z * p2.x - p1.x * p2.z,
p1.x * p2.y - p1.y * p2.x );
}
/*
* Filename ........ vectors.h
* Description ..... Some function prototypes to calculate with vectors.
*
* Student name .... Sander van Veen & Taddeus Kroes
* Student email ... sandervv@gmail.com & taddeuskroes@hotmail.com
* Collegekaart .... 6167969 & 6054129
* Date ............ 09.10.2010
*/
#ifndef VECTORS_H
#define VECTORS_H
#include <math.h>
#include "polys.h"
#define VECTOR_LENGTH(p) sqrt( p.x*p.x + p.y*p.y + p.z*p.z )
point createPoint(GLdouble x, GLdouble y, GLdouble z);
point normalizeVector(point p);
point addVectors(point p1, point p2);
point subtractVectors(point p1, point p2);
point scalarMultiply(point p, GLdouble scalar);
GLdouble dotProduct(point p1, point p2);
point crossProduct(point p1, point p2);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment