mid net refactor

This commit is contained in:
spatialfree 2022-01-19 18:43:28 -05:00
parent 62e762a166
commit 5c2ddd546d
7 changed files with 262 additions and 218 deletions

View file

@ -1,14 +1,13 @@
using System;
using StereoKit;
class Block {
public class Block {
public static Mesh mesh = Default.MeshCube;
public static Material mat = Default.Material;
public bool active = false;
public Solid solid;
public Color color;
public float size = 0.5f;
// if you grab someone else's it becomes your own
@ -16,20 +15,13 @@ class Block {
// public int request; // request ownership
// public int owner; // then if owner continue as usual
// public bool busy; // marked as held so no fighting
public Block(SolidType type, Color color) {
public Block(SolidType type) {
this.solid = new Solid(Vec3.Zero, Quat.Identity, type);
this.size = 0.5f;
this.solid.AddBox(Vec3.One * size, 3);
this.color = color;
Disable();
}
// public Block(Vec3 pos, Quat rot, SolidType type, Color color) {
// this.solid = new Solid(pos, rot, type);
// this.solid.AddBox(Vec3.One, 1);
// this.color = color;
// }
public void Enable(Vec3 pos, Quat rot) {
solid.SetAngularVelocity(Vec3.Zero);
solid.SetVelocity(Vec3.Zero);
@ -43,12 +35,19 @@ class Block {
public void Draw() {
if (active) {
mesh.Draw(mat, solid.GetPose().ToMatrix(Vec3.One * size), color);
mesh.Draw(mat, solid.GetPose().ToMatrix(Vec3.One * size));
}
}
}
class BlockCon {
public class BlockCon {
Monolith mono;
bool chirality;
public BlockCon(Monolith mono, bool chirality) {
this.mono = mono;
this.chirality = chirality;
}
public int index = -1;
public Vec3 offset = Vec3.Zero;
public Quat heldRot = Quat.Identity, spinRot = Quat.Identity, spinDelta = Quat.Identity;
@ -58,8 +57,13 @@ class BlockCon {
float lastPressed = 0;
bool pressed = false;
public void Step(Con con, Con otherCon, Vec3 cursor, ref BlockCon otherBlockCon, ref Block[] blocks) {
public void Step() {
Block[] blocks = mono.blocks;
Con con = mono.Con(chirality);
Con otherCon = mono.Con(!chirality);
Vec3 cursor = mono.Glove(chirality).virtualGlove.position;
BlockCon otherBlockCon = mono.BlockCon(!chirality);
bool doublePressed = false;
if (con.device.trigger > 0.5f) {
if (!pressed) {

View file

@ -1,7 +1,7 @@
using System;
using StereoKit;
class Cubic {
public class Cubic {
public bool active;
public Vec3 p0, p1, p2, p3;
public Color color;
@ -11,19 +11,6 @@ class Cubic {
active = false;
}
public void Enable(Vec3 p0, Vec3 p1, Vec3 p2, Vec3 p3, Color c) {
this.p0 = p0;
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
color = c;
active = true;
}
public void Disable() {
active = false;
}
public void Draw() {
if (active) {
Bezier.Draw(p0, p1, p2, p3, color);
@ -31,9 +18,17 @@ class Cubic {
}
}
class CubicCon {
public void Step(Con domCon, Con subCon, Peer peer, ref Cubic[] cubics) {
bool place = domCon.device.IsStickJustClicked || subCon.device.IsStickJustClicked;
public class CubicCon {
Monolith mono;
public CubicCon(Monolith mono) {
this.mono = mono;
}
public void Step() {
Con rCon = mono.rCon;
Con lCon = mono.lCon;
Peer peer = mono.net.me;
bool place = rCon.device.IsStickJustClicked || lCon.device.IsStickJustClicked;
if (place) {
for (int i = 0; i < cubics.Length; i++) {
if (!cubics[i].active) {
@ -44,4 +39,31 @@ class CubicCon {
cubics[PullRequest.RandomRange(0, cubics.Length)].Enable(peer.cursor0, peer.cursor1, peer.cursor2, peer.cursor3, peer.color);
}
}
}
public static class Bezier {
static int detail = 64;
public static void Draw(Vec3 p0, Vec3 p1, Vec3 p2, Vec3 p3, Color color) {
LinePoint[] bezier = new LinePoint[detail];
for (int i = 0; i < bezier.Length; i++) {
float t = i / ((float)bezier.Length - 1);
Vec3 a = Vec3.Lerp(p0, p1, t);
Vec3 b = Vec3.Lerp(p1, p2, t);
Vec3 c = Vec3.Lerp(p2, p3, t);
Vec3 pos = Vec3.Lerp(Vec3.Lerp(a, b, t), Vec3.Lerp(b, c, t), t);
bezier[i] = new LinePoint(pos, color, 0.01f);
}
Lines.Add(bezier);
}
public static Vec3 Sample(Vec3 p0, Vec3 p1, Vec3 p2, Vec3 p3, float t) {
Vec3 a = Vec3.Lerp(p0, p1, t);
Vec3 b = Vec3.Lerp(p1, p2, t);
Vec3 c = Vec3.Lerp(p2, p3, t);
Vec3 pos = Vec3.Lerp(Vec3.Lerp(a, b, t), Vec3.Lerp(b, c, t), t);
return pos;
}
public static Vec3 Sample(Vec3[] points, float t) {
return Sample(points[0], points[1], points[2], points[3], t);
}
}

View file

@ -128,9 +128,9 @@ public class Glove {
// decouple the rendering
// the render-relevent DATA that gets streamed over the network
// that way we can render the same way for all peers
static Mesh mesh = Default.MeshCube;
static Material mat = Default.Material;
static Model model = Model.FromFile("skinned_test.glb", Shader.Default);
Mesh mesh = Default.MeshCube;
Material mat = Default.Material;
Model model = Model.FromFile("skinned_test.glb", Shader.Default);
public void Render(Pose glove, Pose virtualGlove, Pose wrist, float stretch, float twist, bool chirality) {
Lines.Add(pullPoint, glove.position, new Color(1, 0, 1), 0.005f);
Lines.Add(glove.position, virtualGlove.position, new Color(0, 1, 1), 0.005f);
@ -167,12 +167,15 @@ public class Glove {
// Input.HandOverride(chirality ? Handed.Right : Handed.Left, joints);
// Input.HandClearOverride(handed);
// model.Draw(glove.ToMatrix(Vec3.One / 4));
// Matrix m4 = model.RootNode.Child.LocalTransform;
// Pose mPose = m4.Pose;
// mPose.orientation = Quat.FromAngles(Vec3.Right * 45);
// m4 = mPose.ToMatrix();
// model.RootNode.Child.LocalTransform = m4;
ModelNode top = model.FindNode("Top");
top.LocalTransform = Matrix.R(Quat.FromAngles(Vec3.Right * 45));
Console.WriteLine(top.Name);
model.Draw(glove.ToMatrix(Vec3.One / 10));
// get "Top" node
// Console.WriteLine(nodes[].Name);
// ? for stereo kit nick "can i directly update bone transforms on a skinned mesh"

View file

@ -6,12 +6,14 @@ using System.Threading;
using System.Threading.Tasks;
using StereoKit;
class MonoNet {
public class MonoNet {
public Monolith mono;
public bool send;
public MonoNet(Monolith mono) {
this.mono = mono;
this.send = false;
Random rnd = new Random();
me = new Peer(rnd.Next(1, 1024 * 8), SolidType.Normal, Color.White); // let the server determine the id
me = new Peer(rnd.Next(1, 1024 * 8)); // let the server determine the id
// me.block = new Block(new Vec3((float)rnd.NextDouble() * 0.5f, 10, -4), Quat.Identity, SolidType.Normal, Color.White);
}
public Socket socket;
@ -65,7 +67,7 @@ class MonoNet {
break;
}
} else {
peers[i] = new Peer(id, SolidType.Immovable, Color.White * 0.5f);
peers[i] = new Peer(id);
index = i;
break;
}
@ -74,16 +76,7 @@ class MonoNet {
Console.WriteLine("too many peers");
return;
}
peers[index].color = ReadColor();
peers[index].cursor0 = ReadVec3();
peers[index].cursor1 = ReadVec3();
peers[index].cursor2 = ReadVec3();
peers[index].cursor3 = ReadVec3();
peers[index].headset = ReadPose();
peers[index].offHand = ReadPose();
peers[index].mainHand = ReadPose();
ReadBlock(ref peers[index].blocks);
ReadCubic(ref peers[index].cubics);
peers[index].Read();
peers[index].lastPing = Time.Totalf;
}
@ -103,56 +96,46 @@ class MonoNet {
bool running = true;
while (running) {
Thread.Sleep(60);
if (Input.Controller(Handed.Right).IsTracked)
if (send)
continue;
wHead = 0;
WriteInt(me.id);
WriteColor(me.color);
WriteVec3(me.cursor0);
WriteVec3(me.cursor1);
WriteVec3(me.cursor2);
WriteVec3(me.cursor3);
WritePose(me.headset);
WritePose(me.offHand);
WritePose(me.mainHand);
WriteBlock(me.blocks);
WriteCubic(me.cubics);
me.Write();
socket.Send(wData);
}
}
bool ReadBool() {
public bool ReadBool() {
bool result = rData[rHead] == 1;
rHead++;
return result;
}
void WriteBool(bool value) {
public void WriteBool(bool value) {
wData[wHead] = (byte)(value ? 1 : 0);
wHead++;
}
int ReadInt() {
public int ReadInt() {
int value = BitConverter.ToInt32(rData, rHead);
rHead += 4;
return value;
}
void WriteInt(int value) {
public void WriteInt(int value) {
BitConverter.GetBytes(value).CopyTo(wData, wHead);
wHead += 4;
}
float ReadFloat() {
public float ReadFloat() {
float value = BitConverter.ToSingle(rData, rHead);
rHead += 4;
return value;
}
void WriteFloat(float value) {
public void WriteFloat(float value) {
BitConverter.GetBytes(value).CopyTo(wData, wHead);
wHead += 4;
}
Vec3 ReadVec3() {
public Vec3 ReadVec3() {
Vec3 value = new Vec3(
BitConverter.ToSingle(rData, rHead),
BitConverter.ToSingle(rData, rHead + 4),
@ -161,14 +144,14 @@ class MonoNet {
rHead += 12;
return value;
}
void WriteVec3(Vec3 vec) {
public void WriteVec3(Vec3 vec) {
BitConverter.GetBytes(vec.x).CopyTo(wData, wHead);
BitConverter.GetBytes(vec.y).CopyTo(wData, wHead + 4);
BitConverter.GetBytes(vec.z).CopyTo(wData, wHead + 8);
wHead += 12;
}
Quat ReadQuat() {
public Quat ReadQuat() {
Quat value = new Quat(
BitConverter.ToSingle(rData, rHead),
BitConverter.ToSingle(rData, rHead + 4),
@ -178,7 +161,7 @@ class MonoNet {
rHead += 16;
return value;
}
void WriteQuat(Quat quat) {
public void WriteQuat(Quat quat) {
BitConverter.GetBytes(quat.x).CopyTo(wData, wHead);
BitConverter.GetBytes(quat.y).CopyTo(wData, wHead + 4);
BitConverter.GetBytes(quat.z).CopyTo(wData, wHead + 8);
@ -186,18 +169,18 @@ class MonoNet {
wHead += 16;
}
Pose ReadPose() {
public Pose ReadPose() {
return new Pose(
ReadVec3(),
ReadQuat()
);
}
void WritePose(Pose pose) {
public void WritePose(Pose pose) {
WriteVec3(pose.position);
WriteQuat(pose.orientation);
}
Color ReadColor() {
public Color ReadColor() {
Color color = new Color(
BitConverter.ToSingle(rData, rHead),
BitConverter.ToSingle(rData, rHead + 4),
@ -207,7 +190,7 @@ class MonoNet {
rHead += 16;
return color;
}
void WriteColor(Color color) {
public void WriteColor(Color color) {
BitConverter.GetBytes(color.r).CopyTo(wData, wHead);
BitConverter.GetBytes(color.g).CopyTo(wData, wHead + 4);
BitConverter.GetBytes(color.b).CopyTo(wData, wHead + 8);
@ -215,50 +198,6 @@ class MonoNet {
wHead += 16;
}
void ReadBlock(ref Block[] blocks) {
for (int i = 0; i < blocks.Length; i++) {
bool bActive = ReadBool();
Pose pose = ReadPose();
if (bActive) {
blocks[i].Enable(pose.position, pose.orientation);
} else {
blocks[i].Disable();
}
}
}
void WriteBlock(Block[] blocks) {
for (int i = 0; i < blocks.Length; i++) {
WriteBool(blocks[i].active);
WritePose(blocks[i].solid.GetPose());
}
}
void ReadCubic(ref Cubic[] cubics) {
for (int i = 0; i < cubics.Length; i++) {
bool bActive = ReadBool();
Color color = ReadColor();
Vec3 p0 = ReadVec3();
Vec3 p1 = ReadVec3();
Vec3 p2 = ReadVec3();
Vec3 p3 = ReadVec3();
if (bActive) {
cubics[i].Enable(p0, p1, p2, p3, color);
} else {
cubics[i].Disable();
}
}
}
void WriteCubic(Cubic[] cubics) {
for (int i = 0; i < cubics.Length; i++) {
WriteBool(cubics[i].active);
WriteColor(cubics[i].color);
WriteVec3(cubics[i].p0);
WriteVec3(cubics[i].p1);
WriteVec3(cubics[i].p2);
WriteVec3(cubics[i].p3);
}
}
string localIP, publicIP;
void GetIPs() {
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0)) {
@ -268,56 +207,59 @@ class MonoNet {
}
publicIP = new HttpClient().GetStringAsync("https://ipv4.icanhazip.com/").Result.TrimEnd();
}
}
class Peer {
public class Peer {
public float lastPing;
MonoNet net;
public int id; // on connect: wait on server sending your peer id
public Color color;
public Vec3 cursor0, cursor1, cursor2, cursor3;
public Pose headset;
public Pose offHand;
public Pose mainHand;
public Block[] blocks;
public Cubic[] cubics;
NetBlock[] blocks;
NetCubic[] cubics;
// public Sound voice;
// public SoundInst voiceInst; // update position
public Peer(int id, SolidType type, Color color) {
public Peer(MonoNet net, int id) {
this.net = net;
this.id = id;
blocks = new Block[] {
new Block(type, color), new Block(type, color), new Block(type, color),
new Block(type, color), new Block(type, color), new Block(type, color)
};
cubics = new Cubic[] {
new Cubic(), new Cubic(), new Cubic(),
new Cubic(), new Cubic(), new Cubic()
};
// voice = Sound.CreateStream(0.5f);
// voiceInst = voice.Play(Vec3.Zero, 0.5f);
}
BlockCon rBlock = new BlockCon();
BlockCon lBlock = new BlockCon();
CubicCon cubicCon = new CubicCon();
public Vec3 vGlovePos;
public void Step(Monolith mono, Con rCon, Con lCon) { // CLIENT SIDE
rBlock.Step(rCon, lCon, mono.rGlove.virtualGlove.position, ref lBlock, ref blocks);
lBlock.Step(lCon, rCon, mono.lGlove.virtualGlove.position, ref rBlock, ref blocks);
public void Step(Monolith mono) { // CLIENT SIDE
// too much in this networking class
// should contain only network related data
// and not be a weird pitstop for the game logic
// does it store a copy of the data?
// or just a reference to the data?
// only contain a copy of network related data
// and not be a weird pitstop for game logic
// vGlovePos = mono.rGlove.virtualGlove.position;
// game logic driven for write, flexible for read (SolidType.Immovable)
vGlovePos = mono.rGlove.virtualGlove.position;
if (blocks.Length != mono.blocks.Length) { blocks = new NetBlock[mono.blocks.Length]; }
for (int i = 0; i < blocks.Length; i++) {
blocks[i].active = mono.blocks[i].active;
blocks[i].pose = mono.blocks[i].solid.GetPose();
}
if (cubics.Length != mono.cubics.Length) { cubics = new NetCubic[mono.cubics.Length]; }
for (int i = 0; i < cubics.Length; i++) {
cubics[i].active = mono.cubics[i].active;
cubics[i].color = mono.cubics[i].color;
cubics[i].p0 = mono.cubics[i].p0;
cubics[i].p1 = mono.cubics[i].p1;
cubics[i].p2 = mono.cubics[i].p2;
cubics[i].p3 = mono.cubics[i].p3;
}
// for (int i = 0; i < blocks.Length; i++) {
// Pose blockPose = blocks[i].solid.GetPose();
@ -332,22 +274,99 @@ class Peer {
// }
// }
cubicCon.Step(rCon, lCon, this, ref cubics);
Draw(false);
}
public void Draw(bool body) {
if (body){
// Cube(Matrix.TRS(cursor0, Quat.Identity, Vec3.One * 0.05f), color);
Cube(Matrix.TRS(headset.position + Input.Head.Forward * -0.15f, headset.orientation, Vec3.One * 0.3f), color);
// Cube(offHand.ToMatrix(new Vec3(0.1f, 0.025f, 0.1f)), color);
// Cube(mainHand.ToMatrix(new Vec3(0.1f, 0.025f, 0.1f)), color);
public void Write() {
net.WriteInt(id);
net.WriteColor(color);
net.WriteVec3(cursor0);
net.WriteVec3(cursor1);
net.WriteVec3(cursor2);
net.WriteVec3(cursor3);
net.WritePose(headset);
net.WritePose(offHand);
net.WritePose(mainHand);
WriteBlock();
WriteCubic();
}
public void Read() {
color = net.ReadColor();
cursor0 = net.ReadVec3();
cursor1 = net.ReadVec3();
cursor2 = net.ReadVec3();
cursor3 = net.ReadVec3();
headset = net.ReadPose();
offHand = net.ReadPose();
mainHand = net.ReadPose();
ReadBlock();
ReadCubic();
}
Bezier.Draw(cursor0, cursor1, cursor2, cursor3, Color.White);
struct NetBlock {
public bool active;
public Pose pose;
}
void ReadBlock() {
int length = net.ReadInt();
if (length != blocks.Length) { blocks = new NetBlock[length]; }
for (int i = 0; i < length; i++) {
NetBlock netBlock = blocks[i];
netBlock.active = net.ReadBool();
netBlock.pose = net.ReadPose();
}
// Cube(offHand.ToMatrix(new Vec3(0.1f, 0.025f, 0.1f)), color);
// Cube(mainHand.ToMatrix(new Vec3(0.1f, 0.025f, 0.1f)), color);
}
void WriteBlock() {
net.WriteInt(blocks.Length);
for (int i = 0; i < blocks.Length; i++) {
NetBlock netBlock = blocks[i];
net.WriteBool(netBlock.active);
net.WritePose(netBlock.pose);
}
}
public struct NetCubic {
public bool active;
public Color color;
public Vec3 p0, p1, p2, p3;
}
void ReadCubic() {
int length = net.ReadInt();
if (length != cubics.Length) { cubics = new NetCubic[length]; }
for (int i = 0; i < cubics.Length; i++) {
NetCubic cubic = cubics[i];
cubic.active = net.ReadBool();
cubic.color = net.ReadColor();
cubic.p0 = net.ReadVec3();
cubic.p1 = net.ReadVec3();
cubic.p2 = net.ReadVec3();
cubic.p3 = net.ReadVec3();
}
}
void WriteCubic() {
net.WriteInt(cubics.Length);
for (int i = 0; i < cubics.Length; i++) {
net.WriteBool(cubics[i].active);
net.WriteColor(cubics[i].color);
net.WriteVec3(cubics[i].p0);
net.WriteVec3(cubics[i].p1);
net.WriteVec3(cubics[i].p2);
net.WriteVec3(cubics[i].p3);
}
}
public void Draw(bool body) {
if (body) {
Cube(Matrix.TRS(headset.position + Input.Head.Forward * -0.15f, headset.orientation, Vec3.One * 0.3f), color);
}
Bezier.Draw(cursor0, cur Color.White); // overlap
// Cube(offHand.ToMatrix(new Vec3(0.1f, 0.025f, 0.1f)), color);
// Cube(mainHand.ToMatrix(new Vec3(0.1f, 0.025f, 0.1f)), color);
Cube(Matrix.TRS(cursor0, mainHand.orientation, new Vec3(0.025f, 0.1f, 0.1f)), color);
Cube(Matrix.TRS(cursor3, offHand.orientation, new Vec3(0.025f, 0.1f, 0.1f)), color);

View file

@ -48,6 +48,7 @@ public struct Btn {
}
public class Monolith {
public MonoNet net;
public Mic mic;
public Con rCon = new Con(), lCon = new Con();
@ -66,6 +67,13 @@ public class Monolith {
public Glove Glove(bool chirality) {
return chirality ? rGlove : lGlove;
}
public Block[] blocks;
public BlockCon rBlock, lBlock;
public BlockCon BlockCon(bool chirality) {
return chirality ? rBlock : lBlock;
}
public Cubic[] cubics;
public CubicCon cubicCon;
public Vec3 rDragStart, lDragStart;
public float railT;
@ -76,9 +84,23 @@ public class Monolith {
public void Run() {
Renderer.SetClip(0.02f, 1000f);
net = new MonoNet(this);
net.Start();
// mic = new Mic();
rGlove = new Glove(this, true);
lGlove = new Glove(this, false);
blocks = new Block[] {
new Block(SolidType.Normal), new Block(type), new Block(type),
new Block(type), new Block(type), new Block(type)
};
rBlock = new BlockCon(this, true);
lBlock = new BlockCon(this, false);
cubics = new Cubic[] {
new Cubic(), new Cubic(), new Cubic(),
new Cubic(), new Cubic(), new Cubic()
};
cubicCon = new CubicCon(this);
Vec3 pos = new Vec3(0, 0, 0);
@ -105,9 +127,6 @@ public class Monolith {
// Oriel otherOriel = new Oriel();
// otherOriel.Start(4);
MonoNet net = new MonoNet(this);
net.Start();
ColorCube colorCube = new ColorCube();
Vec3 oldLPos = Vec3.Zero;
@ -147,8 +166,13 @@ public class Monolith {
rGlove.Step();
lGlove.Step();
// Blocks
rBlock.Step();
lBlock.Step();
// Cubic
cubicCon.Step(rCon, lCon, this);
// past this point more questions arise
// cubicFlow.Step(new Pose[] { new Pose(rightReachCursor.p0, rCon.ori), new Pose(leftReachCursor.p0, lCon.ori) }, 1);
// if (rCon.stick.y > 0.1f || lCon.stick.y > 0.1f) {
@ -330,6 +354,18 @@ public class Monolith {
// Scene
cube.Draw(matFloor, floor.GetPose().ToMatrix(floorScale), Color.White * 0.666f);
// COLOR CUBE
// reveal when palm up
float reveal = lCon.device.pose.Right.y * 1.666f;
@ -352,38 +388,25 @@ public class Monolith {
oldLPos = lCon.device.pose.position;
net.me.color = colorCube.color;
net.me.headset = Input.Head;
net.me.mainHand = new Pose(rCon.pos, rCon.ori);
net.me.offHand = new Pose(lCon.pos, lCon.ori);
for (int i = 0; i < net.peers.Length; i++) {
Peer peer = net.peers[i];
if (peer != null) {
peer.Draw(true);
}
}
net.me.Step(this, rCon, lCon);
oriel.Step(net.me.cursor0, net.me.cursor3);
// otherOriel.bounds.center = Vec3.Forward * -2;
// otherOriel.Step();
// Matrix orbitMatrix = OrbitalView.transform;
// cube.Step(Matrix.S(Vec3.One * 0.2f) * orbitMatrix);
// Default.MaterialHand["color"] = cube.color;
// cursor.Draw(Matrix.S(0.1f));
// Renderer.RenderTo(camTex, Matrix.TR(Input.Head.position + Vec3.Up * 10, Quat.FromAngles(-90f, 0, 0)), Matrix.Orthographic(2f, 2f, 0.1f, 100f), RenderLayer.All, RenderClear.All);
// quad.Draw(camMat, Matrix.TR(Input.Head.Forward, Quat.FromAngles(0, 180, 0)));
cube.Draw(matFloor, floor.GetPose().ToMatrix(floorScale), Color.White * 0.666f);
})) ;
net.me.color = colorCube.color;
net.me.headset = Input.Head;
net.me.mainHand = rCon.Pose();
net.me.offHand = lCon.Pose();
for (int i = 0; i < net.peers.Length; i++) {
Peer peer = net.peers[i];
if (peer != null) { peer.Draw(true); }
}
net.me.Step(this);
net.send = true;
}));
SK.Shutdown();
}
}

View file

@ -212,33 +212,6 @@ public class SupineCursor : SpatialCursor {
}
}
public static class Bezier {
static int detail = 64;
public static void Draw(Vec3 p0, Vec3 p1, Vec3 p2, Vec3 p3, Color color) {
LinePoint[] bezier = new LinePoint[detail];
for (int i = 0; i < bezier.Length; i++) {
float t = i / ((float)bezier.Length - 1);
Vec3 a = Vec3.Lerp(p0, p1, t);
Vec3 b = Vec3.Lerp(p1, p2, t);
Vec3 c = Vec3.Lerp(p2, p3, t);
Vec3 pos = Vec3.Lerp(Vec3.Lerp(a, b, t), Vec3.Lerp(b, c, t), t);
bezier[i] = new LinePoint(pos, color, 0.01f);
}
Lines.Add(bezier);
}
public static Vec3 Sample(Vec3 p0, Vec3 p1, Vec3 p2, Vec3 p3, float t) {
Vec3 a = Vec3.Lerp(p0, p1, t);
Vec3 b = Vec3.Lerp(p1, p2, t);
Vec3 c = Vec3.Lerp(p2, p3, t);
Vec3 pos = Vec3.Lerp(Vec3.Lerp(a, b, t), Vec3.Lerp(b, c, t), t);
return pos;
}
public static Vec3 Sample(Vec3[] points, float t) {
return Sample(points[0], points[1], points[2], points[3], t);
}
}
// for fun
// public class ClawCursor : SpatialCursor {

BIN
res/skinned_test.blend Normal file

Binary file not shown.