summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile19
-rw-r--r--convtexture.c169
-rw-r--r--intermediate/gun.bmpbin0 -> 16522 bytes
-rw-r--r--testbc1.c74
4 files changed, 257 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index 33c0c01..792b8b1 100644
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ int_dir = intermediate
data_dir = data
target = 3de
convmesh = convmesh
+convtexture = convtexture
packassets = packassets
pack = pack
@@ -29,8 +30,11 @@ mesh_sources = \
$(int_dir)/monkey.obj \
$(int_dir)/cube.obj
+texture_sources = \
+ $(int_dir)/gun.bmp \
+
meshes = $(mesh_sources:$(int_dir)/%.obj=$(data_dir)/%.msh)
-assets = $(meshes)
+textures = $(texture_sources:$(int_dir)/%.bmp=$(data_dir)/%.bc1)
all: $(target) $(pack)
@@ -43,19 +47,23 @@ $(target): $(objects)
$(meshes): $(data_dir)/%.msh : $(int_dir)/%.obj | $(convmesh) $(data_dir)
./$(convmesh) $< $@
-$(convassets): convassets.c
- $(tool_compiler) $(cflags) -o $@ $<
+$(textures): $(data_dir)/%.bc1 : $(int_dir)/%.bmp | $(convtexture) $(data_dir)
+ ./$(convtexture) $< $@
$(convmesh): convmesh.c
$(tool_compiler) $(cflags) -o $@ $<
+$(convtexture): convtexture.c
+ $(tool_compiler) $(cflags) -o $@ $< -lm
+
$(packassets): packassets.c
$(tool_compiler) packassets.c $(cflags) -o $@
-$(pack): $(packassets) $(meshes)
+$(pack): $(packassets) $(meshes) $(textures)
./$(packassets) \
$(data_dir) \
- $(notdir $(meshes))
+ $(notdir $(meshes)) \
+ $(notdir $(textures))
$(data_dir):
mkdir -p $(data_dir)
@@ -63,6 +71,7 @@ $(data_dir):
clean:
rm -f $(packassets)
rm -f $(convmesh)
+ rm -f $(convtexture)
rm -rf data
rm *.d
rm *.o
diff --git a/convtexture.c b/convtexture.c
new file mode 100644
index 0000000..a07c331
--- /dev/null
+++ b/convtexture.c
@@ -0,0 +1,169 @@
+#include "render.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct {
+ float r, g, b;
+} vec3;
+
+typedef struct {
+ vec3 start, end;
+ unsigned char indices[4 * 4];
+} Block;
+
+void get_block(Block* block, Colour* pixels, int stride) {
+ int x, y, i;
+ vec3 cols[4 * 4];
+ vec3 s, e;
+ float cd;
+ for (y = 0; y < 4; y++) {
+ for (x = 0; x < 4; x++) {
+ Colour pixel = pixels[x + y * stride];
+ vec3 vec;
+ vec.r = (float)pixel.r / 255.0f;
+ vec.g = (float)pixel.g / 255.0f;
+ vec.b = (float)pixel.b / 255.0f;
+ cols[x + y * 4] = vec;
+ }
+ }
+ cd = -1.0f;
+ for (i = 0; i < 4 * 4; i++) {
+ int j;
+ vec3* a = &cols[i];
+ for (j = i + 1; j < 4 * 4; j++) {
+ vec3* b = &cols[j];
+ float d =
+ (b->r - a->r) * (b->r - a->r) +
+ (b->g - a->g) * (b->g - a->g) +
+ (b->b - a->b) * (b->b - a->b);
+ if (d > cd) {
+ cd = d;
+ s = *a;
+ e = *b;
+ }
+ }
+ }
+ for (i = 0; i < 4 * 4; i++) {
+ vec3* col = &cols[i];
+ float d;
+ d =
+ (e.r - col->r) * (e.r - col->r) +
+ (e.g - col->g) * (e.g - col->g) +
+ (e.b - col->b) * (e.b - col->b);
+ if (cd < 0.0001f)
+ block->indices[i] = 0;
+ else {
+ d = d / cd;
+ block->indices[i] = (int)((1.0f - d) * 3.1f);
+ }
+ }
+ block->start = s;
+ block->end = e;
+}
+
+void compress_block(const Block* block, FILE* f) {
+ int i;
+ unsigned start =
+ ((unsigned)(block->start.r * 31.9999f) << 11) |
+ ((unsigned)(block->start.g * 63.9999f) << 5) |
+ ((unsigned)(block->start.b * 31.9999f));
+ unsigned end =
+ ((unsigned)(block->end.r * 31.9999f) << 11) |
+ ((unsigned)(block->end.g * 63.9999f) << 5) |
+ ((unsigned)(block->end.b * 31.9999f));
+ unsigned palette = (start << 16) | end;
+ unsigned indices = 0;
+ fwrite(&palette, 1, 4, f);
+ for (i = 0; i < 4 * 4; i++) {
+ indices |= block->indices[i] << (i * 2);
+ }
+ fwrite(&indices, 1, 4, f);
+}
+
+void compress_bc1(Colour* pixels, int w, int h, FILE* f) {
+ int x, y, cw, ch;
+ Block block;
+ fwrite(&w, 1, 4, f);
+ fwrite(&h, 1, 4, f);
+ cw = w / 4;
+ ch = h / 4;
+ for (y = 0; y < ch; y++) {
+ for (x = 0; x < cw; x++) {
+ get_block(&block, &pixels[x * 4 + y * 4 * w], w);
+ compress_block(&block, f);
+ }
+ }
+}
+
+int main(int argc, const char** argv) {
+ FILE* outfile, * infile;
+ char bmp_magic[2];
+ unsigned bmp_offset;
+ int bmp_w, bmp_h, s, x, y;
+ unsigned short bmp_bits;
+ Colour* buffer;
+ Colour pixel;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s infile outfile.\n", argv[0]);
+ return 1;
+ }
+
+ infile = fopen(argv[1], "rb");
+ if (!infile) {
+ fprintf(stderr, "Failed to open %s.\n", argv[1]);
+ return 2;
+ }
+
+ fread(bmp_magic, 2, 1, infile);
+ if (bmp_magic[0] != 'B' || bmp_magic[1] != 'M') {
+ fprintf(stderr, "Not a valid bitmap file.\n");
+ return 3;
+ }
+
+ fseek(infile, 10, SEEK_SET);
+ fread(&bmp_offset, 4, 1, infile);
+ fseek(infile, 18, SEEK_SET);
+ fread(&bmp_w, 4, 1, infile);
+ fread(&bmp_h, 4, 1, infile);
+ fseek(infile, 28, SEEK_SET);
+ fread(&bmp_bits, 2, 1, infile);
+
+ if (bmp_bits != 32) {
+ fprintf(stderr, "Bitmap must have 32 bit pixels. Instead has %d bit pixels.\n", bmp_bits);
+ return 4;
+ }
+
+ if (bmp_w % 4 != 0 || bmp_h % 4 != 0) {
+ fprintf(stderr, "Bitmap must have a size divisible by four.\n");
+ return 5;
+ }
+
+ fseek(infile, bmp_offset, SEEK_SET);
+ s = bmp_w * bmp_h;
+ buffer = malloc(s * 4);
+ /* Flip & read. */
+ for (y = 0; y < bmp_h; y++) {
+ for (x = 0; x < bmp_w; x++) {
+ unsigned char t;
+ fread(&pixel, 1, 4, infile);
+ t = pixel.r;
+ pixel.r = pixel.b;
+ pixel.b = t;
+ if (pixel.a == 0) {
+ pixel.r = 0;
+ pixel.g = 0;
+ pixel.b = 0;
+ }
+ buffer[x + (bmp_h - y - 1) * bmp_w] = pixel;
+ }
+ }
+ outfile = fopen(argv[2], "wb");
+ if (!outfile) {
+ fprintf(stderr, "Failed to open %s.\n", argv[2]);
+ return 6;
+ }
+ compress_bc1(buffer, bmp_w, bmp_h, outfile);
+ fclose(outfile);
+ return 0;
+}
diff --git a/intermediate/gun.bmp b/intermediate/gun.bmp
new file mode 100644
index 0000000..d64cb6c
--- /dev/null
+++ b/intermediate/gun.bmp
Binary files differ
diff --git a/testbc1.c b/testbc1.c
new file mode 100644
index 0000000..2b9aab4
--- /dev/null
+++ b/testbc1.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "render.h"
+
+typedef struct {
+ float r, g, b;
+} vec3;
+
+void lerp(vec3* d, const vec3* a, const vec3* b, float t) {
+ d->r = a->r + t * (b->r - a->r);
+ d->g = a->g + t * (b->g - a->g);
+ d->b = a->b + t * (b->b - a->b);
+}
+
+Colour get_pixel(unsigned* data, int x, int y, int w) {
+ vec3 start, end, col;
+ float t;
+ int i;
+ Colour r = { 0 };
+ unsigned palette = data[(x / 4 + y / 4 * (w / 4)) * 2];
+ unsigned indices = data[(x / 4 + y / 4 * (w / 4)) * 2 + 1];
+ start.r = (float)((palette & (31 << 27)) >> 27) / 32.0f;
+ start.g = (float)((palette & (63 << 21)) >> 21) / 64.0f;
+ start.b = (float)((palette & (31 << 16)) >> 16) / 32.0f;
+ end.r = (float)((palette & (31 << 11)) >> 11) / 32.0f;
+ end.g = (float)((palette & (63 << 5)) >> 5) / 64.0f;
+ end.b = (float)((palette & (31 )) ) / 32.0f;
+ i = x % 4 + (y % 4) * 4;
+ i = (indices & (3 << i * 2)) >> i * 2;
+ t = (float)i / 3.0f;
+ lerp(&col, &start, &end, t);
+ r.r = (int)(col.r * 255.0f);
+ r.g = (int)(col.g * 255.0f);
+ r.b = (int)(col.b * 255.0f);
+ return r;
+}
+
+int main(int argc, const char** argv) {
+ FILE* infile, * outfile;
+ unsigned* data;
+ int w, h, x, y, cw, ch;
+ unsigned palette, indices;
+ vec3 colour;
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s infile outfile.\n", argv[0]);
+ return 1;
+ }
+ infile = fopen(argv[1], "rb");
+ if (!infile) {
+ fprintf(stderr, "Failed to open %s.\n", argv[1]);
+ return 2;
+ }
+ outfile = fopen(argv[2], "w");
+ if (!infile) {
+ fprintf(stderr, "Failed to open %s.\n", argv[2]);
+ return 3;
+ }
+ fread(&w, 1, 4, infile);
+ fread(&h, 1, 4, infile);
+ cw = w / 4;
+ ch = h / 4;
+ data = malloc(cw * ch * 8);
+ fread(data, 1, cw * ch * 8, infile);
+ fprintf(outfile, "P3\n");
+ fprintf(outfile, "%d %d\n", w, h);
+ fprintf(outfile, "255\n");
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ Colour c = get_pixel(data, x, y, w);
+ fprintf(outfile, "%d %d %d\n", c.r, c.g, c.b);
+ }
+ }
+}