Root/
| 1 | /* |
| 2 | * povray.c - Generate POV-Ray output |
| 3 | * |
| 4 | * Written 2010 by Werner Almesberger |
| 5 | * Copyright 2010 by Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include <stdint.h> |
| 15 | #include <stdlib.h> |
| 16 | #include <stdio.h> |
| 17 | #include <string.h> |
| 18 | #include <math.h> |
| 19 | |
| 20 | #include "face.h" |
| 21 | #include "solid.h" |
| 22 | |
| 23 | |
| 24 | static void height_field(const char *name, const struct face *f) |
| 25 | { |
| 26 | FILE *file; |
| 27 | int x, y; |
| 28 | int z; |
| 29 | uint16_t g; |
| 30 | uint8_t v[2]; |
| 31 | |
| 32 | file = fopen(name, "w"); |
| 33 | if (!file) { |
| 34 | perror(name); |
| 35 | exit(1); |
| 36 | } |
| 37 | if (fprintf(file, "P5\n%d %d\n65535\n", f->sx, f->sy) < 0) { |
| 38 | perror(name); |
| 39 | exit(1); |
| 40 | } |
| 41 | for (y = 0; y != f->sy; y++) |
| 42 | for (x = 0; x != f->sx; x++) { |
| 43 | z = get(f->a, x+f->a->min_x, y+f->a->min_y); |
| 44 | g = z == UNDEF ? 0 : |
| 45 | 65535*(z-f->a->min_z)/(f->a->max_z-f->a->min_z); |
| 46 | v[0] = g >> 8; |
| 47 | v[1] = g; |
| 48 | if (fwrite(v, 2, 1, file) != 1) { |
| 49 | perror(name); |
| 50 | exit(1); |
| 51 | } |
| 52 | } |
| 53 | if (fclose(file) < 0) { |
| 54 | perror(name); |
| 55 | exit(1); |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | |
| 60 | static void sanitize(const char *s, char *res) |
| 61 | { |
| 62 | while (*s) { |
| 63 | if ((*s >= 'A' && *s <= 'Z') || |
| 64 | (*s >= 'a' && *s <= 'z') || |
| 65 | (*s >= '0' && *s <= '9') || *s == '_') |
| 66 | *res = *s; |
| 67 | else |
| 68 | *res = '_'; |
| 69 | res++; |
| 70 | s++; |
| 71 | } |
| 72 | *res = 0; |
| 73 | } |
| 74 | |
| 75 | |
| 76 | /* |
| 77 | * For now, we put the part such that its x/y/z center is at the origin. |
| 78 | * Later, we will also have to consider the changes the user made and the |
| 79 | * relation with the opposing face. |
| 80 | */ |
| 81 | |
| 82 | static void povray_face(FILE *file, const struct face *f, const char *side, |
| 83 | const char *prefix, int flip, double dist) |
| 84 | { |
| 85 | double a; |
| 86 | |
| 87 | /* |
| 88 | * 1/65535 = 0.000015..., so we set the water level a bit lower, e.g., |
| 89 | * to 0.0001 |
| 90 | */ |
| 91 | a = asin(-f->m.a[0][1])/M_PI*180; |
| 92 | if (f->m.a[0][0] < 0) |
| 93 | a = 180-a; |
| 94 | fprintf(file, |
| 95 | "\theight_field {\n" |
| 96 | "\t pgm \"%s-%s.pgm\"\n" |
| 97 | "\t water_level 0.00001\n" |
| 98 | "\t smooth\n" |
| 99 | "\t scale <%g, %g, %g> /* scale from unit cube to real size */\n" |
| 100 | "\t rotate <90, 0, 0> /* swap Y/Z axis */\n" |
| 101 | "\t translate <%g, %g, 0> /* move to X/Y center */\n" |
| 102 | "\t rotate <%g, %g, 0> /* z0 plane tilt */\n" |
| 103 | "\t translate <0, 0, %g> /* min_z offset */\n" |
| 104 | "\t translate <0, 0, %g> /* z0 plane offset */\n" |
| 105 | "\t rotate <0, 0, %g> /* overlay - rotation */\n" |
| 106 | "\t translate <%g, %g, 0> /* overlay - shift */\n" |
| 107 | "%s" /* flip bottom face */ |
| 108 | "\t translate <0, 0, %g> /* half the distance between faces */\n" |
| 109 | "\t}\n", prefix, side, |
| 110 | f->sx*f->x_step, (f->sz-1)*f->z_step, f->sy*f->y_step, |
| 111 | -f->sx*f->x_step/2, f->sy*f->y_step/2, |
| 112 | -fy_to_angle(f), fx_to_angle(f), |
| 113 | f->a->min_z*f->z_step, |
| 114 | -f->z_ref*f->z_step, |
| 115 | a, |
| 116 | f->m.b[0]*f->x_step, f->m.b[1]*f->y_step, |
| 117 | flip ? "\t rotate <0, 180, 0>\t/* flip bottom face */\n" : "", |
| 118 | dist*f->z_step); |
| 119 | } |
| 120 | |
| 121 | |
| 122 | void povray(const char *file_name, const char *name, const struct solid *s) |
| 123 | { |
| 124 | FILE *file; |
| 125 | char tmp[1000]; /* @@@ enough */ |
| 126 | |
| 127 | file = strcmp(file_name, "-") ? fopen(file_name, "w") : stdout; |
| 128 | if (!file) { |
| 129 | perror(file_name); |
| 130 | exit(1); |
| 131 | } |
| 132 | |
| 133 | sprintf(tmp, "%s-top.pgm", name); |
| 134 | height_field(tmp, s->a); |
| 135 | sprintf(tmp, "%s-bot.pgm", name); |
| 136 | height_field(tmp, s->b); |
| 137 | |
| 138 | sanitize(name, tmp); |
| 139 | fprintf(file, "#declare Part_%s =\n intersection {\n", tmp); |
| 140 | povray_face(file, s->a, "top", name, 0, s->dist/2); |
| 141 | povray_face(file, s->b, "bot", name, 1, -s->dist/2); |
| 142 | fprintf(file, " }\n"); |
| 143 | |
| 144 | /* @@@ not reliable */ |
| 145 | if (ferror(file)) { |
| 146 | perror(file_name); |
| 147 | exit(1); |
| 148 | } |
| 149 | if (fflush(file) == EOF) { |
| 150 | perror(file_name); |
| 151 | exit(1); |
| 152 | } |
| 153 | if (file != stdout) |
| 154 | if (fclose(file) < 0) { |
| 155 | perror(file_name); |
| 156 | exit(1); |
| 157 | } |
| 158 | } |
| 159 |
Branches:
master
