296 lines
No EOL
9.7 KiB
C#
296 lines
No EOL
9.7 KiB
C#
using System.Collections.Generic;
|
|
using StereoKit;
|
|
|
|
namespace snake;
|
|
|
|
static class Arts
|
|
{
|
|
static Model assets_model = Model.FromFile("meshes/assets.glb", Shader.Unlit);
|
|
static Dictionary<string, Mesh> meshes = new();
|
|
static Material mat_mono = new Material("mono.hlsl");
|
|
static Material mat_unlit = new Material("unlit.hlsl");
|
|
static Material mat_box = new Material("unlit.hlsl");
|
|
static Material mat_backbox = new Material("backbox.hlsl");
|
|
static Material mat_justcolor = new Material("justcolor.hlsl");
|
|
|
|
public static Vec3 box_shake = new(0, 0, 0);
|
|
static Quat food_ori = Quat.Identity;
|
|
|
|
static XYZi last_headpos = new(0, 0, 0);
|
|
static DeltaBool headmove = new(false);
|
|
static XYZi last_tailpos = new(0, 0, 0);
|
|
static DeltaBool tailmove = new(false);
|
|
|
|
static TextStyle text_style;
|
|
|
|
public static void Init()
|
|
{
|
|
foreach (ModelNode node in assets_model.Nodes)
|
|
{
|
|
if (node.Mesh != null)
|
|
{
|
|
meshes.Add(node.Name, node.Mesh);
|
|
}
|
|
}
|
|
|
|
text_style = TextStyle.FromFont(
|
|
Font.FromFile("Staatliches.ttf"),
|
|
1.0f * U.cm,
|
|
Color.White
|
|
);
|
|
|
|
mat_backbox.FaceCull = Cull.Front;
|
|
mat_backbox.Transparency = Transparency.Add;
|
|
mat_backbox.DepthTest = DepthTest.LessOrEq;
|
|
mat_backbox.DepthWrite = false;
|
|
|
|
mat_box.Chain = mat_backbox;
|
|
}
|
|
|
|
public static void Frame()
|
|
{
|
|
bool vr = Device.DisplayBlend == DisplayBlend.Opaque;
|
|
// render hands if not in mixed reality
|
|
Input.HandVisible(Handed.Max, false);
|
|
if (vr)
|
|
{
|
|
// background standin if no passthrough
|
|
}
|
|
|
|
// fullstick
|
|
Mesh.Sphere.Draw(
|
|
mat_unlit,
|
|
Matrix.TS(
|
|
Rig.r_con_stick.position,
|
|
5 * U.mm
|
|
),
|
|
Color.White
|
|
);
|
|
Lines.Add(
|
|
Rig.r_con_stick.position + V.XYZ(0, 0, 0),
|
|
Rig.r_con_stick.position + Rig.fullstick * U.cm,
|
|
Color.White,
|
|
2 * U.mm
|
|
);
|
|
|
|
// box
|
|
box_shake = Vec3.Lerp(box_shake, Vec3.Zero, Time.Stepf / 0.333f);
|
|
// scale in
|
|
float box_scale = Mono.box_scale; // Maths.min(Maths.smooth_stop(Maths.u_scalar(Time.Totalf - 3)) * Mono.box_scale, Mono.box_scale);
|
|
Hierarchy.Push(Matrix.TRS(
|
|
Mono.box_pose.position + (box_shake * U.cm * 0.333f),
|
|
Mono.box_pose.orientation,
|
|
box_scale
|
|
));
|
|
// meshes["InsideOut"].Draw(mat_unlit, Matrix.Identity);
|
|
meshes["InsideOut"].Draw(
|
|
mat_box,
|
|
Matrix.Identity
|
|
);
|
|
meshes["Corrugation"].Draw(
|
|
Mono.in_dist.state ? mat_justcolor : mat_unlit,
|
|
Matrix.Identity
|
|
);
|
|
if (Mono.in_cone.state && Mono.box_mode == Mono.BoxMode.Hold || Mono.box_mode == Mono.BoxMode.Mount)
|
|
{
|
|
Lines.Add(
|
|
V.XYZ(0, Mono.SD_Y - 0.5f, 0),
|
|
V.XYZ(0, Mono.SD_Y + 3.0f, 0),
|
|
Color.White,
|
|
1.0f * U.mm
|
|
);
|
|
}
|
|
if (Mono.menu)
|
|
{
|
|
meshes["Tape"].Draw(mat_mono, Matrix.Identity);
|
|
meshes["uiPlay"].Draw(
|
|
mat_unlit,
|
|
Matrix.TR(
|
|
V.XYZ(0, 0, Mono.SD_Z - 0.5f + 0.1f),
|
|
Quat.FromAngles(90, 0, 0)
|
|
)
|
|
);
|
|
meshes["uiCursor"].Draw(
|
|
mat_unlit,
|
|
Matrix.TR(
|
|
V.XYZ(0, 0, Mono.SD_Z - 0.5f + 0.2f),
|
|
Quat.FromAngles(90, 0, 0)
|
|
)
|
|
);
|
|
}
|
|
|
|
// snake
|
|
float snake_t = headmove.state ? Maths.u_clamp(Maths.smooth_stop((float)Mono.step_t) * 3.0f) : 1.0f;
|
|
bool food_next = !Mono.eaten_latch.state && (Mono.snake[0] + Mono.snake_dir) == Mono.food;
|
|
if (!food_next)
|
|
{
|
|
meshes["Tongue"].Draw(
|
|
mat_mono,
|
|
Matrix.TRS(
|
|
Mono.snake[0].ToVec3,
|
|
Quat.LookDir(Rig.fullstick),
|
|
V.XYZ(1, 1, 0.666f + Maths.smooth_stop((float)Mono.step_t) * 0.333f)
|
|
)
|
|
);
|
|
}
|
|
|
|
string face = "Face0Default";
|
|
face = Mono.grow_buffer > 0 ? "Face2Eaten" : face;
|
|
face = Mono.in_box.delta != 0 ? "Face3Bump" : face;
|
|
face = food_next ? "Face1Eat" : face;
|
|
meshes[face].Draw(
|
|
mat_mono,
|
|
Matrix.TRS(
|
|
Mono.snake[0].ToVec3 - (Mono.snake_dir.ToVec3 * (float)(1.0 - snake_t) * 0.3f),
|
|
Quat.LookDir(Mono.snake_dir.ToVec3),
|
|
V.XYZ(1, 1, (float)(snake_t))
|
|
)
|
|
);
|
|
|
|
for (int i = 1; i < Mono.snake_len; i++)
|
|
{
|
|
float scale = 1.0f;
|
|
if ((int)((Time.Total - Mono.eat_timestamp) * Mono.snake_len / Mono.step_step) == i)
|
|
{
|
|
scale = 1.1f;
|
|
}
|
|
meshes["Segment"].Draw(
|
|
mat_mono,
|
|
Matrix.TRS(
|
|
Mono.snake[i].ToVec3,
|
|
Quat.LookAt(Mono.snake[i].ToVec3, Mono.snake[i - 1].ToVec3),
|
|
scale
|
|
)
|
|
);
|
|
}
|
|
// false tail
|
|
if (tailmove.state && snake_t < 1.0f)
|
|
{
|
|
int i_tail = Maths.min(Mono.snake_len, Mono.snake.Length - 1);
|
|
Vec3 tail_dir = Vec3.Direction(Mono.snake[i_tail - 1].ToVec3, Mono.snake[i_tail].ToVec3);
|
|
meshes["Segment"].Draw(
|
|
mat_mono,
|
|
Matrix.TRS(
|
|
Mono.snake[i_tail].ToVec3 + (tail_dir * (float)(snake_t) * 0.7f),
|
|
Quat.LookDir(tail_dir),
|
|
V.XYZ(1, 1, (float)(1.0 - snake_t))
|
|
)
|
|
);
|
|
}
|
|
|
|
// holes
|
|
foreach (KeyValuePair<XYZi, XYZi> hole in Mono.holes)
|
|
{
|
|
Vec3 hole_normal = V.XYZ(
|
|
Maths.abs(hole.Value.x) * Maths.sign(hole.Key.x),
|
|
Maths.abs(hole.Value.y) * Maths.sign(hole.Key.y),
|
|
Maths.abs(hole.Value.z) * Maths.sign(hole.Key.z)
|
|
);
|
|
// Vec3 hole_world_normal = Mono.box_pose.orientation * hole_normal;
|
|
// Vec3 hole_world = Mono.box_pose.ToMatrix(Mono.box_scale) * V.XYZ(
|
|
// hole.Key.x - hole.Value.x * 0.5f,
|
|
// hole.Key.y - hole.Value.y * 0.5f,
|
|
// hole.Key.z - hole.Value.z * 0.5f
|
|
// );
|
|
// Vec3 cam_dir = (Rig.head.orientation * Vec3.Forward);
|
|
// Vec3 hole_view_dir = Vec3.Direction(hole_world, Rig.head.position);
|
|
// bool back_hole = Vec3.Dot(hole_world_normal, hole_view_dir) < 0.0;
|
|
bool hole_flip = Vec3.Dot(hole_normal, hole.Value.ToVec3) < 0.0;
|
|
|
|
meshes[hole_flip ? "Hole" : "HoleFlip"].Draw(
|
|
mat_box,
|
|
Matrix.TRS(
|
|
hole.Key.ToVec3,
|
|
Quat.LookDir(hole.Value.ToVec3),
|
|
1
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
// food
|
|
if (!food_next)
|
|
{
|
|
food_ori *= Quat.FromAngles(
|
|
90 * Time.Stepf,
|
|
30 * Time.Stepf,
|
|
10 * Time.Stepf
|
|
);
|
|
}
|
|
if (!Mono.eaten_latch.state)
|
|
{
|
|
float food_t = Mono.eaten_latch.delta == -1 ? Maths.smooth_stop((float)Mono.step_t) : 1;
|
|
meshes["Food"].Draw(
|
|
mat_mono,
|
|
Matrix.TRS(
|
|
Mono.food.ToVec3,
|
|
food_ori,
|
|
food_t
|
|
)
|
|
);
|
|
}
|
|
|
|
// particles
|
|
Particle[] particles = VFX.particles;
|
|
for (int i = 0; i < particles.Length; i++)
|
|
{
|
|
Particle particle = particles[i];
|
|
meshes["FoodParticle"].Draw(
|
|
mat_mono,
|
|
Matrix.TRS(
|
|
particle.pos,
|
|
particle.ori,
|
|
particle.scl
|
|
)
|
|
);
|
|
}
|
|
|
|
// score
|
|
char[] score_txt = Mono.snake_len.ToString("000").ToCharArray();
|
|
Quat score_ori = Quat.LookDir(Rig.head.position - Mono.box_pose.position);
|
|
Vec3 score_pos = score_ori * V.XYZ(0, -Mono.SD_Y - 1, -Mono.SD_Z - 1);
|
|
for (int i = 0; i < score_txt.Length; i++)
|
|
{
|
|
Text.Add(
|
|
score_txt[i].ToString(),
|
|
Matrix.TRS(
|
|
score_pos + score_ori * V.XYZ((1 - i) * 0.333f, 0, 0),
|
|
score_ori,
|
|
40
|
|
),
|
|
text_style
|
|
);
|
|
}
|
|
|
|
Hierarchy.Pop();
|
|
|
|
// for (int sx = -Mono.head_fill.Xslen; Mono.head_fill.InX(sx); sx++)
|
|
// {
|
|
// for (int sy = -Mono.head_fill.Yslen; Mono.head_fill.InY(sy); sy++)
|
|
// {
|
|
// for (int sz = -Mono.head_fill.Zslen; Mono.head_fill.InZ(sz); sz++)
|
|
// {
|
|
// Vec3 pos = Mono.box_pose.ToMatrix(U.cm) * V.XYZ(sx, sy, sz);
|
|
// Text.Add(
|
|
// (Mono.head_fill[new XYZi(sx, sy, sz)] + Mono.tail_fill[new XYZi(sx, sy, sz)]).ToString(),
|
|
// Matrix.TRS(
|
|
// pos,
|
|
// Quat.LookAt(pos, Input.Head.position),
|
|
// 0.1f
|
|
// )
|
|
// );
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
public static void Step()
|
|
{
|
|
XYZi snake_head = Mono.snake[0];
|
|
XYZi snake_tail = Mono.snake[Mono.snake_len - 1];
|
|
headmove.Step(snake_head != last_headpos);
|
|
tailmove.Step(snake_tail != last_tailpos);
|
|
last_headpos = snake_head;
|
|
last_tailpos = snake_tail;
|
|
}
|
|
} |