288 lines
7.3 KiB
C++
288 lines
7.3 KiB
C++
#include "holly/background.hpp"
|
|
#include "holly/holly.hpp"
|
|
|
|
#include "math/float_types.hpp"
|
|
#include "math/transform.hpp"
|
|
|
|
#include "ta_parameter.hpp"
|
|
|
|
#include "scene/logo/scene.hpp"
|
|
#include "scene/logo/sound.hpp"
|
|
|
|
#include "texture.hpp"
|
|
#include "framebuffer.hpp"
|
|
|
|
#include "model/blender_export.h"
|
|
#include "model/32bitlogo/model.h"
|
|
|
|
static vec3 screen_transform(const vec3& v)
|
|
{
|
|
return {v.x, v.y, 1.0f / v.z};
|
|
}
|
|
|
|
static inline float light_intensity(vec3 n, vec3 l)
|
|
{
|
|
float ambient = 0.4f;
|
|
float diffuse_strength = 0.7f;
|
|
|
|
float n_dot_l = dot(n, l);
|
|
float diffuse = 0;
|
|
if (n_dot_l > 0)
|
|
diffuse = diffuse_strength * n_dot_l * (inverse_length(n) * inverse_length(l));
|
|
|
|
return ambient + diffuse;
|
|
}
|
|
|
|
vec3 light_vec = (vec3){-1, -1, -1} - (vec3){0, 0, 0};
|
|
|
|
using vec3i = vec<3, int>;
|
|
|
|
static inline vec3i color_lerp(const vec3i& a, const vec3i& b, float f)
|
|
{
|
|
float dr = b.x - a.x;
|
|
float dg = b.y - a.y;
|
|
float db = b.z - a.z;
|
|
|
|
return {
|
|
(int)((float)a.x + dr * f),
|
|
(int)((float)a.y + dg * f),
|
|
(int)((float)a.z + db * f),
|
|
};
|
|
}
|
|
|
|
static inline int vec3i_to_int(const vec3i& a)
|
|
{
|
|
return (a.x << 16) | (a.y << 8) | (a.z << 0);
|
|
}
|
|
|
|
static void render_mesh(ta_parameter_writer& writer, const mesh& mesh, const mat4x4& trans, float base_intensity, bool wireframe, bool diffuse)
|
|
{
|
|
if (wireframe) {
|
|
global_polygon_untextured(writer,
|
|
para_control::list_type::translucent,
|
|
tsp_instruction_word::dst_alpha_instr::zero);
|
|
} else {
|
|
uint32_t texture_size = tsp_instruction_word::texture_u_size::from_int(8)
|
|
| tsp_instruction_word::texture_v_size::from_int(8);
|
|
|
|
global_polygon_intensity(writer,
|
|
para_control::list_type::translucent,
|
|
texture::offset::logo,
|
|
texture_size,
|
|
texture_control_word::pixel_format::_565);
|
|
}
|
|
|
|
vec3 position_cache[mesh.position_length];
|
|
for (int i = 0; i < mesh.position_length; i++) {
|
|
position_cache[i] = screen_transform(trans * mesh.position[i]);
|
|
}
|
|
vec3 normal_cache[mesh.polygons_length];
|
|
for (int i = 0; i < mesh.polygons_length; i++) {
|
|
normal_cache[i] = normal_multiply(trans, mesh.polygon_normal[i]);
|
|
}
|
|
|
|
const vec3i white = vec3i(0xc0, 0xbe, 0xbc);
|
|
const vec3i green = vec3i(0x33, 0xd1, 0x7a);
|
|
|
|
const int wireframe_color = vec3i_to_int(color_lerp(white, green, base_intensity));
|
|
|
|
//const int green = (int)(255.f * base_intensity) << 8;
|
|
|
|
for (int i = 0; i < mesh.polygons_length; i++) {
|
|
const polygon& p = mesh.polygons[i];
|
|
|
|
vec3 ap = position_cache[p.a];
|
|
vec3 bp = position_cache[p.b];
|
|
vec3 cp = position_cache[p.c];
|
|
vec3 dp = position_cache[p.d];
|
|
|
|
if (wireframe) {
|
|
line_type_0(writer, ap, bp, wireframe_color);
|
|
line_type_0(writer, bp, cp, wireframe_color);
|
|
if (p.d == -1) {
|
|
line_type_0(writer, cp, ap, wireframe_color);
|
|
} else {
|
|
line_type_0(writer, cp, dp, wireframe_color);
|
|
line_type_0(writer, dp, ap, wireframe_color);
|
|
}
|
|
} else {
|
|
vec2 at = mesh.uv_layers[0][p.uv_index + 0];
|
|
vec2 bt = mesh.uv_layers[0][p.uv_index + 1];
|
|
vec2 ct = mesh.uv_layers[0][p.uv_index + 2];
|
|
vec2 dt = mesh.uv_layers[0][p.uv_index + 3];
|
|
|
|
float intensity = diffuse ? light_intensity(normal_cache[i], light_vec) : 1.0;
|
|
|
|
if (p.d == -1) {
|
|
tri_type_7(writer,
|
|
ap, at,
|
|
bp, bt,
|
|
cp, ct,
|
|
intensity);
|
|
} else {
|
|
quad_type_7(writer,
|
|
ap, at,
|
|
bp, bt,
|
|
cp, ct,
|
|
dp, dt,
|
|
intensity);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace scene::logo {
|
|
|
|
const struct scene::scene scene = {
|
|
.ta_alloc = ta_alloc_ctrl::pt_opb::no_list
|
|
| ta_alloc_ctrl::tm_opb::no_list
|
|
| ta_alloc_ctrl::t_opb::_32x4byte
|
|
| ta_alloc_ctrl::om_opb::no_list
|
|
| ta_alloc_ctrl::o_opb::no_list,
|
|
.opb_size = {
|
|
.opaque = 0,
|
|
.opaque_modifier = 0,
|
|
.translucent = 32 * 4,
|
|
.translucent_modifier = 0,
|
|
.punch_through = 0
|
|
},
|
|
.transfer = transfer,
|
|
.interrupt = sound::interrupt,
|
|
.init = init,
|
|
.done = done
|
|
};
|
|
|
|
static int tick = 0;
|
|
static int last_tick = 0;
|
|
|
|
struct keyframe {
|
|
float i; // intensity
|
|
float rx; // rotate_x
|
|
float ry; // rotate_y
|
|
float s; // scale
|
|
float duration;
|
|
};
|
|
|
|
const struct keyframe keyframes[] = {
|
|
{
|
|
.i = 0,
|
|
.rx = 0,
|
|
.ry = pi,
|
|
.s = 0.01,
|
|
.duration = 1.0 / (3.670),
|
|
},
|
|
{
|
|
.i = 1,
|
|
.rx = 0,
|
|
.ry = pi,
|
|
.s = 0.1,
|
|
.duration = 1.0 / (10.988),
|
|
},
|
|
{
|
|
.i = 1,
|
|
.rx = pi / 4,
|
|
.ry = -(pi - pi / 4),
|
|
.s = 0.7,
|
|
.duration = 1.0 / (10),
|
|
},
|
|
};
|
|
|
|
const int keyframes_length = (sizeof (keyframes)) / (sizeof (keyframes[0]));
|
|
|
|
static inline float clamp(float f)
|
|
{
|
|
if (f > 1.0)
|
|
return 1.0;
|
|
else if (f < 0.0)
|
|
return 0.0;
|
|
else
|
|
return f;
|
|
}
|
|
|
|
static inline keyframe interpolate(const keyframe& a, const keyframe& b, const float dt, const float tick_div)
|
|
{
|
|
float ratio = clamp(dt * a.duration * tick_div);
|
|
|
|
float di = b.i - a.i;
|
|
float drx = b.rx - a.rx;
|
|
float dry = b.ry - a.ry;
|
|
float ds = b.s - a.s;
|
|
|
|
return {
|
|
.i = a.i + di * ratio,
|
|
.rx = a.rx + drx * ratio,
|
|
.ry = a.ry + dry * ratio,
|
|
.s = a.s + ds * ratio,
|
|
.duration = 0,
|
|
};
|
|
}
|
|
|
|
void transfer(ta_multiwriter& multi)
|
|
{
|
|
vec3 t = {framebuffer.px_width / 2.f, framebuffer.px_height / 2.f, 0};
|
|
float s = framebuffer.px_height / 3.f;
|
|
|
|
static int keyframe_ix = 0;
|
|
|
|
const float tick_div = framebuffer.px_height == 480 ? (1.0 / 60.0) : (1.0 / 120.0);
|
|
const float tick_mul = framebuffer.px_height == 480 ? 60 : 120;
|
|
|
|
float dt = tick - last_tick;
|
|
if (dt * keyframes[keyframe_ix].duration * tick_div >= 1) {
|
|
if (keyframe_ix < (keyframes_length - 2)) {
|
|
last_tick = tick;
|
|
dt = 0;
|
|
keyframe_ix += 1;
|
|
}
|
|
}
|
|
keyframe k = interpolate(keyframes[keyframe_ix], keyframes[keyframe_ix + 1], dt, tick_div);
|
|
|
|
mat4x4 trans
|
|
= translate(t)
|
|
* scale((vec3){s, s, 1})
|
|
* translate((vec3){0, 0, 10})
|
|
//* rotate_x(pi / 8)
|
|
//* rotate_y(pi + pi/8)
|
|
* scale(k.s)
|
|
* rotate_x(k.rx)
|
|
* rotate_y(k.ry)
|
|
* scale((vec3){-1, -1, 1});
|
|
|
|
bool _32_wf = tick < (10.988 * tick_mul);
|
|
bool bit_wf = tick < (11.908 * tick_mul);
|
|
bool jam_wf = tick < (12.825 * tick_mul);
|
|
|
|
bool diffuse = tick >= (14.608 * tick_mul);
|
|
|
|
render_mesh(multi.op, mesh_thirty_two, trans, k.i, _32_wf, diffuse);
|
|
if (keyframe_ix > 0) {
|
|
render_mesh(multi.op, mesh_bit, trans, k.i, bit_wf, diffuse);
|
|
render_mesh(multi.op, mesh_jam, trans, k.i, jam_wf, diffuse);
|
|
}
|
|
|
|
tick += 1;
|
|
}
|
|
|
|
void init()
|
|
{
|
|
background_parameter2(texture_memory_alloc.background[1].start,
|
|
0xc0bebc);
|
|
holly.VO_BORDER_COL = 0xc0bebc;
|
|
|
|
::scene::logo::sound::init();
|
|
}
|
|
|
|
int done()
|
|
{
|
|
float tick_mul = framebuffer.px_height == 480 ? 60 : 120;
|
|
|
|
if (tick >= (20.000 * tick_mul)) {
|
|
int scene_id = ::scene::id::tracker;
|
|
printf("scene transition to tracker %d\n", scene_id);
|
|
return scene_id;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|