example: add modifier_volume_cube
This commit is contained in:
parent
05d2ead439
commit
be19abcdcf
2
Makefile
2
Makefile
@ -4,7 +4,7 @@ include base.mk
|
|||||||
include common.mk
|
include common.mk
|
||||||
include headers.mk
|
include headers.mk
|
||||||
|
|
||||||
OPT = -Og
|
OPT = -O2
|
||||||
MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST)))))
|
MAKEFILE_PATH := $(patsubst %/,%,$(dir $(abspath $(firstword $(MAKEFILE_LIST)))))
|
||||||
CFLAGS += -I$(MAKEFILE_PATH)
|
CFLAGS += -I$(MAKEFILE_PATH)
|
||||||
LIB ?= $(MAKEFILE_PATH)
|
LIB ?= $(MAKEFILE_PATH)
|
||||||
|
@ -859,3 +859,17 @@ SPECK_OBJ = \
|
|||||||
|
|
||||||
example/speck.elf: LDSCRIPT = $(LIB)/main.lds
|
example/speck.elf: LDSCRIPT = $(LIB)/main.lds
|
||||||
example/speck.elf: $(START_OBJ) $(SPECK_OBJ)
|
example/speck.elf: $(START_OBJ) $(SPECK_OBJ)
|
||||||
|
|
||||||
|
MODIFIER_VOLUME_CUBE_OBJ = \
|
||||||
|
example/modifier_volume_cube.o \
|
||||||
|
holly/core.o \
|
||||||
|
holly/region_array.o \
|
||||||
|
holly/background.o \
|
||||||
|
holly/ta_fifo_polygon_converter.o \
|
||||||
|
holly/video_output.o \
|
||||||
|
sh7091/serial.o \
|
||||||
|
font/terminus/ter_u32n.data.o \
|
||||||
|
$(LIBGCC)
|
||||||
|
|
||||||
|
example/modifier_volume_cube.elf: LDSCRIPT = $(LIB)/main.lds
|
||||||
|
example/modifier_volume_cube.elf: $(START_OBJ) $(MODIFIER_VOLUME_CUBE_OBJ)
|
||||||
|
912
example/modifier_volume_cube.cpp
Normal file
912
example/modifier_volume_cube.cpp
Normal file
@ -0,0 +1,912 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "holly/background.hpp"
|
||||||
|
#include "holly/core.hpp"
|
||||||
|
#include "holly/core_bits.hpp"
|
||||||
|
#include "holly/holly.hpp"
|
||||||
|
#include "holly/isp_tsp.hpp"
|
||||||
|
#include "holly/region_array.hpp"
|
||||||
|
#include "holly/ta_bits.hpp"
|
||||||
|
#include "holly/ta_fifo_polygon_converter.hpp"
|
||||||
|
#include "holly/ta_global_parameter.hpp"
|
||||||
|
#include "holly/ta_parameter.hpp"
|
||||||
|
#include "holly/ta_vertex_parameter.hpp"
|
||||||
|
#include "holly/texture_memory_alloc3.hpp"
|
||||||
|
#include "holly/video_output.hpp"
|
||||||
|
|
||||||
|
#include "sh7091/sh7091.hpp"
|
||||||
|
#include "sh7091/serial.hpp"
|
||||||
|
|
||||||
|
#include "systembus.hpp"
|
||||||
|
#include "systembus_bits.hpp"
|
||||||
|
|
||||||
|
#include "memorymap.hpp"
|
||||||
|
|
||||||
|
#include "model/model.h"
|
||||||
|
#include "model/cube.h"
|
||||||
|
#include "model/plane/model.h"
|
||||||
|
|
||||||
|
#include "font/terminus/ter_u32n.data.h"
|
||||||
|
|
||||||
|
#include "math/vec2.hpp"
|
||||||
|
#include "math/vec3.hpp"
|
||||||
|
#include "math/vec4.hpp"
|
||||||
|
#include "math/mat3x3.hpp"
|
||||||
|
#include "math/mat4x4.hpp"
|
||||||
|
#include "math/math.hpp"
|
||||||
|
|
||||||
|
#define assert(b) \
|
||||||
|
do { \
|
||||||
|
if (!(b)) { \
|
||||||
|
serial::string(__FILE__); \
|
||||||
|
serial::character(':'); \
|
||||||
|
serial::integer<uint32_t>(__LINE__, ' '); \
|
||||||
|
serial::string(__func__); \
|
||||||
|
serial::string(": assertion failed: "); \
|
||||||
|
serial::string(#b); \
|
||||||
|
serial::character('\n'); \
|
||||||
|
while (1); \
|
||||||
|
} \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
using vec2 = vec<2, float>;
|
||||||
|
using vec3 = vec<3, float>;
|
||||||
|
using vec4 = vec<4, float>;
|
||||||
|
using mat3x3 = mat<3, 3, float>;
|
||||||
|
using mat4x4 = mat<4, 4, float>;
|
||||||
|
|
||||||
|
const float deg = 0.017453292519943295;
|
||||||
|
|
||||||
|
#define _fsrra(n) \
|
||||||
|
({ \
|
||||||
|
float v = (n); \
|
||||||
|
asm("fsrra %0" \
|
||||||
|
: "=f" (v) \
|
||||||
|
: "0" (v)); \
|
||||||
|
v; \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline int max(int a, int b)
|
||||||
|
{
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int min(int a, int b)
|
||||||
|
{
|
||||||
|
return (a > b) ? b : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void global_polygon_type_0(ta_parameter_writer& writer, bool shadow)
|
||||||
|
{
|
||||||
|
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
|
||||||
|
| para_control::list_type::opaque
|
||||||
|
| obj_control::col_type::packed_color
|
||||||
|
| (shadow ? obj_control::shadow : 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
|
||||||
|
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||||
|
|
||||||
|
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
|
||||||
|
| tsp_instruction_word::src_alpha_instr::one
|
||||||
|
| tsp_instruction_word::dst_alpha_instr::zero
|
||||||
|
;
|
||||||
|
|
||||||
|
const uint32_t texture_control_word = 0;
|
||||||
|
|
||||||
|
writer.append<ta_global_parameter::polygon_type_0>() =
|
||||||
|
ta_global_parameter::polygon_type_0(parameter_control_word,
|
||||||
|
isp_tsp_instruction_word,
|
||||||
|
tsp_instruction_word,
|
||||||
|
texture_control_word,
|
||||||
|
0, // data_size_for_sort_dma
|
||||||
|
0 // next_address_for_sort_dma
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void global_modifier_volume(ta_parameter_writer& writer)
|
||||||
|
{
|
||||||
|
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
|
||||||
|
| para_control::list_type::opaque_modifier_volume
|
||||||
|
;
|
||||||
|
|
||||||
|
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::volume_instruction::normal_polygon
|
||||||
|
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||||
|
|
||||||
|
writer.append<ta_global_parameter::modifier_volume>() =
|
||||||
|
ta_global_parameter::modifier_volume(parameter_control_word,
|
||||||
|
isp_tsp_instruction_word
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_line(ta_parameter_writer& writer, vec3 p1, vec3 p2, uint32_t base_color)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
const uint32_t parameter_control_word = para_control::para_type::sprite
|
||||||
|
| para_control::list_type::opaque
|
||||||
|
| obj_control::col_type::packed_color;
|
||||||
|
|
||||||
|
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
|
||||||
|
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||||
|
|
||||||
|
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
|
||||||
|
| tsp_instruction_word::src_alpha_instr::one
|
||||||
|
| tsp_instruction_word::dst_alpha_instr::zero
|
||||||
|
;
|
||||||
|
|
||||||
|
const uint32_t texture_control_word = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
float dy = p2.y - p1.y;
|
||||||
|
float dx = p2.x - p1.x;
|
||||||
|
float d = _fsrra(dx * dx + dy * dy) * 0.7f;
|
||||||
|
float dy1 = dy * d;
|
||||||
|
float dx1 = dx * d;
|
||||||
|
|
||||||
|
assert(p1.z < 1);
|
||||||
|
assert(p2.z < 1);
|
||||||
|
|
||||||
|
const vec3 v[4] = {
|
||||||
|
{ p1.x + dy1, p1.y + -dx1, p1.z },
|
||||||
|
{ p1.x + -dy1, p1.y + dx1, p1.z },
|
||||||
|
{ p2.x + -dy1, p2.y + dx1, p2.z },
|
||||||
|
{ p2.x + dy1, p2.y + -dx1, p2.z },
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
writer.append<ta_global_parameter::sprite>() =
|
||||||
|
ta_global_parameter::sprite(parameter_control_word,
|
||||||
|
isp_tsp_instruction_word,
|
||||||
|
tsp_instruction_word,
|
||||||
|
texture_control_word,
|
||||||
|
base_color,
|
||||||
|
0, // offset_color
|
||||||
|
0, // data_size_for_sort_dma
|
||||||
|
0); // next_address_for_sort_dma
|
||||||
|
*/
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false),
|
||||||
|
v[0].x, v[0].y, v[0].z,
|
||||||
|
base_color);
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false),
|
||||||
|
v[1].x, v[1].y, v[1].z,
|
||||||
|
base_color);
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false),
|
||||||
|
v[3].x, v[3].y, v[3].z,
|
||||||
|
base_color);
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(true),
|
||||||
|
v[2].x, v[2].y, v[2].z,
|
||||||
|
base_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_glyph(ta_parameter_writer& writer, float x, float y, int c)
|
||||||
|
{
|
||||||
|
constexpr int width = 16;
|
||||||
|
constexpr int height = 32;
|
||||||
|
|
||||||
|
const uint32_t parameter_control_word = para_control::para_type::sprite
|
||||||
|
| para_control::list_type::punch_through
|
||||||
|
| obj_control::col_type::packed_color
|
||||||
|
| obj_control::texture;
|
||||||
|
|
||||||
|
const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater
|
||||||
|
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||||
|
|
||||||
|
const uint32_t tsp_instruction_word = tsp_instruction_word::fog_control::no_fog
|
||||||
|
| 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(width)
|
||||||
|
| tsp_instruction_word::texture_v_size::from_int(height);
|
||||||
|
|
||||||
|
const int ix = c - ' ';
|
||||||
|
const int offset = (width * height * ix) / 2;
|
||||||
|
const uint32_t texture_address = texture_memory_alloc.texture.start + offset;
|
||||||
|
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
|
||||||
|
| texture_control_word::scan_order::twiddled
|
||||||
|
| texture_control_word::texture_address(texture_address / 8);
|
||||||
|
|
||||||
|
constexpr vec2 v[4] = {
|
||||||
|
{ 0.f, 0.f },
|
||||||
|
{ 1.f, 0.f },
|
||||||
|
{ 1.f, 1.f },
|
||||||
|
{ 0.f, 1.f },
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr uint32_t base_color = 0;
|
||||||
|
writer.append<ta_global_parameter::sprite>() =
|
||||||
|
ta_global_parameter::sprite(parameter_control_word,
|
||||||
|
isp_tsp_instruction_word,
|
||||||
|
tsp_instruction_word,
|
||||||
|
texture_control_word,
|
||||||
|
base_color,
|
||||||
|
0, // offset_color
|
||||||
|
0, // data_size_for_sort_dma
|
||||||
|
0); // next_address_for_sort_dma
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::sprite_type_1>() =
|
||||||
|
ta_vertex_parameter::sprite_type_1(para_control::para_type::vertex_parameter,
|
||||||
|
v[0].x * width + x,
|
||||||
|
v[0].y * height + y,
|
||||||
|
0.1f,
|
||||||
|
v[1].x * width + x,
|
||||||
|
v[1].y * height + y,
|
||||||
|
0.1f,
|
||||||
|
v[2].x * width + x,
|
||||||
|
v[2].y * height + y,
|
||||||
|
0.1f,
|
||||||
|
v[3].x * width + x,
|
||||||
|
v[3].y * height + y,
|
||||||
|
uv_16bit(v[0].x, v[0].y),
|
||||||
|
uv_16bit(v[1].x, v[1].y),
|
||||||
|
uv_16bit(v[2].x, v[2].y));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 screen_transform(const mat4x4& screen, vec3 v)
|
||||||
|
{
|
||||||
|
v = screen * v;
|
||||||
|
|
||||||
|
float dim = 480 / 2.0 * 1.5;
|
||||||
|
|
||||||
|
return {
|
||||||
|
v.x / v.z * dim + 640 / 2.0f,
|
||||||
|
v.y / v.z * dim + 480 / 2.0f,
|
||||||
|
1 / v.z,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_basis(ta_parameter_writer& writer, const mat4x4& screen)
|
||||||
|
{
|
||||||
|
global_polygon_type_0(writer, false);
|
||||||
|
|
||||||
|
vec3 origin = screen_transform(screen, {0, 0, 0});
|
||||||
|
vec3 z = screen_transform(screen, {0, 0, 1});
|
||||||
|
vec3 y = screen_transform(screen, {0, 1, 0});
|
||||||
|
vec3 x = screen_transform(screen, {1, 0, 0});
|
||||||
|
|
||||||
|
uint32_t base_color = 0xffffff;
|
||||||
|
|
||||||
|
// magenta: Z
|
||||||
|
transfer_line(writer, origin, z, base_color);
|
||||||
|
|
||||||
|
// yellow: Y
|
||||||
|
transfer_line(writer, origin, y, base_color);
|
||||||
|
|
||||||
|
// cyan: X
|
||||||
|
transfer_line(writer, origin, x, base_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_basis_text(ta_parameter_writer& writer, const mat4x4& screen)
|
||||||
|
{
|
||||||
|
vec3 z = screen_transform(screen, (vec3){0, 0, 1} * 1.2f);
|
||||||
|
vec3 y = screen_transform(screen, (vec3){0, 1, 0} * 1.2f);
|
||||||
|
vec3 x = screen_transform(screen, (vec3){1, 0, 0} * 1.2f);
|
||||||
|
|
||||||
|
transfer_glyph(writer, z.x - 5, z.y - 10, 'z');
|
||||||
|
transfer_glyph(writer, y.x - 5, y.y - 10, 'y');
|
||||||
|
transfer_glyph(writer, x.x - 5, x.y - 10, 'x');
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define LINE_DRAWING 1
|
||||||
|
|
||||||
|
static inline void render_quad(ta_parameter_writer& writer,
|
||||||
|
uint32_t base_color,
|
||||||
|
vec3 ap,
|
||||||
|
vec3 bp,
|
||||||
|
vec3 cp,
|
||||||
|
vec3 dp)
|
||||||
|
{
|
||||||
|
#ifdef LINE_DRAWING
|
||||||
|
transfer_line(writer, ap, bp, base_color);
|
||||||
|
transfer_line(writer, bp, cp, base_color);
|
||||||
|
transfer_line(writer, cp, dp, base_color);
|
||||||
|
transfer_line(writer, dp, ap, base_color);
|
||||||
|
#else
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false),
|
||||||
|
ap.x, ap.y, ap.z,
|
||||||
|
base_color);
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false),
|
||||||
|
bp.x, bp.y, bp.z,
|
||||||
|
base_color);
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(false),
|
||||||
|
dp.x, dp.y, dp.z,
|
||||||
|
base_color);
|
||||||
|
|
||||||
|
writer.append<ta_vertex_parameter::polygon_type_0>() =
|
||||||
|
ta_vertex_parameter::polygon_type_0(polygon_vertex_parameter_control_word(true),
|
||||||
|
cp.x, cp.y, cp.z,
|
||||||
|
base_color);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void render_tri(ta_parameter_writer& writer,
|
||||||
|
uint32_t base_color,
|
||||||
|
vec3 ap,
|
||||||
|
vec3 bp,
|
||||||
|
vec3 cp)
|
||||||
|
{
|
||||||
|
#ifdef LINE_DRAWING
|
||||||
|
transfer_line(writer, ap, bp, base_color);
|
||||||
|
transfer_line(writer, bp, cp, base_color);
|
||||||
|
transfer_line(writer, cp, ap, base_color);
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void render_last_tri_mod(ta_parameter_writer& writer)
|
||||||
|
{
|
||||||
|
#ifdef LINE_DRAWING
|
||||||
|
#else
|
||||||
|
const uint32_t last_parameter_control_word = para_control::para_type::polygon_or_modifier_volume
|
||||||
|
| para_control::list_type::opaque_modifier_volume
|
||||||
|
| obj_control::volume::modifier_volume::last_in_volume;
|
||||||
|
|
||||||
|
const uint32_t last_isp_tsp_instruction_word = isp_tsp_instruction_word::volume_instruction::inside_last_polygon
|
||||||
|
| isp_tsp_instruction_word::culling_mode::no_culling;
|
||||||
|
|
||||||
|
writer.append<ta_global_parameter::modifier_volume>() =
|
||||||
|
ta_global_parameter::modifier_volume(last_parameter_control_word,
|
||||||
|
last_isp_tsp_instruction_word);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void render_tri_mod(ta_parameter_writer& writer,
|
||||||
|
vec3 ap,
|
||||||
|
vec3 bp,
|
||||||
|
vec3 cp)
|
||||||
|
{
|
||||||
|
#ifdef LINE_DRAWING
|
||||||
|
transfer_line(writer, ap, bp, base_color);
|
||||||
|
transfer_line(writer, bp, cp, base_color);
|
||||||
|
transfer_line(writer, cp, ap, base_color);
|
||||||
|
#else
|
||||||
|
writer.append<ta_vertex_parameter::modifier_volume>() =
|
||||||
|
ta_vertex_parameter::modifier_volume(modifier_volume_vertex_parameter_control_word(),
|
||||||
|
ap.x, ap.y, ap.z,
|
||||||
|
bp.x, bp.y, bp.z,
|
||||||
|
cp.x, cp.y, cp.z);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_edge_coloring(uint8_t * edge_coloring,
|
||||||
|
const int edge_stride,
|
||||||
|
bool l_dot_n_b, int a, int b)
|
||||||
|
{
|
||||||
|
int ma = min(a, b);
|
||||||
|
int mb = max(a, b);
|
||||||
|
|
||||||
|
int bit = 1 << ((int)l_dot_n_b);
|
||||||
|
|
||||||
|
edge_coloring[ma * edge_stride + mb] |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct edge {
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t random;
|
||||||
|
|
||||||
|
uint32_t xorshift()
|
||||||
|
{
|
||||||
|
uint32_t x = random;
|
||||||
|
x ^= x << 13;
|
||||||
|
x ^= x >> 17;
|
||||||
|
x ^= x << 5;
|
||||||
|
return random = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void render_extension_mesh(ta_parameter_writer& writer,
|
||||||
|
vec3 ap,
|
||||||
|
vec3 bp,
|
||||||
|
vec3 cp,
|
||||||
|
vec3 dp,
|
||||||
|
vec3 ep,
|
||||||
|
vec3 fp,
|
||||||
|
vec3 apo,
|
||||||
|
vec3 bpo,
|
||||||
|
vec3 cpo,
|
||||||
|
vec3 dpo,
|
||||||
|
vec3 epo,
|
||||||
|
vec3 fpo)
|
||||||
|
{
|
||||||
|
render_tri_mod(writer, ap, bp, apo);
|
||||||
|
render_tri_mod(writer, bpo, apo, bp);
|
||||||
|
|
||||||
|
render_tri_mod(writer, bp, cp, bpo);
|
||||||
|
render_tri_mod(writer, cpo, bpo, cp);
|
||||||
|
|
||||||
|
render_tri_mod(writer, cp, dp, cpo);
|
||||||
|
render_tri_mod(writer, dpo, cpo, dp);
|
||||||
|
|
||||||
|
render_tri_mod(writer, dp, ep, dpo);
|
||||||
|
render_tri_mod(writer, epo, dpo, ep);
|
||||||
|
|
||||||
|
render_tri_mod(writer, ep, fp, epo);
|
||||||
|
render_tri_mod(writer, fpo, epo, fp);
|
||||||
|
|
||||||
|
render_tri_mod(writer, fp, ap, fpo);
|
||||||
|
render_last_tri_mod(writer);
|
||||||
|
render_tri_mod(writer, apo, fpo, ap);
|
||||||
|
|
||||||
|
/*
|
||||||
|
random = 0x12345789;
|
||||||
|
|
||||||
|
render_quad(writer, xorshift(), ap, bp, bpo, apo);
|
||||||
|
|
||||||
|
render_quad(writer, xorshift(), bp, cp, cpo, bpo);
|
||||||
|
|
||||||
|
render_quad(writer, xorshift(), cp, dp, dpo, cpo);
|
||||||
|
|
||||||
|
render_quad(writer, xorshift(), dp, ep, epo, dpo);
|
||||||
|
|
||||||
|
render_quad(writer, xorshift(), ep, fp, fpo, epo);
|
||||||
|
|
||||||
|
render_quad(writer, xorshift(), fp, ap, apo, fpo);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_silhouette(ta_parameter_writer& writer,
|
||||||
|
const mat4x4& screen,
|
||||||
|
const mat4x4& model,
|
||||||
|
const vec3 light_vec,
|
||||||
|
const uint8_t * edge_coloring,
|
||||||
|
const int edge_stride)
|
||||||
|
{
|
||||||
|
struct edge silhouette[6];
|
||||||
|
int ix = 0;
|
||||||
|
|
||||||
|
for (int a = 0; a < edge_stride; a++) {
|
||||||
|
for (int b = 0; b < edge_stride; b++) {
|
||||||
|
uint8_t coloring = edge_coloring[a * edge_stride + b];
|
||||||
|
if (coloring == 0b11) {
|
||||||
|
silhouette[ix++] = {a, b};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(ix == 6);
|
||||||
|
|
||||||
|
int last_ix = 0;
|
||||||
|
int order_ix = 0;
|
||||||
|
int order_vtx[6];
|
||||||
|
order_vtx[order_ix++] = silhouette[0].a;
|
||||||
|
|
||||||
|
// calculate vertex ordering
|
||||||
|
while (order_ix < 6) {
|
||||||
|
for (int i = 1; i < 6; i++) {
|
||||||
|
if (i == last_ix)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int last_vtx = order_vtx[order_ix - 1];
|
||||||
|
if (last_vtx == silhouette[i].a) {
|
||||||
|
last_ix = i;
|
||||||
|
order_vtx[order_ix++] = silhouette[i].b;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (last_vtx == silhouette[i].b) {
|
||||||
|
last_ix = i;
|
||||||
|
order_vtx[order_ix++] = silhouette[i].a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec3 * position = cube_position;
|
||||||
|
|
||||||
|
vec3 ap = screen_transform(screen, model * position[order_vtx[0]]);
|
||||||
|
vec3 bp = screen_transform(screen, model * position[order_vtx[1]]);
|
||||||
|
vec3 cp = screen_transform(screen, model * position[order_vtx[2]]);
|
||||||
|
vec3 dp = screen_transform(screen, model * position[order_vtx[3]]);
|
||||||
|
vec3 ep = screen_transform(screen, model * position[order_vtx[4]]);
|
||||||
|
vec3 fp = screen_transform(screen, model * position[order_vtx[5]]);
|
||||||
|
|
||||||
|
float scale = 5;
|
||||||
|
mat4x4 translate = {
|
||||||
|
1, 0, 0, -light_vec.x * scale,
|
||||||
|
0, 1, 0, -light_vec.y * scale,
|
||||||
|
0, 0, 1, -light_vec.z * scale,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
mat4x4 model2 = model * translate;
|
||||||
|
|
||||||
|
vec3 apo = screen_transform(screen, model2 * position[order_vtx[0]]);
|
||||||
|
vec3 bpo = screen_transform(screen, model2 * position[order_vtx[1]]);
|
||||||
|
vec3 cpo = screen_transform(screen, model2 * position[order_vtx[2]]);
|
||||||
|
vec3 dpo = screen_transform(screen, model2 * position[order_vtx[3]]);
|
||||||
|
vec3 epo = screen_transform(screen, model2 * position[order_vtx[4]]);
|
||||||
|
vec3 fpo = screen_transform(screen, model2 * position[order_vtx[5]]);
|
||||||
|
|
||||||
|
if (0) { // perimeter
|
||||||
|
uint32_t base_color = 0xff0080;
|
||||||
|
|
||||||
|
transfer_line(writer, ap, bp, base_color);
|
||||||
|
transfer_line(writer, bp, cp, base_color);
|
||||||
|
transfer_line(writer, cp, dp, base_color);
|
||||||
|
transfer_line(writer, dp, ep, base_color);
|
||||||
|
transfer_line(writer, ep, fp, base_color);
|
||||||
|
transfer_line(writer, fp, ap, base_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1) { // near end cap
|
||||||
|
render_tri_mod(writer, ap, bp, cp);
|
||||||
|
render_tri_mod(writer, cp, dp, ep);
|
||||||
|
render_tri_mod(writer, ep, fp, ap);
|
||||||
|
render_tri_mod(writer, ap, cp, ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1) { // far end cap
|
||||||
|
render_tri_mod(writer, apo, bpo, cpo);
|
||||||
|
render_tri_mod(writer, cpo, dpo, epo);
|
||||||
|
render_tri_mod(writer, epo, fpo, apo);
|
||||||
|
render_tri_mod(writer, apo, cpo, epo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1) {
|
||||||
|
render_extension_mesh(writer,
|
||||||
|
ap,
|
||||||
|
bp,
|
||||||
|
cp,
|
||||||
|
dp,
|
||||||
|
ep,
|
||||||
|
fp,
|
||||||
|
apo,
|
||||||
|
bpo,
|
||||||
|
cpo,
|
||||||
|
dpo,
|
||||||
|
epo,
|
||||||
|
fpo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_cube(ta_parameter_writer& writer,
|
||||||
|
const mat4x4& screen,
|
||||||
|
const mat4x4& model,
|
||||||
|
const vec3 light_vec)
|
||||||
|
{
|
||||||
|
const vec3 * normal = cube_normal;
|
||||||
|
const vec3 * position = cube_position;
|
||||||
|
const union quadrilateral * quadrilateral = cube_Cube_quadrilateral;
|
||||||
|
|
||||||
|
const int edge_stride = 8;
|
||||||
|
const int edge_coloring_length = edge_stride * edge_stride;
|
||||||
|
uint8_t __attribute__((aligned(4))) edge_coloring[edge_coloring_length];
|
||||||
|
for (int i = 0; i < edge_coloring_length / 4; i++)
|
||||||
|
reinterpret_cast<uint32_t *>(edge_coloring)[i] = 0;
|
||||||
|
|
||||||
|
global_polygon_type_0(writer, false); // no self-shadow
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
const union quadrilateral& q = quadrilateral[i];
|
||||||
|
vec3 n3 = normal[q.a.normal];
|
||||||
|
vec4 n4 = model * (vec4){n3.x, n3.y, n3.z, 0.f}; // no translation component
|
||||||
|
vec3 n = {n4.x, n4.y, n4.z};
|
||||||
|
float l_dot_n = dot(light_vec, n);
|
||||||
|
bool l_dot_n_b = l_dot_n > 0;
|
||||||
|
|
||||||
|
set_edge_coloring(edge_coloring, edge_stride, l_dot_n_b, q.a.position, q.b.position);
|
||||||
|
set_edge_coloring(edge_coloring, edge_stride, l_dot_n_b, q.b.position, q.c.position);
|
||||||
|
set_edge_coloring(edge_coloring, edge_stride, l_dot_n_b, q.c.position, q.d.position);
|
||||||
|
set_edge_coloring(edge_coloring, edge_stride, l_dot_n_b, q.d.position, q.a.position);
|
||||||
|
|
||||||
|
vec3 ap = model * position[q.a.position];
|
||||||
|
vec3 bp = model * position[q.b.position];
|
||||||
|
vec3 cp = model * position[q.c.position];
|
||||||
|
vec3 dp = model * position[q.d.position];
|
||||||
|
|
||||||
|
uint32_t base_color = l_dot_n_b ? 0xff8000 : 0x0080ff;
|
||||||
|
|
||||||
|
vec3 sap = screen_transform(screen, ap);
|
||||||
|
vec3 sbp = screen_transform(screen, bp);
|
||||||
|
vec3 scp = screen_transform(screen, cp);
|
||||||
|
vec3 sdp = screen_transform(screen, dp);
|
||||||
|
|
||||||
|
render_quad(writer,
|
||||||
|
base_color,
|
||||||
|
sap,
|
||||||
|
sbp,
|
||||||
|
scp,
|
||||||
|
sdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1) {
|
||||||
|
// end of opaque list
|
||||||
|
writer.append<ta_global_parameter::end_of_list>() =
|
||||||
|
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
|
||||||
|
|
||||||
|
global_modifier_volume(writer);
|
||||||
|
|
||||||
|
render_silhouette(writer,
|
||||||
|
screen,
|
||||||
|
model,
|
||||||
|
light_vec,
|
||||||
|
edge_coloring,
|
||||||
|
edge_stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_plane(ta_parameter_writer& writer,
|
||||||
|
const mat4x4& screen,
|
||||||
|
const vec3 light_vec)
|
||||||
|
{
|
||||||
|
//const vec3 * normal = plane_normal;
|
||||||
|
const vec3 * position = plane_position;
|
||||||
|
const union quadrilateral * quadrilateral = plane_Plane.quadrilateral;
|
||||||
|
int count = plane_Plane.quadrilateral_count;
|
||||||
|
|
||||||
|
float scale = 3;
|
||||||
|
const mat4x4 model = {
|
||||||
|
scale, 0, 0, 0,
|
||||||
|
0, scale, 0, 0,
|
||||||
|
0, 0, scale, 1,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
global_polygon_type_0(writer, true); // with shadow
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
const union quadrilateral& q = quadrilateral[i];
|
||||||
|
|
||||||
|
vec3 ap = model * position[q.a.position];
|
||||||
|
vec3 bp = model * position[q.b.position];
|
||||||
|
vec3 cp = model * position[q.c.position];
|
||||||
|
vec3 dp = model * position[q.d.position];
|
||||||
|
|
||||||
|
uint32_t base_color = 0xffff80;
|
||||||
|
|
||||||
|
vec3 sap = screen_transform(screen, ap);
|
||||||
|
vec3 sbp = screen_transform(screen, bp);
|
||||||
|
vec3 scp = screen_transform(screen, cp);
|
||||||
|
vec3 sdp = screen_transform(screen, dp);
|
||||||
|
|
||||||
|
render_quad(writer,
|
||||||
|
base_color,
|
||||||
|
sap,
|
||||||
|
sbp,
|
||||||
|
scp,
|
||||||
|
sdp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline mat4x4 screen_rotation()
|
||||||
|
{
|
||||||
|
float zt = -0.7853981633974483 / 1.5;
|
||||||
|
float xt = -0.7853981633974483 * 1;
|
||||||
|
mat4x4 rx = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, cos(xt), -sin(xt), 0,
|
||||||
|
0, sin(xt), cos(xt), 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
mat4x4 rz = {
|
||||||
|
cos(zt), -sin(zt), 0, 0,
|
||||||
|
sin(zt), cos(zt), 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
mat4x4 t = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 2.5,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
return t * rx * rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_light_vec(ta_parameter_writer& writer, const mat4x4& screen, vec3 l)
|
||||||
|
{
|
||||||
|
vec3 a = screen_transform(screen, {0, 0, 0});
|
||||||
|
vec3 b = screen_transform(screen, l * 0.5f);
|
||||||
|
|
||||||
|
transfer_line(writer, a, b, 0x00ff00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen, vec3 light_vec)
|
||||||
|
{
|
||||||
|
// opaque
|
||||||
|
render_basis(writer, screen);
|
||||||
|
|
||||||
|
render_light_vec(writer, screen, light_vec);
|
||||||
|
|
||||||
|
if (1) {
|
||||||
|
render_plane(writer,
|
||||||
|
screen,
|
||||||
|
light_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mat4x4 model = mat4x4() * 0.3f;
|
||||||
|
render_cube(writer,
|
||||||
|
screen,
|
||||||
|
model,
|
||||||
|
light_vec);
|
||||||
|
|
||||||
|
writer.append<ta_global_parameter::end_of_list>() =
|
||||||
|
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
|
||||||
|
|
||||||
|
// punch_through
|
||||||
|
/*
|
||||||
|
render_basis_text(writer, screen);
|
||||||
|
|
||||||
|
writer.append<ta_global_parameter::end_of_list>() =
|
||||||
|
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 update_light()
|
||||||
|
{
|
||||||
|
static float ltheta = 2;
|
||||||
|
|
||||||
|
vec3 light_origin = {0, 0, 0};
|
||||||
|
vec3 light_pos = {1, 1, 2};
|
||||||
|
|
||||||
|
mat3x3 rot = {
|
||||||
|
cos(ltheta), -sin(ltheta), 0,
|
||||||
|
sin(ltheta), cos(ltheta), 0,
|
||||||
|
0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
light_pos = rot * light_pos;
|
||||||
|
ltheta += deg / 8;
|
||||||
|
|
||||||
|
vec3 light_vec = light_origin - light_pos;
|
||||||
|
|
||||||
|
return light_vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_ta_fifo_texture_memory_32byte(void * dst, void * src, int length)
|
||||||
|
{
|
||||||
|
uint32_t out_addr = (uint32_t)dst;
|
||||||
|
sh7091.CCN.QACR0 = ((reinterpret_cast<uint32_t>(out_addr) >> 24) & 0b11100);
|
||||||
|
sh7091.CCN.QACR1 = ((reinterpret_cast<uint32_t>(out_addr) >> 24) & 0b11100);
|
||||||
|
|
||||||
|
volatile uint32_t * base = &store_queue[(out_addr & 0x03ffffc0) / 4];
|
||||||
|
uint32_t * src32 = reinterpret_cast<uint32_t *>(src);
|
||||||
|
|
||||||
|
length = (length + 31) & ~31; // round up to nearest multiple of 32
|
||||||
|
while (length > 0) {
|
||||||
|
base[0] = src32[0];
|
||||||
|
base[1] = src32[1];
|
||||||
|
base[2] = src32[2];
|
||||||
|
base[3] = src32[3];
|
||||||
|
base[4] = src32[4];
|
||||||
|
base[5] = src32[5];
|
||||||
|
base[6] = src32[6];
|
||||||
|
base[7] = src32[7];
|
||||||
|
asm volatile ("pref @%0"
|
||||||
|
: // output
|
||||||
|
: "r" (&base[0]) // input
|
||||||
|
: "memory");
|
||||||
|
length -= 32;
|
||||||
|
base += 8;
|
||||||
|
src32 += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_textures()
|
||||||
|
{
|
||||||
|
system.LMMODE0 = 0; // 64-bit address space
|
||||||
|
system.LMMODE1 = 0; // 64-bit address space
|
||||||
|
|
||||||
|
uint32_t offset = texture_memory_alloc.texture.start;
|
||||||
|
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
|
||||||
|
void * src = reinterpret_cast<void *>(&_binary_font_terminus_ter_u32n_data_start);
|
||||||
|
uint32_t size = reinterpret_cast<uint32_t>(&_binary_font_terminus_ter_u32n_data_size);
|
||||||
|
transfer_ta_fifo_texture_memory_32byte(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t argb1555(int a, int r, int g, int b)
|
||||||
|
{
|
||||||
|
return ((a & 1) << 15) | ((r & 31) << 10) | ((g & 31) << 5) | ((b & 31) << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void transfer_palette()
|
||||||
|
{
|
||||||
|
holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::argb1555;
|
||||||
|
|
||||||
|
holly.PALETTE_RAM[ 0 + 0] = argb1555(0, 0, 0, 0);
|
||||||
|
holly.PALETTE_RAM[ 0 + 1] = argb1555(1, 31, 31, 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t __attribute__((aligned(32))) ta_parameter_buf[1024 * 1024];
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
serial::init(0);
|
||||||
|
transfer_textures();
|
||||||
|
transfer_palette();
|
||||||
|
|
||||||
|
constexpr uint32_t ta_alloc = 0
|
||||||
|
//ta_alloc_ctrl::pt_opb::_16x4byte
|
||||||
|
| ta_alloc_ctrl::tm_opb::no_list
|
||||||
|
| ta_alloc_ctrl::t_opb::no_list
|
||||||
|
| ta_alloc_ctrl::om_opb::_16x4byte
|
||||||
|
| ta_alloc_ctrl::o_opb::_16x4byte;
|
||||||
|
|
||||||
|
constexpr int render_passes = 1;
|
||||||
|
constexpr struct opb_size opb_size[render_passes] = {
|
||||||
|
{
|
||||||
|
.opaque = 16 * 4,
|
||||||
|
.opaque_modifier = 16 * 4,
|
||||||
|
.translucent = 0,
|
||||||
|
.translucent_modifier = 0,
|
||||||
|
//.punch_through = 16 * 4
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
holly.SOFTRESET = softreset::pipeline_soft_reset
|
||||||
|
| softreset::ta_soft_reset;
|
||||||
|
holly.SOFTRESET = 0;
|
||||||
|
|
||||||
|
core_init();
|
||||||
|
holly.FPU_SHAD_SCALE = fpu_shad_scale::simple_shadow_enable::intensity_volume_mode;
|
||||||
|
video_output::set_mode_vga();
|
||||||
|
|
||||||
|
const int framebuffer_width = 640;
|
||||||
|
const int framebuffer_height = 480;
|
||||||
|
const int tile_width = framebuffer_width / 32;
|
||||||
|
const int tile_height = framebuffer_height / 32;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
region_array_multipass(tile_width,
|
||||||
|
tile_height,
|
||||||
|
opb_size,
|
||||||
|
render_passes,
|
||||||
|
texture_memory_alloc.region_array[i].start,
|
||||||
|
texture_memory_alloc.object_list[i].start);
|
||||||
|
|
||||||
|
background_parameter2(texture_memory_alloc.background[i].start,
|
||||||
|
0xff202040);
|
||||||
|
}
|
||||||
|
|
||||||
|
ta_parameter_writer writer = ta_parameter_writer(ta_parameter_buf);
|
||||||
|
|
||||||
|
int ta = 0;
|
||||||
|
int core = 0;
|
||||||
|
|
||||||
|
const float degree = 0.017453292519943295 / 5;
|
||||||
|
float theta = 0;
|
||||||
|
|
||||||
|
const mat4x4 screen = screen_rotation();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
vec3 light_vec = update_light();
|
||||||
|
|
||||||
|
ta_polygon_converter_init2(texture_memory_alloc.isp_tsp_parameters[ta].start,
|
||||||
|
texture_memory_alloc.isp_tsp_parameters[ta].end,
|
||||||
|
texture_memory_alloc.object_list[ta].start,
|
||||||
|
texture_memory_alloc.object_list[ta].end,
|
||||||
|
opb_size[0].total(),
|
||||||
|
ta_alloc,
|
||||||
|
tile_width,
|
||||||
|
tile_height);
|
||||||
|
writer.offset = 0;
|
||||||
|
transfer_scene(writer, screen, light_vec);
|
||||||
|
ta_polygon_converter_writeback(writer.buf, writer.offset);
|
||||||
|
ta_polygon_converter_transfer(writer.buf, writer.offset);
|
||||||
|
ta_wait_opaque_modifier_volume_list();
|
||||||
|
|
||||||
|
core_start_render2(texture_memory_alloc.region_array[core].start,
|
||||||
|
texture_memory_alloc.isp_tsp_parameters[core].start,
|
||||||
|
texture_memory_alloc.background[core].start,
|
||||||
|
texture_memory_alloc.framebuffer[core].start,
|
||||||
|
framebuffer_width);
|
||||||
|
core_wait_end_of_render_video();
|
||||||
|
|
||||||
|
holly.FB_R_SOF1 = texture_memory_alloc.framebuffer[ta].start;
|
||||||
|
|
||||||
|
theta += degree;
|
||||||
|
}
|
||||||
|
}
|
BIN
font/terminus/ter_u32n.data
Normal file
BIN
font/terminus/ter_u32n.data
Normal file
Binary file not shown.
15
font/terminus/ter_u32n.data.h
Normal file
15
font/terminus/ter_u32n.data.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint32_t _binary_font_terminus_ter_u32n_data_start __asm("_binary_font_terminus_ter_u32n_data_start");
|
||||||
|
extern uint32_t _binary_font_terminus_ter_u32n_data_end __asm("_binary_font_terminus_ter_u32n_data_end");
|
||||||
|
extern uint32_t _binary_font_terminus_ter_u32n_data_size __asm("_binary_font_terminus_ter_u32n_data_size");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -80,6 +80,18 @@ mat<4, 4, T>::operator[](int i) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr mat<4, 4, T> operator+(mat<4, 4, T> const& m1, mat<4, 4, T> const& m2)
|
||||||
|
{
|
||||||
|
#define c(i, j) ( m1[i][j] + m2[i][j] )
|
||||||
|
|
||||||
|
return mat<4, 4, T>(c(0,0), c(0,1), c(0,2), c(0,3),
|
||||||
|
c(1,0), c(1,1), c(1,2), c(1,3),
|
||||||
|
c(2,0), c(2,1), c(2,2), c(2,3),
|
||||||
|
c(3,0), c(3,1), c(3,2), c(3,3));
|
||||||
|
#undef c
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, mat<4, 4, T> const& m2)
|
inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, mat<4, 4, T> const& m2)
|
||||||
{
|
{
|
||||||
@ -96,6 +108,18 @@ inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, mat<4, 4, T> con
|
|||||||
#undef c
|
#undef c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, float s)
|
||||||
|
{
|
||||||
|
#define c(i, j) ( m1[i][j] * s )
|
||||||
|
|
||||||
|
return mat<4, 4, T>(c(0,0), c(0,1), c(0,2), c(0,3),
|
||||||
|
c(1,0), c(1,1), c(1,2), c(1,3),
|
||||||
|
c(2,0), c(2,1), c(2,2), c(2,3),
|
||||||
|
c(3,0), c(3,1), c(3,2), c(3,3));
|
||||||
|
#undef c
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr typename mat<4, 4, T>::row_type operator*
|
inline constexpr typename mat<4, 4, T>::row_type operator*
|
||||||
(
|
(
|
||||||
@ -113,6 +137,23 @@ inline constexpr typename mat<4, 4, T>::row_type operator*
|
|||||||
#undef c
|
#undef c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr vec<3, T> operator*
|
||||||
|
(
|
||||||
|
mat<4, 4, T> const& m,
|
||||||
|
vec<3, T> const& v
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#define c(i) ( \
|
||||||
|
m[i][0] * v[0] \
|
||||||
|
+ m[i][1] * v[1] \
|
||||||
|
+ m[i][2] * v[2] \
|
||||||
|
+ m[i][3] )
|
||||||
|
|
||||||
|
return vec<3, T>(c(0), c(1), c(2));
|
||||||
|
#undef c
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr mat<4, 4, T> transpose(mat<4, 4, T> const& m)
|
inline constexpr mat<4, 4, T> transpose(mat<4, 4, T> const& m)
|
||||||
{
|
{
|
||||||
|
104
model/cube/model.h
Normal file
104
model/cube/model.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
// floating-point
|
||||||
|
const vertex_position cube_position[] = {
|
||||||
|
{1.0, 1.0, -1.0},
|
||||||
|
{1.0, -1.0, -1.0},
|
||||||
|
{1.0, 1.0, 1.0},
|
||||||
|
{1.0, -1.0, 1.0},
|
||||||
|
{-1.0, 1.0, -1.0},
|
||||||
|
{-1.0, -1.0, -1.0},
|
||||||
|
{-1.0, 1.0, 1.0},
|
||||||
|
{-1.0, -1.0, 1.0},
|
||||||
|
};
|
||||||
|
|
||||||
|
// floating-point
|
||||||
|
const vertex_texture cube_texture[] = {
|
||||||
|
{0.625, 0.5},
|
||||||
|
{0.875, 0.5},
|
||||||
|
{0.875, 0.75},
|
||||||
|
{0.625, 0.75},
|
||||||
|
{0.375, 0.75},
|
||||||
|
{0.625, 1.0},
|
||||||
|
{0.375, 1.0},
|
||||||
|
{0.375, 0.0},
|
||||||
|
{0.625, 0.0},
|
||||||
|
{0.625, 0.25},
|
||||||
|
{0.375, 0.25},
|
||||||
|
{0.125, 0.5},
|
||||||
|
{0.375, 0.5},
|
||||||
|
{0.125, 0.75},
|
||||||
|
};
|
||||||
|
|
||||||
|
// floating-point
|
||||||
|
const vertex_normal cube_normal[] = {
|
||||||
|
{0.0, 1.0, 0.0},
|
||||||
|
{0.0, 0.0, 1.0},
|
||||||
|
{-1.0, 0.0, 0.0},
|
||||||
|
{0.0, -1.0, 0.0},
|
||||||
|
{1.0, 0.0, 0.0},
|
||||||
|
{0.0, 0.0, -1.0},
|
||||||
|
};
|
||||||
|
|
||||||
|
const union quadrilateral cube_Cube_quadrilateral[] = {
|
||||||
|
{ .v = {
|
||||||
|
{0, 0, 0},
|
||||||
|
{4, 1, 0},
|
||||||
|
{6, 2, 0},
|
||||||
|
{2, 3, 0},
|
||||||
|
}},
|
||||||
|
{ .v = {
|
||||||
|
{3, 4, 1},
|
||||||
|
{2, 3, 1},
|
||||||
|
{6, 5, 1},
|
||||||
|
{7, 6, 1},
|
||||||
|
}},
|
||||||
|
{ .v = {
|
||||||
|
{7, 7, 2},
|
||||||
|
{6, 8, 2},
|
||||||
|
{4, 9, 2},
|
||||||
|
{5, 10, 2},
|
||||||
|
}},
|
||||||
|
{ .v = {
|
||||||
|
{5, 11, 3},
|
||||||
|
{1, 12, 3},
|
||||||
|
{3, 4, 3},
|
||||||
|
{7, 13, 3},
|
||||||
|
}},
|
||||||
|
{ .v = {
|
||||||
|
{1, 12, 4},
|
||||||
|
{0, 0, 4},
|
||||||
|
{2, 3, 4},
|
||||||
|
{3, 4, 4},
|
||||||
|
}},
|
||||||
|
{ .v = {
|
||||||
|
{5, 10, 5},
|
||||||
|
{4, 9, 5},
|
||||||
|
{0, 0, 5},
|
||||||
|
{1, 12, 5},
|
||||||
|
}},
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct object cube_Cube = {
|
||||||
|
.triangle = NULL,
|
||||||
|
.quadrilateral = &cube_Cube_quadrilateral[0],
|
||||||
|
.triangle_count = 0,
|
||||||
|
.quadrilateral_count = 6,
|
||||||
|
.material = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct object * cube_object_list[] = {
|
||||||
|
&cube_Cube,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct model cube_model = {
|
||||||
|
.position = &cube_position[0],
|
||||||
|
.texture = &cube_texture[0],
|
||||||
|
.normal = &cube_normal[0],
|
||||||
|
.object = &cube_object_list[0],
|
||||||
|
.object_count = 1,
|
||||||
|
};
|
2411
model/plane/model.h
Normal file
2411
model/plane/model.h
Normal file
File diff suppressed because it is too large
Load Diff
BIN
model/plane/plane.blend
Normal file
BIN
model/plane/plane.blend
Normal file
Binary file not shown.
2
model/plane/plane.mtl
Normal file
2
model/plane/plane.mtl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Blender 4.3.2 MTL File: 'plane.blend'
|
||||||
|
# www.blender.org
|
1095
model/plane/plane.obj
Normal file
1095
model/plane/plane.obj
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,23 @@
|
|||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include "../twiddle.hpp"
|
||||||
|
|
||||||
|
bool is_power(int n)
|
||||||
|
{
|
||||||
|
const int min_power = 8;
|
||||||
|
const int max_power = 1024;
|
||||||
|
int power = min_power;
|
||||||
|
|
||||||
|
while (power <= max_power) {
|
||||||
|
if (n == power)
|
||||||
|
return true;
|
||||||
|
power *= 2;
|
||||||
|
}
|
||||||
|
printf("%d\n", n);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
load_bitmap_char(FT_Face face,
|
load_bitmap_char(FT_Face face,
|
||||||
FT_ULong char_code,
|
FT_ULong char_code,
|
||||||
@ -25,26 +42,24 @@ load_bitmap_char(FT_Face face,
|
|||||||
//printf("num_grays %d\n", face->glyph->bitmap.num_grays);
|
//printf("num_grays %d\n", face->glyph->bitmap.num_grays);
|
||||||
//printf("pitch %d\n", face->glyph->bitmap.pitch);
|
//printf("pitch %d\n", face->glyph->bitmap.pitch);
|
||||||
//printf("width %d\n", face->glyph->bitmap.width);
|
//printf("width %d\n", face->glyph->bitmap.width);
|
||||||
//printf("char_code %lx rows %d\n", char_code, face->glyph->bitmap.rows);
|
//printf("rows %d\n", face->glyph->bitmap.rows);
|
||||||
//assert((face->glyph->bitmap.rows % 8) == 0);
|
assert(face->glyph->bitmap.num_grays == 2);
|
||||||
//assert(face->glyph->bitmap.width / face->glyph->bitmap.pitch == 8);
|
assert(is_power(face->glyph->bitmap.rows));
|
||||||
|
assert(is_power(face->glyph->bitmap.width));
|
||||||
|
assert((int)(face->glyph->bitmap.pitch * 8) == (int)(face->glyph->bitmap.width));
|
||||||
|
|
||||||
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
|
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
|
||||||
uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch];
|
uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch];
|
||||||
uint8_t row_out = 0;
|
for (int x = 0; x < (int)face->glyph->bitmap.width; x += 1) {
|
||||||
for (unsigned int x = 0; x < face->glyph->bitmap.width; x++) {
|
const int bit = (row[x / 8] >> (7 - (x % 8))) & 1;
|
||||||
if (x % 8 == 0) row_out = 0;
|
//std::cerr << (bit ? "█" : " ");
|
||||||
const uint8_t bit = (row[x / 8] >> (7 - (x % 8))) & 1;
|
buf[y * face->glyph->bitmap.width + x] = bit;
|
||||||
std::cerr << (bit ? "█" : " ");
|
|
||||||
row_out |= (bit << (x % 8));
|
|
||||||
if (x % 8 == 7 || x == (face->glyph->bitmap.width - 1))
|
|
||||||
buf[(y * face->glyph->bitmap.pitch) + (x / 8)] = row_out;
|
|
||||||
}
|
}
|
||||||
std::cerr << "|\n";
|
//std::cerr << "|\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'pitch' is bytes; 'width' is pixels
|
// 'pitch' is bytes; 'width' is pixels
|
||||||
return face->glyph->bitmap.rows * face->glyph->bitmap.pitch;
|
return face->glyph->bitmap.rows * face->glyph->bitmap.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -95,11 +110,16 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
assert(end > start);
|
assert(end > start);
|
||||||
|
|
||||||
uint32_t pixels_per_glyph = (face->size->metrics.height * face->size->metrics.max_advance);
|
int width = face->size->metrics.max_advance >> 6;
|
||||||
|
int height = face->size->metrics.height >> 6;
|
||||||
|
uint32_t pixels_per_glyph = width * height;
|
||||||
assert(pixels_per_glyph % 8 == 0);
|
assert(pixels_per_glyph % 8 == 0);
|
||||||
uint32_t bytes_per_glyph = pixels_per_glyph / 8;
|
uint32_t bytes_per_glyph = pixels_per_glyph;
|
||||||
uint32_t num_glyphs = (end - start) + 1;
|
uint32_t num_glyphs = (end - start) + 1;
|
||||||
uint8_t buf[bytes_per_glyph * num_glyphs];
|
uint32_t buf_size = bytes_per_glyph * num_glyphs;
|
||||||
|
uint8_t * buf = (uint8_t *)malloc(buf_size);
|
||||||
|
|
||||||
|
uint8_t * twiddle_buf = (uint8_t *)malloc(buf_size / 2);
|
||||||
|
|
||||||
uint32_t bitmap_offset = 0;
|
uint32_t bitmap_offset = 0;
|
||||||
for (uint32_t char_code = start; char_code <= end; char_code++) {
|
for (uint32_t char_code = start; char_code <= end; char_code++) {
|
||||||
@ -111,16 +131,22 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("twiddle %d %d %d %d\n", bitmap_offset, bitmap_offset / 2, width, height);
|
||||||
|
twiddle::texture_4bpp(&twiddle_buf[bitmap_offset / 2],
|
||||||
|
&buf[bitmap_offset],
|
||||||
|
width,
|
||||||
|
height);
|
||||||
|
|
||||||
bitmap_offset += bitmap_size;
|
bitmap_offset += bitmap_size;
|
||||||
assert(bitmap_offset < (sizeof (buf)));
|
assert(bitmap_offset <= buf_size);
|
||||||
}
|
}
|
||||||
std::cerr << "bitmap_offset: 0x" << std::dec << bitmap_offset << '\n';
|
printf("bitmap_offset: %d\n", bitmap_offset);
|
||||||
|
|
||||||
FILE * out = fopen(output_file_path, "w");
|
FILE * out = fopen(output_file_path, "w");
|
||||||
if (out == NULL) {
|
if (out == NULL) {
|
||||||
perror("fopen(w)");
|
perror("fopen(w)");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fwrite(reinterpret_cast<void*>(&buf), bitmap_offset, 1, out);
|
fwrite(reinterpret_cast<void*>(twiddle_buf), bitmap_offset / 2, 1, out);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user