Compare commits

...

2 Commits

5 changed files with 427 additions and 16 deletions

View File

@ -1020,6 +1020,8 @@ Q3BSP_OBJ = \
pk/maps/20kdm2.bsp.o \ pk/maps/20kdm2.bsp.o \
interrupt.o \ interrupt.o \
maple/maple.o \ maple/maple.o \
font/font_bitmap.o \
font/verite_8x16/verite_8x16.data.o \
pk/textures/e7/e7walldesign01b.data.o \ pk/textures/e7/e7walldesign01b.data.o \
pk/textures/e7/e7steptop2.data.o \ pk/textures/e7/e7steptop2.data.o \
pk/textures/e7/e7dimfloor.data.o \ pk/textures/e7/e7dimfloor.data.o \

View File

@ -63,8 +63,17 @@
#include "pk/models/mapobjects/gratelamp/gratetorch2.data.h" #include "pk/models/mapobjects/gratelamp/gratetorch2.data.h"
#include "pk/models/mapobjects/gratelamp/gratetorch2b.data.h" #include "pk/models/mapobjects/gratelamp/gratetorch2b.data.h"
#include "font/font_bitmap.hpp"
#include "font/verite_8x16/verite_8x16.data.h"
#include "palette.hpp"
#include "printf/unparse.h"
#include "assert.h"
#include "pk/texture.h" #include "pk/texture.h"
constexpr int font_offset = ((0x7f - 0x20) + 1) * 8 * 16 / 2;
using vec2 = vec<2, float>; using vec2 = vec<2, float>;
using vec3 = vec<3, float>; using vec3 = vec<3, float>;
using vec4 = vec<4, float>; using vec4 = vec<4, float>;
@ -136,6 +145,34 @@ static inline vec3 screen_transform(vec3 v)
}; };
} }
void global_polygon_type_0(ta_parameter_writer& writer)
{
const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume
| para_control::list_type::translucent
| 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::src_alpha
| tsp_instruction_word::dst_alpha_instr::inverse_src_alpha
| tsp_instruction_word::use_alpha
;
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_polygon_type_1(ta_parameter_writer& writer, void global_polygon_type_1(ta_parameter_writer& writer,
uint32_t obj_control_texture, uint32_t obj_control_texture,
uint32_t texture_u_v_size, uint32_t texture_u_v_size,
@ -185,7 +222,7 @@ void global_texture(ta_parameter_writer& writer, int ix)
| tsp_instruction_word::texture_v_size::from_int(texture->height) | tsp_instruction_word::texture_v_size::from_int(texture->height)
; ;
uint32_t texture_address = texture_memory_alloc.texture.start + texture->offset * 2; uint32_t texture_address = texture_memory_alloc.texture.start + font_offset + texture->offset * 2;
uint32_t texture_control_word = texture_control_word::pixel_format::_565 uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::non_twiddled | texture_control_word::scan_order::non_twiddled
| texture_control_word::texture_address(texture_address / 8) | texture_control_word::texture_address(texture_address / 8)
@ -281,15 +318,17 @@ float light_intensity(vec3 light_vec, vec3 n)
{ {
float n_dot_l = dot(n, light_vec); float n_dot_l = dot(n, light_vec);
float intensity = 0.4f; float intensity = 0.5f;
if (n_dot_l > 0) { if (n_dot_l > 0) {
intensity += 0.5f * n_dot_l * (inverse_length(n) * inverse_length(light_vec)); intensity += 0.7f * n_dot_l * (inverse_length(n) * inverse_length(light_vec));
if (intensity > 1.0f) if (intensity > 1.0f)
intensity = 1.0f; intensity = 1.0f;
} }
return intensity; return intensity;
} }
static vec3 light_vec = {20, -20, -20};
void transfer_faces(uint8_t * buf, q3bsp_header_t * header, ta_parameter_writer& writer) void transfer_faces(uint8_t * buf, q3bsp_header_t * header, ta_parameter_writer& writer)
{ {
q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES]; q3bsp_direntry * ve = &header->direntries[LUMP_VERTEXES];
@ -302,8 +341,6 @@ void transfer_faces(uint8_t * buf, q3bsp_header_t * header, ta_parameter_writer&
int face_count = fe->length / (sizeof (struct q3bsp_face)); int face_count = fe->length / (sizeof (struct q3bsp_face));
const vec3 light_vec = {20, 20, 20};
int textures_length = (sizeof (textures)) / (sizeof (textures[0])); int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
int last_texture = -1; int last_texture = -1;
@ -383,6 +420,243 @@ void transfer_faces(uint8_t * buf, q3bsp_header_t * header, ta_parameter_writer&
} }
} }
static inline void render_quad(ta_parameter_writer& writer,
vec3 ap,
vec3 bp,
vec3 cp,
vec3 dp,
uint32_t base_color)
{
if (ap.z < 0 || bp.z < 0 || cp.z < 0 || dp.z < 0)
return;
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);
}
void render_bounding_box(ta_parameter_writer& writer, mat4x4& trans, vec3 max, vec3 min, uint32_t color)
{
vec3 a = max;
vec3 b = min;
global_polygon_type_0(writer);
// ax
render_quad(writer,
screen_transform(trans * (vec3){a.x, a.y, a.z}),
screen_transform(trans * (vec3){a.x, b.y, a.z}),
screen_transform(trans * (vec3){a.x, b.y, b.z}),
screen_transform(trans * (vec3){a.x, a.y, b.z}),
color);
// bx
render_quad(writer,
screen_transform(trans * (vec3){b.x, a.y, a.z}),
screen_transform(trans * (vec3){b.x, b.y, a.z}),
screen_transform(trans * (vec3){b.x, b.y, b.z}),
screen_transform(trans * (vec3){b.x, a.y, b.z}),
color);
// ay
render_quad(writer,
screen_transform(trans * (vec3){b.x, a.y, a.z}),
screen_transform(trans * (vec3){a.x, a.y, a.z}),
screen_transform(trans * (vec3){a.x, a.y, b.z}),
screen_transform(trans * (vec3){b.x, a.y, b.z}),
color);
// by
render_quad(writer,
screen_transform(trans * (vec3){b.x, b.y, a.z}),
screen_transform(trans * (vec3){a.x, b.y, a.z}),
screen_transform(trans * (vec3){a.x, b.y, b.z}),
screen_transform(trans * (vec3){b.x, b.y, b.z}),
color);
// az
render_quad(writer,
screen_transform(trans * (vec3){b.x, a.y, a.z}),
screen_transform(trans * (vec3){b.x, b.y, a.z}),
screen_transform(trans * (vec3){a.x, b.y, a.z}),
screen_transform(trans * (vec3){a.x, a.y, a.z}),
color);
// bz
render_quad(writer,
screen_transform(trans * (vec3){b.x, a.y, b.z}),
screen_transform(trans * (vec3){b.x, b.y, b.z}),
screen_transform(trans * (vec3){a.x, b.y, b.z}),
screen_transform(trans * (vec3){a.x, a.y, b.z}),
color);
}
int format_float(char * s, float num, int pad_length)
{
int offset = 0;
bool negative = num < 0;
if (negative) num = -num;
int32_t whole = num;
int digits = digits_base10(whole);
offset += unparse_base10_unsigned(&s[offset], whole, pad_length, ' ');
if (negative)
s[offset - (digits + 1)] = '-';
s[offset++] = '.';
int32_t fraction = (int32_t)((num - (float)whole) * 1000.0);
if (fraction < 0)
fraction = -fraction;
offset += unparse_base10_unsigned(&s[offset], fraction, 3, '0');
return offset;
}
void render_matrix(ta_parameter_writer& writer, const mat4x4& trans)
{
for (int row = 0; row < 4; row++) {
char __attribute__((aligned(4))) s[64];
for (uint32_t i = 0; i < (sizeof (s)) / 4; i++)
reinterpret_cast<uint32_t *>(s)[i] = 0x20202020;
int offset = 0;
offset += format_float(&s[offset], trans[row][0], 7);
offset += format_float(&s[offset], trans[row][1], 7);
offset += format_float(&s[offset], trans[row][2], 7);
offset += format_float(&s[offset], trans[row][3], 7);
font_bitmap::transform_string(writer,
8, 16, // texture
8, 16, // glyph
16 + 2 * 8, // position x
16 + row * 16, // position y
s, offset,
para_control::list_type::opaque);
}
}
static int root_ix = 0;
void render_ix(ta_parameter_writer& writer, int row, char * s, int ix)
{
int offset = 15;
bool is_leaf = ix < 0;
if (ix < 0)
ix = -(ix - 1);
offset += unparse_base10_unsigned(&s[offset], ix, 5, ' ');
if (is_leaf) {
s[offset++] = ' ';
s[offset++] = '(';
s[offset++] = 'l';
s[offset++] = 'e';
s[offset++] = 'a';
s[offset++] = 'f';
s[offset++] = ')';
} else {
s[offset++] = ' ';
s[offset++] = '(';
s[offset++] = 'n';
s[offset++] = 'o';
s[offset++] = 'd';
s[offset++] = 'e';
s[offset++] = ')';
}
font_bitmap::transform_string(writer,
8, 16, // texture
8, 16, // glyph
16 + 50 * 8, // position x
16 + row * 16, // position y
s, offset,
para_control::list_type::opaque);
}
void render_leaf_ix(ta_parameter_writer& writer)
{
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_pk_maps_20kdm2_bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * ne = &header->direntries[LUMP_NODES];
q3bsp_node_t * nodes = reinterpret_cast<q3bsp_node_t *>(&buf[ne->offset]);
q3bsp_node_t * root = &nodes[root_ix];
{
char s[32] = "root: ";
int row = 0;
render_ix(writer, row, s, root_ix);
}
{
char s[32] = "root.child[0]: ";
int row = 1;
render_ix(writer, row, s, root->children[0]);
}
{
char s[32] = "root.child[1]: ";
int row = 2;
render_ix(writer, row, s, root->children[1]);
}
}
void render_bounding_box_mm(ta_parameter_writer& writer, mat4x4& trans, int mins[3], int maxs[3], uint32_t color)
{
vec3 max = {(float)maxs[0], (float)maxs[1], (float)maxs[2]};
vec3 min = {(float)mins[0], (float)mins[1], (float)mins[2]};
render_bounding_box(writer, trans, max, min, color);
}
void render_bounding_boxes(ta_parameter_writer& writer, mat4x4& trans)
{
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_pk_maps_20kdm2_bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
q3bsp_direntry * le = &header->direntries[LUMP_LEAFS];
q3bsp_leaf_t * leafs = reinterpret_cast<q3bsp_leaf_t *>(&buf[le->offset]);
q3bsp_direntry * ne = &header->direntries[LUMP_NODES];
q3bsp_node_t * nodes = reinterpret_cast<q3bsp_node_t *>(&buf[ne->offset]);
q3bsp_node_t * root = &nodes[root_ix];
{
if (root->children[0] >= 0) {
q3bsp_node_t * a = &nodes[root->children[0]];
uint32_t color = 0x80ff00e6;
render_bounding_box_mm(writer, trans, a->mins, a->maxs, color);
} else {
int leaf_ix = -(root->children[0] + 1);
q3bsp_leaf_t * leaf = &leafs[leaf_ix];
uint32_t color = 0x80ff0016;
render_bounding_box_mm(writer, trans, leaf->maxs, leaf->mins, color);
}
if (root->children[1] >= 0) {
q3bsp_node_t * b = &nodes[root->children[1]];
uint32_t color = 0x8000ffe6;
render_bounding_box_mm(writer, trans, b->mins, b->maxs, color);
} else {
int leaf_ix = -(root->children[1] + 1);
q3bsp_leaf_t * leaf = &leafs[leaf_ix];
uint32_t color = 0x8000ff16;
render_bounding_box_mm(writer, trans, leaf->maxs, leaf->mins, color);
}
}
}
void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans) void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans)
{ {
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_pk_maps_20kdm2_bsp_start); uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_pk_maps_20kdm2_bsp_start);
@ -395,6 +669,14 @@ void transfer_scene(ta_parameter_writer& writer, const mat4x4& screen_trans)
transfer_faces(buf, header, writer); transfer_faces(buf, header, writer);
render_matrix(writer, trans);
render_leaf_ix(writer);
writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
render_bounding_boxes(writer, trans);
writer.append<ta_global_parameter::end_of_list>() = writer.append<ta_global_parameter::end_of_list>() =
ta_global_parameter::end_of_list(para_control::para_type::end_of_list); ta_global_parameter::end_of_list(para_control::para_type::end_of_list);
} }
@ -470,7 +752,7 @@ void transfer_textures()
int textures_length = (sizeof (textures)) / (sizeof (textures[0])); int textures_length = (sizeof (textures)) / (sizeof (textures[0]));
for (int i = 0; i < textures_length; i++) { for (int i = 0; i < textures_length; i++) {
uint32_t offset = texture_memory_alloc.texture.start + textures[i].offset * 2; uint32_t offset = texture_memory_alloc.texture.start + font_offset + textures[i].offset * 2;
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]); void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
void * src = textures[i].start; void * src = textures[i].start;
uint32_t size = textures[i].size; uint32_t size = textures[i].size;
@ -478,6 +760,8 @@ void transfer_textures()
} }
} }
static bool push = false;
mat4x4 update_analog(mat4x4& screen) mat4x4 update_analog(mat4x4& screen)
{ {
const float x_ = static_cast<float>(data[0].analog_coordinate_axis[2] - 0x80) / 127.f; const float x_ = static_cast<float>(data[0].analog_coordinate_axis[2] - 0x80) / 127.f;
@ -488,6 +772,9 @@ mat4x4 update_analog(mat4x4& screen)
int da = ft0::data_transfer::digital_button::da(data[0].digital_button) == 0; int da = ft0::data_transfer::digital_button::da(data[0].digital_button) == 0;
int ua = ft0::data_transfer::digital_button::ua(data[0].digital_button) == 0; int ua = ft0::data_transfer::digital_button::ua(data[0].digital_button) == 0;
int db_x = ft0::data_transfer::digital_button::x(data[0].digital_button) == 0;
int db_y = ft0::data_transfer::digital_button::y(data[0].digital_button) == 0;
float x = 0; float x = 0;
if (ra && !la) x = -10; if (ra && !la) x = -10;
if (la && !ra) x = 10; if (la && !ra) x = 10;
@ -520,20 +807,62 @@ mat4x4 update_analog(mat4x4& screen)
0, 0, 0, 1, 0, 0, 0, 1,
}; };
uint8_t * buf = reinterpret_cast<uint8_t *>(&_binary_pk_maps_20kdm2_bsp_start);
q3bsp_header_t * header = reinterpret_cast<q3bsp_header_t *>(buf);
//q3bsp_direntry * le = &header->direntries[LUMP_LEAFS];
//int num_leaves = le->length / (sizeof (struct q3bsp_leaf));
q3bsp_direntry * ne = &header->direntries[LUMP_NODES];
q3bsp_node_t * nodes = reinterpret_cast<q3bsp_node_t *>(&buf[ne->offset]);
if (db_x && !db_y && !push) {
push = true;
//leaf_ix -= 1;
//if (leaf_ix < 0) leaf_ix = num_leaves - 1;
int ix = nodes[root_ix].children[0];
if (ix >= 0)
root_ix = ix;
}
if (db_y && !db_x && !push) {
push = true;
//leaf_ix += 1;
//if (leaf_ix > num_leaves) leaf_ix = 0;
int ix = nodes[root_ix].children[1];
if (ix >= 0)
root_ix = ix;
}
if (!db_x && !db_y) {
push = false;
}
return rx * ry * t * screen; return rx * ry * t * screen;
} }
void transfer_font()
{
const uint8_t * src = reinterpret_cast<const uint8_t *>(&_binary_font_verite_8x16_verite_8x16_data_start);
uint32_t offset = font_bitmap::inflate(1, // pitch
8, // width
16, // height
8, // texture_width
16, // texture_height
src);
printf("font_offset %d actual %d\n", font_offset, offset);
}
int main() int main()
{ {
serial::init(0); serial::init(0);
interrupt_init(); interrupt_init();
transfer_textures(); transfer_textures();
transfer_font();
palette_data<3>();
constexpr uint32_t ta_alloc = 0 constexpr uint32_t ta_alloc = 0
| ta_alloc_ctrl::pt_opb::no_list | ta_alloc_ctrl::pt_opb::no_list
| ta_alloc_ctrl::tm_opb::no_list | ta_alloc_ctrl::tm_opb::no_list
| ta_alloc_ctrl::t_opb::no_list | ta_alloc_ctrl::t_opb::_16x4byte
| ta_alloc_ctrl::om_opb::no_list | ta_alloc_ctrl::om_opb::no_list
| ta_alloc_ctrl::o_opb::_16x4byte; | ta_alloc_ctrl::o_opb::_16x4byte;
@ -542,7 +871,7 @@ int main()
{ {
.opaque = 16 * 4, .opaque = 16 * 4,
.opaque_modifier = 0, .opaque_modifier = 0,
.translucent = 0, .translucent = 16 * 4,
.translucent_modifier = 0, .translucent_modifier = 0,
.punch_through = 0 .punch_through = 0
} }
@ -581,10 +910,10 @@ int main()
int core = 0; int core = 0;
mat4x4 trans = { mat4x4 trans = {
1, 0, 0, -1000, 1.0, 0.0, 0.000, -1400.0,
0, 1, 0, -1000, 0.0, -0.574, -0.818, 981.0,
0, 0, 1, 1000, 0.0, 0.818, -0.574, 711.0,
0, 0, 0, 1, 0.0, 0.000, 0.000, 1.0,
}; };
do_get_condition(); do_get_condition();
@ -608,7 +937,8 @@ int main()
transfer_scene(writer, trans); transfer_scene(writer, trans);
ta_polygon_converter_writeback(writer.buf, writer.offset); ta_polygon_converter_writeback(writer.buf, writer.offset);
ta_polygon_converter_transfer(writer.buf, writer.offset); ta_polygon_converter_transfer(writer.buf, writer.offset);
ta_wait_opaque_list(); ta_wait_translucent_list();
//ta_wait_opaque_list();
render_done = 0; render_done = 0;
core_start_render2(texture_memory_alloc.region_array[core].start, core_start_render2(texture_memory_alloc.region_array[core].start,

View File

@ -2,7 +2,7 @@
#include "../holly/holly.hpp" #include "../holly/holly.hpp"
#include "../holly/core_bits.hpp" #include "../holly/core_bits.hpp"
#include "../holly/texture_memory_alloc.hpp" #include "../holly/texture_memory_alloc3.hpp"
#include "../holly/isp_tsp.hpp" #include "../holly/isp_tsp.hpp"
#include "../holly/ta_parameter.hpp" #include "../holly/ta_parameter.hpp"
#include "../holly/ta_global_parameter.hpp" #include "../holly/ta_global_parameter.hpp"
@ -47,7 +47,7 @@ static inline void inflate_character(const uint32_t pitch,
} }
} }
auto texture = reinterpret_cast<volatile uint32_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]); auto texture = reinterpret_cast<volatile uint32_t *>(&texture_memory64[texture_memory_alloc.texture.start / 4]);
uint8_t temp2[texture_width * texture_height / 2]; uint8_t temp2[texture_width * texture_height / 2];
@ -137,7 +137,7 @@ void transform_string(ta_parameter_writer& parameter,
if (len < 0) { if (len < 0) {
if (s[string_ix] == 0) break; if (s[string_ix] == 0) break;
} else if (string_ix >= len) break; } else if (string_ix >= len) break;
const uint32_t texture_address = texture_memory_alloc::texture.start; const uint32_t texture_address = texture_memory_alloc.texture.start;
const uint32_t glyph_address = texture_address + texture_width * texture_height * (s[string_ix] - ' ') / 2; const uint32_t glyph_address = texture_address + texture_width * texture_height * (s[string_ix] - ' ') / 2;
const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette
| texture_control_word::scan_order::twiddled | texture_control_word::scan_order::twiddled

View File

@ -0,0 +1,78 @@
# Blender 4.2.1 LTS
# www.blender.org
o Icosphere
v 0.000000 -1.000000 0.000000
v 0.723600 -0.447215 0.525720
v -0.276385 -0.447215 0.850640
v -0.894425 -0.447215 0.000000
v -0.276385 -0.447215 -0.850640
v 0.723600 -0.447215 -0.525720
v 0.276385 0.447215 0.850640
v -0.723600 0.447215 0.525720
v -0.723600 0.447215 -0.525720
v 0.276385 0.447215 -0.850640
v 0.894425 0.447215 0.000000
v 0.000000 1.000000 0.000000
vn 0.1876 -0.7947 0.5774
vn 0.6071 -0.7947 -0.0000
vn -0.4911 -0.7947 0.3568
vn -0.4911 -0.7947 -0.3568
vn 0.1876 -0.7947 -0.5774
vn 0.9822 -0.1876 -0.0000
vn 0.3035 -0.1876 0.9342
vn -0.7946 -0.1876 0.5774
vn -0.7946 -0.1876 -0.5774
vn 0.3035 -0.1876 -0.9342
vn 0.7946 0.1876 0.5774
vn -0.3035 0.1876 0.9342
vn -0.9822 0.1876 -0.0000
vn -0.3035 0.1876 -0.9342
vn 0.7946 0.1876 -0.5774
vn 0.4911 0.7947 0.3568
vn -0.1876 0.7947 0.5774
vn -0.6071 0.7947 -0.0000
vn -0.1876 0.7947 -0.5774
vn 0.4911 0.7947 -0.3568
vt 0.181819 0.000000
vt 0.272728 0.157461
vt 0.090910 0.157461
vt 0.363637 0.000000
vt 0.454546 0.157461
vt 0.909091 0.000000
vt 1.000000 0.157461
vt 0.818182 0.157461
vt 0.727273 0.000000
vt 0.636364 0.157461
vt 0.545455 0.000000
vt 0.363637 0.314921
vt 0.181819 0.314921
vt 0.909091 0.314921
vt 0.727273 0.314921
vt 0.545455 0.314921
vt 0.000000 0.314921
vt 0.272728 0.472382
vt 0.090910 0.472382
vt 0.818182 0.472382
vt 0.636364 0.472382
vt 0.454546 0.472382
s 0
f 1/1/1 2/2/1 3/3/1
f 2/2/2 1/4/2 6/5/2
f 1/6/3 3/7/3 4/8/3
f 1/9/4 4/8/4 5/10/4
f 1/11/5 5/10/5 6/5/5
f 2/2/6 6/5/6 11/12/6
f 3/3/7 2/2/7 7/13/7
f 4/8/8 3/7/8 8/14/8
f 5/10/9 4/8/9 9/15/9
f 6/5/10 5/10/10 10/16/10
f 2/2/11 11/12/11 7/13/11
f 3/3/12 7/13/12 8/17/12
f 4/8/13 8/14/13 9/15/13
f 5/10/14 9/15/14 10/16/14
f 6/5/15 10/16/15 11/12/15
f 7/13/16 11/12/16 12/18/16
f 8/17/17 7/13/17 12/19/17
f 9/15/18 8/14/18 12/20/18
f 10/16/19 9/15/19 12/21/19
f 11/12/20 10/16/20 12/22/20

View File

@ -12,6 +12,7 @@ int unparse_base10(char * s, int32_t n, int len, char fill);
int unparse_base10_64(char * s, int64_t n, int len, char fill); int unparse_base10_64(char * s, int64_t n, int len, char fill);
int unparse_base16(char * s, uint32_t n, int len, char fill); int unparse_base16(char * s, uint32_t n, int len, char fill);
int digits_base10(uint32_t n);
int digits_base_64(uint64_t n); int digits_base_64(uint64_t n);
int digits_base10_64(uint64_t n); int digits_base10_64(uint64_t n);