|    163  |    167  | 
|    164 		return acc; |    168 		return acc; | 
|    165 	} |    169 	} | 
|    166 } |    170 } | 
|    167  |    171  | 
|         |    172 static void *renderrow(void *data) | 
|         |    173 { | 
|         |    174 	RenderrowData *d = (RenderrowData*) data; | 
|         |    175 	for (int x = 0; x < d->w; x++) { | 
|         |    176 		// generate a ray from eye passing through this pixel | 
|         |    177 #if 1 | 
|         |    178 		// no oversampling | 
|         |    179 		Vector3 dir = Vector3(d->vx, d->vy, 0) - d->eye; | 
|         |    180 		dir.normalize(); | 
|         |    181 		Ray ray(d->eye, dir); | 
|         |    182 		Colour c = d->rt->raytrace(ray, 0, NULL); | 
|         |    183 #else | 
|         |    184 		// 5x oversampling | 
|         |    185 		Vector3 dir = Vector3(); | 
|         |    186 		Colour c = Colour(); | 
|         |    187  | 
|         |    188 		for (int i = 0; i < 5; i++) | 
|         |    189 		{ | 
|         |    190 			float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; | 
|         |    191 			float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; | 
|         |    192 			dir = Vector3(d->vx + osax[i] * d->dx, | 
|         |    193 				d->vy + osay[i]*d->dy , 0) - d->eye; | 
|         |    194 			dir.normalize(); | 
|         |    195 			Ray ray(d->eye, dir); | 
|         |    196 			c += d->rt->raytrace(ray, 0, NULL); | 
|         |    197 		} | 
|         |    198 		c = c * (1./5); | 
|         |    199 #endif | 
|         |    200 		*(d->iter++) = c.r; | 
|         |    201 		*d->iter++ = c.g; | 
|         |    202 		*d->iter++ = c.b; | 
|         |    203 		d->vx += d->dx; | 
|         |    204 	} | 
|         |    205 #ifdef PTHREADS | 
|         |    206 	pthread_exit((void *)d); | 
|         |    207 #endif | 
|         |    208 } | 
|         |    209  | 
|    168 float *Raytracer::render(int w, int h) |    210 float *Raytracer::render(int w, int h) | 
|    169 { |    211 { | 
|    170 	int x, y; |    212 	float *data; | 
|    171 	float *data, *iter; |         | 
|    172  |    213  | 
|    173 	data = (float *) malloc(w*h*3*sizeof(float)); |    214 	data = (float *) malloc(w*h*3*sizeof(float)); | 
|    174 	if (!data) |    215 	if (!data) | 
|    175 		return NULL; |    216 		return NULL; | 
|    176  |    217  | 
|    177 	float startx = -1.0 * 4, starty = (float)h/w * 4; |    218 	float startx = -1.0 * 4, starty = (float)h/w * 4; | 
|    178 	float dx = -2*startx/w, dy = -2*starty/h; |    219 	float dx = -2*startx/w, dy = -2*starty/h; | 
|    179 	float vx, vy; |    220 	float vy; | 
|         |    221 	RenderrowData *d; | 
|    180  |    222  | 
|    181 	//srand(time(NULL)); |    223 	//srand(time(NULL)); | 
|    182  |    224  | 
|    183 	// eye - viewing point |    225 	// eye - viewing point | 
|    184 	Vector3 eye(0, 0, -5); |    226 	Vector3 eye(0, 0, -5); | 
|    185  |    227  | 
|    186 	// for each pixel... |    228 	// for each pixel... | 
|    187 	iter = data; |    229 	vy = starty; | 
|    188 	for (vy = starty, y = 0; y < h; y++) { |    230  | 
|    189 		vx = startx; |    231 #ifdef PTHREADS | 
|    190 		for (x = 0; x < w; x++) { |    232 	int num_threads = 20; | 
|    191 			// generate a ray from eye passing through this pixel |    233 	printf("* pthreads enabled, using %d threads\n", num_threads); | 
|    192 #if 1 |    234 	pthread_t threads[num_threads]; | 
|    193 			// no oversampling |    235 	for (int t = 0; t < num_threads; t++) | 
|    194 			Vector3 dir = Vector3(vx, vy, 0) - eye; |    236 		threads[t] = NULL; | 
|    195 			dir.normalize(); |    237 	int t = 0; | 
|    196 			Ray ray(eye, dir); |    238 #endif | 
|    197 			Colour c = raytrace(ray, 0, NULL); |    239  | 
|         |    240 	printf("* rendering row   0 (  0% done)"); | 
|         |    241 	for (int y = 0; y < h; y++) { | 
|         |    242 		d = (RenderrowData*) malloc(sizeof(RenderrowData)); | 
|         |    243 		d->rt = this; | 
|         |    244 		d->w = w; | 
|         |    245 		d->vx = startx; | 
|         |    246 		d->vy = vy; | 
|         |    247 		d->dx = dx; | 
|         |    248 		d->dy = dy; | 
|         |    249 		d->eye = eye; | 
|         |    250 		d->iter = data + y*3*w; | 
|         |    251 #ifdef PTHREADS | 
|         |    252 		/* create new thread and increase 't' */ | 
|         |    253 		int rc = pthread_create(&threads[t++], NULL, renderrow, (void *)d); | 
|         |    254 		if (rc) { | 
|         |    255 			printf("\nERROR: return code from pthread_create() is %d\n", rc); | 
|         |    256 			exit(1); | 
|         |    257 		} | 
|         |    258 		/* when 't' owerflows, reset it */ | 
|         |    259 		if (t >= num_threads) | 
|         |    260 			t = 0; | 
|         |    261 		/* wait for next thread in fifo queue, so the descriptor can be reused; | 
|         |    262 		   this also limits number of running threads */ | 
|         |    263 		if (threads[t] != NULL) | 
|         |    264 			if (pthread_join(threads[t], (void**)&d) == 0) | 
|         |    265 				free(d); | 
|    198 #else |    266 #else | 
|    199 			// 5x oversampling |    267 		renderrow((void *)d); | 
|    200 			Vector3 dir = Vector3(); |    268 		free(d); | 
|    201 			Colour c = Colour(); |    269 #endif | 
|    202  |         | 
|    203 			for (int i = 0; i < 5; i++) |         | 
|    204 			{ |         | 
|    205 				float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4}; |         | 
|    206 				float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4}; |         | 
|    207 				dir = Vector3(vx + osax[i]*dx, |         | 
|    208 					vy + osay[i]*dy , 0) - eye; |         | 
|    209 				dir.normalize(); |         | 
|    210 				Ray ray(eye, dir); |         | 
|    211 				c += raytrace(ray, 0, NULL); |         | 
|    212 			} |         | 
|    213 			c = c * (1./5); |         | 
|    214 #endif |         | 
|    215 			*iter++ = c.r; |         | 
|    216 			*iter++ = c.g; |         | 
|    217 			*iter++ = c.b; |         | 
|    218 			vx += dx; |         | 
|    219 		} |         | 
|    220 		vy += dy; |    270 		vy += dy; | 
|    221 		printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%2d%% done (row %4d)", y*100/(h-1), y); |    271 		printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%4d (%2d%% done)", y, y*100/(h-1)); | 
|    222 	} |    272 	} | 
|    223 	printf("\n"); |    273 	printf("\n"); | 
|         |    274  | 
|         |    275 #ifdef PTHREADS | 
|         |    276 	printf("* waiting for threads to finish\n"); | 
|         |    277 	for (t = 0; t < num_threads; t++) | 
|         |    278 		if (pthread_join(threads[t], (void**)&d) == 0) | 
|         |    279 			free(d); | 
|         |    280 #endif | 
|         |    281  | 
|    224 	return data; |    282 	return data; | 
|    225 } |    283 } | 
|    226  |    284  | 
|    227 void Raytracer::addshape(Shape *shape) |    285 void Raytracer::addshape(Shape *shape) | 
|    228 { |    286 { |