private void Timer_Tick() { double angle = (0.05f * frame) * Math.PI / 180; var xAxis = new Vector3(1, 0, 0); var zAxis = new Vector3(0, 0, 1); var yAxis = new Vector3(0, 1, 0); var rotation = Matrix.RotationAxis(xAxis, 0); double angleEach = 0; int counter = 0; for (int i = 0; i < NumSegments && i < numBonesInModel; ++i, counter += numSegmentPerBone) { if (i == 0) { boneInternal[0] = rotation; } else { var vp = Vector3.Transform(path[counter - numSegmentPerBone], Matrix.RotationAxis(xAxis, (float)angleEach)).ToVector3(); angleEach += angle; var v = Vector3.Transform(path[counter], Matrix.RotationAxis(xAxis, (float)angleEach)).ToVector3(); var rad = Math.Acos(Vector3.Dot(yAxis, (v - vp).Normalized())); if (angleEach < 0) { rad = -rad; } var rot = Matrix.RotationAxis(xAxis, (float)rad); var trans = Matrix.Translation(v); boneInternal[i] = rot * trans; } } var newBone = new BoneMatricesStruct() { Bones = boneInternal.ToArray() }; context.Post((o) => { Bones = newBone; }, null); if (frame > 40 || frame < -40) { direction = !direction; } if (direction) { ++frame; } else { --frame; } }
public MainViewModel() { this.Title = "BoneSkin Demo"; this.SubTitle = "WPF & SharpDX"; EffectsManager = new DefaultEffectsManager(); RenderTechnique = EffectsManager[DefaultRenderTechniqueNames.Blinn]; this.Camera = new HelixToolkit.Wpf.SharpDX.PerspectiveCamera { Position = new Media3D.Point3D(20, 20, 20), LookDirection = new Media3D.Vector3D(-20, -20, -20), UpDirection = new Media3D.Vector3D(0, 1, 0) }; this.Light1Color = Colors.White; this.Light1Direction = new Media3D.Vector3D(-10, -10, -10); this.AmbientLightColor = Colors.DarkGray; SetupCameraBindings(this.Camera); var builder = new MeshBuilder(true, true, true); path = new List <Vector3>(); for (int i = 0; i < NumSegments; ++i) { path.Add(new Vector3(0, (float)i / 10, 0)); } builder.AddTube(path, 2, Theta, false, false, true); Model = builder.ToMesh(); for (int i = 0; i < Model.Positions.Count; ++i) { Model.Positions[i] = new Vector3(Model.Positions[i].X, 0, Model.Positions[i].Z); } Material = new PhongMaterial() { DiffuseColor = Colors.SteelBlue.ToColor4() }; for (int i = 0; i < numBonesInModel; ++i) { boneInternal[i] = Matrix.Identity; } Bones = new BoneMatricesStruct() { Bones = boneInternal.ToArray() }; builder = new MeshBuilder(true, true, false); builder.AddBox(new Vector3(), 40, 0.5, 40, BoxFaces.All); FloorModel = builder.ToMesh(); int boneId = 0; numSegmentPerBone = (int)Math.Max(1, (double)Model.Positions.Count / Theta / (numBonesInModel - 1)); int count = 0; for (int i = 0; i < Model.Positions.Count / Theta; ++i) { boneParams.AddRange(Enumerable.Repeat(new BoneIds() { Bone1 = Math.Min(numBonesInModel - 1, boneId), Bone2 = Math.Min(numBonesInModel - 1, boneId - 1), Bone3 = Math.Min(numBonesInModel - 1, boneId + 1), Weights = new Vector4(0.6f, 0.2f, 0.2f, 0) }, Theta)); ++count; if (count == numSegmentPerBone) { count = 0; ++boneId; } } VertexBoneParams = boneParams.ToArray(); Instances = new List <Matrix>(); for (int i = 0; i < 3; ++i) { Instances.Add(Matrix.Translation(new Vector3(-5 + i * 4, 0, -10))); } for (int i = 0; i < 3; ++i) { Instances.Add(Matrix.Translation(new Vector3(-5 + i * 4, 0, 0))); } for (int i = 0; i < 3; ++i) { Instances.Add(Matrix.Translation(new Vector3(-5 + i * 4, 0, 10))); } StartAnimation(); }