diff options
| -rw-r--r-- | Makefile | 19 | ||||
| -rw-r--r-- | convtexture.c | 169 | ||||
| -rw-r--r-- | intermediate/gun.bmp | bin | 0 -> 16522 bytes | |||
| -rw-r--r-- | testbc1.c | 74 | 
4 files changed, 257 insertions, 5 deletions
| @@ -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.bmpBinary files differ new file mode 100644 index 0000000..d64cb6c --- /dev/null +++ b/intermediate/gun.bmp 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); +		} +	} +} |