Commit 85db55d9 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Graphics ass11

Added framework.
parent 90b6be6e
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 `libpng12-config --libs`
.c.o:
$(CC) -c $(CFLAGS) $<
all: main
main: geometry.o main.o polys.o readpng.o bsp.o
$(CC) $(LDFLAGS) -o main geometry.o main.o polys.o readpng.o bsp.o
readpng.o: readpng.c
$(CC) -c $(CLFAGS) `libpng12-config --cflags` readpng.c
clean:
rm -f *.o
rm -f main
geometry.o : geometry.h polys.h geometry.c
polys.o : polys.h polys.c
main.o : bsp.h geometry.h polys.h readpng.h main.c
readpng.o : readpng.h readpng.c
bsp.o : bsp.h bsp.c polys.h
/* Computer Graphics
*
* Filename ........ bsp.c
* Description ..... Functions related to Binary Space-Partitioning trees
* Date ............ 23.11.2009
* Created by ...... Paul Melis
*
* Student name ....
* Student email ...
* Collegekaart ....
* Date ............
* Comments ........
*
*
* (always fill in these fields before submitting!!)
*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "bsp.h"
/* Given a list of polygons builds a BSP tree by recursively choosing
* one polygon that defines a split plane and dividing the other polygons
* arbitrarily into left and right subsets. This does NOT result in a
* correct BSP tree.
*
* Returns the root node of the BSP tree */
BSPNode*
BuildBSPTreeIncorrect(polys *polygons)
{
polys *left_polygons, *right_polygons;
BSPNode *left_tree, *right_tree;
BSPNode *root;
poly split_poly;
// Arbitrary initial capacity for the lists, they will grow as
// needed automatically
left_polygons = CreatePolylist(4);
right_polygons = CreatePolylist(4);
// Pick a polygon which defines the split plane
split_poly = polygons->items[0];
// Arbitrarily assign polys to left and right sublists
// This is where a "real" BSP construction routine would need
// to do much more work...
for (int i = 1; i < polygons->length; i++)
{
if (i % 2 == 0)
AddPolyToPolylist(left_polygons, polygons->items[i]);
else
AddPolyToPolylist(right_polygons, polygons->items[i]);
}
// Recursively subdivide the left and right lists
left_tree = NULL;
if (left_polygons->length > 0)
left_tree = BuildBSPTreeIncorrect(left_polygons);
right_tree = NULL;
if (right_polygons->length > 0)
right_tree = BuildBSPTreeIncorrect(right_polygons);
// We can free the child polygon lists, as each child polygon
// will now have been stored in a BSP node
DestroyPolylist(left_polygons);
DestroyPolylist(right_polygons);
// Create tree node and return it
root = (BSPNode*) malloc(sizeof(BSPNode));
root->polygon = split_poly;
root->left_child = left_tree;
root->right_child = right_tree;
return root;
}
/* Checks if the line segment p1 -> p2 intersects the
* plane defined by point plane_p and normal plane_n.
*
* Returns 1 if an intersection was found and sets t appropriately
* (the intersection point will be (1-t)*p1 + t*p2)
* Returns 0 otherwise. */
int
check_for_intersection(float *t, vec3 plane_p, vec3 plane_n, vec3 p1, vec3 p2)
{
float D = v3_dotprod(plane_n, plane_p);
float denom = v3_dotprod(plane_n, v3_subtract(p2, p1));
if (fabs(denom) < 1.0e-6)
{
// Line segment parallel to the plane, no intersection possible
return 0;
}
float tt = (D - v3_dotprod(plane_n, p1)) / denom;
if (tt < 0.0 || tt > 1.0)
{
// Although the infinite line through p1 and p2 intersects
// the plane, the line *segment* p1 -> p2 does not
return 0;
}
// We have an intersection, set t
*t = tt;
return 1;
}
/* Triangle 'p' is known to intersect the plane defined
* by 'plane_p' and 'plane_n'. One of the vertices of 'p'
* (the one with index 'in_plane') is known to lie in the plane.
* Array 'side' describes for each vertex of 'p' on which side
* of the plane it lies (see comment for split_triangle()).
*
* Split the triangle along the plane and add the resulting
* new triangles to the relevant list(s).
*
* Make sure to set the correct texture coordinates for each
* edge intersection point and set the correct triangle normal
* for new triangles.
*/
void
split_triangle_one_edge_intersection(polys *left_polygons, polys *right_polygons,
vec3 plane_p, vec3 plane_n, poly p, int *side, int in_plane)
{
}
/* Triangle 'p' is known to intersect the plane defined
* by 'plane_p' and 'plane_n'. One of the vertices of 'p'
* (the one with index 'single') is known to be alone on
* one side of the plane. Array 'side' describes for each
* vertex of 'p' on which side of the plane it lies (see comment
* for split_triangle()).
*
* Split the triangle along the plane and add the resulting
* new triangles to the relevant list(s).
*
* Make sure to set the correct texture coordinates for each
* edge intersection point and set the correct triangle normal
* for new triangles.
*/
void
split_triangle_two_edge_intersections(polys *left_polygons, polys *right_polygons,
vec3 plane_p, vec3 plane_n, poly p, int *side, int single)
{
}
/* Polygon 'p' (a triangle) is known to straddle the plane defined by
* point 'plane_p' and normal 'plane_n'. The array 'side' describes
* for each vertex of p on which side of the plane it lies
* (-1 = left of, 1 = right of, 0 = on the plane). The length of
* the 'side' array is equal to p.points.
*
* Split the triangle in multiple triangles based on intersections
* of the triangle's edges with the plane, using the two split functions
* above. Add the new triangles to the relevant list(s).
*/
void
split_triangle(polys *left_polygons, polys *right_polygons,
vec3 plane_p, vec3 plane_n, poly p, int *side)
{
}
/*
* Create a correct BSP-tree for the given list of transparent
* polygons. Return the root node of the tree.
*/
BSPNode*
BuildBSPTree(polys *polygons)
{
}
/* Computer Graphics
*
* Filename ........ bsp.h
* Description ..... Functions related to Binary Space-Partitioning trees
* Date ............ 22.11.2009
* Created by ...... Paul Melis
*/
#ifndef BSP_H
#define BSP_H
#include "polys.h"
typedef struct BSPNode
{
// May be NULL
struct BSPNode *left_child, *right_child;
// The polygon assigned to this node.
// It defines the split plane.
poly polygon;
}
BSPNode;
BSPNode* BuildBSPTreeIncorrect(polys *polygons);
BSPNode* BuildBSPTree(polys *polygons);
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
v 0.382683 0.000000 5.528998
v 0.707107 0.000000 5.312225
v 0.923880 0.000000 4.987802
v 1.000000 0.000000 4.605118
v 0.923880 0.000000 4.222435
v 0.707107 0.000000 3.898011
v 0.382683 0.000000 3.681239
v 0.270598 0.270598 3.681239
v 0.500000 0.500000 3.898011
v 0.653281 0.653282 4.222435
v 0.707107 0.707107 4.605118
v 0.653281 0.653282 4.987802
v 0.500000 0.500000 5.312225
v 0.270598 0.270598 5.528998
v -0.000000 0.382683 5.528998
v -0.000000 0.707107 5.312225
v -0.000000 0.923880 4.987802
v -0.000000 1.000000 4.605118
v -0.000000 0.923880 4.222435
v -0.000000 0.707107 3.898011
v -0.000000 0.382684 3.681239
v -0.270598 0.270598 3.681239
v -0.500000 0.500000 3.898011
v -0.653282 0.653281 4.222435
v -0.707107 0.707107 4.605118
v -0.653282 0.653281 4.987802
v -0.500000 0.500000 5.312225
v -0.270598 0.270598 5.528998
v -0.382683 -0.000000 5.528998
v -0.707107 -0.000000 5.312225
v -0.923880 -0.000000 4.987802
v -1.000000 -0.000000 4.605118
v -0.923880 -0.000000 4.222435
v -0.707107 -0.000000 3.898011
v -0.382684 -0.000000 3.681239
v -0.000000 -0.000000 3.679463
v -0.270598 -0.270598 3.681239
v -0.500000 -0.500000 3.898011
v -0.653281 -0.653282 4.222435
v -0.707107 -0.707107 4.605118
v -0.653281 -0.653282 4.987802
v -0.500000 -0.500000 5.312225
v -0.270598 -0.270598 5.528998
v 0.000000 -0.382683 5.528998
v 0.000000 -0.707107 5.312225
v 0.000000 -0.923880 4.987802
v 0.000000 -1.000000 4.605118
v 0.000000 -0.923880 4.222435
v 0.000000 -0.707107 3.898011
v 0.000000 -0.382684 3.681239
v 0.270598 -0.270598 3.681239
v 0.500000 -0.500000 3.898011
v 0.653282 -0.653281 4.222435
v 0.707107 -0.707107 4.605118
v 0.653282 -0.653281 4.987802
v 0.500000 -0.500000 5.312225
v 0.270598 -0.270598 5.528998
v 0.382683 -0.000000 5.624637
v 0.270598 -0.270598 5.624637
v 0.000000 -0.382683 5.624637
v -0.270598 -0.270598 5.624637
v -0.382683 -0.000000 5.624637
v -0.270598 0.270598 5.624637
v -0.000000 0.382683 5.624637
v 0.270598 0.270598 5.624637
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
7 0.0 0.0
6 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
6 0.0 0.0
7 0.0 0.0
8 0.0 0.0
5 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
5 0.0 0.0
8 0.0 0.0
9 0.0 0.0
4 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
4 0.0 0.0
9 0.0 0.0
10 0.0 0.0
3 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
3 0.0 0.0
10 0.0 0.0
11 0.0 0.0
2 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
2 0.0 0.0
11 0.0 0.0
12 0.0 0.0
1 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
13 0.0 0.0
0 0.0 0.0
1 0.0 0.0
12 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
12 0.0 0.0
15 0.0 0.0
14 0.0 0.0
13 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
11 0.0 0.0
16 0.0 0.0
15 0.0 0.0
12 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
10 0.0 0.0
17 0.0 0.0
16 0.0 0.0
11 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
9 0.0 0.0
18 0.0 0.0
17 0.0 0.0
10 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
8 0.0 0.0
19 0.0 0.0
18 0.0 0.0
9 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
7 0.0 0.0
20 0.0 0.0
19 0.0 0.0
8 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
20 0.0 0.0
7 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
21 0.0 0.0
20 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
20 0.0 0.0
21 0.0 0.0
22 0.0 0.0
19 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
19 0.0 0.0
22 0.0 0.0
23 0.0 0.0
18 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
18 0.0 0.0
23 0.0 0.0
24 0.0 0.0
17 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
17 0.0 0.0
24 0.0 0.0
25 0.0 0.0
16 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
16 0.0 0.0
25 0.0 0.0
26 0.0 0.0
15 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
15 0.0 0.0
26 0.0 0.0
27 0.0 0.0
14 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
26 0.0 0.0
29 0.0 0.0
28 0.0 0.0
27 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
25 0.0 0.0
30 0.0 0.0
29 0.0 0.0
26 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
24 0.0 0.0
31 0.0 0.0
30 0.0 0.0
25 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
23 0.0 0.0
32 0.0 0.0
31 0.0 0.0
24 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
22 0.0 0.0
33 0.0 0.0
32 0.0 0.0
23 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
21 0.0 0.0
34 0.0 0.0
33 0.0 0.0
22 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
34 0.0 0.0
21 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
36 0.0 0.0
34 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
34 0.0 0.0
36 0.0 0.0
37 0.0 0.0
33 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
33 0.0 0.0
37 0.0 0.0
38 0.0 0.0
32 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
32 0.0 0.0
38 0.0 0.0
39 0.0 0.0
31 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
31 0.0 0.0
39 0.0 0.0
40 0.0 0.0
30 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
30 0.0 0.0
40 0.0 0.0
41 0.0 0.0
29 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
29 0.0 0.0
41 0.0 0.0
42 0.0 0.0
28 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
41 0.0 0.0
44 0.0 0.0
43 0.0 0.0
42 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
40 0.0 0.0
45 0.0 0.0
44 0.0 0.0
41 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
39 0.0 0.0
46 0.0 0.0
45 0.0 0.0
40 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
38 0.0 0.0
47 0.0 0.0
46 0.0 0.0
39 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
37 0.0 0.0
48 0.0 0.0
47 0.0 0.0
38 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
36 0.0 0.0
49 0.0 0.0
48 0.0 0.0
37 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
49 0.0 0.0
36 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
50 0.0 0.0
49 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
49 0.0 0.0
50 0.0 0.0
51 0.0 0.0
48 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
48 0.0 0.0
51 0.0 0.0
52 0.0 0.0
47 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
47 0.0 0.0
52 0.0 0.0
53 0.0 0.0
46 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
46 0.0 0.0
53 0.0 0.0
54 0.0 0.0
45 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
45 0.0 0.0
54 0.0 0.0
55 0.0 0.0
44 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
44 0.0 0.0
55 0.0 0.0
56 0.0 0.0
43 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
0 0.0 0.0
56 0.0 0.0
55 0.0 0.0
1 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
54 0.0 0.0
2 0.0 0.0
1 0.0 0.0
55 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
53 0.0 0.0
3 0.0 0.0
2 0.0 0.0
54 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
52 0.0 0.0
4 0.0 0.0
3 0.0 0.0
53 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
51 0.0 0.0
5 0.0 0.0
4 0.0 0.0
52 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
50 0.0 0.0
6 0.0 0.0
5 0.0 0.0
51 0.0 0.0
p 3 -1
0.5 0.5 0.8 0.5
35 0.0 0.0
6 0.0 0.0
50 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
56 0.0 0.0
0 0.0 0.0
57 0.0 0.0
58 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
43 0.0 0.0
56 0.0 0.0
58 0.0 0.0
59 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
42 0.0 0.0
43 0.0 0.0
59 0.0 0.0
60 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
28 0.0 0.0
42 0.0 0.0
60 0.0 0.0
61 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
27 0.0 0.0
28 0.0 0.0
61 0.0 0.0
62 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
14 0.0 0.0
27 0.0 0.0
62 0.0 0.0
63 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
13 0.0 0.0
14 0.0 0.0
63 0.0 0.0
64 0.0 0.0
p 4 -1
0.5 0.5 0.8 0.5
0 0.0 0.0
13 0.0 0.0
64 0.0 0.0
57 0.0 0.0
/* Computer Graphics, Assignment, Depth-sorting and transparency
* Description .....
* Date ............ 22.11.2007
* Created by ...... Paul Melis
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "geometry.h"
#include "polys.h"
#ifndef M_PI
#define M_PI 3.141592653589793
#endif
static void
setSpherePoint(vec3 *p, vec3* n, vec3* t, int latitude, int longitude,
double sx, double sy, double sz, double ox, double oy, double oz)
{
double dToR = M_PI / 180.0;
double len;
p->x = ox + sin(longitude * dToR) * cos(latitude * dToR) * sx;
p->y = oy + sin(latitude * dToR) * sy;
p->z = oz + cos(longitude * dToR) * cos(latitude * dToR) * sz;
t->x = longitude / 360.0;
t->y = (90.0 - latitude) / 180.0;
// calculate normal, this actually doesn't take the sphere size
// per axis into account, but should still be usable
n->x = p->x - ox;
n->y = p->y - oy;
n->z = p->z - oz;
len = n->x*n->x + n->y*n->y + n->z*n->z;
n->x /= len;
n->y /= len;
n->z /= len;
}
void
createSphere(polys * list, double sx, double sy, double sz, double ox,
double oy, double oz, double r, double g, double b)
{
int latitude, longitude;
poly p;
// prepare poly, as these values are the same for all generated polys
p.points = 4;
p.color[0] = r;
p.color[1] = g;
p.color[2] = b;
p.color[3] = 0;
// sweep over sphere's surface and generate polys
for (latitude = -90; latitude < 90; latitude += 10)
{
for (longitude = 0; longitude < 360; longitude += 10)
{
setSpherePoint(&(p.pts[0]), &(p.normal[0]), &(p.tcoord[0]),
latitude, longitude, sx, sy, sz, ox, oy, oz);
setSpherePoint(&(p.pts[1]), &(p.normal[1]), &(p.tcoord[1]),
latitude+10, longitude, sx, sy, sz, ox, oy, oz);
setSpherePoint(&(p.pts[2]), &(p.normal[2]), &(p.tcoord[2]),
latitude+10, longitude+10, sx, sy, sz, ox, oy, oz);
setSpherePoint(&(p.pts[3]), &(p.normal[3]), &(p.tcoord[3]),
latitude, longitude+10, sx, sy, sz, ox, oy, oz);
AddPolyToPolylist(list, p);
}
}
}
// Calculate the coordinates, normal vector and texture coordinates for
// a hemisphere point at the given latitude and longitude (in degrees).
// The radius of the hemisphere is s, the center point (at the base of the
// hemisphere) is ox,oy,oz.
static void
setHemispherePoint(vec3 *p, vec3* n, vec3* t, int latitude, int longitude,
double s, double ox, double oy, double oz)
{
double dToR = M_PI / 180.0;
double len;
p->x = ox + sin(longitude * dToR) * cos(latitude * dToR) * s;
p->y = oy + sin(latitude * dToR) * s;
p->z = oz + cos(longitude * dToR) * cos(latitude * dToR) * s;
t->x = longitude / 360.0;
t->y = 1.0 * latitude / 90.0;
// calculate normal
n->x = p->x - ox;
n->y = p->y - oy;
n->z = p->z - oz;
len = n->x*n->x + n->y*n->y + n->z*n->z;
n->x /= len;
n->y /= len;
n->z /= len;
}
void
createHemisphere(polys * list, double s, double ox, double oy, double oz,
double r, double g, double b)
{
int latitude, longitude;
poly p;
// prepare poly, as these values are the same for all generated polys
p.points = 4;
p.color[0] = r;
p.color[1] = g;
p.color[2] = b;
p.color[3] = 1;
// sweep over sphere's surface and generate polys
for (latitude = 0; latitude < 90; latitude += 10)
{
for (longitude = 0; longitude < 360; longitude += 10)
{
setHemispherePoint(&(p.pts[0]), &(p.normal[0]), &(p.tcoord[0]),
latitude, longitude, s, ox, oy, oz);
setHemispherePoint(&(p.pts[1]), &(p.normal[1]), &(p.tcoord[1]),
latitude, longitude+10, s, ox, oy, oz);
setHemispherePoint(&(p.pts[2]), &(p.normal[2]), &(p.tcoord[2]),
latitude+10, longitude+10, s, ox, oy, oz);
setHemispherePoint(&(p.pts[3]), &(p.normal[3]), &(p.tcoord[3]),
latitude+10, longitude, s, ox, oy, oz);
AddPolyToPolylist(list, p);
}
}
}
// Create a cylinder along the Y axis whose base center point is
// at (ox, oy, oz), having the given radius and height.
// Use the given color for the generated polygons.
void
createCylinder(polys * list, double radius, double height,
double ox, double oy, double oz,
double r, double g, double b)
{
int longitude;
GLfloat x, z;
GLfloat x2, z2;
double dToR = M_PI / 180.0;
double len;
poly p;
int i;
// prepare poly datastructure, as these values are the same for all generated polys
p.points = 4;
p.color[0] = r;
p.color[1] = g;
p.color[2] = b;
p.color[3] = 0;
// sweep around cylinder axis
for (longitude = 0; longitude < 360; longitude += 10)
{
x = ox + sin(longitude * dToR) * radius;
z = oz + cos(longitude * dToR) * radius;
x2 = ox + sin((longitude+10) * dToR) * radius;
z2 = oz + cos((longitude+10) * dToR) * radius;
p.pts[0].x = x; p.pts[0].y = oy; p.pts[0].z = z;
p.pts[1].x = x; p.pts[1].y = oy+height; p.pts[1].z = z;
p.pts[2].x = x2; p.pts[2].y = oy+height; p.pts[2].z = z2;
p.pts[3].x = x2; p.pts[3].y = oy; p.pts[3].z = z2;
for (i = 0; i < 4; i++)
{
p.normal[i].x = p.pts[i].x - ox;
p.normal[i].y = 0.0;
p.normal[i].z = p.pts[i].z - oz;
len = p.normal[i].x*p.normal[i].x + p.normal[i].z*p.normal[i].z;
p.normal[i].x /= len;
p.normal[i].z /= len;
}
p.tcoord[0].x = p.tcoord[1].x = longitude / 360.0;
p.tcoord[2].x = p.tcoord[3].x = (longitude+10) / 360.0;
p.tcoord[0].y = p.tcoord[3].y = 1.0;
p.tcoord[1].y = p.tcoord[2].y = 0.0;
AddPolyToPolylist(list, p);
}
}
// Read the vertex data for a single polygon and store it in 'p'.
// Called from loadPolygonalObject() after a 'p ...' line (+ color)
// has been read.
static void
readPolyVertices(poly *p, FILE *f, const vec3 *vertex_list, int num_vertices_to_read,
int texture_id, GLuint opengl_texture_name)
{
char line[1024];
int num_read;
int pidx;
int vidx;
float s, t;
p->points = num_vertices_to_read;
num_read = 0;
pidx = 0;
while (num_read < num_vertices_to_read)
{
if (fgets(line, 1024, f) == NULL)
{
printf("Unexpected end-of-file reading poly vertices!\n");
exit(-1);
}
if (sscanf(line, "%d %f %f\n", &vidx, &s, &t) == 3)
{
//printf("%d %f %f %f %f %f\n", vidx, nx, ny, nz, s, t);
p->pts[pidx] = vertex_list[vidx];
p->texture_id = texture_id;
p->opengl_texture_name = opengl_texture_name;
p->tcoord[pidx].x = s;
p->tcoord[pidx].y = t;
num_read++;
pidx++;
}
else if (line[0] && line[0] != '#')
{
printf("Expected line declaring polygon vertex, got instead:\n");
printf("%s\n", line);
exit(-1);
}
}
}
// Read a polygonal object from a .OBJ file.
// Scale the input coordinates uniformly with a factor s followed by
// a translation (tx,ty,tz). This allows a very simple transformation
// on the loaded data, e.g. to position objects in the scene.
void
loadPolygonalObject(polys* list, const char *objfile, GLuint *texture_names, int num_textures,
double s, double tx, double ty, double tz)
{
FILE *f;
char line[1024];
float x, y, z;
vec3 *vertices;
int num_vertices;
int num_vertices_allocated;
poly p;
float colr, colg, colb, cola;
int num_poly_vertices, texture_id;
int i;
float len;
vec3 v, w, n;
int texture_name;
f = fopen(objfile, "rt");
if (!f)
{
fprintf(stderr, "loadPolygonalObject(): Could not open file '%s' for reading!\n", objfile);
exit(-1);
}
printf("Reading %s\n", objfile);
num_vertices = 0;
num_vertices_allocated = 1024;
vertices = malloc(num_vertices_allocated * sizeof(vec3));
while (fgets(line, 1024, f))
{
if (sscanf(line, "v %f %f %f\n", &x, &y, &z))
{
// vertex
//printf("vertex: %f %f %f\n", x, y, z);
// current vertex list is full, add more space
if (num_vertices == num_vertices_allocated)
{
num_vertices_allocated = (int)(1.5 * num_vertices_allocated);
vertices = realloc(vertices, num_vertices_allocated * sizeof(vec3));
if (vertices == NULL)
{
printf("No memory to hold vertices!\n");
exit(-1);
}
}
// store vertex, after scaling and translation
vertices[num_vertices].x = tx + s*x;
vertices[num_vertices].y = ty + s*y;
vertices[num_vertices].z = tz + s*z;
num_vertices++;
}
else if (sscanf(line, "p %d %d\n", &num_poly_vertices, &texture_id))
{
if (num_poly_vertices < 3)
{
printf("In %s, line:\n", objfile);
printf("%s\n", line);
printf("Need at least 3 vertices to define a polygon!\n");
exit(-1);
}
else if (num_poly_vertices > 4)
{
printf("In %s, line:\n", objfile);
printf("%s\n", line);
printf("Polygons may only consist of 3 or 4 vertices, sorry\n");
printf("(this is due to OpenGL not handling concave polygons very well)\n");
exit(-1);
}
// read polygon color
if (fscanf(f, "%f %f %f %f\n", &colr, &colg, &colb, &cola) == EOF)
{
printf("Could not read polygon color!\n");
exit(-1);
}
p.color[0] = colr;
p.color[1] = colg;
p.color[2] = colb;
p.color[3] = cola;
texture_name = -1;
if (texture_id > num_textures)
printf("Texture ID (%d) out of range (<= %d)\n", texture_id, num_textures-1);
else if (texture_id >= 0)
// Determine corresponding OpenGL texture name
texture_name = texture_names[texture_id];
// read vertices making up poly
readPolyVertices(&p, f, vertices, num_poly_vertices, texture_id, texture_name);
// Use first 3 polygon vertices to calculate the polygon normal vector
// (i.e. assumes polygon is planar)
v.x = p.pts[2].x - p.pts[1].x;
v.y = p.pts[2].y - p.pts[1].y;
v.z = p.pts[2].z - p.pts[1].z;
w.x = p.pts[0].x - p.pts[1].x;
w.y = p.pts[0].y - p.pts[1].y;
w.z = p.pts[0].z - p.pts[1].z;
n.x = v.y * w.z - v.z * w.y;
n.y = v.z * w.x - v.x * w.z;
n.z = v.x * w.y - v.y * w.x;
len = sqrt(n.x * n.x + n.y * n.y + n.z * n.z);
n.x /= len;
n.y /= len;
n.z /= len;
// Set vertex normals to polygon normal
for (i = 0; i < num_poly_vertices; i++)
p.normal[i] = n;
// Add polygon
AddPolyToPolylist(list, p);
}
}
//printf("%d vertices read\n", num_vertices);
fclose(f);
free(vertices);
}
#ifndef GEOMETRY_H
#define GEOMETRY_H
#include "polys.h"
// Create a sphere centered at (ox, oy, oz), having sizes
// sx, sy and sz in X, Y and Z respectively. Use the given color.
void
createSphere(polys * list, double sx, double sy, double sz, double ox,
double oy, double oz, double r, double g, double b);
// Create a hemisphere whose base point is at (ox, oy, oz), having radius s.
// Use the given color.
void
createHemisphere(polys * list, double s, double ox, double oy, double oz,
double r, double g, double b);
// Create a cylinder along the Y axis whose base center point is
// at (ox, oy, oz), having the given radius and height.
// Use the given color for the generated polygons.
void
createCylinder(polys * list, double radius, double height,
double ox, double oy, double oz,
double r, double g, double b);
// Read a polygonal object from a .OBJ file.
// Scale the input coordinates uniformly with a factor s followed by
// a translation (tx,ty,tz).
void
loadPolygonalObject(polys * list, const char *objfile, GLuint *texture_names, int num_textures,
double s, double tx, double ty, double tz);
#endif
v -0.299609 0.000000 4.581704
v -0.271560 0.000000 4.650124
v -0.191683 0.000000 4.708128
v -0.072139 0.000000 4.746885
v 0.068874 0.000000 4.760495
v 0.224853 -0.000000 4.658367
v 0.329430 -0.000000 4.712994
v 0.375700 0.000000 4.650124
v 0.375700 0.022108 4.630084
v 0.329430 0.029671 4.674540
v 0.224853 0.024771 4.635912
v 0.068874 0.057770 4.708128
v -0.072139 0.053372 4.698505
v -0.191683 0.040849 4.671099
v -0.271560 0.022108 4.630084
v -0.271560 0.031265 4.581704
v -0.191683 0.057770 4.581704
v -0.072139 0.075480 4.581704
v 0.068874 0.081699 4.581704
v 0.224853 0.035031 4.581704
v 0.329430 0.041961 4.581704
v 0.375700 0.031265 4.581704
v 0.375700 0.022108 4.533323
v 0.329430 0.029671 4.488867
v 0.224853 0.024771 4.527495
v 0.068874 0.057770 4.494184
v -0.072139 0.053372 4.491802
v -0.191683 0.040849 4.519207
v -0.271560 0.022108 4.533323
v -0.271560 -0.000000 4.513283
v -0.191683 -0.000000 4.482179
v -0.072139 -0.000000 4.467538
v 0.068874 -0.000000 4.462441
v 0.224853 -0.000000 4.505041
v 0.329430 -0.000000 4.450413
v 0.375700 -0.000000 4.513283
v 0.403749 -0.000000 4.581704
v 0.375700 -0.022108 4.533323
v 0.329430 -0.029671 4.488867
v 0.224853 -0.024771 4.527495
v 0.068874 -0.057770 4.494184
v -0.072139 -0.053372 4.491802
v -0.191683 -0.040849 4.519208
v -0.271560 -0.022108 4.533323
v -0.271560 -0.031265 4.581704
v -0.191683 -0.057770 4.581704
v -0.072139 -0.075480 4.581704
v 0.068874 -0.081699 4.581704
v 0.224853 -0.035031 4.581704
v 0.329430 -0.041961 4.581704
v 0.375700 -0.031265 4.581704
v 0.375700 -0.022108 4.630084
v 0.329430 -0.029671 4.674540
v 0.224853 -0.024771 4.635912
v 0.068874 -0.057770 4.708128
v -0.072139 -0.053372 4.698505
v -0.191683 -0.040849 4.671099
v -0.271560 -0.022108 4.630085
v 0.068874 -0.057770 4.494184
v 0.068874 -0.081699 4.581704
v -0.072139 -0.075480 4.581704
v -0.072139 -0.053372 4.491802
v 0.068874 0.057770 4.494184
v -0.072139 0.053372 4.491802
v -0.072139 0.075480 4.581704
v 0.068874 0.081699 4.581704
v 0.067339 0.104029 4.532372
v 0.035043 0.116076 4.442444
v -0.041377 0.112954 4.438537
v -0.073673 0.098301 4.529950
v 0.034841 -0.109676 4.442885
v 0.067339 -0.101504 4.533247
v -0.073673 -0.095677 4.531074
v -0.041175 -0.106388 4.439116
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
8 0.0 0.0
7 0.0 0.0
p 4 -1
0.8 0.4 0 1
7 0.0 0.0
8 0.0 0.0
9 0.0 0.0
6 0.0 0.0
p 4 -1
0.8 0.4 0 1
6 0.0 0.0
9 0.0 0.0
10 0.0 0.0
5 0.0 0.0
p 4 -1
0.8 0.4 0 1
5 0.0 0.0
10 0.0 0.0
11 0.0 0.0
4 0.0 0.0
p 4 -1
0.8 0.4 0 1
4 0.0 0.0
11 0.0 0.0
12 0.0 0.0
3 0.0 0.0
p 4 -1
0.8 0.4 0 1
3 0.0 0.0
12 0.0 0.0
13 0.0 0.0
2 0.0 0.0
p 4 -1
0.8 0.4 0 1
2 0.0 0.0
13 0.0 0.0
14 0.0 0.0
1 0.0 0.0
p 3 -1
0.8 0.4 0 1
14 0.0 0.0
0 0.0 0.0
1 0.0 0.0
p 3 -1
0.8 0.4 0 1
15 0.0 0.0
0 0.0 0.0
14 0.0 0.0
p 4 -1
0.8 0.4 0 1
13 0.0 0.0
16 0.0 0.0
15 0.0 0.0
14 0.0 0.0
p 4 -1
0.8 0.4 0 1
12 0.0 0.0
17 0.0 0.0
16 0.0 0.0
13 0.0 0.0
p 4 -1
0.8 0.4 0 1
11 0.0 0.0
18 0.0 0.0
17 0.0 0.0
12 0.0 0.0
p 4 -1
0.8 0.4 0 1
10 0.0 0.0
19 0.0 0.0
18 0.0 0.0
11 0.0 0.0
p 4 -1
0.8 0.4 0 1
9 0.0 0.0
20 0.0 0.0
19 0.0 0.0
10 0.0 0.0
p 4 -1
0.8 0.4 0 1
8 0.0 0.0
21 0.0 0.0
20 0.0 0.0
9 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
21 0.0 0.0
8 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
22 0.0 0.0
21 0.0 0.0
p 4 -1
0.8 0.4 0 1
21 0.0 0.0
22 0.0 0.0
23 0.0 0.0
20 0.0 0.0
p 4 -1
0.8 0.4 0 1
20 0.0 0.0
23 0.0 0.0
24 0.0 0.0
19 0.0 0.0
p 4 -1
0.8 0.4 0 1
19 0.0 0.0
24 0.0 0.0
25 0.0 0.0
18 0.0 0.0
p 4 -1
0.8 0.4 0 1
17 0.0 0.0
26 0.0 0.0
27 0.0 0.0
16 0.0 0.0
p 4 -1
0.8 0.4 0 1
16 0.0 0.0
27 0.0 0.0
28 0.0 0.0
15 0.0 0.0
p 3 -1
0.8 0.4 0 1
28 0.0 0.0
0 0.0 0.0
15 0.0 0.0
p 3 -1
0.8 0.4 0 1
29 0.0 0.0
0 0.0 0.0
28 0.0 0.0
p 4 -1
0.8 0.4 0 1
27 0.0 0.0
30 0.0 0.0
29 0.0 0.0
28 0.0 0.0
p 4 -1
0.8 0.4 0 1
26 0.0 0.0
31 0.0 0.0
30 0.0 0.0
27 0.0 0.0
p 4 -1
0.8 0.4 0 1
25 0.0 0.0
32 0.0 0.0
31 0.0 0.0
26 0.0 0.0
p 4 -1
0.8 0.4 0 1
24 0.0 0.0
33 0.0 0.0
32 0.0 0.0
25 0.0 0.0
p 4 -1
0.8 0.4 0 1
23 0.0 0.0
34 0.0 0.0
33 0.0 0.0
24 0.0 0.0
p 4 -1
0.8 0.4 0 1
22 0.0 0.0
35 0.0 0.0
34 0.0 0.0
23 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
35 0.0 0.0
22 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
37 0.0 0.0
35 0.0 0.0
p 4 -1
0.8 0.4 0 1
35 0.0 0.0
37 0.0 0.0
38 0.0 0.0
34 0.0 0.0
p 4 -1
0.8 0.4 0 1
34 0.0 0.0
38 0.0 0.0
39 0.0 0.0
33 0.0 0.0
p 4 -1
0.8 0.4 0 1
33 0.0 0.0
39 0.0 0.0
40 0.0 0.0
32 0.0 0.0
p 4 -1
0.8 0.4 0 1
32 0.0 0.0
40 0.0 0.0
41 0.0 0.0
31 0.0 0.0
p 4 -1
0.8 0.4 0 1
31 0.0 0.0
41 0.0 0.0
42 0.0 0.0
30 0.0 0.0
p 4 -1
0.8 0.4 0 1
30 0.0 0.0
42 0.0 0.0
43 0.0 0.0
29 0.0 0.0
p 3 -1
0.8 0.4 0 1
43 0.0 0.0
0 0.0 0.0
29 0.0 0.0
p 3 -1
0.8 0.4 0 1
44 0.0 0.0
0 0.0 0.0
43 0.0 0.0
p 4 -1
0.8 0.4 0 1
42 0.0 0.0
45 0.0 0.0
44 0.0 0.0
43 0.0 0.0
p 4 -1
0.8 0.4 0 1
41 0.0 0.0
46 0.0 0.0
45 0.0 0.0
42 0.0 0.0
p 4 -1
0.8 0.4 0 1
39 0.0 0.0
48 0.0 0.0
47 0.0 0.0
40 0.0 0.0
p 4 -1
0.8 0.4 0 1
38 0.0 0.0
49 0.0 0.0
48 0.0 0.0
39 0.0 0.0
p 4 -1
0.8 0.4 0 1
37 0.0 0.0
50 0.0 0.0
49 0.0 0.0
38 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
50 0.0 0.0
37 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
51 0.0 0.0
50 0.0 0.0
p 4 -1
0.8 0.4 0 1
50 0.0 0.0
51 0.0 0.0
52 0.0 0.0
49 0.0 0.0
p 4 -1
0.8 0.4 0 1
49 0.0 0.0
52 0.0 0.0
53 0.0 0.0
48 0.0 0.0
p 4 -1
0.8 0.4 0 1
48 0.0 0.0
53 0.0 0.0
54 0.0 0.0
47 0.0 0.0
p 4 -1
0.8 0.4 0 1
47 0.0 0.0
54 0.0 0.0
55 0.0 0.0
46 0.0 0.0
p 4 -1
0.8 0.4 0 1
46 0.0 0.0
55 0.0 0.0
56 0.0 0.0
45 0.0 0.0
p 4 -1
0.8 0.4 0 1
45 0.0 0.0
56 0.0 0.0
57 0.0 0.0
44 0.0 0.0
p 3 -1
0.8 0.4 0 1
57 0.0 0.0
0 0.0 0.0
44 0.0 0.0
p 3 -1
0.8 0.4 0 1
1 0.0 0.0
0 0.0 0.0
57 0.0 0.0
p 4 -1
0.8 0.4 0 1
56 0.0 0.0
2 0.0 0.0
1 0.0 0.0
57 0.0 0.0
p 4 -1
0.8 0.4 0 1
55 0.0 0.0
3 0.0 0.0
2 0.0 0.0
56 0.0 0.0
p 4 -1
0.8 0.4 0 1
54 0.0 0.0
4 0.0 0.0
3 0.0 0.0
55 0.0 0.0
p 4 -1
0.8 0.4 0 1
53 0.0 0.0
5 0.0 0.0
4 0.0 0.0
54 0.0 0.0
p 4 -1
0.8 0.4 0 1
52 0.0 0.0
6 0.0 0.0
5 0.0 0.0
53 0.0 0.0
p 4 -1
0.8 0.4 0 1
51 0.0 0.0
7 0.0 0.0
6 0.0 0.0
52 0.0 0.0
p 3 -1
0.8 0.4 0 1
36 0.0 0.0
7 0.0 0.0
51 0.0 0.0
p 4 -1
0.8 0.4 0 1
40 0.0 0.0
47 0.0 0.0
59 0.0 0.0
58 0.0 0.0
p 4 -1
0.8 0.4 0 1
47 0.0 0.0
46 0.0 0.0
60 0.0 0.0
59 0.0 0.0
p 4 -1
0.8 0.4 0 1
46 0.0 0.0
41 0.0 0.0
61 0.0 0.0
60 0.0 0.0
p 4 -1
0.8 0.4 0 1
41 0.0 0.0
40 0.0 0.0
58 0.0 0.0
61 0.0 0.0
p 4 -1
0.8 0.4 0 1
25 0.0 0.0
26 0.0 0.0
63 0.0 0.0
62 0.0 0.0
p 4 -1
0.8 0.4 0 1
26 0.0 0.0
17 0.0 0.0
64 0.0 0.0
63 0.0 0.0
p 4 -1
0.8 0.4 0 1
18 0.0 0.0
25 0.0 0.0
62 0.0 0.0
65 0.0 0.0
p 4 -1
0.8 0.4 0 1
17 0.0 0.0
18 0.0 0.0
65 0.0 0.0
64 0.0 0.0
p 4 -1
0.8 0.4 0 1
62 0.0 0.0
67 0.0 0.0
66 0.0 0.0
65 0.0 0.0
p 4 -1
0.8 0.4 0 1
63 0.0 0.0
68 0.0 0.0
67 0.0 0.0
62 0.0 0.0
p 4 -1
0.8 0.4 0 1
64 0.0 0.0
69 0.0 0.0
68 0.0 0.0
63 0.0 0.0
p 4 -1
0.8 0.4 0 1
65 0.0 0.0
66 0.0 0.0
69 0.0 0.0
64 0.0 0.0
p 4 -1
0.8 0.4 0 1
66 0.0 0.0
67 0.0 0.0
68 0.0 0.0
69 0.0 0.0
p 4 -1
0.8 0.4 0 1
59 0.0 0.0
71 0.0 0.0
70 0.0 0.0
58 0.0 0.0
p 4 -1
0.8 0.4 0 1
60 0.0 0.0
72 0.0 0.0
71 0.0 0.0
59 0.0 0.0
p 4 -1
0.8 0.4 0 1
61 0.0 0.0
73 0.0 0.0
72 0.0 0.0
60 0.0 0.0
p 4 -1
0.8 0.4 0 1
58 0.0 0.0
70 0.0 0.0
73 0.0 0.0
61 0.0 0.0
p 4 -1
0.8 0.4 0 1
70 0.0 0.0
71 0.0 0.0
72 0.0 0.0
73 0.0 0.0
v -250 250 -0.01
v -250 -250 -0.01
v 250 -250 -0.01
v 250 250 -0.01
# (3=grass texture)
p 4 3
0.5 1.0 0.5 1
0 0 0
1 100 0
2 100 50
3 0 50
\ No newline at end of file
v -20 20 0
v 20 20 0
v 20 -20 0
v -20 -20 0
v -20 20 8
v 20 20 8
v 20 -20 8
v -20 -20 8
v -20 -16 8
v -20 -16 0
# (6=hek texture)
p 4 6
1.0 1.0 1.0 1
3 0 0
2 10 0
6 10 2
7 0 2
p 4 6
1.0 1.0 1.0 1
2 0 0
1 10 0
5 10 2
6 0 2
p 4 6
1.0 1.0 1.0 1
1 0 0
0 10 0
4 10 2
5 0 2
p 4 6
1.0 1.0 1.0 1
0 0 0
9 10 0
8 10 2
4 0 2
# 0-3: on ground plane
v 10 8 0
v -10 8 0
v -10 -8 0
v 10 -8 0
# 4-7: above ground plane
v 10 8 10
v -10 8 10
v -10 -8 10
v 10 -8 10
# 8-9: roof vertices
v 10 0 16
v -10 0 16
# 10-13: window hole (10x5) in long wall
v -5 -8 3
v 5 -8 3
v 5 -8 8
v -5 -8 8
# 14-17: window hole (10x5) in short wall
v 10 -5 3
v 10 5 3
v 10 5 8
v 10 -5 8
# 0: brick only
# 1: brick + window
# 2: roof
# long wall with real hole for window
# (made out of 4 quads)
# 18-21, vertices along the long edges
v -5 -8 0
v 5 -8 0
v 5 -8 10
v -5 -8 10
p 4 0
1 1 1 1
2 0.0 0.0
18 0.25 0.0
21 0.25 1.0
6 0.0 1.0
p 4 0
1 1 1 1
18 0.25 0.0
19 0.75 0.0
11 0.75 0.3
10 0.25 0.3
p 4 0
1 1 1 1
13 0.25 0.8
12 0.75 0.8
20 0.75 1.0
21 0.25 1.0
p 4 0
1 1 1 1
19 0.75 0.0
3 1.0 0.0
7 1.0 1.0
20 0.75 1.0
# short wall with real hole for window
# (made out of 4 quads)
# 22-25, vertices along the short edges
v 10 -5 0
v 10 5 0
v 10 5 10
v 10 -5 10
p 4 0
1 1 1 1
3 0.1 0.0
22 0.25 0.0
25 0.25 1.0
7 0.1 1.0
p 4 0
1 1 1 1
22 0.25 0.0
23 0.75 0.0
15 0.75 0.3
14 0.25 0.3
p 4 0
1 1 1 1
17 0.25 0.8
16 0.75 0.8
24 0.75 1.0
25 0.25 1.0
p 4 0
1 1 1 1
23 0.75 0.0
0 1.0 0.0
4 1.0 1.0
24 0.75 1.0
# long wall with fake (textured) window
p 4 1
1 1 1 1
0 0.0 0.0
1 1.0 0.0
5 1.0 1.0
4 0.0 1.0
# short wall with fake (textured) window
p 4 1
1 1 1 1
1 0.1 0.0
2 0.9 0.0
6 0.9 1.0
5 0.1 1.0
# real window in long wall
# -1 = untextured, use given color, ignore texture coordinates
# note the alpha of 0.5
p 4 -1
0.7 0.7 0.7 0.5
10 0.0 0.0
11 0.0 0.0
12 0.0 0.0
13 0.0 0.0
# real window in short wall
# -1 = untextured, use given color, ignore texture coordinates
# note the alpha of 0.5
p 4 -1
0.7 0.7 0.7 0.5
14 0.0 0.0
15 0.0 0.0
16 0.0 0.0
17 0.0 0.0
# roof polygons
p 4 2
1 1 1 1
6 0.0 0.0
7 2.0 0.0
8 2.0 1.0
9 0.0 1.0
p 4 2
1 1 1 1
4 0.0 0.0
5 2.0 0.0
9 2.0 1.0
8 0.0 1.0
# "triangles" at the side of the roof
p 3 0
1 1 1 1
7 0.1 1.0
4 0.9 1.0
8 0.5 1.6
p 3 0
1 1 1 1
5 0.1 1.0
6 0.9 1.0
9 0.5 1.6
/* Computer Graphics, Assignment, Depth-sorting and transparency
* Description ..... Depth-Sorting
* Date ............ 23.11.2009
* Created by ...... Paul Melis
*
* Student name ....
* Student email ...
* Collegekaart ....
* Date ............
* Comments ........
*
*
* (always fill in these fields before submitting!!)
*/
#if defined(__GNUC__)
#define glCheckError(s) { GLenum error; if ((error=glGetError())) \
fprintf(stderr, "* GL error - %s (%s; %s, line %d): %s\n", \
(s), __FUNCTION__,__FILE__,__LINE__, gluErrorString(error)); }
#else /* __GNUC__ */
#define glCheckError(s) { GLenum error; if ((error=glGetError())) \
fprintf(stderr, "* GL error - %s (line %d): %s\n", \
(s), __LINE__, gluErrorString(error)); }
#endif /* __GNUC__ */
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include "polys.h"
#include "readpng.h"
#include "geometry.h"
#include "bsp.h"
struct texture_data
{
const char *filename;
int contains_transparency;
};
struct texture_data texture_files[] =
{
// File name, transparency flag (the flag will be set during image loading)
{ "textures/wall_bricks_only.png", 0 },
{ "textures/wall_with_window.png", 0 },
{ "textures/roof2.png", 0 },
{ "textures/grass.png", 0 },
{ "textures/tree.png", 0 },
{ "textures/sky.png", 0 },
{ "textures/hek2.png", 0 },
{ NULL, 0 },
};
GLuint *texture_names;
int num_textures;
polys *scene_polygons;
polys *scene_opaque_polygons;
polys *scene_transparent_polygons;
polys *polylistSkydome;
BSPNode *bsp_root;
int show_textures = 0;
int show_polygons_as_lines = 0;
int do_depth_sorting = 0;
int sort_using_rays = 0;
int draw_opaque_polygons = 1;
vec3 camPosition;
float camDistance = 35.0;
float camRotZ = -45.0, camAzimuth = 20.0;
float saved_camRotZ, saved_camAzimuth, saved_camDistance;
int mouse_mode = 0;
int mx, my;
GLfloat mat_sun[] = { 1.0, 1.0, 0.5, 1.0 };
GLfloat mat_no_sun[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
GLfloat mat_diffuse[] = { 1, 1, 1, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_no_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat mat_no_specular[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat mat_no_shininess[] = { 0.0 };
GLfloat light_position[] = { -8.0, -8.0, 8.0, 0.0 };
GLfloat light_ambient[] = { 0.4, 0.4, 0.4, 0.0 };
GLfloat light_diffuse[] = { 0.6, 0.6, 0.6, 0.0 };
// Rough center points of the objects in the scene.
// Note: these positions are only used for rotating around them
// with the camera, not to place objects in the scene.
#define NUM_OBJECTS 4
vec3 object_positions[NUM_OBJECTS] =
{
/* house, goldfish, tree, somewhere at the side of the house */
{0.0, 0.0, 5.0},
{0.0, 0.0, 4.5},
{5.0, 18.0, 10.0},
{0.0, 10.0, 0.0},
};
// Determines around which object the camera rotates
int current_object = 0;
void
InitializePolygonlists(void)
{
polys *model_polygons;
poly p;
scene_polygons = CreatePolylist(128);
model_polygons = CreatePolylist(128);
// Load the models from .obj files and create a single polylist
// (scene_polygons) to hold all polygons
// House
loadPolygonalObject(model_polygons, "house.obj", texture_names, num_textures,
1.0, 0.0, 0.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
// Ground
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "ground.obj", texture_names, num_textures,
1.0, 0.0, 0.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
// Table
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "table.obj", texture_names, num_textures,
1.0, 0.0, 0.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
#if 0
// Tree
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "tree.obj", texture_names, num_textures,
0.6, 5.0, 16.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
#endif
#if 0
// Fish bowl
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "fishbowl.obj", texture_names, num_textures,
1.0, 0.0, 0.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
// Goldfish
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "goldfish.obj", texture_names, num_textures,
1.0, 0.0, 0.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
#endif
#if 0
// Fence
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "hek.obj", texture_names, num_textures,
1.0, 0.0, 0.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
#endif
#if 0
// A transparent cow (moooh!)
ClearPolylist(model_polygons);
loadPolygonalObject(model_polygons, "cow.obj", texture_names, num_textures,
10.0, -3.0, -15.0, 0.0);
AppendPolylist(scene_polygons, model_polygons);
#endif
// The skydome
polylistSkydome = CreatePolylist(1000);
createHemisphere(polylistSkydome, 250, 0, 0, 0, 1, 1, 1);
for (int i = 0; i < polylistSkydome->length; i++)
polylistSkydome->items[i].opengl_texture_name = texture_names[5];
// Done!
printf("%d polygons in the scene\n", scene_polygons->length);
//
// Sort polygons by type (opaque versus transparent)
//
// Estimate needed list size
scene_opaque_polygons = CreatePolylist(scene_polygons->length/2);
scene_transparent_polygons = CreatePolylist(scene_polygons->length/2);
for (int i = 0; i < scene_polygons->length; i++)
{
p = scene_polygons->items[i];
if (
// Non-textured transparent polygon
(p.texture_id == -1 && p.color[3] < 1.0)
||
// Textured transparent polygon
(p.texture_id >= 0 && texture_files[p.texture_id].contains_transparency)
)
{
// We split quads into two triangles, so that all transparent
// geometry is defined with triangles only. This makes the
// splitting during BSP construction much easier as
// we only have to handle one type of primitive that can be
// split in only a few ways.
if (p.points == 4)
{
poly q = p;
// q is defined by points 0, 1 and 2 of p
q.points = 3;
AddPolyToPolylist(scene_transparent_polygons, q);
// second q is defined by points 0, 2 and 3 of p
q.pts[1] = p.pts[2];
q.tcoord[1] = p.tcoord[2];
q.pts[2] = p.pts[3];
q.tcoord[2] = p.tcoord[3];
AddPolyToPolylist(scene_transparent_polygons, q);
}
else if (p.points == 3)
AddPolyToPolylist(scene_transparent_polygons, p);
else
printf("Skipping polygon with %d points, only quads or triangles allowed\n", p.points);
}
else
{
// Opaque polygon
AddPolyToPolylist(scene_opaque_polygons, p);
}
}
printf("%d opaque polygons\n", scene_opaque_polygons->length);
printf("%d transparent polygons\n", scene_transparent_polygons->length);
// Build BSP tree
bsp_root = BuildBSPTreeIncorrect(scene_transparent_polygons);
}
void
InitGL(void)
{
GLvoid *image_data;
int i, width, height;
int has_alpha_channel;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat) 800 / (GLfloat) 600, 0.1f, 1000.0f);
glClearColor(0.7, 0.7, 1, 1);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE); // We want 2-sided geometry
glEnable(GL_COLOR_MATERIAL);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_no_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_no_shininess);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Using GL_REPLACE will effectively disable lighting.
// The default mode, GL_MODULATE, will use the texture color to
// module the shaded material color, so the end result still
// contains the shading.
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// generate OpenGL texture names
num_textures = 0;
for (i = 0; texture_files[i].filename != NULL; i++)
num_textures++;
texture_names = malloc(num_textures * sizeof(GLuint));
glGenTextures(num_textures, texture_names);
glCheckError("glGenTextures");
// create textures from image files
GLint texture_internal_format;
GLenum texture_format, texture_type;
for (i = 0; i < num_textures; i++)
{
image_data = (GLvoid *) readPNGFile(texture_files[i].filename, &width, &height, &has_alpha_channel);
if (image_data)
{
printf("texture %d (OpenGL name = %d): %s, %d x %d\n", i,
texture_names[i], texture_files[i].filename, width, height);
if (has_alpha_channel)
{
// Convert the RGB image to RGBA, by replacing
// red pixels with transparent ones
printf("... contains alpha channel\n");
texture_files[i].contains_transparency = 1;
texture_internal_format = GL_RGBA8;
texture_format = GL_RGBA;
texture_type = GL_UNSIGNED_BYTE;
}
else
{
texture_internal_format = GL_RGB8;
texture_format = GL_RGB;
texture_type = GL_UNSIGNED_BYTE;
}
glBindTexture(GL_TEXTURE_2D, texture_names[i]);
glCheckError("glBindTexture");
#if 0
// No mipmapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckError("glTexParameteri");
glTexImage2D(GL_TEXTURE_2D, 0, texture_internal_format,
width, height, 0, texture_format, texture_type, image_data);
glCheckError("glTexImage2D");
#else
// Mipmapping
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glCheckError("glTexParameteri");
gluBuild2DMipmaps(GL_TEXTURE_2D, texture_internal_format, width, height,
texture_format, texture_type, image_data);
glCheckError("gluBuild2DMipmaps");
#endif
// Free the image data, as OpenGL will have made its internal
// copy by now
free(image_data);
}
else
{
perror(texture_files[i].filename);
exit(0);
}
}
}
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, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Draw a single polygon, taking into account the texture
// and transparency properties of the polygon
void
DrawPolygon(poly p)
{
if (p.opengl_texture_name >= 0)
{
// Textured
glColor3f(p.color[0], p.color[1], p.color[2]);
glBindTexture(GL_TEXTURE_2D, p.opengl_texture_name);
}
else
{
// Untextured (but colored and possibly with alpha transparency)
glColor4f(p.color[0], p.color[1], p.color[2], p.color[3]);
glBindTexture(GL_TEXTURE_2D, 0);
}
glBegin(GL_POLYGON);
for (int j = 0; j < p.points; j++)
{
glNormal3f(p.normal[j].x, p.normal[j].y, p.normal[j].z);
glTexCoord2f(p.tcoord[j].x, p.tcoord[j].y);
glVertex3f(p.pts[j].x, p.pts[j].y, p.pts[j].z);
}
glEnd();
}
// Draw all the polygons in a list
void
DrawPolylist(polys * list)
{
int i;
for (i = 0; i < list->length; i++)
DrawPolygon(list->items[i]);
}
// Use the BSP tree to draw transparent geometry in the correct
// order, based on the given eye position
void
DrawBSPTree(BSPNode *node, vec3 eye_position)
{
}
void
SetupCamera(void)
{
float cx, cy, cz;
float t;
float beta, gamma;
vec3 op;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Verbose, but straightforward way, of positioning the camera.
// Assume the camera's final position is (cx, cy, cz) and Z is up.
// Start with c being (camDistance, 0, 0)
// First rotate around Y, then around Z.
// Now we have c at the given distance from the origin, with specified rotation angles.
// degrees -> radians
beta = camAzimuth / 180.0 * 3.1415926535;
gamma = camRotZ / 180.0 * 3.1415926535;
cx = camDistance;
cy = cz = 0.0;
// Rotate around Y
t = cx;
cx = cx * cos(beta) - cz * sin(beta);
cz = t * sin(beta) + cz * cos(beta);
// Rotate around Z
t = cx;
cx = cx * cos(gamma) + cy * sin(gamma);
cy = t * sin(gamma) + cy * cos(gamma);
// Translate view to rotate around the selected object
op = object_positions[current_object];
gluLookAt(cx+op.x, cy+op.y, cz+op.z, op.x, op.y, op.z, 0.0, 0.0, 1.0);
camPosition.x = cx + op.x;
camPosition.y = cy + op.y;
camPosition.z = cz + op.z;
}
void
DrawGLScene(void)
{
float tx, ty, tz;
float a, rx, ry, rz;
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// set camera based on previous mouse input
SetupCamera();
// Set the light position. We do that after setting up the
// camera so that the light position will keep its world position.
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
// Draw the scene
if (show_polygons_as_lines)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_TEXTURE_2D);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
if (show_textures)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
}
else
glDisable(GL_TEXTURE_2D);
}
if (draw_opaque_polygons)
{
DrawPolylist(scene_opaque_polygons);
// Draw the skydome with lighting turned off
glPushAttrib(GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glPushMatrix();
glRotatef(90, 1, 0, 0);
DrawPolylist(polylistSkydome);
glPopMatrix();
glPopAttrib();
}
// XXX use BSP to draw
DrawBSPTree(bsp_root, camPosition);
#if 0
// Axes
glPushAttrib(GL_LIGHTING_BIT);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(1,0,0);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glColor3f(0,1,0);
glVertex3f(0,0,0);
glVertex3f(0,1,0);
glColor3f(0,0,1);
glVertex3f(0,0,0);
glVertex3f(0,0,1);
glEnd();
glPopAttrib();
#endif
// Finally, swap back and front buffers
glutSwapBuffers();
}
void
keyPressed(unsigned char key, int x, int y)
{
(void)x;
(void)y;
switch (key)
{
case 'o':
draw_opaque_polygons = 1 - draw_opaque_polygons;
glutPostRedisplay();
break;
case 't':
show_textures = 1 - show_textures;
glutPostRedisplay();
break;
case 'l':
show_polygons_as_lines = 1;
glutPostRedisplay();
break;
case 'p':
show_polygons_as_lines = 0;
glutPostRedisplay();
break;
case 'd':
do_depth_sorting = 1 - do_depth_sorting;
printf("Depth sorting now %s\n", do_depth_sorting ? "on" : "off");
glutPostRedisplay();
break;
case 'r':
sort_using_rays = 1 - sort_using_rays;
printf("Depth sorting using rays now %s\n", sort_using_rays ? "on" : "off");
glutPostRedisplay();
break;
case 'v':
current_object = (current_object + 1) % NUM_OBJECTS;
glutPostRedisplay();
break;
case 'q':
exit(-1);
}
}
void
specialKeyPressed(int key, int x, int y)
{
(void)x;
(void)y;
(void)key;
DrawGLScene();
}
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.1)
camDistance = 0.1;
else if (camDistance > 1000.0)
camDistance = 1000.0;
}
}
int
main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL Framework");
glutDisplayFunc(&DrawGLScene);
glutIdleFunc(&DrawGLScene);
glutReshapeFunc(&ReSizeGLScene);
glutSpecialFunc(&specialKeyPressed);
glutKeyboardFunc(&keyPressed);
glutMouseFunc(&mouseFunc);
glutMotionFunc(&motionFunc);
InitGL();
InitializePolygonlists();
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 immediately 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;
}
void
DestroyPolylist(polys *list)
{
if (list == NULL)
return;
list->capacity = 0;
list->length = 0;
free(list->items);
list = NULL;
}
void
ClearPolylist(polys *list)
{
list->length = 0;
}
/* exit() if no memory available, returns 0 if poly* is NULL, 1 otherwise */
static 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;
}
/* 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. */
static 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;
}
/* poly's are structs of (point) arrays, so they are passed by value instead
* of by reference (as do arrays) */
void
AddPolyToPolylist(polys *list, poly p)
{
if (list == NULL)
return;
/* 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++;
}
/* Append the items of 'to_append' to 'list' */
void
AppendPolylist(polys *list, polys *to_append)
{
for (int i = 0; i < to_append->length; i++)
AddPolyToPolylist(list, to_append->items[i]);
}
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>
#include "v3math.h"
#define MAX_VERTICES 4
typedef struct poly
{
// Number of vertices
int points;
// Vertices and their normals
vec3 pts[MAX_VERTICES];
vec3 normal[MAX_VERTICES];
// Overall polygon color
GLfloat color[4];
// Texture identifier as set in a .obj file (can be -1)
int texture_id;
// OpenGL texture name
// (note: signed, so we can use -1 to denote 'no texture')
GLint opengl_texture_name;
// Texture coordinates per vertex
vec3 tcoord[MAX_VERTICES];
}
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;
/* array of polygons, with length "capacity" of which only the first "length"
* items will be in use */
poly *items;
}
polys;
/* Create an empty list of polys, initially reserving space for 'n' polys */
polys* CreatePolylist(int n);
/* Destroy a list of polygons */
void DestroyPolylist(polys *list);
/* poly's are structs of (point) arrays, so they are passed by value instead
* of by reference (as do arrays) */
void AddPolyToPolylist(polys *list, poly p);
/* Append the items of 'to_append' to 'list' */
void AppendPolylist(polys *list, polys *to_append);
/* Copies the list of polys `list', calls AddPolytoPolylist() for each poly
* in the given list. */
polys* CopyPolylist(polys *list);
/* Clear a list of polygons. Note: this does not de-allocate the item array */
void ClearPolylist(polys *list);
#endif
/*
The following code is based on:
http://www.iwr.uni-heidelberg.de/groups/ngg/CG200708/Txt/png.c
The original copyright notice:
* png.c -- png texture loader
* last modification: aug. 14, 2007
*
* Copyright (c) 2005-2007 David HENRY
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* gcc -Wall -ansi -lGL -lGLU -lglut
* `libpng12-config --cflags --libs` png.c -o png
*/
#include <stdio.h>
#include <stdlib.h>
#include <png.h>
#include "readpng.h"
// Returns NULL if loading failed, or a pointer to
// a malloc()ed pixel buffer otherwise.
// The output parameters width, height and has_alpha_channel will be
// set apropriately in the latter case
GLubyte*
readPNGFile(const char *filename, int *width, int *height, int *has_alpha_channel)
{
png_byte magic[8];
png_structp png_ptr;
png_infop info_ptr;
png_uint_32 w, h;
png_bytep *row_pointers = NULL;
GLubyte *texels;
int bytes_per_pixel;
int bit_depth, color_type;
FILE *f;
int i;
f = fopen (filename, "rb");
if (!f)
{
fprintf(stderr, "Could not open '%s'!\n", filename);
return NULL;
}
// Read and check magic number
fread(magic, 1, sizeof (magic), f);
if (!png_check_sig(magic, sizeof(magic)))
{
fprintf(stderr, "Not a valid PNG file: '%s'\n", filename);
fclose(f);
return NULL;
}
// Create png read struct
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
fclose(f);
return NULL;
}
// Create png info struct
info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr)
{
fclose(f);
png_destroy_read_struct (&png_ptr, NULL, NULL);
return NULL;
}
if (setjmp (png_jmpbuf (png_ptr)))
{
fclose(f);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
if (row_pointers)
free(row_pointers);
// XXX free texels
return NULL;
}
png_init_io(png_ptr, f);
png_set_sig_bytes(png_ptr, sizeof (magic));
// Read png info
png_read_info(png_ptr, info_ptr);
// Get some data from the header
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
color_type = png_get_color_type(png_ptr, info_ptr);
// Check if we can handle this image type
if (bit_depth != 8)
{
// XXX proper cleanup
return NULL;
}
if (color_type == PNG_COLOR_TYPE_RGB)
{
bytes_per_pixel = 3;
*has_alpha_channel = 0;
}
else if (color_type == PNG_COLOR_TYPE_RGBA)
{
bytes_per_pixel = 4;
*has_alpha_channel = 1;
}
else
{
return NULL;
}
png_get_IHDR (png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL);
*width = w;
*height = h;
// Allocate memory for pixel data
texels = (GLubyte*) malloc(w * h * bytes_per_pixel);
// Allocate memory for the row pointers array
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * h);
// Set up the row pointers
for (i = 0; i < h; ++i)
row_pointers[i] = (png_bytep) (texels + (h - (i + 1)) * w * bytes_per_pixel);
// Read pixel data using the row pointers
png_read_image(png_ptr, row_pointers);
// Finish decompression and release memory
png_read_end(png_ptr, NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
// Cleanup
free(row_pointers);
fclose(f);
return texels;
}
#ifndef READPNG_H
#define READPNG_H
#include <GL/gl.h>
GLubyte* readPNGFile(const char *filename, int *width, int *height, int *has_alpha_channel);
#endif
v 2.627827 2.556087 0.025656
v 2.627827 2.214265 0.025656
v 2.286005 2.214265 0.025656
v 2.286005 2.556087 0.025656
v 2.627827 2.556087 3.596503
v 2.627827 2.214265 3.596503
v 2.286005 2.214265 3.596503
v 2.286005 2.556087 3.596503
v 2.627827 -2.316548 0.025656
v 2.627827 -2.658370 0.025656
v 2.286005 -2.658370 0.025656
v 2.286005 -2.316548 0.025656
v 2.627827 -2.316548 3.596503
v 2.627827 -2.658370 3.596503
v 2.286005 -2.658370 3.596503
v 2.286005 -2.316548 3.596503
v -2.230601 -2.316548 0.025656
v -2.230601 -2.658370 0.025656
v -2.572424 -2.658370 0.025656
v -2.572423 -2.316548 0.025656
v -2.230601 -2.316548 3.596503
v -2.230602 -2.658370 3.596503
v -2.572424 -2.658370 3.596503
v -2.572424 -2.316548 3.596503
v -2.230601 2.556087 0.025656
v -2.230601 2.214265 0.025656
v -2.572424 2.214265 0.025656
v -2.572423 2.556087 0.025656
v -2.230601 2.556087 3.596503
v -2.230602 2.214265 3.596503
v -2.572424 2.214265 3.596503
v -2.572424 2.556087 3.596503
v 2.781483 2.781482 3.530788
v 2.781483 -2.781483 3.530788
v -2.781483 -2.781482 3.530788
v -2.781482 2.781484 3.530788
v 2.781484 2.781481 3.673192
v 2.781481 -2.781484 3.673192
v -2.781484 -2.781482 3.673192
v -2.781482 2.781483 3.673192
p 4 -1
0.8 0.2 0.1 1
0 0.0 0.0
4 0.0 0.0
5 0.0 0.0
1 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
1 0.0 0.0
5 0.0 0.0
6 0.0 0.0
2 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
2 0.0 0.0
6 0.0 0.0
7 0.0 0.0
3 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
4 0.0 0.0
0 0.0 0.0
3 0.0 0.0
7 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
8 0.0 0.0
12 0.0 0.0
13 0.0 0.0
9 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
9 0.0 0.0
13 0.0 0.0
14 0.0 0.0
10 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
10 0.0 0.0
14 0.0 0.0
15 0.0 0.0
11 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
12 0.0 0.0
8 0.0 0.0
11 0.0 0.0
15 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
16 0.0 0.0
20 0.0 0.0
21 0.0 0.0
17 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
17 0.0 0.0
21 0.0 0.0
22 0.0 0.0
18 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
18 0.0 0.0
22 0.0 0.0
23 0.0 0.0
19 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
20 0.0 0.0
16 0.0 0.0
19 0.0 0.0
23 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
24 0.0 0.0
28 0.0 0.0
29 0.0 0.0
25 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
25 0.0 0.0
29 0.0 0.0
30 0.0 0.0
26 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
26 0.0 0.0
30 0.0 0.0
31 0.0 0.0
27 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
28 0.0 0.0
24 0.0 0.0
27 0.0 0.0
31 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
32 0.0 0.0
33 0.0 0.0
34 0.0 0.0
35 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
36 0.0 0.0
39 0.0 0.0
38 0.0 0.0
37 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
32 0.0 0.0
36 0.0 0.0
37 0.0 0.0
33 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
33 0.0 0.0
37 0.0 0.0
38 0.0 0.0
34 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
34 0.0 0.0
38 0.0 0.0
39 0.0 0.0
35 0.0 0.0
p 4 -1
0.8 0.2 0.1 1
36 0.0 0.0
32 0.0 0.0
35 0.0 0.0
39 0.0 0.0
v 16.082331 11.889433 0.000001
v -16.082329 -11.889434 -0.000001
v -16.082329 -11.889432 40.000000
v 16.082335 11.889438 39.999992
# (4=tree texture)
p 4 4
0.5 1.0 0.5 1
0 0 0
3 0 0.99
2 1 0.99
1 1 0
v -11.889431 16.082329 -0.000001
v 11.889435 -16.082331 0.000001
v 11.889429 -16.082327 40.000004
v -11.889439 16.082336 39.999992
# (4=tree texture)
p 4 4
0.5 1.0 0.5 1
4 0 0
7 0 0.99
6 1 0.99
5 1 0
#ifndef V3MATH_H
#define V3MATH_H
#include <math.h>
typedef struct
{
float x, y, z;
}
vec3;
// Create a new 3-vector of floats
static inline vec3
v3_create(float x, float y, float z)
{
vec3 res;
res.x = x;
res.y = y;
res.z = z;
return res;
}
// Return -a
static inline vec3
v3_negate(vec3 a)
{
vec3 res;
res.x = - a.x;
res.y = - a.y;
res.z = - a.z;
return res;
}
// Return a + b
static inline vec3
v3_add(vec3 a,vec3 b)
{
vec3 res;
res.x = a.x+b.x;
res.y = a.y+b.y;
res.z = a.z+b.z;
return res;
}
// Return a - b
static inline vec3
v3_subtract(vec3 a, vec3 b)
{
vec3 res;
res.x = a.x-b.x;
res.y = a.y-b.y;
res.z = a.z-b.z;
return res;
}
// Return a / |a|
static inline vec3
v3_normalize(vec3 a)
{
vec3 res;
double l = sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
res = a;
res.x /= l;
res.y /= l;
res.z /= l;
return res;
}
// Return a ^ b
static inline vec3
v3_crossprod(vec3 a, vec3 b)
{
vec3 res;
res.x = a.y*b.z - a.z*b.y;
res.y = a.z*b.x - a.x*b.z;
res.z = a.x*b.y - a.y*b.x;
return res;
}
// Return a * b
static inline float
v3_dotprod(vec3 a, vec3 b)
{
return a.x*b.x + a.y*b.y + a.z*b.z;
}
// Return a*s
static inline vec3
v3_multiply(vec3 a, float s)
{
vec3 res;
res.x = a.x*s;
res.y = a.y*s;
res.z = a.z*s;
return res;
}
// Return |a|
static inline float
v3_length(vec3 a)
{
return sqrt(a.x*a.x + a.y*a.y + a.z*a.z);
}
// Return the i-th component of a, i.e. for i=0
// this returns a.x
static inline float
v3_component(vec3 a, int i)
{
if (i == 0)
return a.x;
else if (i == 1)
return a.y;
else
return a.z;
}
// Set the i-th component of a to v
static inline vec3
v3_set_component(vec3 a, int i, float v)
{
vec3 res = a;
if (i == 0)
res.x = v;
else if (i == 1)
res.y = v;
else
res.z = v;
return res;
}
#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