Integrated libpng (still need to autogenerate some files + I had not checked for error handling)
This commit is contained in:
parent
872381e686
commit
48882dd251
@ -39,8 +39,8 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c)
|
||||
add_executable(0_render_test src/l2/tests/r0/r0.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(0_render_test -lvulkan -lwayland-client -lm -lxkbcommon)
|
||||
|
||||
add_executable(0_render_test_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
|
||||
target_link_libraries(0_render_test_tex_init_prep -lm)
|
||||
add_executable(0r_tex_init_prep src/l2/tests/r0/r0_tex_init_prep.c)
|
||||
target_link_libraries(0r_tex_init_prep -lm -lpng)
|
||||
|
||||
add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon)
|
||||
|
||||
@ -422,6 +422,7 @@ void generate_geom_header() {
|
||||
VecU8_append_span(&res.result, cstr("#include \"../../src/l1/core/int_primitives.h\"\n"));
|
||||
VecU8_append_span(&res.result, cstr("#include <math.h>\n\n"));
|
||||
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(cstr("cvec"), cstr("U8")));
|
||||
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(cstr("uvec"), cstr("U32")));
|
||||
VecU8_append_vec(&res.result, generate_xvec234_structs_and_base_methods(cstr("ivec"), cstr("S32")));
|
||||
|
||||
VecU8_append_vec(&res.result, generate_xvec234_structs_and_cool_methods(cstr("vec"), cstr("float"), cstr("sqrtf")));
|
||||
|
||||
@ -80,4 +80,9 @@ float pow2f(float x) {
|
||||
return x * x;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
U32 width;
|
||||
U32 height;
|
||||
} SizeOfRectangleU32;
|
||||
|
||||
#endif
|
||||
|
||||
254
src/l2/margaret/png_pixel_masses.h
Normal file
254
src/l2/margaret/png_pixel_masses.h
Normal file
@ -0,0 +1,254 @@
|
||||
#ifndef PROTOTYPE1_SRC_L2_MARGARET_PNG_PIXEL_MASSES_H
|
||||
#define PROTOTYPE1_SRC_L2_MARGARET_PNG_PIXEL_MASSES_H
|
||||
|
||||
#include "../../../gen/l1/pixel_masses.h"
|
||||
#include "../../l1/core/util.h"
|
||||
#include "../../l1/core/VecU8_as_str.h"
|
||||
#include <png.h>
|
||||
|
||||
// todo: generate all of this automaticcally
|
||||
|
||||
void margaret_libpng_h_error_cb(png_structp pngshka, png_const_charp err) {
|
||||
printf("[!] %s\n", err);
|
||||
}
|
||||
|
||||
void margaret_libpng_h_warning_cb(png_structp pngshka, png_const_charp warning) {
|
||||
printf("[.] %s\n", warning);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
VecU8 err;
|
||||
} ResultVoidOrVecU8;
|
||||
|
||||
void ResultVoidOrVecU8_drop(ResultVoidOrVecU8 self) {
|
||||
if (self.variant == Result_Err)
|
||||
VecU8_drop(self.err);
|
||||
}
|
||||
|
||||
ResultVoidOrVecU8 TextureDataR8G8B8A8_write_to_png(const TextureDataR8G8B8A8* self, SpanU8 filename) {
|
||||
VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0);
|
||||
FILE *fp = fopen((CSTR)nt_filename.buf, "wb");
|
||||
VecU8_drop(nt_filename);
|
||||
if (!fp) {
|
||||
return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_fmt("Unable to open file %s", filename)};
|
||||
}
|
||||
png_structp pngshka = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);
|
||||
if (!pngshka)
|
||||
abortf("png_create_write_struct");
|
||||
png_infop info = png_create_info_struct(pngshka);
|
||||
if (!info)
|
||||
abortf("png_create_info_struct");
|
||||
|
||||
png_bytep* row_pointers = NULL;
|
||||
|
||||
if (setjmp(png_jmpbuf(pngshka))){
|
||||
png_destroy_write_struct(&pngshka, &info);
|
||||
fclose(fp);
|
||||
free(row_pointers);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr("Some png error happened")};
|
||||
}
|
||||
png_init_io(pngshka, fp);
|
||||
|
||||
U32 width = self->width;
|
||||
U32 height = TextureDataR8G8B8A8_get_height(self);
|
||||
|
||||
png_set_IHDR(pngshka, info, width, height, 8, PNG_COLOR_TYPE_RGBA,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
row_pointers = calloc(height, sizeof(row_pointers));
|
||||
for (U32 y = 0; y < height; y++) {
|
||||
row_pointers[height - 1 - y] = (png_bytep)((TextureDataR8G8B8A8_at(self, 0, y)));
|
||||
}
|
||||
png_set_rows(pngshka, info, row_pointers);
|
||||
png_write_png(pngshka, info, 0, NULL);
|
||||
/* No more errors */
|
||||
free(row_pointers);
|
||||
png_destroy_write_struct(&pngshka, &info);
|
||||
fclose(fp);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Ok};
|
||||
}
|
||||
|
||||
/* Aborts on error */
|
||||
void TextureDataR8G8B8A8_write_to_png_nofail(const TextureDataR8G8B8A8* self, SpanU8 filename) {
|
||||
ResultVoidOrVecU8 res = TextureDataR8G8B8A8_write_to_png(self, filename);
|
||||
if (res.variant == Result_Err) {
|
||||
SpanU8_fprint(VecU8_to_span(&res.err), stderr);
|
||||
abortf("TextureDataR8G8B8A8_write_to_png");
|
||||
}
|
||||
}
|
||||
|
||||
/* This structure will be pinned */
|
||||
typedef struct {
|
||||
FILE* fp;
|
||||
png_structp pngshka;
|
||||
png_infop info;
|
||||
png_infop end_info;
|
||||
} MargaretPromisedPngR8G8B8A8;
|
||||
|
||||
void MargaretPromisedPngR8G8B8A8_drop(MargaretPromisedPngR8G8B8A8 self) {
|
||||
png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);
|
||||
fclose(self.fp);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
union {
|
||||
MargaretPromisedPngR8G8B8A8 ok;
|
||||
VecU8 err;
|
||||
};
|
||||
} ResultMargaretPromisedPngR8G8B8A8OrVecU8;
|
||||
|
||||
void ResultMargaretPromisedPngR8G8B8A8OrVecU8_drop(ResultMargaretPromisedPngR8G8B8A8OrVecU8 self) {
|
||||
if (self.variant == Result_Ok)
|
||||
MargaretPromisedPngR8G8B8A8_drop(self.ok);
|
||||
else
|
||||
VecU8_drop(self.err);
|
||||
}
|
||||
|
||||
ResultMargaretPromisedPngR8G8B8A8OrVecU8 MargaretPromisedPngR8G8B8A8_begin(SpanU8 filename) {
|
||||
VecU8 nt_filename = VecU8_fmt("%s%c", filename, 0);
|
||||
FILE* fp = fopen((CSTR)nt_filename.buf, "rb");
|
||||
VecU8_drop(nt_filename);
|
||||
if (!fp) {
|
||||
return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Err,
|
||||
.err = VecU8_fmt("Unable to open file %s", filename)};
|
||||
}
|
||||
png_structp pngshka = png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, margaret_libpng_h_error_cb, margaret_libpng_h_warning_cb);
|
||||
if (!pngshka)
|
||||
abortf("png_create_read_struct");
|
||||
png_infop info = png_create_info_struct(pngshka);
|
||||
if (!info)
|
||||
abortf("png_create_info_struct");
|
||||
png_infop end_info = png_create_info_struct(pngshka);
|
||||
if (!end_info)
|
||||
abortf("png_create_info_struct");
|
||||
if (setjmp(png_jmpbuf(pngshka))) {
|
||||
png_destroy_read_struct(&pngshka, &info, &end_info);
|
||||
fclose(fp);
|
||||
return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Err,
|
||||
.err = VecU8_from_cstr("Some png error happened")};
|
||||
}
|
||||
png_init_io(pngshka, fp);
|
||||
png_read_info(pngshka, info);
|
||||
U32 width, height;
|
||||
int bit_depth, color_type;
|
||||
assert(png_get_IHDR(pngshka, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));
|
||||
|
||||
if (bit_depth == 16) {
|
||||
png_set_strip_16(pngshka);
|
||||
}
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
if (bit_depth == 1 || bit_depth == 2 || bit_depth == 4) {
|
||||
png_set_expand_gray_1_2_4_to_8(pngshka);
|
||||
}
|
||||
png_set_gray_to_rgb(pngshka);
|
||||
if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(pngshka);
|
||||
} else {
|
||||
png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
} else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
png_set_gray_to_rgb(pngshka);
|
||||
} else if (color_type == PNG_COLOR_TYPE_RGB) {
|
||||
if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(pngshka);
|
||||
} else {
|
||||
png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
} else if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(pngshka);
|
||||
|
||||
if (png_get_valid(pngshka, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(pngshka);
|
||||
} else {
|
||||
png_set_add_alpha(pngshka, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
}
|
||||
png_read_update_info(pngshka, info);
|
||||
|
||||
return (ResultMargaretPromisedPngR8G8B8A8OrVecU8){.variant = Result_Ok,
|
||||
.ok = (MargaretPromisedPngR8G8B8A8){.fp = fp, .pngshka = pngshka, .info = info, .end_info = end_info}};
|
||||
}
|
||||
|
||||
SizeOfRectangleU32 MargaretPromisedPngR8G8B8A8_get_extent(const MargaretPromisedPngR8G8B8A8* self) {
|
||||
U32 width, height;
|
||||
int bit_depth, color_type;
|
||||
assert(png_get_IHDR(self->pngshka, self->info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL));
|
||||
return (SizeOfRectangleU32){width, height};
|
||||
}
|
||||
|
||||
|
||||
size_t MargaretPromisedPngR8G8B8A8_get_needed_buffer_size(const MargaretPromisedPngR8G8B8A8* self) {
|
||||
SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(self);
|
||||
return 4 * dim.width * dim.height;
|
||||
}
|
||||
|
||||
ResultVoidOrVecU8 MargaretPromisedPngR8G8B8A8_finish(MargaretPromisedPngR8G8B8A8 self, void* buffer) {
|
||||
SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(&self);
|
||||
|
||||
png_bytep* row_pointers = NULL;
|
||||
if (setjmp(png_jmpbuf(self.pngshka))) {
|
||||
png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);
|
||||
fclose(self.fp);
|
||||
free(row_pointers);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Err, .err = VecU8_from_cstr("Some png error happened")};
|
||||
}
|
||||
|
||||
row_pointers = calloc(dim.height, sizeof(row_pointers));
|
||||
for (U32 y = 0; y < dim.height; y++) {
|
||||
row_pointers[y] = ((png_bytep)buffer) + 4 * dim.width * y;
|
||||
}
|
||||
png_read_image(self.pngshka, row_pointers);
|
||||
png_read_end(self.pngshka, self.end_info);
|
||||
/* No more errors */
|
||||
png_destroy_read_struct(&self.pngshka, &self.info, &self.end_info);
|
||||
fclose(self.fp);
|
||||
free(row_pointers);
|
||||
return (ResultVoidOrVecU8){.variant = Result_Ok};
|
||||
}
|
||||
|
||||
// todo: move it to pixel_masses.h (and also generate result types automatically
|
||||
typedef struct {
|
||||
Result_variant variant;
|
||||
union {
|
||||
TextureDataR8G8B8A8 ok;
|
||||
VecU8 err;
|
||||
};
|
||||
} ResultTextureDataR8G8B8A8OrVecU8;
|
||||
|
||||
void ResultTextureDataR8G8B8A8OrVecU8_drop(ResultTextureDataR8G8B8A8OrVecU8 self) {
|
||||
if (self.variant == Result_Ok)
|
||||
TextureDataR8G8B8A8_drop(self.ok);
|
||||
else
|
||||
VecU8_drop(self.err);
|
||||
}
|
||||
|
||||
ResultTextureDataR8G8B8A8OrVecU8 MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(MargaretPromisedPngR8G8B8A8 self) {
|
||||
SizeOfRectangleU32 dim = MargaretPromisedPngR8G8B8A8_get_extent(&self);
|
||||
TextureDataR8G8B8A8 tex = TextureDataR8G8B8A8_new(dim.width, dim.height);
|
||||
ResultVoidOrVecU8 res = MargaretPromisedPngR8G8B8A8_finish(self, tex.pixels.buf);
|
||||
if (res.variant == Result_Err)
|
||||
return (ResultTextureDataR8G8B8A8OrVecU8){.variant = Result_Err, .err = res.err};
|
||||
return (ResultTextureDataR8G8B8A8OrVecU8){.variant = Result_Ok, .ok = tex};
|
||||
}
|
||||
|
||||
/* aborts on error */
|
||||
TextureDataR8G8B8A8 TextureDataR8G8B8A8_read_from_png_nofail(SpanU8 name) {
|
||||
ResultMargaretPromisedPngR8G8B8A8OrVecU8 res_1 = MargaretPromisedPngR8G8B8A8_begin(name);
|
||||
if (res_1.variant == Result_Err) {
|
||||
SpanU8_fprint(VecU8_to_span(&res_1.err), stderr);
|
||||
abortf("MargaretPromisedPngR8G8B8A8_begin");
|
||||
}
|
||||
/* res_1 invalidated, we moved ownership to _finish methos */
|
||||
ResultTextureDataR8G8B8A8OrVecU8 res_2 = MargaretPromisedPngR8G8B8A8_finish_into_TextureDataR8G8B8A8(res_1.ok);
|
||||
if (res_2.variant == Result_Err) {
|
||||
SpanU8_fprint(VecU8_to_span(&res_2.err), stderr);
|
||||
abortf("MargaretPromisedPngR8G8B8A8_finish (into TextureData)");
|
||||
}
|
||||
return res_2.ok;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -611,11 +611,13 @@ TextureDataR8 generate_tex_template_for_one_fourth_of_a_cylinder(float s_resol,
|
||||
*Vecvec2_mat(&P, i) = vec2_mul_vec2(*Vecvec2_at(&P, i), cord_resol);
|
||||
}
|
||||
TextureDataR8_draw_perimeter_maxing(&res, Vecvec2_to_span(&P));
|
||||
Vecvec2_drop(P);
|
||||
|
||||
Bublazhuzhka crap_on_back_side = fill_rectangle_with_crap(w, r);
|
||||
// todo: draw bublazhuzhka pixel-by-pixel myself
|
||||
Bublazhuzhka_TextureDataR8_draw_maxing(&crap_on_back_side, &res,
|
||||
(mat3x2){.x.x = cord_resol.x, .y.y = cord_resol.y, .z = vec2_mul_vec2((vec2){r, r}, cord_resol)});
|
||||
Bublazhuzhka_drop(crap_on_back_side);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -648,6 +650,7 @@ TextureDataR8G8B8 generate_normal_tex_for_one_fourth_of_a_cylinder(float s_resol
|
||||
(FnHeightMapGradFlatSurfCallback){.fn = height_map_cb_that_uses_bublazhuzhka, .guest = &crap_on_the_back_side});
|
||||
draw_polygon_on_normal_texture_flat_param_surf(&res, (vec2){0, 0}, (vec2){0, r}, (vec2){w, r}, trop_back_side, orient_back_side,
|
||||
(FnHeightMapGradFlatSurfCallback){.fn = height_map_cb_that_uses_bublazhuzhka, .guest = &crap_on_the_back_side});
|
||||
Bublazhuzhka_drop(crap_on_the_back_side);
|
||||
|
||||
mat3x2 str = {.x.x = cord_resol.x, .y.y = cord_resol.y};
|
||||
draw_polygon_on_normal_texture_absolutely_flat(&res, v0tex, v1tex, v4tex, str, (vec3){0, -1, 0});
|
||||
|
||||
@ -1,44 +1,61 @@
|
||||
#include "r0_assets.h"
|
||||
#include "../../marie/rasterization.h"
|
||||
#include "../../margaret/png_pixel_masses.h"
|
||||
|
||||
void draw_cool_triangle_h_frag(void* ug, S32 x, S32 y, MarieVertAttr attr_col) {
|
||||
TextureDataR8G8B8* tex = (TextureDataR8G8B8*)ug;
|
||||
if (TextureDataR8G8B8_is_inside(tex, x, y)) {
|
||||
*TextureDataR8G8B8_mat(tex, x, y) = (cvec3){255, (S32)roundf(attr_col.x * 255), (S32)roundf(attr_col.y * 255)};
|
||||
// todo: move it to some other file
|
||||
void TextureDataR8G8B8A8_print(const TextureDataR8G8B8A8* self) {
|
||||
U64 width = self->width;
|
||||
U64 height = TextureDataR8G8B8A8_get_height(self);
|
||||
U64 cell_width = MAX_U64(1, width / 350);
|
||||
U64 cell_height = MAX_U64(1, cell_width * 14 / 8);
|
||||
for (U64 CY = 0; CY < height; CY += cell_height) {
|
||||
for (U64 CX = 0; CX < width; CX += cell_width) {
|
||||
float lum = 0;
|
||||
for (U64 j = 0; j < cell_height; j++) {
|
||||
U64 y = cell_height * CY + j;
|
||||
if (y >= height)
|
||||
continue;
|
||||
for (U64 i = 0; i < cell_width; i++) {
|
||||
U64 x = cell_width * CX + i;
|
||||
if (x >= width)
|
||||
continue;
|
||||
cvec4 pix = *TextureDataR8G8B8A8_at(self, x, y);
|
||||
lum += (float)pix.x / 255 * 0.21f + (float)pix.y / 255 * 0.71f + (float)pix.z / 255 * 0.08f;
|
||||
}
|
||||
}
|
||||
lum /= (float)cell_width * (float)cell_height;
|
||||
printf("%s", lum > 0.95 ? "@" : (lum > 0.8 ? "#" : (lum > 0.65 ? "*" : (lum > 0.4 ? "_" : (lum > 0.2 ? "." : " ")))));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void draw_cool_triangle(TextureDataR8G8B8* tex, vec2 A, vec2 B, vec2 C) {
|
||||
marie_rasterize_triangle_with_attr((MariePlaneVertAttr){.pos = A, .attr = {A.x / 1000, A.y / 1000, 0, 1}},
|
||||
(MariePlaneVertAttr){.pos = B, .attr = {B.x / 1000, B.y / 1000, 0, 1}},
|
||||
(MariePlaneVertAttr){.pos = C, .attr = {C.x / 1000, C.y / 1000, 0, 1}},
|
||||
(FnMarieRasterizerCallback){.fn = draw_cool_triangle_h_frag, .guest = (void*)tex});
|
||||
void model_1_template() {
|
||||
TextureDataR8 tex_1 = generate_tex_template_for_one_fourth_of_a_cylinder(120, 10, 2, 6);
|
||||
TextureDataR8G8B8A8 tex_1_big = TextureDataR8G8B8A8_new(tex_1.width, TextureDataR8_get_height(&tex_1));
|
||||
for (size_t i = 0; i < tex_1.pixels.len; i++) {
|
||||
U8 g = *VecU8_at(&tex_1.pixels, i);
|
||||
*Veccvec4_mat(&tex_1_big.pixels, i) = (cvec4){g, g, g, 255};
|
||||
}
|
||||
TextureDataR8G8B8A8_write_to_png_nofail(&tex_1_big, cstr("textures/log_10_2_6_TEMPLATE.png"));
|
||||
TextureDataR8G8B8A8_drop(tex_1_big);
|
||||
TextureDataR8_drop(tex_1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
TextureDataR8 tex_1 = generate_tex_template_for_one_fourth_of_a_cylinder(120, 10, 2, 6);
|
||||
TextureDataR8_write_to_file(&tex_1, "log_10_2_6_TEMPLATE.a8");
|
||||
TextureDataR8_drop(tex_1);
|
||||
void model_1_normal() {
|
||||
TextureDataR8G8B8 tex_2 = generate_normal_tex_for_one_fourth_of_a_cylinder(120, 10, 2, 6);
|
||||
TextureDataR8G8B8A8 tex_2_big = TextureDataR8G8B8A8_new(tex_2.width, TextureDataR8G8B8_get_height(&tex_2));
|
||||
for (size_t i = 0; i < tex_2.pixels.len; i++) {
|
||||
cvec3 rgb = *Veccvec3_at(&tex_2.pixels, i);
|
||||
*Veccvec4_mat(&tex_2_big.pixels, i) = (cvec4){rgb.x, rgb.y, rgb.z, 255};
|
||||
}
|
||||
TextureDataR8G8B8A8_write_to_file(&tex_2_big, "log_10_2_6_NORMAL.r8g8b8a8");
|
||||
TextureDataR8G8B8A8_write_to_png_nofail(&tex_2_big, cstr("textures/log_10_2_6_NORMAL.png"));
|
||||
TextureDataR8G8B8A8_drop(tex_2_big);
|
||||
TextureDataR8G8B8_drop(tex_2);
|
||||
}
|
||||
|
||||
// TextureDataR8G8B8 t = TextureDataR8G8B8_new(1000, 1000);\
|
||||
// vec2 center = {500, 500};
|
||||
// for (int i = 0; i < 70; i++) {
|
||||
// float a1 = (float)i * 2 * M_PIf / 70;
|
||||
// float a2 = (float)(i + 1) * 2 * M_PIf / 70;
|
||||
// vec2 A = vec2_add_vec2(center, vec2_mul_scal((vec2){cosf(a1), sinf(a1)}, 480));
|
||||
// vec2 B = vec2_add_vec2(center, vec2_mul_scal((vec2){cosf(a2), sinf(a2)}, 480));
|
||||
// draw_cool_triangle(&t, B, A, center);
|
||||
// }
|
||||
// TextureDataR8G8B8_write_to_file(&t, "experiment.r8g8b8");
|
||||
// TextureDataR8G8B8_drop(t);
|
||||
int main() {
|
||||
model_1_template();
|
||||
model_1_normal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 25 KiB |
Loading…
x
Reference in New Issue
Block a user