Mercurial > cgi-bin > hgwebdir.cgi > PR > Applications > SSR > SSR__C-Ray__Bench
changeset 0:11a4bcadac2a
Initial SSR version
| author | Merten Sach <msach@mailbox.tu-berlin.de> |
|---|---|
| date | Thu, 22 Sep 2011 14:16:25 +0200 |
| parents | |
| children | b6c9e5f46e98 |
| files | .hgignore Makefile README.txt c-ray-mt.c scene sphfract |
| diffstat | 6 files changed, 996 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Thu Sep 22 14:16:25 2011 +0200 1.3 @@ -0,0 +1,7 @@ 1.4 +syntax: glob 1.5 + 1.6 +histograms 1.7 +nbproject 1.8 +c-ray-mt 1.9 +*.ppm 1.10 +*.o
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Thu Sep 22 14:16:25 2011 +0200 2.3 @@ -0,0 +1,48 @@ 2.4 +obj = \ 2.5 + SSR_lib/VMS/Histogram/Histogram.o \ 2.6 + SSR_lib/VMS/Histogram/FloatHist.o \ 2.7 + SSR_lib/VMS/CoreLoop.o \ 2.8 + SSR_lib/VMS/VMS.o \ 2.9 + SSR_lib/VMS/MasterLoop.o \ 2.10 + SSR_lib/VMS/Queue_impl/PrivateQueue.o \ 2.11 + SSR_lib/VMS/Hash_impl/PrivateHash.o \ 2.12 + SSR_lib/VMS/DynArray/DynArray.o \ 2.13 + SSR_lib/SSR_PluginFns.o \ 2.14 + SSR_lib/SSR_lib.o \ 2.15 + SSR_lib/VMS/Histogram/DblHist.o \ 2.16 + SSR_lib/SSR.o \ 2.17 + SSR_lib/VMS/probes.o \ 2.18 + SSR_lib/VMS/ProcrContext.o \ 2.19 + SSR_lib/SSR_Request_Handlers.o \ 2.20 + SSR_lib/VMS/Hash_impl/MurmurHash2.o \ 2.21 + SSR_lib/VMS/vmalloc.o \ 2.22 + SSR_lib/VMS/contextSwitch.o \ 2.23 + SSR_lib/VMS/Queue_impl/BlockingQueue.o \ 2.24 + SSR_lib/VMS/vutilities.o \ 2.25 + c-ray-mt.o 2.26 + 2.27 +bin = c-ray-mt 2.28 + 2.29 +CC = gcc 2.30 +CFLAGS = -m64 -ffast-math -fwrapv -fno-omit-frame-pointer -O3 -D SSR -D APPLICATION=C-RAY -g -Wall 2.31 + 2.32 +$(bin): $(obj) 2.33 + $(CC) -o $@ $(obj) -lm -lpthread 2.34 + 2.35 +%.o : %.c 2.36 + $(CC) -c $(CFLAGS) -o $@ $< 2.37 + 2.38 +.PHONY: clean 2.39 +clean: 2.40 + rm -f $(obj) $(bin) 2.41 + 2.42 +.PHONY: install 2.43 +install: 2.44 + cp $(bin) /usr/local/bin/$(bin) 2.45 + 2.46 +.PHONY: uninstall 2.47 +uninstall: 2.48 + rm -f /usr/local/bin/$(bin) 2.49 + 2.50 + 2.51 +# $@ Name des Targets
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/README.txt Thu Sep 22 14:16:25 2011 +0200 3.3 @@ -0,0 +1,27 @@ 3.4 +Kernel: Ray Tracing 3.5 + 3.6 +This is a kernel-type benchmark of a very simple and brute-force ray tracer. 3.7 + 3.8 +Installation: 3.9 + 3.10 +To install the kernel benchmark, navigate to the directory this file is located in, open up a terminal and simply type 'make'. For certain architectures 3.11 +or special compilation options, you might need to change compilation parameters in the makefile. 3.12 + 3.13 +Usage: 3.14 + 3.15 +You may execute the benchmark by navigating to this directory after compilation and typing 3.16 + 3.17 +./c-ray-mt -i FILENAME -s RESOLUTION -o OUTPUT.ppm 3.18 + 3.19 +'FILENAME' has to be either "scene" or "sphfract" or another predefined scene description file if there is one. 3.20 +'RESOLUTION' specifies the resolution of the produced image and has to be given in the form 1920x1200, for example. 3.21 +'OUTPUT' is the name of the file the rendered image will be contained in after the benchmark ran. 3.22 + 3.23 +The specification of how many threads are used to perform the rendering depends on the parallel programming model. 3.24 + 3.25 +Benchmark Versions: 3.26 + 3.27 +Serial 3.28 +POSIX Threads 3.29 +OpenMP SuperScalar 3.30 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/c-ray-mt.c Thu Sep 22 14:16:25 2011 +0200 4.3 @@ -0,0 +1,704 @@ 4.4 +/* c-ray-mt - a simple multithreaded raytracing filter. 4.5 + * Copyright (C) 2006 John Tsiombikas <nuclear@siggraph.org> 4.6 + * 4.7 + * You are free to use, modify and redistribute this program under the 4.8 + * terms of the GNU General Public License v2 or (at your option) later. 4.9 + * see "http://www.gnu.org/licenses/gpl.txt" for details. 4.10 + * --------------------------------------------------------------------- 4.11 + * Usage: 4.12 + * compile: just type make 4.13 + * (add any arch-specific optimizations for your compiler in CFLAGS first) 4.14 + * run: cat scene | ./c-ray-mt [-t num-threads] >foo.ppm 4.15 + * (on broken systems such as windows try: c-ray-mt -i scene -o foo.ppm) 4.16 + * enjoy: display foo.ppm 4.17 + * (with imagemagick, or use your favorite image viewer) 4.18 + * --------------------------------------------------------------------- 4.19 + * Scene file format: 4.20 + * # sphere (many) 4.21 + * s x y z rad r g b shininess reflectivity 4.22 + * # light (many) 4.23 + * l x y z 4.24 + * # camera (one) 4.25 + * c x y z fov tx ty tz 4.26 + * --------------------------------------------------------------------- 4.27 + */ 4.28 +#include <stdio.h> 4.29 +#include <stdlib.h> 4.30 +#include <string.h> 4.31 +#include <math.h> 4.32 +#include <ctype.h> 4.33 +#include <errno.h> 4.34 +#include <pthread.h> 4.35 +#include "SSR_lib/SSR.h" 4.36 + 4.37 +#define VER_MAJOR 1 4.38 +#define VER_MINOR 1 4.39 +#define VER_STR "c-ray-mt v%d.%d\n" 4.40 + 4.41 +#if !defined(unix) && !defined(__unix__) 4.42 +#ifdef __MACH__ 4.43 +#define unix 1 4.44 +#define __unix__ 1 4.45 +#endif /* __MACH__ */ 4.46 +#endif /* unix */ 4.47 + 4.48 +/* find the appropriate way to define explicitly sized types */ 4.49 +/* for C99 or GNU libc (also mach's libc) we can use stdint.h */ 4.50 +#if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) || defined(__MACH__) 4.51 +#include <stdint.h> 4.52 +#elif defined(unix) || defined(__unix__) /* some UNIX systems have them in sys/types.h */ 4.53 +#include <sys/types.h> 4.54 +#elif defined(__WIN32__) || defined(WIN32) /* the nameless one */ 4.55 +typedef unsigned __int8 uint8_t; 4.56 +typedef unsigned __int32 uint32_t; 4.57 +#endif /* sized type detection */ 4.58 + 4.59 +struct vec3 { 4.60 + double x, y, z; 4.61 +}; 4.62 + 4.63 +struct ray { 4.64 + struct vec3 orig, dir; 4.65 +}; 4.66 + 4.67 +struct material { 4.68 + struct vec3 col; /* color */ 4.69 + double spow; /* specular power */ 4.70 + double refl; /* reflection intensity */ 4.71 +}; 4.72 + 4.73 +struct sphere { 4.74 + struct vec3 pos; 4.75 + double rad; 4.76 + struct material mat; 4.77 + struct sphere *next; 4.78 +}; 4.79 + 4.80 +struct spoint { 4.81 + struct vec3 pos, normal, vref; /* position, normal and view reflection */ 4.82 + double dist; /* parametric distance of intersection along the ray */ 4.83 +}; 4.84 + 4.85 +struct camera { 4.86 + struct vec3 pos, targ; 4.87 + double fov; 4.88 +}; 4.89 + 4.90 +struct procr_data { 4.91 + VirtProcr *VP; 4.92 + VirtProcr *parentVP; 4.93 + int sl_start, sl_count; 4.94 + uint32_t *pixels; 4.95 +}; 4.96 +typedef struct procr_data procr_data; 4.97 + 4.98 +void render_scanline(int xsz, int ysz, int sl, uint32_t *fb, int samples); 4.99 +struct vec3 trace(struct ray ray, int depth); 4.100 +struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth); 4.101 +struct vec3 reflect(struct vec3 v, struct vec3 n); 4.102 +struct vec3 cross_product(struct vec3 v1, struct vec3 v2); 4.103 +struct ray get_primary_ray(int x, int y, int sample); 4.104 +struct vec3 get_sample_pos(int x, int y, int sample); 4.105 +struct vec3 jitter(int x, int y, int s); 4.106 +int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp); 4.107 +void load_scene(FILE *fp); 4.108 +unsigned long get_msec(void); 4.109 + 4.110 +void thread_func(void *tdata, VirtProcr *VProc); 4.111 + 4.112 +#define MAX_LIGHTS 16 /* maximum number of lights */ 4.113 +#define RAY_MAG 1000.0 /* trace rays of this magnitude */ 4.114 +#define MAX_RAY_DEPTH 5 /* raytrace recursion limit */ 4.115 +#define FOV 0.78539816 /* field of view in rads (pi/4) */ 4.116 +#define HALF_FOV (FOV * 0.5) 4.117 +#define ERR_MARGIN 1e-6 /* an arbitrary error margin to avoid surface acne */ 4.118 + 4.119 +/* bit-shift ammount for packing each color into a 32bit uint */ 4.120 +#ifdef LITTLE_ENDIAN 4.121 +#define RSHIFT 16 4.122 +#define BSHIFT 0 4.123 +#else /* big endian */ 4.124 +#define RSHIFT 0 4.125 +#define BSHIFT 16 4.126 +#endif /* endianess */ 4.127 +#define GSHIFT 8 /* this is the same in both byte orders */ 4.128 + 4.129 +/* some helpful macros... */ 4.130 +#define SQ(x) ((x) * (x)) 4.131 +#define MAX(a, b) ((a) > (b) ? (a) : (b)) 4.132 +#define MIN(a, b) ((a) < (b) ? (a) : (b)) 4.133 +#define DOT(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) 4.134 +#define NORMALIZE(a) do {\ 4.135 + double len = sqrt(DOT(a, a));\ 4.136 + (a).x /= len; (a).y /= len; (a).z /= len;\ 4.137 +} while(0); 4.138 + 4.139 +//SSR Message Types 4.140 +#define WORK_START 1 4.141 +#define WORK_END 2 4.142 + 4.143 +/* global state */ 4.144 +int xres = 800; 4.145 +int yres = 600; 4.146 +int rays_per_pixel = 1; 4.147 +double aspect = 1.333333; 4.148 +struct sphere *obj_list; 4.149 +struct vec3 lights[MAX_LIGHTS]; 4.150 +int lnum = 0; 4.151 +struct camera cam; 4.152 + 4.153 +int thread_num = 1; 4.154 +struct procr_data *procrs; 4.155 + 4.156 +volatile int end = 0; 4.157 +volatile int start = 0; 4.158 +int32 end_mutex, end_cond; 4.159 +int32 start_cond, start_mutex; 4.160 + 4.161 +#define NRAN 1024 4.162 +#define MASK (NRAN - 1) 4.163 +struct vec3 urand[NRAN]; 4.164 +int irand[NRAN]; 4.165 + 4.166 +unsigned long rend_time, start_time; 4.167 + 4.168 +const char *usage = { 4.169 + "Usage: c-ray-mt [options]\n" 4.170 + " Reads a scene file from stdin, writes the image to stdout, and stats to stderr.\n\n" 4.171 + "Options:\n" 4.172 + " -t <num> how many threads to use (default: 1)\n" 4.173 + " -s WxH where W is the width and H the height of the image\n" 4.174 + " -r <rays> shoot <rays> rays per pixel (antialiasing)\n" 4.175 + " -i <file> read from <file> instead of stdin\n" 4.176 + " -o <file> write to <file> instead of stdout\n" 4.177 + " -h this help screen\n\n" 4.178 +}; 4.179 + 4.180 +char __ProgrammName[] = "c-ray"; 4.181 +char __DataSet[255]; 4.182 + 4.183 + 4.184 +void raytrace(void *pixels, VirtProcr *Vprocr); 4.185 + 4.186 +int main(int argc, char **argv) { 4.187 + int i; 4.188 + uint32_t *pixels; 4.189 + FILE *infile = stdin, *outfile = stdout; 4.190 + 4.191 + for(i=1; i<argc; i++) { 4.192 + if(argv[i][0] == '-' && argv[i][2] == 0) { 4.193 + char *sep; 4.194 + switch(argv[i][1]) { 4.195 + case 't': 4.196 + if(!isdigit(argv[++i][0])) { 4.197 + fprintf(stderr, "-t mus be followed by the number of worker threads to spawn\n"); 4.198 + return EXIT_FAILURE; 4.199 + } 4.200 + thread_num = atoi(argv[i]); 4.201 + if(!thread_num) { 4.202 + fprintf(stderr, "invalid number of threads specified: %d\n", thread_num); 4.203 + return EXIT_FAILURE; 4.204 + } 4.205 + break; 4.206 + 4.207 + case 's': 4.208 + if(!isdigit(argv[++i][0]) || !(sep = strchr(argv[i], 'x')) || !isdigit(*(sep + 1))) { 4.209 + fputs("-s must be followed by something like \"640x480\"\n", stderr); 4.210 + return EXIT_FAILURE; 4.211 + } 4.212 + xres = atoi(argv[i]); 4.213 + yres = atoi(sep + 1); 4.214 + aspect = (double)xres / (double)yres; 4.215 + break; 4.216 + 4.217 + case 'i': 4.218 + if(!(infile = fopen(argv[++i], "rb"))) { 4.219 + fprintf(stderr, "failed to open input file %s: %s\n", argv[i], strerror(errno)); 4.220 + return EXIT_FAILURE; 4.221 + } 4.222 + break; 4.223 + 4.224 + case 'o': 4.225 + if(!(outfile = fopen(argv[++i], "wb"))) { 4.226 + fprintf(stderr, "failed to open output file %s: %s\n", argv[i], strerror(errno)); 4.227 + return EXIT_FAILURE; 4.228 + } 4.229 + break; 4.230 + 4.231 + case 'r': 4.232 + if(!isdigit(argv[++i][0])) { 4.233 + fputs("-r must be followed by a number (rays per pixel)\n", stderr); 4.234 + return EXIT_FAILURE; 4.235 + } 4.236 + rays_per_pixel = atoi(argv[i]); 4.237 + break; 4.238 + 4.239 + case 'h': 4.240 + fputs(usage, stdout); 4.241 + return 0; 4.242 + 4.243 + default: 4.244 + fprintf(stderr, "unrecognized argument: %s\n", argv[i]); 4.245 + fputs(usage, stderr); 4.246 + return EXIT_FAILURE; 4.247 + } 4.248 + } else { 4.249 + fprintf(stderr, "unrecognized argument: %s\n", argv[i]); 4.250 + fputs(usage, stderr); 4.251 + return EXIT_FAILURE; 4.252 + } 4.253 + } 4.254 + 4.255 + 4.256 + if(!(pixels = malloc(xres * yres * sizeof *pixels))) { 4.257 + perror("pixel buffer allocation failed"); 4.258 + return EXIT_FAILURE; 4.259 + } 4.260 + load_scene(infile); 4.261 + 4.262 + //This is the transition to the VMS runtime 4.263 + SSR__create_seed_procr_and_do_work(raytrace, (void*)pixels); 4.264 + 4.265 + /* output statistics to stderr */ 4.266 + fprintf(stderr, "Rendering took: %lu seconds (%lu milliseconds)\n", rend_time / 1000, rend_time); 4.267 + 4.268 + /* output the image */ 4.269 + fprintf(outfile, "P6\n%d %d\n255\n", xres, yres); 4.270 + for(i=0; i<xres * yres; i++) { 4.271 + fputc((pixels[i] >> RSHIFT) & 0xff, outfile); 4.272 + fputc((pixels[i] >> GSHIFT) & 0xff, outfile); 4.273 + fputc((pixels[i] >> BSHIFT) & 0xff, outfile); 4.274 + } 4.275 + fflush(outfile); 4.276 + 4.277 + if(infile != stdin) fclose(infile); 4.278 + if(outfile != stdout) fclose(outfile); 4.279 + 4.280 + struct sphere *walker = obj_list; 4.281 + while(walker) { 4.282 + struct sphere *tmp = walker; 4.283 + walker = walker->next; 4.284 + free(tmp); 4.285 + } 4.286 + free(pixels); 4.287 + return 0; 4.288 +} 4.289 + 4.290 +/* this is run after the VMS is set up*/ 4.291 +void raytrace(void *pixels, VirtProcr *VProc) 4.292 +{ 4.293 + int i; 4.294 + double sl, sl_per_procr; 4.295 + 4.296 + /* initialize the random number tables for the jitter */ 4.297 + for(i=0; i<NRAN; i++) urand[i].x = (double)rand() / RAND_MAX - 0.5; 4.298 + for(i=0; i<NRAN; i++) urand[i].y = (double)rand() / RAND_MAX - 0.5; 4.299 + for(i=0; i<NRAN; i++) irand[i] = (int)(NRAN * ((double)rand() / RAND_MAX)); 4.300 + 4.301 + if(thread_num > yres) { 4.302 + fprintf(stderr, "more threads than scanlines specified, reducing number of threads to %d\n", yres); 4.303 + thread_num = yres; 4.304 + } 4.305 + 4.306 + 4.307 + if(!(procrs = SSR__malloc_to(thread_num * sizeof(procr_data), VProc))) { 4.308 + perror("failed to allocate thread table"); 4.309 + exit(EXIT_FAILURE); 4.310 + } 4.311 + 4.312 + sl = 0.0; 4.313 + sl_per_procr = (double)yres / (double)thread_num; 4.314 + for(i=0; i<thread_num; i++) { 4.315 + procrs[i].sl_start = (int)sl; 4.316 + sl += sl_per_procr; 4.317 + procrs[i].sl_count = (int)sl - procrs[i].sl_start; 4.318 + procrs[i].pixels = (uint32_t*)pixels; 4.319 + procrs[i].parentVP = VProc; 4.320 + 4.321 + procrs[i].VP = SSR__create_procr_with((VirtProcrFnPtr)thread_func, 4.322 + (void*)(&procrs[i]), VProc); 4.323 + } 4.324 + 4.325 + procrs[thread_num - 1].sl_count = yres - procrs[thread_num - 1].sl_start; 4.326 + 4.327 + fprintf(stderr, VER_STR, VER_MAJOR, VER_MINOR); 4.328 + 4.329 + // start worker threads 4.330 + //printf("start of worker thread (%d)\n", VProc->procrID); 4.331 + start_time = get_msec(); 4.332 + for(i=0; i<thread_num; i++) 4.333 + SSR__send_of_type_to(VProc, NULL, WORK_START, procrs[i].VP); 4.334 + 4.335 + //printf("wait for worker (%d)\n", VProc->procrID); 4.336 + for(i=0; i<thread_num; i++) 4.337 + SSR__receive_type_to(WORK_END, VProc); 4.338 + 4.339 + rend_time = get_msec() - start_time; 4.340 + 4.341 + SSR__free(procrs,VProc); 4.342 + SSR__dissipate_procr(VProc); 4.343 +} 4.344 + 4.345 +/* render a frame of xsz/ysz dimensions into the provided framebuffer */ 4.346 +void render_scanline(int xsz, int ysz, int sl, uint32_t *fb, int samples) { 4.347 + int i, s; 4.348 + double rcp_samples = 1.0 / (double)samples; 4.349 + 4.350 + for(i=0; i<xsz; i++) { 4.351 + double r, g, b; 4.352 + r = g = b = 0.0; 4.353 + 4.354 + for(s=0; s<samples; s++) { 4.355 + struct vec3 col = trace(get_primary_ray(i, sl, s), 0); 4.356 + r += col.x; 4.357 + g += col.y; 4.358 + b += col.z; 4.359 + } 4.360 + 4.361 + r = r * rcp_samples; 4.362 + g = g * rcp_samples; 4.363 + b = b * rcp_samples; 4.364 + 4.365 + fb[sl * xsz + i] = ((uint32_t)(MIN(r, 1.0) * 255.0) & 0xff) << RSHIFT | 4.366 + ((uint32_t)(MIN(g, 1.0) * 255.0) & 0xff) << GSHIFT | 4.367 + ((uint32_t)(MIN(b, 1.0) * 255.0) & 0xff) << BSHIFT; 4.368 + } 4.369 +} 4.370 + 4.371 +/* trace a ray throught the scene recursively (the recursion happens through 4.372 + * shade() to calculate reflection rays if necessary). 4.373 + */ 4.374 +struct vec3 trace(struct ray ray, int depth) { 4.375 + struct vec3 col; 4.376 + struct spoint sp, nearest_sp; 4.377 + struct sphere *nearest_obj = 0; 4.378 + struct sphere *iter = obj_list->next; 4.379 + 4.380 + /* if we reached the recursion limit, bail out */ 4.381 + if(depth >= MAX_RAY_DEPTH) { 4.382 + col.x = col.y = col.z = 0.0; 4.383 + return col; 4.384 + } 4.385 + 4.386 + /* find the nearest intersection ... */ 4.387 + while(iter) { 4.388 + if(ray_sphere(iter, ray, &sp)) { 4.389 + if(!nearest_obj || sp.dist < nearest_sp.dist) { 4.390 + nearest_obj = iter; 4.391 + nearest_sp = sp; 4.392 + } 4.393 + } 4.394 + iter = iter->next; 4.395 + } 4.396 + 4.397 + /* and perform shading calculations as needed by calling shade() */ 4.398 + if(nearest_obj) { 4.399 + col = shade(nearest_obj, &nearest_sp, depth); 4.400 + } else { 4.401 + col.x = col.y = col.z = 0.0; 4.402 + } 4.403 + 4.404 + return col; 4.405 +} 4.406 + 4.407 +/* Calculates direct illumination with the phong reflectance model. 4.408 + * Also handles reflections by calling trace again, if necessary. 4.409 + */ 4.410 +struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth) { 4.411 + int i; 4.412 + struct vec3 col = {0, 0, 0}; 4.413 + 4.414 + /* for all lights ... */ 4.415 + for(i=0; i<lnum; i++) { 4.416 + double ispec, idiff; 4.417 + struct vec3 ldir; 4.418 + struct ray shadow_ray; 4.419 + struct sphere *iter = obj_list->next; 4.420 + int in_shadow = 0; 4.421 + 4.422 + ldir.x = lights[i].x - sp->pos.x; 4.423 + ldir.y = lights[i].y - sp->pos.y; 4.424 + ldir.z = lights[i].z - sp->pos.z; 4.425 + 4.426 + shadow_ray.orig = sp->pos; 4.427 + shadow_ray.dir = ldir; 4.428 + 4.429 + /* shoot shadow rays to determine if we have a line of sight with the light */ 4.430 + while(iter) { 4.431 + if(ray_sphere(iter, shadow_ray, 0)) { 4.432 + in_shadow = 1; 4.433 + break; 4.434 + } 4.435 + iter = iter->next; 4.436 + } 4.437 + 4.438 + /* and if we're not in shadow, calculate direct illumination with the phong model. */ 4.439 + if(!in_shadow) { 4.440 + NORMALIZE(ldir); 4.441 + 4.442 + idiff = MAX(DOT(sp->normal, ldir), 0.0); 4.443 + ispec = obj->mat.spow > 0.0 ? pow(MAX(DOT(sp->vref, ldir), 0.0), obj->mat.spow) : 0.0; 4.444 + 4.445 + col.x += idiff * obj->mat.col.x + ispec; 4.446 + col.y += idiff * obj->mat.col.y + ispec; 4.447 + col.z += idiff * obj->mat.col.z + ispec; 4.448 + } 4.449 + } 4.450 + 4.451 + /* Also, if the object is reflective, spawn a reflection ray, and call trace() 4.452 + * to calculate the light arriving from the mirror direction. 4.453 + */ 4.454 + if(obj->mat.refl > 0.0) { 4.455 + struct ray ray; 4.456 + struct vec3 rcol; 4.457 + 4.458 + ray.orig = sp->pos; 4.459 + ray.dir = sp->vref; 4.460 + ray.dir.x *= RAY_MAG; 4.461 + ray.dir.y *= RAY_MAG; 4.462 + ray.dir.z *= RAY_MAG; 4.463 + 4.464 + rcol = trace(ray, depth + 1); 4.465 + col.x += rcol.x * obj->mat.refl; 4.466 + col.y += rcol.y * obj->mat.refl; 4.467 + col.z += rcol.z * obj->mat.refl; 4.468 + } 4.469 + 4.470 + return col; 4.471 +} 4.472 + 4.473 +/* calculate reflection vector */ 4.474 +struct vec3 reflect(struct vec3 v, struct vec3 n) { 4.475 + struct vec3 res; 4.476 + double dot = v.x * n.x + v.y * n.y + v.z * n.z; 4.477 + res.x = -(2.0 * dot * n.x - v.x); 4.478 + res.y = -(2.0 * dot * n.y - v.y); 4.479 + res.z = -(2.0 * dot * n.z - v.z); 4.480 + return res; 4.481 +} 4.482 + 4.483 +struct vec3 cross_product(struct vec3 v1, struct vec3 v2) { 4.484 + struct vec3 res; 4.485 + res.x = v1.y * v2.z - v1.z * v2.y; 4.486 + res.y = v1.z * v2.x - v1.x * v2.z; 4.487 + res.z = v1.x * v2.y - v1.y * v2.x; 4.488 + return res; 4.489 +} 4.490 + 4.491 +/* determine the primary ray corresponding to the specified pixel (x, y) */ 4.492 +struct ray get_primary_ray(int x, int y, int sample) { 4.493 + struct ray ray; 4.494 + float m[3][3]; 4.495 + struct vec3 i, j = {0, 1, 0}, k, dir, orig, foo; 4.496 + 4.497 + k.x = cam.targ.x - cam.pos.x; 4.498 + k.y = cam.targ.y - cam.pos.y; 4.499 + k.z = cam.targ.z - cam.pos.z; 4.500 + NORMALIZE(k); 4.501 + 4.502 + i = cross_product(j, k); 4.503 + j = cross_product(k, i); 4.504 + m[0][0] = i.x; m[0][1] = j.x; m[0][2] = k.x; 4.505 + m[1][0] = i.y; m[1][1] = j.y; m[1][2] = k.y; 4.506 + m[2][0] = i.z; m[2][1] = j.z; m[2][2] = k.z; 4.507 + 4.508 + ray.orig.x = ray.orig.y = ray.orig.z = 0.0; 4.509 + ray.dir = get_sample_pos(x, y, sample); 4.510 + ray.dir.z = 1.0 / HALF_FOV; 4.511 + ray.dir.x *= RAY_MAG; 4.512 + ray.dir.y *= RAY_MAG; 4.513 + ray.dir.z *= RAY_MAG; 4.514 + 4.515 + dir.x = ray.dir.x + ray.orig.x; 4.516 + dir.y = ray.dir.y + ray.orig.y; 4.517 + dir.z = ray.dir.z + ray.orig.z; 4.518 + foo.x = dir.x * m[0][0] + dir.y * m[0][1] + dir.z * m[0][2]; 4.519 + foo.y = dir.x * m[1][0] + dir.y * m[1][1] + dir.z * m[1][2]; 4.520 + foo.z = dir.x * m[2][0] + dir.y * m[2][1] + dir.z * m[2][2]; 4.521 + 4.522 + orig.x = ray.orig.x * m[0][0] + ray.orig.y * m[0][1] + ray.orig.z * m[0][2] + cam.pos.x; 4.523 + orig.y = ray.orig.x * m[1][0] + ray.orig.y * m[1][1] + ray.orig.z * m[1][2] + cam.pos.y; 4.524 + orig.z = ray.orig.x * m[2][0] + ray.orig.y * m[2][1] + ray.orig.z * m[2][2] + cam.pos.z; 4.525 + 4.526 + ray.orig = orig; 4.527 + ray.dir.x = foo.x + orig.x; 4.528 + ray.dir.y = foo.y + orig.y; 4.529 + ray.dir.z = foo.z + orig.z; 4.530 + 4.531 + return ray; 4.532 +} 4.533 + 4.534 + 4.535 +struct vec3 get_sample_pos(int x, int y, int sample) { 4.536 + struct vec3 pt; 4.537 + static double sf = 0.0; 4.538 + 4.539 + if(sf == 0.0) { 4.540 + sf = 1.5 / (double)xres; 4.541 + } 4.542 + 4.543 + pt.x = ((double)x / (double)xres) - 0.5; 4.544 + pt.y = -(((double)y / (double)yres) - 0.65) / aspect; 4.545 + 4.546 + if(sample) { 4.547 + struct vec3 jt = jitter(x, y, sample); 4.548 + pt.x += jt.x * sf; 4.549 + pt.y += jt.y * sf / aspect; 4.550 + } 4.551 + return pt; 4.552 +} 4.553 + 4.554 +/* jitter function taken from Graphics Gems I. */ 4.555 +struct vec3 jitter(int x, int y, int s) { 4.556 + struct vec3 pt; 4.557 + pt.x = urand[(x + (y << 2) + irand[(x + s) & MASK]) & MASK].x; 4.558 + pt.y = urand[(y + (x << 2) + irand[(y + s) & MASK]) & MASK].y; 4.559 + return pt; 4.560 +} 4.561 + 4.562 +/* Calculate ray-sphere intersection, and return {1, 0} to signify hit or no hit. 4.563 + * Also the surface point parameters like position, normal, etc are returned through 4.564 + * the sp pointer if it is not NULL. 4.565 + */ 4.566 +int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp) { 4.567 + double a, b, c, d, sqrt_d, t1, t2; 4.568 + 4.569 + a = SQ(ray.dir.x) + SQ(ray.dir.y) + SQ(ray.dir.z); 4.570 + b = 2.0 * ray.dir.x * (ray.orig.x - sph->pos.x) + 4.571 + 2.0 * ray.dir.y * (ray.orig.y - sph->pos.y) + 4.572 + 2.0 * ray.dir.z * (ray.orig.z - sph->pos.z); 4.573 + c = SQ(sph->pos.x) + SQ(sph->pos.y) + SQ(sph->pos.z) + 4.574 + SQ(ray.orig.x) + SQ(ray.orig.y) + SQ(ray.orig.z) + 4.575 + 2.0 * (-sph->pos.x * ray.orig.x - sph->pos.y * ray.orig.y - sph->pos.z * ray.orig.z) - SQ(sph->rad); 4.576 + 4.577 + if((d = SQ(b) - 4.0 * a * c) < 0.0) return 0; 4.578 + 4.579 + sqrt_d = sqrt(d); 4.580 + t1 = (-b + sqrt_d) / (2.0 * a); 4.581 + t2 = (-b - sqrt_d) / (2.0 * a); 4.582 + 4.583 + if((t1 < ERR_MARGIN && t2 < ERR_MARGIN) || (t1 > 1.0 && t2 > 1.0)) return 0; 4.584 + 4.585 + if(sp) { 4.586 + if(t1 < ERR_MARGIN) t1 = t2; 4.587 + if(t2 < ERR_MARGIN) t2 = t1; 4.588 + sp->dist = t1 < t2 ? t1 : t2; 4.589 + 4.590 + sp->pos.x = ray.orig.x + ray.dir.x * sp->dist; 4.591 + sp->pos.y = ray.orig.y + ray.dir.y * sp->dist; 4.592 + sp->pos.z = ray.orig.z + ray.dir.z * sp->dist; 4.593 + 4.594 + sp->normal.x = (sp->pos.x - sph->pos.x) / sph->rad; 4.595 + sp->normal.y = (sp->pos.y - sph->pos.y) / sph->rad; 4.596 + sp->normal.z = (sp->pos.z - sph->pos.z) / sph->rad; 4.597 + 4.598 + sp->vref = reflect(ray.dir, sp->normal); 4.599 + NORMALIZE(sp->vref); 4.600 + } 4.601 + return 1; 4.602 +} 4.603 + 4.604 +/* Load the scene from an extremely simple scene description file */ 4.605 +#define DELIM " \t\n" 4.606 +void load_scene(FILE *fp) { 4.607 + char line[256], *ptr, type; 4.608 + 4.609 + obj_list = malloc(sizeof(struct sphere)); 4.610 + obj_list->next = 0; 4.611 + 4.612 + while((ptr = fgets(line, 256, fp))) { 4.613 + int i; 4.614 + struct vec3 pos, col; 4.615 + double rad, spow, refl; 4.616 + 4.617 + while(*ptr == ' ' || *ptr == '\t') ptr++; 4.618 + if(*ptr == '#' || *ptr == '\n') continue; 4.619 + 4.620 + if(!(ptr = strtok(line, DELIM))) continue; 4.621 + type = *ptr; 4.622 + 4.623 + for(i=0; i<3; i++) { 4.624 + if(!(ptr = strtok(0, DELIM))) break; 4.625 + *((double*)&pos.x + i) = atof(ptr); 4.626 + } 4.627 + 4.628 + if(type == 'l') { 4.629 + lights[lnum++] = pos; 4.630 + continue; 4.631 + } 4.632 + 4.633 + if(!(ptr = strtok(0, DELIM))) continue; 4.634 + rad = atof(ptr); 4.635 + 4.636 + for(i=0; i<3; i++) { 4.637 + if(!(ptr = strtok(0, DELIM))) break; 4.638 + *((double*)&col.x + i) = atof(ptr); 4.639 + } 4.640 + 4.641 + if(type == 'c') { 4.642 + cam.pos = pos; 4.643 + cam.targ = col; 4.644 + cam.fov = rad; 4.645 + continue; 4.646 + } 4.647 + 4.648 + if(!(ptr = strtok(0, DELIM))) continue; 4.649 + spow = atof(ptr); 4.650 + 4.651 + if(!(ptr = strtok(0, DELIM))) continue; 4.652 + refl = atof(ptr); 4.653 + 4.654 + if(type == 's') { 4.655 + struct sphere *sph = malloc(sizeof *sph); 4.656 + sph->next = obj_list->next; 4.657 + obj_list->next = sph; 4.658 + 4.659 + sph->pos = pos; 4.660 + sph->rad = rad; 4.661 + sph->mat.col = col; 4.662 + sph->mat.spow = spow; 4.663 + sph->mat.refl = refl; 4.664 + } else { 4.665 + fprintf(stderr, "unknown type: %c\n", type); 4.666 + } 4.667 + } 4.668 +} 4.669 + 4.670 + 4.671 +/* provide a millisecond-resolution timer for each system */ 4.672 +#if defined(unix) || defined(__unix__) 4.673 +#include <time.h> 4.674 +#include <sys/time.h> 4.675 +unsigned long get_msec(void) { 4.676 + static struct timeval timeval, first_timeval; 4.677 + 4.678 + gettimeofday(&timeval, 0); 4.679 + if(first_timeval.tv_sec == 0) { 4.680 + first_timeval = timeval; 4.681 + return 0; 4.682 + } 4.683 + return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000; 4.684 +} 4.685 +#elif defined(__WIN32__) || defined(WIN32) 4.686 +#include <windows.h> 4.687 +unsigned long get_msec(void) { 4.688 + return GetTickCount(); 4.689 +} 4.690 +#else 4.691 +#error "I don't know how to measure time on your platform" 4.692 +#endif 4.693 + 4.694 +void thread_func(void *tdata, VirtProcr *VProc) { 4.695 + int i; 4.696 + procr_data *td = (procr_data*)tdata; 4.697 + 4.698 + SSR__receive_type_to(WORK_START, VProc); 4.699 + 4.700 + for(i=0; i<td->sl_count; i++) { 4.701 + render_scanline(xres, yres, i + td->sl_start, td->pixels, rays_per_pixel); 4.702 + } 4.703 + 4.704 + SSR__send_of_type_to(VProc, NULL, WORK_END, td->parentVP); 4.705 + 4.706 + SSR__dissipate_procr(VProc); 4.707 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/scene Thu Sep 22 14:16:25 2011 +0200 5.3 @@ -0,0 +1,18 @@ 5.4 +# spheres 5.5 +# position radius color shininess reflectivity 5.6 +s -1.5 -0.3 -1 0.7 1.0 0.2 0.05 50.0 0.3 5.7 +s 1.5 -0.4 0 0.6 0.1 0.85 1.0 50.0 0.4 5.8 + 5.9 +# walls 5.10 +s 0 -1000 2 999 0.1 0.2 0.6 80.0 0.5 5.11 + 5.12 +# bouncing ball 5.13 +s 0 0 2 1 0.0 0.0 0.0 60.0 0.7 5.14 + 5.15 +# lights... 5.16 +l -50 100 -50 5.17 +l 40 40 150 5.18 + 5.19 +# camera (there can be only one!) 5.20 +# position FOV target 5.21 +c 0 6 -17 45 0 -1 0
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/sphfract Thu Sep 22 14:16:25 2011 +0200 6.3 @@ -0,0 +1,192 @@ 6.4 +s 0 0 0 1.0 0.25 0.25 0.25 50.0 0.65 6.5 +s 1.4 0 0 0.4 0.25 0.25 0.25 50.0 0.65 6.6 +s 1.96 0 0 0.16 0.25 0.25 0.25 50.0 0.65 6.7 +s 2.184 0 0 0.064 0.25 0.25 0.25 50.0 0.65 6.8 +s 1.96 0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 6.9 +s 1.96 -0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 6.10 +s 1.96 0 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.11 +s 1.96 0 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.12 +s 1.4 0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 6.13 +s 1.624 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.14 +s 1.176 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.15 +s 1.4 0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 6.16 +s 1.4 0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.17 +s 1.4 0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.18 +s 1.4 -0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 6.19 +s 1.624 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.20 +s 1.176 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.21 +s 1.4 -0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 6.22 +s 1.4 -0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.23 +s 1.4 -0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.24 +s 1.4 0 0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.25 +s 1.624 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.26 +s 1.176 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.27 +s 1.4 0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.28 +s 1.4 -0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.29 +s 1.4 0 0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.30 +s 1.4 0 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.31 +s 1.624 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.32 +s 1.176 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.33 +s 1.4 0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.34 +s 1.4 -0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.35 +s 1.4 0 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.36 +s -1.4 0 0 0.4 0.25 0.25 0.25 50.0 0.65 6.37 +s -1.96 0 0 0.16 0.25 0.25 0.25 50.0 0.65 6.38 +s -2.184 0 0 0.064 0.25 0.25 0.25 50.0 0.65 6.39 +s -1.96 0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 6.40 +s -1.96 -0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 6.41 +s -1.96 0 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.42 +s -1.96 0 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.43 +s -1.4 0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 6.44 +s -1.176 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.45 +s -1.624 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.46 +s -1.4 0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 6.47 +s -1.4 0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.48 +s -1.4 0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.49 +s -1.4 -0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 6.50 +s -1.176 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.51 +s -1.624 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 6.52 +s -1.4 -0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 6.53 +s -1.4 -0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.54 +s -1.4 -0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.55 +s -1.4 0 0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.56 +s -1.176 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.57 +s -1.624 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.58 +s -1.4 0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.59 +s -1.4 -0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.60 +s -1.4 0 0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.61 +s -1.4 0 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.62 +s -1.176 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.63 +s -1.624 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.64 +s -1.4 0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.65 +s -1.4 -0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.66 +s -1.4 0 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.67 +s 0 1.4 0 0.4 0.25 0.25 0.25 50.0 0.65 6.68 +s 0.56 1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 6.69 +s 0.784 1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 6.70 +s 0.56 1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 6.71 +s 0.56 1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 6.72 +s 0.56 1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.73 +s 0.56 1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.74 +s -0.56 1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 6.75 +s -0.784 1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 6.76 +s -0.56 1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 6.77 +s -0.56 1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 6.78 +s -0.56 1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.79 +s -0.56 1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.80 +s 0 1.96 0 0.16 0.25 0.25 0.25 50.0 0.65 6.81 +s 0.224 1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 6.82 +s -0.224 1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 6.83 +s 0 2.184 0 0.064 0.25 0.25 0.25 50.0 0.65 6.84 +s 0 1.96 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.85 +s 0 1.96 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.86 +s 0 1.4 0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.87 +s 0.224 1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.88 +s -0.224 1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.89 +s 0 1.624 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.90 +s 0 1.176 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.91 +s 0 1.4 0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.92 +s 0 1.4 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.93 +s 0.224 1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.94 +s -0.224 1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.95 +s 0 1.624 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.96 +s 0 1.176 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.97 +s 0 1.4 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.98 +s 0 -1.4 0 0.4 0.25 0.25 0.25 50.0 0.65 6.99 +s 0.56 -1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 6.100 +s 0.784 -1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 6.101 +s 0.56 -1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 6.102 +s 0.56 -1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 6.103 +s 0.56 -1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.104 +s 0.56 -1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.105 +s -0.56 -1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 6.106 +s -0.784 -1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 6.107 +s -0.56 -1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 6.108 +s -0.56 -1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 6.109 +s -0.56 -1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.110 +s -0.56 -1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.111 +s 0 -1.96 0 0.16 0.25 0.25 0.25 50.0 0.65 6.112 +s 0.224 -1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 6.113 +s -0.224 -1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 6.114 +s 0 -2.184 0 0.064 0.25 0.25 0.25 50.0 0.65 6.115 +s 0 -1.96 0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.116 +s 0 -1.96 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 6.117 +s 0 -1.4 0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.118 +s 0.224 -1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.119 +s -0.224 -1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.120 +s 0 -1.176 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.121 +s 0 -1.624 0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.122 +s 0 -1.4 0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.123 +s 0 -1.4 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 6.124 +s 0.224 -1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.125 +s -0.224 -1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.126 +s 0 -1.176 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.127 +s 0 -1.624 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 6.128 +s 0 -1.4 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 6.129 +s 0 0 1.4 0.4 0.25 0.25 0.25 50.0 0.65 6.130 +s 0.56 0 1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.131 +s 0.784 0 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.132 +s 0.56 0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.133 +s 0.56 -0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.134 +s 0.56 0 1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.135 +s 0.56 0 1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.136 +s -0.56 0 1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.137 +s -0.784 0 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.138 +s -0.56 0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.139 +s -0.56 -0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.140 +s -0.56 0 1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.141 +s -0.56 0 1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.142 +s 0 0.56 1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.143 +s 0.224 0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.144 +s -0.224 0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.145 +s 0 0.784 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.146 +s 0 0.56 1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.147 +s 0 0.56 1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.148 +s 0 -0.56 1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.149 +s 0.224 -0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.150 +s -0.224 -0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.151 +s 0 -0.784 1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.152 +s 0 -0.56 1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.153 +s 0 -0.56 1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.154 +s 0 0 1.96 0.16 0.25 0.25 0.25 50.0 0.65 6.155 +s 0.224 0 1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.156 +s -0.224 0 1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.157 +s 0 0.224 1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.158 +s 0 -0.224 1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.159 +s 0 0 2.184 0.064 0.25 0.25 0.25 50.0 0.65 6.160 +s 0 0 -1.4 0.4 0.25 0.25 0.25 50.0 0.65 6.161 +s 0.56 0 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.162 +s 0.784 0 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.163 +s 0.56 0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.164 +s 0.56 -0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.165 +s 0.56 0 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.166 +s 0.56 0 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.167 +s -0.56 0 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.168 +s -0.784 0 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.169 +s -0.56 0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.170 +s -0.56 -0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.171 +s -0.56 0 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.172 +s -0.56 0 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.173 +s 0 0.56 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.174 +s 0.224 0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.175 +s -0.224 0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.176 +s 0 0.784 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.177 +s 0 0.56 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.178 +s 0 0.56 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.179 +s 0 -0.56 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 6.180 +s 0.224 -0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.181 +s -0.224 -0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.182 +s 0 -0.784 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 6.183 +s 0 -0.56 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 6.184 +s 0 -0.56 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 6.185 +s 0 0 -1.96 0.16 0.25 0.25 0.25 50.0 0.65 6.186 +s 0.224 0 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.187 +s -0.224 0 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.188 +s 0 0.224 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.189 +s 0 -0.224 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 6.190 +s 0 0 -2.184 0.064 0.25 0.25 0.25 50.0 0.65 6.191 +s 0 -10002.25 0 10000 0.2 0.35 0.5 80.0 0.4 6.192 +s 0 10100.00 0 10000 0.5 0.2 0.1 40.0 0.0 6.193 +l -50 68 -50 6.194 +l 40 40 150 6.195 +c -7 6 -12 45 0 -0.65 0
