demo/lizard: in-person game jam event version

This commit is contained in:
Zack Buhman 2025-07-29 17:14:21 -05:00
parent e2a005d2b9
commit 151e4342f3
43 changed files with 1446 additions and 30 deletions

2
.gitignore vendored
View File

@ -13,3 +13,5 @@ __pycache__
*.blend1
*.scramble
*.FCStd1
*.data
*_128.png

15
build_textures.sh Normal file
View File

@ -0,0 +1,15 @@
set -eux
for i in texture/*.png; do
j=$(echo $i | cut -d. -f1).data
python ~/model_generator/color_convert.py $i rgb565 twiddled non_mipmapped $j
make ${j}.h
done
rm -f texture/walking/*128.png
for i in texture/walking/*.png; do
j=$(echo $i | cut -d. -f1)
python ~/physics_engine/tools/canvas_size.py $i 128 32 ${j}_128.png
python ~/model_generator/color_convert.py ${j}_128.png argb4444 twiddled non_mipmapped ${j}_128.data
make ${j}_128.data.h
done

28
demo.mk
View File

@ -1,6 +1,18 @@
FONT_OBJ = \
font/ter_u12n.data.o
TEXTURE_OBJ = \
texture/igh25_box_top_32.data.o \
texture/igh25_box_bottom_32.data.o \
texture/igh25_box_side_32.data.o \
texture/walking/frame0000_128.data.o \
texture/walking/frame0001_128.data.o \
texture/walking/frame0002_128.data.o \
texture/walking/frame0003_128.data.o \
texture/walking/frame0004_128.data.o \
texture/walking/frame0005_128.data.o \
texture/walking/frame0006_128.data.o
DEMO_OBJ = \
$(LIB)/holly/core.o \
$(LIB)/holly/region_array.o \
@ -23,6 +35,8 @@ DEMO_OBJ = \
src/demo/bridge.o \
src/demo/sailboat.o \
src/demo/collision.o \
src/demo/lizard/main.o \
src/demo/lizard/world.o \
src/physics/particle.o \
src/physics/particle_link.o \
src/physics/particle_contact.o \
@ -31,4 +45,16 @@ DEMO_OBJ = \
src/physics/collide.o
demo.elf: LDSCRIPT = $(LIB)/main.lds
demo.elf: $(START_OBJ) $(DEMO_OBJ) $(FONT_OBJ) $(LIBGCC)
demo.elf: $(START_OBJ) $(DEMO_OBJ) $(FONT_OBJ) $(TEXTURE_OBJ) $(LIBGCC)
%_128.png: %.png
python tools/canvas_size.py $< 128 32 $@
texture/igh25_box_%.data: texture/igh25_box_%.png
python ../model_generator/color_convert.py $< rgb565 twiddled non_mipmapped $@
texture/walking/%.data: texture/walking/%.png
python ../model_generator/color_convert.py $< argb4444 twiddled non_mipmapped $@
font/ter_u12n.data:
$(LIB)/tools/ttf_bitmap2 20 7f 128 64 /usr/share/fonts/terminus/ter-u12n.otb $@ > /dev/null

Binary file not shown.

View File

@ -102,7 +102,7 @@ namespace demo {
printf("en cables %d\n", en_cables);
}
void bridge::analog(float dx) {
void bridge::analog(float dl, float dr, float dx, float dy) {
interpolator.interp_add(dx * 0.5f);
}

View File

@ -25,7 +25,7 @@ namespace demo {
void draw_weight(ta_parameter_writer& writer, const mat4x4& trans);
void draw(ta_parameter_writer& writer, const mat4x4& trans) override;
void a() override;
void analog(float dx) override;
void analog(float dl, float dr, float dx, float dy) override;
static const inline int particles_length = 12;
physics::particle particles[particles_length];

View File

@ -0,0 +1,28 @@
#include "demo/lizard/world.hpp"
namespace demo {
world::platform level1_platforms[] = {
{
.position = vec3( 7.500, 0.000, 7.500),
.scale = vec3( 3.000, 1.000, 3.000),
},
{
.position = vec3( 12.500, 0.000, 7.500),
.scale = vec3( 3.000, 1.000, 3.000),
},
{
.position = vec3( 17.500, 0.000, 7.500),
.scale = vec3( 3.000, 1.000, 3.000),
},
{
.position = vec3( 12.500, 0.000, 12.500),
.scale = vec3( 3.000, 1.000, 3.000),
},
};
world::level level1_level = {
.platforms = level1_platforms,
.platforms_length = (sizeof (level1_platforms)) / (sizeof (world::platform)),
};
}

228
src/demo/lizard/main.cpp Normal file
View File

@ -0,0 +1,228 @@
#include "math/float_types.hpp"
#include "math/transform.hpp"
#include "platform/graphics_primitive.hpp"
#include "platform/font.hpp"
#include "demo/lizard/main.hpp"
#include "demo/lizard/levels.hpp"
#include "texture/igh25_box_top_32.data.h"
#include "assert.h"
extern float alpha_mul;
const int lizard_frames[] = {
texture::offset::walking_frame0000,
texture::offset::walking_frame0001,
texture::offset::walking_frame0002,
texture::offset::walking_frame0003,
texture::offset::walking_frame0004,
texture::offset::walking_frame0005,
texture::offset::walking_frame0006,
};
const int lizard_frames_count = (sizeof (lizard_frames)) / (sizeof (lizard_frames[0]));
int last_drawn_frame;
namespace demo {
static inline void print_mat4x4(const mat4x4& mat)
{
for (int i = 0; i < 4; i++) {
printf("%f %f %f %f\n", mat[i][0], mat[i][1], mat[i][2], mat[i][3]);
}
}
mat4x4 lizard::init()
{
vx = 0;
vy = 0;
current_level = &demo::level1_level;
world::table_build(*current_level);
lizard_position = {7.5, 1, 7.5};
lizard_velocity = {0, 0, 0};
return view_trans;
}
static float sign(float n)
{
if (n > 0)
return 1;
else
return -1;
}
void lizard::update()
{
/*
if (!collided)
lizard_velocity.y -= 0.01;
*/
if (abs(lizard_velocity.x) > 0.05)
lizard_velocity.x = 0.05 * sign(lizard_velocity.x);
if (abs(lizard_velocity.y) > 0.05)
lizard_velocity.y = 0.05 * sign(lizard_velocity.y);
if (abs(lizard_velocity.z) > 0.05)
lizard_velocity.z = 0.05 * sign(lizard_velocity.z);
lizard_velocity.x *= 0.8;
lizard_velocity.y *= 0.8;
lizard_velocity.z *= 0.8;
lizard_frame += magnitude(lizard_velocity) * 15;
lizard_position.x += lizard_velocity.x;
lizard_position.y += lizard_velocity.y;
lizard_position.z += lizard_velocity.z;
world::platform * p = lizard_collide();
collided = p != nullptr;
if (collided) {
lizard_position.y -= -lizard_velocity.y;
}
view_trans
= translate(vec3(0, 0, 3))
* rotate_x(vy)
* rotate_y(vx)
* translate(-lizard_position);
}
void lizard::y()
{
lizard_velocity.y += 0.01;
}
void lizard::a()
{
lizard_velocity.y -= 0.01;
}
void lizard::x()
{
lizard_heading -= pi * (1.0f / 160);
}
void lizard::b()
{
lizard_heading += pi * (1.0f / 160);
}
void lizard::analog(float dl, float dr, float dx, float dy)
{
//float forward = (dr - dl) * -0.001f;
//alpha_mul += forward;
float forward = (dr - dl) * -0.04f;
lizard_velocity.x += -cos(lizard_heading) * forward;
lizard_velocity.z += sin(lizard_heading) * forward;
vy += dy * 0.03f;
vx += dx * 0.03f;
}
world::platform * lizard::lizard_collide()
{
world::platform * p = world::table_lookup(lizard_position.x, lizard_position.z);
if (p == nullptr)
return nullptr;
float ym = lizard_position.y - 0.5;
float yp = lizard_position.y + 0.5;
float pm = p->position.y - p->scale.y * 0.5;
float pp = p->position.y + p->scale.y * 0.5;
if (ym < pp && yp > pm)
return p;
else
return nullptr;
}
void lizard::draw_hud(ta_parameter_writer& writer)
{
const int title_length = 8;
const int title_width_2 = (font::ter_u12n.hori_advance * title_length) >> 1;
const int framebuffer_width_2 = framebuffer::framebuffer.px_width >> 1;
const int x = framebuffer_width_2 - title_width_2;
vec3 center_p = vec3(x, 5, 10);
font::ter_u12n.global(writer);
font::ter_u12n.draw_string(writer, center_p, "platform", 0xffffffff);
vec3 status_p = vec3(10, 10, 10);
/*
if (collided)
font::ter_u12n.draw_string(writer, status_p, "collide", 0xffffffff);
else
font::ter_u12n.draw_string(writer, status_p, "air", 0xffffffff);
*/
font::ter_u12n.draw_float(writer, status_p, (float)last_drawn_frame, 0xffffffff, 10);
}
void lizard::draw_platform(ta_parameter_writer& writer, const mat4x4& trans, const world::platform& p)
{
mat4x4 t
= trans
* translate(p.position)
* scale(p.scale);
draw_textured_cube(writer,
t,
p.scale,
texture::cube_type_1);
}
void lizard::draw_lizard(ta_parameter_writer& writer, const mat4x4& trans)
{
mat4x4 t
= trans
* translate(lizard_position)
* rotate_y(lizard_heading);
/*
draw_icosphere(writer,
t,
vec3(1, 0.5, 0));
*/
int frame = ((int)lizard_frame) % lizard_frames_count;
if (frame < 0)
frame = lizard_frames_count + frame;
last_drawn_frame = frame;
draw_textured_voxel(writer,
t,
lizard_frames[frame]);
}
void lizard::draw(ta_parameter_writer& writer, const mat4x4& _)
{
// punch through
const mat4x4& trans = view_trans;
draw_hud(writer);
draw_lizard(writer, trans);
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
// opaque
//draw_axis(writer, trans * translate(lizard_position));
for (int i = 0; i < current_level->platforms_length; i++) {
draw_platform(writer, trans, current_level->platforms[i]);
}
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
}
}

40
src/demo/lizard/main.hpp Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include "demo/scene.hpp"
#include "demo/lizard/world.hpp"
namespace demo {
struct lizard : scene {
world::level * current_level;
vec3 lizard_position;
vec3 lizard_velocity;
float lizard_heading;
float lizard_frame;
bool collided;
mat4x4 view_trans;
float vx;
float vy;
mat4x4 init() override;
void update() override;
void y() override;
void x() override;
void b() override;
void a() override;
void analog(float dl, float dr, float dx, float dy) override;
world::platform * lizard_collide();
void draw_hud(ta_parameter_writer& writer);
void draw_platform(ta_parameter_writer& writer, const mat4x4& trans, const world::platform& p);
void draw_lizard(ta_parameter_writer& writer, const mat4x4& trans);
void draw(ta_parameter_writer& writer, const mat4x4& trans) override;
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

109
src/demo/lizard/world.cpp Normal file
View File

@ -0,0 +1,109 @@
#include <limits>
#include "demo/lizard/world.hpp"
#include "assert.h"
namespace demo::world {
struct min_max {
int x_min;
int x_max;
int z_min;
int z_max;
};
static platform_lookup lookup;
static inline void clear_table()
{
for (int i = 0; i < lookup_table_dim * lookup_table_dim; i++) {
lookup.table[i] = nullptr;
}
}
static inline bool float_equal_int(float f)
{
int i = (int)f;
float fi = (float)i;
return fi == f;
}
static inline min_max calculate_platforms_area(const level& level)
{
float x_min = std::numeric_limits<float>::max();
float x_max = std::numeric_limits<float>::min();
float z_min = std::numeric_limits<float>::max();
float z_max = std::numeric_limits<float>::min();
for (int i = 0; i < level.platforms_length; i++) {
const vec3& position = level.platforms[i].position;
float scale_x_2 = level.platforms[i].scale.x * 0.5;
float scale_z_2 = level.platforms[i].scale.z * 0.5;
if (position.x - scale_x_2 < x_min)
x_min = position.x - scale_x_2;
if (position.x + scale_x_2 > x_max)
x_max = position.x + scale_x_2;
if (position.z - scale_z_2 < z_min)
z_min = position.z - scale_z_2;
if (position.z + scale_z_2 > z_max)
z_max = position.z + scale_z_2;
}
assert(float_equal_int(x_min));
assert(float_equal_int(x_max));
assert(float_equal_int(z_min));
assert(float_equal_int(z_max));
return {
(int)x_min,
(int)x_max,
(int)z_min,
(int)z_max,
};
}
void table_build(const level& level)
{
clear_table();
min_max mm = calculate_platforms_area(level);
lookup.xz_offset = vec2i(mm.x_min, mm.z_min);
lookup.size = vec2i(mm.x_max - mm.x_min,
mm.z_max - mm.z_min);
for (int i = 0; i < level.platforms_length; i++) {
const vec3& position = level.platforms[i].position;
int scale_x = (int)level.platforms[i].scale.x;
int scale_z = (int)level.platforms[i].scale.z;
float scale_x_2 = level.platforms[i].scale.x * 0.5;
float scale_z_2 = level.platforms[i].scale.z * 0.5;
for (int xo = 0; xo < scale_x; xo++) {
for (int zo = 0; zo < scale_z; zo++) {
int x = xo + (int)(position.x - scale_x_2) - mm.x_min;
int z = zo + (int)(position.z - scale_z_2) - mm.z_min;
assert(x >= 0);
assert(z >= 0);
assert(x < lookup.size.x);
assert(z < lookup.size.y);
lookup.table[z * lookup.size.x + x] = &level.platforms[i];
}
}
}
}
platform * table_lookup(float x, float z)
{
int xi = ((int)x) - lookup.xz_offset.x;
int zi = ((int)z) - lookup.xz_offset.y;
if (xi < 0 || zi < 0 || xi >= lookup.size.x || zi >= lookup.size.y) {
return nullptr;
}
return lookup.table[zi * lookup.size.x + xi];
}
}

29
src/demo/lizard/world.hpp Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include "math/float_types.hpp"
namespace demo::world {
using vec2i = vec<2, int>;
struct platform {
vec3 position;
vec3 scale;
};
struct level {
platform * platforms;
int platforms_length;
};
constexpr int lookup_table_dim = 128;
struct platform_lookup {
vec2i xz_offset;
vec2i size;
platform * table[lookup_table_dim * lookup_table_dim];
};
void table_build(const level& level);
platform * table_lookup(float x, float z);
}

View File

@ -7,11 +7,15 @@ namespace demo {
struct scene {
virtual mat4x4 init() = 0;
virtual void analog(float dx) {}
virtual void analog(float dl, float dr, float dx, float dy) {}
virtual void a() {}
virtual void b() {}
virtual void x() {}
virtual void y() {}
virtual void ra() {}
virtual void la() {}
virtual void da() {}
virtual void ua() {}
virtual void update() = 0;
virtual void draw(ta_parameter_writer& writer, const mat4x4& trans) = 0;
};

View File

@ -83,10 +83,10 @@ namespace font {
int32_t whole = num;
offset += unparse_base10_unsigned(&s[offset], whole, 0, 0);
s[offset++] = '.';
int32_t fraction = (int32_t)((num - (float)whole) * 1000.0);
int32_t fraction = (int32_t)((num - (float)whole) * 1000000000.0);
if (fraction < 0)
fraction = -fraction;
offset += unparse_base10_unsigned(&s[offset], fraction, 3, '0');
offset += unparse_base10_unsigned(&s[offset], fraction, 9, '0');
return offset;
}

View File

@ -27,6 +27,7 @@
#include "demo/bridge.hpp"
#include "demo/sailboat.hpp"
#include "demo/collision.hpp"
#include "demo/lizard/main.hpp"
#include "maple/maple_bus_bits.hpp"
@ -94,14 +95,19 @@ namespace graphics {
}
}
/*
demo::ballistics _ballistics;
demo::bridge _bridge;
demo::sailboat _sailboat;
demo::collision _collision;
demo::scene * current_scene = &_collision;
*/
demo::lizard _lizard;
demo::scene * current_scene = &_lizard;
void draw()
{
holly.PT_ALPHA_REF = 15;
current_scene->draw(writer, view_trans * scale(0.05f));
}
@ -172,25 +178,39 @@ namespace graphics {
auto& data = data_fields.data;
float dx = static_cast<float>(data.analog_coordinate_axis[2] - 0x80) * 0.001;
float dy = static_cast<float>(data.analog_coordinate_axis[3] - 0x80) * 0.001;
float dl = static_cast<float>(data.analog_coordinate_axis[0]) * (1.f / 255.f);
float dr = static_cast<float>(data.analog_coordinate_axis[1]) * (1.f / 255.f);
float dx = static_cast<float>(data.analog_coordinate_axis[2] - 0x80) * (1.f / 128.f);
float dy = static_cast<float>(data.analog_coordinate_axis[3] - 0x80) * (1.f / 128.f);
bool a = ft0::data_transfer::digital_button::a(data.digital_button) == 0;
bool b = ft0::data_transfer::digital_button::b(data.digital_button) == 0;
bool x = ft0::data_transfer::digital_button::x(data.digital_button) == 0;
bool y = ft0::data_transfer::digital_button::y(data.digital_button) == 0;
if (last[port_ix].a == 0 && a) current_scene->a();
if (last[port_ix].b == 0 && b) current_scene->b();
if (last[port_ix].x == 0 && x) current_scene->x();
if (last[port_ix].y == 0 && y) current_scene->y();
bool ra = ft0::data_transfer::digital_button::ra(data.digital_button) == 0;
bool la = ft0::data_transfer::digital_button::la(data.digital_button) == 0;
bool da = ft0::data_transfer::digital_button::da(data.digital_button) == 0;
bool ua = ft0::data_transfer::digital_button::ua(data.digital_button) == 0;
if (a) current_scene->a();
if (b) current_scene->b();
if (x) current_scene->x();
if (y) current_scene->y();
if (ra) current_scene->ra();
if (la) current_scene->la();
if (da) current_scene->da();
if (ua) current_scene->ua();
last[port_ix].a = a;
last[port_ix].b = b;
last[port_ix].x = x;
last[port_ix].y = y;
current_scene->analog(dx);
current_scene->analog(dl, dr, dx, dy);
view_trans = view_trans * rotate_y(dy);// * rotate_x(dx);
//view_trans = rotate_y(dy) * view_trans;// * rotate_x(dx);
}
}
}

View File

@ -154,7 +154,7 @@ void draw_icosphere(ta_parameter_writer& writer,
const vec3& ap = position_cache[tris[i].a];
const vec3& bp = position_cache[tris[i].b];
const vec3& cp = position_cache[tris[i].c];
const float& intensity = _intensity(trans, normal[tris[i].n]);
const float intensity = _intensity(trans, normal[tris[i].n]);
tri_type_2(writer,
ap,
@ -261,3 +261,289 @@ void draw_halfspace(ta_parameter_writer& writer,
dp,
1.0f);
}
void draw_textured_cube(ta_parameter_writer& writer,
const mat4x4& trans,
const vec3& scale,
const texture::cube_texture_offsets& offsets)
{
static const vec3 position[] = {
{-0.5, -0.5, 0.5},
{-0.5, 0.5, 0.5},
{-0.5, -0.5, -0.5},
{-0.5, 0.5, -0.5},
{ 0.5, -0.5, 0.5},
{ 0.5, 0.5, 0.5},
{ 0.5, -0.5, -0.5},
{ 0.5, 0.5, -0.5},
};
static const vec3 normal[] = {
{-1.0, -0.0, -0.0},
{-0.0, -0.0, -1.0},
{ 1.0, -0.0, -0.0},
{-0.0, -0.0, 1.0},
{-0.0, -1.0, -0.0},
{-0.0, 1.0, -0.0},
};
static const vec2 texture[] = {
{0.0, 0.0},
{1.0, 0.0},
{1.0, 1.0},
{0.0, 1.0},
};
const int position_length = (sizeof (position)) / (sizeof (position[0]));
struct quad {
int a, b, c, d;
};
static const quad quads[] = {
{0, 1, 3, 2}, // front (z, y)
{2, 3, 7, 6}, // left (x, y)
{6, 7, 5, 4}, // rear (z, y)
{4, 5, 1, 0}, // right (x, y)
{2, 6, 4, 0}, // bottom (x, z)
{7, 3, 1, 5} // top (x, z)
};
const vec2 uv_scale[] = {
{scale.z, scale.y},
{scale.x, scale.y},
{scale.z, scale.y},
{scale.x, scale.y},
{scale.z, scale.x},
{scale.z, scale.x},
};
const int quads_length = (sizeof (quads)) / (sizeof (quads[0]));
vec3 position_cache[position_length];
for (int i = 0; i < position_length; i++) {
position_cache[i] = trans * position[i];
}
int texture_uv_size
= tsp_instruction_word::texture_shading_instruction::decal
| tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::texture_u_size::from_int(32)
| tsp_instruction_word::texture_v_size::from_int(32);
int pixel_format
= texture_control_word::pixel_format::_565;
const vec4 color = {0, 0, 0, 0};
global_polygon_textured_intensity(writer,
color,
para_control::list_type::opaque,
offsets.side,
texture_uv_size,
pixel_format);
for (int i = 0; i < quads_length; i++) {
if (i == 4)
global_polygon_textured_intensity(writer,
color,
para_control::list_type::opaque,
offsets.bottom,
texture_uv_size,
pixel_format);
if (i == 5)
global_polygon_textured_intensity(writer,
color,
para_control::list_type::opaque,
offsets.top,
texture_uv_size,
pixel_format);
const vec3& ap = position_cache[quads[i].a];
const vec3& bp = position_cache[quads[i].b];
const vec3& cp = position_cache[quads[i].c];
const vec3& dp = position_cache[quads[i].d];
const vec2& at = texture[3] * uv_scale[i];
const vec2& bt = texture[0] * uv_scale[i];
const vec2& ct = texture[1] * uv_scale[i];
const vec2& dt = texture[2] * uv_scale[i];
const float base_intensity = _intensity(trans, normal[i]);
quad_type_7_maybe_clip(writer,
ap, at,
bp, bt,
cp, ct,
dp, dt,
base_intensity);
}
}
constexpr inline float pow(float x, int n)
{
for (int i = 0; i < n; i++)
x *= x;
return x;
}
float alpha_mul = 0.9;
void draw_textured_voxel(ta_parameter_writer& writer,
const mat4x4& trans,
int texture_offset)
{
static const vec3 position[] = {
{-0.5, 0.5, 0.0},
{ 0.5, 0.5, 0.0},
{ 0.5, -0.5, 0.0},
{-0.5, -0.5, 0.0},
};
static const vec2 texture[] = {
{0.0, 0.0},
{1.0, 0.0},
{1.0, 1.0},
{0.0, 1.0},
};
const int position_length = (sizeof (position)) / (sizeof (position[0]));
const vec3 pos_scale = {96 / 32, 1.0f, 1.0f};
const vec2 uv_scale = {96.0f / 128.0f, 1.0};
vec3 position_cache[position_length];
for (int i = 0; i < position_length; i++) {
position_cache[i] = trans * (position[i] * pos_scale);
}
int texture_uv_size
= tsp_instruction_word::texture_shading_instruction::modulate_alpha
| tsp_instruction_word::src_alpha_instr::src_alpha
| tsp_instruction_word::dst_alpha_instr::inverse_src_alpha
| tsp_instruction_word::texture_u_size::from_int(128)
| tsp_instruction_word::texture_v_size::from_int(32)
| tsp_instruction_word::use_alpha;
int pixel_format
= texture_control_word::pixel_format::_4444;
const float table[] = {
0.063,
0.063,
0.063,
0.074,
0.077, // after purple
0.077, // after purple
0.077, // after purple
0.077, // after purple
0.077, // after purple
0.084, // purple
0.084, // purple
0.084, // purple
0.084, // purple
0.084, // purple
0.090,
0.090,
0.090,
0.100,
0.100,
0.100,
0.111,
0.111,
0.111,
0.129,
0.129,
0.129,
0.148,
0.148,
0.148,
0.180,
0.180,
0.180,
0.440, // green
0.440, // green
0.440, // green
0.881, // yellow
1.0,
1.0,
1.0,
0.881, // yellow
0.440, // green
0.440, // green
0.440, // green
0.180,
0.180,
0.180,
0.148,
0.148,
0.148,
0.129,
0.129,
0.129,
0.111,
0.111,
0.111,
0.100,
0.100,
0.100,
0.090,
0.090,
0.090,
0.084, // purple
0.084, // purple
0.084, // purple
0.084, // purple
0.084, // purple
0.077, // after purple
0.077, // after purple
0.077, // after purple
0.077, // after purple
0.077, // after purple
0.074,
0.063,
0.063,
0.063,
};
const int table_length = (sizeof (table)) / (sizeof (table[0]));
constexpr int num_quads = table_length;
constexpr int half_quads = (num_quads - 1) / 2;
constexpr float inverse_half_quads = 1.0f / (float)half_quads;
for (int i = 0; i < num_quads; i++) {
float z = (float)(i - half_quads) * inverse_half_quads;
float s = sin<float>(z * pi * 0.5f + pi * 0.5f);
//printf("%f\n", s);
//float a = pow(s, 5);
float a = table[i];
//float a = alpha_mul;
vec4 color = {1, 1, 1, a};
global_polygon_textured_intensity(writer,
color,
para_control::list_type::punch_through,
texture_offset,
texture_uv_size,
pixel_format);
vec3 z_trans = {0, 0, z * 0.35f};
const vec3& ap = trans * (position[0] * pos_scale + z_trans);
const vec3& bp = trans * (position[1] * pos_scale + z_trans);
const vec3& cp = trans * (position[2] * pos_scale + z_trans);
const vec3& dp = trans * (position[3] * pos_scale + z_trans);
const vec2& at = texture[0] * uv_scale;
const vec2& bt = texture[1] * uv_scale;
const vec2& ct = texture[2] * uv_scale;
const vec2& dt = texture[3] * uv_scale;
//const float base_intensity = _intensity(trans, normal[i]);
const float base_intensity = 1.0f;
quad_type_7_maybe_clip(writer,
ap, at,
bp, bt,
cp, ct,
dp, dt,
base_intensity);
}
}

View File

@ -1,10 +1,9 @@
#include "math/math.hpp"
#include "holly/framebuffer.hpp"
#include "platform/ta_parameter_presets.hpp"
#include "platform/texture.hpp"
#define _fsrra(n) (1.0f / (sqrt<float>(n)))
static inline void draw_line(ta_parameter_writer& writer,
const vec3& p1,
const vec3& p2)
@ -28,17 +27,7 @@ static inline void draw_line(ta_parameter_writer& writer,
dp,
intensity);
}
static inline vec3 screen_transform(const vec3& v)
{
float tx = framebuffer::framebuffer.px_width / 2.f;
float ty = framebuffer::framebuffer.px_height / 2.f;
float s = framebuffer::framebuffer.px_height / 2.f;
float z = _fsrra(v.z);
float z2 = z * z;
return {(v.x) * s * z2 + tx , (v.y) * s * z2 + ty , z2};
}
#undef _fsrra
static inline void draw_grid(ta_parameter_writer& writer,
const mat4x4& trans)
@ -91,6 +80,11 @@ void draw_cube(ta_parameter_writer& writer,
const mat4x4& trans,
const vec3& color);
void draw_textured_cube(ta_parameter_writer& writer,
const mat4x4& trans,
const vec3& scale,
const texture::cube_texture_offsets& offsets);
void draw_icosphere(ta_parameter_writer& writer,
const mat4x4& trans,
const vec3& color);
@ -106,3 +100,7 @@ void draw_halfspace(ta_parameter_writer& writer,
const vec3& n,
const mat4x4& trans,
const vec3& color);
void draw_textured_voxel(ta_parameter_writer& writer,
const mat4x4& trans,
int texture_offset);

View File

@ -5,7 +5,9 @@
#include "holly/ta_global_parameter.hpp"
#include "holly/isp_tsp.hpp"
#include "holly/texture_memory_alloc9.hpp"
#include "holly/framebuffer.hpp"
#include "math/geometry.hpp"
#include "math/float_types.hpp"
static inline void global_polygon_intensity(ta_parameter_writer& writer,
@ -35,6 +37,38 @@ static inline void global_polygon_intensity(ta_parameter_writer& writer,
1.0f, color.x, color.y, color.z);
}
static inline void global_polygon_textured_intensity(ta_parameter_writer& writer,
const vec4& color,
int list_type,
int texture_offset,
int texture_uv_size,
int pixel_format)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| list_type
| obj_control::col_type::intensity_mode_1
| obj_control::texture
;
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater_or_equal
| isp_tsp_instruction_word::culling_mode::no_culling;//cull_if_positive;
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
| texture_uv_size;
const uint32_t texture_address = texture_memory_alloc.texture.start + texture_offset;
const uint32_t texture_control_word = pixel_format
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
writer.append<ta_global_parameter::polygon_type_1>() =
ta_global_parameter::polygon_type_1(parameter_control_word,
isp_tsp_instruction_word,
tsp_instruction_word,
texture_control_word,
color.w, color.x, color.y, color.z);
}
static inline void global_polygon_textured(ta_parameter_writer& writer,
uint32_t list_type,
uint32_t texture_offset,
@ -151,3 +185,156 @@ static inline void quad_type_3(ta_parameter_writer& writer,
ct.x, ct.y,
base_color, 0);
}
static inline void quad_type_7(ta_parameter_writer& writer,
const vec3& ap, const vec2& at,
const vec3& bp, const vec2& bt,
const vec3& cp, const vec2& ct,
const vec3& dp, const vec2& dt,
float base_intensity)
{
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false),
ap.x, ap.y, ap.z,
at.x, at.y,
base_intensity, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false),
bp.x, bp.y, bp.z,
bt.x, bt.y,
base_intensity, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false),
dp.x, dp.y, dp.z,
dt.x, dt.y,
base_intensity, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(true),
cp.x, cp.y, cp.z,
ct.x, ct.y,
base_intensity, 0);
}
static inline void tri_type_7(ta_parameter_writer& writer,
const vec3& ap, const vec2& at,
const vec3& bp, const vec2& bt,
const vec3& cp, const vec2& ct,
float base_intensity)
{
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false),
ap.x, ap.y, ap.z,
at.x, at.y,
base_intensity, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(false),
bp.x, bp.y, bp.z,
bt.x, bt.y,
base_intensity, 0);
writer.append<ta_vertex_parameter::polygon_type_7>() =
ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(true),
cp.x, cp.y, cp.z,
ct.x, ct.y,
base_intensity, 0);
}
#define _fsrra(n) (1.0f / (sqrt<float>(n)))
static inline vec3 screen_transform(const vec3& v)
{
float tx = framebuffer::framebuffer.px_width / 2.f;
float ty = framebuffer::framebuffer.px_height / 2.f;
float s = framebuffer::framebuffer.px_height / 2.f;
float z = _fsrra(v.z);
float z2 = z * z;
return {(-v.x) * s * z2 + tx , (-v.y) * s * z2 + ty , z2};
}
#undef _fsrra
static inline void tri_type_7_clip(ta_parameter_writer& writer,
const vec3& ap, const vec2& at,
const vec3& bp, const vec2& bt,
const vec3& cp, const vec2& ct,
float base_intensity)
{
const vec3 plane_point = {0.f, 0.f, 0.5f};
const vec3 plane_normal = {0.f, 0.f, 1.f};
vec3 preclip_position[] = {ap, bp, cp};
vec2 preclip_texture[] = {at, bt, ct};
vec3 clip_position[4];
vec2 clip_texture[4];
int output_length = geometry::clip_polygon_2<3>(clip_position,
clip_texture ,
plane_point,
plane_normal,
preclip_position,
preclip_texture);
{
vec3 ap = screen_transform(clip_position[0]);
vec3 bp = screen_transform(clip_position[1]);
vec3 cp = screen_transform(clip_position[2]);
const vec2& at = clip_texture[0];
const vec2& bt = clip_texture[1];
const vec2& ct = clip_texture[2];
if (output_length >= 4) {
vec3 dp = screen_transform(clip_position[3]);
const vec2& dt = clip_texture[3];
quad_type_7(writer,
ap, at,
bp, bt,
cp, ct,
dp, dt,
base_intensity);
} else {
tri_type_7(writer,
ap, at,
bp, bt,
cp, ct,
base_intensity);
}
}
}
static inline void quad_type_7_maybe_clip(ta_parameter_writer& writer,
const vec3& ap, const vec2& at,
const vec3& bp, const vec2& bt,
const vec3& cp, const vec2& ct,
const vec3& dp, const vec2& dt,
float base_intensity)
{
if (ap.z < 0 && bp.z < 0 && cp.z < 0 && dp.z < 0) {
return;
}
if (ap.z < 0 || bp.z < 0 || cp.z < 0 || dp.z < 0) {
tri_type_7_clip(writer,
ap, at,
bp, bt,
cp, ct,
base_intensity);
tri_type_7_clip(writer,
ap, at,
cp, ct,
dp, dt,
base_intensity);
} else {
quad_type_7(writer,
screen_transform(ap), at,
screen_transform(bp), bt,
screen_transform(cp), ct,
screen_transform(dp), dt,
base_intensity);
}
}

View File

@ -8,6 +8,16 @@
#include "holly/ta_fifo_texture_memory_transfer.hpp"
#include "font/ter_u12n.data.h"
#include "texture/igh25_box_top_32.data.h"
#include "texture/igh25_box_bottom_32.data.h"
#include "texture/igh25_box_side_32.data.h"
#include "texture/walking/frame0000_128.data.h"
#include "texture/walking/frame0001_128.data.h"
#include "texture/walking/frame0002_128.data.h"
#include "texture/walking/frame0003_128.data.h"
#include "texture/walking/frame0004_128.data.h"
#include "texture/walking/frame0005_128.data.h"
#include "texture/walking/frame0006_128.data.h"
namespace texture {
struct entry {
@ -22,6 +32,56 @@ namespace texture {
.size = reinterpret_cast<int>(&_binary_font_ter_u12n_data_size),
.offset = offset::ter_u12n,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_igh25_box_top_32_data_start),
.size = reinterpret_cast<int>(&_binary_texture_igh25_box_top_32_data_size),
.offset = offset::igh25_box_top_32,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_igh25_box_bottom_32_data_start),
.size = reinterpret_cast<int>(&_binary_texture_igh25_box_bottom_32_data_size),
.offset = offset::igh25_box_bottom_32,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_igh25_box_side_32_data_start),
.size = reinterpret_cast<int>(&_binary_texture_igh25_box_side_32_data_size),
.offset = offset::igh25_box_side_32,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0000_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0000_128_data_size),
.offset = offset::walking_frame0000,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0001_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0001_128_data_size),
.offset = offset::walking_frame0001,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0002_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0002_128_data_size),
.offset = offset::walking_frame0002,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0003_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0003_128_data_size),
.offset = offset::walking_frame0003,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0004_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0004_128_data_size),
.offset = offset::walking_frame0004,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0005_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0005_128_data_size),
.offset = offset::walking_frame0005,
},
{
.start = reinterpret_cast<void *>(&_binary_texture_walking_frame0006_128_data_start),
.size = reinterpret_cast<int>(&_binary_texture_walking_frame0006_128_data_size),
.offset = offset::walking_frame0006,
},
};
const int textures_length = (sizeof (textures)) / (sizeof (textures[0]));

View File

@ -1,7 +1,31 @@
#pragma once
namespace texture {
namespace offset {
constexpr int ter_u12n = 0;
constexpr int igh25_box_top_32 = ter_u12n + 4096;
constexpr int igh25_box_bottom_32 = igh25_box_top_32 + 2048;
constexpr int igh25_box_side_32 = igh25_box_bottom_32 + 2048;
constexpr int walking_frame0000 = igh25_box_side_32 + 2048;
constexpr int walking_frame0001 = walking_frame0000 + 8192;
constexpr int walking_frame0002 = walking_frame0001 + 8192;
constexpr int walking_frame0003 = walking_frame0002 + 8192;
constexpr int walking_frame0004 = walking_frame0003 + 8192;
constexpr int walking_frame0005 = walking_frame0004 + 8192;
constexpr int walking_frame0006 = walking_frame0005 + 8192;
}
struct cube_texture_offsets {
const int top;
const int bottom;
const int side;
};
constexpr cube_texture_offsets cube_type_1 = {
offset::igh25_box_top_32,
offset::igh25_box_bottom_32,
offset::igh25_box_side_32,
};
void init();
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_igh25_box_bottom_32_data_start __asm("_binary_texture_igh25_box_bottom_32_data_start");
extern uint32_t _binary_texture_igh25_box_bottom_32_data_end __asm("_binary_texture_igh25_box_bottom_32_data_end");
extern uint32_t _binary_texture_igh25_box_bottom_32_data_size __asm("_binary_texture_igh25_box_bottom_32_data_size");
#ifdef __cplusplus
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_igh25_box_side_32_data_start __asm("_binary_texture_igh25_box_side_32_data_start");
extern uint32_t _binary_texture_igh25_box_side_32_data_end __asm("_binary_texture_igh25_box_side_32_data_end");
extern uint32_t _binary_texture_igh25_box_side_32_data_size __asm("_binary_texture_igh25_box_side_32_data_size");
#ifdef __cplusplus
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_igh25_box_top_32_data_start __asm("_binary_texture_igh25_box_top_32_data_start");
extern uint32_t _binary_texture_igh25_box_top_32_data_end __asm("_binary_texture_igh25_box_top_32_data_end");
extern uint32_t _binary_texture_igh25_box_top_32_data_size __asm("_binary_texture_igh25_box_top_32_data_size");
#ifdef __cplusplus
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
texture/walking/frame0000.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0000_128_data_start __asm("_binary_texture_walking_frame0000_128_data_start");
extern uint32_t _binary_texture_walking_frame0000_128_data_end __asm("_binary_texture_walking_frame0000_128_data_end");
extern uint32_t _binary_texture_walking_frame0000_128_data_size __asm("_binary_texture_walking_frame0000_128_data_size");
#ifdef __cplusplus
}
#endif

BIN
texture/walking/frame0001.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0001_128_data_start __asm("_binary_texture_walking_frame0001_128_data_start");
extern uint32_t _binary_texture_walking_frame0001_128_data_end __asm("_binary_texture_walking_frame0001_128_data_end");
extern uint32_t _binary_texture_walking_frame0001_128_data_size __asm("_binary_texture_walking_frame0001_128_data_size");
#ifdef __cplusplus
}
#endif

BIN
texture/walking/frame0002.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0002_128_data_start __asm("_binary_texture_walking_frame0002_128_data_start");
extern uint32_t _binary_texture_walking_frame0002_128_data_end __asm("_binary_texture_walking_frame0002_128_data_end");
extern uint32_t _binary_texture_walking_frame0002_128_data_size __asm("_binary_texture_walking_frame0002_128_data_size");
#ifdef __cplusplus
}
#endif

BIN
texture/walking/frame0003.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0003_128_data_start __asm("_binary_texture_walking_frame0003_128_data_start");
extern uint32_t _binary_texture_walking_frame0003_128_data_end __asm("_binary_texture_walking_frame0003_128_data_end");
extern uint32_t _binary_texture_walking_frame0003_128_data_size __asm("_binary_texture_walking_frame0003_128_data_size");
#ifdef __cplusplus
}
#endif

BIN
texture/walking/frame0004.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0004_128_data_start __asm("_binary_texture_walking_frame0004_128_data_start");
extern uint32_t _binary_texture_walking_frame0004_128_data_end __asm("_binary_texture_walking_frame0004_128_data_end");
extern uint32_t _binary_texture_walking_frame0004_128_data_size __asm("_binary_texture_walking_frame0004_128_data_size");
#ifdef __cplusplus
}
#endif

BIN
texture/walking/frame0005.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0005_128_data_start __asm("_binary_texture_walking_frame0005_128_data_start");
extern uint32_t _binary_texture_walking_frame0005_128_data_end __asm("_binary_texture_walking_frame0005_128_data_end");
extern uint32_t _binary_texture_walking_frame0005_128_data_size __asm("_binary_texture_walking_frame0005_128_data_size");
#ifdef __cplusplus
}
#endif

BIN
texture/walking/frame0006.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,15 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_texture_walking_frame0006_128_data_start __asm("_binary_texture_walking_frame0006_128_data_start");
extern uint32_t _binary_texture_walking_frame0006_128_data_end __asm("_binary_texture_walking_frame0006_128_data_end");
extern uint32_t _binary_texture_walking_frame0006_128_data_size __asm("_binary_texture_walking_frame0006_128_data_size");
#ifdef __cplusplus
}
#endif

17
tools/canvas_size.py Normal file
View File

@ -0,0 +1,17 @@
from PIL import Image
import sys
def main():
in_file = sys.argv[1]
new_width = int(sys.argv[2])
new_height = int(sys.argv[3])
dst_file = sys.argv[4]
with Image.open(in_file) as im:
dst = Image.new(im.mode, (new_width, new_height))
for y in range(im.height):
for x in range(im.width):
dst.putpixel((x, y), im.getpixel((x, y)))
dst.save(dst_file)
if __name__ == "__main__":
main()

42
tools/generate.py Normal file
View File

@ -0,0 +1,42 @@
import io
def should_autonewline(line):
return (
"static_assert" not in line
and "extern" not in line
and (len(line.split()) < 2 or line.split()[1] != '=') # hacky; meh
)
def _render(out, lines):
indent = " "
level = 0
namespace = 0
for l in lines:
if l and (l[0] == "}" or l[0] == ")"):
level -= 2
if level < 0:
assert namespace >= 0
namespace -= 1
level = 0
if len(l) == 0:
out.write("\n")
else:
out.write(indent * level + l + "\n")
if l and (l[-1] == "{" or l[-1] == "("):
#if l.startswith("namespace"):
# namespace += 1
#else:
level += 2
if level == 0 and l and l[-1] == ";":
if should_autonewline(l):
out.write("\n")
return out
def renderer():
out = io.StringIO()
def render(lines):
return _render(out, lines)
return render, out

151
tools/parse_map.py Normal file
View File

@ -0,0 +1,151 @@
from PIL import Image
import sys
from dataclasses import dataclass
from generate import renderer
from os import path
visited = set()
@dataclass
class vec3:
x: float
y: float
z: float
@dataclass
class Platform:
scale: vec3
position: vec3
def parse_width(x, y, get_pixel):
width = 0
while True:
px = get_pixel(x, y)
if px[0] != 0:
width += 1
x += 1
else:
break
return width
def parse_height(x, y, get_pixel):
height = 0
while True:
px = get_pixel(x, y)
if px[0] != 0:
height += 1
y += 1
else:
break
return height
def round_to_one(n):
if n == 0:
return 1
else:
return n
def visit_pixels(x, y, width, height):
for yi in range(round_to_one(height)):
for xi in range(round_to_one(width)):
xx = x + xi
yy = y + yi
location = (xx, yy)
assert location not in visited
visited.add(location)
def parse_platform(x, y, get_pixel):
width = parse_width(x, y, get_pixel)
height = parse_height(x, y, get_pixel)
visit_pixels(x, y, width, height)
if width != 0 and height != 0:
px = get_pixel(x, y)
position = vec3(
x + (width / 2),
(px[0] - 128),
y + (height / 2),
)
scale = vec3(
width,
1,
height,
)
return Platform(
position=position,
scale=scale,
)
else:
return None
def find_platforms(im):
width, height = im.size
pixels = im.convert("RGB").getdata()
def get_pixel(x, y):
return pixels[y * width + x]
platforms = []
for y in range(height):
for x in range(width):
if (x, y) not in visited:
platform = parse_platform(x, y, get_pixel)
if platform is not None:
platforms.append(platform)
return platforms
def format_vec3(v):
return ", ".join((
f"{n: 8.03f}"
for n in [v.x, v.y, v.z]
))
def generate_platform(platform):
yield "{"
yield f".position = vec3({format_vec3(platform.position)}),"
yield f".scale = vec3({format_vec3(platform.scale)}),"
yield "},"
def generate_level(name, platforms):
yield f"world::platform {name}_platforms[] = {{"
for platform in platforms:
yield from generate_platform(platform)
yield "};"
yield f"world::level {name}_level = {{"
yield f".platforms = {name}_platforms,"
yield f".platforms_length = (sizeof ({name}_platforms)) / (sizeof (world::platform)),"
yield "};"
def generate_file(name_platforms_list):
yield '#include "demo/platform/world.hpp"'
yield ""
yield f"namespace demo::map {{"
yield ""
for name, platforms in name_platforms_list:
yield from generate_level(name, platforms)
yield ""
yield '}'
def level_name(p):
_, fn = path.split(p)
name, _ = path.splitext(fn)
return name
def find_all_platforms(maps):
for filename in maps:
with Image.open(filename) as im:
name = level_name(filename)
platforms = find_platforms(im)
yield (name, platforms)
maps = sys.argv[1:]
render, out = renderer()
render(generate_file(find_all_platforms(maps)))
sys.stdout.write(out.getvalue())