mat_t modelviewprojection;
mat_t viewport;
bool dirty;
+ const model_t* current;
#if LIGHTING
list_t* lights;
color_t ambient;
raster_viewport(p, 0, 0, width, height);
p->model = p->view = p->projection = MAT_IDENTITY;
p->dirty = false;
+ p->current = NULL;
#if LIGHTING
p->ambient = color_new(S(0.2), S(0.2), S(0.2), S(1.0));
}
+color_t raster_color(const raster_t* p, vec_t pt)
+{
+ int u = (int)((scal_t)p->w * pt.x);
+ int v = (int)((scal_t)p->h * pt.y);
+ return p->pixels[p->w * (p->h - v - 1) + u];
+}
+
+
void raster_clear(raster_t* p, color_t fill)
{
size_t size = p->w * p->h;
}
-#define _CHECK_WRITE(X) if ((X) <= 0) goto fail
+#define _DO_OR_DIE(X) if ((X) <= 0) goto fail
int raster_export_ppm(const raster_t* p, const char* filename)
{
return -1;
}
- _CHECK_WRITE(fprintf(file, "P3\n%u %u\n255\n", p->w, p->h));
+ _DO_OR_DIE(fprintf(file, "P3\n%u %u\n255\n", p->w, p->h));
for (int y = (int)p->h - 1; y >= 0; --y) {
for (int x = 0; x < p->w; ++x) {
rgbachan_t r, g, b;
color_split(p->pixels[y * p->w + x], &r, &g, &b, NULL);
- _CHECK_WRITE(fprintf(file, "%hhu %hhu %hhu\n", r, g, b));
+ _DO_OR_DIE(fprintf(file, "%hhu %hhu %hhu\n", r, g, b));
}
}
/*
* Check the return values to avoid loud warnings.
*/
- _CHECK_WRITE(fwrite(&magicNumber, sizeof(magicNumber), 1, file));
- _CHECK_WRITE(fwrite(&fileSize, sizeof(fileSize), 1, file));
- _CHECK_WRITE(fwrite(&reserved0, sizeof(reserved0), 1, file));
- _CHECK_WRITE(fwrite(&reserved1, sizeof(reserved1), 1, file));
- _CHECK_WRITE(fwrite(&dataOffset, sizeof(dataOffset), 1, file));
- _CHECK_WRITE(fwrite(&infoHeaderSize, sizeof(infoHeaderSize), 1, file));
- _CHECK_WRITE(fwrite(&width, sizeof(width), 1, file));
- _CHECK_WRITE(fwrite(&height, sizeof(height), 1, file));
- _CHECK_WRITE(fwrite(&colorPlanes, sizeof(colorPlanes), 1, file));
- _CHECK_WRITE(fwrite(&bitsPerPixel, sizeof(bitsPerPixel), 1, file));
- _CHECK_WRITE(fwrite(&compression, sizeof(compression), 1, file));
- _CHECK_WRITE(fwrite(&dataSize, sizeof(dataSize), 1, file));
- _CHECK_WRITE(fwrite(&horizontalResolution, sizeof(horizontalResolution), 1, file));
- _CHECK_WRITE(fwrite(&verticalResolution, sizeof(verticalResolution), 1, file));
- _CHECK_WRITE(fwrite(&paletteColorCount, sizeof(paletteColorCount), 1, file));
- _CHECK_WRITE(fwrite(&importantPaletteColorCount, sizeof(importantPaletteColorCount), 1, file));
+ _DO_OR_DIE(fwrite(&magicNumber, sizeof(magicNumber), 1, file));
+ _DO_OR_DIE(fwrite(&fileSize, sizeof(fileSize), 1, file));
+ _DO_OR_DIE(fwrite(&reserved0, sizeof(reserved0), 1, file));
+ _DO_OR_DIE(fwrite(&reserved1, sizeof(reserved1), 1, file));
+ _DO_OR_DIE(fwrite(&dataOffset, sizeof(dataOffset), 1, file));
+ _DO_OR_DIE(fwrite(&infoHeaderSize, sizeof(infoHeaderSize), 1, file));
+ _DO_OR_DIE(fwrite(&width, sizeof(width), 1, file));
+ _DO_OR_DIE(fwrite(&height, sizeof(height), 1, file));
+ _DO_OR_DIE(fwrite(&colorPlanes, sizeof(colorPlanes), 1, file));
+ _DO_OR_DIE(fwrite(&bitsPerPixel, sizeof(bitsPerPixel), 1, file));
+ _DO_OR_DIE(fwrite(&compression, sizeof(compression), 1, file));
+ _DO_OR_DIE(fwrite(&dataSize, sizeof(dataSize), 1, file));
+ _DO_OR_DIE(fwrite(&horizontalResolution, sizeof(horizontalResolution), 1, file));
+ _DO_OR_DIE(fwrite(&verticalResolution, sizeof(verticalResolution), 1, file));
+ _DO_OR_DIE(fwrite(&paletteColorCount, sizeof(paletteColorCount), 1, file));
+ _DO_OR_DIE(fwrite(&importantPaletteColorCount, sizeof(importantPaletteColorCount), 1, file));
size_t size = width * height;
for (int i = 0; i < size; ++i)
argb = PACK(argb, 2, r);
argb = PACK(argb, 1, g);
argb = PACK(argb, 0, b);
- _CHECK_WRITE(fwrite(&argb, sizeof(argb), 1, file));
+ _DO_OR_DIE(fwrite(&argb, sizeof(argb), 1, file));
}
fclose(file);
return 0;
}
-#undef _CHECK_WRITE
+
+raster_t* raster_import(const char* filename)
+{
+ int type = 0;
+ char* ext = strrchr(filename, '.');
+ if (ext == NULL) {
+ goto fail;
+ }
+ ++ext;
+
+ if (strcmp(ext, "bmp") == 0) {
+ return raster_import_bmp(filename);
+ }
+ if (strcmp(ext, "ppm") == 0) {
+ return raster_import_ppm(filename);
+ }
+
+fail:
+ fprintf(stderr, "Unknown file type: %s", filename);
+ return NULL;
+}
+
+raster_t* raster_import_ppm(const char* filename)
+{
+ FILE* file = fopen(filename, "r");
+ if (file == NULL) {
+ fprintf(stderr, "Cannot read from %s: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+ int w, h;
+ if (fscanf(file, "P3 %d %d 255 ", &w, &h) != 2) {
+ fprintf(stderr, "Cannot read header from %s: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+ raster_t* p = raster_alloc(w, h, COLOR_WHITE);
+
+ for (int y = h - 1; y >= 0; --y) {
+ for (int x = 0; x < w; ++x) {
+ uint16_t r, g, b;
+ /* mingw32 does not like %hhu conversion type */
+ if (fscanf(file, "%hu %hu %hu ", &r, &g, &b) != 3) {
+ fprintf(stderr, "Failed reading color values from %s: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+ rgba_t rgba = PACK(rgba, 3, (uint8_t)r);
+ rgba = PACK(rgba, 2, (uint8_t)g);
+ rgba = PACK(rgba, 1, (uint8_t)b);
+ rgba = PACK(rgba, 0, 255);
+ p->pixels[y * w + x] = color_from_rgba(rgba);
+ }
+ }
+
+ fclose(file);
+ return p;
+
+fail:
+ raster_destroy(p);
+ fclose(file);
+ fprintf(stderr, "Unexpected file format in %s: %s\n", filename, strerror(errno));
+ return NULL;
+}
+
+raster_t* raster_import_bmp(const char* filename)
+{
+ FILE* file = fopen(filename, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "Cannot read from %s: %s\n", filename, strerror(errno));
+ return NULL;
+ }
+
+ uint16_t magicNumber;
+ uint16_t reserved0;//0x4D41;
+ uint16_t reserved1;//0x5454;
+ uint32_t dataOffset;
+ uint32_t infoHeaderSize;
+ uint32_t width;
+ uint32_t height;
+ uint16_t colorPlanes;
+ uint16_t bitsPerPixel;
+ uint32_t compression;
+ uint32_t dataSize;
+ uint32_t horizontalResolution;
+ uint32_t verticalResolution;
+ uint32_t paletteColorCount;
+ uint32_t importantPaletteColorCount;
+ uint32_t fileSize;
+
+ raster_t* p = NULL;
+
+ _DO_OR_DIE(fread(&magicNumber, sizeof(magicNumber), 1, file));
+ _DO_OR_DIE(fread(&fileSize, sizeof(fileSize), 1, file));
+ _DO_OR_DIE(fread(&reserved0, sizeof(reserved0), 1, file));
+ _DO_OR_DIE(fread(&reserved1, sizeof(reserved1), 1, file));
+ _DO_OR_DIE(fread(&dataOffset, sizeof(dataOffset), 1, file));
+ _DO_OR_DIE(fread(&infoHeaderSize, sizeof(infoHeaderSize), 1, file));
+ _DO_OR_DIE(fread(&width, sizeof(width), 1, file));
+ _DO_OR_DIE(fread(&height, sizeof(height), 1, file));
+ _DO_OR_DIE(fread(&colorPlanes, sizeof(colorPlanes), 1, file));
+ _DO_OR_DIE(fread(&bitsPerPixel, sizeof(bitsPerPixel), 1, file));
+ _DO_OR_DIE(fread(&compression, sizeof(compression), 1, file));
+ _DO_OR_DIE(fread(&dataSize, sizeof(dataSize), 1, file));
+ _DO_OR_DIE(fread(&horizontalResolution, sizeof(horizontalResolution), 1, file));
+ _DO_OR_DIE(fread(&verticalResolution, sizeof(verticalResolution), 1, file));
+ _DO_OR_DIE(fread(&paletteColorCount, sizeof(paletteColorCount), 1, file));
+ _DO_OR_DIE(fread(&importantPaletteColorCount, sizeof(importantPaletteColorCount), 1, file));
+
+ p = raster_alloc((int)width, (int)height, COLOR_WHITE);
+
+ size_t size = width * height;
+ for (int i = 0; i < size; ++i)
+ {
+ uint32_t argb;
+ _DO_OR_DIE(fread(&argb, sizeof(argb), 1, file));
+ rgba_t rgba = PACK(rgba, 3, UNPACK(argb, 2));
+ rgba = PACK(rgba, 2, UNPACK(argb, 1));
+ rgba = PACK(rgba, 1, UNPACK(argb, 0));
+ rgba = PACK(rgba, 0, UNPACK(argb, 3));
+ p->pixels[i] = color_from_rgba(rgba);
+ }
+
+ fclose(file);
+ return p;
+
+fail:
+ if (p) {
+ raster_destroy(p);
+ }
+ fclose(file);
+ fprintf(stderr, "Unexpected file format in %s: %s\n", filename, strerror(errno));
+ return NULL;
+}
+
+#undef _DO_OR_DIE
void raster_draw_model(raster_t* p, const model_t* model)
model_transformation(model, &p->model);
p->dirty = true;
raster_material(p, model_specular(model), model_shininess(model));
+ p->current = model;
IF_RENDER_PROGRESS(tri = 0);
for (const list_t* ti = model_geometry(model); ti; ti = ti->link) {
#if VERBOSITY >= 4
INLINE_MAYBE
color_t _do_phong_lighting(raster_t* p, vert_t vert)
{
+#if TEXTURING
+ vert.c = color_mult(vert.c, model_tcolor(p->current, vert.t));
+#endif
#if LIGHTING
color_t color = COLOR_BLACK;
color.a = vert.c.a;
p->modelviewprojection = mat_mult(p->projection, p->modelviewprojection);
p->dirty = false;
}
+
t = tri_transform(t, p->modelviewprojection);
+
+ // save w-values for texture mapping perspective correction
+ scal_t w1 = t.a.v.w;
+ scal_t w2 = t.b.v.w;
+ scal_t w3 = t.c.v.w;
+
t = tri_homodiv(t);
if (!_try_cull_backface(t)) {
#if LIGHTING >= 1
tri_t tl = tri_transform(*triangle, p->model);
+ tl.a.t.w = w1;
+ tl.b.t.w = w2;
+ tl.c.t.w = w3;
#endif
#if LIGHTING == 1