Implemented Basic OBJ file loading

This commit is contained in:
cannoli-fruit 2026-07-28 21:58:41 -04:00
commit 3934a87949
6 changed files with 11695 additions and 14 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "Lazyc"]
path = Lazyc
url = https://youra.monster/git/Cody/Lazyc

1
Lazyc Submodule

@ -0,0 +1 @@
Subproject commit 3a2363b4af31e619c64c6a3b5ffd5aff000fcc24

View file

@ -27,7 +27,7 @@ targets = {
for f in p:lines() do for f in p:lines() do
base = f:match("([^/]+)%.c$") base = f:match("([^/]+)%.c$")
obj = "build/"..base..".o" obj = "build/"..base..".o"
cc = "cc -c '"..f.."' -o '"..obj.."'" cc = "cc -I./Lazyc -c '"..f.."' -o '"..obj.."' -ggdb"
e,h,c = os.execute(cc) e,h,c = os.execute(cc)
if c ~= 0 and c ~= nil then if c ~= 0 and c ~= nil then
print("Compilation Error") print("Compilation Error")

View file

@ -2,6 +2,9 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#define LAZY_IMPL
#include "lazy.h"
typedef struct { typedef struct {
float x; float x;
@ -102,7 +105,7 @@ Collision intersect(Ray *r, Triangle *tr) {
Vec3 pvec = vec3_cross(&r->d, &e2); Vec3 pvec = vec3_cross(&r->d, &e2);
float det = vec3_dot(&e1, &pvec); float det = vec3_dot(&e1, &pvec);
if (fabs(det) < 0.01) if (fabs(det) < 0.001)
return (Collision){0}; return (Collision){0};
float invdet = 1.0 / det; float invdet = 1.0 / det;
@ -161,10 +164,10 @@ Vec3 shade(Collision *c, Ray *r, size_t depth, Triangle *scene, size_t tricnt) {
} }
Vec3 col = (Vec3){.x = 0.0f, .y = 0.0f, .z = 0.0f}; Vec3 col = (Vec3){.x = 0.0f, .y = 0.0f, .z = 0.0f};
Vec3 amb = vec3_scale(0.1, &c->mat.col); Vec3 amb = vec3_scale(0.3, &c->mat.col);
col = vec3_add(&col, &amb); col = vec3_add(&col, &amb);
for (int i = 0; i < 1; ++i) { // Assume only 1 light at 10,10,-2 for now for (int i = 0; i < 1; ++i) { // Assume only 1 light
Vec3 light = (Vec3){.x = 10, .y = -10, .z = -2}; Vec3 light = (Vec3){.x = 10, .y = -10, .z = -2};
Vec3 lightColor = (Vec3){.x = 1, .y = 1, .z = 1}; Vec3 lightColor = (Vec3){.x = 1, .y = 1, .z = 1};
float lightStrength = 0.5; float lightStrength = 0.5;
@ -172,11 +175,13 @@ Vec3 shade(Collision *c, Ray *r, size_t depth, Triangle *scene, size_t tricnt) {
Vec3 toLight = vec3_sub(&light, &c->p); Vec3 toLight = vec3_sub(&light, &c->p);
float lightDist = vec3_mag(&toLight); float lightDist = vec3_mag(&toLight);
toLight = vec3_norm(&toLight); toLight = vec3_norm(&toLight);
Vec3 offset = vec3_scale(0.01, &c->normal); Vec3 offset = vec3_scale(0.01, &c->normal);
Ray shadow = (Ray){.o = vec3_add(&c->p, &offset), .d = toLight}; Ray shadow = (Ray){.o = vec3_add(&c->p, &offset), .d = toLight};
Collision shadowC = intersectScene(&shadow, scene, tricnt); Collision shadowC = intersectScene(&shadow, scene, tricnt);
int inShadow = int inShadow =
shadowC.intersected && shadowC.t < lightDist && shadowC.t > 0.1; shadowC.intersected && shadowC.t < lightDist && shadowC.t > 0.01;
if (!inShadow) { if (!inShadow) {
float diff = vec3_dot(&c->normal, &toLight); float diff = vec3_dot(&c->normal, &toLight);
if (diff < 0.0) if (diff < 0.0)
@ -254,6 +259,157 @@ Vec3 rotateY(Vec3 *v, float angle) {
return (Vec3){.x = c * v->x - s * v->z, .y = v->y, .z = s * v->x + c * v->z}; return (Vec3){.x = c * v->x - s * v->z, .y = v->y, .z = s * v->x + c * v->z};
} }
Vec3 rotateZ(Vec3 *v, float angle) {
float c = cosf(angle);
float s = sinf(angle);
return (Vec3){.x = c * v->x - s * v->y, .y = s * v->x + c * v->y, .z = v->z};
}
void loadObj(const char *fname, Triangle *scene, size_t *tricnt, Vec3 col, Vec3 position, Vec3 rotation) {
FILE *f = fopen(fname, "rb");
size_t startTricnt = *tricnt;
Lz_DA(Vec3) verticies = {0};
lz_da_append(verticies, ((Vec3) {.x = 0, .y = 0, .z = 0})); // Objs are 1 indexed pmo
Material m = {
.refl = 0.2,
.brightness = 0.8,
.col = col
};
float maxX =-99999;
float minX = 99999;
float maxY =-99999;
float minY = 99999;
float maxZ =-99999;
float minZ = 99999;
while (1) {
char c;
char buf[16];
int err = fscanf(f, "%15s", buf);
if (err == EOF) abort();
if (buf[0] == '#') {
while ((c = fgetc(f)) != '\n' && c != EOF);
if (c == EOF) break;
continue;
}
printf("Read: |%s|\n", buf);
if (!strcmp(buf, "v")) {
float x,y,z;
err = fscanf(f, "%f %f %f\n", &x, &y, &z);
if (err == EOF) abort();
if (x > maxX) maxX = x;
if (x < minX) minX = x;
if (y > maxY) maxY = y;
if (y < minY) minY = y;
if (z > maxZ) maxZ = z;
if (z < minZ) minZ = z;
Vec3 v = (Vec3) {.x = x, .y = y, .z = z};
lz_da_append(verticies, v);
printf("Vertex: %d\n", verticies.cnt-1);
continue;
}
if (!strcmp(buf, "vn")) {
// Unimplemented / Don't Care
continue;
}
if (!strcmp(buf, "f") || !strcmp(buf, "f ")) {
printf("Face\n");
int verts[64];
int count = 0;
char token[64];
int c;
while (1) {
err = fscanf(f, "%d", &verts[count++]);
if (verts[count-1] == 0 || verts[count-1] >= verticies.cnt) {
abort();
}
if (err == EOF) {
abort();
}
c = fgetc(f);
if (c == '\n' || c == EOF) {
break;
}
ungetc(c, f);
}
printf("Count: %d\n", count);
for (int i = 0; i < count; ++i) {
printf(" Vertex: %d\n", verts[i]);
}
if (count != 3) {
abort();
}
if (count == 0) {
while ((c = fgetc(f)) != '\n' && c != EOF);
if (c == EOF) break;
continue;
}
for (int i = 1; i < count - 1; ++i) {
scene[(*tricnt)++] = (Triangle) {
.p0 = verticies.data[verts[0]],
.p1 = verticies.data[verts[i]],
.p2 = verticies.data[verts[i + 1]],
.mat = m
};
printf("Triangle: %d\n", *tricnt);
}
if (c == EOF) break;
continue;
}
printf("Invalid thingy %s\n", buf);
while ((c = fgetc(f)) != '\n' && c != EOF);
if (c == EOF) break;
}
float offsetX = -(minX+maxX)/2;
float offsetY = -(minY+maxY)/2;
float offsetZ = -(minZ+maxZ)/2;
for (int i = startTricnt; i < *tricnt; ++i) {
//printf("Offset %zu\n", i);
scene[i].p0.x += offsetX;
scene[i].p1.x += offsetX;
scene[i].p2.x += offsetX;
scene[i].p0.y += offsetY;
scene[i].p1.y += offsetY;
scene[i].p2.y += offsetY;
scene[i].p0.z += offsetZ;
scene[i].p1.z += offsetZ;
scene[i].p2.z += offsetZ;
scene[i].p0 = rotateX(&scene[i].p0, rotation.x);
scene[i].p0 = rotateY(&scene[i].p0, rotation.y);
scene[i].p0 = rotateZ(&scene[i].p0, rotation.z);
scene[i].p1 = rotateX(&scene[i].p1, rotation.x);
scene[i].p1 = rotateY(&scene[i].p1, rotation.y);
scene[i].p1 = rotateZ(&scene[i].p1, rotation.z);
scene[i].p2 = rotateX(&scene[i].p2, rotation.x);
scene[i].p2 = rotateY(&scene[i].p2, rotation.y);
scene[i].p2 = rotateZ(&scene[i].p2, rotation.z);
scene[i].p0.x += position.x;
scene[i].p0.y += position.y;
scene[i].p0.z += position.z;
scene[i].p1.x += position.x;
scene[i].p1.y += position.y;
scene[i].p1.z += position.z;
scene[i].p2.x += position.x;
scene[i].p2.y += position.y;
scene[i].p2.z += position.z;
}
printf("Verticies: %zu\n", verticies.cnt);
}
int main() { int main() {
printf("Hello World!\n"); printf("Hello World!\n");
@ -266,7 +422,27 @@ int main() {
fprintf(f, "255\n", W, H); fprintf(f, "255\n", W, H);
size_t tricnt = 0; size_t tricnt = 0;
Triangle *scene = malloc(128 * sizeof(Triangle)); Triangle *scene = malloc(8192 * sizeof(Triangle));
Vec3 red = (Vec3){.x = 0.8, .y = 0.2, .z = 0.2};
Vec3 green = (Vec3){.x = 0.2, .y = 0.8, .z = 0.2};
Vec3 blue = (Vec3){.x = 0.2, .y = 0.2, .z = 0.8};
Vec3 pos = {
.x = 0,
.y = 0,
.z = 25
};
Vec3 rotation = {
.x = 0,
.y = 0,
.z = -0.2
};
loadObj("teapot.obj", scene, &tricnt, blue, pos, rotation);
printf("Loaded Successfully %d triangles\n", tricnt);
/* Penrose triangle
Vec3 red = (Vec3){.x = 0.8, .y = 0.2, .z = 0.2}; Vec3 red = (Vec3){.x = 0.8, .y = 0.2, .z = 0.2};
Vec3 green = (Vec3){.x = 0.2, .y = 0.8, .z = 0.2}; Vec3 green = (Vec3){.x = 0.2, .y = 0.8, .z = 0.2};
Vec3 blue = (Vec3){.x = 0.2, .y = 0.2, .z = 0.8}; Vec3 blue = (Vec3){.x = 0.2, .y = 0.2, .z = 0.8};
@ -275,9 +451,11 @@ int main() {
float bz = 84; float bz = 84;
float l = 16; float l = 16;
float g = 2; float g = 2;
addBeam(scene, &tricnt, &red, bx, by, bz, g, l, g); addBeam(scene, &tricnt, &red, bx, by, bz, g, l, g);
addBeam(scene, &tricnt, &green, bx + g, by + l - g, bz, g, g, l); addBeam(scene, &tricnt, &green, bx + g, by + l - g, bz, g, g, l);
addBeam(scene, &tricnt, &blue, bx + g, by + l, bz + l - g, l, g, g); addBeam(scene, &tricnt, &blue, bx + g, by + l, bz + l - g, l, g, g);
*/
/* Chessboard /* Chessboard
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@ -315,6 +493,9 @@ int main() {
float aspect = (float)W / (float)H; float aspect = (float)W / (float)H;
for (int j = 0; j < H; ++j) { for (int j = 0; j < H; ++j) {
if (j % 10 == 0) {
printf("Rendered %d rows\n", j);
}
for (int i = 0; i < W; ++i) { for (int i = 0; i < W; ++i) {
Vec3 camOrigin = (Vec3){.x = 0, .y = 0, .z = 0}; Vec3 camOrigin = (Vec3){.x = 0, .y = 0, .z = 0};
@ -325,7 +506,7 @@ int main() {
u /= zoom; u /= zoom;
v /= zoom; v /= zoom;
float rconst = 0.00; float rconst = 0.0005;
float ur = (randfloat() - 0.5) * rconst; float ur = (randfloat() - 0.5) * rconst;
u += ur; u += ur;
@ -333,12 +514,14 @@ int main() {
v += vr; v += vr;
Vec3 camDir = (Vec3){.x = u, .y = v, .z = 1.0}; Vec3 camDir = (Vec3){.x = u, .y = v, .z = 1.0};
/* For penrose triangle
camDir = rotateX(&camDir, -0.76); camDir = rotateX(&camDir, -0.76);
camDir = rotateY(&camDir, -0.78539); camDir = rotateY(&camDir, -0.78539);
*/
camDir = vec3_norm(&camDir); camDir = vec3_norm(&camDir);
Ray camray = (Ray){.o = camOrigin, .d = camDir}; Ray camray = (Ray){.o = camOrigin, .d = camDir};
Vec3 col = trace(&camray, scene, tricnt, 4); Vec3 col = trace(&camray, scene, tricnt, 4);
uint8_t quant = 0xD0; uint8_t quant = 0xFF;
fputc((uint8_t)(0xFF * col.x) & quant, f); fputc((uint8_t)(0xFF * col.x) & quant, f);
fputc((uint8_t)(0xFF * col.y) & quant, f); fputc((uint8_t)(0xFF * col.y) & quant, f);
fputc((uint8_t)(0xFF * col.z) & quant, f); fputc((uint8_t)(0xFF * col.z) & quant, f);

1530
suzanne.obj Normal file

File diff suppressed because it is too large Load diff

9964
teapot.obj Normal file

File diff suppressed because it is too large Load diff