memory optimized bmp loading finished

This commit is contained in:
MallocNull 2020-12-14 15:44:03 -06:00
parent 020dacba24
commit 041f291963
11 changed files with 319 additions and 59 deletions

View file

@ -1 +0,0 @@
boo

View file

@ -19,4 +19,30 @@ void mfree(int n, ...) {
}
va_end(args);
}
uint8_t* _ord(uint8_t* buf, int length, int le) {
static int end_chk = -1;
if(end_chk == -1) {
uint16_t chk = 0xB00B;
end_chk = ((uint8_t*)&chk)[0] == 0x0B;
}
if((end_chk && le) || (!end_chk && !le))
return buf;
uint8_t tmp[8] = { 0 };
for(int i = 0; i < length; ++i)
tmp[i] = buf[length - i - 1];
memcpy(buf, tmp, length);
return buf;
}
uint8_t* ltoh(uint8_t* buf, int length) {
return _ord(buf, length, 1);
}
uint8_t* btoh(uint8_t* buf, int length) {
return _ord(buf, length, 0);
}

View file

@ -1,9 +1,13 @@
#ifndef KOA_ETC_H
#define KOA_ETC_H
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
void mfree(int n, ...);
uint8_t* ltoh(uint8_t*, int);
uint8_t* btoh(uint8_t*, int);
#endif

View file

@ -60,3 +60,135 @@ char* file_read(const char* file) {
return content;
}
int _bmp_load_metadata(FILE* fp, bmp_meta_t* out) {
return 1;
}
int bmp_load_metadata(const char* file, bmp_meta_t* out) {
FILE* fp = fopen(file, "rb");
if(fp == NULL)
return 0;
uint8_t buffer[4] = { 0 };
fread(buffer, 1, 2, fp);
if(memcmp("BM", buffer, 2) != 0)
return 0;
fread(buffer, 1, 4, fp);
out->size = *(uint32_t*)ltoh(buffer, 4);
fseek(fp, 0, SEEK_END);
if(ftell(fp) != out->size)
return 0;
fseek(fp, 0x0A, SEEK_SET);
fread(buffer, 1, 4, fp);
out->header_size = *(uint32_t*)ltoh(buffer, 4);
out->body_size = out->size - out->header_size;
fseek(fp, 0x12, SEEK_SET);
fread(buffer, 1, 4, fp);
out->width = *(uint32_t*)ltoh(buffer, 4);
fread(buffer, 1, 4, fp);
out->height = *(uint32_t*)ltoh(buffer, 4);
fseek(fp, 2, SEEK_CUR);
fread(buffer, 1, 2, fp);
out->bitpp = *(uint16_t*)ltoh(buffer, 2);
out->bytepp = out->bitpp / 8;
if(out->bitpp != 24 && out->bitpp != 32)
return 0;
strcpy(out->file, file);
return 1;
}
bmp_t* bmp_load(const char* file) {
return bmp_load_chunk(file, 0, 0, -1, -1);
}
bmp_t* bmp_load_chunk
(const char* file, int x, int y, int width, int height)
{
if(x < 0 || y < 0)
return NULL;
bmp_meta_t data;
if(!bmp_load_metadata(file, &data))
return NULL;
bmp_t* bmp = malloc(sizeof(bmp_t));
bmp->pixels = NULL;
bmp->data = data;
if(!bmp_reload_chunk(bmp, x, y, width, height)) {
free(bmp);
return NULL;
}
return bmp;
}
int bmp_reload_chunk(bmp_t* bmp, int x, int y, int width, int height) {
bmp_meta_t* data = &bmp->data;
if(data == NULL)
return 0;
FILE* fp = fopen(data->file, "rb");
if(fp == NULL)
return 0;
if(x > data->width || y > data->height) {
fclose(fp);
return NULL;
}
if(bmp->pixels != NULL) {
for(int i = 0; i < bmp->height; ++i)
free(bmp->pixels[i]);
free(bmp->pixels);
}
width = (width <= 0 || (x + width > data->width))
? data->width - x
: width;
height = (height <= 0 || (y + height > data->height))
? data->height - y
: height;
bmp->width = width;
bmp->height = height;
bmp->pixels = malloc(sizeof(pixel_t*) * height);
for(int i = 0; i < height; ++i)
bmp->pixels[i] = malloc(sizeof(pixel_t) * width);
uint8_t buffer[4];
for(int ay = 0; ay < height; ++ay) {
fseek(fp,
data->header_size
+ (data->width * (data->height - (y + ay) - 1) * data->bytepp)
+ x * data->bytepp,
SEEK_SET
);
for(int ax = 0; ax < width; ++ax) {
fread(buffer, 1, data->bytepp, fp);
pixel_t* px = &bmp->pixels[ay][ax];
px->b = buffer[0];
px->g = buffer[1];
px->r = buffer[2];
}
}
fclose(fp);
return 1;
}
void bmp_unload(bmp_t* bmp) {
free(bmp->pixels);
free(bmp);
}

View file

@ -3,8 +3,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include "koa/etc.h"
#include "koa/thread.h"
#include "koa/time.h"
@ -16,4 +18,30 @@ void err_out(const char*);
char* file_read(const char*);
// BEGIN BMP LOADING FUNCTIONS
typedef struct {
uint8_t r, g, b;
} pixel_t;
typedef struct {
char file[4096];
uint32_t width, height, size,
header_size, body_size;
uint16_t bitpp, bytepp;
} bmp_meta_t;
typedef struct {
bmp_meta_t data;
uint32_t width, height;
pixel_t** pixels;
} bmp_t;
bmp_t* bmp_load(const char*);
bmp_t* bmp_load_chunk(const char*, int, int, int, int);
int bmp_reload_chunk(bmp_t*, int, int, int, int);
int bmp_load_metadata(const char*, bmp_meta_t*);
void bmp_unload(bmp_t*);
#endif

29
src/koa/sdl.c Normal file
View file

@ -0,0 +1,29 @@
#include "sdl.h"
void get_pixel(SDL_Color* out, SDL_Surface* img, int x, int y) {
int bpp = img->format->BytesPerPixel;
uint8_t* ptr = (uint8_t*)img->pixels + y * img->pitch + x * bpp;
Uint32 pixel;
switch(bpp) {
case 1:
pixel = *ptr;
break;
case 2:
pixel = *(Uint16*)ptr;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
pixel = ptr[0] << 16 | ptr[1] << 8 | ptr[2];
else
pixel = ptr[0] | ptr[1] << 8 | ptr[2] << 16;
break;
case 4:
pixel = *(Uint32*)ptr;
break;
default:
pixel = 0;
}
SDL_GetRGBA(pixel, img->format, &out->r, &out->g, &out->b, &out->a);
}

13
src/koa/sdl.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef KOA_SDL_H
#define KOA_SDL_H
#include <SDL.h>
#include <stdlib.h>
typedef struct {
uint8_t r, g, b, a;
} pixel_t;
void get_pixel(SDL_Color*, SDL_Surface*, int x, int y);
#endif

View file

@ -1,12 +1,12 @@
#include <SDL.h>
#include <GL/glew.h>
#include <SDL_opengl.h>
#include <cglm/cglm.h>
#include <GL/glu.h>
#include <stdio.h>
#include <assert.h>
#include <cglm/cglm.h>
#include "koa/file.h"
#include "okuu/mesh.h"
#include "okuu/shader.h"
@ -17,6 +17,7 @@
struct {
SDL_Window* window;
SDL_GLContext ctx;
const uint8_t* keys;
int mode, running;
mesh_t* monkey;
@ -40,7 +41,7 @@ int main(int argc, char* argv[]) {
if(init() < 0)
return -1;
_g.monkey = mesh_load("data/monkey.rbm");
_g.monkey = mesh_load("data/player.rbm");
_s_def.shader = shader_create("default");
shader_source(_s_def.shader, 2,
@ -51,6 +52,7 @@ int main(int argc, char* argv[]) {
"model", "view", "projection"
);
_g.keys = SDL_GetKeyboardState(NULL);
_g.running = 1;
while(_g.running)
run();
@ -61,22 +63,13 @@ int main(int argc, char* argv[]) {
void run() {
static mat4 model, view, projection;
static float rot_up = 45, rot_around = 45;
static int init = 1;
if(init) {
//glm_translate_make(model, (vec3){ 0.0f, 0.f, -3.f });
//glm_rotate(model, glm_rad(180), (vec3){0.f, 1.f, 0.f});
glm_rotate_make(model, glm_rad(180), (vec3){ 0.f, 1.f, 0.f });
//glm_mat4_identity(model);
glm_rotate_make(model, glm_rad(90), (vec3){ 0.f, -1.f, 0.f });
//glm_mat4_identity(view);
glm_lookat(
(vec3){3.f, 3.f, 3.f},
(vec3){0.f, 0.f, 0.f},
(vec3){0.f, 1.f, 0.f},
view
);
glm_mat4_identity(view);
glm_perspective(
glm_rad(45),
@ -85,11 +78,6 @@ void run() {
projection
);
/*glm_perspective_default(
(float)WINDOW_WIDTH/(float)WINDOW_HEIGHT,
projection
);*/
shader_start(_s_def.shader); {
glUniformMatrix4fv(_ATTR(DEF_MODEL), 1, GL_FALSE, (float*)model);
glUniformMatrix4fv(_ATTR(DEF_VIEW), 1, GL_FALSE, (float*)view);
@ -103,7 +91,21 @@ void run() {
glClearColor(0.f, 0.f, 0.5f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float radius = 2.f + 2.f * (rot_up / 90.f);
glm_lookat(
(vec3){
cos(glm_rad(rot_up)) * radius * cos(glm_rad(rot_around)),
radius * sin(glm_rad(rot_up)),
cos(glm_rad(rot_up)) * radius * sin(glm_rad(rot_around))
},
(vec3){0.f, 0.f, 0.f},
(vec3){0.f, 1.f, 0.f},
view
);
shader_start(_s_def.shader); {
glUniformMatrix4fv(_ATTR(DEF_VIEW), 1, GL_FALSE, (float*)view);
mesh_bind(_g.monkey);
mesh_render(_g.monkey);
mesh_unbind();
@ -111,26 +113,34 @@ void run() {
SDL_GL_SwapWindow(_g.window);
SDL_PumpEvents();
if(_g.keys[SDL_SCANCODE_ESCAPE])
_g.running = 0;
if(_g.keys[SDL_SCANCODE_F]) {
_g.mode = !_g.mode;
SDL_SetWindowFullscreen(
_g.window,
_g.mode == 0
? 0
: SDL_WINDOW_FULLSCREEN
);
}
if(_g.keys[SDL_SCANCODE_UP])
rot_up = glm_min(89.f, rot_up + 1.5f);
else if(_g.keys[SDL_SCANCODE_DOWN])
rot_up = glm_max(0.f, rot_up - 1.5f);
if(_g.keys[SDL_SCANCODE_RIGHT])
rot_around -= 2.f;
else if(_g.keys[SDL_SCANCODE_LEFT])
rot_around += 2.f;
SDL_Event ev;
while(SDL_PollEvent(&ev)) {
if(ev.type == SDL_KEYDOWN) {
switch(ev.key.keysym.sym) {
case SDLK_ESCAPE:
_g.running = 0;
break;
case 'f':
_g.mode = !_g.mode;
SDL_SetWindowFullscreen(
_g.window,
_g.mode == 0
? 0
: SDL_WINDOW_FULLSCREEN
);
break;
}
} else if(ev.type == SDL_QUIT) {
if(ev.type == SDL_QUIT)
_g.running = 0;
}
}
}

View file

@ -8,24 +8,6 @@ typedef struct {
uint32_t data[3][3];
} _tri_t;
uint8_t* _ord(uint8_t* buf, int length) {
static int end_chk = -1;
if(end_chk == -1) {
uint16_t chk = 0xB00B;
end_chk = ((uint8_t*)&chk)[0] == 0x0B;
}
if(end_chk)
return buf;
uint8_t tmp[8] = { 0 };
for(int i = 0; i < length; ++i)
tmp[i] = buf[length - i - 1];
memcpy(buf, tmp, length);
return buf;
}
int _populate_pts
(_pt_t* data, FILE* fp, uint32_t length, int width)
{
@ -38,7 +20,7 @@ int _populate_pts
if(chk != 4)
return 0;
data[i].data[j] = *(float*)_ord(buffer, 4);
data[i].data[j] = *(float*)ltoh(buffer, 4);
}
}
@ -60,7 +42,7 @@ int _populate_faces
if(chk != length)
return 0;
data[at].data[i][j] = *(uint32_t *) _ord(buffer, 4);
data[at].data[i][j] = *(uint32_t *) ltoh(buffer, 4);
}
}
@ -86,7 +68,7 @@ mesh_t* mesh_load(const char* file) {
for(int i = 0; i < 4; ++i) {
fread(buffer, 1, 4, fp);
counts[i] = *(uint32_t*)_ord(buffer, 4);
counts[i] = *(uint32_t*)ltoh(buffer, 4);
}
if(feof(fp) || counts[VERT_CNT] == 0 || counts[FACE_CNT] == 0) {

8
src/okuu/terrain.c Normal file
View file

@ -0,0 +1,8 @@
#include "terrain.h"
terrain_t* terrain_load
(const char* heights, const char* colors,
int initial_x, int initial_y)
{
}

29
src/okuu/terrain.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef OKUU_TERRAIN_H
#define OKUU_TERRAIN_H
#include <SDL.h>
#include <SDL_image.h>
#include <GL/glew.h>
#include <SDL_opengl.h>
#include <cglm/cglm.h>
#include <GL/glu.h>
#include <stdlib.h>
#include <stdarg.h>
#include "koa/file.h"
#define CHUNK_SIZE 20
typedef struct {
bmp_meta_t meta[2];
GLuint buffers[3], vao;
int offset_x, offset_y;
uint8_t heights[CHUNK_SIZE][CHUNK_SIZE];
} terrain_t;
terrain_t* terrain_load(const char*, const char*, int, int);
void terrain_unload(terrain_t*);
#endif