memory optimized bmp loading finished
This commit is contained in:
parent
020dacba24
commit
041f291963
11 changed files with 319 additions and 59 deletions
|
@ -1 +0,0 @@
|
|||
boo
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
132
src/koa/file.c
132
src/koa/file.c
|
@ -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);
|
||||
}
|
|
@ -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
29
src/koa/sdl.c
Normal 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
13
src/koa/sdl.h
Normal 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
|
84
src/main.c
84
src/main.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
8
src/okuu/terrain.c
Normal 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
29
src/okuu/terrain.h
Normal 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
|
Loading…
Reference in a new issue