example/md5: add textures

This commit is contained in:
Zack Buhman 2025-05-13 03:26:47 -05:00
parent 29b7f2b351
commit f72e3da6c1
15 changed files with 680 additions and 33 deletions

View File

@ -47,6 +47,11 @@ using vec3 = vec<3, float>;
using vec4 = vec<4, float>;
using mat4x4 = mat<4, 4, float>;
#include "model/boblamp/guard1_body.data.h"
#include "model/boblamp/guard1_face.data.h"
#include "model/boblamp/guard1_helmet.data.h"
#include "model/boblamp/iron_grill.data.h"
#include "model/boblamp/round_grill.data.h"
#include "md5/md5mesh.h"
#include "md5/md5anim.h"
#include "model/boblamp/boblamp_mesh.h"
@ -241,6 +246,9 @@ void transfer_triangle(ta_parameter_writer& writer,
vec3 ap,
vec3 bp,
vec3 cp,
vec2 at,
vec2 bt,
vec2 ct,
vec3 ac,
vec3 bc,
vec3 cc
@ -249,23 +257,29 @@ void transfer_triangle(ta_parameter_writer& writer,
if (ap.z < 0 || bp.z < 0 || cp.z < 0)
return;
writer.append<ta_vertex_parameter::polygon_type_1>() =
ta_vertex_parameter::polygon_type_1(polygon_vertex_parameter_control_word(false),
writer.append<ta_vertex_parameter::polygon_type_5>() =
ta_vertex_parameter::polygon_type_5(polygon_vertex_parameter_control_word(false),
ap.x, ap.y, ap.z,
at.x, at.y,
1.0,
ac.x, ac.y, ac.z);
ac.x, ac.y, ac.z,
0, 0, 0, 0);
writer.append<ta_vertex_parameter::polygon_type_1>() =
ta_vertex_parameter::polygon_type_1(polygon_vertex_parameter_control_word(false),
writer.append<ta_vertex_parameter::polygon_type_5>() =
ta_vertex_parameter::polygon_type_5(polygon_vertex_parameter_control_word(false),
bp.x, bp.y, bp.z,
bt.x, bt.y,
1.0,
bc.x, bc.y, bc.z);
bc.x, bc.y, bc.z,
0, 0, 0, 0);
writer.append<ta_vertex_parameter::polygon_type_1>() =
ta_vertex_parameter::polygon_type_1(polygon_vertex_parameter_control_word(true),
writer.append<ta_vertex_parameter::polygon_type_5>() =
ta_vertex_parameter::polygon_type_5(polygon_vertex_parameter_control_word(true),
cp.x, cp.y, cp.z,
ct.x, ct.y,
1.0,
cc.x, cc.y, cc.z);
cc.x, cc.y, cc.z,
0, 0, 0, 0);
}
vec4 quaternion_normalize(vec4 q)
@ -403,7 +417,7 @@ vec3 vertex_weight_color(const md5_mesh_joint * joints,
}
}
return {0.0, 0.0, 1.0};
return {1.0, 1.0, 1.0};
}
static inline vec3 screen_transform(vec3 v)
@ -469,6 +483,9 @@ void transfer_mesh(ta_parameter_writer& writer,
screen_transform(ap),
screen_transform(bp),
screen_transform(cp),
av->tex,
bv->tex,
cv->tex,
ac * a_diffuse,
bc * b_diffuse,
cc * c_diffuse
@ -476,20 +493,29 @@ void transfer_mesh(ta_parameter_writer& writer,
}
}
void transfer_scene(ta_parameter_writer& writer,
const mat4x4& screen_trans)
void global_polygon(ta_parameter_writer& writer, const md5_shader * shader)
{
uint32_t control = para_control::list_type::opaque;
uint32_t control = para_control::list_type::opaque
| obj_control::texture;
uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one
| tsp_instruction_word::dst_alpha_instr::zero
| tsp_instruction_word::fog_control::no_fog
| tsp_instruction_word::texture_shading_instruction::decal;
uint32_t texture_control_word = 0;
| tsp_instruction_word::texture_shading_instruction::modulate
| tsp_instruction_word::texture_u_size::from_int(shader->width)
| tsp_instruction_word::texture_v_size::from_int(shader->height);
uint32_t texture_address = texture_memory_alloc.texture.start + shader->offset;
uint32_t texture_control_word = texture_control_word::pixel_format::_565
| texture_control_word::scan_order::twiddled
| texture_control_word::texture_address(texture_address / 8);
global_polygon_type_0(writer,
control,
tsp_instruction_word,
texture_control_word);
}
void transfer_scene(ta_parameter_writer& writer,
const mat4x4& screen_trans)
{
int frame_ix0 = animation_tick / ticks_per_animation_frame;
int frame_ix1 = frame_ix0 + 1;
if (frame_ix1 >= animation_frames)
@ -500,8 +526,13 @@ void transfer_scene(ta_parameter_writer& writer,
float lerp = (float)(animation_tick - (frame_ix0 * ticks_per_animation_frame)) * tick_div;
interpolate_skeleton(anim->num_joints, skeleton0, skeleton1, lerp);
const md5_shader * last_shader = NULL;
for (int i = 0; i < boblamp_mesh.num_meshes; i++) {
transfer_mesh(writer, screen_trans, boblamp_mesh.joints, &boblamp_mesh.meshes[i]);
const md5_mesh_mesh * mesh = &boblamp_mesh.meshes[i];
if (last_shader != mesh->shader)
global_polygon(writer, mesh->shader);
transfer_mesh(writer, screen_trans, boblamp_mesh.joints, mesh);
}
writer.append<ta_global_parameter::end_of_list>() =
@ -554,6 +585,57 @@ void update_maple(struct md5_mesh * m, struct md5_anim * a)
last_da = da;
}
void transfer_ta_fifo_texture_memory_32byte(void * dst, const void * src, int length)
{
assert((((int)dst) & 31) == 0);
assert((((int)length) & 31) == 0);
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 & 0x03ffffe0) / 4];
const uint32_t * src32 = reinterpret_cast<const 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_boblamp_textures()
{
for (uint32_t i = 0; i < (sizeof (boblamp_shaders)) / (sizeof (boblamp_shaders[0])); i++) {
const md5_shader * shader = boblamp_shaders[i];
uint32_t offset = texture_memory_alloc.texture.start + shader->offset;
void * dst = reinterpret_cast<void *>(&ta_fifo_texture_memory[offset / 4]);
transfer_ta_fifo_texture_memory_32byte(dst, shader->start, shader->size);
}
}
void transfer_textures()
{
system.LMMODE0 = 0; // 64-bit address space
system.LMMODE1 = 0; // 64-bit address space
transfer_boblamp_textures();
}
uint8_t __attribute__((aligned(32))) ta_parameter_buf[1024 * 1024];
int main()
@ -591,6 +673,8 @@ int main()
background_parameter2(texture_memory_alloc.background[0].start,
0xff202040);
transfer_textures();
ta_parameter_writer writer = ta_parameter_writer(ta_parameter_buf, (sizeof (ta_parameter_buf)));
video_output::set_mode_vga();
@ -612,7 +696,7 @@ int main()
do_get_condition();
update_maple(&boblamp_mesh, &boblamp_anim);
//screen_trans = screen_trans * rotate_z(0.01f);
screen_trans = screen_trans * rotate_z(0.003f);
writer.offset = 0;
transfer_scene(writer, screen_trans);

View File

@ -28,5 +28,5 @@ constexpr texture_memory_alloc texture_memory_alloc = {
.background = {{0x1c2000, 0x1c2020},
{0x5c2000, 0x5c2020}},
// 64-bit addresses
.texture = {0x384040, 0x800000}
.texture = {0x384080, 0x800000}
};

View File

@ -30,8 +30,16 @@ struct md5_mesh_weight {
const vec3 pos;
};
struct md5_shader {
const void * start;
const int size;
const int width;
const int height;
const int offset;
};
struct md5_mesh_mesh {
const char * shader;
const md5_shader * shader;
const int num_verts;
const md5_mesh_vert * verts;
const int num_tris;

View File

@ -2,6 +2,8 @@ from generate import renderer
from math import sqrt
import sys
import md5mesh
from os import path
from PIL import Image
def vec2(a, b):
return f"{{{a:.6f}, {b:.6f}}}"
@ -19,6 +21,13 @@ def unit_quaternion_w(x, y, z):
else:
return -sqrt(t)
def sanitize_name(name):
return name.replace("-", "_").replace("/", "_").replace(".", "_")
def shader_to_data_name(shader):
name = path.splitext(shader)[0]
return sanitize_name(name)
def render_md5_mesh_joint(joint):
yield f'.bone_name = "{joint.bone_name}",'
yield f".parent_index = {joint.parent_index},"
@ -48,7 +57,8 @@ def render_md5_mesh_weight(weight):
yield f".pos = {pos},"
def render_md5_mesh_mesh(prefix, i, mesh):
yield f'.shader = "{mesh.shader}",'
name = shader_to_data_name(mesh.shader)
yield f'.shader = &{prefix}_{name}, // {mesh.shader}'
yield f".num_verts = {mesh.num_verts},"
yield f".verts = {prefix}_{i}_verts,"
yield f".num_tris = {mesh.num_tris},"
@ -94,12 +104,47 @@ def render_md5_mesh_joints(prefix, joints):
yield "},"
yield "};"
def render_md5_mesh_meshes(prefix, meshes):
offset = None
def render_shader(prefix, dirname, shader):
global offset
name = shader_to_data_name(shader)
dir = sanitize_name(dirname)
filename = path.join(dirname, shader)
with Image.open(filename) as im:
width, height = im.size
yield f"struct md5_shader {prefix}_{name} = {{"
yield f".start = (void *)&_binary_{dir}_{name}_data_start,"
yield f".size = (int)&_binary_{dir}_{name}_data_size,"
yield f".width = {width},"
yield f".height = {height},"
yield f".offset = {offset},"
yield "};"
offset += width * height * 2
def render_md5_mesh_shaders(prefix, dirname, meshes):
global offset
offset = 0
shaders = set(mesh.shader for mesh in meshes)
for shader in shaders:
yield from render_shader(prefix, dirname, shader)
yield f"struct md5_shader * {prefix}_shaders[] = {{"
for shader in shaders:
name = shader_to_data_name(shader)
yield f"&{prefix}_{name},"
yield "};"
def render_md5_mesh_meshes(prefix, dirname, meshes):
for i, mesh in enumerate(meshes):
yield from render_md5_mesh_verts(prefix, i, mesh.verts)
yield from render_md5_mesh_tris(prefix, i, mesh.tris)
yield from render_md5_mesh_weights(prefix, i, mesh.weights)
yield from render_md5_mesh_shaders(prefix, dirname, meshes)
yield f"struct md5_mesh_mesh {prefix}_meshes[] = {{"
for i, mesh in enumerate(meshes):
yield "{"
@ -107,23 +152,28 @@ def render_md5_mesh_meshes(prefix, meshes):
yield "},"
yield "};"
def render_mesh(prefix, m):
def render_mesh(prefix, dirname, m):
yield from render_md5_mesh_joints(prefix, m.joints)
yield from render_md5_mesh_meshes(prefix, m.meshes)
yield from render_md5_mesh_meshes(prefix, dirname, m.meshes)
yield f"struct md5_mesh {prefix}_mesh = {{"
yield from render_md5_mesh(prefix, m)
yield "};"
def render_all(prefix, m):
yield from render_mesh(prefix, m)
def render_all(prefix, dirname, m):
yield from render_mesh(prefix, dirname, m)
if __name__ == "__main__":
with open(sys.argv[1], 'r') as f:
filename = sys.argv[1]
prefix = sys.argv[2]
dirname = path.split(filename)[0]
with open(filename, 'r') as f:
buf = f.read()
l = [i.strip() for i in buf.split('\n') if i.strip()]
m = md5mesh.parse_file(l)
render, out = renderer()
render(render_all(sys.argv[2], m))
render(render_all(prefix, dirname, m))
sys.stdout.write(out.getvalue())

View File

@ -17759,9 +17759,57 @@ struct md5_mesh_weight boblamp_5_weights[] = {
},
};
struct md5_shader boblamp_guard1_helmet = {
.start = (void *)&_binary_model_boblamp_guard1_helmet_data_start,
.size = (int)&_binary_model_boblamp_guard1_helmet_data_size,
.width = 256,
.height = 256,
.offset = 0,
};
struct md5_shader boblamp_round_grill = {
.start = (void *)&_binary_model_boblamp_round_grill_data_start,
.size = (int)&_binary_model_boblamp_round_grill_data_size,
.width = 256,
.height = 256,
.offset = 131072,
};
struct md5_shader boblamp_iron_grill = {
.start = (void *)&_binary_model_boblamp_iron_grill_data_start,
.size = (int)&_binary_model_boblamp_iron_grill_data_size,
.width = 256,
.height = 256,
.offset = 262144,
};
struct md5_shader boblamp_guard1_face = {
.start = (void *)&_binary_model_boblamp_guard1_face_data_start,
.size = (int)&_binary_model_boblamp_guard1_face_data_size,
.width = 512,
.height = 256,
.offset = 393216,
};
struct md5_shader boblamp_guard1_body = {
.start = (void *)&_binary_model_boblamp_guard1_body_data_start,
.size = (int)&_binary_model_boblamp_guard1_body_data_size,
.width = 512,
.height = 512,
.offset = 655360,
};
struct md5_shader * boblamp_shaders[] = {
&boblamp_guard1_helmet,
&boblamp_round_grill,
&boblamp_iron_grill,
&boblamp_guard1_face,
&boblamp_guard1_body,
};
struct md5_mesh_mesh boblamp_meshes[] = {
{
.shader = "guard1_body.tga",
.shader = &boblamp_guard1_body, // guard1_body.tga
.num_verts = 494,
.verts = boblamp_0_verts,
.num_tris = 628,
@ -17770,7 +17818,7 @@ struct md5_mesh_mesh boblamp_meshes[] = {
.weights = boblamp_0_weights,
},
{
.shader = "guard1_face.tga",
.shader = &boblamp_guard1_face, // guard1_face.tga
.num_verts = 110,
.verts = boblamp_1_verts,
.num_tris = 177,
@ -17779,7 +17827,7 @@ struct md5_mesh_mesh boblamp_meshes[] = {
.weights = boblamp_1_weights,
},
{
.shader = "guard1_helmet.tga",
.shader = &boblamp_guard1_helmet, // guard1_helmet.tga
.num_verts = 80,
.verts = boblamp_2_verts,
.num_tris = 78,
@ -17788,7 +17836,7 @@ struct md5_mesh_mesh boblamp_meshes[] = {
.weights = boblamp_2_weights,
},
{
.shader = "iron_grill.tga",
.shader = &boblamp_iron_grill, // iron_grill.tga
.num_verts = 18,
.verts = boblamp_3_verts,
.num_tris = 16,
@ -17797,7 +17845,7 @@ struct md5_mesh_mesh boblamp_meshes[] = {
.weights = boblamp_3_weights,
},
{
.shader = "round_grill.tga",
.shader = &boblamp_round_grill, // round_grill.tga
.num_verts = 38,
.verts = boblamp_4_verts,
.num_tris = 22,
@ -17806,7 +17854,7 @@ struct md5_mesh_mesh boblamp_meshes[] = {
.weights = boblamp_4_weights,
},
{
.shader = "guard1_body.tga",
.shader = &boblamp_guard1_body, // guard1_body.tga
.num_verts = 135,
.verts = boblamp_5_verts,
.num_tris = 106,

Binary file not shown.

View File

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

File diff suppressed because one or more lines are too long

View File

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

Binary file not shown.

View File

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

Binary file not shown.

View File

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

Binary file not shown.

View File

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