using System.Collections.Generic; using StereoKit; namespace slash; static class Arts { static Model assets_model = Model.FromFile("meshes/assets.glb", Shader.Unlit); static Dictionary meshes = new(); static Material mat_mono = new Material("mono.hlsl"); static Material mat_unlit = new Material("unlit.hlsl"); static Material mat_add = new Material("unlit.hlsl"); static Material mat_both = new Material("unlit.hlsl"); static Material mat_backface = new Material("backface.hlsl"); static Material mat_justcolor = new Material("justcolor.hlsl"); static Material mat_slash = new Material("unlit.hlsl"); public static Vec3 shake = new(0, 0, 0); // static Quat spin_ori = Quat.Identity; public static Vec3 last_tip_pos = new(0, 0, 0); static TextStyle text_style; public static void Init() { foreach (ModelNode node in assets_model.Nodes) { if (node.Mesh != null && node.Child == null) // [!] sloppy way to differentiate { meshes.Add(node.Name, node.Mesh); } else { // parse enemy cols for (int i = 0; i < Mono.enemy_types.Length; i++) { Enemy enemy_type = Mono.enemy_types[i]; if (node.Name == enemy_type.col_ref) { ModelNode sibling = node.Child; while (sibling != null) { enemy_type.cols.Add(new( sibling.LocalTransform.Pose.position, sibling.LocalTransform.Scale.x * 2.0f )); sibling = sibling.Sibling; } } } } } text_style = TextStyle.FromFont( Font.FromFile("Assets/Staatliches.ttf"), 1.0f * U.cm, Color.White ); mat_add.Transparency = Transparency.Add; mat_add.DepthTest = DepthTest.LessOrEq; mat_add.DepthWrite = false; mat_backface.FaceCull = Cull.Front; mat_backface.Transparency = Transparency.Add; mat_backface.DepthTest = DepthTest.LessOrEq; mat_backface.DepthWrite = false; mat_both.Chain = mat_backface; mat_slash.FaceCull = Cull.None; } public static void Frame() { // Input.HandVisible(Handed.Max, false); // world Matrix m4_world = Mono.world_pose.ToMatrix(); Hierarchy.Push(m4_world); // ground meshes["circle"].Draw( mat_unlit, Matrix.TRS( V.XYZ(0, 0, 0), Quat.Identity, 12.0f ), Color.Hex(0x808080FF).ToLinear() ); // bamboo for (int i = -12; i <= 12; i++) { float z_offset = Noise.s_scalar_x(i) * 2.0f; float x_offset = Noise.s_scalar_x(i + 32) * 0.2f; float x_wind = Maths.smooth_stop(Maths.u_scalar(SKMath.Sin((i * 0.16f) - Time.Totalf))); Vec3[] p = new Vec3[] { V.XYZ(i * 0.3f, 0, -10 + z_offset), V.XYZ(i * 0.3f, 1, -10 + z_offset), V.XYZ(i * 0.3f, 4, -10 + z_offset), V.XYZ(i * 0.3f + x_offset + x_wind, 5, -10 + z_offset), }; // debug bezier points // for (int i = 0; i < p.Length; i++) // { // Mesh.Sphere.Draw( // mat_justcolor, // Matrix.TS( // p[i], // 2 * U.mm // ), // Color.White // ); // } // ground bump // Mesh.Sphere.Draw( // mat_justcolor, // Matrix.TS( // box_mount, // 3 * U.mm // ), // Color.Hex(0x959493FF).ToLinear() // ); int steps = 92; Vec3 pastPos = p[0]; float pastThc = 0.0f; for (int j = 0; j < steps; j++) { float t = (float)j / (steps - 1); Vec3 a = Vec3.Lerp(p[0], p[1], t); Vec3 b = Vec3.Lerp(p[1], p[2], t); Vec3 c = Vec3.Lerp(p[2], p[3], t); Vec3 pos = Vec3.Lerp(Vec3.Lerp(a, b, t), Vec3.Lerp(b, c, t), t); float thc = (1.0f + Maths.precision((1.0f - t), Maths.lerp(0.1f, 0.2f, Noise.u_scalar_x(i))) * 2.0f) * U.cm * 6.0f; Lines.Add( pastPos, pos, thc != pastThc ? Color.Hex(0x959493FF).ToLinear() : Color.Hex(0xB9E7AFFF).ToLinear(), thc ); pastPos = pos; pastThc = thc; } } // unit cube // Mesh.Cube.Draw( // mat_unlit, // Matrix.Identity, // Color.Hex(0x13180AFF).ToLinear() // ); // enemy Enemy enemy_test = Mono.enemy_types[(int)(Time.Totalf % Mono.enemy_types.Length)]; Quat enemy_orbit = Quat.FromAngles(0, 0, 45) * Quat.FromAngles(0, (Time.Totalf * 30) % 360, 0); enemy_test.pose.position = V.XYZ(0, 0, -3.0f) + enemy_orbit * V.XYZ(0, 0, -3); // V.XYZ(SKMath.Sin(Time.Totalf * 1f) * 1.0f, 0.666f, -3.0f); for (int i = 0; i < enemy_test.cols.Count; i++) { Sphere col = enemy_test.cols[i]; Mesh.Sphere.Draw( mat_mono, Matrix.TS( col.center, col.radius * 2.0f ) * enemy_test.pose.ToMatrix(), Color.Hex(0x13180AFF).ToLinear() ); } // eyes // Mesh.Cube.Draw( // mat_unlit, // Rig.head.ToMatrix().Transform(), // Color.Hex(0x13180AFF).ToLinear() // ); // blade Mesh mesh = new(); Quat blade_ori = Rig.r_hld.orientation; Vec3 blade_pos = Rig.r_hld.position; Vec3 tip_pos = blade_pos + blade_ori * V.XYZ(0, 0, -1); mesh.SetData( new Vertex[] { new( blade_pos, V.XYZ(0,0,1)), new( tip_pos, V.XYZ(0,0,1)), new(last_tip_pos, V.XYZ(0,0,1)) }, new uint[] { 0, 1, 2 } ); mesh.Draw( mat_slash, Matrix.Identity, Color.Hex(0xF9BF05FF).ToLinear() ); Ray slash_ray = new Ray(tip_pos, Vec3.Direction(tip_pos, last_tip_pos)); float ray_dist = Vec3.Distance(tip_pos, last_tip_pos); last_tip_pos = Vec3.Lerp(last_tip_pos, tip_pos, Time.Stepf / 0.1f); if (true) // hit test { Matrix enemy_m4 = enemy_test.pose.ToMatrix(); Ray local_ray = enemy_m4.Inverse.Transform(slash_ray); bool hit = false; float min_dist = ray_dist; Vec3 min_hit_pos = Vec3.Zero; for (int i = 0; i < enemy_test.cols.Count; i++) { Sphere col = enemy_test.cols[i]; Vec3 hit_pos = Vec3.Zero; if (col.Intersect(local_ray, out hit_pos)) { float hit_dist = Vec3.Distance(hit_pos, local_ray.position); if (hit_dist < min_dist) { hit = true; min_dist = hit_dist; min_hit_pos = hit_pos; } } } min_hit_pos = enemy_m4.Transform(min_hit_pos); if (hit) { Mesh.Sphere.Draw( mat_unlit, Matrix.TS( min_hit_pos, 4 * U.cm ), Color.White ); if (Rig.btn_select.state) { VFX.Play(min_hit_pos); } } } // revolver Quat rvolv_ori = Rig.l_aim.orientation; Vec3 rvolv_pos = Rig.l_aim.position; Ray ray = new( rvolv_pos, rvolv_ori * Vec3.Forward ); Lines.Add( ray, 10.0f, // [!] hardcoded design value Color.Hex(0xF9BF05FF).ToLinear(), U.cm ); if (true) // hit test { Matrix enemy_m4 = enemy_test.pose.ToMatrix(); Ray local_ray = enemy_m4.Inverse.Transform(ray); bool hit = false; float min_dist = float.MaxValue; Vec3 min_hit_pos = Vec3.Zero; for (int i = 0; i < enemy_test.cols.Count; i++) { Sphere col = enemy_test.cols[i]; Vec3 hit_pos = Vec3.Zero; if (col.Intersect(local_ray, out hit_pos)) { float hit_dist = Vec3.Distance(hit_pos, local_ray.position); if (hit_dist < min_dist) { hit = true; min_dist = hit_dist; min_hit_pos = hit_pos; } } } min_hit_pos = enemy_m4.Transform(min_hit_pos); if (hit) { Mesh.Sphere.Draw( mat_unlit, Matrix.TS( min_hit_pos, 4 * U.cm ), Color.White ); if (Rig.btn_select.delta == +1) { VFX.Play(min_hit_pos); } } } // particles Particle[] particles = VFX.particles; for (int i = 0; i < particles.Length; i++) { Particle particle = particles[i]; Mesh.Sphere.Draw( mat_unlit, Matrix.TRS( particle.pos, particle.ori, particle.scl ), Color.Hex(0xC75A09FF).ToLinear() ); } Hierarchy.Pop(); // menu Matrix m4_menu = Mono.menu_pose.ToMatrix(Mono.menu_scale); Hierarchy.Push(m4_menu); // score char[] score_txt = Mono.score.ToString("000").ToCharArray(); for (int i = 0; i < score_txt.Length; i++) { Text.Add( score_txt[i].ToString(), Matrix.TS( V.XYZ(0, 0, 0), 48 ), text_style ); } Hierarchy.Pop(); } }