private void ParentMeshInSpace_GetRenderSceneDataAddToFrameData(Component_MeshInSpace sender, ViewportRenderingContext context, GetRenderSceneDataMode mode, ref Component_RenderingPipeline.RenderSceneData.MeshItem item) { if (!CalculateOnCPU) { Component_Skeleton skeleton = ReplaceSkeleton; if (skeleton == null) { skeleton = ParentMeshInSpace?.Mesh.Value?.Skeleton; } if (skeleton != null) { var animation = PlayAnimation.Value; if (animation != null) { UpdateAnimationTime(); //settings.animationStates = new AnimationStateItem[ 1 ]; //settings.animationStates[ 0 ] = new AnimationStateItem( animation, currentLocalTime, 1 ); var skeletonAnimation = animation as Component_SkeletonAnimation; var track = skeletonAnimation?.Track.Value; if (track != null || CalculateBoneTransforms != null) { Update(skeleton, track, currentAnimationTime); if (transformMatrixRelativeToSkin != null && transformMatrixRelativeToSkin.Length != 0) { item.AnimationData = new Component_RenderingPipeline.RenderSceneData.MeshItem.AnimationDataClass(); bool dualQuaternion = false; // GetSkinningMode( skeleton ) == Component_Skeleton.SkinningModeEnum.DualQuaternion; if (dualQuaternion) { item.AnimationData.Mode = 2; } else { item.AnimationData.Mode = 1; } //create dynamic texture var size = new Vector2I(4, MathEx.NextPowerOfTwo(transformMatrixRelativeToSkin.Length)); var bonesTexture = context.DynamicTexture_Alloc(ViewportRenderingContext.DynamicTextureType.DynamicTexture, Component_Image.TypeEnum._2D, size, PixelFormat.Float32RGBA, 0, false); //try get array from texture to minimize memory allocations var surfaces = bonesTexture.Result.GetData(); if (surfaces == null) { surfaces = new GpuTexture.SurfaceData[] { new GpuTexture.SurfaceData(0, 0, new byte[size.X * size.Y * 16]) } } ; var data = surfaces[0].data; //copy data to the texture unsafe { fixed(byte *pData2 = data) { Matrix4F *pData = (Matrix4F *)pData2; for (int n = 0; n < transformMatrixRelativeToSkin.Length; n++) { pData[n] = transformMatrixRelativeToSkin[n]; } } } bonesTexture.Result.SetData(new GpuTexture.SurfaceData[] { new GpuTexture.SurfaceData(0, 0, data) }); item.AnimationData.BonesTexture = bonesTexture; } } } } } } void RenderSkeleton(Viewport viewport) { // ParentMeshInSpace.Transform is automaticaly applyed to ParentMeshInSpace.Mesh, skeleton must be transformed manually var transformMatrix = ParentMeshInSpace?.Transform.Value?.ToMatrix4() ?? Matrix4.Identity; var skeletonArrows = GetCurrentAnimatedSkeletonArrows(); if (skeletonArrows != null) { var color = new ColorValue(0, 0.5, 1, 0.7); //ToDo : Вынести в другое место. viewport.Simple3DRenderer.SetColor(color, color * ProjectSettings.Get.HiddenByOtherObjectsColorMultiplier); foreach (var arrow in skeletonArrows) { viewport.Simple3DRenderer.AddArrow(transformMatrix * arrow.Start, transformMatrix * arrow.End); } } } bool CheckNeedModifiableMesh() { if (CalculateOnCPU) { if (ReplaceSkeleton.ReferenceSpecified) { return(true); } var mesh = ParentMeshInSpace?.Mesh.Value; if (mesh != null && mesh.Skeleton.ReferenceSpecified) { return(true); } if (PlayAnimation.ReferenceSpecified) { return(true); } } return(false); } void UpdateModifiableMesh(ViewportRenderingContext context) { var originalMesh = ParentMeshInSpace.Mesh.Value; var modifiableMesh = ParentMeshInSpace.ModifiableMesh; Component_Skeleton skeleton = ReplaceSkeleton; if (skeleton == null) { skeleton = originalMesh.Skeleton; } if (skeleton != null) { //!!!!сериализовывать var animation = PlayAnimation.Value; if (animation != null) { UpdateAnimationTime(); //settings.animationStates = new AnimationStateItem[ 1 ]; //settings.animationStates[ 0 ] = new AnimationStateItem( animation, currentLocalTime, 1 ); var skeletonAnimation = animation as Component_SkeletonAnimation; var track = skeletonAnimation?.Track.Value; if (track != null || CalculateBoneTransforms != null) { Update(skeleton, track, currentAnimationTime); CalculateCPU(skeleton, originalMesh, modifiableMesh); } } if (needResetToOriginalMesh) { needResetToOriginalMesh = false; if (CalculateOnCPU) { ResetToOriginalMesh(originalMesh, modifiableMesh); } } } } ///////////////////////////////////////// void ResetTime(bool needResetToOriginalMesh) { if (needResetToOriginalMesh) { this.needResetToOriginalMesh = true; } currentEngineTime = EngineApp.EngineTime; currentAnimationTime = (PlayAnimation.Value as Component_SkeletonAnimation)?.TrackStartTime ?? 0; } void UpdateAnimationTime() { double t = EngineApp.EngineTime; double increment = t - currentEngineTime; currentEngineTime = t; currentAnimationTime += increment * Speed; var animation = PlayAnimation.Value as Component_SkeletonAnimation; if (animation != null) { double animationStartTime = animation.TrackStartTime; double animationLength = animation.Length; if (animationLength > 0) { if (AutoRewind) { while (currentAnimationTime > animationStartTime + animationLength) { currentAnimationTime -= animationLength; } while (currentAnimationTime < animationStartTime) { currentAnimationTime += animationLength; } } else { MathEx.Clamp(ref currentAnimationTime, animationStartTime, animationStartTime + animationLength); } } else { currentAnimationTime = animationStartTime; } } else { currentAnimationTime = 0; } }