loading png textures and reading obj uv coordinates

This commit is contained in:
jb 2025-07-27 19:00:58 -07:00
parent 541c4dec44
commit e2def09d77
10 changed files with 1467 additions and 63 deletions

View File

@ -13,6 +13,7 @@ add_executable(${PROJECT_NAME} scripts/main.c
scripts/light.c
scripts/texture.c
scripts/swap.c
scripts/upng.c
scripts/display.c)
# --- SDL2 SETUP ---

View File

@ -1,46 +1,48 @@
# Blender v2.76 (sub 0) OBJ File: ''
# www.blender.org
# cube.obj
#
mtllib cube.mtl
o Cube
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
o cube
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -0.999999
v 0.999999 1.000000 1.000001
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v 1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 1.000000 0.333333
vt 1.000000 0.666667
vt 0.666667 0.666667
vt 0.666667 0.333333
vt 0.666667 0.000000
vt 0.000000 0.333333
vt 0.000000 0.000000
vt 0.333333 0.000000
vt 0.333333 1.000000
vt 0.000000 1.000000
vt 0.000000 0.666667
vt 0.333333 0.333333
vt 0.333333 0.666667
v 1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
vt 1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vt 0.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -0.000000 0.000000 1.000000
vn -1.000000 -0.000000 -0.000000
vn 0.000000 0.000000 -1.000000
usemtl Material
s off
f 2/1/1 3/2/1 4/3/1
f 8/1/2 7/4/2 6/5/2
f 5/6/3 6/7/3 2/8/3
f 6/8/4 7/5/4 3/4/4
f 3/9/5 7/10/5 8/11/5
f 1/12/6 4/13/6 8/11/6
f 1/4/1 2/1/1 4/3/1
f 5/14/2 8/1/2 6/5/2
f 1/12/3 5/6/3 2/8/3
f 2/12/4 6/8/4 3/4/4
f 4/13/5 3/9/5 8/11/5
f 5/6/6 1/12/6 8/11/6
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
g cube
usemtl cube
s 1
f 1/1/1 2/2/1 3/3/1
f 3/3/1 2/2/1 4/4/1
s 2
f 3/1/2 4/2/2 5/3/2
f 5/3/2 4/2/2 6/4/2
s 3
f 5/4/3 6/3/3 7/2/3
f 7/2/3 6/3/3 8/1/3
s 4
f 7/1/4 8/2/4 1/3/4
f 1/3/4 8/2/4 2/4/4
s 5
f 2/1/5 8/2/5 4/3/5
f 4/3/5 8/2/5 6/4/5
s 6
f 7/1/6 1/2/6 5/3/6
f 5/3/6 1/2/6 3/4/6

BIN
assets/cube.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

View File

@ -39,7 +39,7 @@ void setup(void) {
// Creating a SDL texture that is used to display the color buffer
color_buffer_texture = SDL_CreateTexture(
renderer,
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_RGBA32,
SDL_TEXTUREACCESS_STREAMING,
window_width,
window_height
@ -53,13 +53,14 @@ void setup(void) {
proj_matrix = mat4_make_perspective(fov, aspect, znear, zfar);
// Manually load the hardcoded texture data from the static array
mesh_texture = (uint32_t*)REDBRICK_TEXTURE;
texture_width = 64;
texture_height = 64;
//mesh_texture = (uint32_t*)REDBRICK_TEXTURE;
//texture_width = 64;
//texture_height = 64;
load_png_texture_data("../assets/cube.png");
// Loads the vertex and face values for the mesh data structure
load_cube_mesh_data();
// load_obj_file_data("./assets/f22.obj");
//load_cube_mesh_data();
load_obj_file_data("../assets/cube.obj");
}
///////////////////////////////////////////////////////////////////////////////
@ -131,9 +132,9 @@ void update(void) {
face_t mesh_face = mesh.faces[i];
vec3_t face_vertices[3];
face_vertices[0] = mesh.vertices[mesh_face.a - 1];
face_vertices[1] = mesh.vertices[mesh_face.b - 1];
face_vertices[2] = mesh.vertices[mesh_face.c - 1];
face_vertices[0] = mesh.vertices[mesh_face.a];
face_vertices[1] = mesh.vertices[mesh_face.b];
face_vertices[2] = mesh.vertices[mesh_face.c];
vec4_t transformed_vertices[3];
@ -316,6 +317,7 @@ void free_resources(void) {
free(color_buffer);
array_free(mesh.faces);
array_free(mesh.vertices);
upng_free(png_texture);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -24,23 +24,23 @@ vec3_t cube_vertices[N_CUBE_VERTICES] = {
face_t cube_faces[N_CUBE_FACES] = {
// front
{ .a = 1, .b = 2, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 1, .b = 3, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 1, .b = 2, .c = 3, .a_uv = { 0, 1 }, .b_uv = { 0, 0 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 1, .b = 3, .c = 4, .a_uv = { 0, 1 }, .b_uv = { 1, 0 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
// right
{ .a = 4, .b = 3, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 4, .b = 5, .c = 6, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 4, .b = 3, .c = 5, .a_uv = { 0, 1 }, .b_uv = { 0, 0 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 4, .b = 5, .c = 6, .a_uv = { 0, 1 }, .b_uv = { 1, 0 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
// back
{ .a = 6, .b = 5, .c = 7, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 7, .c = 8, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 5, .c = 7, .a_uv = { 0, 1 }, .b_uv = { 0, 0 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 7, .c = 8, .a_uv = { 0, 1 }, .b_uv = { 1, 0 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
// left
{ .a = 8, .b = 7, .c = 2, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 8, .b = 2, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 8, .b = 7, .c = 2, .a_uv = { 0, 1 }, .b_uv = { 0, 0 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 8, .b = 2, .c = 1, .a_uv = { 0, 1 }, .b_uv = { 1, 0 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
// top
{ .a = 2, .b = 7, .c = 5, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 2, .b = 5, .c = 3, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 2, .b = 7, .c = 5, .a_uv = { 0, 1 }, .b_uv = { 0, 0 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 2, .b = 5, .c = 3, .a_uv = { 0, 1 }, .b_uv = { 1, 0 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
// bottom
{ .a = 6, .b = 8, .c = 1, .a_uv = { 0, 0 }, .b_uv = { 0, 1 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 1, .c = 4, .a_uv = { 0, 0 }, .b_uv = { 1, 1 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF }
{ .a = 6, .b = 8, .c = 1, .a_uv = { 0, 1 }, .b_uv = { 0, 0 }, .c_uv = { 1, 0 }, .color = 0xFFFFFFFF },
{ .a = 6, .b = 1, .c = 4, .a_uv = { 0, 1 }, .b_uv = { 1, 0 }, .c_uv = { 1, 1 }, .color = 0xFFFFFFFF }
};
void load_cube_mesh_data(void) {
@ -59,6 +59,8 @@ void load_obj_file_data(char* filename) {
file = fopen(filename, "r");
char line[1024];
tex2_t* textcoords = NULL;
while (fgets(line, 1024, file)) {
// Vertex information
if (strncmp(line, "v ", 2) == 0) {
@ -66,6 +68,12 @@ void load_obj_file_data(char* filename) {
sscanf(line, "v %f %f %f", &vertex.x, &vertex.y, &vertex.z);
array_push(mesh.vertices, vertex);
}
// texture coordinate information
if (strncmp(line, "vt ", 3) == 0) {
tex2_t textcoord;
sscanf(line, "vt %f %f", &textcoord.u, &textcoord.v);
array_push(textcoords, textcoord);
}
// Face information
if (strncmp(line, "f ", 2) == 0) {
int vertex_indices[3];
@ -78,12 +86,16 @@ void load_obj_file_data(char* filename) {
&vertex_indices[2], &texture_indices[2], &normal_indices[2]
);
face_t face = {
.a = vertex_indices[0],
.b = vertex_indices[1],
.c = vertex_indices[2],
.a = vertex_indices[0] - 1,
.b = vertex_indices[1] - 1,
.c = vertex_indices[2] - 1,
.a_uv = textcoords[texture_indices[0] - 1],
.b_uv = textcoords[texture_indices[1] - 1],
.c_uv = textcoords[texture_indices[2] - 1],
.color = 0xFFFFFFFF
};
array_push(mesh.faces, face);
}
}
array_free(textcoords);
}

View File

@ -4,6 +4,7 @@
int texture_width = 64;
int texture_height = 64;
upng_t* png_texture = NULL;
uint32_t* mesh_texture = NULL;
const uint8_t REDBRICK_TEXTURE[] = {
@ -72,3 +73,18 @@ const uint8_t REDBRICK_TEXTURE[] = {
0x38, 0x38, 0x38, 0xff, 0x54, 0x54, 0x54, 0xff, 0x38, 0x38, 0x38, 0xff, 0x54, 0x54, 0x54, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x48, 0x48, 0x48, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x38, 0x38, 0x38, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff,
0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff,
};
void load_png_texture_data(char* filename) {
//upng_t * upng;
png_texture = upng_new_from_file(filename);
if (png_texture != NULL) {
upng_decode(png_texture);
if (upng_get_error(png_texture) == UPNG_EOK) {
mesh_texture = (uint32_t*)upng_get_buffer(png_texture);
texture_height = upng_get_height(png_texture);
texture_width = upng_get_width(png_texture);
}
}
}

View File

@ -2,6 +2,7 @@
#define TEXTURE_H
#include <stdint.h>
#include "upng.h"
typedef struct {
float u;
@ -14,5 +15,8 @@ extern int texture_height;
extern const uint8_t REDBRICK_TEXTURE[];
extern uint32_t* mesh_texture;
extern upng_t* png_texture;
void load_png_texture_data(char* filename);
#endif

View File

@ -262,6 +262,11 @@ void draw_textured_triangle(
float_swap(&v0, &v1);
}
// flip v component to account for inverted uv coordinates (where v grows downwrds)
v0 = 1.0f - v0;
v1 = 1.0f - v1;
v2 = 1.0f - v2;
// Create vector points and texture coords after we sort the vertices
vec4_t point_a = { x0, y0, z0, w0 };
vec4_t point_b = { x1, y1, z1, w1 };

1281
scripts/upng.c Normal file

File diff suppressed because it is too large Load Diff

81
scripts/upng.h Normal file
View File

@ -0,0 +1,81 @@
/*
uPNG -- derived from LodePNG version 20100808
Copyright (c) 2005-2010 Lode Vandevenne
Copyright (c) 2010 Sean Middleditch
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#if !defined(UPNG_H)
#define UPNG_H
typedef enum upng_error {
UPNG_EOK = 0, /* success (no error) */
UPNG_ENOMEM = 1, /* memory allocation failed */
UPNG_ENOTFOUND = 2, /* resource not found (file missing) */
UPNG_ENOTPNG = 3, /* image data does not have a PNG header */
UPNG_EMALFORMED = 4, /* image data is not a valid PNG image */
UPNG_EUNSUPPORTED = 5, /* critical PNG chunk type is not supported */
UPNG_EUNINTERLACED = 6, /* image interlacing is not supported */
UPNG_EUNFORMAT = 7, /* image color format is not supported */
UPNG_EPARAM = 8 /* invalid parameter to method call */
} upng_error;
typedef enum upng_format {
UPNG_BADFORMAT,
UPNG_RGB8,
UPNG_RGB16,
UPNG_RGBA8,
UPNG_RGBA16,
UPNG_LUMINANCE1,
UPNG_LUMINANCE2,
UPNG_LUMINANCE4,
UPNG_LUMINANCE8,
UPNG_LUMINANCE_ALPHA1,
UPNG_LUMINANCE_ALPHA2,
UPNG_LUMINANCE_ALPHA4,
UPNG_LUMINANCE_ALPHA8
} upng_format;
typedef struct upng_t upng_t;
upng_t* upng_new_from_bytes (const unsigned char* buffer, unsigned long size);
upng_t* upng_new_from_file (const char* path);
void upng_free (upng_t* upng);
upng_error upng_header (upng_t* upng);
upng_error upng_decode (upng_t* upng);
upng_error upng_get_error (const upng_t* upng);
unsigned upng_get_error_line (const upng_t* upng);
unsigned upng_get_width (const upng_t* upng);
unsigned upng_get_height (const upng_t* upng);
unsigned upng_get_bpp (const upng_t* upng);
unsigned upng_get_bitdepth (const upng_t* upng);
unsigned upng_get_components (const upng_t* upng);
unsigned upng_get_pixelsize (const upng_t* upng);
upng_format upng_get_format (const upng_t* upng);
const unsigned char* upng_get_buffer (const upng_t* upng);
unsigned upng_get_size (const upng_t* upng);
#endif /*defined(UPNG_H)*/