+++ /dev/null
-
-/*
- * CS5600 University of Utah
- * Charles McGarvey
- * mcgarvey@eng.utah.edu
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "pixmap.h"
-
-
-struct pixmap
-{
- color_t* pixels;
- int w;
- int h;
- int left, right, bottom, top;
- mat_t modelview;
- mat_t projection;
- mat_t final;
-};
-
-
-pixmap_t* pixmap_alloc(int width, int height, color_t fill)
-{
- assert(0 < width && 0 < height && "zero-dimension pixmap not allowed");
- size_t size = width * height;
-
- pixmap_t* p = (pixmap_t*)mem_alloc(sizeof(pixmap_t));
- p->pixels = (color_t*)mem_alloc(sizeof(color_t) * size);
- p->w = width;
- p->h = height;
- p->left = p->bottom = 0;
- p->right = width;
- p->top = height;
- pixmap_clear(p, fill);
- return p;
-}
-
-void pixmap_destroy(pixmap_t* p)
-{
- mem_free(p->pixels);
- mem_free(p);
-}
-
-
-void pixmap_clear(pixmap_t* p, color_t fill)
-{
- size_t size = p->w * p->h;
- for (int i = 0; i < size; ++i) {
- p->pixels[i] = fill;
- }
-}
-
-
-static void _pixmap_set_transformation(pixmap_t* p)
-{
- /*
- * Just including a viewport transformation in the final transformation.
- * This could probably be faster by separating this out.
- */
- mat_t viewport = MAT_VIEWPORT(p->left, p->bottom, p->right - p->left, p->top - p->bottom);
- p->final = mat_mult(p->projection, p->modelview);
- p->final = mat_mult(viewport, p->final);
-}
-
-
-void pixmap_viewport(pixmap_t* p, int x, int y, int width, int height)
-{
- p->left = x;
- p->right = x + width;
- p->bottom = y;
- p->top = y + height;
- _pixmap_set_transformation(p);
-}
-
-void pixmap_modelview(pixmap_t* p, const mat_t* transform)
-{
- p->modelview = *transform;
- _pixmap_set_transformation(p);
-}
-
-void pixmap_projection(pixmap_t* p, const mat_t* transform)
-{
- p->projection = *transform;
- _pixmap_set_transformation(p);
-}
-
-
-#define _CHECK_WRITE(X) if ((X) <= 0) goto fail
-
-int pixmap_export_ppm(const pixmap_t* p, const char* filename)
-{
- FILE* file = fopen(filename, "w");
- if (file == NULL) {
-fail: fprintf(stderr, "Cannot write to %s: %s\n", filename, strerror(errno));
- return -1;
- }
-
- _CHECK_WRITE(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));
- }
- }
-
- fclose(file);
- return 0;
-}
-
-int pixmap_export_bmp(const pixmap_t* p, const char* filename)
-{
- /*
- * This function was adapted from sample code provided with the assignment
- * instructions.
- */
- FILE* file = fopen(filename, "wb");
- if (file == NULL) {
-fail: fprintf(stderr, "Cannot write to %s: %s\n", filename, strerror(errno));
- return -1;
- }
-
- uint16_t magicNumber = 0x4D42;
- uint16_t reserved0 = 0;//0x4D41;
- uint16_t reserved1 = 0;//0x5454;
- uint32_t dataOffset = 54;
- uint32_t infoHeaderSize = 40;
- uint32_t width = p->w;
- uint32_t height = p->h;
- uint16_t colorPlanes = 1;
- uint16_t bitsPerPixel = 32;
- uint32_t compression = 0;
- uint32_t dataSize = width * height * bitsPerPixel / 8;
- uint32_t horizontalResolution = 2835;
- uint32_t verticalResolution = 2835;
- uint32_t paletteColorCount = 0;
- uint32_t importantPaletteColorCount = 0;
- uint32_t fileSize = 54 + dataSize;
-
- /*
- * 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));
-
- size_t size = width * height;
- for (int i = 0; i < size; ++i)
- {
- rgbachan_t a, r, g, b;
- color_split(p->pixels[i], &r, &g, &b, &a);
- uint32_t argb = PACK(argb, 3, a);
- argb = PACK(argb, 2, r);
- argb = PACK(argb, 1, g);
- argb = PACK(argb, 0, b);
- _CHECK_WRITE(fwrite(&argb, sizeof(argb), 1, file));
- }
-
- fclose(file);
- return 0;
-}
-
-
-void pixmap_draw_tri(pixmap_t* p, const tri_t* triangle)
-{
- tri_t t = tri_transform(*triangle, p->final);
-
- for (int y = p->bottom; y < p->top; ++y) {
- for (int x = p->left; x < p->right; ++x) {
- vec_t pt = vec_new((scal_t)x, (scal_t)y, S(0.0));
- vec_t b = tri_barycentric(&t, pt);
- if (vec_is_barycentric(b)) {
- color_t* c = p->pixels + y * p->w + x;
- color_t color = color_new(
- t.a.c.r * b.x + t.b.c.r * b.y + t.c.c.r * b.z,
- t.a.c.g * b.x + t.b.c.g * b.y + t.c.c.g * b.z,
- t.a.c.b * b.x + t.b.c.b * b.y + t.c.c.b * b.z,
- S(1.0)
- );
- *c = color;
- }
- }
- }
-}
-