-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.h
254 lines (213 loc) · 10.1 KB
/
utils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/*
utils.h - F.J. Estrada, Dec. 9, 2010
Utilities for the ray tracer. This file implements a number of
functions to simplify the raytracing code, including;
- Creating new instances of rays, objects, and light sources
- Setting up a camera
- Performing transformations on objects
- Image output
You MAY modify this file but only to ADD MORE OBJECT DEFINITIONS,
the rest of the file must remain unchanged.
Code for short inline functions is here, not in utils.c
Last Update: F.J. Estrada, Aug. 2017
*/
#include "RayTracer.h"
#include "svdDynamic.h"
#ifndef __utils_header
#define __utils_header
#define PRECISION 0.0001
// Functions to apply transformations to objects.
// If you add any transformations to the list below, document them carefully
inline void matMult(double A[4][4], double B[4][4])
{
// Performs matrix multiplication B=A*B (notice the result is left
// in B). This is so that we can compose transformations by
// premultiplying a given transformation matrix by one of our
// simple transformation matrices (rotate, translate, scale, etc).
// Note the indexing convention is [row][col]
double C[4][4];
int i,j,k;
memset(C,0,16*sizeof(double));
for (i=0;i<4;i++)
for (j=0;j<4;j++)
C[i][j]=(A[i][0]*B[0][j])+(A[i][1]*B[1][j])+(A[i][2]*B[2][j])+(A[i][3]*B[3][j]);
memcpy(B,C,16*sizeof(double));
}
inline void matVecMult(double A[4][4], struct point3D *pt)
{
// Matrix vector multiplication pt=A*pt, notice that the result
// is left in pt. This is useful for performing transformations
// on points and rays
struct point3D pr;
pr.px=(A[0][0]*pt->px)+(A[0][1]*pt->py)+(A[0][2]*pt->pz)+(A[0][3]*pt->pw);
pr.py=(A[1][0]*pt->px)+(A[1][1]*pt->py)+(A[1][2]*pt->pz)+(A[1][3]*pt->pw);
pr.pz=(A[2][0]*pt->px)+(A[2][1]*pt->py)+(A[2][2]*pt->pz)+(A[2][3]*pt->pw);
pr.pw=(A[3][0]*pt->px)+(A[3][1]*pt->py)+(A[3][2]*pt->pz)+(A[3][3]*pt->pw);
memcpy(pt,&pr,4*sizeof(double));
}
inline void matTranspose(double A[4][4], double B[4][4]){
// Performs matrix transpose B=A^T
double C[4][4];
int i, j, k;
memset(C, 0, 16*sizeof(double));
for(i=0; i < 4; i++){
for(j=0; j < 4; j++){
C[i][j] = A[j][i];
}
}
memcpy(B,C,16*sizeof(double));
}
// Matrix manipulation - Mind the fact that these functions will change the matrix T - for hierarchical objects you will
// need to be careful to make local copies for manipulation where needed.
void invert(double *T, double *Tinv);
void RotateXMat(double T[4][4], double theta); // X-axis rotation by theta radians
void RotateYMat(double T[4][4], double theta); // Y-axis rotation by theta radians
void RotateZMat(double T[4][4], double theta); // Z-axis rotation by theta radians
void TranslateMat(double T[4][4], double tx, double ty, double tz); // 3D translation
void ScaleMat(double T[4][4], double sx, double sy, double sz); // 3D non-uniform scaling
// Functions for geometric manipulation of *INDIVIDUAL* objects - be careful with composite objects: You will have
// to apply any transforms to each of the components.
void RotateX(struct object3D *o, double theta); // X-axis rotation by theta radians
void RotateY(struct object3D *o, double theta); // Y-axis rotation by theta radians
void RotateZ(struct object3D *o, double theta); // Z-axis rotation by theta radians
void Translate(struct object3D *o, double tx, double ty, double tz); // 3D translation
void Scale(struct object3D *o, double sx, double sy, double sz); // 3D non-uniform scaling
void printmatrix(double mat[4][4]);
// Vector management
inline void normalize(struct point3D *v)
{
// Normalizes a vector to unit length.
// Note that this assumes the w component of v is one, so make
// sure you don't have homogeneous vectors with w != 1
// floating around or things will go south.
double l;
l=v->px*v->px;
l+=(v->py*v->py);
l+=(v->pz*v->pz);
l=1.0/sqrt(l);
v->px*=l;
v->py*=l;
v->pz*=l;
}
inline double dot(struct point3D *u, struct point3D *v)
{
// Computes the dot product of 3D vectors u and v.
// The function assumes the w components of both vectors
// are 1.
return((u->px*v->px)+(u->py*v->py)+(u->pz*v->pz));
}
inline struct point3D *cross(struct point3D *u, struct point3D *v)
{
// Allocates and returns a vector with the cross product u x v.
// The function assumes the w components of both vectors
// are 1.
struct point3D *cp;
cp=(struct point3D *)calloc(1,sizeof(struct point3D));
cp->px=(u->py*v->pz)-(v->py*u->pz);
cp->py=(v->px*u->pz)-(u->px*v->pz);
cp->pz=(u->px*v->py)-(v->px*u->py);
cp->pw=1;
return(cp);
}
inline void addVectors(struct point3D *a, struct point3D *b)
{
// Performs the vector addition b=a+b. Note the result
// is left in b. This function assumes the w components
// of both vectors are set to 1.
b->px=b->px+a->px;
b->py=b->py+a->py;
b->pz=b->pz+a->pz;
b->pw=1; // Mind the homogeneous coordinate!
}
inline void subVectors(struct point3D *a, struct point3D *b)
{
// Performs the vector subtraction b=b-a. Note the result
// is left in b. This function assumes the w components
// of both vectors are set to 1.
b->px=b->px-a->px;
b->py=b->py-a->py;
b->pz=b->pz-a->pz;
b->pw=1; // Mind the homogeneous coordinate!
}
inline void scalarMultVector(struct point3D *a, double x){
// Performs the vector scalar multiplication a=a*x. The result is stored back into a;
a->px=a->px*x;
a->py=a->py*x;
a->pz=a->pz*x;
a->pw=1;
}
inline double length(struct point3D *a)
{
// Compute and return the length of a vector
return(sqrt((a->px*a->px)+(a->py*a->py)+(a->pz*a->pz)));
}
// Functions to instantiate primitives
struct point3D *newPoint(double px, double py, double pz);
struct pointLS *newPLS(struct point3D *p0, double r, double g, double b);
// Ray management inlines
inline void rayPosition(struct ray3D *ray, double lambda, struct point3D *pos)
{
// Compute and return 3D position corresponding to a given lambda
// for the ray.
pos->px=ray->p0.px+(lambda*ray->d.px);
pos->py=ray->p0.py+(lambda*ray->d.py);
pos->pz=ray->p0.pz+(lambda*ray->d.pz);
pos->pw=1;
}
inline void initRay(struct ray3D *ray, struct point3D *p0, struct point3D *d)
{
// Initializes the given ray3D struct with the the position
// and direction vectors. Note that this function DOES NOT normalize
// d to be a unit vector.
memcpy(&ray->p0,p0,sizeof(struct point3D));
memcpy(&ray->d,d,sizeof(struct point3D));
ray->rayPos=&rayPosition;
}
// Ray and normal transformations to enable the use of canonical intersection tests with transformed objects
void rayTransform(struct ray3D *ray_orig, struct ray3D *ray_transformed, struct object3D *obj);
void normalTransform(struct point3D *n_orig, struct point3D *n_transformed, struct object3D *obj);
// Functions to create new objects, one for each type of object implemented.
// You'll need to add code for these functions in utils.c
struct object3D *newPlane(double ra, double rd, double rs, double rg, double r, double g, double b, double alpha, double R_index, double shiny);
struct object3D *newSphere(double ra, double rd, double rs, double rg, double r, double g, double b, double alpha, double R_index, double shiny);
struct object3D *newCyl(double ra, double rd, double rs, double rg, double r, double g, double b, double alpha, double R_index, double shiny);
// Functions to obtain surface coordinates on objects
void planeCoordinates(struct object3D *plane, double a, double b, double *x, double *y, double *z);
void sphereCoordinates(struct object3D *plane, double a, double b, double *x, double *y, double *z);
void sphereNormal(struct object3D *sphere, double a, double b, double *x, double *y, double *z);
void cylCoordinates(struct object3D *plane, double a, double b, double *x, double *y, double *z);
void planeSample(struct object3D *plane, double *x, double *y, double *z);
void sphereSample(struct object3D *plane, double *x, double *y, double *z);
void cylSample(struct object3D *plane, double *x, double *y, double *z);
// Functions to compute intersections for objects.
// You'll need to add code for these in utils.c
void planeIntersect(struct object3D *plane, struct ray3D *r, double *lambda, struct point3D *p, struct point3D *n, double *a, double *b);
void sphereIntersect(struct object3D *sphere, struct ray3D *r, double *lambda, struct point3D *p, struct point3D *n, double *a, double *b);
void cylIntersect(struct object3D *cylinder, struct ray3D *r, double *lambda, struct point3D *p, struct point3D *n, double *a, double *b);
// Functions to texture-map objects
// You will need to add code for these if you implement texture mapping.
void loadTexture(struct object3D *o, const char *filename, int type, struct textureNode **t_list);
void texMap(struct image *img, double a, double b, double *R, double *G, double *B);
void alphaMap(struct image *img, double a, double b, double *R, double *G, double *B);
// Functions to insert objects and lights into their respective lists
void insertObject(struct object3D *o, struct object3D **list);
void insertPLS(struct pointLS *l, struct pointLS **list);
void addAreaLight(double sx, double sy, double nx, double ny, double nz,\
double tx, double ty, double tz, int lx, int ly,\
double r, double g, double b, struct object3D **o_list, struct pointLS **l_list);
// Function to set up the camera and viewing coordinate frame.
// You will have to add code to this function's body in utils.c
struct view *setupView(struct point3D *e, struct point3D *g, struct point3D *up, double f, double wl, double wt, double wsize);
// Image management output. Note that you will need to free() any images you
// allocate with newImage() using deleteImage().
struct image *readPPMimage(const char *filename);
struct image *readPGMimage(const char *filename);
struct image *newImage(int size_x, int size_y);
void imageOutput(struct image *im, const char *filename);
void deleteImage(struct image *im);
// Cleanup: Release memory allocated to objects and light sources. Note that you will
// need to do your own clean-up wherever you have requested ray positions,
// since each call to the ray position function returns a newly allocated point3D
// structure.
void cleanup(struct object3D *o_list, struct pointLS *l_list, struct textureNode *t_list);
#endif