Compare commits

...

13 commits

3 changed files with 205 additions and 100 deletions

View file

@ -18,7 +18,6 @@ static class Arts
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;
@ -70,8 +69,18 @@ static class Arts
mat_both.Chain = mat_backface;
mat_slash.FaceCull = Cull.None;
tip_index = new int[] { 0, 0 };
tip_buffer = new Vec3[][] { new Vec3[tip_count], new Vec3[tip_count] };
slashing = new DeltaBool[] { new(false), new(false) };
}
// slash tip pos frame circle buffer [!] move out of render class
static int tip_count = 24; // [!] this needs to be scaled with headset framerate
static int[] tip_index;
static Vec3[][] tip_buffer;
static DeltaBool[] slashing;
// [!] hacky offset stepper for noise
public static int offset = 0;
static int offstep() => offset += 100;
@ -87,12 +96,23 @@ static class Arts
// ground
meshes["circle"].Draw(
mat_unlit,
Matrix.TRS(
V.XYZ(0, 1 * U.cm, 0),
Quat.Identity,
2.0f
),
Color.Hex(0x808080FF).ToLinear()
);
// pool
meshes["circle"].Draw(
mat_add,
Matrix.TRS(
V.XYZ(0, 0, 0),
Quat.Identity,
12.0f
),
Color.Hex(0x808080FF).ToLinear()
Color.Hex(0x7090AAFF).ToLinear()
);
// bamboo
@ -113,7 +133,7 @@ static class Arts
pos + V.XYZ(x_offset + x_wind, 5, 0),
};
if (Noise.u_scalar < 0.1f * Time.Stepf)
if (Noise.u_scalar < 0.05f * Time.Stepf)
{
VFX.Leaf(p[3]);
// static float fall_timer = 0.0f;
@ -199,9 +219,11 @@ static class Arts
// );
// 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);
Enemy enemy_test = Mono.enemy_types[(int)((Time.Totalf / 3) % 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);
enemy_test.pose.position = V.XYZ(0, 1.0f, -1.0f);
// V.XYZ(SKMath.Sin(Time.Totalf * 1f) * 1.0f, 0.666f, -3.0f);
for (int i = 0; i < enemy_test.cols.Count; i++)
{
@ -224,65 +246,93 @@ static class Arts
// );
// 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
for (int i = 0; i < (int)Handed.Max; i++)
{
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++)
Quat blade_ori = Rig.pose_hld[i].orientation;
Vec3 blade_pos = Rig.pose_hld[i].position;
Vec3 tip_pos = blade_pos + blade_ori * V.XYZ(0, 0, -1);
if (!Rig.holding[i]) // [!] generic placeholder check
{
Sphere col = enemy_test.cols[i];
Vec3 hit_pos = Vec3.Zero;
if (col.Intersect(local_ray, out hit_pos))
// reset tip buffer
for (int j = 0; j < tip_count; j++)
{
float hit_dist = Vec3.Distance(hit_pos, local_ray.position);
if (hit_dist < min_dist)
tip_buffer[i][j] = tip_pos;
}
continue;
}
tip_index[i] = (tip_index[i] + 1) % tip_count;
tip_buffer[i][tip_index[i]] = tip_pos;
Vec3 oldest_tip = tip_buffer[i][(tip_index[i] + 1) % tip_count];
Vec3 mid_tip = tip_buffer[i][(tip_index[i] + (tip_count / 3) * 2) % tip_count];
slashing[i].Step(Vec3.Distance(tip_pos, oldest_tip) > 0.2f);
if (slashing[i].delta == -1)
{
Rig.holding[i] = false;
// [!] janky placeholder reset
Rig.upper_sheathes[0] = true;
Rig.upper_sheathes[1] = true;
}
Mesh mesh = new();
mesh.SetData(
new Vertex[] {
new( blade_pos, V.XYZ(0,0,1)),
new( tip_pos, V.XYZ(0,0,1)),
new( mid_tip, V.XYZ(0,0,1)),
new(oldest_tip, V.XYZ(0,0,1)),
},
new uint[] {
0, 1, 2,
0, 2, 3,
}
);
mesh.Draw(
mat_slash,
Matrix.Identity,
Color.Hex(0xF9BF05FF).ToLinear()
);
Ray slash_ray = new Ray(tip_pos, Vec3.Direction(tip_pos, oldest_tip));
float ray_dist = Vec3.Distance(tip_pos, oldest_tip);
// last_tip_pos = Vec3.Lerp(last_tip_pos, tip_pos, Time.Stepf / 0.1f);
// 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 j = 0; j < enemy_test.cols.Count; j++)
{
Sphere col = enemy_test.cols[j];
Vec3 hit_pos = Vec3.Zero;
if (col.Intersect(local_ray, out hit_pos))
{
hit = true;
min_dist = hit_dist;
min_hit_pos = 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);
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
);
VFX.Play(min_hit_pos);
if (hit)
{
Mesh.Sphere.Draw(
mat_unlit,
Matrix.TS(
min_hit_pos,
4 * U.cm
),
Color.White
);
VFX.Play(min_hit_pos);
}
}
}
@ -342,6 +392,31 @@ static class Arts
}
}
// hand debug
for (int i = 0; i < (int)Handed.Max; i++)
{
Mesh.Sphere.Draw(
mat_unlit,
Rig.pose_hld[i].ToMatrix(
2 * U.cm
),
Color.Hex(Rig.holding[i] ? 0xFF00FFFF : 0x808080FF).ToLinear()
);
}
// shoulder debug
for (int i = 0; i < (int)Handed.Max; i++)
{
Mesh.Sphere.Draw(
mat_unlit,
Matrix.TS(
Rig.head.position + Rig.head.orientation * V.XYZ(Maths.s_scalar(i) * 0.333f, 0, -0.333f),
2 * U.cm
),
Color.Hex(Rig.upper_sheathes[i] ? 0xFF00FFFF : 0x808080FF).ToLinear()
);
}
// particles
for (int i = 0; i < VFX.ps.count; i++)
{

View file

@ -8,19 +8,17 @@ class Program
{
static void Main(string[] args)
{
SK.AddStepper<PassthroughFBExt>();
// Initialize StereoKit
SKSettings settings = new SKSettings
{
appName = "slash",
assetsFolder = "Assets",
blendPreference = DisplayBlend.AnyTransparent,
blendPreference = DisplayBlend.Opaque,
// overlayApp = true,
// overlayPriority = 1,
depthMode = DepthMode.D32,
disableFlatscreenMRSim = true,
renderScaling = 2,
renderScaling = 1.5f,
renderMultisample = 0,
// displayPreference = DisplayMode.Flatscreen
@ -29,9 +27,7 @@ class Program
if (!SK.Initialize(settings))
return;
Renderer.Scaling = 2;
World.OcclusionEnabled = true;
Device.DisplayBlend = DisplayBlend.AnyTransparent;
Renderer.Scaling = 1.5f;
Renderer.EnableSky = false;
Renderer.ClearColor = Color.Hex(0x42A590FF).ToLinear();// new Color(0.0f, 0.0f, 0.0f, 0.0f);

View file

@ -7,19 +7,35 @@ static class Rig
public static Pose head = Pose.Identity;
public static DeltaBool btn_select = new(false);
public static DeltaBool btn_grip = new(false);
public static DeltaBool btn_back = new(false);
public static Pose l_hld, l_aim, r_hld, r_aim;
public static DeltaBool[] btn_grip;
public static DeltaBool l_btn_grip => btn_grip[(int)Handed.Left];
public static DeltaBool r_btn_grip => btn_grip[(int)Handed.Right];
public static Pose[] pose_hld;
public static Pose l_hld => pose_hld[(int)Handed.Left];
public static Pose r_hld => pose_hld[(int)Handed.Right];
public static Pose[] pose_aim;
public static Pose l_aim => pose_aim[(int)Handed.Left];
public static Pose r_aim => pose_aim[(int)Handed.Right];
public static Vec3 fullstick = Vec3.Up;
public static Pose r_con_stick = Pose.Identity;
public static XYZi new_dir = new(0, 0, 1);
public static bool[] upper_sheathes = new bool[] { true, true };
public static bool[] lower_sheathes = new bool[] { true, true };
public static bool[] holding = new bool[] { false, false };
public static void Init()
{
btn_grip = new DeltaBool[] { new(false), new(false) };
pose_hld = new Pose[] { new(), new() };
pose_aim = new Pose[] { new(), new() };
}
public static void Frame()
@ -32,11 +48,11 @@ static class Rig
btn_select.Step(Input.Key(Key.MouseLeft).IsActive());
btn_back.Step(Input.Key(Key.MouseRight).IsActive());
r_hld = new Pose(
pose_hld[(int)Handed.Right] = new Pose(
V.XYZ(SKMath.Sin(Time.Totalf * 6f) * 0.6f * 0.0f, 0.5f, 1.0f),
Quat.FromAngles(0, 0, 45) * Quat.FromAngles(0, SKMath.Sin(Time.Totalf * 6f) * 60f, 0)
);
l_aim = new Pose(
pose_aim[(int)Handed.Left] = new Pose(
V.XYZ(1.0f, 0.5f, 0.5f), // V.XYZ(SKMath.Sin(Time.Totalf * 2f) * 0.6f, 0.5f, 0.5f),
Quat.Identity
);
@ -51,39 +67,57 @@ static class Rig
}
else
{
// Hand r_hand = Input.Hand(Handed.Right);
// [!] hand input simulates controller...
Controller r_con = Input.Controller(Handed.Right);
r_hld = r_con.pose;
r_aim = r_con.aim;
Controller l_con = Input.Controller(Handed.Left);
l_hld = l_con.pose;
l_aim = l_con.aim;
btn_grip[(int)Handed.Left].Step(l_con.grip > 0.5f);
pose_hld[(int)Handed.Left] = l_con.pose;
pose_aim[(int)Handed.Left] = l_con.aim;
bool con_tracked = r_con.trackedPos > TrackState.Lost;
// bool hand_tracked = Input.HandSource(Handed.Right) > HandSource.None;
if (con_tracked)
Controller r_con = Input.Controller(Handed.Right);
btn_grip[(int)Handed.Right].Step(r_con.grip > 0.5f);
pose_hld[(int)Handed.Right] = r_con.pose;
pose_aim[(int)Handed.Right] = r_con.aim;
btn_select.Step(r_con.x1.IsActive() || r_con.trigger > 0.5f);
btn_back.Step(r_con.x2.IsActive());
// bool con_tracked = r_con.trackedPos > TrackState.Lost;
Vec2 stick = r_con.stick;
Quat stick_rot = Quat.FromAngles(stick.y * -90, 0, stick.x * +90);
float stick_sign = r_con.IsStickClicked ? -1 : +1;
r_con_stick = r_con.aim;
// r_con_stick.position += r_con_stick.orientation * V.XYZ(0.0065f, -0.012f, -0.05f);
// r_con_stick.orientation *= Quat.FromAngles(-50, 0, 0);
fullstick = r_con_stick.orientation * stick_rot * Vec3.Up * stick_sign;
// Vec3 fullstick = r_hand.palm.orientation * Vec3.Up;
float ax = Maths.abs(fullstick.x);
float ay = Maths.abs(fullstick.y);
float az = Maths.abs(fullstick.z);
if (ax > ay && ax > az) new_dir = new(Maths.sign(fullstick.x), 0, 0);
if (ay > ax && ay > az) new_dir = new(0, Maths.sign(fullstick.y), 0);
if (az > ax && az > ay) new_dir = new(0, 0, Maths.sign(fullstick.z));
// sheathe grabs
// shoulders
// put hand in head space
// if behind head then handedness = left or right sheathe
// else check for left or right of head to grab at left or right sheathe
for (int i = 0; i < (int)Handed.Max; i++)
{
btn_select.Step(r_con.x1.IsActive() || r_con.trigger > 0.5f);
btn_grip.Step(r_con.grip > 0.5f);
btn_back.Step(r_con.x2.IsActive());
Vec2 stick = r_con.stick;
Quat stick_rot = Quat.FromAngles(stick.y * -90, 0, stick.x * +90);
float stick_sign = r_con.IsStickClicked ? -1 : +1;
r_con_stick = r_con.aim;
// r_con_stick.position += r_con_stick.orientation * V.XYZ(0.0065f, -0.012f, -0.05f);
// r_con_stick.orientation *= Quat.FromAngles(-50, 0, 0);
fullstick = r_con_stick.orientation * stick_rot * Vec3.Up * stick_sign;
// Vec3 fullstick = r_hand.palm.orientation * Vec3.Up;
float ax = Maths.abs(fullstick.x);
float ay = Maths.abs(fullstick.y);
float az = Maths.abs(fullstick.z);
if (ax > ay && ax > az) new_dir = new(Maths.sign(fullstick.x), 0, 0);
if (ay > ax && ay > az) new_dir = new(0, Maths.sign(fullstick.y), 0);
if (az > ax && az > ay) new_dir = new(0, 0, Maths.sign(fullstick.z));
if (!holding[i])
{
Vec3 local_pos = head.orientation.Inverse * (pose_hld[i].position - head.position);
Handed side = local_pos.x < 0 ? Handed.Left : Handed.Right;
if (upper_sheathes[(int)side])
{
if (btn_grip[i].delta == +1)
{
upper_sheathes[(int)side] = false;
holding[i] = true;
}
}
}
}
}
}